00001
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028 #include "system.h"
00029 #include "base64.h"
00030 #include "debug.h"
00031
00032
00033 static int _debug = 0;
00034
00035
00036 static const char* to_b64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
00037
00038
00039 #define CHARS_PER_LINE 64
00040
00041
00042 char* b64enc(const memchunk* chunk)
00043 {
00044 int div = chunk->size / 3;
00045 int rem = chunk->size % 3;
00046 int chars = div*4 + rem + 1;
00047 int newlines = (chars + CHARS_PER_LINE - 1) / CHARS_PER_LINE;
00048
00049 const byte* data = chunk->data;
00050 char* string = (char*) malloc(chars + newlines + 1);
00051
00052 if (string)
00053 {
00054 register char* buf = string;
00055
00056 chars = 0;
00057
00058 while (div > 0)
00059 {
00060 buf[0] = to_b64[ ((unsigned)data[0] >> 2) & 0x3f];
00061 buf[1] = to_b64[(((unsigned)data[0] << 4) & 0x30) | (((unsigned)data[1] >> 4) & 0xf)];
00062 buf[2] = to_b64[(((unsigned)data[1] << 2) & 0x3c) | (((unsigned)data[2] >> 6) & 0x3)];
00063 buf[3] = to_b64[ (unsigned)data[2] & 0x3f];
00064 data += 3;
00065 buf += 4;
00066 div--;
00067 chars += 4;
00068 if (chars == CHARS_PER_LINE)
00069 {
00070 chars = 0;
00071 *(buf++) = '\n';
00072 }
00073 }
00074
00075 switch (rem)
00076 {
00077 case 2:
00078 buf[0] = to_b64[ ((unsigned)data[0] >> 2) & 0x3f];
00079 buf[1] = to_b64[(((unsigned)data[0] << 4) & 0x30) + (((unsigned)data[1] >> 4) & 0xf)];
00080 buf[2] = to_b64[ ((unsigned)data[1] << 2) & 0x3c];
00081 buf[3] = '=';
00082 buf += 4;
00083 chars += 4;
00084 break;
00085 case 1:
00086 buf[0] = to_b64[ ((unsigned)data[0] >> 2) & 0x3f];
00087 buf[1] = to_b64[ ((unsigned)data[0] << 4) & 0x30];
00088 buf[2] = '=';
00089 buf[3] = '=';
00090 buf += 4;
00091 chars += 4;
00092 break;
00093 }
00094
00095
00096 *buf = '\0';
00097 }
00098
00099
00100 return string;
00101
00102 }
00103
00104
00105
00106 memchunk* b64dec(const char* string)
00107 {
00108
00109
00110 memchunk* rc = 0;
00111
00112 if (string)
00113 {
00114 register int length = strlen(string);
00115
00116
00117 if (length > 0)
00118 {
00119 register int count = 0, rem = 0;
00120 register const char* tmp = string;
00121
00122 while (length > 0)
00123 {
00124 register int skip = strspn(tmp, to_b64);
00125 count += skip;
00126 length -= skip;
00127 tmp += skip;
00128 if (length > 0)
00129 {
00130 register int i, vrfy = strcspn(tmp, to_b64);
00131
00132 for (i = 0; i < vrfy; i++)
00133 {
00134 if (isspace(tmp[i]))
00135 continue;
00136
00137 if (tmp[i] == '=')
00138 {
00139
00140 rem = count % 4;
00141
00142
00143 if (rem < 2)
00144 return 0;
00145
00146
00147 break;
00148 }
00149 else
00150 {
00151
00152
00153
00154
00155
00156 return 0;
00157 }
00158 }
00159
00160 length -= vrfy;
00161 tmp += vrfy;
00162 }
00163 }
00164
00165 rc = memchunkAlloc((count / 4) * 3 + (rem ? (rem - 1) : 0));
00166
00167 if (rc)
00168 {
00169 if (count > 0)
00170 {
00171 register int i, qw = 0, tw = 0;
00172 register byte* data = rc->data;
00173
00174 length = strlen(tmp = string);
00175
00176 for (i = 0; i < length; i++)
00177 {
00178 register char ch = string[i];
00179 register byte bits;
00180
00181 if (isspace(ch))
00182 continue;
00183
00184 bits = 0;
00185 if ((ch >= 'A') && (ch <= 'Z'))
00186 {
00187 bits = (byte) (ch - 'A');
00188 }
00189 else if ((ch >= 'a') && (ch <= 'z'))
00190 {
00191 bits = (byte) (ch - 'a' + 26);
00192 }
00193 else if ((ch >= '0') && (ch <= '9'))
00194 {
00195 bits = (byte) (ch - '0' + 52);
00196 }
00197 else if (ch == '+')
00198 {
00199 bits = 62;
00200 }
00201 else if (ch == '/')
00202 {
00203 bits = 63;
00204 }
00205 else if (ch == '=')
00206 break;
00207 else
00208 {};
00209
00210 switch (qw++)
00211 {
00212 case 0:
00213 data[tw+0] = (bits << 2) & 0xfc;
00214 break;
00215 case 1:
00216 data[tw+0] |= (bits >> 4) & 0x03;
00217 data[tw+1] = (bits << 4) & 0xf0;
00218 break;
00219 case 2:
00220 data[tw+1] |= (bits >> 2) & 0x0f;
00221 data[tw+2] = (bits << 6) & 0xc0;
00222 break;
00223 case 3:
00224 data[tw+2] |= bits & 0x3f;
00225 break;
00226 }
00227
00228 if (qw == 4)
00229 {
00230 qw = 0;
00231 tw += 3;
00232 }
00233 }
00234 }
00235 }
00236 }
00237 }
00238
00239 return rc;
00240 }
00241
00242
00243 int b64encode_chars_per_line = B64ENCODE_CHARS_PER_LINE;
00244
00245 const char * b64encode_eolstr = B64ENCODE_EOLSTR;
00246
00247
00248
00249 char * b64encode (const void * data, int ns)
00250 {
00251 static char b64enc[] =
00252 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
00253 const char *e;
00254 const unsigned char *s = data;
00255 unsigned char *t, *te;
00256 int nt;
00257 int lc;
00258 unsigned c;
00259
00260 if (s == NULL) return NULL;
00261 if (*s == '\0') return calloc(1, sizeof(*t));
00262
00263 if (ns == 0) ns = strlen(s);
00264 nt = ((ns + 2) / 3) * 4;
00265
00266
00267 if (b64encode_chars_per_line > 0 && b64encode_eolstr != NULL) {
00268 lc = (nt + b64encode_chars_per_line - 1) / b64encode_chars_per_line;
00269 if (((nt + b64encode_chars_per_line - 1) % b64encode_chars_per_line) != 0)
00270 ++lc;
00271 nt += lc * strlen(b64encode_eolstr);
00272 }
00273
00274 t = te = malloc(nt + 1);
00275
00276 lc = 0;
00277 if (te)
00278 while (ns) {
00279
00280 if (_debug)
00281 fprintf(stderr, "%7u %02x %02x %02x -> %02x %02x %02x %02x\n",
00282 (unsigned)ns, (unsigned)s[0], (unsigned)s[1], (unsigned)s[2],
00283 (unsigned)(s[0] >> 2),
00284 (unsigned)((s[0] & 0x3) << 4) | (s[1] >> 4),
00285 (unsigned)((s[1] & 0xf) << 2) | (s[2] >> 6),
00286 (unsigned)(s[2]& 0x3f));
00287 c = *s++;
00288 *te++ = b64enc[ (c >> 2) ], lc++;
00289 *te++ = b64enc[ ((c & 0x3) << 4) | (*s >> 4) ], lc++;
00290 if (--ns == 0) {
00291 *te++ = '=';
00292 *te++ = '=';
00293 continue;
00294 }
00295 c = *s++;
00296 *te++ = b64enc[ ((c & 0xf) << 2) | (*s >> 6) ], lc++;
00297 if (--ns == 0) {
00298 *te++ = '=';
00299 continue;
00300 }
00301 *te++ = b64enc[ (int)(*s & 0x3f) ], lc++;
00302
00303
00304 if (b64encode_chars_per_line > 0 && b64encode_eolstr != NULL) {
00305 if (lc >= b64encode_chars_per_line) {
00306 for (e = b64encode_eolstr; *e != '\0'; e++)
00307 *te++ = *e;
00308 lc = 0;
00309 }
00310 }
00311 s++;
00312 --ns;
00313 }
00314
00315 if (te) {
00316
00317 if (b64encode_chars_per_line > 0 && b64encode_eolstr != NULL) {
00318 if (lc != 0) {
00319 for (e = b64encode_eolstr; *e != '\0'; e++)
00320 *te++ = *e;
00321 }
00322 }
00323 *te = '\0';
00324 }
00325
00326
00327 return t;
00328
00329 }
00330
00331
00332
00333
00334 #define CRC24_INIT 0xb704ceL
00335 #define CRC24_POLY 0x1864cfbL
00336
00337
00338 char * b64crc (const unsigned char * data, int ns)
00339 {
00340 const unsigned char *s = data;
00341 uint32 crc = CRC24_INIT;
00342
00343 while (ns-- > 0) {
00344 int i;
00345 crc ^= (*s++) << 16;
00346 for (i = 0; i < 8; i++) {
00347 crc <<= 1;
00348 if (crc & 0x1000000)
00349 crc ^= CRC24_POLY;
00350 }
00351 }
00352 crc &= 0xffffff;
00353
00354 #if !WORDS_BIGENDIAN
00355 crc = swapu32(crc);
00356 #endif
00357
00358 data = (byte *)&crc;
00359 data++;
00360 ns = 3;
00361 return b64encode(data, ns);
00362 }
00363
00364
00365
00366 const char * b64decode_whitespace = B64DECODE_WHITESPACE;
00367
00368
00369
00370 int b64decode (const char * s, void ** datap, int *lenp)
00371 {
00372 unsigned char b64dec[256];
00373 const unsigned char *t;
00374 unsigned char *te;
00375 int ns, nt;
00376 unsigned a, b, c, d;
00377
00378 if (s == NULL) return 1;
00379
00380
00381 memset(b64dec, 0x80, sizeof(b64dec));
00382 for (c = 'A'; c <= 'Z'; c++)
00383 b64dec[ c ] = 0 + (c - 'A');
00384 for (c = 'a'; c <= 'z'; c++)
00385 b64dec[ c ] = 26 + (c - 'a');
00386 for (c = '0'; c <= '9'; c++)
00387 b64dec[ c ] = 52 + (c - '0');
00388 b64dec[(unsigned)'+'] = 62;
00389 b64dec[(unsigned)'/'] = 63;
00390 b64dec[(unsigned)'='] = 0;
00391
00392
00393 if (b64decode_whitespace) {
00394 const char *e;
00395 for (e = b64decode_whitespace; *e != '\0'; e++) {
00396 if (b64dec[ (unsigned)*e ] == 0x80)
00397 b64dec[ (unsigned)*e ] = 0x81;
00398 }
00399 }
00400
00401
00402 ns = 0;
00403 for (t = s; *t != '\0'; t++) {
00404 switch (b64dec[ (unsigned)*t ]) {
00405 case 0x80:
00406 if (_debug)
00407 fprintf(stderr, "--- b64decode %c(%02x) %02x\n", *t, (unsigned)(*t & 0xff), (unsigned)b64dec[ (unsigned)*t ]);
00408 return 3;
00409 break;
00410 case 0x81:
00411 break;
00412 default:
00413 ns++;
00414 break;
00415 }
00416 }
00417
00418 if (ns & 0x3) return 2;
00419
00420 nt = (ns / 4) * 3;
00421 t = te = malloc(nt + 1);
00422
00423 while (ns > 0) {
00424
00425
00426 while ((a = b64dec[ (unsigned)*s++ ]) == 0x81)
00427 {};
00428 while ((b = b64dec[ (unsigned)*s++ ]) == 0x81)
00429 {};
00430 while ((c = b64dec[ (unsigned)*s++ ]) == 0x81)
00431 {};
00432 while ((d = b64dec[ (unsigned)*s++ ]) == 0x81)
00433 {};
00434
00435 if (_debug)
00436 fprintf(stderr, "%7u %02x %02x %02x %02x -> %02x %02x %02x\n",
00437 (unsigned)ns, a, b, c, d,
00438 (((a << 2) | (b >> 4)) & 0xff),
00439 (((b << 4) | (c >> 2)) & 0xff),
00440 (((c << 6) | d) & 0xff));
00441
00442 ns -= 4;
00443 *te++ = (a << 2) | (b >> 4);
00444 if (s[-2] == '=') break;
00445 *te++ = (b << 4) | (c >> 2);
00446 if (s[-1] == '=') break;
00447 *te++ = (c << 6) | d;
00448 }
00449
00450 if (ns != 0) {
00451 if (t) free((void *)t);
00452 return 1;
00453 }
00454 if (lenp)
00455 *lenp = (te - t);
00456
00457 if (datap)
00458 *datap = (void *)t;
00459 else
00460 if (t) free((void *)t);
00461 else
00462 {};
00463
00464 return 0;
00465 }
00466
00467