Commit | Line | Data |
---|---|---|
3719602c PC |
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 |