00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00027 #include "common.h"
00028 #include "base64.h"
00029 #include "intreadwrite.h"
00030
00031
00032 static const uint8_t map2[256] =
00033 {
00034 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
00035 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
00036 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
00037 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
00038 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
00039 0xff, 0xff, 0xff,
00040
00041 0x3e, 0xff, 0xff, 0xff, 0x3f, 0x34, 0x35, 0x36,
00042 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0xff,
00043 0xff, 0xff, 0xfe, 0xff, 0xff, 0xff, 0x00, 0x01,
00044 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09,
00045 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11,
00046 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19,
00047 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x1a, 0x1b,
00048 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23,
00049 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b,
00050 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33,
00051
00052 0xff, 0xff, 0xff, 0xff, 0xff,
00053 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
00054 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
00055 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
00056 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
00057 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
00058 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
00059 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
00060 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
00061 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
00062 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
00063 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
00064 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
00065 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
00066 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
00067 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
00068 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
00069 };
00070
00071 #define BASE64_DEC_STEP(i) do { \
00072 bits = map2[in[i]]; \
00073 if (bits & 0x80) \
00074 goto out ## i; \
00075 v = i ? (v << 6) + bits : bits; \
00076 } while(0)
00077
00078 int av_base64_decode(uint8_t *out, const char *in_str, int out_size)
00079 {
00080 uint8_t *dst = out;
00081 uint8_t *end = out + out_size;
00082
00083 const uint8_t *in = in_str;
00084 unsigned bits = 0xff;
00085 unsigned v;
00086
00087 while (end - dst > 3) {
00088 BASE64_DEC_STEP(0);
00089 BASE64_DEC_STEP(1);
00090 BASE64_DEC_STEP(2);
00091 BASE64_DEC_STEP(3);
00092
00093 v = av_be2ne32(v << 8);
00094 AV_WN32(dst, v);
00095 dst += 3;
00096 in += 4;
00097 }
00098 if (end - dst) {
00099 BASE64_DEC_STEP(0);
00100 BASE64_DEC_STEP(1);
00101 BASE64_DEC_STEP(2);
00102 BASE64_DEC_STEP(3);
00103 *dst++ = v >> 16;
00104 if (end - dst)
00105 *dst++ = v >> 8;
00106 if (end - dst)
00107 *dst++ = v;
00108 in += 4;
00109 }
00110 while (1) {
00111 BASE64_DEC_STEP(0);
00112 in++;
00113 BASE64_DEC_STEP(0);
00114 in++;
00115 BASE64_DEC_STEP(0);
00116 in++;
00117 BASE64_DEC_STEP(0);
00118 in++;
00119 }
00120
00121 out3:
00122 *dst++ = v >> 10;
00123 v <<= 2;
00124 out2:
00125 *dst++ = v >> 4;
00126 out1:
00127 out0:
00128 return bits & 1 ? -1 : dst - out;
00129 }
00130
00131
00132
00133
00134
00135
00136
00137 char *av_base64_encode(char *out, int out_size, const uint8_t *in, int in_size)
00138 {
00139 static const char b64[] =
00140 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
00141 char *ret, *dst;
00142 unsigned i_bits = 0;
00143 int i_shift = 0;
00144 int bytes_remaining = in_size;
00145
00146 if (in_size >= UINT_MAX / 4 ||
00147 out_size < AV_BASE64_SIZE(in_size))
00148 return NULL;
00149 ret = dst = out;
00150 while (bytes_remaining > 3) {
00151 i_bits = AV_RB32(in);
00152 in += 3; bytes_remaining -= 3;
00153 *dst++ = b64[ i_bits>>26 ];
00154 *dst++ = b64[(i_bits>>20) & 0x3F];
00155 *dst++ = b64[(i_bits>>14) & 0x3F];
00156 *dst++ = b64[(i_bits>>8 ) & 0x3F];
00157 }
00158 i_bits = 0;
00159 while (bytes_remaining) {
00160 i_bits = (i_bits << 8) + *in++;
00161 bytes_remaining--;
00162 i_shift += 8;
00163 }
00164 while (i_shift > 0) {
00165 *dst++ = b64[(i_bits << 6 >> i_shift) & 0x3f];
00166 i_shift -= 6;
00167 }
00168 while ((dst - ret) & 3)
00169 *dst++ = '=';
00170 *dst = '\0';
00171
00172 return ret;
00173 }
00174
00175 #ifdef TEST
00176
00177
00178 #undef printf
00179
00180 #define MAX_DATA_SIZE 1024
00181 #define MAX_ENCODED_SIZE 2048
00182
00183 static int test_encode_decode(const uint8_t *data, unsigned int data_size,
00184 const char *encoded_ref)
00185 {
00186 char encoded[MAX_ENCODED_SIZE];
00187 uint8_t data2[MAX_DATA_SIZE];
00188 int data2_size, max_data2_size = MAX_DATA_SIZE;
00189
00190 if (!av_base64_encode(encoded, MAX_ENCODED_SIZE, data, data_size)) {
00191 printf("Failed: cannot encode the input data\n");
00192 return 1;
00193 }
00194 if (encoded_ref && strcmp(encoded, encoded_ref)) {
00195 printf("Failed: encoded string differs from reference\n"
00196 "Encoded:\n%s\nReference:\n%s\n", encoded, encoded_ref);
00197 return 1;
00198 }
00199
00200 if ((data2_size = av_base64_decode(data2, encoded, max_data2_size)) != data_size) {
00201 printf("Failed: cannot decode the encoded string\n"
00202 "Encoded:\n%s\n", encoded);
00203 return 1;
00204 }
00205 if ((data2_size = av_base64_decode(data2, encoded, data_size)) != data_size) {
00206 printf("Failed: cannot decode with minimal buffer\n"
00207 "Encoded:\n%s\n", encoded);
00208 return 1;
00209 }
00210 if (memcmp(data2, data, data_size)) {
00211 printf("Failed: encoded/decoded data differs from original data\n");
00212 return 1;
00213 }
00214 if (av_base64_decode(NULL, encoded, 0) != 0) {
00215 printf("Failed: decode to NULL buffer\n");
00216 return 1;
00217 }
00218 if (strlen(encoded)) {
00219 char *end = strchr(encoded, '=');
00220 if (!end)
00221 end = encoded + strlen(encoded) - 1;
00222 *end = '%';
00223 if (av_base64_decode(NULL, encoded, 0) >= 0) {
00224 printf("Failed: error detection\n");
00225 return 1;
00226 }
00227 }
00228
00229 printf("Passed!\n");
00230 return 0;
00231 }
00232
00233 int main(int argc, char ** argv)
00234 {
00235 int i, error_count = 0;
00236 struct test {
00237 const uint8_t *data;
00238 const char *encoded_ref;
00239 } tests[] = {
00240 { "", ""},
00241 { "1", "MQ=="},
00242 { "22", "MjI="},
00243 { "333", "MzMz"},
00244 { "4444", "NDQ0NA=="},
00245 { "55555", "NTU1NTU="},
00246 { "666666", "NjY2NjY2"},
00247 { "abc:def", "YWJjOmRlZg=="},
00248 };
00249 char in[1024], out[2048];
00250
00251 printf("Encoding/decoding tests\n");
00252 for (i = 0; i < FF_ARRAY_ELEMS(tests); i++)
00253 error_count += test_encode_decode(tests[i].data, strlen(tests[i].data), tests[i].encoded_ref);
00254
00255 if (argc>1 && !strcmp(argv[1], "-t")) {
00256 memset(in, 123, sizeof(in));
00257 for(i=0; i<10000; i++){
00258 START_TIMER
00259 av_base64_encode(out, sizeof(out), in, sizeof(in));
00260 STOP_TIMER("encode")
00261 }
00262 for(i=0; i<10000; i++){
00263 START_TIMER
00264 av_base64_decode(in, out, sizeof(in));
00265 STOP_TIMER("decode")
00266 }
00267
00268 for(i=0; i<10000; i++){
00269 START_TIMER
00270 av_base64_decode(NULL, out, 0);
00271 STOP_TIMER("syntax check")
00272 }
00273 }
00274
00275 return error_count;
00276 }
00277
00278
00279 #endif