+
+/* Encode the string STR of length LENGTH to base64 format and place it
+ to B64STORE. The output will be \0-terminated, and must point to a
+ writable buffer of at least 1+BASE64_LENGTH(length) bytes. It
+ returns the length of the resulting base64 data, not counting the
+ terminating zero.
+
+ This implementation will not emit newlines after 76 characters of
+ base64 data. */
+
+int
+base64_encode (const char *str, int length, char *b64store)
+{
+ /* Conversion table. */
+ static char tbl[64] = {
+ 'A','B','C','D','E','F','G','H',
+ 'I','J','K','L','M','N','O','P',
+ 'Q','R','S','T','U','V','W','X',
+ 'Y','Z','a','b','c','d','e','f',
+ 'g','h','i','j','k','l','m','n',
+ 'o','p','q','r','s','t','u','v',
+ 'w','x','y','z','0','1','2','3',
+ '4','5','6','7','8','9','+','/'
+ };
+ int i;
+ const unsigned char *s = (const unsigned char *) str;
+ char *p = b64store;
+
+ /* Transform the 3x8 bits to 4x6 bits, as required by base64. */
+ for (i = 0; i < length; i += 3)
+ {
+ *p++ = tbl[s[0] >> 2];
+ *p++ = tbl[((s[0] & 3) << 4) + (s[1] >> 4)];
+ *p++ = tbl[((s[1] & 0xf) << 2) + (s[2] >> 6)];
+ *p++ = tbl[s[2] & 0x3f];
+ s += 3;
+ }
+
+ /* Pad the result if necessary... */
+ if (i == length + 1)
+ *(p - 1) = '=';
+ else if (i == length + 2)
+ *(p - 1) = *(p - 2) = '=';
+
+ /* ...and zero-terminate it. */
+ *p = '\0';
+
+ 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, 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))
+
+/* 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).
+
+ Since TO is assumed to contain binary data, it is not
+ NUL-terminated. The function returns the length of the data
+ written to TO. -1 is returned in case of error caused by malformed
+ base64 input. */
+
+int
+base64_decode (const char *base64, char *to)
+{
+ /* 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] =
+ {
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0- 9 */
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 10- 19 */
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 20- 29 */
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 30- 39 */
+ -1, -1, -1, 62, -1, -1, -1, 63, 52, 53, /* 40- 49 */
+ 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, /* 50- 59 */
+ -1, -1, -1, -1, -1, 0, 1, 2, 3, 4, /* 60- 69 */
+ 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, /* 70- 79 */
+ 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, /* 80- 89 */
+ 25, -1, -1, -1, -1, -1, -1, 26, 27, 28, /* 90- 99 */
+ 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, /* 100-109 */
+ 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, /* 110-119 */
+ 49, 50, 51, -1, -1, -1, -1, -1 /* 120-127 */
+ };
+
+ const char *p = base64;
+ char *q = to;
+
+ while (1)
+ {
+ unsigned char c;
+ unsigned long value;
+
+ /* Process first byte of a quadruplet. */
+ NEXT_BASE64_CHAR (c, p);
+ if (!c)
+ break;
+ if (c == '=')
+ return -1; /* illegal '=' while decoding base64 */
+ value = base64_char_to_value[c] << 18;
+
+ /* Process scond byte of a quadruplet. */
+ NEXT_BASE64_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;
+ *q++ = value >> 16;
+
+ /* Process third byte of a quadruplet. */
+ NEXT_BASE64_CHAR (c, p);
+ if (!c)
+ return -1; /* premature EOF while decoding base64 */
+
+ if (c == '=')
+ {
+ NEXT_BASE64_CHAR (c, p);
+ if (!c)
+ return -1; /* premature EOF while decoding base64 */
+ if (c != '=')
+ return -1; /* padding `=' expected but not found */
+ continue;
+ }
+
+ value |= base64_char_to_value[c] << 6;
+ *q++ = 0xff & value >> 8;
+
+ /* Process fourth byte of a quadruplet. */
+ NEXT_BASE64_CHAR (c, p);
+ if (!c)
+ return -1; /* premature EOF while decoding base64 */
+ if (c == '=')
+ continue;
+
+ value |= base64_char_to_value[c];
+ *q++ = 0xff & value;
+ }
+
+ return q - to;
+}
+
+#undef IS_ASCII
+#undef IS_BASE64
+#undef NEXT_BASE64_CHAR
+\f
+/* Simple merge sort for use by stable_sort. Implementation courtesy
+ Zeljko Vrba with additional debugging by Nenad Barbutov. */
+
+static void
+mergesort_internal (void *base, void *temp, size_t size, size_t from, size_t to,
+ int (*cmpfun) (const void *, const void *))
+{
+#define ELT(array, pos) ((char *)(array) + (pos) * size)
+ if (from < to)
+ {
+ size_t i, j, k;
+ size_t mid = (to + from) / 2;
+ mergesort_internal (base, temp, size, from, mid, cmpfun);
+ mergesort_internal (base, temp, size, mid + 1, to, cmpfun);
+ i = from;
+ j = mid + 1;
+ for (k = from; (i <= mid) && (j <= to); k++)
+ if (cmpfun (ELT (base, i), ELT (base, j)) <= 0)
+ memcpy (ELT (temp, k), ELT (base, i++), size);
+ else
+ memcpy (ELT (temp, k), ELT (base, j++), size);
+ while (i <= mid)
+ memcpy (ELT (temp, k++), ELT (base, i++), size);
+ while (j <= to)
+ memcpy (ELT (temp, k++), ELT (base, j++), size);
+ for (k = from; k <= to; k++)
+ memcpy (ELT (base, k), ELT (temp, k), size);
+ }
+#undef ELT
+}
+
+/* Stable sort with interface exactly like standard library's qsort.
+ Uses mergesort internally, allocating temporary storage with
+ alloca. */
+
+void
+stable_sort (void *base, size_t nmemb, size_t size,
+ int (*cmpfun) (const void *, const void *))
+{
+ if (size > 1)
+ {
+ void *temp = alloca (nmemb * size * sizeof (void *));
+ mergesort_internal (base, temp, size, 0, nmemb - 1, cmpfun);
+ }
+}