mirror of
https://github.com/mirror/wget.git
synced 2024-12-28 05:40:08 +08:00
[svn] New option --ignore-case for case-insensitive matching.
This commit is contained in:
parent
854db53e84
commit
097695b723
4
NEWS
4
NEWS
@ -7,6 +7,10 @@ Please send GNU Wget bug reports to <bug-wget@gnu.org>.
|
||||
|
||||
* 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.)
|
||||
|
@ -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.
|
||||
|
@ -47,6 +47,11 @@
|
||||
#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 */
|
||||
|
||||
|
||||
|
@ -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,
|
||||
|
@ -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 },
|
||||
|
@ -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"),
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
68
src/utils.c
68
src/utils.c
@ -615,6 +615,28 @@ file_merge (const char *base, const char *file)
|
||||
return result;
|
||||
}
|
||||
|
||||
/* 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;
|
||||
}
|
||||
}
|
||||
|
@ -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 *);
|
||||
|
Loading…
Reference in New Issue
Block a user