KMIME Library
kmime_codecs.cpp
Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00033 #include "kmime_codecs.h"
00034 #include "kmime_util.h"
00035 #include "kmime_codec_base64.h"
00036 #include "kmime_codec_qp.h"
00037 #include "kmime_codec_uuencode.h"
00038 #include "kmime_codec_identity.h"
00039
00040 #include "kautodeletehash.h"
00041
00042 #include <kascii.h>
00043 #include <kdebug.h>
00044 #include <kglobal.h>
00045
00046 #include <QtCore/QCoreApplication>
00047 #include <QtCore/QMutex>
00048
00049 #include <cassert>
00050 #include <cstring>
00051 #include <string.h>
00052
00053 using namespace KMime;
00054
00055 namespace KMime {
00056
00057
00058
00059 KAutoDeleteHash<QByteArray, Codec> *Codec::all = 0;
00060 K_GLOBAL_STATIC(QMutex, dictLock)
00061
00062
00063 void Codec::cleanupCodec()
00064 {
00065 delete all;
00066 all = 0;
00067 }
00068
00069 void Codec::fillDictionary()
00070 {
00071
00072
00073 all->insert( "base64", new Base64Codec() );
00074 all->insert( "quoted-printable", new QuotedPrintableCodec() );
00075 all->insert( "b", new Rfc2047BEncodingCodec() );
00076 all->insert( "q", new Rfc2047QEncodingCodec() );
00077 all->insert( "x-kmime-rfc2231", new Rfc2231EncodingCodec() );
00078 all->insert( "x-uuencode", new UUCodec() );
00079
00080 }
00081
00082 Codec *Codec::codecForName( const char *name )
00083 {
00084 const QByteArray ba( name );
00085 return codecForName( ba );
00086 }
00087
00088 Codec *Codec::codecForName( const QByteArray &name )
00089 {
00090 dictLock->lock();
00091 if ( !all ) {
00092 all = new KAutoDeleteHash<QByteArray, Codec>();
00093 qAddPostRoutine(cleanupCodec);
00094 fillDictionary();
00095 }
00096 QByteArray lowerName = name;
00097 kAsciiToLower( lowerName.data() );
00098 Codec *codec = (*all)[ lowerName ];
00099 dictLock->unlock();
00100
00101 if ( !codec ) {
00102 kDebug() << "Unknown codec \"" << name << "\" requested!";
00103 }
00104
00105 return codec;
00106 }
00107
00108 bool Codec::encode( const char* &scursor, const char * const send,
00109 char* &dcursor, const char * const dend,
00110 bool withCRLF ) const
00111 {
00112
00113 Encoder *enc = makeEncoder( withCRLF );
00114 assert( enc );
00115
00116
00117 while ( !enc->encode( scursor, send, dcursor, dend ) ) {
00118 if ( dcursor == dend ) {
00119 delete enc;
00120 return false;
00121 }
00122 }
00123
00124
00125 while ( !enc->finish( dcursor, dend ) ) {
00126 if ( dcursor == dend ) {
00127 delete enc;
00128 return false;
00129 }
00130 }
00131
00132
00133 delete enc;
00134 return true;
00135 }
00136
00137 QByteArray Codec::encode( const QByteArray &src, bool withCRLF ) const
00138 {
00139
00140 QByteArray result;
00141 result.resize( maxEncodedSizeFor( src.size(), withCRLF ) );
00142
00143
00144 QByteArray::ConstIterator iit = src.begin();
00145 QByteArray::ConstIterator iend = src.end();
00146 QByteArray::Iterator oit = result.begin();
00147 QByteArray::ConstIterator oend = result.end();
00148
00149
00150 if ( !encode( iit, iend, oit, oend, withCRLF ) ) {
00151 kFatal() << name() << "codec lies about it's mEncodedSizeFor()";
00152 }
00153
00154
00155 result.truncate( oit - result.begin() );
00156
00157 return result;
00158 }
00159
00160 QByteArray Codec::decode( const QByteArray &src, bool withCRLF ) const
00161 {
00162
00163 QByteArray result;
00164 result.resize( maxDecodedSizeFor( src.size(), withCRLF ) );
00165
00166
00167 QByteArray::ConstIterator iit = src.begin();
00168 QByteArray::ConstIterator iend = src.end();
00169 QByteArray::Iterator oit = result.begin();
00170 QByteArray::ConstIterator oend = result.end();
00171
00172
00173 if ( !decode( iit, iend, oit, oend, withCRLF ) ) {
00174 kFatal() << name() << "codec lies about it's maxDecodedSizeFor()";
00175 }
00176
00177
00178 result.truncate( oit - result.begin() );
00179
00180 return result;
00181 }
00182
00183 bool Codec::decode( const char* &scursor, const char * const send,
00184 char* &dcursor, const char * const dend,
00185 bool withCRLF ) const
00186 {
00187
00188 Decoder *dec = makeDecoder( withCRLF );
00189 assert( dec );
00190
00191
00192 while ( !dec->decode( scursor, send, dcursor, dend ) ) {
00193 if ( dcursor == dend ) {
00194 delete dec;
00195 return false;
00196 }
00197 }
00198
00199
00200 while ( !dec->finish( dcursor, dend ) ) {
00201 if ( dcursor == dend ) {
00202 delete dec;
00203 return false;
00204 }
00205 }
00206
00207
00208 delete dec;
00209 return true;
00210 }
00211
00212
00213
00214 bool Encoder::flushOutputBuffer( char* &dcursor, const char * const dend )
00215 {
00216 int i;
00217
00218 for ( i = 0 ; dcursor != dend && i < mOutputBufferCursor ; ++i ) {
00219 *dcursor++ = mOutputBuffer[i];
00220 }
00221
00222
00223 int numCharsLeft = mOutputBufferCursor - i;
00224
00225 if ( numCharsLeft ) {
00226 ::memmove( mOutputBuffer, mOutputBuffer + i, numCharsLeft );
00227 }
00228
00229 mOutputBufferCursor = numCharsLeft;
00230
00231 return !numCharsLeft;
00232 }
00233
00234 }