base64.cc
00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013 #include "base64.h"
00014 #include <string>
00015 #include <iterator>
00016
00017 #define TRUE 1
00018 #define FALSE 0
00019
00020 #define LINELEN 72
00021
00022 typedef unsigned char byte;
00023
00024 static byte dtable[256];
00025
00026 static int errcheck = TRUE;
00027
00028
00029
00030
00031 class base64_input
00032 {
00033 std::string::const_iterator begin, end;
00034 public:
00035 base64_input(const std::string &input)
00036 : begin(input.begin()), end(input.end()) {}
00037
00038 int operator()()
00039 {
00040 if (begin == end) {
00041 return EOF;
00042 }
00043 return *begin++;
00044 }
00045 };
00046
00047
00048
00049
00050
00051 class base64_output
00052 {
00053 std::back_insert_iterator<std::string> insert;
00054 int linelength;
00055
00056 public:
00057 base64_output(std::string &output)
00058 : insert(back_inserter(output)),
00059 linelength(0)
00060 {}
00061
00062 void operator()(int c)
00063 {
00064 if (linelength >= LINELEN) {
00065 *insert++ = '\n';
00066 *insert++ = ' ';
00067 linelength = 0;
00068 }
00069 *insert++ = (unsigned char) c;
00070 linelength++;
00071 }
00072 };
00073
00074
00075
00076 static bool encode(base64_input &inchar, base64_output &ochar)
00077 {
00078 int i, hiteof = FALSE;
00079
00080
00081
00082 for (i = 0; i < 26; i++) {
00083 dtable[i] = 'A' + i;
00084 dtable[26 + i] = 'a' + i;
00085 }
00086 for (i = 0; i < 10; i++) {
00087 dtable[52 + i] = '0' + i;
00088 }
00089 dtable[62] = '+';
00090 dtable[63] = '/';
00091
00092 while (!hiteof) {
00093 byte igroup[3], ogroup[4];
00094 int c, n;
00095
00096 igroup[0] = igroup[1] = igroup[2] = 0;
00097 for (n = 0; n < 3; n++) {
00098 c = inchar();
00099 if (c == EOF) {
00100 hiteof = TRUE;
00101 break;
00102 }
00103 igroup[n] = (byte) c;
00104 }
00105 if (n > 0) {
00106 ogroup[0] = dtable[igroup[0] >> 2];
00107 ogroup[1] = dtable[((igroup[0] & 3) << 4) | (igroup[1] >> 4)];
00108 ogroup[2] = dtable[((igroup[1] & 0xF) << 2) | (igroup[2] >> 6)];
00109 ogroup[3] = dtable[igroup[2] & 0x3F];
00110
00111
00112
00113
00114
00115 if (n < 3) {
00116 ogroup[3] = '=';
00117 if (n < 2) {
00118 ogroup[2] = '=';
00119 }
00120 }
00121 for (i = 0; i < 4; i++) {
00122 ochar(ogroup[i]);
00123 }
00124 }
00125 }
00126 return true;
00127 }
00128
00129
00130
00131 static int insig(base64_input &inchar)
00132 {
00133 int c;
00134
00135
00136 while (TRUE) {
00137 c = inchar();
00138 if (c == EOF || (c > ' ')) {
00139 return c;
00140 }
00141 }
00142
00143 }
00144
00145
00146
00147 static bool decode(base64_input &inchar, base64_output &ochar)
00148 {
00149 int i;
00150
00151 for (i = 0; i < 255; i++) {
00152 dtable[i] = 0x80;
00153 }
00154 for (i = 'A'; i <= 'Z'; i++) {
00155 dtable[i] = 0 + (i - 'A');
00156 }
00157 for (i = 'a'; i <= 'z'; i++) {
00158 dtable[i] = 26 + (i - 'a');
00159 }
00160 for (i = '0'; i <= '9'; i++) {
00161 dtable[i] = 52 + (i - '0');
00162 }
00163 dtable[(int)'+'] = 62;
00164 dtable[(int)'/'] = 63;
00165 dtable[(int)'='] = 0;
00166
00167
00168 while (TRUE) {
00169 byte a[4], b[4], o[3];
00170
00171 for (i = 0; i < 4; i++) {
00172 int c = insig(inchar);
00173
00174 if (c == EOF) {
00175
00176 return false;
00177 }
00178 if (dtable[c] & 0x80) {
00179 if (errcheck) {
00180
00181 return false;
00182 }
00183
00184 i--;
00185 continue;
00186 }
00187 a[i] = (byte) c;
00188 b[i] = (byte) dtable[c];
00189 }
00190 o[0] = (b[0] << 2) | (b[1] >> 4);
00191 o[1] = (b[1] << 4) | (b[2] >> 2);
00192 o[2] = (b[2] << 6) | b[3];
00193 i = a[2] == '=' ? 1 : (a[3] == '=' ? 2 : 3);
00194 for (int w = 0; w < i; w++ )
00195 ochar(o[w]);
00196 if (i < 3) {
00197 return true;
00198 }
00199 }
00200 }
00201
00202
00203 bool base64_encode(const std::string &in, std::string &out)
00204 {
00205 out.clear();
00206 base64_input input(in);
00207 base64_output output(out);
00208 return encode(input, output);
00209 }
00210
00211 bool base64_decode(const std::string &in, std::string &out)
00212 {
00213 out.clear();
00214 base64_input input(in);
00215 base64_output output(out);
00216 return decode(input, output);
00217 }
00218
00219
00220 #ifdef __TEST_MODE__
00221
00222 #include <iostream>
00223 using namespace std;
00224
00225
00226
00227 int main()
00228 {
00229 string test = "This is a test.", encoded, decoded;
00230 base64_encode(test, encoded);
00231 base64_decode(encoded, decoded);
00232 if( test != decoded )
00233 cerr << "Test failed" << endl;
00234 else
00235 cerr << "Success" << endl;
00236 }
00237
00238 #endif
00239