]> sjero.net Git - wget/commitdiff
[svn] New option --ignore-case for case-insensitive matching.
authorhniksic <devnull@localhost>
Wed, 6 Jul 2005 19:44:00 +0000 (12:44 -0700)
committerhniksic <devnull@localhost>
Wed, 6 Jul 2005 19:44:00 +0000 (12:44 -0700)
NEWS
src/ChangeLog
src/config-post.h
src/ftp.c
src/init.c
src/main.c
src/options.h
src/recur.c
src/utils.c
src/utils.h

diff --git a/NEWS b/NEWS
index cd63c617f0af443c22c07881239be87548bca8ae..7a425eef81483c3709795da0e3ac7cb7d57ea9c6 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -7,6 +7,10 @@ Please send GNU Wget bug reports to <bug-wget@gnu.org>.
 \f
 * Changes in Wget 1.11.
 
+** The new function `--ignore-case' makes Wget ignore case when
+matching files, directories, and wildcards.  This affects the -X, -I,
+-A, and -R options, as well as globbing in FTP URLs.
+
 ** ETA projection is now displayed in "dot" progress output as well as
 in the default progress bar.  (The dot progress is used by default when
 logging Wget's output to file using the `-o' option.)
index 8efc71f39fac95a86da3a8f9b2a18934e272d62f..0c1cd1dd2dac951694ea98477e537858c3768736 100644 (file)
@@ -1,3 +1,13 @@
+2005-07-06  Hrvoje Niksic  <hniksic@xemacs.org>
+
+       * utils.c (fnmatch_nocase): New function.
+       (proclist): Use it instead of fnmatch when opt.ignore_case is
+       requested.
+       (in_acclist): Respect opt.ignore_case.
+       (frontcmp): Respect opt.ignore_case.
+
+       * options.h (struct options): New flag opt.ignore_case.
+
 2005-07-06  Hrvoje Niksic  <hniksic@xemacs.org>
 
        * ptimer.c: Measure time in seconds rather than milliseconds.
index c22df03846410035d4509f29ac6062c8be699a1b..f3cbec3ca4a44ad362de39f4d2e30a228e366d81 100644 (file)
 #define _SVID_SOURCE
 #define _BSD_SOURCE
 
+/* Under glibc-based systems we want all GNU extensions as well.  This
+   declares some unnecessary cruft, but also useful functions such as
+   timegm, FNM_CASEFOLD extension to fnmatch, memrchr, etc.  */
+#define _GNU_SOURCE
+
 #endif /* NAMESPACE_TWEAKS */
 
 
index 60d9b4a1b9cedfdeb665a1682fe973c3bfd33afa..dd27349b19709f85ed7dc5504844e1d0942d1280 100644 (file)
--- a/src/ftp.c
+++ b/src/ftp.c
@@ -1621,7 +1621,7 @@ ftp_retrieve_dirs (struct url *u, struct fileinfo *f, ccon *con)
       DEBUGP (("Composing new CWD relative to the initial directory.\n"));
       DEBUGP (("  odir = '%s'\n  f->name = '%s'\n  newdir = '%s'\n\n",
               odir, f->name, newdir));
