psyced/world/net/library/base64.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