mirror of
https://github.com/moparisthebest/wget
synced 2024-07-03 16:38:41 -04:00
Add support for .. at beginning of paths back in, but only for FTP.
This commit is contained in:
parent
db61675ec0
commit
886cc094e1
@ -1,5 +1,12 @@
|
||||
2008-04-27 Micah Cowan <micah@cowan.name>
|
||||
|
||||
* url.c (path_simplify): Go back to allowing leading ".." in
|
||||
paths, but only for FTP URLs.
|
||||
(test_path_simplify): Add scheme-specificness to tests, adapt for
|
||||
mu_run_test.
|
||||
|
||||
* test.c (all_tests): Add test_path_simplify.
|
||||
|
||||
* main.c (main): Downgrade -r, -p with -O to a warning rather than
|
||||
an error; elaborate just a bit more for other -O combination
|
||||
cases.
|
||||
|
@ -40,6 +40,7 @@ const char *test_subdir_p();
|
||||
const char *test_dir_matches_p();
|
||||
const char *test_commands_sorted();
|
||||
const char *test_cmd_spec_restrict_file_names();
|
||||
const char *test_path_simplify ();
|
||||
const char *test_append_uri_pathel();
|
||||
const char *test_are_urls_equal();
|
||||
const char *test_is_robots_txt_url();
|
||||
@ -54,6 +55,7 @@ all_tests()
|
||||
mu_run_test (test_dir_matches_p);
|
||||
mu_run_test (test_commands_sorted);
|
||||
mu_run_test (test_cmd_spec_restrict_file_names);
|
||||
mu_run_test (test_path_simplify);
|
||||
mu_run_test (test_append_uri_pathel);
|
||||
mu_run_test (test_are_urls_equal);
|
||||
mu_run_test (test_is_robots_txt_url);
|
||||
|
98
src/url.c
98
src/url.c
@ -81,7 +81,7 @@ static struct scheme_data supported_schemes[] =
|
||||
|
||||
/* Forward declarations: */
|
||||
|
||||
static bool path_simplify (char *);
|
||||
static bool path_simplify (enum url_scheme, char *);
|
||||
|
||||
/* Support for escaping and unescaping of URL strings. */
|
||||
|
||||
@ -829,7 +829,7 @@ url_parse (const char *url, int *error)
|
||||
u->passwd = passwd;
|
||||
|
||||
u->path = strdupdelim (path_b, path_e);
|
||||
path_modified = path_simplify (u->path);
|
||||
path_modified = path_simplify (scheme, u->path);
|
||||
split_path (u->path, &u->dir, &u->file);
|
||||
|
||||
host_modified = lowercase_str (u->host);
|
||||
@ -1526,10 +1526,11 @@ url_file_name (const struct url *u)
|
||||
test case. */
|
||||
|
||||
static bool
|
||||
path_simplify (char *path)
|
||||
path_simplify (enum url_scheme scheme, char *path)
|
||||
{
|
||||
char *h = path; /* hare */
|
||||
char *t = path; /* tortoise */
|
||||
char *beg = path;
|
||||
char *end = strchr (path, '\0');
|
||||
|
||||
while (h < end)
|
||||
@ -1545,17 +1546,29 @@ path_simplify (char *path)
|
||||
{
|
||||
/* Handle "../" by retreating the tortoise by one path
|
||||
element -- but not past beggining. */
|
||||
if (t > path)
|
||||
if (t > beg)
|
||||
{
|
||||
/* Move backwards until T hits the beginning of the
|
||||
previous path element or the beginning of path. */
|
||||
for (--t; t > path && t[-1] != '/'; t--)
|
||||
for (--t; t > beg && t[-1] != '/'; t--)
|
||||
;
|
||||
}
|
||||
else if (scheme == SCHEME_FTP)
|
||||
{
|
||||
/* If we're at the beginning, copy the "../" literally
|
||||
and move the beginning so a later ".." doesn't remove
|
||||
it. This violates RFC 3986; but we do it for FTP
|
||||
anyway because there is otherwise no way to get at a
|
||||
parent directory, when the FTP server drops us in a
|
||||
non-root directory (which is not uncommon). */
|
||||
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. */
|
||||
@ -1991,9 +2004,10 @@ are_urls_equal (const char *u1, const char *u2)
|
||||
return (*p == 0 && *q == 0 ? true : false);
|
||||
}
|
||||
|
||||
#if 0
|
||||
#ifdef TESTING
|
||||
/* Debugging and testing support for path_simplify. */
|
||||
|
||||
#if 0
|
||||
/* Debug: run path_simplify on PATH and return the result in a new
|
||||
string. Useful for calling from the debugger. */
|
||||
static char *
|
||||
@ -2003,17 +2017,20 @@ ps (char *path)
|
||||
path_simplify (copy);
|
||||
return copy;
|
||||
}
|
||||
#endif
|
||||
|
||||
static void
|
||||
run_test (char *test, char *expected_result, bool expected_change)
|
||||
static const char *
|
||||
run_test (char *test, char *expected_result, enum url_scheme scheme,
|
||||
bool expected_change)
|
||||
{
|
||||
char *test_copy = xstrdup (test);
|
||||
bool modified = path_simplify (test_copy);
|
||||
bool modified = path_simplify (scheme, test_copy);
|
||||
|
||||
if (0 != strcmp (test_copy, expected_result))
|
||||
{
|
||||
printf ("Failed path_simplify(\"%s\"): expected \"%s\", got \"%s\".\n",
|
||||
test, expected_result, test_copy);
|
||||
mu_assert ("", 0);
|
||||
}
|
||||
if (modified != expected_change)
|
||||
{
|
||||
@ -2025,51 +2042,60 @@ run_test (char *test, char *expected_result, bool expected_change)
|
||||
test);
|
||||
}
|
||||
xfree (test_copy);
|
||||
mu_assert ("", modified == expected_change);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
const char *
|
||||
test_path_simplify (void)
|
||||
{
|
||||
static struct {
|
||||
char *test, *result;
|
||||
enum url_scheme scheme;
|
||||
bool should_modify;
|
||||
} tests[] = {
|
||||
{ "", "", false },
|
||||
{ ".", "", true },
|
||||
{ "./", "", true },
|
||||
{ "..", "", true },
|
||||
{ "../", "", true },
|
||||
{ "foo", "foo", false },
|
||||
{ "foo/bar", "foo/bar", false },
|
||||
{ "foo///bar", "foo///bar", false },
|
||||
{ "foo/.", "foo/", true },
|
||||
{ "foo/./", "foo/", true },
|
||||
{ "foo./", "foo./", false },
|
||||
{ "foo/../bar", "bar", true },
|
||||
{ "foo/../bar/", "bar/", true },
|
||||
{ "foo/bar/..", "foo/", true },
|
||||
{ "foo/bar/../x", "foo/x", true },
|
||||
{ "foo/bar/../x/", "foo/x/", true },
|
||||
{ "foo/..", "", true },
|
||||
{ "foo/../..", "", true },
|
||||
{ "foo/../../..", "", true },
|
||||
{ "foo/../../bar/../../baz", "baz", true },
|
||||
{ "a/b/../../c", "c", true },
|
||||
{ "./a/../b", "b", true }
|
||||
{ "", "", SCHEME_HTTP, false },
|
||||
{ ".", "", SCHEME_HTTP, true },
|
||||
{ "./", "", SCHEME_HTTP, true },
|
||||
{ "..", "", SCHEME_HTTP, true },
|
||||
{ "../", "", SCHEME_HTTP, true },
|
||||
{ "..", "..", SCHEME_FTP, false },
|
||||
{ "../", "../", SCHEME_FTP, false },
|
||||
{ "foo", "foo", SCHEME_HTTP, false },
|
||||
{ "foo/bar", "foo/bar", SCHEME_HTTP, false },
|
||||
{ "foo///bar", "foo///bar", SCHEME_HTTP, false },
|
||||
{ "foo/.", "foo/", SCHEME_HTTP, true },
|
||||
{ "foo/./", "foo/", SCHEME_HTTP, true },
|
||||
{ "foo./", "foo./", SCHEME_HTTP, false },
|
||||
{ "foo/../bar", "bar", SCHEME_HTTP, true },
|
||||
{ "foo/../bar/", "bar/", SCHEME_HTTP, true },
|
||||
{ "foo/bar/..", "foo/", SCHEME_HTTP, true },
|
||||
{ "foo/bar/../x", "foo/x", SCHEME_HTTP, true },
|
||||
{ "foo/bar/../x/", "foo/x/", SCHEME_HTTP, true },
|
||||
{ "foo/..", "", SCHEME_HTTP, true },
|
||||
{ "foo/../..", "", SCHEME_HTTP, true },
|
||||
{ "foo/../../..", "", SCHEME_HTTP, true },
|
||||
{ "foo/../../bar/../../baz", "baz", SCHEME_HTTP, true },
|
||||
{ "foo/../..", "..", SCHEME_FTP, true },
|
||||
{ "foo/../../..", "../..", SCHEME_FTP, true },
|
||||
{ "foo/../../bar/../../baz", "../../baz", SCHEME_FTP, true },
|
||||
{ "a/b/../../c", "c", SCHEME_HTTP, true },
|
||||
{ "./a/../b", "b", SCHEME_HTTP, true }
|
||||
};
|
||||
int i;
|
||||
|
||||
for (i = 0; i < countof (tests); i++)
|
||||
{
|
||||
const char *message;
|
||||
char *test = tests[i].test;
|
||||
char *expected_result = tests[i].result;
|
||||
enum url_scheme scheme = tests[i].scheme;
|
||||
bool expected_change = tests[i].should_modify;
|
||||
run_test (test, expected_result, expected_change);
|
||||
message = run_test (test, expected_result, scheme, expected_change);
|
||||
if (message) return message;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef TESTING
|
||||
|
||||
const char *
|
||||
test_append_uri_pathel()
|
||||
|
Loading…
Reference in New Issue
Block a user