+ return(privoxy_tolower(*s1) - privoxy_tolower(*s2));
+
+}
+
+
+/*********************************************************************
+ *
+ * Function : chomp
+ *
+ * Description : In-situ-eliminate all leading and trailing whitespace
+ * from a string.
+ *
+ * Parameters :
+ * 1 : s : string to be chomped.
+ *
+ * Returns : chomped string
+ *
+ *********************************************************************/
+char *chomp(char *string)
+{
+ char *p, *q, *r;
+
+ /*
+ * strip trailing whitespace
+ */
+ p = string + strlen(string);
+ while (p > string && privoxy_isspace(*(p-1)))
+ {
+ p--;
+ }
+ *p = '\0';
+
+ /*
+ * find end of leading whitespace
+ */
+ q = r = string;
+ while (*q && privoxy_isspace(*q))
+ {
+ q++;
+ }
+
+ /*
+ * if there was any, move the rest forwards
+ */
+ if (q != string)
+ {
+ while (q <= p)
+ {
+ *r++ = *q++;
+ }
+ }
+
+ return(string);
+
+}
+
+
+/*********************************************************************
+ *
+ * Function : string_append
+ *
+ * Description : Reallocate target_string and append text to it.
+ * This makes it easier to append to malloc'd strings.
+ * This is similar to the (removed) strsav(), but
+ * running out of memory isn't catastrophic.
+ *
+ * Programming style:
+ *
+ * The following style provides sufficient error
+ * checking for this routine, with minimal clutter
+ * in the source code. It is recommended if you
+ * have many calls to this function:
+ *
+ * char * s = strdup(...); // don't check for error
+ * string_append(&s, ...); // don't check for error
+ * string_append(&s, ...); // don't check for error
+ * string_append(&s, ...); // don't check for error
+ * if (NULL == s) { ... handle error ... }
+ *
+ * OR, equivalently:
+ *
+ * char * s = strdup(...); // don't check for error
+ * string_append(&s, ...); // don't check for error
+ * string_append(&s, ...); // don't check for error
+ * if (string_append(&s, ...)) {... handle error ...}
+ *
+ * Parameters :
+ * 1 : target_string = Pointer to old text that is to be
+ * extended. *target_string will be free()d by this
+ * routine. target_string must be non-NULL.
+ * If *target_string is NULL, this routine will
+ * do nothing and return with an error - this allows
+ * you to make many calls to this routine and only
+ * check for errors after the last one.
+ * 2 : text_to_append = Text to be appended to old.
+ * Must not be NULL.
+ *
+ * Returns : JB_ERR_OK on success, and sets *target_string
+ * to newly malloc'ed appended string. Caller
+ * must free(*target_string).
+ * JB_ERR_MEMORY on out-of-memory. (And free()s
+ * *target_string and sets it to NULL).
+ * JB_ERR_MEMORY if *target_string is NULL.
+ *
+ *********************************************************************/
+jb_err string_append(char **target_string, const char *text_to_append)
+{
+ size_t old_len;
+ char *new_string;
+ size_t new_size;
+
+ assert(target_string);
+ assert(text_to_append);
+
+ if (*target_string == NULL)
+ {
+ return JB_ERR_MEMORY;
+ }
+
+ if (*text_to_append == '\0')
+ {
+ return JB_ERR_OK;
+ }
+
+ old_len = strlen(*target_string);
+
+ new_size = strlen(text_to_append) + old_len + 1;
+
+ if (NULL == (new_string = realloc(*target_string, new_size)))
+ {
+ free(*target_string);
+
+ *target_string = NULL;
+ return JB_ERR_MEMORY;
+ }
+
+ strlcpy(new_string + old_len, text_to_append, new_size - old_len);
+
+ *target_string = new_string;
+ return JB_ERR_OK;
+}
+
+
+/*********************************************************************
+ *
+ * Function : string_join
+ *
+ * Description : Join two strings together. Frees BOTH the original
+ * strings. If either or both input strings are NULL,
+ * fails as if it had run out of memory.
+ *
+ * For comparison, string_append requires that the
+ * second string is non-NULL, and doesn't free it.
+ *
+ * Rationale: Too often, we want to do
+ * string_append(s, html_encode(s2)). That assert()s
+ * if s2 is NULL or if html_encode() runs out of memory.
+ * It also leaks memory. Proper checking is cumbersome.
+ * The solution: string_join(s, html_encode(s2)) is safe,
+ * and will free the memory allocated by html_encode().
+ *
+ * Parameters :
+ * 1 : target_string = Pointer to old text that is to be
+ * extended. *target_string will be free()d by this
+ * routine. target_string must be non-NULL.
+ * 2 : text_to_append = Text to be appended to old.
+ *
+ * Returns : JB_ERR_OK on success, and sets *target_string
+ * to newly malloc'ed appended string. Caller
+ * must free(*target_string).
+ * JB_ERR_MEMORY on out-of-memory, or if
+ * *target_string or text_to_append is NULL. (In
+ * this case, frees *target_string and text_to_append,
+ * sets *target_string to NULL).
+ *
+ *********************************************************************/
+jb_err string_join(char **target_string, char *text_to_append)
+{
+ jb_err err;
+
+ assert(target_string);
+
+ if (text_to_append == NULL)
+ {
+ freez(*target_string);
+ return JB_ERR_MEMORY;
+ }
+
+ err = string_append(target_string, text_to_append);
+
+ freez(text_to_append);
+
+ return err;
+}
+
+
+/*********************************************************************
+ *
+ * Function : string_toupper
+ *
+ * Description : Produce a copy of string with all convertible
+ * characters converted to uppercase.
+ *
+ * Parameters :
+ * 1 : string = string to convert
+ *
+ * Returns : Uppercase copy of string if possible,
+ * NULL on out-of-memory or if string was NULL.
+ *
+ *********************************************************************/
+char *string_toupper(const char *string)
+{
+ char *result, *p;
+ const char *q;
+
+ if (!string || ((result = (char *) zalloc(strlen(string) + 1)) == NULL))
+ {
+ return NULL;
+ }
+
+ q = string;
+ p = result;
+
+ while (*q != '\0')
+ {
+ *p++ = (char)toupper((int) *q++);
+ }
+
+ return result;
+
+}
+
+
+/*********************************************************************
+ *
+ * Function : string_move
+ *
+ * Description : memmove wrapper to move the last part of a string
+ * towards the beginning, overwriting the part in
+ * the middle. strlcpy() can't be used here as the
+ * strings overlap.
+ *
+ * Parameters :
+ * 1 : dst = Destination to overwrite
+ * 2 : src = Source to move.
+ *
+ * Returns : N/A
+ *
+ *********************************************************************/
+void string_move(char *dst, char *src)
+{
+ assert(dst < src);
+
+ /* +1 to copy the terminating nul as well. */
+ memmove(dst, src, strlen(src)+1);
+}
+
+
+/*********************************************************************
+ *
+ * Function : bindup
+ *
+ * Description : Duplicate the first n characters of a string that may
+ * contain '\0' characters.
+ *
+ * Parameters :
+ * 1 : string = string to be duplicated
+ * 2 : len = number of bytes to duplicate
+ *
+ * Returns : pointer to copy, or NULL if failiure
+ *
+ *********************************************************************/
+char *bindup(const char *string, size_t len)
+{
+ char *duplicate;
+
+ duplicate = (char *)malloc(len);
+ if (NULL != duplicate)
+ {
+ memcpy(duplicate, string, len);
+ }
+
+ return duplicate;
+
+}
+
+
+/*********************************************************************
+ *
+ * Function : make_path
+ *
+ * Description : Takes a directory name and a file name, returns
+ * the complete path. Handles windows/unix differences.
+ * If the file name is already an absolute path, or if
+ * the directory name is NULL or empty, it returns
+ * the filename.
+ *
+ * Parameters :
+ * 1 : dir: Name of directory or NULL for none.
+ * 2 : file: Name of file. Should not be NULL or empty.
+ *
+ * Returns : "dir/file" (Or on windows, "dir\file").
+ * It allocates the string on the heap. Caller frees.
+ * Returns NULL in error (i.e. NULL file or out of
+ * memory)
+ *
+ *********************************************************************/
+char * make_path(const char * dir, const char * file)
+{
+#ifdef AMIGA
+ char path[512];
+
+ if (dir)
+ {
+ if (dir[0] == '.')
+ {
+ if (dir[1] == '/')
+ {
+ strncpy(path,dir+2,512);
+ }
+ else
+ {
+ strncpy(path,dir+1,512);
+ }
+ }
+ else
+ {
+ strncpy(path,dir,512);
+ }
+ path[511]=0;
+ }
+ else
+ {
+ path[0]=0;
+ }
+ if (AddPart(path,file,512))
+ {
+ return strdup(path);
+ }
+ else
+ {
+ return NULL;
+ }
+#else /* ndef AMIGA */
+
+ if ((file == NULL) || (*file == '\0'))
+ {
+ return NULL; /* Error */
+ }
+
+ if ((dir == NULL) || (*dir == '\0') /* No directory specified */
+#if defined(_WIN32) || defined(__OS2__)
+ || (*file == '\\') || (file[1] == ':') /* Absolute path (DOS) */
+#else /* ifndef _WIN32 || __OS2__ */
+ || (*file == '/') /* Absolute path (U*ix) */
+#endif /* ifndef _WIN32 || __OS2__ */
+ )
+ {
+ return strdup(file);
+ }
+ else
+ {
+ char * path;
+ size_t path_size = strlen(dir) + strlen(file) + 2; /* +2 for trailing (back)slash and \0 */
+
+#if defined(unix)
+ if (*dir != '/' && basedir && *basedir)
+ {
+ /*
+ * Relative path, so start with the base directory.
+ */
+ path_size += strlen(basedir) + 1; /* +1 for the slash */
+ path = malloc(path_size);
+ if (!path) log_error(LOG_LEVEL_FATAL, "malloc failed!");
+ strlcpy(path, basedir, path_size);
+ strlcat(path, "/", path_size);
+ strlcat(path, dir, path_size);
+ }
+ else
+#endif /* defined unix */
+ {
+ path = malloc(path_size);
+ if (!path) log_error(LOG_LEVEL_FATAL, "malloc failed!");
+ strlcpy(path, dir, path_size);
+ }
+
+ assert(NULL != path);
+#if defined(_WIN32) || defined(__OS2__)
+ if (path[strlen(path)-1] != '\\')
+ {
+ strlcat(path, "\\", path_size);
+ }
+#else /* ifndef _WIN32 || __OS2__ */
+ if (path[strlen(path)-1] != '/')
+ {
+ strlcat(path, "/", path_size);
+ }
+#endif /* ifndef _WIN32 || __OS2__ */
+ strlcat(path, file, path_size);
+
+ return path;
+ }
+#endif /* ndef AMIGA */
+}
+
+
+/*********************************************************************
+ *
+ * Function : pick_from_range
+ *
+ * Description : Pick a positive number out of a given range.
+ * Should only be used if randomness would be nice,
+ * but isn't really necessary.
+ *
+ * Parameters :
+ * 1 : range: Highest possible number to pick.
+ *
+ * Returns : Picked number.
+ *
+ *********************************************************************/
+long int pick_from_range(long int range)
+{
+ long int number;
+#ifdef _WIN32
+ static unsigned long seed = 0;
+#endif /* def _WIN32 */
+
+ assert(range != 0);
+ assert(range > 0);
+
+ if (range <= 0) return 0;
+
+#ifdef HAVE_RANDOM
+ number = random() % range + 1;
+#elif defined(MUTEX_LOCKS_AVAILABLE)
+ privoxy_mutex_lock(&rand_mutex);
+#ifdef _WIN32
+ if (!seed)
+ {
+ seed = (unsigned long)(GetCurrentThreadId()+GetTickCount());
+ }
+ srand(seed);
+ seed = (unsigned long)((rand() << 16) + rand());
+#endif /* def _WIN32 */
+ number = (unsigned long)((rand() << 16) + (rand())) % (unsigned long)(range + 1);
+ privoxy_mutex_unlock(&rand_mutex);
+#else
+ /*
+ * XXX: Which platforms reach this and are there
+ * better options than just using rand() and hoping
+ * that it's safe?
+ */
+ log_error(LOG_LEVEL_INFO, "No thread-safe PRNG available? Header time randomization "
+ "might cause crashes, predictable results or even combine these fine options.");
+ number = rand() % (long int)(range + 1);
+
+#endif /* (def HAVE_RANDOM) */
+
+ return number;
+}
+
+
+#ifdef USE_PRIVOXY_STRLCPY
+/*********************************************************************
+ *
+ * Function : privoxy_strlcpy
+ *
+ * Description : strlcpy(3) look-alike for those without decent libc.
+ *
+ * Parameters :
+ * 1 : destination: buffer to copy into.
+ * 2 : source: String to copy.
+ * 3 : size: Size of destination buffer.
+ *
+ * Returns : The length of the string that privoxy_strlcpy() tried to create.
+ *
+ *********************************************************************/
+size_t privoxy_strlcpy(char *destination, const char *source, const size_t size)
+{
+ if (0 < size)
+ {
+ snprintf(destination, size, "%s", source);
+ /*
+ * Platforms that lack strlcpy() also tend to have
+ * a broken snprintf implementation that doesn't
+ * guarantee nul termination.
+ *
+ * XXX: the configure script should detect and reject those.
+ */
+ destination[size-1] = '\0';
+ }
+ return strlen(source);
+}
+#endif /* def USE_PRIVOXY_STRLCPY */
+
+
+#ifndef HAVE_STRLCAT
+/*********************************************************************
+ *
+ * Function : privoxy_strlcat
+ *
+ * Description : strlcat(3) look-alike for those without decent libc.
+ *
+ * Parameters :
+ * 1 : destination: C string.
+ * 2 : source: String to copy.
+ * 3 : size: Size of destination buffer.
+ *
+ * Returns : The length of the string that privoxy_strlcat() tried to create.
+ *
+ *********************************************************************/
+size_t privoxy_strlcat(char *destination, const char *source, const size_t size)
+{
+ const size_t old_length = strlen(destination);
+ return old_length + strlcpy(destination + old_length, source, size - old_length);
+}
+#endif /* ndef HAVE_STRLCAT */
+
+
+#if !defined(HAVE_TIMEGM) && defined(HAVE_TZSET) && defined(HAVE_PUTENV)
+/*********************************************************************
+ *
+ * Function : timegm
+ *
+ * Description : libc replacement function for the inverse of gmtime().
+ * Copyright (C) 2004 Free Software Foundation, Inc.
+ *
+ * Code originally copied from GnuPG, modifications done
+ * for Privoxy: style changed, #ifdefs for _WIN32 added
+ * to have it work on mingw32.
+ *
+ * XXX: It's very unlikely to happen, but if the malloc()
+ * call fails the time zone will be permanently set to UTC.
+ *
+ * Parameters :
+ * 1 : tm: Broken-down time struct.
+ *
+ * Returns : tm converted into time_t seconds.
+ *
+ *********************************************************************/
+time_t timegm(struct tm *tm)
+{
+ time_t answer;
+ char *zone;
+
+ zone = getenv("TZ");
+ putenv("TZ=UTC");
+ tzset();
+ answer = mktime(tm);
+ if (zone)
+ {
+ char *old_zone;
+
+ old_zone = malloc(3 + strlen(zone) + 1);
+ if (old_zone)
+ {
+ strcpy(old_zone, "TZ=");
+ strcat(old_zone, zone);
+ putenv(old_zone);
+#ifdef _WIN32
+ free(old_zone);
+#endif /* def _WIN32 */
+ }
+ }
+ else
+ {
+#ifdef HAVE_UNSETENV
+ unsetenv("TZ");
+#elif defined(_WIN32)
+ putenv("TZ=");
+#else
+ putenv("TZ");
+#endif
+ }
+ tzset();
+
+ return answer;
+}
+#endif /* !defined(HAVE_TIMEGM) && defined(HAVE_TZSET) && defined(HAVE_PUTENV) */
+
+
+#ifndef HAVE_SNPRINTF
+/*
+ * What follows is a portable snprintf routine, written by Mark Martinec.
+ * See: http://www.ijs.si/software/snprintf/
+
+ snprintf.c
+ - a portable implementation of snprintf,
+ including vsnprintf.c, asnprintf, vasnprintf, asprintf, vasprintf
+
+ snprintf is a routine to convert numeric and string arguments to
+ formatted strings. It is similar to sprintf(3) provided in a system's
+ C library, yet it requires an additional argument - the buffer size -
+ and it guarantees never to store anything beyond the given buffer,
+ regardless of the format or arguments to be formatted. Some newer
+ operating systems do provide snprintf in their C library, but many do
+ not or do provide an inadequate (slow or idiosyncratic) version, which
+ calls for a portable implementation of this routine.
+
+Author
+
+ Mark Martinec <mark.martinec@ijs.si>, April 1999, June 2000
+ Copyright © 1999, Mark Martinec
+
+ */
+
+#define PORTABLE_SNPRINTF_VERSION_MAJOR 2
+#define PORTABLE_SNPRINTF_VERSION_MINOR 2
+
+#if defined(NEED_ASPRINTF) || defined(NEED_ASNPRINTF) || defined(NEED_VASPRINTF) || defined(NEED_VASNPRINTF)
+# if defined(NEED_SNPRINTF_ONLY)
+# undef NEED_SNPRINTF_ONLY
+# endif
+# if !defined(PREFER_PORTABLE_SNPRINTF)
+# define PREFER_PORTABLE_SNPRINTF
+# endif
+#endif
+
+#if defined(SOLARIS_BUG_COMPATIBLE) && !defined(SOLARIS_COMPATIBLE)
+#define SOLARIS_COMPATIBLE
+#endif
+
+#if defined(HPUX_BUG_COMPATIBLE) && !defined(HPUX_COMPATIBLE)
+#define HPUX_COMPATIBLE
+#endif
+
+#if defined(DIGITAL_UNIX_BUG_COMPATIBLE) && !defined(DIGITAL_UNIX_COMPATIBLE)
+#define DIGITAL_UNIX_COMPATIBLE
+#endif
+
+#if defined(PERL_BUG_COMPATIBLE) && !defined(PERL_COMPATIBLE)
+#define PERL_COMPATIBLE
+#endif
+
+#if defined(LINUX_BUG_COMPATIBLE) && !defined(LINUX_COMPATIBLE)
+#define LINUX_COMPATIBLE
+#endif
+
+#include <sys/types.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include <assert.h>
+#include <errno.h>
+
+#ifdef isdigit
+#undef isdigit
+#endif
+#define isdigit(c) ((c) >= '0' && (c) <= '9')
+
+/* For copying strings longer or equal to 'breakeven_point'
+ * it is more efficient to call memcpy() than to do it inline.
+ * The value depends mostly on the processor architecture,
+ * but also on the compiler and its optimization capabilities.
+ * The value is not critical, some small value greater than zero
+ * will be just fine if you don't care to squeeze every drop
+ * of performance out of the code.
+ *
+ * Small values favor memcpy, large values favor inline code.
+ */
+#if defined(__alpha__) || defined(__alpha)
+# define breakeven_point 2 /* AXP (DEC Alpha) - gcc or cc or egcs */
+#endif
+#if defined(__i386__) || defined(__i386)
+# define breakeven_point 12 /* Intel Pentium/Linux - gcc 2.96 */
+#endif
+#if defined(__hppa)
+# define breakeven_point 10 /* HP-PA - gcc */
+#endif
+#if defined(__sparc__) || defined(__sparc)
+# define breakeven_point 33 /* Sun Sparc 5 - gcc 2.8.1 */
+#endif
+
+/* some other values of possible interest: */
+/* #define breakeven_point 8 */ /* VAX 4000 - vaxc */
+/* #define breakeven_point 19 */ /* VAX 4000 - gcc 2.7.0 */
+
+#ifndef breakeven_point
+# define breakeven_point 6 /* some reasonable one-size-fits-all value */
+#endif
+
+#define fast_memcpy(d,s,n) \
+ { register size_t nn = (size_t)(n); \
+ if (nn >= breakeven_point) memcpy((d), (s), nn); \
+ else if (nn > 0) { /* proc call overhead is worth only for large strings*/\
+ register char *dd; register const char *ss; \
+ for (ss=(s), dd=(d); nn>0; nn--) *dd++ = *ss++; } }
+
+#define fast_memset(d,c,n) \
+ { register size_t nn = (size_t)(n); \
+ if (nn >= breakeven_point) memset((d), (int)(c), nn); \
+ else if (nn > 0) { /* proc call overhead is worth only for large strings*/\
+ register char *dd; register const int cc=(int)(c); \
+ for (dd=(d); nn>0; nn--) *dd++ = cc; } }
+
+/* prototypes */
+
+#if defined(NEED_ASPRINTF)
+int asprintf (char **ptr, const char *fmt, /*args*/ ...);
+#endif
+#if defined(NEED_VASPRINTF)
+int vasprintf (char **ptr, const char *fmt, va_list ap);
+#endif
+#if defined(NEED_ASNPRINTF)
+int asnprintf (char **ptr, size_t str_m, const char *fmt, /*args*/ ...);
+#endif
+#if defined(NEED_VASNPRINTF)
+int vasnprintf (char **ptr, size_t str_m, const char *fmt, va_list ap);
+#endif
+
+#if defined(HAVE_SNPRINTF)
+/* declare our portable snprintf routine under name portable_snprintf */
+/* declare our portable vsnprintf routine under name portable_vsnprintf */
+#else
+/* declare our portable routines under names snprintf and vsnprintf */
+#define portable_snprintf snprintf
+#if !defined(NEED_SNPRINTF_ONLY)
+#define portable_vsnprintf vsnprintf
+#endif
+#endif