00001 #include "Base64.h"
00002 #include <iostream>
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032 using namespace std;
00033
00034 namespace base64 {
00035 static const char fillchar = '=';
00036 static const string::size_type np = string::npos;
00037
00038
00039 const string Base64Table("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/");
00040
00041
00042
00043 const string::size_type DecodeTable[] = {
00044 np,np,np,np,np,np,np,np,np,np,
00045 np,np,np,np,np,np,np,np,np,np,
00046 np,np,np,np,np,np,np,np,np,np,
00047 np,np,np,np,np,np,np,np,np,np,
00048 np,np,np,62,np,np,np,63,52,53,
00049 54,55,56,57,58,59,60,61,np,np,
00050 np,np,np,np,np, 0, 1, 2, 3, 4,
00051 5, 6, 7, 8, 9,10,11,12,13,14,
00052 15,16,17,18,19,20,21,22,23,24,
00053 25,np,np,np,np,np,np,26,27,28,
00054 29,30,31,32,33,34,35,36,37,38,
00055 39,40,41,42,43,44,45,46,47,48,
00056 49,50,51,np,np,np,np,np,np,np,
00057 np,np,np,np,np,np,np,np,np,np,
00058 np,np,np,np,np,np,np,np,np,np,
00059 np,np,np,np,np,np,np,np,np,np,
00060 np,np,np,np,np,np,np,np,np,np,
00061 np,np,np,np,np,np,np,np,np,np,
00062 np,np,np,np,np,np,np,np,np,np,
00063 np,np,np,np,np,np,np,np,np,np,
00064 np,np,np,np,np,np,np,np,np,np,
00065 np,np,np,np,np,np,np,np,np,np,
00066 np,np,np,np,np,np,np,np,np,np,
00067 np,np,np,np,np,np,np,np,np,np,
00068 np,np,np,np,np,np,np,np,np,np,
00069 np,np,np,np,np,np
00070 };
00071
00072
00073 string encode(char buf[], unsigned int len) {
00074 string ret;
00075 if(len==0)
00076 return "";
00077 ret.reserve((len-1)/3*4 + 4 + 1);
00078
00079 for (string::size_type i = 0; i < len; ++i)
00080 {
00081 char c;
00082 c = (buf[i] >> 2) & 0x3f;
00083 ret.append(1, Base64Table[c]);
00084 c = (buf[i] << 4) & 0x3f;
00085 if (++i < len)
00086 c |= (buf[i] >> 4) & 0x0f;
00087
00088 ret.append(1, Base64Table[c]);
00089 if (i < len)
00090 {
00091 c = (buf[i] << 2) & 0x3f;
00092 if (++i < len)
00093 c |= (buf[i] >> 6) & 0x03;
00094
00095 ret.append(1, Base64Table[c]);
00096 }
00097 else
00098 {
00099 ++i;
00100 ret.append(1, fillchar);
00101 }
00102
00103 if (i < len)
00104 {
00105 c = buf[i] & 0x3f;
00106 ret.append(1, Base64Table[c]);
00107 }
00108 else
00109 {
00110 ret.append(1, fillchar);
00111 }
00112 }
00113
00114 return(ret);
00115 }
00116
00117 unsigned int decodeSize(const std::string& data) {
00118 unsigned int fills=0;
00119 unsigned int size=data.size();
00120
00121 while(size>0 && DecodeTable[(unsigned char)data[size-1]]==np && data[size-1]!=fillchar)
00122 size--;
00123 if((size/4) * 4 != size) {
00124 cerr << "base 64 decodeSize error: data size is not multiple of 4" << endl;
00125 return size/4*3 + 3;
00126 }
00127
00128 while(fills<size && data[size-fills-1]==fillchar)
00129 fills++;
00130 if(fills>2) {
00131 cerr << "base 64 decodeSize error: too many fill characters";
00132 size-=(fills/3) * 3;
00133 fills=fills%3;
00134 }
00135
00136 return size/4*3-fills;
00137 }
00138 char* decode(const std::string& data) {
00139 unsigned int len=decodeSize(data);
00140 char * buf = new char[len];
00141 if(!decode(data,buf,len)) {
00142 delete [] buf;
00143 return NULL;
00144 }
00145 return buf;
00146 }
00147 bool decode(const std::string& data, char buf[], unsigned int len) {
00148 const string::size_type size = data.length();
00149 string::size_type i = 0, p=0;
00150 while(true)
00151 {
00152 bool retry=false;
00153 string::size_type d=np;
00154 do {
00155 d=DecodeTable[(unsigned char)data[i++]];
00156 retry=false;
00157 if(d==np) {
00158 if(fillchar == data[i-1]) {
00159 cerr << "base64 decode error: unexpected fill char -- offset read?" << endl;
00160 return false;
00161 }
00162 if(!isspace(data[i-1])) {
00163 cerr << "base 64 decode error: illegal character '" << data[i-1] << '\'' << endl;
00164 return false;
00165 }
00166 retry=true;
00167 }
00168 } while(retry);
00169 char c = (char) d;
00170
00171 do {
00172 d=DecodeTable[(unsigned char)data[i++]];
00173 retry=false;
00174 if(d==np) {
00175 if(fillchar == data[i-1]) {
00176 cerr << "base64 decode error: unexpected fill char -- offset read?" << endl;
00177 return false;
00178 }
00179 if(!isspace(data[i-1])) {
00180 cerr << "base 64 decode error: illegal character '" << data[i-1] << '\'' << endl;
00181 return false;
00182 }
00183 retry=true;
00184 }
00185 } while(retry);
00186 if(p>=len)
00187 return false;
00188 char c1 = (char) d;
00189 c = (c << 2) | ((c1 >> 4) & 0x3);
00190 buf[p++]=c;
00191 if(i>=size) {
00192 cerr << "base64 decode error: Truncated data" << endl;
00193 return false;
00194 }
00195
00196 do {
00197 d=DecodeTable[(unsigned char)data[i++]];
00198 retry=false;
00199 if(d==np) {
00200 if(fillchar == data[i-1]) {
00201 return true;
00202 }
00203 if(!isspace(data[i-1])) {
00204 cerr << "base 64 decode error: illegal character '" << data[i-1] << '\'' << endl;
00205 return false;
00206 }
00207 retry=true;
00208 }
00209 } while(retry);
00210 if(p>=len)
00211 return false;
00212 c = (char) d;
00213 c1 = ((c1 << 4) & 0xf0) | ((c >> 2) & 0xf);
00214 buf[p++]=c1;
00215 if(i>=size) {
00216 cerr << "base64 decode error: Truncated data" << endl;
00217 return false;
00218 }
00219
00220 do {
00221 d=DecodeTable[(unsigned char)data[i++]];
00222 retry=false;
00223 if(d==np) {
00224 if(fillchar == data[i-1]) {
00225 return true;
00226 }
00227 if(!isspace(data[i-1])) {
00228 cerr << "base 64 decode error: illegal character '" << data[i-1] << '\'' << endl;
00229 return false;
00230 }
00231 retry=true;
00232 }
00233 } while(retry);
00234 if(p>=len)
00235 return false;
00236 c1 = (char) d;
00237 c = ((c << 6) & 0xc0) | c1;
00238 buf[p++]=c;
00239 if(i==size)
00240 return true;
00241 }
00242
00243
00244 }
00245 }