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
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;
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;