39 using namespace KMime;
54 static const uchar base64DecodeMap[128] = {
55 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
56 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
58 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 62, 64, 64, 64, 63,
59 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 64, 64, 64, 64, 64, 64,
61 64, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
62 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 64, 64, 64, 64, 64,
64 64, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
65 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 64, 64, 64, 64, 64
68 static const char base64EncodeMap[64] = {
69 'A',
'B',
'C',
'D',
'E',
'F',
'G',
'H',
70 'I',
'J',
'K',
'L',
'M',
'N',
'O',
'P',
71 'Q',
'R',
'S',
'T',
'U',
'V',
'W',
'X',
72 'Y',
'Z',
'a',
'b',
'c',
'd',
'e',
'f',
73 'g',
'h',
'i',
'j',
'k',
'l',
'm',
'n',
74 'o',
'p',
'q',
'r',
's',
't',
'u',
'v',
75 'w',
'x',
'y',
'z',
'0',
'1',
'2',
'3',
76 '4',
'5',
'6',
'7',
'8',
'9',
'+',
'/'
80 class Base64Decoder :
public Decoder
88 Base64Decoder(
bool withCRLF=
false )
89 :
Decoder( withCRLF ), mStepNo( 0 ), mOutbits( 0 ),
90 mSawPadding( false ) {}
93 virtual ~Base64Decoder() {}
95 bool decode(
const char* &scursor,
const char *
const send,
96 char* &dcursor,
const char *
const dend );
98 bool finish(
char* &dcursor,
const char *
const dend )
100 Q_UNUSED( dcursor ); Q_UNUSED( dend );
105 class Base64Encoder :
public Encoder
109 uint mWrittenPacketsOnThisLine;
111 bool mInsideFinishing : 1;
115 friend class Rfc2047BEncodingEncoder;
117 Base64Encoder(
bool withCRLF=
false )
118 :
Encoder( withCRLF ), mStepNo( 0 ), mWrittenPacketsOnThisLine( 0 ),
119 mNextbits( 0 ), mInsideFinishing( false ) {}
121 bool generic_finish(
char* &dcursor,
const char *
const dend,
125 virtual ~Base64Encoder() {}
127 bool encode(
const char* &scursor,
const char *
const send,
128 char* &dcursor,
const char *
const dend );
130 bool finish(
char* &dcursor,
const char *
const dend );
133 bool writeBase64( uchar ch,
char* &dcursor,
const char *
const dend )
134 {
return write( base64EncodeMap[ ch ], dcursor, dend ); }
137 class Rfc2047BEncodingEncoder :
public Base64Encoder
141 Rfc2047BEncodingEncoder(
bool withCRLF=
false )
142 : Base64Encoder( withCRLF ) {}
145 bool encode(
const char* &scursor,
const char *
const send,
146 char* &dcursor,
const char *
const dend );
147 bool finish(
char* &dcursor,
const char *
const dend );
152 return new Base64Encoder( withCRLF );
157 return new Base64Decoder( withCRLF );
162 return new Rfc2047BEncodingEncoder( withCRLF );
169 bool Base64Decoder::decode(
const char* &scursor,
const char *
const send,
170 char* &dcursor,
const char *
const dend )
172 while ( dcursor != dend && scursor != send ) {
173 uchar ch = *scursor++;
178 value = base64DecodeMap[ ch ];
187 if ( mStepNo == 0 || mStepNo == 1 ) {
188 if ( !mSawPadding ) {
190 kWarning() <<
"Base64Decoder: unexpected padding"
191 "character in input stream";
195 }
else if ( mStepNo == 2 ) {
197 }
else if ( mStepNo == 3 ) {
203 mStepNo = ( mStepNo + 1 ) % 4;
212 kWarning() <<
"Base64Decoder: Embedded padding character"
220 mOutbits = value << 2;
223 *dcursor++ = (char)( mOutbits | value >> 4 );
224 mOutbits = value << 4;
227 *dcursor++ = (char)( mOutbits | value >> 2 );
228 mOutbits = value << 6;
231 *dcursor++ = (char)( mOutbits | value );
237 mStepNo = ( mStepNo + 1 ) % 4;
241 return scursor == send;
244 bool Base64Encoder::encode(
const char* &scursor,
const char *
const send,
245 char* &dcursor,
const char *
const dend )
247 const uint maxPacketsPerLine = 76 / 4;
250 if ( mInsideFinishing ) {
254 while ( scursor != send && dcursor != dend ) {
258 if ( mOutputBufferCursor && !flushOutputBuffer( dcursor, dend ) ) {
259 return scursor == send;
262 uchar ch = *scursor++;
266 if ( mStepNo == 0 && mWrittenPacketsOnThisLine >= maxPacketsPerLine ) {
267 writeCRLF( dcursor, dend );
268 mWrittenPacketsOnThisLine = 0;
275 assert( mNextbits == 0 );
276 writeBase64( ch >> 2, dcursor, dend );
277 mNextbits = ( ch & 0x3 ) << 4;
280 assert( ( mNextbits & ~0x30 ) == 0 );
281 writeBase64( mNextbits | ch >> 4, dcursor, dend );
282 mNextbits = ( ch & 0xf ) << 2;
285 assert( ( mNextbits & ~0x3C ) == 0 );
286 writeBase64( mNextbits | ch >> 6, dcursor, dend );
287 writeBase64( ch & 0x3F, dcursor, dend );
289 mWrittenPacketsOnThisLine++;
294 mStepNo = ( mStepNo + 1 ) % 3;
297 if ( mOutputBufferCursor ) {
298 flushOutputBuffer( dcursor, dend );
301 return scursor == send;
304 bool Rfc2047BEncodingEncoder::encode(
const char* &scursor,
305 const char *
const send,
307 const char *
const dend )
310 if ( mInsideFinishing ) {
314 while ( scursor != send && dcursor != dend ) {
318 if ( mOutputBufferCursor && !flushOutputBuffer( dcursor, dend ) ) {
319 return scursor == send;
322 uchar ch = *scursor++;
329 assert( mNextbits == 0 );
330 writeBase64( ch >> 2, dcursor, dend );
331 mNextbits = ( ch & 0x3 ) << 4;
334 assert( ( mNextbits & ~0x30 ) == 0 );
335 writeBase64( mNextbits | ch >> 4, dcursor, dend );
336 mNextbits = ( ch & 0xf ) << 2;
339 assert( ( mNextbits & ~0x3C ) == 0 );
340 writeBase64( mNextbits | ch >> 6, dcursor, dend );
341 writeBase64( ch & 0x3F, dcursor, dend );
347 mStepNo = ( mStepNo + 1 ) % 3;
350 if ( mOutputBufferCursor ) {
351 flushOutputBuffer( dcursor, dend );
354 return scursor == send;
357 bool Base64Encoder::finish(
char* &dcursor,
const char *
const dend )
359 return generic_finish( dcursor, dend,
true );
362 bool Rfc2047BEncodingEncoder::finish(
char* & dcursor,
363 const char *
const dend )
365 return generic_finish( dcursor, dend,
false );
368 bool Base64Encoder::generic_finish(
char* &dcursor,
const char *
const dend,
371 if ( mInsideFinishing ) {
372 return flushOutputBuffer( dcursor, dend );
375 if ( mOutputBufferCursor && !flushOutputBuffer( dcursor, dend ) ) {
379 mInsideFinishing =
true;
387 writeBase64( mNextbits, dcursor, dend );
391 assert( mNextbits == 0 );
402 write(
'=', dcursor, dend );
405 write(
'=', dcursor, dend );
409 writeCRLF( dcursor, dend );
411 return flushOutputBuffer( dcursor, dend );
Encoder * makeEncoder(bool withCRLF=false) const
This file is part of the API for handling MIME data and defines the Base64 and RFC2047B Codec classes...
Decoder * makeDecoder(bool withCRLF=false) const
A class representing the codec for Base64 as specified in RFC2045.
Stateful CTE decoder class.
bool write(char ch, char *&dcursor, const char *const dend)
Writes character ch to the output stream or the output buffer, depending on whether or not the output...
Encoder * makeEncoder(bool withCRLF=false) const
A class representing the codec for the B encoding as specified in RFC2047B.