base64.c

Go to the documentation of this file.
00001 
00016 #include <stdlib.h>
00017 #include <string.h>
00018 
00019 #include "base64.h"
00020 
00021 static const unsigned char base64_table[64] =
00022         "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
00023 
00037 unsigned char * base64_encode(const unsigned char *src, size_t len,
00038                               size_t *out_len)
00039 {
00040         unsigned char *out, *pos;
00041         const unsigned char *end, *in;
00042         size_t olen;
00043         int line_len;
00044 
00045         olen = len * 4 / 3 + 4; /* 3-byte blocks to 4-byte */
00046         olen += olen / 72; /* line feeds */
00047         olen++; /* nul termination */
00048         out = malloc(olen);
00049         if (out == NULL)
00050                 return NULL;
00051 
00052         end = src + len;
00053         in = src;
00054         pos = out;
00055         line_len = 0;
00056         while (end - in >= 3) {
00057                 *pos++ = base64_table[in[0] >> 2];
00058                 *pos++ = base64_table[((in[0] & 0x03) << 4) | (in[1] >> 4)];
00059                 *pos++ = base64_table[((in[1] & 0x0f) << 2) | (in[2] >> 6)];
00060                 *pos++ = base64_table[in[2] & 0x3f];
00061                 in += 3;
00062                 line_len += 4;
00063                 if (line_len >= 72) {
00064                         *pos++ = '\n';
00065                         line_len = 0;
00066                 }
00067         }
00068 
00069         if (end - in) {
00070                 *pos++ = base64_table[in[0] >> 2];
00071                 if (end - in == 1) {
00072                         *pos++ = base64_table[(in[0] & 0x03) << 4];
00073                         *pos++ = '=';
00074                 } else {
00075                         *pos++ = base64_table[((in[0] & 0x03) << 4) |
00076                                               (in[1] >> 4)];
00077                         *pos++ = base64_table[(in[1] & 0x0f) << 2];
00078                 }
00079                 *pos++ = '=';
00080                 line_len += 4;
00081         }
00082 
00083         if (line_len)
00084                 *pos++ = '\n';
00085 
00086         *pos = '\0';
00087         if (out_len)
00088                 *out_len = pos - out;
00089         return out;
00090 }
00091 
00092 
00104 unsigned char * base64_decode(const unsigned char *src, size_t len,
00105                               size_t *out_len)
00106 {
00107         unsigned char dtable[256], *out, *pos, in[4], block[4], tmp;
00108         size_t i, count, olen;
00109 
00110         memset(dtable, 0x80, 256);
00111         for (i = 0; i < sizeof(base64_table); i++)
00112                 dtable[base64_table[i]] = i;
00113         dtable['='] = 0;
00114 
00115         count = 0;
00116         for (i = 0; i < len; i++) {
00117                 if (dtable[src[i]] != 0x80)
00118                         count++;
00119         }
00120 
00121         if (count % 4)
00122                 return NULL;
00123 
00124         olen = count / 4 * 3;
00125         pos = out = malloc(count);
00126         if (out == NULL)
00127                 return NULL;
00128 
00129         count = 0;
00130         for (i = 0; i < len; i++) {
00131                 tmp = dtable[src[i]];
00132                 if (tmp == 0x80)
00133                         continue;
00134 
00135                 in[count] = src[i];
00136                 block[count] = tmp;
00137                 count++;
00138                 if (count == 4) {
00139                         *pos++ = (block[0] << 2) | (block[1] >> 4);
00140                         *pos++ = (block[1] << 4) | (block[2] >> 2);
00141                         *pos++ = (block[2] << 6) | block[3];
00142                         count = 0;
00143                 }
00144         }
00145 
00146         if (pos > out) {
00147                 if (in[2] == '=')
00148                         pos -= 2;
00149                 else if (in[3] == '=')
00150                         pos--;
00151         }
00152 
00153         *out_len = pos - out;
00154         return out;
00155 }
00156 
00157 
00158 #ifdef TEST_MAIN
00159 #include <stdio.h>
00160 
00161 int main(int argc, char *argv[])
00162 {
00163         FILE *f;
00164         size_t len, elen;
00165         unsigned char *buf, *e;
00166 
00167         if (argc != 4) {
00168                 printf("Usage: base64 <encode|decode> <in file> <out file>\n");
00169                 return -1;
00170         }
00171 
00172         f = fopen(argv[2], "r");
00173         if (f == NULL)
00174                 return -1;
00175         fseek(f, 0, SEEK_END);
00176         len = ftell(f);
00177         fseek(f, 0, SEEK_SET);
00178         buf = malloc(len);
00179         if (buf == NULL) {
00180                 fclose(f);
00181                 return -1;
00182         }
00183         fread(buf, 1, len, f);
00184         fclose(f);
00185 
00186         if (strcmp(argv[1], "encode") == 0)
00187                 e = base64_encode(buf, len, &elen);
00188         else
00189                 e = base64_decode(buf, len, &elen);
00190         if (e == NULL)
00191                 return -2;
00192         f = fopen(argv[3], "w");
00193         if (f == NULL)
00194                 return -3;
00195         fwrite(e, 1, elen, f);
00196         fclose(f);
00197         free(e);
00198 
00199         return 0;
00200 }
00201 #endif /* TEST_MAIN */
00202 

Generated on Sat May 6 21:13:29 2006 for wpa_supplicant by  doxygen 1.4.2