/* Downloader for X
* Copyright (C) 1999-2005 Koshelev Maxim
* This Program is free but not GPL!!! You can't modify it
* without agreement with author. You can't distribute modified
* program but you can distribute unmodified program.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
*/
#include "addr.h"
#include "locstr.h"
#include "var.h"
#include <string.h>
#include <strings.h>
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include "dbc.h"
struct tProtoInfo{
char *name;
int port;
int proto;
};
tProtoInfo begin_protos[]={
{"cid:",0,D_PROTO_UNKNOWN},
{"clsid:",0,D_PROTO_UNKNOWN},
{"file:",0,D_PROTO_UNKNOWN},
{"finger:",0,D_PROTO_UNKNOWN},
{"ftp:",21,D_PROTO_FTP},
{"gopher:",0,D_PROTO_UNKNOWN},
{"hdl:",0,D_PROTO_UNKNOWN},
{"http:",80,D_PROTO_HTTP},
{"https:",0,D_PROTO_HTTPS},
{"ilu:",0,D_PROTO_UNKNOWN},
{"ior:",0,D_PROTO_UNKNOWN},
{"irc:",0,D_PROTO_UNKNOWN},
{"java:",0,D_PROTO_UNKNOWN},
{"javascript:",0,D_PROTO_UNKNOWN},
{"lifn:",0,D_PROTO_UNKNOWN},
{"mail:",0,D_PROTO_UNKNOWN},
{"mailto:",0,D_PROTO_UNKNOWN},
{"mid:",0,D_PROTO_UNKNOWN},
{"news:",0,D_PROTO_UNKNOWN},
{"nntp:",0,D_PROTO_UNKNOWN},
{"path:",0,D_PROTO_UNKNOWN},
{"prospero:",0,D_PROTO_UNKNOWN},
{"rlogin:",0,D_PROTO_UNKNOWN},
{"service:",0,D_PROTO_UNKNOWN},
{"shttp:",0,D_PROTO_UNKNOWN},
{"snews:",0,D_PROTO_UNKNOWN},
{"stanf:",0,D_PROTO_UNKNOWN},
{"telnet:",0,D_PROTO_UNKNOWN},
{"tn3270:",0,D_PROTO_UNKNOWN},
{"wais:",0,D_PROTO_UNKNOWN},
{"whois++:",0,D_PROTO_UNKNOWN},
{"socks:",0,D_PROTO_SOCKS}
};
tProtoInfo proto_infos[]={
{"?",0,D_PROTO_UNKNOWN},
{"ftp",21,D_PROTO_FTP},
{"http",80,D_PROTO_HTTP},
{"https",443,D_PROTO_HTTPS},
{"search",80,D_PROTO_SEARCH},
{"socks",0,D_PROTO_SOCKS}
};
int get_port_by_proto(int proto){
return(proto_infos[proto].port);
};
int get_proto_by_name(const char *str){
if (str==NULL) return D_PROTO_UNKNOWN;
for (int i=D_PROTO_FTP;i<D_PROTO_LAST;i++)
if (equal_uncase(str,proto_infos[i].name))
return i;
return D_PROTO_UNKNOWN;
};
const char *get_name_by_proto(int proto){
if (proto>=D_PROTO_LAST || proto<D_PROTO_UNKNOWN)
return(proto_infos[D_PROTO_UNKNOWN].name);
return(proto_infos[proto].name);
};
static int get_proto_by_string(const char *str){
if (str==NULL) return D_PROTO_UNKNOWN;
if (begin_string_uncase(str,"www")) return D_PROTO_HTTP;
if (begin_string_uncase(str,"ftp")) return D_PROTO_FTP;
return D_PROTO_FTP;
};
int global_url(char *url) {
DBC_RETVAL_IF_FAIL(url!=NULL,0);
for (unsigned int i=0;i<sizeof(begin_protos)/sizeof(tProtoInfo);i++){
if (begin_string_uncase(url,begin_protos[i].name)){
return(1);
};
};
return(0);
};
#include <iostream>
namespace d4x{
ShortURL::operator std::string() const{
std::string portstr;
if (port!=get_port_by_proto(proto)){
char buf[30];
sprintf(buf,":%i",port);
portstr=buf;
};
if (proto==D_PROTO_FTP || params.empty())
return(std::string(proto_infos[proto].name)+"://"+host+portstr+hexed_string(path/file));
return(std::string(proto_infos[proto].name)+"://"+host+portstr+hexed_string(path/file)+"?"+hexed_string(params));
};
URL::URL(const std::string &_s){
// PROTO://USER:PASS@HOST/PATH/FILE?PARAMS
std::string::size_type p=_s.find("://");
std::string protostr;
if (p!=std::string::npos && p!=0){
protostr=_s.substr(0,p);
p+=3;
}else{
p=0;
};
if (protostr.empty())
proto=get_proto_by_string(_s.c_str());
else
proto=get_proto_by_name(protostr.c_str());
std::string::size_type p1=_s.find('/',p);
if (p1!=std::string::npos){
host=_s.substr(p,p1-p);
p=_s.find('?',p1);
std::string::size_type p2 = (proto==D_PROTO_HTTP||proto==D_PROTO_HTTPS)?_s.rfind('#'):std::string::npos;
if (p!=std::string::npos){
path=unhexed_string(_s.substr(p1,p-p1));
if(p2==std::string::npos)
params=_s.substr(p+1);
else
params=_s.substr(p+1,p2-p-1);
}else{
if (p2==std::string::npos)
path=unhexed_string(_s.substr(p1));
else
path=unhexed_string(_s.substr(p1,p2-p1));
};
}else{
host=_s.substr(p);
};
// host is USER:PASS@HOST:PORT
// path is PATH/FILE
p=host.find('@');
if (p!=std::string::npos){
user=host.substr(0,p);
host=host.substr(p+1);
};
p=user.find(':');
if (p!=std::string::npos){
pass=user.substr(p+1);
user=user.substr(0,p);
};
p=host.find(':');
if (p!=std::string::npos){
port=atoi(host.substr(p+1).c_str());
host=host.substr(0,p);
};
p=path.rfind('/');
if (p!=std::string::npos){
file=path.substr(p+1);
path=path.substr(0,p);
};
path=d4x::Path("/")/path;
if (!port)
port=get_port_by_proto(proto);
if (proto==D_PROTO_FTP && file.find('*')!=std::string::npos)
mask=true;
else
mask=false;
};
URL &URL::operator=(const URL &_u){
host=_u.host;
user=_u.user;
pass=_u.pass;
path=_u.path;
file=_u.file;
params=_u.params;
tag=_u.tag;
proto=_u.proto;
port=_u.port;
mask=_u.mask;
return *this;
};
bool URL::operator==(const URL &_u) const{
if (strcasecmp(host.c_str(),_u.host.c_str()) ||
path!=_u.path || file!=_u.file || params!=_u.params ||
proto!=_u.proto || port!=port || user!=user)
return false;
return true;
};
bool URL::operator<(const URL &u_) const{
return operator std::string()<std::string(u_);
};
bool URL::is_valid(){
if (host.empty() || path.empty() || port==0) return false;
return true;
};
URL::operator std::string() const{
std::string portstr;
std::string userstr;
if (port!=get_port_by_proto(proto)){
char buf[30];
sprintf(buf,":%i",port);
portstr=buf;
};
if (!user.empty() || !pass.empty()){
if (pass.empty())
userstr=user+"@";
else
userstr=user+":"+pass+"@";
};
if (proto==D_PROTO_FTP || params.empty())
return(std::string(proto_infos[proto].name)+"://"+userstr+host+portstr+hexed_string(path/file));
return(std::string(proto_infos[proto].name)+"://"+userstr+host+portstr+hexed_string(path/file)+"?"+hexed_string(params));
};
void URL::copy_host(const URL&_u){
host=_u.host;
pass=_u.pass;
user=_u.user;
port=_u.port;
proto=_u.proto;
};
void URL::clear(){
pass.clear();
user.clear();
host.clear();
path.clear();
file.clear();
params.clear();
mask=false;
port=0;
proto=D_PROTO_UNKNOWN;
};
};
/*
/* parsing url
struct tTwoStrings{
char *one;
char *two;
tTwoStrings();
void zero();
~tTwoStrings();
};
tTwoStrings::tTwoStrings() {
one=two=NULL;
};
void tTwoStrings::zero() {
one=two=NULL;
};
tTwoStrings::~tTwoStrings() {};
static void split_string(char *what,char *delim,tTwoStrings *out) {
if (what==NULL || delim==NULL) return;
char * where=strstr(what,delim);
if (where) {
int len=strlen(where),len1=strlen(delim);
out->two=copy_string(where+len1);
len1=strlen(what)-len;
out->one=copy_string2(what,len1);
} else {
out->two=copy_string(what);
out->one=NULL;
};
delete[] what;
};
static void rsplit_string(char *what,char delim,tTwoStrings *out) {
if (what==NULL) return;
char * where=rindex(what,delim);
if (where) {
int len=strlen(where),len1=1;
out->two=copy_string(where+len1);
len1=strlen(what)-len;
out->one=copy_string2(what,len1);
} else {
out->two=copy_string(what);
out->one=NULL;
};
delete[] what;
};
/*------------------ end of temporary functions ------------
tAddr::tAddr() {
proto=D_PROTO_UNKNOWN;
port=0;
mask=0;
};
tAddr::tAddr(const tAddr *a) {
proto=D_PROTO_UNKNOWN;
port=0;
mask=0;
copy(a);
};
tAddr::tAddr(const char *str){
from_string(str);
};
void tAddr::from_string(const char *str){
clear();
char *host1=NULL,*username1=NULL,*pass1=NULL,*path1=NULL,*file1=NULL;
char *proto_name=NULL;
proto=D_PROTO_UNKNOWN;
port=0;
mask=0;
if (str==NULL) return;
for (unsigned int i=0;i<sizeof(begin_protos)/sizeof(tProtoInfo);i++){
if (begin_string_uncase(str,begin_protos[i].name)){
proto_name=begin_protos[i].name;
port=begin_protos[i].port;
proto=begin_protos[i].proto;
break;
};
};
if (proto_name) {
const char *tmp=str+strlen(proto_name);
while (*tmp=='/') tmp+=1;
host1=copy_string(tmp);
} else {
proto=get_proto_by_string(str);
host1=copy_string(str);
};
tTwoStrings pair;
if (!host1) {
return;
};
split_string(host1,"/",&pair);
if (pair.one) {
host1=pair.one;
file1=pair.two;
} else {
host1=pair.two;
file1=pair.one;
};
rsplit_string(host1,'@',&pair);
host1=pair.two;
username1=pair.one;
if (username1) {
split_string(username1,":",&pair);
username1=pair.one;
pass1=pair.two;
} else {
username1=NULL;
pass1=NULL;
};
if (file1) {
if (proto==D_PROTO_HTTP){
char *tmp=rindex(file1,'#');
if (tmp) {
*tmp=0;
tmp=file1;
file1=copy_string(tmp);
delete[] tmp;
};
char *prom=index(file1,'?');
if (prom){
params.set(prom+1);
*prom=0;
};
};
// parsing %xx -> CHAR and vice verse
char *prom=parse_percents(file1);
delete[] file1;
file1=prom;
prom=rindex(file1,'/');
if (prom) {
path1=copy_string(prom+1);
*prom=0;
prom=path1;
path1=copy_string(file1);
delete[] file1;
file1=prom;
};
} else {
file1=copy_string("");
};
if (!path1) path1=copy_string("");
split_string(host1,":",&pair);
if (pair.one) {
sscanf(pair.two,"%i",&port);
delete[] pair.two;
host1=pair.one;
} else {
port=0;
host1=pair.two;
};
if (proto==D_PROTO_FTP && index(file1,'*'))
mask=1;
// Parse # in http urls
if (port==0)
port=proto_infos[proto].port;
host.set(host1);if (host1) delete[] host1;
username.set(username1);if (username1) delete[] username1;
pass.set(pass1);if (pass1) delete[] pass1;
path.set(path1);if (path1) delete[] path1;
file.set(file1);if (file1) delete[] file1;
};
void tAddr::print() {
printf("protocol: %s\n",proto_infos[proto].name);
if (host.get()) printf("host: %s\n",host.get());
if (path.get()) printf("path: %s\n",path.get());
if (file.get()) printf("file: %s\n",file.get());
if (username.get()) printf("username: %s\n",username.get());
if (pass.get()) printf("pass: %s\n",pass.get());
printf("port: %i\n",port);
};
static int _str_first_char(const char *a,char b){
if (a && *a==b) return 1;
return 0;
};
static int _str_last_char(const char *a,char b){
if (a){
int len=strlen(a);
if (len && a[len-1]==b) return 1;
};
return 0;
};
void tAddr::save_to_config(int fd){
f_wstr_lf(fd,"URL:");
f_wstr(fd,proto_infos[proto].name);
f_wstr(fd,"://");
if (username.get() && !equal(username.get(),DEFAULT_USER)){
f_wstr(fd,username.get());
f_wstr(fd,":");
f_wstr(fd,pass.get());
f_wstr(fd,"@");
};
f_wstr(fd,host.get());
if (port!=proto_infos[proto].port){
char port_str[MAX_LEN];
g_snprintf(port_str,MAX_LEN,"%d",port);
f_wstr(fd,":");
f_wstr(fd,port_str);
};
if (!_str_first_char(path.get(),'/'))
f_wstr(fd,"/");
if (path.get())
f_wstr(fd,path.get());
if (!_str_last_char(path.get(),'/'))
f_wstr(fd,"/");
f_wstr(fd,file.get());
if (params.get()){
f_wstr(fd,"?");
f_wstr(fd,params.get());
};
f_wstr(fd,"\n");
};
void tAddr::save_to_description(int fd){
f_wstr(fd,proto_infos[proto].name);
f_wstr(fd,"://");
f_wstr(fd,host.get());
if (port!=proto_infos[proto].port){
char port_str[MAX_LEN];
g_snprintf(port_str,MAX_LEN,"%d",port);
f_wstr(fd,":");
f_wstr(fd,port_str);
};
if (!_str_first_char(path.get(),'/'))
f_wstr(fd,"/");
if (path.get())
f_wstr(fd,path.get());
if (!_str_last_char(path.get(),'/'))
f_wstr(fd,"/");
f_wstr(fd,file.get());
if (params.get()){
f_wstr(fd,"?");
f_wstr(fd,params.get());
};
};
void tAddr::compose_path(char *aa, char *bb){
char *tmp=::compose_path(aa,bb);
if (tmp && *tmp=='/')
path.set(tmp+1);
else
path.set(tmp);
if (tmp) delete[] tmp;
};
void tAddr::compose_path2(char *aa, char *bb){
char *cc=sum_strings(bb,"/",NULL);
char *tmp=::compose_path(aa,cc);
delete[] cc;
if (tmp && *tmp=='/')
path.set(tmp+1);
else
path.set(tmp);
if (tmp) delete[] tmp;
};
void tAddr::file_del_sq(){
char *tmp=index(file.get(),'#');
if (tmp) {
*tmp=0;
};
};
void tAddr::make_url(char *where){
DBC_RETURN_IF_FAIL(where!=NULL);
*where=0;
strcat(where,proto_infos[proto].name);
strcat(where,"://");
if (username.get() && !equal(username.get(),DEFAULT_USER)) {
strcat(where,username.get());
strcat(where,":");
if (pass.get()) strcat(where,pass.get());
strcat(where,"@");
};
strcat(where,host.get());
if (port!=proto_infos[proto].port){
char data[MAX_LEN];
sprintf(data,":%i",port);
strcat(where,data);
};
strcat(where,path.get());
if (!_str_last_char(path.get(),'/'))
strcat(where,"/");
strcat(where,file.get());
};
char *tAddr::pathfile(){
if (*(path.get()))
return(sum_strings("/",path.get(),"/",file.get(),NULL));
return(sum_strings("/",file.get(),NULL));
};
char *tAddr::url() {
int params_len=(params.get()?strlen(params.get())+1:0);
int port_len=port==proto_infos[proto].port?0:(int_to_strin_len(port)+1);
if (host.get()==NULL) return (copy_string(""));
char *URL=new char[strlen(proto_infos[proto].name)+strlen(host.get())+
strlen(path.get())+strlen(file.get())+7+params_len+port_len];
*URL=0;
// Easy way to make URL from info field
strcat(URL,proto_infos[proto].name);
strcat(URL,"://");
if (host.get()) strcat(URL,host.get());
if (port_len)
sprintf(URL+strlen(URL),":%i",port);
if (path.get()){
if (!_str_first_char(path.get(),'/')) strcat(URL,"/");
strcat(URL,path.get());
if (!_str_last_char(URL,'/')) strcat(URL,"/");
};
if (file.get()) strcat(URL,file.get());
if (params.get()){
strcat(URL,"?");
strcat(URL,params.get());
};
return URL;
};
char *tAddr::url_parsed() {
int params_len=(params.get()?strlen(params.get())+1:0);
int port_len=port==proto_infos[proto].port?0:(int_to_strin_len(port)+1);
char *rpath=unparse_percents(path.get());
char *rfile=unparse_percents(file.get());;
char *URL=new char[strlen(proto_infos[proto].name)+strlen(host.get())+
strlen(rpath)+strlen(rfile)+7+params_len+port_len];
*URL=0;
// Easy way to make URL from info field
strcat(URL,proto_infos[proto].name);
strcat(URL,"://");
if (host.get()) strcat(URL,host.get());
if (port_len)
sprintf(URL+strlen(URL),":%i",port);
if (rpath){
if (!_str_first_char(rpath,'/')) strcat(URL,"/");
strcat(URL,rpath);
if (!_str_last_char(URL,'/')) strcat(URL,"/");
};
if (rfile) strcat(URL,rfile);
if (params.get()){
strcat(URL,"?");
strcat(URL,params.get());
};
delete[] rfile;
delete[] rpath;
return URL;
};
char *tAddr::url_full(){
int params_len=(params.get()?strlen(params.get())+1:0);
int port_len=port==proto_infos[proto].port?0:(int_to_strin_len(port)+1);
int auth_len=0;
if (host.get()==NULL) return (copy_string(""));
if (pass.get() && username.get())
auth_len=strlen(pass.get())+strlen(username.get());
char *URL=new char[strlen(proto_infos[proto].name)+strlen(host.get())+
strlen(path.get())+strlen(file.get())+7+params_len+
port_len+auth_len];
*URL=0;
//Easy way to make URL from info field
strcat(URL,proto_infos[proto].name);
strcat(URL,"://");
if (auth_len){
strcat(URL,username.get());
strcat(URL,":");
strcat(URL,pass.get());
strcat(URL,"@");
};
if (host.get()) strcat(URL,host.get());
if (port_len)
sprintf(URL+strlen(URL),":%i",port);
if (path.get()){
if (!_str_first_char(path.get(),'/')) strcat(URL,"/");
strcat(URL,path.get());
if (!_str_last_char(URL,'/')) strcat(URL,"/");
};
if (file.get()) strcat(URL,file.get());
if (params.get()){
strcat(URL,"?");
strcat(URL,params.get());
};
return URL;
};
int tAddr::is_valid(){
if (host.get()==NULL || path.get()==NULL || file.get()==NULL) return 0;
return 1;
};
int tAddr::cmp(tAddr *b){
DBC_RETVAL_IF_FAIL(b!=NULL,0);
if (!equal_uncase(host.get(),b->host.get()) ||
!equal(path.get(),b->path.get()) ||
!equal(file.get(),b->file.get()) ||
!equal(params.get(),b->params.get()) ||
proto!=b->proto)
return 0;
if (proto==D_PROTO_FTP && !equal(username.get(),b->username.get()))
return 0;
return 1;
};
void tAddr::copy_host(const tAddr *what){
DBC_RETURN_IF_FAIL(what!=NULL);
host.set(what->host.get());
pass.set(what->pass.get());
username.set(what->username.get());
proto=what->proto;
port=what->port;
};
void tAddr::copy(const tAddr *what){
DBC_RETURN_IF_FAIL(what!=NULL);
copy_host(what);
file.set(what->file.get());
path.set(what->path.get());
params.set(what->params.get());
mask=what->mask;
};
tAddr::~tAddr() {
};
void tAddr::clear(){
port=0;
host.set(NULL);
path.set(NULL);
file.set(NULL);
username.set(NULL);
pass.set(NULL);
tag.set(NULL);
params.set(NULL);
mask=0;
proto=0;
};
*/
/**********************************************/
syntax highlighted by Code2HTML, v. 0.9.1