Tekkotsu Homepage
Demos
Overview
Downloads
Dev. Resources
Reference
Credits

Base64.cc

Go to the documentation of this file.
00001 #include "Base64.h"
00002 #include <iostream>
00003 
00004 /*! @file
00005  * @brief Describes base64 namespace, which holds some functions for encoding and decoding base64 data
00006  * C_Base64 - a simple base64 encoder and decoder.
00007  *
00008  *     Copyright (c) 1999, Bob Withers - bwit@pobox.com
00009  *
00010  * This code may be freely used for any purpose, either personal
00011  * or commercial, provided the authors copyright notice remains
00012  * intact.
00013  *
00014  * Enhancements by Stanley Yamane:
00015  *     - reverse lookup table for the decode function 
00016  *     - reserve string buffer space in advance
00017  *
00018  * Modified by Ethan Tira-Thompson:
00019  *     - changed Base64 class to base64 namespace
00020  *     - modified functions to work on char[] instead of strings
00021  *     - added doxygen commenting
00022  *
00023  * @author Bob Withers - bwit@pobox.com (Creator)
00024  */
00025 
00026 using namespace std;
00027 
00028 namespace base64 {
00029   static const char fillchar = '='; //!< used to mark partial words at the end
00030   static const string::size_type np = string::npos; //!< shorthand for the "no position" return code from string
00031   
00032   //! this lookup table defines the base64 encoding
00033   const string Base64Table("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/");
00034   
00035   //! Decode Table gives the index of any valid base64 character in the Base64 table]
00036   /*! 65 == A, 97 == a, 48 == 0, 43 == +, 47 == / */
00037   const string::size_type DecodeTable[] = {
00038     np,np,np,np,np,np,np,np,np,np,  // 0 - 9
00039     np,np,np,np,np,np,np,np,np,np,  //10 -19
00040     np,np,np,np,np,np,np,np,np,np,  //20 -29
00041     np,np,np,np,np,np,np,np,np,np,  //30 -39
00042     np,np,np,62,np,np,np,63,52,53,  //40 -49
00043     54,55,56,57,58,59,60,61,np,np,  //50 -59
00044     np,np,np,np,np, 0, 1, 2, 3, 4,  //60 -69
00045     5, 6, 7, 8, 9,10,11,12,13,14,  //70 -79
00046     15,16,17,18,19,20,21,22,23,24,  //80 -89
00047     25,np,np,np,np,np,np,26,27,28,  //90 -99
00048     29,30,31,32,33,34,35,36,37,38,  //100 -109
00049     39,40,41,42,43,44,45,46,47,48,  //110 -119
00050     49,50,51,np,np,np,np,np,np,np,  //120 -129
00051     np,np,np,np,np,np,np,np,np,np,  //130 -139
00052     np,np,np,np,np,np,np,np,np,np,  //140 -149
00053     np,np,np,np,np,np,np,np,np,np,  //150 -159
00054     np,np,np,np,np,np,np,np,np,np,  //160 -169
00055     np,np,np,np,np,np,np,np,np,np,  //170 -179
00056     np,np,np,np,np,np,np,np,np,np,  //180 -189
00057     np,np,np,np,np,np,np,np,np,np,  //190 -199
00058     np,np,np,np,np,np,np,np,np,np,  //200 -209
00059     np,np,np,np,np,np,np,np,np,np,  //210 -219
00060     np,np,np,np,np,np,np,np,np,np,  //220 -229
00061     np,np,np,np,np,np,np,np,np,np,  //230 -239
00062     np,np,np,np,np,np,np,np,np,np,  //240 -249
00063     np,np,np,np,np,np               //250 -256
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     //skip any extra characters at the end (e.g. newlines or spaces)
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     //count fill characters ('=')
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     //cout << "Size is " << size/4*3-fills << " with " << fills << " fills and " << data.size()-size << " extra" << endl;
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     //cerr << "base64 decode error: unexpected break" << endl;
00237     //return false;
00238   }
00239 }

Tekkotsu v5.1CVS
Generated Mon May 9 04:58:36 2016 by Doxygen 1.6.3