X-Git-Url: http://mj.ucw.cz/gitweb/?a=blobdiff_plain;ds=inline;f=lib%2Furl.c;h=8475a85f378498835509117b51c5b35362f208eb;hb=e828732528e0ed88973dd18f2dee97a42c0b4e59;hp=a6dcf7aa06fe4f1335edbe921359136b17bed1dc;hpb=877514e50fdbfedb5755d5d5c7316d2dd20f8104;p=libucw.git diff --git a/lib/url.c b/lib/url.c index a6dcf7aa..8475a85f 100644 --- a/lib/url.c +++ b/lib/url.c @@ -1,8 +1,18 @@ /* - * Sherlock Library -- URL Functions (according to RFC 1738 and 1808) + * Sherlock Library -- URL Functions * - * (c) 1997--2001 Martin Mares + * (c) 1997--2004 Martin Mares * (c) 2001 Robert Spalek + * + * This software may be freely distributed and used according to the terms + * of the GNU Lesser General Public License. + * + * The URL syntax corresponds to RFC 2396 with several exceptions: + * + * o Escaping of special characters still follows RFC 1738. + * o Interpretation of path parameters follows RFC 1808. + * + * XXX: The buffer handling in this module is really horrible, but it works. */ #include "lib/lib.h" @@ -13,6 +23,7 @@ #include #include #include +#include /* Configuration */ @@ -23,13 +34,13 @@ static uns url_min_repeat_count = 0x7fffffff; static uns url_max_repeat_length = 0; static struct cfitem url_config[] = { - { "URL", CT_SECTION, NULL }, - { "IgnoreSpaces", CT_INT, &url_ignore_spaces }, - { "IgnoreUnderflow", CT_INT, &url_ignore_underflow }, - { "ComponentSeparators", CT_STRING, &url_component_separators }, - { "MinRepeatCount", CT_INT, &url_min_repeat_count }, - { "MaxRepeatLength", CT_INT, &url_max_repeat_length }, - { NULL, CT_STOP, NULL } + { "URL", CT_SECTION, NULL }, + { "IgnoreSpaces", CT_INT, &url_ignore_spaces }, + { "IgnoreUnderflow", CT_INT, &url_ignore_underflow }, + { "ComponentSeparators", CT_STRING, &url_component_separators }, + { "MinRepeatCount", CT_INT, &url_min_repeat_count }, + { "MaxRepeatLength", CT_INT, &url_max_repeat_length }, + { NULL, CT_STOP, NULL } }; static void CONSTRUCTOR url_init_config(void) @@ -195,7 +206,7 @@ url_split(byte *s, struct url *u, byte *d) s += 2; q = d; - while (*s && *s != '/') /* Copy user:passwd@host:port */ + while (*s && *s != '/' && *s != '?') /* Copy user:passwd@host:port */ *d++ = *s++; *d++ = 0; w = strchr(q, '@'); @@ -203,6 +214,11 @@ url_split(byte *s, struct url *u, byte *d) { *w++ = 0; u->user = q; + if (e = strchr(q, ':')) + { + *e++ = 0; + u->pass = e; + } } else w = q; @@ -241,7 +257,7 @@ relpath_merge(struct url *u, struct url *b) if (a[0] == '/') /* Absolute path => OK */ return 0; - if (o[0] != '/') + if (o[0] != '/' && o[0] != '?') return URL_PATH_UNDERFLOW; if (!a[0]) /* Empty URL -> inherit everything */ @@ -352,9 +368,9 @@ url_normalize(struct url *u, struct url *b) int err; /* Basic checks */ - if (url_proto_path_flags[u->protoid] && !u->host || - u->host && !*u->host || + if (url_proto_path_flags[u->protoid] && (!u->host || !*u->host) || !u->host && u->user || + !u->user && u->pass || !u->rest) return URL_SYNTAX_ERROR; @@ -371,12 +387,25 @@ url_normalize(struct url *u, struct url *b) { u->host = b->host; u->user = b->user; + u->pass = b->pass; u->port = b->port; if (err = relpath_merge(u, b)) return err; } } + /* Change path "?" to "/?" because it's the true meaning */ + if (u->rest[0] == '?') + { + int l = strlen(u->rest); + if (u->bufend - u->buf < l+1) + return URL_ERR_TOO_LONG; + u->buf[0] = '/'; + memcpy(u->buf+1, u->rest, l+1); + u->rest = u->buf; + u->buf += l+2; + } + /* Fill in missing info */ if (u->port == ~0U) u->port = std_ports[u->protoid]; @@ -406,8 +435,8 @@ kill_end_dot(byte *b) if (b) { k = b + strlen(b) - 1; - if (k > b && *k == '.') - *k = 0; + while (k > b && *k == '.') + *k-- = 0; } } @@ -458,6 +487,11 @@ url_pack(struct url *u, byte *d) if (u->user) { d = append(d, u->user, e); + if (u->pass) + { + d = append(d, ":", e); + d = append(d, u->pass, e); + } d = append(d, "@", e); } d = append(d, u->host, e); @@ -538,9 +572,12 @@ int main(int argc, char **argv) char buf1[MAX_URL_SIZE], buf2[MAX_URL_SIZE], buf3[MAX_URL_SIZE], buf4[MAX_URL_SIZE]; int err; struct url url, url0; + char *base = "http://mj@www.hell.org/123/sub_dir/index.html;param?query&zzz/subquery#fragment"; - if (argc != 2) + if (argc != 2 && argc != 3) return 1; + if (argc == 3) + base = argv[2]; if (err = url_deescape(argv[1], buf1)) { printf("deesc: error %d\n", err); @@ -552,8 +589,8 @@ int main(int argc, char **argv) printf("split: error %d\n", err); return 1; } - printf("split: @%s@%s@%s@%d@%s\n", url.protocol, url.user, url.host, url.port, url.rest); - if (err = url_split("http://mj@www.hell.org/123/sub_dir/index.html;param?query&zzz/subquery#fragment", &url0, buf3)) + printf("split: @%s@%s@%s@%s@%d@%s\n", url.protocol, url.user, url.pass, url.host, url.port, url.rest); + if (err = url_split(base, &url0, buf3)) { printf("split base: error %d\n", err); return 1; @@ -563,19 +600,19 @@ int main(int argc, char **argv) printf("normalize base: error %d\n", err); return 1; } - printf("base: @%s@%s@%s@%d@%s\n", url0.protocol, url0.user, url0.host, url0.port, url0.rest); + printf("base: @%s@%s@%s@%s@%d@%s\n", url0.protocol, url0.user, url0.pass, url0.host, url0.port, url0.rest); if (err = url_normalize(&url, &url0)) { printf("normalize: error %d\n", err); return 1; } - printf("normalize: @%s@%s@%s@%d@%s\n", url.protocol, url.user, url.host, url.port, url.rest); + printf("normalize: @%s@%s@%s@%s@%d@%s\n", url.protocol, url.user, url.pass, url.host, url.port, url.rest); if (err = url_canonicalize(&url)) { printf("canonicalize: error %d\n", err); return 1; } - printf("canonicalize: @%s@%s@%s@%d@%s\n", url.protocol, url.user, url.host, url.port, url.rest); + printf("canonicalize: @%s@%s@%s@%s@%d@%s\n", url.protocol, url.user, url.pass, url.host, url.port, url.rest); if (err = url_pack(&url, buf4)) { printf("pack: error %d\n", err);