Libav 0.7.1
|
00001 /* 00002 * Copyright (c) 2006 Ryan Martell. (rdm4@martellventures.com) 00003 * 00004 * This file is part of Libav. 00005 * 00006 * Libav is free software; you can redistribute it and/or 00007 * modify it under the terms of the GNU Lesser General Public 00008 * License as published by the Free Software Foundation; either 00009 * version 2.1 of the License, or (at your option) any later version. 00010 * 00011 * Libav is distributed in the hope that it will be useful, 00012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00014 * Lesser General Public License for more details. 00015 * 00016 * You should have received a copy of the GNU Lesser General Public 00017 * License along with Libav; if not, write to the Free Software 00018 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 00019 */ 00020 00027 #include "common.h" 00028 #include "base64.h" 00029 00030 /* ---------------- private code */ 00031 static const uint8_t map2[] = 00032 { 00033 0x3e, 0xff, 0xff, 0xff, 0x3f, 0x34, 0x35, 0x36, 00034 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0xff, 00035 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x01, 00036 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 00037 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 00038 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 00039 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x1a, 0x1b, 00040 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23, 00041 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 00042 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33 00043 }; 00044 00045 int av_base64_decode(uint8_t *out, const char *in, int out_size) 00046 { 00047 int i, v; 00048 uint8_t *dst = out; 00049 00050 v = 0; 00051 for (i = 0; in[i] && in[i] != '='; i++) { 00052 unsigned int index= in[i]-43; 00053 if (index>=FF_ARRAY_ELEMS(map2) || map2[index] == 0xff) 00054 return -1; 00055 v = (v << 6) + map2[index]; 00056 if (i & 3) { 00057 if (dst - out < out_size) { 00058 *dst++ = v >> (6 - 2 * (i & 3)); 00059 } 00060 } 00061 } 00062 00063 return dst - out; 00064 } 00065 00066 /***************************************************************************** 00067 * b64_encode: Stolen from VLC's http.c. 00068 * Simplified by Michael. 00069 * Fixed edge cases and made it work from data (vs. strings) by Ryan. 00070 *****************************************************************************/ 00071 00072 char *av_base64_encode(char *out, int out_size, const uint8_t *in, int in_size) 00073 { 00074 static const char b64[] = 00075 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; 00076 char *ret, *dst; 00077 unsigned i_bits = 0; 00078 int i_shift = 0; 00079 int bytes_remaining = in_size; 00080 00081 if (in_size >= UINT_MAX / 4 || 00082 out_size < AV_BASE64_SIZE(in_size)) 00083 return NULL; 00084 ret = dst = out; 00085 while (bytes_remaining) { 00086 i_bits = (i_bits << 8) + *in++; 00087 bytes_remaining--; 00088 i_shift += 8; 00089 00090 do { 00091 *dst++ = b64[(i_bits << 6 >> i_shift) & 0x3f]; 00092 i_shift -= 6; 00093 } while (i_shift > 6 || (bytes_remaining == 0 && i_shift > 0)); 00094 } 00095 while ((dst - ret) & 3) 00096 *dst++ = '='; 00097 *dst = '\0'; 00098 00099 return ret; 00100 } 00101 00102 #ifdef TEST 00103 00104 #undef printf 00105 00106 #define MAX_DATA_SIZE 1024 00107 #define MAX_ENCODED_SIZE 2048 00108 00109 static int test_encode_decode(const uint8_t *data, unsigned int data_size, 00110 const char *encoded_ref) 00111 { 00112 char encoded[MAX_ENCODED_SIZE]; 00113 uint8_t data2[MAX_DATA_SIZE]; 00114 int data2_size, max_data2_size = MAX_DATA_SIZE; 00115 00116 if (!av_base64_encode(encoded, MAX_ENCODED_SIZE, data, data_size)) { 00117 printf("Failed: cannot encode the input data\n"); 00118 return 1; 00119 } 00120 if (encoded_ref && strcmp(encoded, encoded_ref)) { 00121 printf("Failed: encoded string differs from reference\n" 00122 "Encoded:\n%s\nReference:\n%s\n", encoded, encoded_ref); 00123 return 1; 00124 } 00125 00126 if ((data2_size = av_base64_decode(data2, encoded, max_data2_size)) < 0) { 00127 printf("Failed: cannot decode the encoded string\n" 00128 "Encoded:\n%s\n", encoded); 00129 return 1; 00130 } 00131 if (memcmp(data2, data, data_size)) { 00132 printf("Failed: encoded/decoded data differs from original data\n"); 00133 return 1; 00134 } 00135 00136 printf("Passed!\n"); 00137 return 0; 00138 } 00139 00140 int main(void) 00141 { 00142 int i, error_count = 0; 00143 struct test { 00144 const uint8_t *data; 00145 const char *encoded_ref; 00146 } tests[] = { 00147 { "", ""}, 00148 { "1", "MQ=="}, 00149 { "22", "MjI="}, 00150 { "333", "MzMz"}, 00151 { "4444", "NDQ0NA=="}, 00152 { "55555", "NTU1NTU="}, 00153 { "666666", "NjY2NjY2"}, 00154 { "abc:def", "YWJjOmRlZg=="}, 00155 }; 00156 00157 printf("Encoding/decoding tests\n"); 00158 for (i = 0; i < FF_ARRAY_ELEMS(tests); i++) 00159 error_count += test_encode_decode(tests[i].data, strlen(tests[i].data), tests[i].encoded_ref); 00160 00161 return error_count; 00162 } 00163 00164 #endif