From 27d5becdaf815f19fa756ae760077383210a172e Mon Sep 17 00:00:00 2001 From: hniksic Date: Sat, 25 Oct 2003 04:58:24 -0700 Subject: [PATCH] [svn] Better document the workings of construct_relative(). Reformat is_valid_ipv6_address() to GNU formatting style. --- src/ChangeLog | 8 +++ src/convert.c | 91 ++++++++++++++++------------ src/url.c | 165 ++++++++++++++++++++++++++------------------------ 3 files changed, 148 insertions(+), 116 deletions(-) diff --git a/src/ChangeLog b/src/ChangeLog index 05861c94..f7e0e94f 100644 --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,3 +1,11 @@ +2003-10-25 Hrvoje Niksic + + * url.c (is_valid_ipv6_address): Reformat to GNU coding style. + Use enums for NS_IN* constants. Use ISXDIGIT. + + * convert.c (construct_relative): Document better how the function + works. + 2003-10-23 Hrvoje Niksic * config.h.in: Deploy preprocessor magic to avoid Ultrix's diff --git a/src/convert.c b/src/convert.c index cb8dbb85..941bf05d 100644 --- a/src/convert.c +++ b/src/convert.c @@ -327,52 +327,67 @@ convert_links (const char *file, struct urlpos *links) logprintf (LOG_VERBOSE, "%d-%d\n", to_file_count, to_url_count); } -/* Construct and return a link that points from S1's position to S2. - Both files should be local file names, S1 of the referrering file, - and S2 of the referred file. +/* Construct and return a link that points from BASEFILE to LINKFILE. + Both files should be local file names, BASEFILE of the referrering + file, and LINKFILE of the referred file. - So, if S1 is "H/index.html" and S2 is "H/images/news.gif", this - function will return "images/news.gif". On the other hand, if S1 - is "H/ioccc/index.html", and S2 is "H/images/fly.gif", it will - return "../images/fly.gif". + Examples: - Caveats: S1 should not begin with `/', unless S2 also begins with - '/'. S1 should not contain things like ".." and such -- - construct_relative ("fly/ioccc/../index.html", - "fly/images/fly.gif") will fail. (A workaround is to call - something like path_simplify() on S1). */ + cr("foo", "bar") -> "bar" + cr("A/foo", "A/bar") -> "bar" + cr("A/foo", "A/B/bar") -> "B/bar" + cr("A/X/foo", "A/Y/bar") -> "../Y/bar" + cr("X/", "Y/bar") -> "../Y/bar" (trailing slash does matter in BASE) + + Both files should be absolute or relative, otherwise strange + results might ensue. The function makes no special efforts to + handle "." and ".." in links, so make sure they're not there + (e.g. using path_simplify). */ static char * -construct_relative (const char *s1, const char *s2) +construct_relative (const char *basefile, const char *linkfile) { - int i, cnt, sepdirs1; - char *res; + char *link; + int basedirs; + const char *b, *l; + int i, start; + + /* First, skip the initial directory components common to both + files. */ + start = 0; + for (b = basefile, l = linkfile; *b == *l && *b != '\0'; ++b, ++l) + { + if (*b == '/') + start = (b - basefile) + 1; + } + basefile += start; + linkfile += start; + + /* With common directories out of the way, the situation we have is + as follows: + b - b1/b2/[...]/bfile + l - l1/l2/[...]/lfile - i = cnt = 0; - /* Skip the directories common to both strings. */ - while (1) + The link we're constructing needs to be: + lnk - ../../l1/l2/[...]/lfile + + Where the number of ".."'s equals the number of bN directory + components in B. */ + + /* Count the directory components in B. */ + basedirs = 0; + for (b = basefile; *b; b++) { - while (s1[i] && s2[i] - && (s1[i] == s2[i]) - && (s1[i] != '/') - && (s2[i] != '/')) - ++i; - if (s1[i] == '/' && s2[i] == '/') - cnt = ++i; - else - break; + if (*b == '/') + ++basedirs; } - for (sepdirs1 = 0; s1[i]; i++) - if (s1[i] == '/') - ++sepdirs1; - /* Now, construct the file as of: - - ../ repeated sepdirs1 time - - all the non-mutual directories of S2. */ - res = (char *)xmalloc (3 * sepdirs1 + strlen (s2 + cnt) + 1); - for (i = 0; i < sepdirs1; i++) - memcpy (res + 3 * i, "../", 3); - strcpy (res + 3 * i, s2 + cnt); - return res; + + /* Construct LINK as explained above. */ + link = (char *)xmalloc (3 * basedirs + strlen (linkfile) + 1); + for (i = 0; i < basedirs; i++) + memcpy (link + 3 * i, "../", 3); + strcpy (link + 3 * i, linkfile); + return link; } static void diff --git a/src/url.c b/src/url.c index 9f50127c..ecb79b9c 100644 --- a/src/url.c +++ b/src/url.c @@ -641,48 +641,52 @@ static char *parse_errors[] = { static int is_valid_ipv4_address (const char *str, const char *end) { - int saw_digit, octets; - int val; + int saw_digit = 0; + int octets = 0; + int val = 0; - saw_digit = 0; - octets = 0; - val = 0; - - while (str < end) { - int ch = *str++; + while (str < end) + { + int ch = *str++; - if (ch >= '0' && ch <= '9') { - val = val * 10 + (ch - '0'); + if (ch >= '0' && ch <= '9') + { + val = val * 10 + (ch - '0'); - if (val > 255) - return 0; - if (saw_digit == 0) { - if (++octets > 4) - return 0; - saw_digit = 1; - } - } else if (ch == '.' && saw_digit == 1) { - if (octets == 4) - return 0; - val = 0; - saw_digit = 0; - } else - return 0; - } + if (val > 255) + return 0; + if (saw_digit == 0) + { + if (++octets > 4) + return 0; + saw_digit = 1; + } + } + else if (ch == '.' && saw_digit == 1) + { + if (octets == 4) + return 0; + val = 0; + saw_digit = 0; + } + else + return 0; + } if (octets < 4) return 0; return 1; } -static const int NS_INADDRSZ = 4; -static const int NS_IN6ADDRSZ = 16; -static const int NS_INT16SZ = 2; - static int is_valid_ipv6_address (const char *str, const char *end) { - static const char xdigits[] = "0123456789abcdef"; + enum { + NS_INADDRSZ = 4, + NS_IN6ADDRSZ = 16, + NS_INT16SZ = 2 + }; + const char *curtok; int tp; const char *colonp; @@ -707,62 +711,67 @@ is_valid_ipv6_address (const char *str, const char *end) saw_xdigit = 0; val = 0; - while (str < end) { - int ch = *str++; - const char *pch; + while (str < end) + { + int ch = *str++; - /* if ch is a number, add it to val. */ - pch = strchr(xdigits, ch); - if (pch != NULL) { - val <<= 4; - val |= (pch - xdigits); - if (val > 0xffff) - return 0; - saw_xdigit = 1; - continue; + /* if ch is a number, add it to val. */ + if (ISXDIGIT (ch)) + { + val <<= 4; + val |= XDIGIT_TO_NUM (ch); + if (val > 0xffff) + return 0; + saw_xdigit = 1; + continue; + } + + /* if ch is a colon ... */ + if (ch == ':') + { + curtok = str; + if (saw_xdigit == 0) + { + if (colonp != NULL) + return 0; + colonp = str + tp; + continue; + } + else if (str == end) + return 0; + if (tp > NS_IN6ADDRSZ - NS_INT16SZ) + return 0; + tp += NS_INT16SZ; + saw_xdigit = 0; + val = 0; + continue; + } + + /* if ch is a dot ... */ + if (ch == '.' && (tp <= NS_IN6ADDRSZ - NS_INADDRSZ) + && is_valid_ipv4_address (curtok, end) == 1) + { + tp += NS_INADDRSZ; + saw_xdigit = 0; + break; + } + + return 0; } - /* if ch is a colon ... */ - if (ch == ':') { - curtok = str; - if (saw_xdigit == 0) { - if (colonp != NULL) - return 0; - colonp = str + tp; - continue; - } else if (str == end) { - return 0; - } - if (tp > NS_IN6ADDRSZ - NS_INT16SZ) + if (saw_xdigit == 1) + { + if (tp > NS_IN6ADDRSZ - NS_INT16SZ) return 0; tp += NS_INT16SZ; - saw_xdigit = 0; - val = 0; - continue; } - /* if ch is a dot ... */ - if (ch == '.' && (tp <= NS_IN6ADDRSZ - NS_INADDRSZ) && - is_valid_ipv4_address(curtok, end) == 1) { - tp += NS_INADDRSZ; - saw_xdigit = 0; - break; + if (colonp != NULL) + { + if (tp == NS_IN6ADDRSZ) + return 0; + tp = NS_IN6ADDRSZ; } - - return 0; - } - - if (saw_xdigit == 1) { - if (tp > NS_IN6ADDRSZ - NS_INT16SZ) - return 0; - tp += NS_INT16SZ; - } - - if (colonp != NULL) { - if (tp == NS_IN6ADDRSZ) - return 0; - tp = NS_IN6ADDRSZ; - } if (tp != NS_IN6ADDRSZ) return 0; -- 2.39.2