mirror of
git://git.psyced.org/git/psyced
synced 2024-08-15 03:25:10 +00:00
103 lines
2.3 KiB
C
103 lines
2.3 KiB
C
|
// $Id: base64.c,v 1.7 2005/11/13 19:52:44 lynx Exp $ // vim:syntax=lpc
|
||
|
//
|
||
|
// base64 encoder/decoder
|
||
|
// 2004 - Dan@Gueldenland - df@erinye.com
|
||
|
//
|
||
|
#include <net.h>
|
||
|
|
||
|
volatile string * char64 = efun::explode("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/", "");
|
||
|
|
||
|
volatile mapping deco64 = funcall( (:
|
||
|
mapping x = ([ ]);
|
||
|
int i;
|
||
|
for(i=0; i<64; ++i) {
|
||
|
x[char64[i][0]] = i+1;
|
||
|
}
|
||
|
x['='] = 1;
|
||
|
return x;
|
||
|
:) );
|
||
|
|
||
|
static int deco(int i) {
|
||
|
i = deco64[i];
|
||
|
if(!i) raise_error("Oh crap.\n");
|
||
|
return i-1;
|
||
|
}
|
||
|
|
||
|
string encode_base64(int * b) {
|
||
|
int bbb, i=0, s=sizeof(b);
|
||
|
string res = "";
|
||
|
|
||
|
while(i+3 <= s) {
|
||
|
bbb = (b[i++] & 0xff) << 16;
|
||
|
bbb |= (b[i++] & 0xff) << 8;
|
||
|
bbb |= b[i++] & 0xff;
|
||
|
res += char64[(bbb & 0xfc0000) >> 18] + char64[(bbb & 0x3f000) >> 12] + char64[(bbb & 0xfc0) >> 6] + char64[bbb & 0x3f];
|
||
|
}
|
||
|
if(s - i == 2) {
|
||
|
bbb = ((b[i++] & 0xff) << 16) | ((b[i++] & 0xff) << 8);
|
||
|
res += char64[(bbb & 0xfc0000) >> 18] + char64[(bbb & 0x3f000) >> 12] + char64[(bbb & 0xfc0) >> 6] + "=";
|
||
|
} else if(s - i == 1) {
|
||
|
bbb = ((b[i] & 0xff) << 16);
|
||
|
res += char64[(bbb & 0xfc0000) >> 18] + char64[(bbb & 0x3f000) >> 12] + "==";
|
||
|
}
|
||
|
|
||
|
return res;
|
||
|
}
|
||
|
|
||
|
// this doesn't really enforce base64, but if it finds = on positions they
|
||
|
// shouldn't be on, this'll get sullen.
|
||
|
int * decode_base64(string b) {
|
||
|
int * res = ({ });
|
||
|
int i=0, s, next;
|
||
|
|
||
|
b = replace(b, "\n", "");
|
||
|
b = replace(b, "\r", "");
|
||
|
|
||
|
s = strlen(b);
|
||
|
|
||
|
while(i+4 <= s) {
|
||
|
res += ({ (deco(b[i]) << 2) | (deco(b[i+1]) >> 4) });
|
||
|
next = ((deco(b[i+1]) << 4) & 0xff) | (deco(b[i+2]) >> 2);
|
||
|
unless (!next && b[i+2] == '=') {
|
||
|
res += ({ next });
|
||
|
} else {
|
||
|
return res;
|
||
|
}
|
||
|
next = ((deco(b[i+2]) << 6) & 0xc0) | deco(b[i+3]);
|
||
|
unless (!next && b[i+3] == '=') {
|
||
|
res += ({ next });
|
||
|
} else {
|
||
|
return res;
|
||
|
}
|
||
|
i += 4;
|
||
|
}
|
||
|
|
||
|
return res;
|
||
|
}
|
||
|
|
||
|
#if DEBUG > 1
|
||
|
void base64_self_test() {
|
||
|
int i, j, cool;
|
||
|
string x, y, z;
|
||
|
|
||
|
for(i=0; i<10; ++i) {
|
||
|
x = "";
|
||
|
j = random(100) + 5;
|
||
|
while(j>0) {
|
||
|
x += to_string(({ 32 + random(96) }));
|
||
|
--j;
|
||
|
}
|
||
|
y = encode_base64(to_array(x));
|
||
|
z = to_string(decode_base64(y));
|
||
|
if(z == x) ++cool;
|
||
|
else {
|
||
|
P2(("uncool:\n%O !=\n%O\n", x, z));
|
||
|
P3(("base: %O\n", y))
|
||
|
P3(("strlen: %O, %O, last: %O\n", strlen(x), strlen(z), z[<1]))
|
||
|
}
|
||
|
}
|
||
|
P2(("base64_self_test: %d out of 10 successful.\n", cool));
|
||
|
}
|
||
|
#endif
|
||
|
|