You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
128 lines
4.1 KiB
128 lines
4.1 KiB
2 months ago
|
/*
|
||
|
* UCW Library -- Base 64 Encoding & Decoding
|
||
|
*
|
||
|
* (c) 2002, Robert Spalek <robert@ucw.cz>
|
||
|
* (c) 2018, Pavel Charvat <pchar@ucw.cz>
|
||
|
*
|
||
|
* This software may be freely distributed and used according to the terms
|
||
|
* of the GNU Lesser General Public License.
|
||
|
*/
|
||
|
|
||
|
#undef LOCAL_DEBUG
|
||
|
|
||
|
#include <ucw/lib.h>
|
||
|
#include <ucw/base64.h>
|
||
|
|
||
|
const byte base64_enc_table[65] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
||
|
const byte base64_dec_table[256] = {
|
||
|
0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
|
||
|
0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
|
||
|
0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x3e, 0x80, 0x80, 0x80, 0x3f,
|
||
|
0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x80, 0x80, 0x80, 0x40, 0x80, 0x80,
|
||
|
0x80, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e,
|
||
|
0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x80, 0x80, 0x80, 0x80, 0x80,
|
||
|
0x80, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28,
|
||
|
0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33, 0x80, 0x80, 0x80, 0x80, 0x80,
|
||
|
0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
|
||
|
0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
|
||
|
0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
|
||
|
0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
|
||
|
0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
|
||
|
0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
|
||
|
0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
|
||
|
0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
|
||
|
};
|
||
|
|
||
|
uint base64_encode(byte *dest, const byte *src, uint len)
|
||
|
{
|
||
|
const byte *ptr = src;
|
||
|
const byte *end = src + len;
|
||
|
byte *out = dest;
|
||
|
|
||
|
/* keep going until we have less than 24 bits */
|
||
|
if (end - ptr >= 3)
|
||
|
for (const byte *x = end - 2; ptr < x; )
|
||
|
{
|
||
|
out[0] = base64_enc_table[ptr[0] >> 2];
|
||
|
out[1] = base64_enc_table[((ptr[0] & 0x03) << 4) + (ptr[1] >> 4)];
|
||
|
out[2] = base64_enc_table[((ptr[1] & 0x0f) << 2) + (ptr[2] >> 6)];
|
||
|
out[3] = base64_enc_table[ptr[2] & 0x3f];
|
||
|
out += 4;
|
||
|
ptr += 3;
|
||
|
}
|
||
|
|
||
|
/* now deal with the tail end of things */
|
||
|
if (ptr != end)
|
||
|
{
|
||
|
out[0] = base64_enc_table[ptr[0] >> 2];
|
||
|
out[3] = BASE64_PADDING;
|
||
|
if (end - ptr >= 2)
|
||
|
{
|
||
|
out[1] = base64_enc_table[((ptr[0] & 0x03) << 4) + (ptr[1] >> 4)];
|
||
|
out[2] = base64_enc_table[(ptr[1] & 0x0f) << 2];
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
out[1] = base64_enc_table[(ptr[0] & 0x03) << 4];
|
||
|
out[2] = BASE64_PADDING;
|
||
|
}
|
||
|
out += 4;
|
||
|
}
|
||
|
|
||
|
return out - dest;
|
||
|
}
|
||
|
|
||
|
uint base64_decode(byte *dest, const byte *src, uint len)
|
||
|
{
|
||
|
const byte *ptr = src;
|
||
|
const byte *end = src + len;
|
||
|
byte *out = dest;
|
||
|
while (1)
|
||
|
{
|
||
|
uint val, ch;
|
||
|
do
|
||
|
{
|
||
|
if (ptr == end || (ch = base64_dec_table[*ptr++]) == BASE64_DEC_PADDING)
|
||
|
goto end;
|
||
|
}
|
||
|
while (ch > BASE64_DEC_PADDING);
|
||
|
val = ch;
|
||
|
do
|
||
|
{
|
||
|
if (ptr == end || (ch = base64_dec_table[*ptr++]) == BASE64_DEC_PADDING)
|
||
|
goto end; // Broken base64 encoding, we only have 6 bits
|
||
|
}
|
||
|
while (ch > BASE64_DEC_PADDING);
|
||
|
val = (val << 6) | ch;
|
||
|
do
|
||
|
{
|
||
|
if (ptr == end || (ch = base64_dec_table[*ptr++]) == BASE64_DEC_PADDING)
|
||
|
{
|
||
|
out[0] = val >> 4;
|
||
|
out += 1;
|
||
|
goto end;
|
||
|
}
|
||
|
}
|
||
|
while (ch > BASE64_DEC_PADDING);
|
||
|
val = (val << 6) | ch;
|
||
|
do
|
||
|
{
|
||
|
if (ptr == end || (ch = base64_dec_table[*ptr++]) == BASE64_DEC_PADDING)
|
||
|
{
|
||
|
out[0] = val >> 10;
|
||
|
out[1] = val >> 2;
|
||
|
out += 2;
|
||
|
goto end;
|
||
|
}
|
||
|
}
|
||
|
while (ch > BASE64_DEC_PADDING);
|
||
|
val = (val << 6) | ch;
|
||
|
out[0] = val >> 16;
|
||
|
out[1] = val >> 8;
|
||
|
out[2] = val;
|
||
|
out += 3;
|
||
|
}
|
||
|
end:
|
||
|
return out - dest;
|
||
|
}
|