# include <termios.h>
#endif
-/* Needed for run_with_timeout. */
+/* Needed for Unix version of run_with_timeout. */
#include <signal.h>
-#ifdef HAVE_SETJMP_H
-# include <setjmp.h>
-#endif
+#include <setjmp.h>
#ifndef HAVE_SIGSETJMP
/* If sigsetjmp is a macro, configure won't pick it up. */
file_merge("/foo/bar/", "baz") => "/foo/bar/baz"
file_merge("foo", "bar") => "bar"
- In other words, it's a simpler and gentler version of uri_merge_1. */
+ In other words, it's a simpler and gentler version of uri_merge. */
char *
file_merge (const char *base, const char *file)
return result;
}
\f
+/* Like fnmatch, but performs a case-insensitive match. */
+
+int
+fnmatch_nocase (const char *pattern, const char *string, int flags)
+{
+#ifdef FNM_CASEFOLD
+ /* The FNM_CASEFOLD flag started as a GNU extension, but it is now
+ also present on *BSD platforms, and possibly elsewhere. */
+ 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 v1;
}
/* Count v1. */
- for (i = 0; v1[i]; i++);
+ for (i = 0; v1[i]; i++)
+ ;
/* Count v2. */
- for (j = 0; v2[j]; j++);
+ for (j = 0; v2[j]; j++)
+ ;
/* Reallocate v1. */
v1 = xrealloc (v1, (i + j + 1) * sizeof (char **));
memcpy (v1 + i, v2, (j + 1) * sizeof (char *));
return p - b64store;
}
-#define IS_ASCII(c) (((c) & 0x80) == 0)
-#define IS_BASE64(c) ((IS_ASCII (c) && base64_char_to_value[c] >= 0) || c == '=')
-
-/* Get next character from the string, ignoring whitespace. C should
- be int, and will contain the next character, \0 if end is reached,
- or -1 if a non-ws non-base64 character is read. */
-#define NEXT_BASE64_CHAR(c, p) for (;;) { \
+/* 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++; \
- if (IS_BASE64 (c) || c == '\0') \
- break; \
- else if (!ISSPACE (c)) \
- { \
- c = -1; \
- break; \
- } \
- /* c is whitespace, keep looping */ \
-}
+} while (ISSPACE (c))
+
+#define IS_ASCII(c) (((c) & 0x80) == 0)
/* Decode data from BASE64 (pointer to \0-terminated text) into memory
pointed to by TO. TO should be large enough to accomodate the
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;
while (1)
{
- int c;
+ unsigned char c;
unsigned long value;
/* Process first byte of a quadruplet. */
- NEXT_BASE64_CHAR (c, p);
+ NEXT_CHAR (c, p);
if (!c)
break;
- if (c == '=' || c == -1)
+ 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 == '=' || c == -1)
+ 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 (c == -1)
+ 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 != '=')
*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 (c == -1)
+ if (!IS_BASE64 (c))
return -1; /* illegal char while decoding base64 */
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. */