/* Various utility functions.
- Copyright (C) 2005 Free Software Foundation, Inc.
+ Copyright (C) 1996-2005 Free Software Foundation, Inc.
This file is part of GNU Wget.
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
-along with Wget; if not, write to the Free Software
-Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+along with Wget; if not, write to the Free Software Foundation, Inc.,
+51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
In addition, as a special exception, the Free Software Foundation
gives permission to link the code of its release of Wget with the
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
}
/* 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
/* 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;
{
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;
}
}
return p - b64store;
}
-#define IS_ASCII(c) (((c) & 0x80) == 0)
-#define IS_BASE64(c) ((IS_ASCII (c) && base64_char_to_value[c] >= 0) || c == '=')
+/* Store in C the next non-whitespace character from the string, or \0
+ when end of string is reached. */
+#define NEXT_CHAR(c, p) do { \
+ c = (unsigned char) *p++; \
+} while (ISSPACE (c))
-/* Get next character from the string, except that non-base64
- characters are ignored, as mandated by rfc2045. */
-#define NEXT_BASE64_CHAR(c, p) do { \
- c = *p++; \
-} while (c != '\0' && !IS_BASE64 (c))
+#define IS_ASCII(c) (((c) & 0x80) == 0)
-/* Decode data from BASE64 (assumed to be encoded as base64) into
- memory pointed to by TO. TO should be large enough to accomodate
- the decoded data, which is guaranteed to be less than
- strlen(base64).
+/* Decode data from BASE64 (pointer to \0-terminated text) into memory
+ pointed to by TO. TO should be large enough to accomodate the
+ decoded data, which is guaranteed to be less than strlen(base64).
Since TO is assumed to contain binary data, it is not
NUL-terminated. The function returns the length of the data
{
/* Table of base64 values for first 128 characters. Note that this
assumes ASCII (but so does Wget in other places). */
- static short base64_char_to_value[128] =
+ static signed char base64_char_to_value[128] =
{
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0- 9 */
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 10- 19 */
39, 40, 41, 42, 43, 44, 45, 46, 47, 48, /* 110-119 */
49, 50, 51, -1, -1, -1, -1, -1 /* 120-127 */
};
+#define BASE64_CHAR_TO_VALUE(c) ((int) base64_char_to_value[c])
+#define IS_BASE64(c) ((IS_ASCII (c) && BASE64_CHAR_TO_VALUE (c) >= 0) || c == '=')
const char *p = base64;
char *q = to;
unsigned long value;
/* Process first byte of a quadruplet. */
- NEXT_BASE64_CHAR (c, p);
+ NEXT_CHAR (c, p);
if (!c)
break;
- if (c == '=')
- return -1; /* illegal '=' while decoding base64 */
- value = base64_char_to_value[c] << 18;
+ if (c == '=' || !IS_BASE64 (c))
+ return -1; /* illegal char while decoding base64 */
+ value = BASE64_CHAR_TO_VALUE (c) << 18;
- /* Process scond byte of a quadruplet. */
- NEXT_BASE64_CHAR (c, p);
+ /* Process second byte of a quadruplet. */
+ NEXT_CHAR (c, p);
if (!c)
return -1; /* premature EOF while decoding base64 */
- if (c == '=')
- return -1; /* illegal `=' while decoding base64 */
- value |= base64_char_to_value[c] << 12;
+ if (c == '=' || !IS_BASE64 (c))
+ return -1; /* illegal char while decoding base64 */
+ value |= BASE64_CHAR_TO_VALUE (c) << 12;
*q++ = value >> 16;
/* Process third byte of a quadruplet. */
- NEXT_BASE64_CHAR (c, p);
+ NEXT_CHAR (c, p);
if (!c)
return -1; /* premature EOF while decoding base64 */
+ if (!IS_BASE64 (c))
+ return -1; /* illegal char while decoding base64 */
if (c == '=')
{
- NEXT_BASE64_CHAR (c, p);
+ NEXT_CHAR (c, p);
if (!c)
return -1; /* premature EOF while decoding base64 */
if (c != '=')
continue;
}
- value |= base64_char_to_value[c] << 6;
+ value |= BASE64_CHAR_TO_VALUE (c) << 6;
*q++ = 0xff & value >> 8;
/* Process fourth byte of a quadruplet. */
- NEXT_BASE64_CHAR (c, p);
+ NEXT_CHAR (c, p);
if (!c)
return -1; /* premature EOF while decoding base64 */
if (c == '=')
continue;
+ if (!IS_BASE64 (c))
+ return -1; /* illegal char while decoding base64 */
- value |= base64_char_to_value[c];
+ value |= BASE64_CHAR_TO_VALUE (c);
*q++ = 0xff & value;
}
+#undef IS_BASE64
+#undef BASE64_CHAR_TO_VALUE
return q - to;
}
#undef IS_ASCII
-#undef IS_BASE64
-#undef NEXT_BASE64_CHAR
+#undef NEXT_CHAR
\f
/* Simple merge sort for use by stable_sort. Implementation courtesy
Zeljko Vrba with additional debugging by Nenad Barbutov. */