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