| 1 | /* |
| 2 | https://github.com/superwills/NibbleAndAHalf |
| 3 | base64.h -- Fast base64 encoding and decoding. |
| 4 | version 1.0.0, April 17, 2013 143a |
| 5 | Copyright (C) 2013 William Sherif |
| 6 | This software is provided 'as-is', without any express or implied |
| 7 | warranty. In no event will the authors be held liable for any damages |
| 8 | arising from the use of this software. |
| 9 | Permission is granted to anyone to use this software for any purpose, |
| 10 | including commercial applications, and to alter it and redistribute it |
| 11 | freely, subject to the following restrictions: |
| 12 | 1. The origin of this software must not be misrepresented; you must not |
| 13 | claim that you wrote the original software. If you use this software |
| 14 | in a product, an acknowledgment in the product documentation would be |
| 15 | appreciated but is not required. |
| 16 | 2. Altered source versions must be plainly marked as such, and must not be |
| 17 | misrepresented as being the original software. |
| 18 | 3. This notice may not be removed or altered from any source distribution. |
| 19 | William Sherif |
| 20 | will.sherif@gmail.com |
| 21 | YWxsIHlvdXIgYmFzZSBhcmUgYmVsb25nIHRvIHVz |
| 22 | |
| 23 | |
| 24 | Modified for RetroArch formatting, logging, and header files. |
| 25 | */ |
| 26 | |
| 27 | |
| 28 | #include <stdio.h> |
| 29 | #include <stdlib.h> |
| 30 | #include <encodings/base64.h> |
| 31 | |
| 32 | const static char* b64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; |
| 33 | |
| 34 | /* maps A=>0,B=>1.. */ |
| 35 | const static unsigned char unb64[]={ |
| 36 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
| 37 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
| 38 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
| 39 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
| 40 | 0, 0, 0, 62, 0, 0, 0, 63, 52, 53, |
| 41 | 54, 55, 56, 57, 58, 59, 60, 61, 0, 0, |
| 42 | 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, |
| 43 | 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, |
| 44 | 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, |
| 45 | 25, 0, 0, 0, 0, 0, 0, 26, 27, 28, |
| 46 | 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, |
| 47 | 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, |
| 48 | 49, 50, 51, 0, 0, 0, 0, 0, 0, 0, |
| 49 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
| 50 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
| 51 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
| 52 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
| 53 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
| 54 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
| 55 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
| 56 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
| 57 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
| 58 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
| 59 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
| 60 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
| 61 | 0, 0, 0, 0, 0, 0, |
| 62 | }; /* This array has 256 elements */ |
| 63 | |
| 64 | /* |
| 65 | Converts binary data of length=len to base64 characters. |
| 66 | Length of the resultant string is stored in flen |
| 67 | (you must pass pointer flen). |
| 68 | */ |
| 69 | char* base64(const void* binaryData, int len, int *flen) |
| 70 | { |
| 71 | char* res; |
| 72 | int byteNo; /* I need this after the loop */ |
| 73 | const unsigned char* bin = (const unsigned char*) binaryData; |
| 74 | int rc = 0; /* result counter */ |
| 75 | int modulusLen = len % 3 ; |
| 76 | /* 2 gives 1 and 1 gives 2, but 0 gives 0. */ |
| 77 | int pad = ((modulusLen&1)<<1) + ((modulusLen&2)>>1); |
| 78 | |
| 79 | *flen = 4*(len + pad)/3; |
| 80 | if (!(res = (char*) malloc(*flen + 1))) /* and one for the NULL */ |
| 81 | return 0; |
| 82 | |
| 83 | for (byteNo=0; byteNo <= len-3; byteNo+=3) |
| 84 | { |
| 85 | unsigned char BYTE0 = bin[byteNo]; |
| 86 | unsigned char BYTE1 = bin[byteNo+1]; |
| 87 | unsigned char BYTE2 = bin[byteNo+2]; |
| 88 | |
| 89 | res[rc++] = b64[BYTE0 >> 2]; |
| 90 | res[rc++] = b64[((0x3&BYTE0)<<4) + (BYTE1 >> 4)]; |
| 91 | res[rc++] = b64[((0x0f&BYTE1)<<2) + (BYTE2>>6)]; |
| 92 | res[rc++] = b64[0x3f&BYTE2]; |
| 93 | } |
| 94 | |
| 95 | if (pad==2) |
| 96 | { |
| 97 | res[rc++] = b64[bin[byteNo] >> 2]; |
| 98 | res[rc++] = b64[(0x3&bin[byteNo])<<4]; |
| 99 | res[rc++] = '='; |
| 100 | res[rc++] = '='; |
| 101 | } |
| 102 | else if (pad==1) |
| 103 | { |
| 104 | res[rc++] = b64[bin[byteNo] >> 2]; |
| 105 | res[rc++] = b64[((0x3&bin[byteNo])<<4) + (bin[byteNo+1] >> 4)]; |
| 106 | res[rc++] = b64[(0x0f&bin[byteNo+1])<<2]; |
| 107 | res[rc++] = '='; |
| 108 | } |
| 109 | |
| 110 | res[rc]=0; /* NULL TERMINATOR! ;) */ |
| 111 | return res; |
| 112 | } |
| 113 | |
| 114 | unsigned char* unbase64(const char* ascii, int len, int *flen) |
| 115 | { |
| 116 | int charNo; |
| 117 | unsigned char *bin; |
| 118 | const unsigned char *safeAsciiPtr = (const unsigned char*) ascii; |
| 119 | int cb = 0; |
| 120 | int pad = 0; |
| 121 | |
| 122 | if (len < 2) /* 2 accesses below would be OOB (Out Of Bounds). */ |
| 123 | { |
| 124 | /* catch empty string, return NULL as result. */ |
| 125 | /* ERROR: You passed an invalid base64 string (too short). |
| 126 | * You get NULL back. */ |
| 127 | *flen = 0; |
| 128 | return 0; |
| 129 | } |
| 130 | |
| 131 | if (safeAsciiPtr[len-1]=='=') |
| 132 | ++pad; |
| 133 | if (safeAsciiPtr[len-2]=='=') |
| 134 | ++pad; |
| 135 | |
| 136 | *flen = 3*len/4 - pad; |
| 137 | if (!(bin = (unsigned char*)malloc(*flen))) |
| 138 | return 0; |
| 139 | |
| 140 | for (charNo=0; charNo <= len-4-pad; charNo+=4) |
| 141 | { |
| 142 | int A = unb64[safeAsciiPtr[charNo]]; |
| 143 | int B = unb64[safeAsciiPtr[charNo+1]]; |
| 144 | int C = unb64[safeAsciiPtr[charNo+2]]; |
| 145 | int D = unb64[safeAsciiPtr[charNo+3]]; |
| 146 | |
| 147 | bin[cb++] = (A<<2) | (B>>4); |
| 148 | bin[cb++] = (B<<4) | (C>>2); |
| 149 | bin[cb++] = (C<<6) | (D); |
| 150 | } |
| 151 | |
| 152 | if (pad==1) |
| 153 | { |
| 154 | int A = unb64[safeAsciiPtr[charNo]]; |
| 155 | int B = unb64[safeAsciiPtr[charNo+1]]; |
| 156 | int C = unb64[safeAsciiPtr[charNo+2]]; |
| 157 | |
| 158 | bin[cb++] = (A<<2) | (B>>4); |
| 159 | bin[cb++] = (B<<4) | (C>>2); |
| 160 | } |
| 161 | else if (pad==2) |
| 162 | { |
| 163 | int A = unb64[safeAsciiPtr[charNo]]; |
| 164 | int B = unb64[safeAsciiPtr[charNo+1]]; |
| 165 | |
| 166 | bin[cb++] = (A<<2) | (B>>4); |
| 167 | } |
| 168 | |
| 169 | return bin; |
| 170 | } |
| 171 | |