00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032 #include "kmime_codec_base64.h"
00033
00034 #include <kdebug.h>
00035
00036 #include <cassert>
00037
00038 using namespace KMime;
00039
00040 namespace KMime {
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053 static const uchar base64DecodeMap[128] = {
00054 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
00055 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
00056
00057 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 62, 64, 64, 64, 63,
00058 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 64, 64, 64, 64, 64, 64,
00059
00060 64, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
00061 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 64, 64, 64, 64, 64,
00062
00063 64, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
00064 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 64, 64, 64, 64, 64
00065 };
00066
00067 static const char base64EncodeMap[64] = {
00068 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H',
00069 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P',
00070 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X',
00071 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f',
00072 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n',
00073 'o', 'p', 'q', 'r', 's', 't', 'u', 'v',
00074 'w', 'x', 'y', 'z', '0', '1', '2', '3',
00075 '4', '5', '6', '7', '8', '9', '+', '/'
00076 };
00077
00078
00079 class Base64Decoder : public Decoder {
00080 uint mStepNo;
00081 uchar mOutbits;
00082 bool mSawPadding : 1;
00083
00084 protected:
00085 friend class Base64Codec;
00086 Base64Decoder( bool withCRLF=false )
00087 : Decoder( withCRLF ), mStepNo(0), mOutbits(0),
00088 mSawPadding(false) {}
00089
00090 public:
00091 virtual ~Base64Decoder() {}
00092
00093 bool decode( const char* & scursor, const char * const send,
00094 char* & dcursor, const char * const dend );
00095
00096 bool finish( char* & , const char * const ) { return true; }
00097 };
00098
00099
00100
00101 class Base64Encoder : public Encoder {
00102 uint mStepNo;
00104 uint mWrittenPacketsOnThisLine;
00105 uchar mNextbits;
00106 bool mInsideFinishing : 1;
00107
00108 protected:
00109 friend class Rfc2047BEncodingCodec;
00110 friend class Rfc2047BEncodingEncoder;
00111 friend class Base64Codec;
00112 Base64Encoder( bool withCRLF=false )
00113 : Encoder( withCRLF ), mStepNo(0), mWrittenPacketsOnThisLine(0),
00114 mNextbits(0), mInsideFinishing(false) {}
00115
00116 bool generic_finish( char* & dcursor, const char * const dend,
00117 bool withLFatEnd );
00118
00119 public:
00120 virtual ~Base64Encoder() {}
00121
00122 bool encode( const char* & scursor, const char * const send,
00123 char* & dcursor, const char * const dend );
00124
00125 bool finish( char* & dcursor, const char * const dend );
00126
00127 protected:
00128 bool writeBase64( uchar ch, char* & dcursor, const char * const dend ) {
00129 return write( base64EncodeMap[ ch ], dcursor, dend );
00130 }
00131 };
00132
00133
00134
00135 class Rfc2047BEncodingEncoder : public Base64Encoder {
00136 protected:
00137 friend class Rfc2047BEncodingCodec;
00138 Rfc2047BEncodingEncoder( bool withCRLF=false )
00139 : Base64Encoder( withCRLF ) {};
00140 public:
00141 bool encode( const char* & scursor, const char * const send,
00142 char* & dcursor, const char * const dend );
00143 bool finish( char* & dcursor, const char * const dend );
00144 };
00145
00146
00147 Encoder * Base64Codec::makeEncoder( bool withCRLF ) const {
00148 return new Base64Encoder( withCRLF );
00149 }
00150
00151 Decoder * Base64Codec::makeDecoder( bool withCRLF ) const {
00152 return new Base64Decoder( withCRLF );
00153 }
00154
00155 Encoder * Rfc2047BEncodingCodec::makeEncoder( bool withCRLF ) const {
00156 return new Rfc2047BEncodingEncoder( withCRLF );
00157 }
00158
00159
00160
00161
00162
00163
00164 bool Base64Decoder::decode( const char* & scursor, const char * const send,
00165 char* & dcursor, const char * const dend )
00166 {
00167 while ( dcursor != dend && scursor != send ) {
00168 uchar ch = *scursor++;
00169 uchar value;
00170
00171
00172 if ( ch < 128 )
00173 value = base64DecodeMap[ ch ];
00174 else
00175 value = 64;
00176
00177
00178 if ( value >= 64 ) {
00179 if ( ch == '=' ) {
00180
00181 if ( mStepNo == 0 || mStepNo == 1) {
00182 if (!mSawPadding) {
00183
00184 kdWarning() << "Base64Decoder: unexpected padding "
00185 "character in input stream" << endl;
00186 }
00187 mSawPadding = true;
00188 break;
00189 } else if ( mStepNo == 2 ) {
00190
00191 } else if ( mStepNo == 3 ) {
00192
00193 mSawPadding = true;
00194 break;
00195 }
00196 mSawPadding = true;
00197 mStepNo = (mStepNo + 1) % 4;
00198 continue;
00199 } else {
00200
00201 continue;
00202 }
00203 }
00204
00205 if ( mSawPadding ) {
00206 kdWarning() << "Base64Decoder: Embedded padding character "
00207 "encountered!" << endl;
00208 return true;
00209 }
00210
00211
00212 switch ( mStepNo ) {
00213 case 0:
00214 mOutbits = value << 2;
00215 break;
00216 case 1:
00217 *dcursor++ = (char)(mOutbits | value >> 4);
00218 mOutbits = value << 4;
00219 break;
00220 case 2:
00221 *dcursor++ = (char)(mOutbits | value >> 2);
00222 mOutbits = value << 6;
00223 break;
00224 case 3:
00225 *dcursor++ = (char)(mOutbits | value);
00226 mOutbits = 0;
00227 break;
00228 default:
00229 assert( 0 );
00230 }
00231 mStepNo = (mStepNo + 1) % 4;
00232 }
00233
00234
00235 return (scursor == send);
00236 }
00237
00238
00239
00240 bool Base64Encoder::encode( const char* & scursor, const char * const send,
00241 char* & dcursor, const char * const dend ) {
00242 const uint maxPacketsPerLine = 76 / 4;
00243
00244
00245 if ( mInsideFinishing ) return true;
00246
00247 while ( scursor != send && dcursor != dend ) {
00248
00249
00250
00251 if ( mOutputBufferCursor && !flushOutputBuffer( dcursor, dend ) )
00252 return (scursor == send);
00253
00254 uchar ch = *scursor++;
00255
00256
00257
00258 if ( mStepNo == 0 && mWrittenPacketsOnThisLine >= maxPacketsPerLine ) {
00259 writeCRLF( dcursor, dend );
00260 mWrittenPacketsOnThisLine = 0;
00261 }
00262
00263
00264
00265 switch ( mStepNo ) {
00266 case 0:
00267 assert( mNextbits == 0 );
00268 writeBase64( ch >> 2, dcursor, dend );
00269 mNextbits = (ch & 0x3) << 4;
00270 break;
00271 case 1:
00272 assert( (mNextbits & ~0x30) == 0 );
00273 writeBase64( mNextbits | ch >> 4, dcursor, dend );
00274 mNextbits = (ch & 0xf) << 2;
00275 break;
00276 case 2:
00277 assert( (mNextbits & ~0x3C) == 0 );
00278 writeBase64( mNextbits | ch >> 6, dcursor, dend );
00279 writeBase64( ch & 0x3F, dcursor, dend );
00280 mNextbits = 0;
00281 mWrittenPacketsOnThisLine++;
00282 break;
00283 default:
00284 assert( 0 );
00285 }
00286 mStepNo = ( mStepNo + 1 ) % 3;
00287 }
00288
00289 if ( mOutputBufferCursor ) flushOutputBuffer( dcursor, dend );
00290
00291 return (scursor == send);
00292 }
00293
00294
00295 bool Rfc2047BEncodingEncoder::encode( const char* & scursor,
00296 const char * const send,
00297 char* & dcursor,
00298 const char * const dend )
00299 {
00300
00301 if ( mInsideFinishing ) return true;
00302
00303 while ( scursor != send && dcursor != dend ) {
00304
00305
00306
00307 if ( mOutputBufferCursor && !flushOutputBuffer( dcursor, dend ) )
00308 return (scursor == send);
00309
00310 uchar ch = *scursor++;
00311
00312
00313
00314
00315 switch ( mStepNo ) {
00316 case 0:
00317 assert( mNextbits == 0 );
00318 writeBase64( ch >> 2, dcursor, dend );
00319 mNextbits = (ch & 0x3) << 4;
00320 break;
00321 case 1:
00322 assert( (mNextbits & ~0x30) == 0 );
00323 writeBase64( mNextbits | ch >> 4, dcursor, dend );
00324 mNextbits = (ch & 0xf) << 2;
00325 break;
00326 case 2:
00327 assert( (mNextbits & ~0x3C) == 0 );
00328 writeBase64( mNextbits | ch >> 6, dcursor, dend );
00329 writeBase64( ch & 0x3F, dcursor, dend );
00330 mNextbits = 0;
00331 break;
00332 default:
00333 assert( 0 );
00334 }
00335 mStepNo = ( mStepNo + 1 ) % 3;
00336 }
00337
00338 if ( mOutputBufferCursor ) flushOutputBuffer( dcursor, dend );
00339
00340 return (scursor == send);
00341 }
00342
00343
00344 bool Base64Encoder::finish( char* & dcursor, const char * const dend ) {
00345 return generic_finish( dcursor, dend, true );
00346 }
00347
00348 bool Rfc2047BEncodingEncoder::finish( char* & dcursor,
00349 const char * const dend ) {
00350 return generic_finish( dcursor, dend, false );
00351 }
00352
00353 bool Base64Encoder::generic_finish( char* & dcursor, const char * const dend,
00354 bool withLFatEnd )
00355 {
00356 if ( mInsideFinishing )
00357 return flushOutputBuffer( dcursor, dend );
00358
00359 if ( mOutputBufferCursor && !flushOutputBuffer( dcursor, dend ) )
00360 return false;
00361
00362 mInsideFinishing = true;
00363
00364
00365
00366
00367 switch ( mStepNo ) {
00368 case 1:
00369 case 2:
00370 writeBase64( mNextbits, dcursor, dend );
00371 mNextbits = 0;
00372 break;
00373 case 0:
00374 assert( mNextbits == 0 );
00375 break;
00376 default:
00377 assert( 0 );
00378 }
00379
00380
00381
00382
00383 switch( mStepNo ) {
00384 case 1:
00385 write( '=', dcursor, dend );
00386
00387 case 2:
00388 write( '=', dcursor, dend );
00389
00390 case 0:
00391 if ( withLFatEnd )
00392 writeCRLF( dcursor, dend );
00393 return flushOutputBuffer( dcursor, dend );
00394 default:
00395 assert( 0 );
00396 }
00397 return true;
00398 }
00399
00400
00401
00402
00403
00404
00405 }