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 }