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 #define MAX_DATA_SIZE 1024
00179 #define MAX_ENCODED_SIZE 2048
00180
00181 static int test_encode_decode(const uint8_t *data, unsigned int data_size,
00182 const char *encoded_ref)
00183 {
00184 char encoded[MAX_ENCODED_SIZE];
00185 uint8_t data2[MAX_DATA_SIZE];
00186 int data2_size, max_data2_size = MAX_DATA_SIZE;
00187
00188 if (!av_base64_encode(encoded, MAX_ENCODED_SIZE, data, data_size)) {
00189 printf("Failed: cannot encode the input data\n");
00190 return 1;
00191 }
00192 if (encoded_ref && strcmp(encoded, encoded_ref)) {
00193 printf("Failed: encoded string differs from reference\n"
00194 "Encoded:\n%s\nReference:\n%s\n", encoded, encoded_ref);
00195 return 1;
00196 }
00197
00198 if ((data2_size = av_base64_decode(data2, encoded, max_data2_size)) != data_size) {
00199 printf("Failed: cannot decode the encoded string\n"
00200 "Encoded:\n%s\n", encoded);
00201 return 1;
00202 }
00203 if ((data2_size = av_base64_decode(data2, encoded, data_size)) != data_size) {
00204 printf("Failed: cannot decode with minimal buffer\n"
00205 "Encoded:\n%s\n", encoded);
00206 return 1;
00207 }
00208 if (memcmp(data2, data, data_size)) {
00209 printf("Failed: encoded/decoded data differs from original data\n");
00210 return 1;
00211 }
00212 if (av_base64_decode(NULL, encoded, 0) != 0) {
00213 printf("Failed: decode to NULL buffer\n");
00214 return 1;
00215 }
00216 if (strlen(encoded)) {
00217 char *end = strchr(encoded, '=');
00218 if (!end)
00219 end = encoded + strlen(encoded) - 1;
00220 *end = '%';
00221 if (av_base64_decode(NULL, encoded, 0) >= 0) {
00222 printf("Failed: error detection\n");
00223 return 1;
00224 }
00225 }
00226
00227 printf("Passed!\n");
00228 return 0;
00229 }
00230
00231 int main(int argc, char ** argv)
00232 {
00233 int i, error_count = 0;
00234 struct test {
00235 const uint8_t *data;
00236 const char *encoded_ref;
00237 } tests[] = {
00238 { "", ""},
00239 { "1", "MQ=="},
00240 { "22", "MjI="},
00241 { "333", "MzMz"},
00242 { "4444", "NDQ0NA=="},
00243 { "55555", "NTU1NTU="},
00244 { "666666", "NjY2NjY2"},
00245 { "abc:def", "YWJjOmRlZg=="},
00246 };
00247 char in[1024], out[2048];
00248
00249 printf("Encoding/decoding tests\n");
00250 for (i = 0; i < FF_ARRAY_ELEMS(tests); i++)
00251 error_count += test_encode_decode(tests[i].data, strlen(tests[i].data), tests[i].encoded_ref);
00252
00253 if (argc>1 && !strcmp(argv[1], "-t")) {
00254 memset(in, 123, sizeof(in));
00255 for(i=0; i<10000; i++){
00256 START_TIMER
00257 av_base64_encode(out, sizeof(out), in, sizeof(in));
00258 STOP_TIMER("encode")
00259 }
00260 for(i=0; i<10000; i++){
00261 START_TIMER
00262 av_base64_decode(in, out, sizeof(in));
00263 STOP_TIMER("decode")
00264 }
00265
00266 for(i=0; i<10000; i++){
00267 START_TIMER
00268 av_base64_decode(NULL, out, 0);
00269 STOP_TIMER("syntax check")
00270 }
00271 }
00272
00273 return error_count;
00274 }
00275
00276
00277 #endif