/**************** MySQL UDF gcc -Wall -I/usr/local/include -shared -o base64.so -c base64.c SELECT base64encode('data,binary,text,...'); SELECT base64decode('b64strings'); this code based on PHP's base64.c term is below. Murakami Takeshi takeshi@softagency.co.jp --- changelog 2001-06-18 * base64decode can handle LF,CR,'\' -- takeshi@softagency.co.jp 2001-06-15 * init. -- takeshi@softagency.co.jp ****************/ /* +----------------------------------------------------------------------+ | PHP version 4.0 | +----------------------------------------------------------------------+ | Copyright (c) 1997-2001 The PHP Group | +----------------------------------------------------------------------+ | This source file is subject to version 2.02 of the PHP license, | | that is bundled with this package in the file LICENSE, and is | | available at through the world-wide-web at | | http://www.php.net/license/2_02.txt. | | If you did not receive a copy of the PHP license and are unable to | | obtain it through the world-wide-web, please send a note to | | license@php.net so we can mail you a copy immediately. | +----------------------------------------------------------------------+ | Author: Jim Winstead (jimw@php.net) | +----------------------------------------------------------------------+ */ #include #include #include #include static char base64_table[] = { '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', '+', '/', '\0' }; static char base64_pad = '='; typedef unsigned char uchar; #define is_base64char(c) ( ( (uchar)0x30 <= (uchar)(c) && (uchar)(c) <= (uchar)0x39 ) || \ ( (uchar)0x41 <= (uchar)(c) && (uchar)(c) <= (uchar)0x5a ) || \ ( (uchar)0x61 <= (uchar)(c) && (uchar)(c) <= (uchar)0x7a ) || \ ( (uchar)0x2b == (uchar)(c) ) || \ ( (uchar)0x2f == (uchar)(c) ) ) /*****************************/ my_bool base64encode_init(UDF_INIT* initid, UDF_ARGS* args, char* message) { if (args->arg_count != 1) { strcpy(message,"Wrong arguments to base64encode; must be (str)"); return 1; } if ( args->arg_type[0] != STRING_RESULT ) { args->arg_type[0] = STRING_RESULT; } return 0; } void base64encode_deinit(UDF_INIT* initid) { if (initid->ptr) free(initid->ptr); } char *base64encode(UDF_INIT *initid, UDF_ARGS *args, char *result, unsigned long *ret_length, char *is_null, char *error) { const unsigned char *current; unsigned long i = 0; unsigned long len; /* *is_null=0; */ current = args->args[0]; len = args->lengths[0]; if (len <= 0 || args->arg_type[0] != STRING_RESULT ) { *is_null=0; *ret_length = 0; return 0; } if (!args || !args->args[0]) { *is_null=1; *ret_length = 0; return 0; } if ( len < 1) { len=1; } if (!( result = (char*) malloc( sizeof(char) * ((len + 3 - len % 3) * 4 / 3 + 1) ) ) ) { /* strmov(message,"Couldn't allocate memory in base64encode_init"); */ *is_null=1; *error=1; *ret_length = 0; return 0; } if (initid->ptr) free(initid->ptr); initid->ptr = result; i=0; while (len > 2) { /* keep going until we have less than 24 bits */ result[i++] = base64_table[current[0] >> 2]; result[i++] = base64_table[((current[0] & 0x03) << 4) + (current[1] >> 4)]; result[i++] = base64_table[((current[1] & 0x0f) << 2) + (current[2] >> 6)]; result[i++] = base64_table[current[2] & 0x3f]; current += 3; len -= 3; /* we just handle 3 octets of data */ } /* now deal with the tail end of things */ if (len != 0) { result[i++] = base64_table[current[0] >> 2]; if (len > 1) { result[i++] = base64_table[((current[0] & 0x03) << 4) + (current[1] >> 4)]; result[i++] = base64_table[(current[1] & 0x0f) << 2]; result[i++] = base64_pad; } else { result[i++] = base64_table[(current[0] & 0x03) << 4]; result[i++] = base64_pad; result[i++] = base64_pad; } } *ret_length = i; result[i] = '\0'; return result; } /*****************************/ my_bool base64decode_init(UDF_INIT* initid, UDF_ARGS* args, char* message) { if (args->arg_count != 1) { strcpy(message,"Wrong arguments to base64decode; must be (str)"); return 1; } if ( args->arg_type[0] != STRING_RESULT ) { args->arg_type[0] = STRING_RESULT; } return 0; } void base64decode_deinit(UDF_INIT* initid) { if (initid->ptr) free(initid->ptr); } char *base64decode(UDF_INIT *initid, UDF_ARGS *args, char *result, unsigned long *ret_length, char *is_null, char *error) { const unsigned char *current; unsigned long i, j, k, ch; unsigned long len; static short reverse_table[256]; static int table_built; if (++table_built == 1) { char *chp; for(ch = 0; ch < 256; ch++) { chp = strchr(base64_table, ch); if(chp) { reverse_table[ch] = chp - base64_table; } else { reverse_table[ch] = -1; } } } current = args->args[0]; len = args->lengths[0]; if (len <= 0 || args->arg_type[0] != STRING_RESULT ) { *is_null=0; *ret_length = 0; return 0; } if (!args || !args->args[0]) { *is_null=1; *ret_length = 0; return 0; } if ( len < 1) { len=1; } if (!( result = (char*) malloc( sizeof(char) * (len + 1) ) ) ) { *is_null=1; *error=1; *ret_length = 0; return 0; } if (initid->ptr) free(initid->ptr); initid->ptr = result; i=0; j=0; while ((ch = *current) != '\0') { current++; if (ch == base64_pad) break; if ( ! is_base64char(ch) ) { continue; } if ( ch == 0x5c ) { if ( *current != '\0' ) { current++; continue; } else { break; } } if (ch == ' ') ch = '+'; ch = reverse_table[ch]; if (ch < 0) continue; switch(i % 4) { case 0: result[j] = ch << 2; break; case 1: result[j++] |= ch >> 4; result[j] = (ch & 0x0f) << 4; break; case 2: result[j++] |= ch >>2; result[j] = (ch & 0x03) << 6; break; case 3: result[j++] |= ch; break; } i++; } k = j; /* mop things up if we ended on a boundary */ if (ch == base64_pad) { switch(i % 4) { case 0: case 1: *is_null=1; *error=1; *ret_length = 0; return 0; case 2: k++; case 3: result[k++] = 0; } } *ret_length = j; result[k] = '\0'; return result; }