X-Git-Url: http://sjero.net/git/?p=wget;a=blobdiff_plain;f=src%2Futils.c;h=2e45c4d5812edb4966cd83aa9ae98e0c88d6a53c;hp=2894d8f30a69b62253b3a5a83358e3f3d6322070;hb=52ad80309f8c9a5c1498f6ff6b3e11d8997290d7;hpb=8f0378df0b2708cb8e20bcfce6d3ab55ca7c2a40 diff --git a/src/utils.c b/src/utils.c index 2894d8f3..2e45c4d5 100644 --- a/src/utils.c +++ b/src/utils.c @@ -2170,3 +2170,143 @@ xsleep (double seconds) } #endif /* not WINDOWS */ + +/* Encode the string S of length LENGTH to base64 format and place it + to STORE. STORE will be 0-terminated, and must point to a writable + buffer of at least 1+BASE64_LENGTH(length) bytes. */ + +void +base64_encode (const char *s, char *store, int length) +{ + /* 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; + unsigned char *p = (unsigned char *)store; + + /* 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'; +} + +#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. */ + 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 dcoding 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 dcoding 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