00001 /*------------------------------------------------------------------------------ 00002 Name: Base64.cpp 00003 Project: xmlBlaster.org 00004 Copyright: 2001-2002 Randy Charles Morin randy@kbcafe.com 00005 Comment: http://www.kbcafe.com/articles/HowTo.Base64.pdf 00006 Allowed to distribute under xmlBlasters LGPL in email 00007 from Randy Charles Morin <randy@kbcafe.com> from 2004-01-18 00008 Minor change by Marcel Ruff xmlBlaster@marcelruff.info 00009 http://www.xmlBlaster.org 00010 ------------------------------------------------------------------------------*/ 00011 #include <string> 00012 #include <vector> 00013 #include <util/Base64.h> 00014 00015 using namespace std; 00016 using namespace org::xmlBlaster::util; 00017 00018 std::string Base64::Encode(const std::vector<unsigned char> & vby) 00019 { 00020 std::string retval; 00021 if (vby.size() == 0) 00022 { 00023 return retval; 00024 } 00025 retval.reserve(vby.size()/3*4+4); 00026 for (std::vector<unsigned char>::size_type i=0;i<vby.size();i+=3) 00027 { 00028 unsigned char by1=0,by2=0,by3=0; 00029 by1 = vby[i]; 00030 if (i+1<vby.size()) 00031 { 00032 by2 = vby[i+1]; 00033 }; 00034 if (i+2<vby.size()) 00035 { 00036 by3 = vby[i+2]; 00037 } 00038 unsigned char by4=0,by5=0,by6=0,by7=0; 00039 by4 = by1>>2; 00040 by5 = ((by1&0x3)<<4)|(by2>>4); 00041 by6 = ((by2&0xf)<<2)|(by3>>6); 00042 by7 = by3&0x3f; 00043 retval += Encode(by4); 00044 retval += Encode(by5); 00045 if (i+1<vby.size()) 00046 { 00047 retval += Encode(by6); 00048 } 00049 else 00050 { 00051 retval += "="; 00052 }; 00053 if (i+2<vby.size()) 00054 { 00055 retval += Encode(by7); 00056 } 00057 else 00058 { 00059 retval += "="; 00060 } 00061 } 00062 return retval; 00063 } 00064 00065 std::vector<unsigned char> Base64::Decode(const std::string & _str) 00066 { 00067 std::string str; 00068 for (std::string::size_type j=0;j<_str.length();j++) 00069 { 00070 if (IsBase64(_str[j])) 00071 { 00072 str += _str[j]; 00073 } 00074 } 00075 std::vector<unsigned char> retval; 00076 if (str.length() == 0) 00077 { 00078 return retval; 00079 } 00080 retval.reserve(str.size()/4*3+3); 00081 for (std::string::size_type i=0;i<str.length();i+=4) 00082 { 00083 char c1='A',c2='A',c3='A',c4='A'; 00084 c1 = str[i]; 00085 if (i+1<str.length()) 00086 { 00087 c2 = str[i+1]; 00088 }; 00089 if (i+2<str.length()) 00090 { 00091 c3 = str[i+2]; 00092 }; 00093 if (i+3<str.length()) 00094 { 00095 c4 = str[i+3]; 00096 }; 00097 unsigned char by1=0,by2=0,by3=0,by4=0; 00098 by1 = Decode(c1); 00099 by2 = Decode(c2); 00100 by3 = Decode(c3); 00101 by4 = Decode(c4); 00102 retval.push_back( (by1<<2)|(by2>>4) ); 00103 if (c3 != '=') 00104 { 00105 retval.push_back( ((by2&0xf)<<4)|(by3>>2) ); 00106 } 00107 if (c4 != '=') 00108 { 00109 retval.push_back( ((by3&0x3)<<6)|by4 ); 00110 } 00111 } 00112 return retval; 00113 } 00114 00115 00116 #ifdef BASE64_MAIN 00117 // For testing only 00118 // g++ -Wall -g -o Base64 Base64.cpp -DBASE64_MAIN=1 -I../ 00119 #include <iostream> 00120 #include <fstream> 00121 static void inout(char * szFilename); 00122 00123 int main(int argc, char* argv[]) 00124 { 00125 if (argc != 2) 00126 std::cerr << "Usage: base64 [file]" << std::endl; 00127 inout(argv[1]); 00128 return 0; 00129 } 00130 00131 void inout(char * szFilename) 00132 { 00133 std::vector<unsigned char> vby1; 00134 00135 { // Read the given file ... 00136 std::ifstream infile; 00137 infile.open(szFilename, std::ios::binary); //std::ios::in+std::ios::binary); 00138 if (!infile.is_open()) 00139 { 00140 std::cerr << "File not open!"; 00141 return; 00142 } 00143 infile >> std::noskipws; 00144 unsigned char uc; 00145 while (true) 00146 { 00147 infile >> uc; 00148 if (!infile.eof()) 00149 { 00150 vby1.push_back(uc); 00151 } 00152 else 00153 { 00154 break; 00155 } 00156 } 00157 std::cout << "File length is " << vby1.size() << std::endl; 00158 } 00159 00160 // Encode the file content ... 00161 std::vector<unsigned char>::iterator j; 00162 std::string str = Base64::Encode(vby1); 00163 std::cout << "Interim" << std::endl; 00164 std::cout << str << std::endl << std::endl; 00165 00166 { // Dump encoding to file ... 00167 std::ofstream outfile; 00168 std::string strOutfile = szFilename; 00169 strOutfile += ".b64"; 00170 outfile.open(strOutfile.c_str(), std::ios::binary); // std::ios::out+std::ios::binary); 00171 if (!outfile.is_open()) 00172 { 00173 std::cerr << "File not open!"; 00174 return; 00175 } 00176 outfile << str; 00177 std::cout << "Dumped encoding to file " << strOutfile << std::endl; 00178 } 00179 00180 // decode back again and test the cycle ... 00181 std::vector<unsigned char> vby2; 00182 vby2 = Base64::Decode(str); 00183 std::vector<unsigned char>::iterator k; 00184 int i=1; 00185 j = vby2.begin(); 00186 k = vby1.begin(); 00187 if (vby1.size() != vby2.size()) 00188 { 00189 std::cerr << "Error in size " << vby1.size() << " " << vby2.size() << std::endl; 00190 return; 00191 } 00192 for (;j!=vby2.end();j++,k++,i++) 00193 { 00194 if (*j != *k) 00195 { 00196 std::cerr << "Error in translation " << i << std::endl; 00197 return; 00198 } 00199 } 00200 /* 00201 { 00202 std::ofstream outfile; 00203 std::string strOutfile = szFilename; 00204 strOutfile += ".bak"; 00205 outfile.open(strOutfile.c_str(), std::ios::binary); // std::ios::out+std::ios::binary); 00206 if (!outfile.is_open()) 00207 { 00208 std::cerr << "File not open!"; 00209 return; 00210 } 00211 unsigned char uc; 00212 j = vby2.begin(); 00213 for (;j!=vby2.end();j++) 00214 { 00215 uc = *j; 00216 outfile << uc; 00217 } 00218 } 00219 */ 00220 std::cout << "Success, test OK" << std::endl; 00221 return; 00222 } 00223 #endif // BASE64_MAIN 00224