libkmime
kmime_codec_uuencode.cpp00001
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_uuencode.h"
00033
00034 #include <kdebug.h>
00035
00036 #include <cassert>
00037
00038 using namespace KMime;
00039
00040 namespace KMime {
00041
00042
00043 class UUDecoder : public Decoder {
00044 uint mStepNo;
00045 uchar mAnnouncedOctetCount;
00046 uchar mCurrentOctetCount;
00047 uchar mOutbits;
00048 bool mLastWasCRLF : 1;
00049 bool mSawBegin : 1;
00050 uint mIntoBeginLine : 3;
00051 bool mSawEnd : 1;
00052 uint mIntoEndLine : 2;
00053
00054 void searchForBegin( const char* & scursor, const char * const send );
00055
00056 protected:
00057 friend class UUCodec;
00058 UUDecoder( bool withCRLF=false )
00059 : Decoder( withCRLF ), mStepNo(0),
00060 mAnnouncedOctetCount(0), mCurrentOctetCount(0),
00061 mOutbits(0), mLastWasCRLF(true),
00062 mSawBegin(false), mIntoBeginLine(0),
00063 mSawEnd(false), mIntoEndLine(0) {}
00064
00065 public:
00066 virtual ~UUDecoder() {}
00067
00068 bool decode( const char* & scursor, const char * const send,
00069 char* & dcursor, const char * const dend );
00070
00071 bool finish( char* & , const char * const ) { return true; }
00072 };
00073
00074
00075
00076 Encoder * UUCodec::makeEncoder( bool ) const {
00077 return 0;
00078 }
00079
00080 Decoder * UUCodec::makeDecoder( bool withCRLF ) const {
00081 return new UUDecoder( withCRLF );
00082 }
00083
00084
00085
00086
00087
00088
00089
00090
00091 void UUDecoder::searchForBegin( const char* & scursor, const char * const send ) {
00092 static const char begin[] = "begin\n";
00093 static const uint beginLength = 5;
00094
00095 assert( !mSawBegin || mIntoBeginLine > 0 );
00096
00097 while ( scursor != send ) {
00098 uchar ch = *scursor++;
00099 if ( ch == begin[mIntoBeginLine] ) {
00100 if ( mIntoBeginLine < beginLength ) {
00101
00102 ++mIntoBeginLine;
00103 if ( mIntoBeginLine == beginLength )
00104 mSawBegin = true;
00105 } else {
00106
00107 mLastWasCRLF = true;
00108 mIntoBeginLine = 0;
00109 return;
00110 }
00111 } else if ( mSawBegin ) {
00112
00113 } else {
00114 kdWarning() << "UUDecoder: garbage before \"begin\", resetting parser"
00115 << endl;
00116 mIntoBeginLine = 0;
00117 }
00118 }
00119
00120 }
00121
00122
00123
00124
00125 static inline uchar uuDecode( uchar c ) {
00126 return ( c - ' ' )
00127 & 0x3F;
00128 }
00129
00130
00131 bool UUDecoder::decode( const char* & scursor, const char * const send,
00132 char* & dcursor, const char * const dend )
00133 {
00134
00135 if ( !mSawBegin || mIntoBeginLine != 0 )
00136 searchForBegin( scursor, send );
00137
00138 else if ( mSawEnd ) {
00139 scursor = send;
00140 return true;
00141 }
00142
00143 while ( dcursor != dend && scursor != send ) {
00144 uchar ch = *scursor++;
00145 uchar value;
00146
00147
00148 if ( mIntoEndLine > 0 ) {
00149 static const char end[] = "end";
00150 static const uint endLength = 3;
00151
00152 if ( ch == end[mIntoEndLine] ) {
00153 ++mIntoEndLine;
00154 if ( mIntoEndLine == endLength ) {
00155 mSawEnd = true;
00156 scursor = send;
00157 return true;
00158 }
00159 continue;
00160 } else {
00161 kdWarning() << "UUDecoder: invalid line octet count looks like \"end\" (mIntoEndLine = " << mIntoEndLine << " )!" << endl;
00162 mIntoEndLine = 0;
00163
00164 }
00165 }
00166
00167
00168
00169
00170
00171 if ( mLastWasCRLF ) {
00172
00173 mLastWasCRLF = false;
00174 mCurrentOctetCount = 0;
00175
00176
00177 if ( ch == 'e' )
00178 mIntoEndLine = 1;
00179 else if ( ch > 0x60 )
00180 {}
00181 else if ( ch > ' ' )
00182 mAnnouncedOctetCount = uuDecode( ch );
00183 else if ( ch == '\n' )
00184 mLastWasCRLF = true;
00185
00186 continue;
00187 }
00188
00189
00190 if ( ch > 0x60 )
00191 continue;
00192 else if ( ch > ' ' )
00193 value = uuDecode( ch );
00194 else if ( ch == '\n' ) {
00195 mLastWasCRLF = true;
00196 continue;
00197 } else
00198 continue;
00199
00200
00201 switch ( mStepNo ) {
00202 case 0:
00203 mOutbits = value << 2;
00204 break;
00205 case 1:
00206 if ( mCurrentOctetCount < mAnnouncedOctetCount )
00207 *dcursor++ = (char)(mOutbits | value >> 4);
00208 ++mCurrentOctetCount;
00209 mOutbits = value << 4;
00210 break;
00211 case 2:
00212 if ( mCurrentOctetCount < mAnnouncedOctetCount )
00213 *dcursor++ = (char)(mOutbits | value >> 2);
00214 ++mCurrentOctetCount;
00215 mOutbits = value << 6;
00216 break;
00217 case 3:
00218 if ( mCurrentOctetCount < mAnnouncedOctetCount )
00219 *dcursor++ = (char)(mOutbits | value);
00220 ++mCurrentOctetCount;
00221 mOutbits = 0;
00222 break;
00223 default:
00224 assert( 0 );
00225 }
00226 mStepNo = (mStepNo + 1) % 4;
00227
00228
00229 kdWarning( mCurrentOctetCount == mAnnouncedOctetCount + 1 )
00230 << "UUDecoder: mismatch between announced ("
00231 << mAnnouncedOctetCount << ") and actual line octet count!" << endl;
00232
00233 }
00234
00235
00236 return (scursor == send);
00237 }
00238
00239
00240 }
|