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;
00046 olen += olen / 72;
00047 olen++;
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
00202