32 #include "kmime_codec_base64.h" 38 using namespace KMime; 53 static const uchar base64DecodeMap[128] = { 54 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 55 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 57 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 62, 64, 64, 64, 63, 58 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 64, 64, 64, 64, 64, 64, 60 64, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 61 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 64, 64, 64, 64, 64, 63 64, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 64 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 64, 64, 64, 64, 64 67 static const char base64EncodeMap[64] = { 68 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 69 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 70 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 71 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 72 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 73 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 74 'w', 'x', 'y', 'z', '0', '1', '2', '3', 75 '4', '5', '6', '7', '8', '9', '+', '/' 79 class Base64Decoder : public Decoder { 85 friend class Base64Codec; 86 Base64Decoder( bool withCRLF= false ) 87 : Decoder( withCRLF ), mStepNo(0), mOutbits(0), 91 virtual ~Base64Decoder() {} 93 bool decode( const char* & scursor, const char * const send, 94 char* & dcursor, const char * const dend ); 96 bool finish( char* & , const char * const ) { return true; } 101 class Base64Encoder : public Encoder { 104 uint mWrittenPacketsOnThisLine; 106 bool mInsideFinishing : 1; 109 friend class Rfc2047BEncodingCodec; 110 friend class Rfc2047BEncodingEncoder; 111 friend class Base64Codec; 112 Base64Encoder( bool withCRLF= false ) 113 : Encoder( withCRLF ), mStepNo(0), mWrittenPacketsOnThisLine(0), 114 mNextbits(0), mInsideFinishing(false) {} 116 bool generic_finish( char* & dcursor, const char * const dend, 120 virtual ~Base64Encoder() {} 122 bool encode( const char* & scursor, const char * const send, 123 char* & dcursor, const char * const dend ); 125 bool finish( char* & dcursor, const char * const dend ); 128 bool writeBase64( uchar ch, char* & dcursor, const char * const dend ) { 129 return write( base64EncodeMap[ ch ], dcursor, dend ); 135 class Rfc2047BEncodingEncoder : public Base64Encoder { 137 friend class Rfc2047BEncodingCodec; 138 Rfc2047BEncodingEncoder( bool withCRLF= false ) 139 : Base64Encoder( withCRLF ) {}; 141 bool encode( const char* & scursor, const char * const send, 142 char* & dcursor, const char * const dend ); 143 bool finish( char* & dcursor, const char * const dend ); 147 Encoder * Base64Codec::makeEncoder( bool withCRLF ) const { 148 return new Base64Encoder( withCRLF ); 151 Decoder * Base64Codec::makeDecoder( bool withCRLF ) const { 152 return new Base64Decoder( withCRLF ); 155 Encoder * Rfc2047BEncodingCodec::makeEncoder( bool withCRLF ) const { 156 return new Rfc2047BEncodingEncoder( withCRLF ); 164 bool Base64Decoder::decode( const char* & scursor, const char * const send, 165 char* & dcursor, const char * const dend ) 167 while ( dcursor != dend && scursor != send ) { 168 uchar ch = *scursor++; 173 value = base64DecodeMap[ ch ]; 181 if ( mStepNo == 0 || mStepNo == 1) { 184 kdWarning() << "Base64Decoder: unexpected padding " 185 "character in input stream" << endl; 189 } else if ( mStepNo == 2 ) { 191 } else if ( mStepNo == 3 ) { 197 mStepNo = (mStepNo + 1) % 4; 206 kdWarning() << "Base64Decoder: Embedded padding character " 207 "encountered!" << endl; 214 mOutbits = value << 2; 217 *dcursor++ = (char)(mOutbits | value >> 4); 218 mOutbits = value << 4; 221 *dcursor++ = (char)(mOutbits | value >> 2); 222 mOutbits = value << 6; 225 *dcursor++ = (char)(mOutbits | value); 231 mStepNo = (mStepNo + 1) % 4; 235 return (scursor == send); 240 bool Base64Encoder::encode( const char* & scursor, const char * const send, 241 char* & dcursor, const char * const dend ) { 242 const uint maxPacketsPerLine = 76 / 4; 245 if ( mInsideFinishing ) return true; 247 while ( scursor != send && dcursor != dend ) { 251 if ( mOutputBufferCursor && !flushOutputBuffer( dcursor, dend ) ) 252 return (scursor == send); 254 uchar ch = *scursor++; 258 if ( mStepNo == 0 && mWrittenPacketsOnThisLine >= maxPacketsPerLine ) { 259 writeCRLF( dcursor, dend ); 260 mWrittenPacketsOnThisLine = 0; 267 assert( mNextbits == 0 ); 268 writeBase64( ch >> 2, dcursor, dend ); 269 mNextbits = (ch & 0x3) << 4; 272 assert( (mNextbits & ~0x30) == 0 ); 273 writeBase64( mNextbits | ch >> 4, dcursor, dend ); 274 mNextbits = (ch & 0xf) << 2; 277 assert( (mNextbits & ~0x3C) == 0 ); 278 writeBase64( mNextbits | ch >> 6, dcursor, dend ); 279 writeBase64( ch & 0x3F, dcursor, dend ); 281 mWrittenPacketsOnThisLine++; 286 mStepNo = ( mStepNo + 1 ) % 3; 289 if ( mOutputBufferCursor ) flushOutputBuffer( dcursor, dend ); 291 return (scursor == send); 295 bool Rfc2047BEncodingEncoder::encode( const char* & scursor, 296 const char * const send, 298 const char * const dend ) 301 if ( mInsideFinishing ) return true; 303 while ( scursor != send && dcursor != dend ) { 307 if ( mOutputBufferCursor && !flushOutputBuffer( dcursor, dend ) ) 308 return (scursor == send); 310 uchar ch = *scursor++; 317 assert( mNextbits == 0 ); 318 writeBase64( ch >> 2, dcursor, dend ); 319 mNextbits = (ch & 0x3) << 4; 322 assert( (mNextbits & ~0x30) == 0 ); 323 writeBase64( mNextbits | ch >> 4, dcursor, dend ); 324 mNextbits = (ch & 0xf) << 2; 327 assert( (mNextbits & ~0x3C) == 0 ); 328 writeBase64( mNextbits | ch >> 6, dcursor, dend ); 329 writeBase64( ch & 0x3F, dcursor, dend ); 335 mStepNo = ( mStepNo + 1 ) % 3; 338 if ( mOutputBufferCursor ) flushOutputBuffer( dcursor, dend ); 340 return (scursor == send); 344 bool Base64Encoder::finish( char* & dcursor, const char * const dend ) { 345 return generic_finish( dcursor, dend, true ); 348 bool Rfc2047BEncodingEncoder::finish( char* & dcursor, 349 const char * const dend ) { 350 return generic_finish( dcursor, dend, false ); 353 bool Base64Encoder::generic_finish( char* & dcursor, const char * const dend, 356 if ( mInsideFinishing ) 357 return flushOutputBuffer( dcursor, dend ); 359 if ( mOutputBufferCursor && !flushOutputBuffer( dcursor, dend ) ) 362 mInsideFinishing = true; 370 writeBase64( mNextbits, dcursor, dend ); 374 assert( mNextbits == 0 ); 385 write( '=', dcursor, dend ); 388 write( '=', dcursor, dend ); 392 writeCRLF( dcursor, dend ); 393 return flushOutputBuffer( dcursor, dend ); Stateful encoder class, modelled after TQTextEncoder.
Stateful decoder class, modelled after TQTextDecoder.
|