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