-      if (!accdir (newdir, ALLABS))
+      if (!accdir (newdir))
        {
          logprintf (LOG_VERBOSE, _("\
 Not descending to `%s' as it is excluded/not-included.\n"),
@@ -1714,12 +1714,14 @@ ftp_retrieve_glob (struct url *u, ccon *con, int action)
      If we are dealing with a globbing pattern, that is.  */
   if (*u->file && (action == GLOB_GLOBALL || action == GLOB_GETONE))
     {
+      int (*matcher) (const char *, const char *, int)
+       = opt.ignore_case ? fnmatch_nocase : fnmatch;
       int matchres = 0;
 
       f = start;
       while (f)
        {
-         matchres = fnmatch (u->file, f->name, 0);
+         matchres = matcher (u->file, f->name, 0);
          if (matchres == -1)
            {
              logprintf (LOG_NOTQUIET, "%s: %s\n", con->target,
index dbad20c317ca8dcdc56cbec31721d576f0f817b4..faffc44c4f1db7e8f963ad114c89fcaeea373969 100644 (file)
@@ -163,6 +163,7 @@ static struct {
   { "httpproxy",       &opt.http_proxy,        cmd_string },
   { "httpsproxy",      &opt.https_proxy,       cmd_string },
   { "httpuser",                &opt.http_user,         cmd_string },
+  { "ignorecase",      &opt.ignore_case,       cmd_boolean },
   { "ignorelength",    &opt.ignore_length,     cmd_boolean },
   { "ignoretags",      &opt.ignore_tags,       cmd_vector },
   { "includedirectories", &opt.includes,       cmd_directory_vector },
index ed3349147825ac06415d7a4bc4c29785a927bfac..6107a51dc599645c74906592a35c8a5732051eb4 100644 (file)
@@ -174,6 +174,7 @@ static struct cmdline_option option_data[] =
     { "http-passwd", 0, OPT_VALUE, "httppassword", -1 }, /* deprecated */
     { "http-password", 0, OPT_VALUE, "httppassword", -1 },
     { "http-user", 0, OPT_VALUE, "httpuser", -1 },
+    { "ignore-case", 0, OPT_BOOLEAN, "ignorecase", -1 },
     { "ignore-length", 0, OPT_BOOLEAN, "ignorelength", -1 },
     { "ignore-tags", 0, OPT_VALUE, "ignoretags", -1 },
     { "include-directories", 'I', OPT_VALUE, "includedirectories", -1 },
@@ -446,6 +447,8 @@ Download:\n"),
        --no-dns-cache            disable caching DNS lookups.\n"),
     N_("\
        --restrict-file-names=OS  restrict chars in file names to ones OS allows.\n"),
+    N_("\
+       --ignore-case             ignore case when matching files/directories.\n"),
 #ifdef ENABLE_IPV6
     N_("\
   -4,  --inet4-only              connect only to IPv4 addresses.\n"),
index 8c1105efb6ccd48c974a599edccbada45bf82505..8d57d46325e54962c47bf2c76d2c14779860c98a 100644 (file)
@@ -66,6 +66,8 @@ struct options
   char **excludes;             /* List of excluded FTP directories. */
   char **includes;             /* List of FTP directories to
                                   follow. */
+  bool ignore_case;            /* Whether to ignore case when
+                                  matching dirs and files */
 
   char **domains;              /* See host.c */
   char **exclude_domains;
index 6c182f07012b1b5bab679b57d6b9e38e9944974a..71008fb9501a931e3211e7c290414d463e4b4469 100644 (file)
@@ -495,7 +495,7 @@ download_child_p (const struct urlpos *upos, struct url *parent, int depth,
      exclusion and inclusion lists.  */
   if (opt.includes || opt.excludes)
     {
-      if (!accdir (u->dir, ALLABS))
+      if (!accdir (u->dir))
        {
          DEBUGP (("%s (%s) is excluded/not-included.\n", url, u->dir));
          goto out;
index 6e9e0a694fe43d160723bec138cd589bc7b5b5af..991aaf4befa4fd6735646d627016df736eb06384 100644 (file)
@@ -615,6 +615,28 @@ file_merge (const char *base, const char *file)
   return result;
 }
 \f
+/* Like fnmatch, but performs a lower-case comparison.  */
+
+int
+fnmatch_nocase (const char *pattern, const char *string, int flags)
+{
+#ifdef FNM_CASEFOLD
+  return fnmatch (pattern, string, flags | FNM_CASEFOLD);
+#else
+  /* Turn PATTERN and STRING to lower case and call fnmatch on them. */
+  char *patcopy = (char *) alloca (strlen (pattern) + 1);
+  char *strcopy = (char *) alloca (strlen (string) + 1);
+  char *p;
+  for (p = patcopy; *pattern; pattern++, p++)
+    *p = TOLOWER (*pattern);
+  *p = '\0';
+  for (p = strcopy; *string; string++, p++)
+    *p = TOLOWER (*string);
+  *p = '\0';
+  return fnmatch (patcopy, strcopy, flags);
+#endif
+}
+
 static bool in_acclist (const char *const *, const char *, bool);
 
 /* Determine whether a file is acceptable to be followed, according to
@@ -642,28 +664,34 @@ acceptable (const char *s)
 }
 
 /* Compare S1 and S2 frontally; S2 must begin with S1.  E.g. if S1 is
-   `/something', frontcmp() will return 1 only if S2 begins with
-   `/something'.  Otherwise, 0 is returned.  */
+   `/something', frontcmp() will return true only if S2 begins with
+   `/something'.  */
 bool
 frontcmp (const char *s1, const char *s2)
 {
-  for (; *s1 && *s2 && (*s1 == *s2); ++s1, ++s2);
+  if (!opt.ignore_case)
+    for (; *s1 && *s2 && (*s1 == *s2); ++s1, ++s2);
+  else
+    for (; *s1 && *s2 && (TOLOWER (*s1) == TOLOWER (*s2)); ++s1, ++s2);
   return *s1 == '\0';
 }
 
 /* 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, enum accd flags)
+proclist (char **strlist, const char *s)
 {
   char **x;
+  int (*matcher) (const char *, const char *, int)
+    = opt.ignore_case ? fnmatch_nocase : fnmatch;
+
   for (x = strlist; *x; x++)
     {
-      /* Remove leading '/' if ALLABS */
-      char *p = *x + ((flags & ALLABS) && (**x == '/'));
+      /* Remove leading '/' */
+      char *p = *x + (**x == '/');
       if (has_wildcards_p (p))
        {
-         if (fnmatch (p, s, FNM_PATHNAME) == 0)
+         if (matcher (p, s, FNM_PATHNAME) == 0)
            break;
        }
       else
@@ -678,22 +706,23 @@ proclist (char **strlist, const char *s, enum accd flags)
 /* Returns whether DIRECTORY is acceptable for download, wrt the
    include/exclude lists.
 
-   If FLAGS is ALLABS, the leading `/' is ignored in paths; relative
-   and absolute paths may be freely intermixed.  */
+   The leading `/' is ignored in paths; relative and absolute paths
+   may be freely intermixed.  */
+
 bool
-accdir (const char *directory, enum accd flags)
+accdir (const char *directory)
 {
   /* Remove starting '/'.  */
-  if (flags & ALLABS && *directory == '/')
+  if (*directory == '/')
     ++directory;
   if (opt.includes)
     {
-      if (!proclist (opt.includes, directory, flags))
+      if (!proclist (opt.includes, directory))
        return false;
     }
   if (opt.excludes)
     {
-      if (proclist (opt.excludes, directory, flags))
+      if (proclist (opt.excludes, directory))
        return false;
     }
   return true;
@@ -748,21 +777,24 @@ in_acclist (const char *const *accepts, const char *s, bool backward)
     {
       if (has_wildcards_p (*accepts))
        {
-         /* fnmatch returns 0 if the pattern *does* match the
-            string.  */
-         if (fnmatch (*accepts, s, 0) == 0)
+         int res = opt.ignore_case
+           ? fnmatch_nocase (*accepts, s, 0) : fnmatch (*accepts, s, 0);
+         /* fnmatch returns 0 if the pattern *does* match the string.  */
+         if (res == 0)
            return true;
        }
       else
        {
          if (backward)
            {
-             if (match_tail (s, *accepts, 0))
+             if (match_tail (s, *accepts, opt.ignore_case))
                return true;
            }
          else
            {
-             if (!strcmp (s, *accepts))
+             int cmp = opt.ignore_case
+               ? strcasecmp (s, *accepts) : strcmp (s, *accepts);
+             if (cmp == 0)
                return true;
            }
        }
index 2cdb44841e2e5121ab4be679c1bf2474aeab6411..db0edb0f359e2dd58a47f8088d439090b617f571 100644 (file)
@@ -30,10 +30,6 @@ so, delete this exception statement from your version.  */
 #ifndef UTILS_H
 #define UTILS_H
 
-enum accd {
-   ALLABS = 1
-};
-
 struct hash_table;
 
 struct file_memory {
@@ -72,8 +68,9 @@ FILE *unique_create (const char *, bool, char **);
 FILE *fopen_excl (const char *, bool);
 char *file_merge (const char *, const char *);
 
+int fnmatch_nocase (const char *, const char *, int);
 bool acceptable (const char *);
-bool accdir (const char *s, enum accd);
+bool accdir (const char *s);
 char *suffix (const char *s);
 bool match_tail (const char *, const char *, bool);
 bool has_wildcards_p (const char *);