"Fossies" - the Fresh Open Source Software Archive

Member "links-1.03/url.c" (18 Sep 2011, 13604 Bytes) of archive /linux/www/links-1.03.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "url.c" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes report: 2.8_vs_1.03.

    1 #include "links.h"
    2 
    3 struct {
    4     unsigned char *prot;
    5     int port;
    6     void (*func)(struct connection *);
    7     void (*nc_func)(struct session *, unsigned char *);
    8     int free_syntax;
    9     int need_slashes;
   10     int need_slash_after_host;
   11     int allow_post;
   12 } protocols[]= {
   13         {"file", 0, file_func, NULL, 1, 1, 0, 0},
   14         {"https", 443, https_func, NULL, 0, 1, 1, 1},
   15         {"http", 80, http_func, NULL, 0, 1, 1, 1},
   16         {"proxy", 3128, proxy_func, NULL, 0, 1, 1, 1},
   17         {"ftp", 21, ftp_func, NULL, 0, 1, 1, 0},
   18         {"finger", 79, finger_func, NULL, 0, 1, 1, 0},
   19 #ifndef DISABLE_SMB
   20         {"smb", 139, smb_func, NULL, 0, 1, 1, 0},
   21 #endif
   22         {"mailto", 0, NULL, mailto_func, 0, 0, 0, 0},
   23         {"telnet", 0, NULL, telnet_func, 0, 0, 0, 0},
   24         {"tn3270", 0, NULL, tn3270_func, 0, 0, 0, 0},
   25         {"mms", 0, NULL, mms_func, 1, 0, 1, 0},
   26         {NULL, 0, NULL, NULL, 0, 0, 0, 0}
   27 };
   28 
   29 int check_protocol(unsigned char *p, int l)
   30 {
   31     int i;
   32     for (i = 0; protocols[i].prot; i++)
   33         if (!casecmp(protocols[i].prot, p, l) && (int)strlen(protocols[i].prot) == l) {
   34             return i;
   35         }
   36     return -1;
   37 }
   38 
   39 int get_prot_info(unsigned char *prot, int *port, void (**func)(struct connection *), void (**nc_func)(struct session *ses, unsigned char *), int *allow_post)
   40 {
   41     int i;
   42     for (i = 0; protocols[i].prot; i++)
   43         if (!strcasecmp(protocols[i].prot, prot)) {
   44             if (port) *port = protocols[i].port;
   45             if (func) *func = protocols[i].func;
   46             if (nc_func) *nc_func = protocols[i].nc_func;
   47             if (allow_post) *allow_post = protocols[i].allow_post;
   48             return 0;
   49         }
   50     return -1;
   51 }
   52 
   53 int parse_url(unsigned char *url, int *prlen, unsigned char **user, int *uslen, unsigned char **pass, int *palen, unsigned char **host, int *holen, unsigned char **port, int *polen, unsigned char **data, int *dalen, unsigned char **post)
   54 {
   55     unsigned char *p, *q;
   56     unsigned char p_c[2];
   57     int a;
   58     if (prlen) *prlen = 0;
   59     if (user) *user = NULL;
   60     if (uslen) *uslen = 0;
   61     if (pass) *pass = NULL;
   62     if (palen) *palen = 0;
   63     if (host) *host = NULL;
   64     if (holen) *holen = 0;
   65     if (port) *port = NULL;
   66     if (polen) *polen = 0;
   67     if (data) *data = NULL;
   68     if (dalen) *dalen = 0;
   69     if (post) *post = NULL;
   70     if (!url || !(p = strchr(url, ':'))) return -1;
   71     if (prlen) *prlen = p - url;
   72     if ((a = check_protocol(url, p - url)) == -1) return -1;
   73     if (p[1] != '/' || p[2] != '/') {
   74         if (protocols[a].need_slashes) return -1;
   75         p -= 2;
   76     }
   77     if (protocols[a].free_syntax) {
   78         if (data) *data = p + 3;
   79         if (dalen) *dalen = strlen(p + 3);
   80         return 0;
   81     }
   82     p += 3;
   83     q = p + strcspn(p, "@/?");
   84     if (!*q && protocols[a].need_slash_after_host) return -1;
   85     if (*q == '@') {
   86         unsigned char *pp;
   87         while (strcspn(q + 1, "@") < strcspn(q + 1, "/?"))
   88             q = q + 1 + strcspn(q + 1, "@");
   89         pp = strchr(p, ':');
   90         if (!pp || pp > q) {
   91             if (user) *user = p;
   92             if (uslen) *uslen = q - p;
   93         } else {
   94             if (user) *user = p;
   95             if (uslen) *uslen = pp - p;
   96             if (pass) *pass = pp + 1;
   97             if (palen) *palen = q - pp - 1;
   98         }
   99         p = q + 1;
  100     } 
  101     q = p + strcspn(p, ":/?");
  102     if (!*q && protocols[a].need_slash_after_host) return -1;
  103     if (host) *host = p;
  104     if (holen) *holen = q - p;
  105     if (*q == ':') {
  106         unsigned char *pp = q + strcspn(q, "/");
  107         int cc;
  108         if (*pp != '/' && protocols[a].need_slash_after_host) return -1;
  109         if (port) *port = q + 1;
  110         if (polen) *polen = pp - q - 1;
  111         for (cc = 0; cc < pp - q - 1; cc++) if (q[cc+1] < '0' || q[cc+1] > '9') return -1;
  112         q = pp;
  113     }
  114     if (*q && *q != '?') q++;
  115     p = q;
  116     p_c[0] = POST_CHAR;
  117     p_c[1] = 0;
  118     q = p + strcspn(p, p_c);
  119     if (data) *data = p;
  120     if (dalen) *dalen = q - p;
  121     if (post) *post = *q ? q + 1 : NULL;
  122     return 0;
  123 }
  124 
  125 unsigned char *get_protocol_name(unsigned char *url)
  126 {
  127     int l;
  128     if (parse_url(url, &l, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL)) return NULL;
  129     return memacpy(url, l);
  130 }
  131 
  132 unsigned char *get_host_and_pass(unsigned char *url)
  133 {
  134     unsigned char *u, *h, *p, *z, *k;
  135     int hl, pl;
  136     if (parse_url(url, NULL, &u, NULL, NULL, NULL, &h, &hl, &p, &pl, NULL, NULL, NULL)) return NULL;
  137     z = u ? u : h;
  138     k = p ? p + pl : h + hl;
  139     return memacpy(z, k - z);
  140 }
  141 
  142 unsigned char *get_host_name(unsigned char *url)
  143 {
  144     unsigned char *h;
  145     int hl;
  146     if (parse_url(url, NULL, NULL, NULL, NULL, NULL, &h, &hl, NULL, NULL, NULL, NULL, NULL)) return stracpy("");
  147     return memacpy(h, hl);
  148 }
  149 
  150 unsigned char *get_user_name(unsigned char *url)
  151 {
  152     unsigned char *h;
  153     int hl;
  154     if (parse_url(url, NULL, &h, &hl, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL)) return NULL;
  155     return memacpy(h, hl);
  156 }
  157 
  158 unsigned char *get_pass(unsigned char *url)
  159 {
  160     unsigned char *h;
  161     int hl;
  162     if (parse_url(url, NULL,NULL,  NULL, &h, &hl, NULL, NULL, NULL, NULL, NULL, NULL, NULL)) return NULL;
  163     return memacpy(h, hl);
  164 }
  165 
  166 unsigned char *get_port_str(unsigned char *url)
  167 {
  168     unsigned char *h;
  169     int hl;
  170     if (parse_url(url, NULL, NULL, NULL, NULL, NULL, NULL, NULL, &h, &hl, NULL, NULL, NULL)) return NULL;
  171     return hl ? memacpy(h, hl) : NULL;
  172 }
  173 
  174 int get_port(unsigned char *url)
  175 {
  176     unsigned char *h;
  177     int hl;
  178     long n = -1;
  179     if (parse_url(url, NULL, NULL, NULL, NULL, NULL, NULL, NULL, &h, &hl, NULL, NULL, NULL)) return -1;
  180     if (h) {
  181         n = strtol(h, NULL, 10);
  182         if (n && n < MAXINT) return n;
  183     }
  184     if ((h = get_protocol_name(url))) {
  185         int nn = -1;    /* against warning */
  186         get_prot_info(h, &nn, NULL, NULL, NULL);
  187         mem_free(h);
  188         n = nn;
  189     }
  190     return n;
  191 }
  192 
  193 void (*get_protocol_handle(unsigned char *url))(struct connection *)
  194 {
  195     unsigned char *p;
  196     void (*f)(struct connection *) = NULL;
  197     int post = 0;
  198     if (!(p = get_protocol_name(url))) return NULL;
  199     get_prot_info(p, NULL, &f, NULL, &post);
  200     mem_free(p);
  201     if (!post && strchr(url, POST_CHAR)) return NULL;
  202     return f;
  203 }
  204 
  205 void (*get_external_protocol_function(unsigned char *url))(struct session *, unsigned char *)
  206 {
  207     unsigned char *p;
  208     void (*f)(struct session *, unsigned char *) = NULL;
  209     int post = 0;
  210     if (!(p = get_protocol_name(url))) return NULL;
  211     get_prot_info(p, NULL, NULL, &f, &post);
  212     mem_free(p);
  213     if (!post && strchr(url, POST_CHAR)) return NULL;
  214     return f;
  215 }
  216 
  217 unsigned char *get_url_data(unsigned char *url)
  218 {
  219     unsigned char *d;
  220     if (parse_url(url, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, &d, NULL, NULL)) return NULL;
  221     return d;
  222 }
  223 
  224 #define dsep(x) (lo ? dir_sep(x) : (x) == '/')
  225 
  226 void translate_directories(unsigned char *url)
  227 {
  228     unsigned char *dd = get_url_data(url);
  229     unsigned char *s, *d;
  230     int lo = !casecmp(url, "file://", 7);
  231     if (!dd || dd == url/* || *--dd != '/'*/) return;
  232     if (!dsep(*dd)) dd--;
  233     s = dd;
  234     d = dd;
  235     r:
  236     if (end_of_dir(s[0])) {
  237         memmove(d, s, strlen(s) + 1);
  238         return;
  239     }
  240     if (dsep(s[0]) && s[1] == '.' && dsep(s[2])) {
  241         /**d++ = s[0];*/
  242         if (s == dd && !s[3]) goto p;
  243         s += 2;
  244         goto r;
  245     }
  246     if (dsep(s[0]) && s[1] == '.' && s[2] == '.' && (dsep(s[3]) || !s[3])) {
  247         while (d > dd) {
  248             d--;
  249             if (dsep(*d)) goto b;
  250         }
  251         b:
  252         if (!s[3]) *d++ = *s;
  253         s += 3;
  254         goto r;
  255     }
  256     p:
  257     if ((*d++ = *s++)) goto r;
  258 }
  259 
  260 void insert_wd(unsigned char **up, unsigned char *cwd)
  261 {
  262     unsigned char *url = *up;
  263     if (!url || !cwd || !*cwd) return;
  264     if (casecmp(url, "file://", 7)) return;
  265     if (dir_sep(url[7])) return;
  266 #ifdef DOS_FS
  267     if (upcase(url[7]) >= 'A' && upcase(url[7]) <= 'Z' && url[8] == ':' && dir_sep(url[9])) return;
  268 #endif
  269 #ifdef SPAD
  270     if (_is_absolute(url + 7) != _ABS_NO) return;
  271 #endif
  272     url = mem_alloc(strlen(*up) + strlen(cwd) + 2);
  273     memcpy(url, *up, 7);
  274     strcpy(url + 7, cwd);
  275     if (!dir_sep(cwd[strlen(cwd) - 1])) strcat(url, "/");
  276     strcat(url, *up + 7);
  277     mem_free(*up);
  278     *up = url;
  279 }
  280 
  281 unsigned char *join_urls(unsigned char *base, unsigned char *rel)
  282 {
  283     unsigned char *p, *n, *pp;
  284     int l;
  285     int lo = !casecmp(base, "file://", 7);
  286     if (rel[0] == '#' || !rel[0]) {
  287         n = stracpy(base);
  288         for (p = n; *p && *p != POST_CHAR && *p != '#'; p++) ;
  289         *p = 0;
  290         add_to_strn(&n, rel);
  291         translate_directories(n);
  292         return n;
  293     }
  294     if (rel[0] == '?' || rel[0] == '&') {
  295         unsigned char rj[3];
  296         unsigned char *d = get_url_data(base);
  297         if (!d) goto bad_base;
  298         rj[0] = rel[0];
  299         rj[1] = POST_CHAR;
  300         rj[2] = 0;
  301         d += strcspn(d, rj);
  302         n = memacpy(base, d - base);
  303         add_to_strn(&n, rel);
  304         translate_directories(n);
  305         return n;
  306     }
  307     if (rel[0] == '/' && rel[1] == '/') {
  308         unsigned char *s, *n;
  309         if (!(s = strstr(base, "//"))) {
  310             if (!(s = strchr(base, ':'))) {
  311                 bad_base:
  312                 internal("bad base url: %s", base);
  313                 return NULL;
  314             }
  315             s++;
  316         }
  317         n = memacpy(base, s - base);
  318         add_to_strn(&n, rel);
  319         if (!parse_url(n, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL)) {
  320             translate_directories(n);
  321             return n;
  322         }
  323         mem_free(n);
  324     }
  325     if (!casecmp("proxy://", rel, 8)) goto prx;
  326     if (!parse_url(rel, &l, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL)) {
  327         n = stracpy(rel);
  328         translate_directories(n);
  329         return n;
  330     }
  331     n = stracpy(rel);
  332     while (n[0] && n[strlen(n) - 1] <= ' ') n[strlen(n) - 1] = 0;
  333     add_to_strn(&n, "/");
  334     if (!parse_url(n, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL)) {
  335         translate_directories(n);
  336         return n;
  337     }
  338     mem_free(n);
  339     prx:
  340     if (parse_url(base, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, &p, NULL, NULL) || !p) {
  341         goto bad_base;
  342     }
  343     if (!dsep(*p)) p--;
  344     if (end_of_dir(rel[0])) for (; *p; p++) {
  345         if (end_of_dir(*p)) break;
  346     } else if (!dsep(rel[0])) for (pp = p; *pp; pp++) {
  347         if (end_of_dir(*pp)) break;
  348         if (dsep(*pp)) p = pp + 1;
  349     }
  350     n = mem_alloc(p - base + strlen(rel) + 1);
  351     memcpy(n, base, p - base);
  352     strcpy(n + (p - base), rel);
  353     translate_directories(n);
  354     return n;
  355 }
  356 
  357 unsigned char *translate_url(unsigned char *url, unsigned char *cwd)
  358 {
  359     unsigned char *ch;
  360     unsigned char *nu, *da;
  361     unsigned char *prefix;
  362     int sl;
  363     while (*url == ' ') url++;
  364     if (!casecmp("proxy://", url, 8)) return NULL;
  365     if (!parse_url(url, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, &da, NULL, NULL)) {
  366         nu = stracpy(url);
  367         insert_wd(&nu, cwd);
  368         translate_directories(nu);
  369         return nu;
  370     }
  371     if (strchr(url, POST_CHAR)) return NULL;
  372     if (strstr(url, "://")) {
  373         nu = stracpy(url);
  374         add_to_strn(&nu, "/");
  375         if (!parse_url(nu, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL)) {
  376             insert_wd(&nu, cwd);
  377             translate_directories(nu);
  378             return nu;
  379         }
  380         mem_free(nu);
  381     }
  382     ch = url + strcspn(url, ".:/@");
  383     prefix = "file://";
  384     sl = 0;
  385     if (*ch != ':' || *(url + strcspn(url, "/@")) == '@') {
  386         if (*url != '.' && *ch == '.') {
  387             unsigned char *f, *e;
  388             int i;
  389             for (e = ch + 1; *(f = e + strcspn(e, ".:/")) == '.'; e = f + 1) ;
  390             for (i = 0; i < f - e; i++) if (e[i] >= '0' && e[i] <= '9') goto http;
  391             if (f - e == 2) {
  392                 http:
  393                 prefix = "http://", sl = 1;
  394             } else {
  395                 unsigned char *tld[] = { "com", "edu", "net", "org", "gov", "mil", "int", "arpa", "aero", "biz", "coop", "info", "museum", "name", "pro", "cat", "jobs", "mobi", "travel", "tel", NULL };
  396                 for (i = 0; tld[i]; i++) if ((size_t)(f - e) == strlen(tld[i]) && !casecmp(tld[i], e, f - e)) goto http;
  397             }
  398         }
  399         if (*ch == '@' || *ch == ':' || !cmpbeg(url, "ftp.")) prefix = "ftp://", sl = 1;
  400         goto set_prefix;
  401         set_prefix:
  402         nu = stracpy(prefix);
  403         add_to_strn(&nu, url);
  404         if (sl && !strchr(url, '/')) add_to_strn(&nu, "/");
  405         if (parse_url(nu, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL)) mem_free(nu), nu = NULL;
  406         else {
  407             insert_wd(&nu, cwd);
  408             translate_directories(nu);
  409         }
  410         return nu;
  411     }
  412 #ifdef DOS_FS
  413     if (ch == url + 1) goto set_prefix;
  414 #endif
  415 #ifdef SPAD
  416     if (_is_local(url)) goto set_prefix;
  417 #endif
  418     nu = memacpy(url, ch - url + 1);
  419     add_to_strn(&nu, "//");
  420     add_to_strn(&nu, ch + 1);
  421     if (!parse_url(nu, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL)) {
  422         insert_wd(&nu, cwd);
  423         translate_directories(nu);
  424         return nu;
  425     }
  426     add_to_strn(&nu, "/");
  427     if (!parse_url(nu, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL)) {
  428         insert_wd(&nu, cwd);
  429         translate_directories(nu);
  430         return nu;
  431     }
  432     mem_free(nu);
  433     return NULL;
  434 }
  435 
  436 unsigned char *extract_position(unsigned char *url)
  437 {
  438     unsigned char *u, *uu, *r;
  439     if ((u = get_url_data(url))) url = u;
  440     if (!(u = strchr(url, POST_CHAR))) u = url + strlen(url);
  441     if (!(uu = memchr(url, '#', u - url))) return NULL;
  442     r = mem_alloc(u - uu);
  443     memcpy(r, uu + 1, u - uu - 1);
  444     r[u - uu - 1] = 0;
  445     memmove(uu, u, strlen(u) + 1);
  446     return r;
  447 }
  448 
  449 void get_filename_from_url(unsigned char *url, unsigned char **s, int *l)
  450 {
  451     int lo = !casecmp(url, "file://", 7);
  452     unsigned char *uu;
  453     if ((uu = get_url_data(url))) url = uu;
  454     *s = url;
  455     while (*url && !end_of_dir(*url)) {
  456         if (dsep(*url)) *s = url + 1;
  457         url++;
  458     }
  459     *l = url - *s;
  460 }
  461 
  462 #define accept_char(x)  ((x) != '"' && (x) != '\'' && (x) != '&' && (x) != '<' && (x) != '>')
  463 #define special_char(x) ((x) == '%' || (x) == '#')
  464 
  465 void add_conv_str(unsigned char **s, int *l, unsigned char *b, int ll, int encode_special)
  466 {
  467     for (; ll; ll--, b++) {
  468         if ((unsigned char)*b < ' ') continue;
  469         if (special_char(*b) && encode_special == 1) {
  470             unsigned char h[4];
  471             sprintf(h, "%%%02X", (unsigned)*b & 0xff);
  472             add_to_str(s, l, h);
  473         } else if (*b == '%' && encode_special <= -1 && ll > 2 && ((b[1] >= '0' && b[1] <= '9') || (b[1] >= 'A' && b[1] <= 'F') || (b[1] >= 'a' && b[1] <= 'f'))) {
  474             unsigned char h = 0;
  475             int i;
  476             for (i = 1; i < 3; i++) {
  477                 if (b[i] >= '0' && b[i] <= '9') h = h * 16 + b[i] - '0';
  478                 if (b[i] >= 'A' && b[i] <= 'F') h = h * 16 + b[i] - 'A' + 10;
  479                 if (b[i] >= 'a' && b[i] <= 'f') h = h * 16 + b[i] - 'a' + 10;
  480             }
  481             if (h >= ' ') add_chr_to_str(s, l, h);
  482             ll -= 2;
  483             b += 2;
  484         } else if (accept_char(*b) || encode_special == -2) {
  485             add_chr_to_str(s, l, *b);
  486         } else {
  487             add_to_str(s, l, "&#");
  488             add_num_to_str(s, l, (int)*b);
  489             add_chr_to_str(s, l, ';');
  490         }
  491     }
  492 }