├── README.md └── base64.c /README.md: -------------------------------------------------------------------------------- 1 | # MySQL User Defined Function (UDF) 2 | 3 | * base64encode 4 | * base64decode 5 | 6 | ## Summary 7 | 8 | It provides base64 encode/decode function for MySQL-5.1/5.5/5.6 as UDF. 9 | It has based on base64_encode/base64_decode of PHP implementation. 10 | 11 | ## Compatibility 12 | 13 | * MySQL-5.1 14 | * MySQL-5.5 15 | * MySQL-5.6 16 | 17 | ## Usage 18 | 19 | ```sql 20 | SELECT base64encode('data,binary,text,...'); 21 | SELECT base64decode('b64strings'); 22 | INSERT INTO t1 (body) VALUES (base64encode('something')); 23 | ``` 24 | 25 | ## Installation 26 | 27 | build it. 28 | 29 | ```sh 30 | $ git clone https://github.com/y-ken/mysql-udf-base64.git 31 | $ cd mysql-udf-base64 32 | $ gcc -Wall -fPIC -I/usr/local/include -shared base64.c -o base64.so 33 | $ sudo install -m 755 base64.so `mysql_config --plugindir` 34 | ``` 35 | 36 | activate it. 37 | 38 | ```sql 39 | mysql> CREATE FUNCTION base64encode RETURNS STRING SONAME 'base64.so'; 40 | mysql> CREATE FUNCTION base64decode RETURNS STRING SONAME 'base64.so'; 41 | ``` 42 | 43 | use it. 44 | 45 | ```sql 46 | mysql> CREATE TABLE t1 (body text); 47 | mysql> INSERT INTO t1 (body) VALUES (base64encode('something')); 48 | mysql> SELECT body, base64decode(body) from t1; 49 | ``` 50 | 51 | ## Notes 52 | 53 | Below is the original README. 54 | 55 | ``` 56 | this code based on PHP's base64.c 57 | term is below. 58 | 59 | Murakami Takeshi 60 | takeshi@softagency.co.jp 61 | 62 | --- changelog 63 | 2001-06-18 64 | * base64decode can handle LF,CR,'\' 65 | -- takeshi@softagency.co.jp 66 | 67 | 2001-06-15 68 | * init. 69 | -- takeshi@softagency.co.jp 70 | ``` 71 | -------------------------------------------------------------------------------- /base64.c: -------------------------------------------------------------------------------- 1 | /**************** 2 | MySQL UDF 3 | 4 | gcc -Wall -I/usr/local/include -shared -o base64.so -c base64.c 5 | 6 | SELECT base64encode('data,binary,text,...'); 7 | SELECT base64decode('b64strings'); 8 | 9 | this code based on PHP's base64.c 10 | term is below. 11 | 12 | Murakami Takeshi 13 | takeshi@softagency.co.jp 14 | 15 | --- changelog 16 | 2001-06-18 17 | 18 | * base64decode can handle LF,CR,'\' 19 | 20 | -- takeshi@softagency.co.jp 21 | 22 | 2001-06-15 23 | 24 | * init. 25 | 26 | -- takeshi@softagency.co.jp 27 | 28 | ****************/ 29 | /* 30 | +----------------------------------------------------------------------+ 31 | | PHP version 4.0 | 32 | +----------------------------------------------------------------------+ 33 | | Copyright (c) 1997-2001 The PHP Group | 34 | +----------------------------------------------------------------------+ 35 | | This source file is subject to version 2.02 of the PHP license, | 36 | | that is bundled with this package in the file LICENSE, and is | 37 | | available at through the world-wide-web at | 38 | | http://www.php.net/license/2_02.txt. | 39 | | If you did not receive a copy of the PHP license and are unable to | 40 | | obtain it through the world-wide-web, please send a note to | 41 | | license@php.net so we can mail you a copy immediately. | 42 | +----------------------------------------------------------------------+ 43 | | Author: Jim Winstead (jimw@php.net) | 44 | +----------------------------------------------------------------------+ 45 | */ 46 | 47 | #include 48 | #include 49 | #include 50 | #include 51 | 52 | static char base64_table[] = 53 | { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 54 | 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 55 | 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 56 | 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 57 | '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/', '\0' 58 | }; 59 | static char base64_pad = '='; 60 | 61 | typedef unsigned char uchar; 62 | 63 | #define is_base64char(c) ( ( (uchar)0x30 <= (uchar)(c) && (uchar)(c) <= (uchar)0x39 ) || \ 64 | ( (uchar)0x41 <= (uchar)(c) && (uchar)(c) <= (uchar)0x5a ) || \ 65 | ( (uchar)0x61 <= (uchar)(c) && (uchar)(c) <= (uchar)0x7a ) || \ 66 | ( (uchar)0x2b == (uchar)(c) ) || \ 67 | ( (uchar)0x2f == (uchar)(c) ) ) 68 | 69 | 70 | /*****************************/ 71 | my_bool 72 | base64encode_init(UDF_INIT* initid, UDF_ARGS* args, char* message) 73 | { 74 | if (args->arg_count != 1) 75 | { 76 | strcpy(message,"Wrong arguments to base64encode; must be (str)"); 77 | return 1; 78 | } 79 | 80 | if ( args->arg_type[0] != STRING_RESULT ) { 81 | args->arg_type[0] = STRING_RESULT; 82 | } 83 | 84 | return 0; 85 | } 86 | 87 | void 88 | base64encode_deinit(UDF_INIT* initid) 89 | { 90 | if (initid->ptr) 91 | free(initid->ptr); 92 | } 93 | 94 | 95 | char 96 | *base64encode(UDF_INIT *initid, UDF_ARGS *args, char *result, 97 | unsigned long *ret_length, char *is_null, char *error) 98 | { 99 | const unsigned char *current; 100 | unsigned long i = 0; 101 | unsigned long len; 102 | 103 | /* *is_null=0; */ 104 | current = args->args[0]; 105 | len = args->lengths[0]; 106 | 107 | if (len <= 0 || args->arg_type[0] != STRING_RESULT ) 108 | { 109 | *is_null=0; 110 | *ret_length = 0; 111 | return 0; 112 | } 113 | 114 | if (!args || !args->args[0]) 115 | { 116 | *is_null=1; 117 | *ret_length = 0; 118 | return 0; 119 | } 120 | 121 | if ( len < 1) { len=1; } 122 | 123 | if (!( result = (char*) malloc( sizeof(char) * ((len + 3 - len % 3) * 4 / 3 + 1) ) ) ) 124 | { 125 | /* strmov(message,"Couldn't allocate memory in base64encode_init"); */ 126 | *is_null=1; 127 | *error=1; 128 | *ret_length = 0; 129 | return 0; 130 | } 131 | if (initid->ptr) free(initid->ptr); 132 | initid->ptr = result; 133 | 134 | i=0; 135 | while (len > 2) 136 | { /* keep going until we have less than 24 bits */ 137 | result[i++] = base64_table[current[0] >> 2]; 138 | result[i++] = base64_table[((current[0] & 0x03) << 4) + (current[1] >> 4)]; 139 | result[i++] = base64_table[((current[1] & 0x0f) << 2) + (current[2] >> 6)]; 140 | result[i++] = base64_table[current[2] & 0x3f]; 141 | 142 | current += 3; 143 | len -= 3; /* we just handle 3 octets of data */ 144 | } 145 | 146 | /* now deal with the tail end of things */ 147 | if (len != 0) 148 | { 149 | result[i++] = base64_table[current[0] >> 2]; 150 | if (len > 1) { 151 | result[i++] = base64_table[((current[0] & 0x03) << 4) + (current[1] >> 4)]; 152 | result[i++] = base64_table[(current[1] & 0x0f) << 2]; 153 | result[i++] = base64_pad; 154 | } 155 | else { 156 | result[i++] = base64_table[(current[0] & 0x03) << 4]; 157 | result[i++] = base64_pad; 158 | result[i++] = base64_pad; 159 | } 160 | } 161 | 162 | *ret_length = i; 163 | 164 | result[i] = '\0'; 165 | return result; 166 | } 167 | 168 | /*****************************/ 169 | my_bool 170 | base64decode_init(UDF_INIT* initid, UDF_ARGS* args, char* message) 171 | { 172 | if (args->arg_count != 1) 173 | { 174 | strcpy(message,"Wrong arguments to base64decode; must be (str)"); 175 | return 1; 176 | } 177 | 178 | if ( args->arg_type[0] != STRING_RESULT ) { 179 | args->arg_type[0] = STRING_RESULT; 180 | } 181 | 182 | return 0; 183 | } 184 | 185 | void 186 | base64decode_deinit(UDF_INIT* initid) 187 | { 188 | if (initid->ptr) 189 | free(initid->ptr); 190 | } 191 | 192 | char 193 | *base64decode(UDF_INIT *initid, UDF_ARGS *args, char *result, 194 | unsigned long *ret_length, char *is_null, char *error) 195 | { 196 | const unsigned char *current; 197 | unsigned long i, j, k, ch; 198 | unsigned long len; 199 | static short reverse_table[256]; 200 | static int table_built; 201 | 202 | if (++table_built == 1) { 203 | char *chp; 204 | for(ch = 0; ch < 256; ch++) { 205 | chp = strchr(base64_table, ch); 206 | if(chp) { 207 | reverse_table[ch] = chp - base64_table; 208 | } else { 209 | reverse_table[ch] = -1; 210 | } 211 | } 212 | } 213 | 214 | current = args->args[0]; 215 | len = args->lengths[0]; 216 | 217 | if (len <= 0 || args->arg_type[0] != STRING_RESULT ) 218 | { 219 | *is_null=0; 220 | *ret_length = 0; 221 | return 0; 222 | } 223 | 224 | if (!args || !args->args[0]) 225 | { 226 | *is_null=1; 227 | *ret_length = 0; 228 | return 0; 229 | } 230 | 231 | if ( len < 1) { len=1; } 232 | 233 | if (!( result = (char*) malloc( sizeof(char) * (len + 1) ) ) ) 234 | { 235 | *is_null=1; 236 | *error=1; 237 | *ret_length = 0; 238 | return 0; 239 | } 240 | if (initid->ptr) free(initid->ptr); 241 | initid->ptr = result; 242 | 243 | i=0; j=0; 244 | while ((ch = *current) != '\0') 245 | { 246 | current++; 247 | 248 | if (ch == base64_pad) break; 249 | 250 | if ( ! is_base64char(ch) ) { continue; } 251 | if ( ch == 0x5c ) 252 | { 253 | if ( *current != '\0' ) { 254 | current++; 255 | continue; 256 | } 257 | else { 258 | break; 259 | } 260 | } 261 | 262 | if (ch == ' ') ch = '+'; 263 | 264 | ch = reverse_table[ch]; 265 | if (ch < 0) continue; 266 | 267 | switch(i % 4) 268 | { 269 | case 0: 270 | result[j] = ch << 2; 271 | break; 272 | case 1: 273 | result[j++] |= ch >> 4; 274 | result[j] = (ch & 0x0f) << 4; 275 | break; 276 | case 2: 277 | result[j++] |= ch >>2; 278 | result[j] = (ch & 0x03) << 6; 279 | break; 280 | case 3: 281 | result[j++] |= ch; 282 | break; 283 | } 284 | i++; 285 | } 286 | 287 | k = j; 288 | /* mop things up if we ended on a boundary */ 289 | if (ch == base64_pad) 290 | { 291 | switch(i % 4) 292 | { 293 | case 0: 294 | case 1: 295 | *is_null=1; 296 | *error=1; 297 | *ret_length = 0; 298 | return 0; 299 | case 2: 300 | k++; 301 | case 3: 302 | result[k++] = 0; 303 | } 304 | } 305 | 306 | *ret_length = j; 307 | 308 | result[k] = '\0'; 309 | return result; 310 | } 311 | --------------------------------------------------------------------------------