1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189
|
/*
* Worldvisions Weaver Software:
* Copyright (C) 1997-2002 Net Integration Technologies, Inc.
*
* Functions for encoding and decoding strings in MIME's Base64 notation.
*
* Base 64 is pretty easy. The input is processed in groups of three bytes.
* These 24 bits are split into 4 groups of 6 bits. Each group of six bits
* is represented by one character in the base64 alphabet, in the encoded
* output. The alphabet is as follows:
* ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=
* Where 'A' through '/' represent 000000 through 011111, the 64 different
* combinations. The '=' (100000) is padding and has no value when decoded.
*/
#include "wvbase64.h"
// maps codes to the Base64 alphabet
static char alphabet[67] =
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=\n";
// finds codes in the Base64 alphabet
static int lookup(char ch)
{
if (ch >= 'A' && ch <= 'Z')
return ch - 'A';
if (ch >= 'a' && ch <= 'z')
return ch - 'a' + 26;
if (ch >= '0' && ch <= '9')
return ch - '0' + 52;
if (ch == '+')
return 62;
if (ch == '/')
return 63;
if (ch == '=')
return 64; // padding
if (ch == '\n' || ch == ' ' || ch == '\r' || ch == '\t' ||
ch == '\f' || ch == '\v')
return 65; // whitespace
return -1;
}
/***** WvBase64Encoder *****/
WvBase64Encoder::WvBase64Encoder()
{
_reset();
}
bool WvBase64Encoder::_reset()
{
state = ATBIT0;
bits = 0;
return true;
}
bool WvBase64Encoder::_encode(WvBuf &in, WvBuf &out, bool flush)
{
// base 64 encode the entire buffer
while (in.used() != 0)
{
unsigned char next = in.getch();
bits = (bits << 8) | next;
switch (state)
{
case ATBIT0:
out.putch(alphabet[bits >> 2]);
bits &= 0x03;
state = ATBIT2;
break;
case ATBIT2:
out.putch(alphabet[bits >> 4]);
bits &= 0x0f;
state = ATBIT4;
break;
case ATBIT4:
out.putch(alphabet[bits >> 6]);
out.putch(alphabet[bits & 0x3f]);
bits = 0;
state = ATBIT0;
break;
}
}
// do not consider the data flushed if we need padding
if (flush && state != ATBIT0)
return false;
return true;
}
bool WvBase64Encoder::_finish(WvBuf &out)
{
// pad text if needed
switch (state)
{
case ATBIT2:
out.putch(alphabet[bits << 4]);
out.putch('=');
out.putch('=');
break;
case ATBIT4:
out.putch(alphabet[bits << 2]);
out.putch('=');
break;
case ATBIT0:
break;
}
return true;
}
/***** WvBase64Decoder *****/
WvBase64Decoder::WvBase64Decoder()
{
_reset();
}
bool WvBase64Decoder::_reset()
{
state = ATBIT0;
bits = 0;
return true;
}
bool WvBase64Decoder::_encode(WvBuf &in, WvBuf &out, bool flush)
{
// base 64 decode the entire buffer
while (in.used() != 0)
{
unsigned char next = in.getch();
int symbol = lookup(next);
switch (symbol)
{
case -1: // invalid character
seterror("invalid character '%s' in base64 input", next);
return false;
case 64: // padding
// strip out any remaining padding
// we are lenient in that we do not track how much padding we skip
setfinished();
state = PAD;
break;
case 65: // whitespace
break;
default: // other symbol
bits = (bits << 6) | symbol;
switch (state)
{
case ATBIT0:
state = ATBIT2;
break;
case ATBIT2:
out.putch(bits >> 4);
bits &= 0x0f;
state = ATBIT4;
break;
case ATBIT4:
out.putch(bits >> 2);
bits &= 0x03;
state = ATBIT6;
break;
case ATBIT6:
out.putch(bits);
bits = 0;
state = ATBIT0;
break;
case PAD:
seterror("invalid character '%s' "
"after base64 padding", next);
return false;
}
break;
}
}
// if flushing and we did not get sufficient padding, then fail
if (flush && (state == ATBIT2 || state == ATBIT4 || state == ATBIT6))
return false; // insufficient padding to flush!
return true;
}
|