Base64Buffer.cpp
Go to the documentation of this file.00001
00002
00003
00004
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;
00050 for( i=0; i < 64; i++ )
00051 {
00052 m_decodeTable[ m_base64chars[ i ] ] = i;
00053 m_decodeTable[ m_base64chars[ i ] | 0x80 ] = i;
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 ,
00081 unsigned long *outLen )
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);
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
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;
00220
00221 rv = true;
00222 }
00223 while(0);
00224
00225 }
00226 catch(...){};
00227
00228 return rv;
00229 }
00230
00231
00241 bool CBase64Buffer::decode( const char *in, const unsigned long inLen, unsigned char *out, unsigned long *outLen )
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