00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015 #include "wvbase64.h"
00016
00017
00018 static char alphabet[67] =
00019 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=\n";
00020
00021
00022 static int lookup(char ch)
00023 {
00024 if (ch >= 'A' && ch <= 'Z')
00025 return ch - 'A';
00026 if (ch >= 'a' && ch <= 'z')
00027 return ch - 'a' + 26;
00028 if (ch >= '0' && ch <= '9')
00029 return ch - '0' + 52;
00030 if (ch == '+')
00031 return 62;
00032 if (ch == '/')
00033 return 63;
00034 if (ch == '=')
00035 return 64;
00036 if (ch == '\n' || ch == ' ' || ch == '\r' || ch == '\t' ||
00037 ch == '\f' || ch == '\v')
00038 return 65;
00039 return -1;
00040 }
00041
00042
00043
00044
00045 WvBase64Encoder::WvBase64Encoder()
00046 {
00047 _reset();
00048 }
00049
00050
00051 bool WvBase64Encoder::_reset()
00052 {
00053 state = ATBIT0;
00054 bits = 0;
00055 return true;
00056 }
00057
00058
00059 bool WvBase64Encoder::_encode(WvBuf &in, WvBuf &out, bool flush)
00060 {
00061
00062 while (in.used() != 0)
00063 {
00064 unsigned char next = in.getch();
00065 bits = (bits << 8) | next;
00066 switch (state)
00067 {
00068 case ATBIT0:
00069 out.putch(alphabet[bits >> 2]);
00070 bits &= 0x03;
00071 state = ATBIT2;
00072 break;
00073 case ATBIT2:
00074 out.putch(alphabet[bits >> 4]);
00075 bits &= 0x0f;
00076 state = ATBIT4;
00077 break;
00078 case ATBIT4:
00079 out.putch(alphabet[bits >> 6]);
00080 out.putch(alphabet[bits & 0x3f]);
00081 bits = 0;
00082 state = ATBIT0;
00083 break;
00084 }
00085 }
00086
00087 if (flush && state != ATBIT0)
00088 return false;
00089 return true;
00090 }
00091
00092
00093 bool WvBase64Encoder::_finish(WvBuf &out)
00094 {
00095
00096 switch (state)
00097 {
00098 case ATBIT2:
00099 out.putch(alphabet[bits << 4]);
00100 out.putch('=');
00101 out.putch('=');
00102 break;
00103 case ATBIT4:
00104 out.putch(alphabet[bits << 2]);
00105 out.putch('=');
00106 break;
00107 case ATBIT0:
00108 break;
00109 }
00110 return true;
00111 }
00112
00113
00114
00115
00116
00117 WvBase64Decoder::WvBase64Decoder()
00118 {
00119 _reset();
00120 }
00121
00122
00123 bool WvBase64Decoder::_reset()
00124 {
00125 state = ATBIT0;
00126 bits = 0;
00127 return true;
00128 }
00129
00130
00131 bool WvBase64Decoder::_encode(WvBuf &in, WvBuf &out, bool flush)
00132 {
00133
00134 while (in.used() != 0)
00135 {
00136 unsigned char next = in.getch();
00137 int symbol = lookup(next);
00138 switch (symbol)
00139 {
00140 case -1:
00141 seterror("invalid character #%s in base64 input", next);
00142 return false;
00143
00144 case 64:
00145
00146
00147 setfinished();
00148 state = PAD;
00149 break;
00150
00151 case 65:
00152 break;
00153
00154 default:
00155 bits = (bits << 6) | symbol;
00156 switch (state)
00157 {
00158 case ATBIT0:
00159 state = ATBIT2;
00160 break;
00161 case ATBIT2:
00162 out.putch(bits >> 4);
00163 bits &= 0x0f;
00164 state = ATBIT4;
00165 break;
00166 case ATBIT4:
00167 out.putch(bits >> 2);
00168 bits &= 0x03;
00169 state = ATBIT6;
00170 break;
00171 case ATBIT6:
00172 out.putch(bits);
00173 bits = 0;
00174 state = ATBIT0;
00175 break;
00176
00177 case PAD:
00178 seterror("invalid character #%s "
00179 "after base64 padding", next);
00180 return false;
00181 }
00182 break;
00183 }
00184 }
00185
00186 if (flush && (state == ATBIT2 || state == ATBIT4 || state == ATBIT6))
00187 return false;
00188 return true;
00189 }