X-Git-Url: http://mj.ucw.cz/gitweb/?a=blobdiff_plain;f=lib%2Furl.c;h=8f1a435bb241fa2c4592f5f6d93e545baa10d2ef;hb=35257848f97710b8107e20f690404cfaf0838f74;hp=105c7dd019e9f9d3c2de55a711b5cbd6eba390f8;hpb=26deef20888cd415ad2f0261cfa25ba58a0dfebb;p=libucw.git diff --git a/lib/url.c b/lib/url.c index 105c7dd0..8f1a435b 100644 --- a/lib/url.c +++ b/lib/url.c @@ -1,8 +1,8 @@ /* - * Sherlock Library -- URL Functions + * UCW Library -- URL Functions * * (c) 1997--2004 Martin Mares - * (c) 2001 Robert Spalek + * (c) 2001--2005 Robert Spalek * * This software may be freely distributed and used according to the terms * of the GNU Lesser General Public License. @@ -11,9 +11,8 @@ * * o Escaping of special characters still follows RFC 1738. * o Interpretation of path parameters follows RFC 1808. - * o Parsing a relative URL "x" wrt. base "http://hell.org?y" - * gives an error, which might be wrong. However, I failed - * to find any rule applying to this case in the RFC. + * + * XXX: The buffer handling in this module is really horrible, but it works. */ #include "lib/lib.h" @@ -30,23 +29,24 @@ static uns url_ignore_spaces; static uns url_ignore_underflow; -static byte *url_component_separators = ""; +static char *url_component_separators = ""; 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 } +static struct cf_section url_config = { + CF_ITEMS { + CF_UNS("IgnoreSpaces", &url_ignore_spaces), + CF_UNS("IgnoreUnderflow", &url_ignore_underflow), + CF_STRING("ComponentSeparators", &url_component_separators), + CF_UNS("MinRepeatCount", &url_min_repeat_count), + CF_UNS("MaxRepeatLength", &url_max_repeat_length), + CF_END + } }; static void CONSTRUCTOR url_init_config(void) { - cf_register(url_config); + cf_declare_section("URL", &url_config, 0); } /* Escaping and de-escaping */ @@ -58,7 +58,7 @@ enhex(uns x) } int -url_deescape(byte *s, byte *d) +url_deescape(const byte *s, byte *d) { byte *dstart = d; byte *end = d + MAX_URL_SIZE - 10; @@ -100,7 +100,7 @@ url_deescape(byte *s, byte *d) *d++ = *s++; else if (Cspace(*s)) { - byte *s0 = s; + const byte *s0 = s; while (Cspace(*s)) s++; if (!url_ignore_spaces || !(!*s || d == dstart)) @@ -121,7 +121,7 @@ url_deescape(byte *s, byte *d) } int -url_enescape(byte *s, byte *d) +url_enescape(const byte *s, byte *d) { byte *end = d + MAX_URL_SIZE - 10; unsigned int c; @@ -150,13 +150,36 @@ url_enescape(byte *s, byte *d) return 0; } +int +url_enescape_friendly(const byte *src, byte *dest) +{ + byte *end = dest + MAX_URL_SIZE - 10; + while (*src) + { + if (dest >= end) + return URL_ERR_TOO_LONG; + if (*src < NCC_MAX) + *dest++ = NCC_CHARS[*src++]; + else if (*src >= 0x20 && *src < 0x7f) + *dest++ = *src++; + else + { + *dest++ = '%'; + *dest++ = enhex(*src >> 4); + *dest++ = enhex(*src++ & 0x0f); + } + } + *dest = 0; + return 0; +} + /* Split an URL (several parts may be copied to the destination buffer) */ byte *url_proto_names[URL_PROTO_MAX] = URL_PNAMES; static int url_proto_path_flags[URL_PROTO_MAX] = URL_PATH_FLAGS; uns -identify_protocol(byte *p) +identify_protocol(const byte *p) { uns i; @@ -202,18 +225,28 @@ url_split(byte *s, struct url *u, byte *d) { if (s[1] == '/') /* Host spec */ { - byte *q, *w, *e; + byte *q, *e; + byte *at = NULL; char *ep; s += 2; q = d; while (*s && *s != '/' && *s != '?') /* Copy user:passwd@host:port */ - *d++ = *s++; + { + if (*s != '@') + *d++ = *s; + else if (!at) + { + *d++ = 0; + at = d; + } + else /* This shouldn't happen with sane URL's, but we need to be sure */ + *d++ = NCC_AT; + s++; + } *d++ = 0; - w = strchr(q, '@'); - if (w) /* user:passwd present */ + if (at) /* user:passwd present */ { - *w++ = 0; u->user = q; if (e = strchr(q, ':')) { @@ -222,8 +255,8 @@ url_split(byte *s, struct url *u, byte *d) } } else - w = q; - e = strchr(w, ':'); + at = q; + e = strchr(at, ':'); if (e) /* host:port present */ { uns p; @@ -234,7 +267,7 @@ url_split(byte *s, struct url *u, byte *d) else if (p) /* Port 0 (e.g. in :/) is treated as default port */ u->port = p; } - u->host = w; + u->host = at; } } @@ -369,8 +402,7 @@ 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) @@ -396,6 +428,18 @@ url_normalize(struct url *u, struct url *b) } } + /* 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]; @@ -448,7 +492,7 @@ url_canonicalize(struct url *u) /* Pack a broken-down URL */ static byte * -append(byte *d, byte *s, byte *e) +append(byte *d, const byte *s, byte *e) { if (d) while (*s) @@ -527,7 +571,7 @@ url_error(uns err) /* Standard cookbook recipes */ int -url_canon_split(byte *u, byte *buf1, byte *buf2, struct url *url) +url_canon_split_rel(const byte *u, byte *buf1, byte *buf2, struct url *url, struct url *base) { int err; @@ -535,19 +579,19 @@ url_canon_split(byte *u, byte *buf1, byte *buf2, struct url *url) return err; if (err = url_split(buf1, url, buf2)) return err; - if (err = url_normalize(url, NULL)) + if (err = url_normalize(url, base)) return err; return url_canonicalize(url); } int -url_auto_canonicalize(byte *src, byte *dst) +url_auto_canonicalize_rel(const byte *src, byte *dst, struct url *base) { byte buf1[MAX_URL_SIZE], buf2[MAX_URL_SIZE], buf3[MAX_URL_SIZE]; int err; struct url ur; - (void)((err = url_canon_split(src, buf1, buf2, &ur)) || + (void)((err = url_canon_split_rel(src, buf1, buf2, &ur, base)) || (err = url_pack(&ur, buf3)) || (err = url_enescape(buf3, dst))); return err; @@ -621,13 +665,13 @@ int main(int argc, char **argv) #endif struct component { - byte *start; + const byte *start; int length; u32 hash; }; static inline u32 -hashf(byte *start, int length) +hashf(const byte *start, int length) { u32 hf = length; while (length-- > 0) @@ -657,11 +701,11 @@ repeat_count(struct component *comp, uns count, uns len) } int -url_has_repeated_component(byte *url) +url_has_repeated_component(const byte *url) { struct component *comp; uns comps, comp_len, rep_prefix; - byte *c; + const byte *c; uns i; for (comps=0, c=url; c; comps++)