• Main Page
  • Related Pages
  • Modules
  • Data Structures
  • Files
  • File List
  • Globals

libavutil/base64.c

Go to the documentation of this file.
00001 /*
00002  * Copyright (c) 2006 Ryan Martell. (rdm4@martellventures.com)
00003  *
00004  * This file is part of FFmpeg.
00005  *
00006  * FFmpeg 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  * FFmpeg 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 FFmpeg; 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 < (in_size+2) / 3 * 4 + 1)
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

Generated on Fri Sep 16 2011 17:17:51 for FFmpeg by  doxygen 1.7.1