/* Copyright (C) 2003 MySQL AB This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include #include /* strchr() */ #ifndef MAIN static char base64_table[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" "abcdefghijklmnopqrstuvwxyz" "0123456789+/"; int base64_needed_encoded_length(int length_of_data) { int nb_base64_chars; nb_base64_chars= (length_of_data + 2) / 3 * 4; return nb_base64_chars + /* base64 char incl padding */ (nb_base64_chars - 1)/ 76 + /* newlines */ 1; /* NUL termination of string */ } int base64_needed_decoded_length(int length_of_encoded_data) { return (int) ceil(length_of_encoded_data * 3 / 4); } /* Encode a data as base64. Note: We require that dst is pre-allocated to correct size. See base64_needed_encoded_length(). */ int base64_encode(const void *src, size_t src_len, char *dst) { const unsigned char *s= (const unsigned char*)src; size_t i= 0; size_t len= 0; for (; i < src_len; len += 4) { unsigned c; if (len == 76) { len= 0; *dst++= '\n'; } c= s[i++]; c <<= 8; if (i < src_len) c += s[i]; c <<= 8; i++; if (i < src_len) c += s[i]; i++; *dst++= base64_table[(c >> 18) & 0x3f]; *dst++= base64_table[(c >> 12) & 0x3f]; if (i > (src_len + 1)) *dst++= '='; else *dst++= base64_table[(c >> 6) & 0x3f]; if (i > src_len) *dst++= '='; else *dst++= base64_table[(c >> 0) & 0x3f]; } *dst= '\0'; return 0; } static inline uint pos(unsigned char c) { return (uint) (strchr(base64_table, c) - base64_table); } #define SKIP_SPACE(src, i, size) \ { \ while (i < size && my_isspace(&my_charset_latin1, * src)) \ { \ i++; \ src++; \ } \ if (i == size) \ { \ i= size + 1; \ break; \ } \ } /* Decode a base64 string Note: We require that dst is pre-allocated to correct size. See base64_needed_decoded_length(). RETURN Number of bytes produced in dst or -1 in case of failure */ int base64_decode(const char *src, size_t size, void *dst) { char b[3]; size_t i= 0; char *dst_base= (char *)dst; char *d= dst_base; size_t j; while (i < size) { unsigned c= 0; size_t mark= 0; SKIP_SPACE(src, i, size); c += pos(*src++); c <<= 6; i++; SKIP_SPACE(src, i, size); c += pos(*src++); c <<= 6; i++; SKIP_SPACE(src, i, size); if (* src != '=') c += pos(*src++); else { i= size; mark= 2; c <<= 6; goto end; } c <<= 6; i++; SKIP_SPACE(src, i, size); if (*src != '=') c += pos(*src++); else { i= size; mark= 1; goto end; } i++; end: b[0]= (c >> 16) & 0xff; b[1]= (c >> 8) & 0xff; b[2]= (c >> 0) & 0xff; for (j=0; j<3-mark; j++) *d++= b[j]; } if (i != size) { return -1; } return d - dst_base; } #else /* MAIN */ #define require(b) { \ if (!(b)) { \ printf("Require failed at %s:%d\n", __FILE__, __LINE__); \ abort(); \ } \ } int main(void) { int i; size_t j; size_t k, l; size_t dst_len; size_t needed_length; for (i= 0; i < 500; i++) { /* Create source data */ const size_t src_len= rand() % 1000 + 1; char * src= (char *) malloc(src_len); char * s= src; char * str; char * dst; for (j= 0; j