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  * $Author: ejt $
00026  * $Name: tekkotsu-4_0 $
00027  * $Revision: 1.3 $
00028  * $State: Exp $
00029  * $Date: 2005/08/07 04:11:03 $
00030  */
00031 
00032 using namespace std;
00033 
00034 namespace base64 {
00035   static const char fillchar = '='; //!< used to mark partial words at the end
00036   static const string::size_type np = string::npos; //!< shorthand for the "no position" return code from string
00037   
00038   //! this lookup table defines the base64 encoding
00039   const string Base64Table("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/");
00040   
00041   //! Decode Table gives the index of any valid base64 character in the Base64 table]
00042   /*! 65 == A, 97 == a, 48 == 0, 43 == +, 47 == / */
00043   const string::size_type DecodeTable[] = {
00044     np,np,np,np,np,np,np,np,np,np,  // 0 - 9
00045     np,np,np,np,np,np,np,np,np,np,  //10 -19
00046     np,np,np,np,np,np,np,np,np,np,  //20 -29
00047     np,np,np,np,np,np,np,np,np,np,  //30 -39
00048     np,np,np,62,np,np,np,63,52,53,  //40 -49
00049     54,55,56,57,58,59,60,61,np,np,  //50 -59
00050     np,np,np,np,np, 0, 1, 2, 3, 4,  //60 -69
00051     5, 6, 7, 8, 9,10,11,12,13,14,  //70 -79
00052     15,16,17,18,19,20,21,22,23,24,  //80 -89
00053     25,np,np,np,np,np,np,26,27,28,  //90 -99
00054     29,30,31,32,33,34,35,36,37,38,  //100 -109
00055     39,40,41,42,43,44,45,46,47,48,  //110 -119
00056     49,50,51,np,np,np,np,np,np,np,  //120 -129
00057     np,np,np,np,np,np,np,np,np,np,  //130 -139
00058     np,np,np,np,np,np,np,np,np,np,  //140 -149
00059     np,np,np,np,np,np,np,np,np,np,  //150 -159
00060     np,np,np,np,np,np,np,np,np,np,  //160 -169
00061     np,np,np,np,np,np,np,np,np,np,  //170 -179
00062     np,np,np,np,np,np,np,np,np,np,  //180 -189
00063     np,np,np,np,np,np,np,np,np,np,  //190 -199
00064     np,np,np,np,np,np,np,np,np,np,  //200 -209
00065     np,np,np,np,np,np,np,np,np,np,  //210 -219
00066     np,np,np,np,np,np,np,np,np,np,  //220 -229
00067     np,np,np,np,np,np,np,np,np,np,  //230 -239
00068     np,np,np,np,np,np,np,np,np,np,  //240 -249
00069     np,np,np,np,np,np               //250 -256
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     //skip any extra characters at the end (e.g. newlines or spaces)
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     //count fill characters ('=')
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     //cout << "Size is " << size/4*3-fills << " with " << fills << " fills and " << data.size()-size << " extra" << endl;
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     //cerr << "base64 decode error: unexpected break" << endl;
00243     //return false;
00244   }
00245 }

Tekkotsu v4.0
Generated Thu Nov 22 00:54:51 2007 by Doxygen 1.5.4