diff --git a/src/ChangeLog b/src/ChangeLog index abbf2e28..846fa4b2 100644 --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,3 +1,22 @@ +2006-03-15 Mauro Tortonesi + + * utils.c: Restricted operational semantics of frontcmp and proclist + from generic strings to directory names and them to subdir_p and + dir_matches_p respectively. Applied George Ogata's one line patch to + restrict algorithm of subdir_p to full directory name matching. Added + testcases for subdir_p and dir_matches_p. + + * utils.h: Changed all frontcmp occurrences to subdir_p. + + * recur.c: Ditto. + + * test.c: Changed type returned by test functions from char * to const + char *. Added test_subdir_p and test_dir_matches_p to the list of + tests to run. + + * http.c (test_parse_content_disposition): Changed return type from + char * to const char *. + 2006-03-14 Mauro Tortonesi * recur.c (struct queue_element): Changed type of html_allowed member diff --git a/src/http.c b/src/http.c index 4752ce3d..d28ee7a8 100644 --- a/src/http.c +++ b/src/http.c @@ -2929,7 +2929,7 @@ http_cleanup (void) #ifdef TESTING -char * +const char * test_parse_content_disposition() { int i; @@ -2953,8 +2953,6 @@ test_parse_content_disposition() res == test_array[i].result && (res == false || 0 == strcmp (test_array[i].filename, filename))); - - /* printf ("test %d: %s\n", i, res == false ? "false" : filename); */ } return NULL; diff --git a/src/recur.c b/src/recur.c index 641174d6..1e277ca3 100644 --- a/src/recur.c +++ b/src/recur.c @@ -482,7 +482,7 @@ download_child_p (const struct urlpos *upos, struct url *parent, int depth, && u->port == start_url_parsed->port && !(opt.page_requisites && upos->link_inline_p)) { - if (!frontcmp (start_url_parsed->dir, u->dir)) + if (!subdir_p (start_url_parsed->dir, u->dir)) { DEBUGP (("Going to \"%s\" would escape \"%s\" with no_parent on.\n", u->dir, start_url_parsed->dir)); diff --git a/src/test.c b/src/test.c index 06cd0a4b..9f54a3e4 100644 --- a/src/test.c +++ b/src/test.c @@ -35,12 +35,18 @@ so, delete this exception statement from your version. */ #error "TESTING not set!!!" #endif +const char *test_parse_content_disposition(); +const char *test_subdir_p(); +const char *test_dir_matches_p(); + int tests_run; -static char * +static const char * all_tests() { mu_run_test (test_parse_content_disposition); + mu_run_test (test_subdir_p); + mu_run_test (test_dir_matches_p); return NULL; } @@ -49,7 +55,7 @@ all_tests() int main (void) { - char *result = all_tests(); + const char *result = all_tests(); if (result != NULL) { diff --git a/src/test.h b/src/test.h index 60e03c79..9037ea12 100644 --- a/src/test.h +++ b/src/test.h @@ -32,7 +32,7 @@ so, delete this exception statement from your version. */ /* from MinUnit */ #define mu_assert(message, test) do { if (!(test)) return message; } while (0) -#define mu_run_test(test) do { char *message = test(); tests_run++; \ +#define mu_run_test(test) do { const char *message = test(); tests_run++; \ if (message) return message; } while (0) extern int tests_run; diff --git a/src/utils.c b/src/utils.c index 667efce6..72310341 100644 --- a/src/utils.c +++ b/src/utils.c @@ -81,6 +81,10 @@ so, delete this exception statement from your version. */ #include "utils.h" #include "hash.h" +#ifdef TESTING +#include "test.h" +#endif + /* Utility function: like xstrdup(), but also lowercases S. */ char * @@ -677,46 +681,49 @@ acceptable (const char *s) return true; } -/* Compare S1 and S2 frontally; S2 must begin with S1. E.g. if S1 is - `/something', frontcmp() will return true only if S2 begins with - `/something'. */ +/* Check if D2 is a subdirectory of D1. E.g. if D1 is `/something', subdir_p() + will return true if and only if D2 begins with `/something/' or is exactly + '/something'. */ bool -frontcmp (const char *s1, const char *s2) +subdir_p (const char *d1, const char *d2) { if (!opt.ignore_case) - for (; *s1 && *s2 && (*s1 == *s2); ++s1, ++s2) + for (; *d1 && *d2 && (*d1 == *d2); ++d1, ++d2) ; else - for (; *s1 && *s2 && (TOLOWER (*s1) == TOLOWER (*s2)); ++s1, ++s2) + for (; *d1 && *d2 && (TOLOWER (*d1) == TOLOWER (*d2)); ++d1, ++d2) ; - return *s1 == '\0'; + + return *d1 == '\0' && (*d2 == '\0' || *d2 == '/'); } -/* Iterate through STRLIST, and return the first element that matches - S, through wildcards or front comparison (as appropriate). */ -static char * -proclist (char **strlist, const char *s) +/* Iterate through DIRLIST (which must be NULL-terminated), and return the + first element that matches DIR, through wildcards or front comparison (as + appropriate). */ +static bool +dir_matches_p (char **dirlist, const char *dir) { char **x; int (*matcher) (const char *, const char *, int) = opt.ignore_case ? fnmatch_nocase : fnmatch; - for (x = strlist; *x; x++) + for (x = dirlist; *x; x++) { /* Remove leading '/' */ char *p = *x + (**x == '/'); if (has_wildcards_p (p)) { - if (matcher (p, s, FNM_PATHNAME) == 0) + if (matcher (p, dir, FNM_PATHNAME) == 0) break; } else { - if (frontcmp (p, s)) + if (subdir_p (p, dir)) break; } } - return *x; + + return *x ? true : false; } /* Returns whether DIRECTORY is acceptable for download, wrt the @@ -733,12 +740,12 @@ accdir (const char *directory) ++directory; if (opt.includes) { - if (!proclist (opt.includes, directory)) + if (!dir_matches_p (opt.includes, directory)) return false; } if (opt.excludes) { - if (proclist (opt.excludes, directory)) + if (dir_matches_p (opt.excludes, directory)) return false; } return true; @@ -2118,3 +2125,60 @@ print_decimal (double number) return buf; } + +#ifdef TESTING + +const char * +test_subdir_p() +{ + int i; + struct { + char *d1; + char *d2; + bool result; + } test_array[] = { + { "/somedir", "/somedir", true }, + { "/somedir", "/somedir/d2", true }, + { "/somedir/d1", "/somedir", false }, + }; + + for (i = 0; i < countof(test_array); ++i) + { + bool res = subdir_p (test_array[i].d1, test_array[i].d2); + + mu_assert ("test_subdir_p: wrong result", + res == test_array[i].result); + } + + return NULL; +} + +const char * +test_dir_matches_p() +{ + int i; + struct { + char *dirlist[3]; + char *dir; + bool result; + } test_array[] = { + { { "/somedir", "/someotherdir", NULL }, "somedir", true }, + { { "/somedir", "/someotherdir", NULL }, "anotherdir", false }, + { { "/somedir", "/*otherdir", NULL }, "anotherdir", true }, + { { "/somedir/d1", "/someotherdir", NULL }, "somedir/d1", true }, + { { "/somedir/d1", "/someotherdir", NULL }, "d1", false }, + }; + + for (i = 0; i < countof(test_array); ++i) + { + bool res = dir_matches_p (test_array[i].dirlist, test_array[i].dir); + + mu_assert ("test_dir_matches_p: wrong result", + res == test_array[i].result); + } + + return NULL; +} + +#endif /* TESTING */ + diff --git a/src/utils.h b/src/utils.h index db0edb0f..fc605729 100644 --- a/src/utils.h +++ b/src/utils.h @@ -51,7 +51,7 @@ char *xstrdup_lower (const char *); char *strdupdelim (const char *, const char *); char **sepstring (const char *); -bool frontcmp (const char *, const char *); +bool subdir_p (const char *, const char *); void fork_to_background (void); char *aprintf (const char *, ...) GCC_FORMAT_ATTR (1, 2);