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