"Fossies" - the Fresh Open Source Software Archive

Member "zsync-0.6.2/url.c" (16 Sep 2010, 4868 Bytes) of package /linux/privat/old/zsync-0.6.2.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.

    1 
    2 /*
    3  *   zsync - client side rsync over http
    4  *   Copyright (C) 2004,2005,2009 Colin Phipps <cph@moria.org.uk>
    5  *
    6  *   This program is free software; you can redistribute it and/or modify
    7  *   it under the terms of the Artistic License v2 (see the accompanying 
    8  *   file COPYING for the full license terms), or, at your option, any later 
    9  *   version of the same license.
   10  *
   11  *   This program is distributed in the hope that it will be useful,
   12  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
   13  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   14  *   COPYING file for details.
   15  */
   16 
   17 /* Very crude URL parsing module */
   18 
   19 #include "zsglobal.h"
   20 
   21 #include <string.h>
   22 #include <stdlib.h>
   23 
   24 #ifdef WITH_DMALLOC
   25 # include <dmalloc.h>
   26 #endif
   27 
   28 #include "url.h"
   29 
   30 const char http_scheme[] = { "http://" };
   31 
   32 /* path_str = get_http_host_port(url_str, &host, host_len, &port_str)
   33  * For the given url_str, returns:
   34  * the hostname, in host[] array provided by caller (up to length host_len)
   35  * the port (if any) as a malloced string, pointer to this stored in *port_str
   36  * return value is the path part of the URL, a malloced string.
   37  * Or return value NULL on failure (host and port could have been written to).
   38  */
   39 char *get_http_host_port(const char *url, char *hostn, int hnlen, char **port) {
   40     char *p, *q;
   41 
   42     /* Check it's HTTP */
   43     if (memcmp(url, http_scheme, strlen(http_scheme)))
   44         return NULL;
   45 
   46     q = url + strlen(http_scheme);
   47 
   48     p = strchr(q, ':');
   49     if (p) {                    /* if : is after the first /, we have looked too far ahead */
   50         char *r = strchr(q, '/');
   51         if (r && r < p)
   52             p = NULL;
   53     }
   54     if (!p) {
   55         *port = strdup("http");
   56         p = strchr(q, '/');
   57     }
   58 
   59     if (!p)
   60         return NULL;
   61 
   62     if (p - q < hnlen - 1) {
   63         memcpy(hostn, q, p - q);
   64         hostn[p - q] = 0;
   65     }
   66 
   67     if (*p == ':') {
   68         size_t l;
   69         q = p;
   70         p = strchr(p, '/');
   71         l = p ? (size_t) (p - q - 1) : strlen(q) - 1;
   72         *port = malloc(l + 1);
   73         if (!*port)
   74             return NULL;
   75         memcpy(*port, q + 1, l);
   76         (*port)[l] = 0;
   77         if (!p)
   78             p = strdup("/");
   79     }
   80     return p;
   81 }
   82 
   83 /* abs_url_str = make_url_absolute(base_str, url_str)
   84  * Returns an absolute version of url_str relative to base_str, as a malloced
   85  * string. Or NULL on error. */
   86 char * __attribute__ ((pure)) make_url_absolute(const char *base, const char *url) {
   87     if (is_url_absolute(url))
   88         return strdup(url);
   89 
   90     /* Otherwise, we'll need a base URL to get the scheme and host */
   91     if (!base)
   92         return NULL;
   93 
   94     /* Next, is it a full-path URL? */
   95     if (*url == '/') {
   96         size_t l;
   97         char *newurl;
   98 
   99         /* Find the end of the scheme of the base URL, then the end of the
  100          * hostname[:port]/ */
  101         const char *p = strchr(base, ':');
  102         if (!p || p[1] != '/' || p[2] != '/')
  103             return NULL;
  104         p = strchr(p + 3, '/');
  105         if (!p)    /* We have a http://hostname URL (no trailing / or path) */
  106             l = strlen(base);
  107         else       /* http://hostname/... , we want just http://hostname */
  108             l = p - base;
  109 
  110         /* assert */
  111         if (base[l] != '/' && base[l] != '\0')
  112             return NULL;
  113 
  114         /* Append full path to the base http://hostname */
  115         newurl = malloc(l + strlen(url) + 1);
  116         memcpy(newurl, base, l);
  117         strcpy(newurl + l, url);
  118         return newurl;
  119     }
  120 
  121     /* No leading / or scheme - relative path */
  122     {
  123         int l;
  124         char *newurl;
  125 
  126         /* Find the end of the path part of the base URL */
  127         const char *q;
  128         const char *p = strchr(base, '?');
  129         if (!p)
  130             p = strchr(base, '#');
  131         if (!p)
  132             p = base + strlen(base);
  133 
  134         /* Find the last / in the path part */
  135         for (q = p; q > base && *q != '/'; q--);
  136         if (*q != '/')
  137             return NULL;
  138 
  139         /* Take the base URL up to and including the last /, and append the relative URL */
  140         l = q - base + 1;
  141         newurl = malloc(l + strlen(url) + 1);
  142         memcpy(newurl, base, l);
  143         strcpy(newurl + l, url);
  144         return newurl;
  145     }
  146 }
  147 
  148 /* int n = is_url_absolute(url)
  149  * Returns 0 if the supplied string is not an absolute URL.
  150  * Returns the number of characters in the URL scheme if it is.
  151  */
  152 static const char special[] = { ":/?" };
  153 
  154 int __attribute__ ((pure)) is_url_absolute(const char *url) {
  155     /* find end of first no-special-URL-characters part of the string */
  156     int n = strcspn(url, special);
  157 
  158     /* If the first special character is a :, the start is a URL scheme */
  159     if (n > 0 && url[n] == ':')
  160         return n;
  161 
  162     /* otherwise, it's a full path or relative path URL, or just a local file
  163      * path (caller knows the context) */
  164     return 0;
  165 }