#include "url.h"
#include "host.h" /* for is_valid_ipv6_address */
+#ifdef TESTING
+#include "test.h"
+#endif
+
enum {
scm_disabled = 1, /* for https when OpenSSL fails to init. */
scm_has_params = 2, /* whether scheme has ;params */
}
/* Used by main.c: detect URLs written using the "shorthand" URL forms
- popularized by Netscape and NcFTP. HTTP shorthands look like this:
+ originally popularized by Netscape and NcFTP. HTTP shorthands look
+ like this:
www.foo.com[:port]/dir/file -> http://www.foo.com[:port]/dir/file
www.foo.com[:port] -> http://www.foo.com[:port]
rewrite_shorthand_url (const char *url)
{
const char *p;
+ char *ret;
if (url_scheme (url) != SCHEME_INVALID)
return NULL;
/* Look for a ':' or '/'. The former signifies NcFTP syntax, the
latter Netscape. */
- for (p = url; *p && *p != ':' && *p != '/'; p++)
- ;
-
+ p = strpbrk (url, ":/");
if (p == url)
return NULL;
/* If we're looking at "://", it means the URL uses a scheme we
don't support, which may include "https" when compiled without
SSL support. Don't bogusly rewrite such URLs. */
- if (p[0] == ':' && p[1] == '/' && p[2] == '/')
+ if (p && p[0] == ':' && p[1] == '/' && p[2] == '/')
return NULL;
- if (*p == ':')
+ if (p && *p == ':')
{
- const char *pp;
- char *res;
- /* If the characters after the colon and before the next slash
- or end of string are all digits, it's HTTP. */
- int digits = 0;
- for (pp = p + 1; ISDIGIT (*pp); pp++)
- ++digits;
- if (digits > 0 && (*pp == '/' || *pp == '\0'))
+ /* Colon indicates ftp, as in foo.bar.com:path. Check for
+ special case of http port number ("localhost:10000"). */
+ int digits = strspn (p + 1, "0123456789");
+ if (digits && (p[1 + digits] == '/' || p[1 + digits] == '\0'))
goto http;
- /* Prepend "ftp://" to the entire URL... */
- res = xmalloc (6 + strlen (url) + 1);
- sprintf (res, "ftp://%s", url);
- /* ...and replace ':' with '/'. */
- res[6 + (p - url)] = '/';
- return res;
+ /* Turn "foo.bar.com:path" to "ftp://foo.bar.com/path". */
+ ret = aprintf ("ftp://%s", url);
+ ret[6 + (p - url)] = '/';
}
else
{
- char *res;
http:
- /* Just prepend "http://" to what we have. */
- res = xmalloc (7 + strlen (url) + 1);
- sprintf (res, "http://%s", url);
- return res;
+ /* Just prepend "http://" to URL. */
+ ret = aprintf ("http://%s", url);
}
+ return ret;
}
\f
static void split_path (const char *, char **, char **);
}
assert (q - TAIL (dest) == outlen);
}
+
+ /* Perform inline case transformation if required. */
+ if (opt.restrict_files_case == restrict_lowercase
+ || opt.restrict_files_case == restrict_uppercase)
+ {
+ char *q;
+ for (q = TAIL (dest); *q; ++q)
+ {
+ if (opt.restrict_files_case == restrict_lowercase)
+ *q = TOLOWER (*q);
+ else
+ *q = TOUPPER (*q);
+ }
+ }
+
TAIL_INCR (dest, outlen);
}
{
char *h = path; /* hare */
char *t = path; /* tortoise */
- char *beg = path; /* boundary for backing the tortoise */
- char *end = path + strlen (path);
+ char *end = strchr (path, '\0');
while (h < end)
{
{
/* Handle "../" by retreating the tortoise by one path
element -- but not past beggining. */
- if (t > beg)
+ if (t > path)
{
/* Move backwards until T hits the beginning of the
previous path element or the beginning of path. */
- for (--t; t > beg && t[-1] != '/'; t--)
+ for (--t; t > path && t[-1] != '/'; t--)
;
}
- else
- {
- /* If we're at the beginning, copy the "../" literally
- move the beginning so a later ".." doesn't remove
- it. */
- beg = t + 3;
- goto regular;
- }
h += 3;
}
else
{
- regular:
/* A regular path element. If H hasn't advanced past T,
simply skip to the next path element. Otherwise, copy
the path element until the next slash. */
}
/* Find the last occurrence of character C in the range [b, e), or
- NULL, if none are present. We might want to use memrchr (a GNU
- extension) under GNU libc. */
-
-static const char *
-find_last_char (const char *b, const char *e, char c)
-{
- for (; e > b; e--)
- if (*e == c)
- return e;
- return NULL;
-}
+ NULL, if none are present. */
+#define find_last_char(b, e, c) memrchr ((b), (c), (e) - (b))
/* Merge BASE with LINK and return the resulting URI.
{ "", "", false },
{ ".", "", true },
{ "./", "", true },
- { "..", "..", false },
- { "../", "../", false },
+ { "..", "", true },
+ { "../", "", true },
{ "foo", "foo", false },
{ "foo/bar", "foo/bar", false },
{ "foo///bar", "foo///bar", false },
{ "foo/bar/../x", "foo/x", true },
{ "foo/bar/../x/", "foo/x/", true },
{ "foo/..", "", true },
- { "foo/../..", "..", true },
- { "foo/../../..", "../..", true },
- { "foo/../../bar/../../baz", "../../baz", true },
+ { "foo/../..", "", true },
+ { "foo/../../..", "", true },
+ { "foo/../../bar/../../baz", "baz", true },
{ "a/b/../../c", "c", true },
{ "./a/../b", "b", true }
};
}
}
#endif
+\f
+#ifdef TESTING
+
+const char *
+test_append_uri_pathel()
+{
+ int i;
+ struct {
+ char *original_url;
+ char *input;
+ bool escaped;
+ char *expected_result;
+ } test_array[] = {
+ { "http://www.yoyodyne.com/path/", "somepage.html", false, "http://www.yoyodyne.com/path/somepage.html" },
+ };
+
+ for (i = 0; i < sizeof(test_array)/sizeof(test_array[0]); ++i)
+ {
+ struct growable dest;
+ const char *p = test_array[i].input;
+
+ memset (&dest, 0, sizeof (dest));
+
+ append_string (test_array[i].original_url, &dest);
+ append_uri_pathel (p, p + strlen(p), test_array[i].escaped, &dest);
+
+ mu_assert ("test_append_uri_pathel: wrong result",
+ strcmp (dest.base, test_array[i].expected_result) == 0);
+ }
+
+ return NULL;
+}
+
+#endif /* TESTING */
+