316 lines
7.4 KiB
C++
316 lines
7.4 KiB
C++
/* Based on code from Dave Winer (http://www.scripting.com/midas/base64/) */
|
|
#include "precomp_wasabi_bfc.h"
|
|
#include "base64.h"
|
|
|
|
char Base64::encodingTable [64] = {
|
|
'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P',
|
|
'Q','R','S','T','U','V','W','X','Y','Z','a','b','c','d','e','f',
|
|
'g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v',
|
|
'w','x','y','z','0','1','2','3','4','5','6','7','8','9','+','/'
|
|
};
|
|
|
|
int Base64::encode(MemBlock<char> &htext, MemBlock<char> &h64, int linelength) {
|
|
/*
|
|
encode the handle. some funny stuff about linelength -- it only makes
|
|
sense to make it a multiple of 4. if it's not a multiple of 4, we make it
|
|
so (by only checking it every 4 characters.
|
|
further, if it's 0, we don't add any line breaks at all.
|
|
*/
|
|
unsigned long ixtext;
|
|
unsigned long lentext;
|
|
unsigned long origsize;
|
|
long ctremaining;
|
|
unsigned char inbuf [3] = {0}, outbuf [4] = {0};
|
|
short i;
|
|
short charsonline = 0, ctcopy;
|
|
|
|
ixtext = 0;
|
|
|
|
lentext = htext.getSize();
|
|
|
|
while (1) {
|
|
ctremaining = lentext - ixtext;
|
|
|
|
if (ctremaining <= 0)
|
|
break;
|
|
|
|
for (i = 0; i < 3; i++) {
|
|
unsigned long ix = ixtext + i;
|
|
if (ix < lentext)
|
|
inbuf [i] = *htext.getMemory(ix);
|
|
else
|
|
inbuf [i] = 0;
|
|
}
|
|
|
|
outbuf [0] = (inbuf [0] & 0xFC) >> 2;
|
|
outbuf [1] = ((inbuf [0] & 0x03) << 4) | ((inbuf [1] & 0xF0) >> 4);
|
|
outbuf [2] = ((inbuf [1] & 0x0F) << 2) | ((inbuf [2] & 0xC0) >> 6);
|
|
outbuf [3] = inbuf [2] & 0x3F;
|
|
|
|
origsize = h64.getSize();
|
|
h64.setSize(origsize + 4);
|
|
|
|
ctcopy = 4;
|
|
|
|
switch (ctremaining) {
|
|
case 1:
|
|
ctcopy = 2;
|
|
break;
|
|
case 2:
|
|
ctcopy = 3;
|
|
break;
|
|
}
|
|
|
|
for (i = 0; i < ctcopy; i++)
|
|
*h64.getMemory(origsize + i) = encodingTable[outbuf[i]];
|
|
|
|
for (i = ctcopy; i < 4; i++)
|
|
*h64.getMemory(origsize + i) = '=';
|
|
|
|
ixtext += 3;
|
|
charsonline += 4;
|
|
|
|
if (linelength > 0) { /*DW 4/8/97 -- 0 means no line breaks*/
|
|
if (charsonline >= linelength) {
|
|
charsonline = 0;
|
|
origsize = h64.getSize();
|
|
h64.setSize(origsize + 1);
|
|
*h64.getMemory() = '\n';
|
|
}
|
|
}
|
|
}
|
|
return 1;
|
|
}
|
|
int Base64::encode(MemBlock<char> &htext, MemBlock<wchar_t> &h64, int linelength) {
|
|
/*
|
|
encode the handle. some funny stuff about linelength -- it only makes
|
|
sense to make it a multiple of 4. if it's not a multiple of 4, we make it
|
|
so (by only checking it every 4 characters.
|
|
further, if it's 0, we don't add any line breaks at all.
|
|
*/
|
|
unsigned long ixtext;
|
|
unsigned long lentext;
|
|
unsigned long origsize;
|
|
long ctremaining;
|
|
unsigned char inbuf [3] = {0}, outbuf [4] = {0};
|
|
short i;
|
|
short charsonline = 0, ctcopy;
|
|
|
|
ixtext = 0;
|
|
|
|
lentext = htext.getSize();
|
|
|
|
while (1) {
|
|
ctremaining = lentext - ixtext;
|
|
|
|
if (ctremaining <= 0)
|
|
break;
|
|
|
|
for (i = 0; i < 3; i++) {
|
|
unsigned long ix = ixtext + i;
|
|
if (ix < lentext)
|
|
inbuf [i] = *htext.getMemory(ix);
|
|
else
|
|
inbuf [i] = 0;
|
|
}
|
|
|
|
outbuf [0] = (inbuf [0] & 0xFC) >> 2;
|
|
outbuf [1] = ((inbuf [0] & 0x03) << 4) | ((inbuf [1] & 0xF0) >> 4);
|
|
outbuf [2] = ((inbuf [1] & 0x0F) << 2) | ((inbuf [2] & 0xC0) >> 6);
|
|
outbuf [3] = inbuf [2] & 0x3F;
|
|
|
|
origsize = h64.getSize();
|
|
h64.setSize(origsize + 4);
|
|
|
|
ctcopy = 4;
|
|
|
|
switch (ctremaining) {
|
|
case 1:
|
|
ctcopy = 2;
|
|
break;
|
|
case 2:
|
|
ctcopy = 3;
|
|
break;
|
|
}
|
|
|
|
for (i = 0; i < ctcopy; i++)
|
|
*h64.getMemory(origsize + i) = encodingTable[outbuf[i]];
|
|
|
|
for (i = ctcopy; i < 4; i++)
|
|
*h64.getMemory(origsize + i) = '=';
|
|
|
|
ixtext += 3;
|
|
charsonline += 4;
|
|
|
|
if (linelength > 0) { /*DW 4/8/97 -- 0 means no line breaks*/
|
|
if (charsonline >= linelength) {
|
|
charsonline = 0;
|
|
origsize = h64.getSize();
|
|
h64.setSize(origsize + 1);
|
|
*h64.getMemory() = '\n';
|
|
}
|
|
}
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
|
|
int Base64::decode(MemBlock<char> &h64, MemBlock<char> &htext) {
|
|
unsigned long ixtext;
|
|
unsigned long lentext;
|
|
unsigned long origsize;
|
|
unsigned char ch;
|
|
unsigned char inbuf [4] = {0}, outbuf [4] = {0};
|
|
short i, ixinbuf;
|
|
boolean flignore;
|
|
boolean flendtext = false;
|
|
|
|
ixtext = 0;
|
|
|
|
lentext = h64.getSize();
|
|
|
|
ixinbuf = 0;
|
|
|
|
while (true) {
|
|
if (ixtext >= lentext)
|
|
break;
|
|
ch = *h64.getMemory(ixtext++);
|
|
|
|
flignore = 0;
|
|
|
|
if ((ch >= 'A') && (ch <= 'Z'))
|
|
ch = ch - 'A';
|
|
else if ((ch >= 'a') && (ch <= 'z'))
|
|
ch = ch - 'a' + 26;
|
|
else if ((ch >= '0') && (ch <= '9'))
|
|
ch = ch - '0' + 52;
|
|
else if (ch == '+')
|
|
ch = 62;
|
|
else if (ch == '=') /*no op -- can't ignore this one*/
|
|
flendtext = true;
|
|
else if (ch == '/')
|
|
ch = 63;
|
|
else
|
|
flignore = true;
|
|
|
|
if (!flignore) {
|
|
short ctcharsinbuf = 3;
|
|
boolean flbreak = false;
|
|
|
|
if (flendtext) {
|
|
if (ixinbuf == 0)
|
|
break;
|
|
|
|
if ((ixinbuf == 1) || (ixinbuf == 2))
|
|
ctcharsinbuf = 1;
|
|
else
|
|
ctcharsinbuf = 2;
|
|
|
|
ixinbuf = 3;
|
|
flbreak = 1;
|
|
}
|
|
|
|
inbuf [ixinbuf++] = ch;
|
|
|
|
if (ixinbuf == 4) {
|
|
ixinbuf = 0;
|
|
|
|
outbuf [0] = (inbuf [0] << 2) | ((inbuf [1] & 0x30) >> 4);
|
|
outbuf [1] = ((inbuf [1] & 0x0F) << 4) | ((inbuf [2] & 0x3C) >> 2);
|
|
outbuf [2] = ((inbuf [2] & 0x03) << 6) | (inbuf [3] & 0x3F);
|
|
|
|
origsize = htext.getSize();
|
|
htext.setSize(origsize + ctcharsinbuf);
|
|
|
|
for (i = 0; i < ctcharsinbuf; i++)
|
|
*htext.getMemory(origsize + i) = outbuf[i];
|
|
}
|
|
|
|
if (flbreak)
|
|
break;
|
|
}
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
int Base64::decode(MemBlock<wchar_t> &h64, MemBlock<char> &htext) {
|
|
unsigned long ixtext;
|
|
unsigned long lentext;
|
|
unsigned long origsize;
|
|
unsigned char ch;
|
|
unsigned char inbuf [4] = {0}, outbuf [4] = {0};
|
|
short i, ixinbuf;
|
|
boolean flignore;
|
|
boolean flendtext = false;
|
|
|
|
ixtext = 0;
|
|
|
|
lentext = h64.getSize();
|
|
|
|
ixinbuf = 0;
|
|
|
|
while (true) {
|
|
if (ixtext >= lentext)
|
|
break;
|
|
ch = (unsigned char)*h64.getMemory(ixtext++);
|
|
|
|
flignore = 0;
|
|
|
|
if ((ch >= 'A') && (ch <= 'Z'))
|
|
ch = ch - 'A';
|
|
else if ((ch >= 'a') && (ch <= 'z'))
|
|
ch = ch - 'a' + 26;
|
|
else if ((ch >= '0') && (ch <= '9'))
|
|
ch = ch - '0' + 52;
|
|
else if (ch == '+')
|
|
ch = 62;
|
|
else if (ch == '=') /*no op -- can't ignore this one*/
|
|
flendtext = true;
|
|
else if (ch == '/')
|
|
ch = 63;
|
|
else
|
|
flignore = true;
|
|
|
|
if (!flignore) {
|
|
short ctcharsinbuf = 3;
|
|
boolean flbreak = false;
|
|
|
|
if (flendtext) {
|
|
if (ixinbuf == 0)
|
|
break;
|
|
|
|
if ((ixinbuf == 1) || (ixinbuf == 2))
|
|
ctcharsinbuf = 1;
|
|
else
|
|
ctcharsinbuf = 2;
|
|
|
|
ixinbuf = 3;
|
|
flbreak = 1;
|
|
}
|
|
|
|
inbuf [ixinbuf++] = ch;
|
|
|
|
if (ixinbuf == 4) {
|
|
ixinbuf = 0;
|
|
|
|
outbuf [0] = (inbuf [0] << 2) | ((inbuf [1] & 0x30) >> 4);
|
|
outbuf [1] = ((inbuf [1] & 0x0F) << 4) | ((inbuf [2] & 0x3C) >> 2);
|
|
outbuf [2] = ((inbuf [2] & 0x03) << 6) | (inbuf [3] & 0x3F);
|
|
|
|
origsize = htext.getSize();
|
|
htext.setSize(origsize + ctcharsinbuf);
|
|
|
|
for (i = 0; i < ctcharsinbuf; i++)
|
|
*htext.getMemory(origsize + i) = outbuf[i];
|
|
}
|
|
|
|
if (flbreak)
|
|
break;
|
|
}
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
|