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>
|
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
|
* main.c (main): Downgrade -r, -p with -O to a warning rather than
|
||||||
an error; elaborate just a bit more for other -O combination
|
an error; elaborate just a bit more for other -O combination
|
||||||
cases.
|
cases.
|
||||||
|
@ -40,6 +40,7 @@ const char *test_subdir_p();
|
|||||||
const char *test_dir_matches_p();
|
const char *test_dir_matches_p();
|
||||||
const char *test_commands_sorted();
|
const char *test_commands_sorted();
|
||||||
const char *test_cmd_spec_restrict_file_names();
|
const char *test_cmd_spec_restrict_file_names();
|
||||||
|
const char *test_path_simplify ();
|
||||||
const char *test_append_uri_pathel();
|
const char *test_append_uri_pathel();
|
||||||
const char *test_are_urls_equal();
|
const char *test_are_urls_equal();
|
||||||
const char *test_is_robots_txt_url();
|
const char *test_is_robots_txt_url();
|
||||||
@ -54,6 +55,7 @@ all_tests()
|
|||||||
mu_run_test (test_dir_matches_p);
|
mu_run_test (test_dir_matches_p);
|
||||||
mu_run_test (test_commands_sorted);
|
mu_run_test (test_commands_sorted);
|
||||||
mu_run_test (test_cmd_spec_restrict_file_names);
|
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_append_uri_pathel);
|
||||||
mu_run_test (test_are_urls_equal);
|
mu_run_test (test_are_urls_equal);
|
||||||
mu_run_test (test_is_robots_txt_url);
|
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: */
|
/* Forward declarations: */
|
||||||
|
|
||||||
static bool path_simplify (char *);
|
static bool path_simplify (enum url_scheme, char *);
|
||||||
|
|
||||||
/* Support for escaping and unescaping of URL strings. */
|
/* Support for escaping and unescaping of URL strings. */
|
||||||
|
|
||||||
@ -829,7 +829,7 @@ url_parse (const char *url, int *error)
|
|||||||
u->passwd = passwd;
|
u->passwd = passwd;
|
||||||
|
|
||||||
u->path = strdupdelim (path_b, path_e);
|
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);
|
split_path (u->path, &u->dir, &u->file);
|
||||||
|
|
||||||
host_modified = lowercase_str (u->host);
|
host_modified = lowercase_str (u->host);
|
||||||
@ -1526,10 +1526,11 @@ url_file_name (const struct url *u)
|
|||||||
test case. */
|
test case. */
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
path_simplify (char *path)
|
path_simplify (enum url_scheme scheme, char *path)
|
||||||
{
|
{
|
||||||
char *h = path; /* hare */
|
char *h = path; /* hare */
|
||||||
char *t = path; /* tortoise */
|
char *t = path; /* tortoise */
|
||||||
|
char *beg = path;
|
||||||
char *end = strchr (path, '\0');
|
char *end = strchr (path, '\0');
|
||||||
|
|
||||||
while (h < end)
|
while (h < end)
|
||||||
@ -1545,17 +1546,29 @@ path_simplify (char *path)
|
|||||||
{
|
{
|
||||||
/* Handle "../" by retreating the tortoise by one path
|
/* Handle "../" by retreating the tortoise by one path
|
||||||
element -- but not past beggining. */
|
element -- but not past beggining. */
|
||||||
if (t > path)
|
if (t > beg)
|
||||||
{
|
{
|
||||||
/* Move backwards until T hits the beginning of the
|
/* Move backwards until T hits the beginning of the
|
||||||
previous path element or the beginning of path. */
|
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;
|
h += 3;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
regular:
|
||||||
/* A regular path element. If H hasn't advanced past T,
|
/* A regular path element. If H hasn't advanced past T,
|
||||||
simply skip to the next path element. Otherwise, copy
|
simply skip to the next path element. Otherwise, copy
|
||||||
the path element until the next slash. */
|
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);
|
return (*p == 0 && *q == 0 ? true : false);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 0
|
#ifdef TESTING
|
||||||
/* Debugging and testing support for path_simplify. */
|
/* Debugging and testing support for path_simplify. */
|
||||||
|
|
||||||
|
#if 0
|
||||||
/* Debug: run path_simplify on PATH and return the result in a new
|
/* Debug: run path_simplify on PATH and return the result in a new
|
||||||
string. Useful for calling from the debugger. */
|
string. Useful for calling from the debugger. */
|
||||||
static char *
|
static char *
|
||||||
@ -2003,17 +2017,20 @@ ps (char *path)
|
|||||||
path_simplify (copy);
|
path_simplify (copy);
|
||||||
return copy;
|
return copy;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
static void
|
static const char *
|
||||||
run_test (char *test, char *expected_result, bool expected_change)
|
run_test (char *test, char *expected_result, enum url_scheme scheme,
|
||||||
|
bool expected_change)
|
||||||
{
|
{
|
||||||
char *test_copy = xstrdup (test);
|
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))
|
if (0 != strcmp (test_copy, expected_result))
|
||||||
{
|
{
|
||||||
printf ("Failed path_simplify(\"%s\"): expected \"%s\", got \"%s\".\n",
|
printf ("Failed path_simplify(\"%s\"): expected \"%s\", got \"%s\".\n",
|
||||||
test, expected_result, test_copy);
|
test, expected_result, test_copy);
|
||||||
|
mu_assert ("", 0);
|
||||||
}
|
}
|
||||||
if (modified != expected_change)
|
if (modified != expected_change)
|
||||||
{
|
{
|
||||||
@ -2025,51 +2042,60 @@ run_test (char *test, char *expected_result, bool expected_change)
|
|||||||
test);
|
test);
|
||||||
}
|
}
|
||||||
xfree (test_copy);
|
xfree (test_copy);
|
||||||
|
mu_assert ("", modified == expected_change);
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
const char *
|
||||||
test_path_simplify (void)
|
test_path_simplify (void)
|
||||||
{
|
{
|
||||||
static struct {
|
static struct {
|
||||||
char *test, *result;
|
char *test, *result;
|
||||||
|
enum url_scheme scheme;
|
||||||
bool should_modify;
|
bool should_modify;
|
||||||
} tests[] = {
|
} tests[] = {
|
||||||
{ "", "", false },
|
{ "", "", SCHEME_HTTP, false },
|
||||||
{ ".", "", true },
|
{ ".", "", SCHEME_HTTP, true },
|
||||||
{ "./", "", true },
|
{ "./", "", SCHEME_HTTP, true },
|
||||||
{ "..", "", true },
|
{ "..", "", SCHEME_HTTP, true },
|
||||||
{ "../", "", true },
|
{ "../", "", SCHEME_HTTP, true },
|
||||||
{ "foo", "foo", false },
|
{ "..", "..", SCHEME_FTP, false },
|
||||||
{ "foo/bar", "foo/bar", false },
|
{ "../", "../", SCHEME_FTP, false },
|
||||||
{ "foo///bar", "foo///bar", false },
|
{ "foo", "foo", SCHEME_HTTP, false },
|
||||||
{ "foo/.", "foo/", true },
|
{ "foo/bar", "foo/bar", SCHEME_HTTP, false },
|
||||||
{ "foo/./", "foo/", true },
|
{ "foo///bar", "foo///bar", SCHEME_HTTP, false },
|
||||||
{ "foo./", "foo./", false },
|
{ "foo/.", "foo/", SCHEME_HTTP, true },
|
||||||
{ "foo/../bar", "bar", true },
|
{ "foo/./", "foo/", SCHEME_HTTP, true },
|
||||||
{ "foo/../bar/", "bar/", true },
|
{ "foo./", "foo./", SCHEME_HTTP, false },
|
||||||
{ "foo/bar/..", "foo/", true },
|
{ "foo/../bar", "bar", SCHEME_HTTP, true },
|
||||||
{ "foo/bar/../x", "foo/x", true },
|
{ "foo/../bar/", "bar/", SCHEME_HTTP, true },
|
||||||
{ "foo/bar/../x/", "foo/x/", true },
|
{ "foo/bar/..", "foo/", SCHEME_HTTP, true },
|
||||||
{ "foo/..", "", true },
|
{ "foo/bar/../x", "foo/x", SCHEME_HTTP, true },
|
||||||
{ "foo/../..", "", true },
|
{ "foo/bar/../x/", "foo/x/", SCHEME_HTTP, true },
|
||||||
{ "foo/../../..", "", true },
|
{ "foo/..", "", SCHEME_HTTP, true },
|
||||||
{ "foo/../../bar/../../baz", "baz", true },
|
{ "foo/../..", "", SCHEME_HTTP, true },
|
||||||
{ "a/b/../../c", "c", true },
|
{ "foo/../../..", "", SCHEME_HTTP, true },
|
||||||
{ "./a/../b", "b", 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;
|
int i;
|
||||||
|
|
||||||
for (i = 0; i < countof (tests); i++)
|
for (i = 0; i < countof (tests); i++)
|
||||||
{
|
{
|
||||||
|
const char *message;
|
||||||
char *test = tests[i].test;
|
char *test = tests[i].test;
|
||||||
char *expected_result = tests[i].result;
|
char *expected_result = tests[i].result;
|
||||||
|
enum url_scheme scheme = tests[i].scheme;
|
||||||
bool expected_change = tests[i].should_modify;
|
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 *
|
const char *
|
||||||
test_append_uri_pathel()
|
test_append_uri_pathel()
|
||||||
|
Loading…
Reference in New Issue
Block a user