Base64Buffer.cpp

Go to the documentation of this file.
00001 
00002 // Filename: Base64.cpp
00003 // Author: Matt Cooper (mcooper@orionsec.com)
00004 // Last Modified 26 August 2005 Geoff Beier
00006 
00014 #include <string>
00015 #include <cstring>
00016 #include "Base64Buffer.h"
00017 #include "PKIFException.h"
00018 #include "components.h"
00019 #include "PKIFCommonErrors.h"
00020 
00021 #include "boost/numeric/conversion/cast.hpp"
00022 
00023 using boost::numeric_cast;
00024 using boost::bad_numeric_cast;
00025 
00026 using namespace std;
00027 
00028 unsigned char CBase64Buffer::m_base64chars[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
00029 unsigned int CBase64Buffer::m_bitMask[] = { 0, 1, 3, 7, 15, 31, 63, 127, 255 };
00030 int CBase64Buffer::m_decodeTable[ 256 ];
00031 static int tableBuilt = 0;
00039 CBase64Buffer::CBase64Buffer()
00040 {
00041     m_addLineBreaks = 0;
00042     m_prependChars = 0;
00043     m_addCR = true;
00044 
00045     if(!tableBuilt)
00046     {
00047         unsigned int i;
00048         for( i=0; i < 256; i++ ) 
00049             m_decodeTable[i] = -2; // Illegal digit
00050         for( i=0; i < 64; i++ )
00051         {
00052             m_decodeTable[ m_base64chars[ i ] ] = i;
00053             m_decodeTable[ m_base64chars[ i ] | 0x80 ] = i; // Ignore 8th bit
00054         }
00055 
00056         tableBuilt = 1;
00057     }
00058 }
00066 CBase64Buffer::~CBase64Buffer()
00067 {
00068     if(m_prependChars)
00069     {   delete []m_prependChars;    }
00070 }
00078 bool CBase64Buffer::encode(const unsigned char *in, 
00079                     const unsigned long inLen, 
00080                     char *out               /*Must be >= 1.5X+1 the length of in; more if adding line breaks*/, 
00081                     unsigned long *outLen   /*IN / OUT*/ )
00082 {
00083     bool rv = false;
00084     
00085     try
00086     {
00087         do
00088         {
00089             if(!out)
00090             {   break;  }
00091 
00092             if(!outLen)
00093             {   break;  }
00094 
00095             if(!in)
00096             {   break;  }
00097 
00098             if(!inLen)
00099             {   break;  }
00100 
00101             {
00102                 double din = inLen, dout = *outLen;
00103                 double encCount = ((din * 1.5)+1); // +1 for null
00104                 if( (dout < encCount) || 
00105                     (m_addLineBreaks && (dout < (encCount + ((encCount/76) * 2)))))
00106                 {   break;  }
00107             }
00108 
00109             unsigned long tmp, bitsLeft = 0, tmpBits = 0, bitCount = 6, digit = 0, charCount = 0;
00110             char *o = out, *pre;
00111             const unsigned char *end = in + inLen;
00112 
00115 
00116             while( ( in < end ) && ( bitsLeft < bitCount ) ) 
00117             {
00118                 tmp = *in;
00119                 in++;
00120 
00121                 tmpBits <<= 8;
00122                 tmpBits |= (tmp & 0xff);
00123                 bitsLeft += 8;
00124             }
00125 
00126             if( bitsLeft < bitCount )
00127             {
00128                 tmp = tmpBits << ( bitCount - bitsLeft );
00129                 digit = tmp & m_bitMask[bitCount];
00130                 bitCount = bitsLeft;
00131                 bitsLeft = 0;
00132             }
00133             else
00134             {
00135                 tmp = tmpBits >> ( bitsLeft - bitCount );
00136                 digit = tmp & m_bitMask[bitCount];
00137                 bitsLeft -= bitCount;
00138             }
00139             
00142 
00143             if(m_addLineBreaks && m_prependChars)
00144             {
00145                 pre = m_prependChars;
00146                 while(*pre){ *o++ = *pre; pre++; }
00147             }
00148             
00151 
00152             while( bitCount > 0 )
00153             {
00154                 *o++ = m_base64chars[ (int)digit ];
00155 
00156                 charCount++;
00157 
00158                 if(m_addLineBreaks && !(charCount % m_addLineBreaks))
00159                 {
00160                     if(m_addCR){ *o++ = '\r'; }
00161                     *o++ = '\n';
00162 
00163                     if(m_prependChars)
00164                     {
00165                         pre = m_prependChars;
00166                         while(*pre){ *o++ = *pre; pre++; }
00167                     }
00168                 }
00169 
00172 
00173                 while( ( in < end ) && ( bitsLeft < bitCount ) ) 
00174                 {
00175                     tmp = *in;
00176                     in++;
00177 
00178                     tmpBits <<= 8;
00179                     tmpBits |= (tmp & 0xff);
00180                     bitsLeft += 8;
00181                 }
00182 
00183                 if( bitsLeft < bitCount ) 
00184                 {
00185                     tmp = tmpBits << ( bitCount - bitsLeft );
00186                     digit = tmp & m_bitMask[bitCount];
00187                     bitCount = bitsLeft;
00188                     bitsLeft = 0;
00189                 } 
00190                 else 
00191                 {
00192                     tmp = tmpBits >> ( bitsLeft - bitCount );
00193                     digit = tmp & m_bitMask[bitCount];
00194                     bitsLeft -= bitCount;
00195                 }
00196                 
00199             }
00200 
00201             // Pad with '='
00202             while( charCount && (charCount % 4 != 0) )
00203             {
00204                 *o++ = '=';
00205                 charCount++;
00206             }
00207 
00208             *o++ = 0;
00209 
00210             unsigned long tmpLen = 0;
00211             try 
00212             {
00213                 tmpLen = numeric_cast<unsigned long>(o - out);
00214             }
00215             catch(bad_numeric_cast &) 
00216             {
00217                 throw CPKIFException(TOOLKIT_PATH, COMMON_INVALID_INPUT, "Distance is an impossibly long number.");
00218             }
00219             *outLen = tmpLen - 1; // extra 1 for the null
00220 
00221             rv = true;
00222         }
00223         while(0);
00224 
00225     }
00226     catch(...){};
00227 
00228     return rv;
00229 }
00230 
00231 // The size of the output buffer must not be less than 3/4 the size of the input buffer.
00241 bool CBase64Buffer::decode( const char *in, const unsigned long inLen, unsigned char *out, unsigned long *outLen /*IN / OUT*/ )
00242 {
00243     bool rv = false;
00244     
00245     try
00246     {
00247         do
00248         {
00249 
00250             if(!out)
00251             {   break;  }
00252 
00253             if(!outLen)
00254             {   break;  }
00255 
00256             if(!in)
00257             {   break;  }
00258 
00259             if(!inLen)
00260             {   break;  }
00261 
00262             unsigned long c, lp, tmpBits = 0, bitsLeft = 0;
00263             unsigned char *outp = out;
00264             int digit;
00265             
00266             for( lp = 0; lp < inLen; lp++ )
00267             {
00268                 c = *in++;
00269                 digit = m_decodeTable[ c & 0x7F ];
00270                 if( digit >= 0 ) 
00271                 {
00272                     tmpBits = (tmpBits << 6) | (digit & 0x3F);
00273                     bitsLeft += 6;
00274                     while( bitsLeft > 7 ) 
00275                     {
00276                         *outp++ = (unsigned char)((tmpBits >> (bitsLeft - 8)) & 0xFF);
00277 
00278                         bitsLeft -= 8;
00279                     }
00280                 }
00281             }
00282 
00283             unsigned long tmpLen = 0;
00284             try 
00285             {
00286                 tmpLen = numeric_cast<unsigned long>(outp - out);
00287             }
00288             catch(bad_numeric_cast &) 
00289             {
00290                 throw CPKIFException(TOOLKIT_PATH, COMMON_INVALID_INPUT, "Distance is an impossibly long number.");
00291             }
00292             *outLen = tmpLen;
00293             *outp++ = '\0';
00294 
00295             rv = true;
00296         }
00297         while(0);
00298 
00299     }
00300     catch(...){};
00301 
00302     return rv;
00303 }
00311 void CBase64Buffer::addLineBreaks(int addLineBreaks, bool addCarriageReturn)
00312 {
00313     m_addLineBreaks = addLineBreaks;
00314     if(m_addLineBreaks)
00315     {
00316         unsigned long mod = m_addLineBreaks % 4;
00317         if(mod)
00318         {   
00319             if(m_addLineBreaks > 4)
00320             {   m_addLineBreaks -= mod; }
00321             else
00322             {   m_addLineBreaks = 4;    }
00323         }
00324     }
00325 
00326     m_addCR = addCarriageReturn;
00327 }
00335 bool CBase64Buffer::prependChars(const char *sz)
00336 {
00337     bool rv = false;
00338     
00339     try
00340     {
00341         do
00342         {
00343             if(m_prependChars)
00344             {   delete []m_prependChars;  m_prependChars = 0; }
00345 
00346             if(!sz || !*sz){ rv=true; break; }
00347 
00348             m_prependChars = new char[strlen(sz)+1];
00349             strcpy(m_prependChars,sz);
00350 
00351             if(!m_prependChars){ break; }
00352 
00353             if(strlen(m_prependChars) > 3)
00354             {   m_prependChars[3] = 0;  }
00355 
00356             rv = true;
00357         }
00358         while(0);
00359     }
00360     catch(...){};
00361 
00362     return rv;
00363 }
00364 

Generated on Mon Nov 15 11:15:45 2010 for PublicKeyInfrastructureFramework(PKIF) by  doxygen 1.5.6