libkmime

kmime_codecs.cpp
1 /*
2  kmime_codecs.cpp
3 
4  This file is part of KMime, the KDE internet mail/usenet news message library.
5  Copyright (c) 2001-2002 Marc Mutz <mutz@kde.org>
6 
7  KMime is free software; you can redistribute it and/or modify it
8  under the terms of the GNU General Public License, version 2, as
9  published by the Free Software Foundation.
10 
11  KMime is distributed in the hope that it will be useful, but
12  WITHOUT ANY WARRANTY; without even the implied warranty of
13  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14  General Public License for more details.
15 
16  You should have received a copy of the GNU General Public License
17  along with this library; if not, write to the Free Software
18  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19 
20  In addition, as a special exception, the copyright holders give
21  permission to link the code of this library with any edition of
22  the TQt library by Trolltech AS, Norway (or with modified versions
23  of TQt that use the same license as TQt), and distribute linked
24  combinations including the two. You must obey the GNU General
25  Public License in all respects for all of the code used other than
26  TQt. If you modify this file, you may extend this exception to
27  your version of the file, but you are not obligated to do so. If
28  you do not wish to do so, delete this exception statement from
29  your version.
30 */
31 
32 #include "kmime_codecs.h"
33 #include "kmime_util.h"
34 
35 #include "kmime_codec_base64.h"
36 #include "kmime_codec_qp.h"
37 #include "kmime_codec_uuencode.h"
38 #include "kmime_codec_identity.h"
39 
40 #include <kdebug.h>
41 
42 #include <tqcstring.h>
43 #include <kstaticdeleter.h>
44 
45 #include <cassert>
46 #include <cstring>
47 
48 using namespace KMime;
49 
50 namespace KMime {
51 
52 // global list of KMime::Codec's
53 TQAsciiDict<Codec>* Codec::all = 0;
54 static KStaticDeleter<TQAsciiDict<Codec> > sdAll;
55 #if defined(TQT_THREAD_SUPPORT)
56 TQMutex* Codec::dictLock = 0;
57 static KStaticDeleter<TQMutex> sdDictLock;
58 #endif
59 
60 void Codec::fillDictionary() {
61 
62  all->setAutoDelete(true);
63 
64  //all->insert( "7bit", new SevenBitCodec() );
65  //all->insert( "8bit", new EightBitCodec() );
66  all->insert( "base64", new Base64Codec() );
67  all->insert( "quoted-printable", new QuotedPrintableCodec() );
68  all->insert( "b", new Rfc2047BEncodingCodec() );
69  all->insert( "q", new Rfc2047TQEncodingCodec() );
70  all->insert( "x-kmime-rfc2231", new Rfc2231EncodingCodec() );
71  all->insert( "x-uuencode", new UUCodec() );
72  //all->insert( "binary", new BinaryCodec() );
73 
74 }
75 
76 Codec * Codec::codecForName( const char * name ) {
77 #if defined(TQT_THREAD_SUPPORT)
78  if ( !dictLock )
79  sdDictLock.setObject( dictLock, new TQMutex );
80  dictLock->lock(); // protect "all"
81 #endif
82  if ( !all ) {
83  sdAll.setObject( all, new TQAsciiDict<Codec>( 11, false /* case-insensitive */) );
84  fillDictionary();
85  }
86  Codec * codec = (*all)[ name ];
87 #if defined(TQT_THREAD_SUPPORT)
88  dictLock->unlock();
89 #endif
90 
91  if ( !codec )
92  kdDebug() << "Unknown codec \"" << name << "\" requested!" << endl;
93 
94  return codec;
95 }
96 
97 Codec * Codec::codecForName( const TQCString & name ) {
98  return codecForName( name.data() );
99 }
100 
101 bool Codec::encode( const char* & scursor, const char * const send,
102  char* & dcursor, const char * const dend,
103  bool withCRLF ) const
104 {
105  // get an encoder:
106  Encoder * enc = makeEncoder( withCRLF );
107  assert( enc );
108 
109  // encode and check for output buffer overflow:
110  while ( !enc->encode( scursor, send, dcursor, dend ) )
111  if ( dcursor == dend ) {
112  delete enc;
113  return false; // not enough space in output buffer
114  }
115 
116  // finish and check for output buffer overflow:
117  while ( !enc->finish( dcursor, dend ) )
118  if ( dcursor == dend ) {
119  delete enc;
120  return false; // not enough space in output buffer
121  }
122 
123  // cleanup and return:
124  delete enc;
125  return true; // successfully encoded.
126 }
127 
128 TQByteArray Codec::encode( const TQByteArray & src, bool withCRLF ) const
129 {
130  // allocate buffer for the worst case:
131  TQByteArray result( maxEncodedSizeFor( src.size(), withCRLF ) );
132 
133  // set up iterators:
134  TQByteArray::ConstIterator iit = src.begin();
135  TQByteArray::ConstIterator iend = src.end();
136  TQByteArray::Iterator oit = result.begin();
137  TQByteArray::ConstIterator oend = result.end();
138 
139  // encode
140  if ( !encode( iit, iend, oit, oend, withCRLF ) )
141  kdFatal() << name() << " codec lies about it's mEncodedSizeFor()"
142  << endl;
143 
144  // shrink result to actual size:
145  result.truncate( oit - result.begin() );
146 
147  return result;
148 }
149 
150 TQCString Codec::encodeToTQCString( const TQByteArray & src, bool withCRLF ) const
151 {
152  // allocate buffer for the worst case (remember to add one for the trailing NUL)
153  TQCString result( maxEncodedSizeFor( src.size(), withCRLF ) + 1 );
154 
155  // set up iterators:
156  TQByteArray::ConstIterator iit = src.begin();
157  TQByteArray::ConstIterator iend = src.end();
158  TQByteArray::Iterator oit = result.begin();
159  TQByteArray::ConstIterator oend = result.end() - 1;
160 
161  // encode
162  if ( !encode( iit, iend, oit, oend, withCRLF ) )
163  kdFatal() << name() << " codec lies about it's mEncodedSizeFor()"
164  << endl;
165 
166  // shrink result to actual size:
167  result.truncate( oit - result.begin() );
168 
169  return result;
170 }
171 
172 TQByteArray Codec::decode( const TQByteArray & src, bool withCRLF ) const
173 {
174  // allocate buffer for the worst case:
175  TQByteArray result( maxDecodedSizeFor( src.size(), withCRLF ) );
176 
177  // set up iterators:
178  TQByteArray::ConstIterator iit = src.begin();
179  TQByteArray::ConstIterator iend = src.end();
180  TQByteArray::Iterator oit = result.begin();
181  TQByteArray::ConstIterator oend = result.end();
182 
183  // decode
184  if ( !decode( iit, iend, oit, oend, withCRLF ) )
185  kdFatal() << name() << " codec lies about it's maxDecodedSizeFor()"
186  << endl;
187 
188  // shrink result to actual size:
189  result.truncate( oit - result.begin() );
190 
191  return result;
192 }
193 
194 bool Codec::decode( const char* & scursor, const char * const send,
195  char* & dcursor, const char * const dend,
196  bool withCRLF ) const
197 {
198  // get a decoder:
199  Decoder * dec = makeDecoder( withCRLF );
200  assert( dec );
201 
202  // decode and check for output buffer overflow:
203  while ( !dec->decode( scursor, send, dcursor, dend ) )
204  if ( dcursor == dend ) {
205  delete dec;
206  return false; // not enough space in output buffer
207  }
208 
209  // finish and check for output buffer overflow:
210  while ( !dec->finish( dcursor, dend ) )
211  if ( dcursor == dend ) {
212  delete dec;
213  return false; // not enough space in output buffer
214  }
215 
216  // cleanup and return:
217  delete dec;
218  return true; // successfully encoded.
219 }
220 
221 // write as much as possible off the output buffer. Return true if
222 // flushing was complete, false if some chars could not be flushed.
223 bool Encoder::flushOutputBuffer( char* & dcursor, const char * const dend ) {
224  int i;
225  // copy output buffer to output stream:
226  for ( i = 0 ; dcursor != dend && i < mOutputBufferCursor ; ++i )
227  *dcursor++ = mOutputBuffer[i];
228 
229  // calculate the number of missing chars:
230  int numCharsLeft = mOutputBufferCursor - i;
231  // push the remaining chars to the begin of the buffer:
232  if ( numCharsLeft )
233  tqmemmove( mOutputBuffer, mOutputBuffer + i, numCharsLeft );
234  // adjust cursor:
235  mOutputBufferCursor = numCharsLeft;
236 
237  return !numCharsLeft;
238 }
239 
240 
241 } // namespace KMime
Abstract base class of codecs like base64 and quoted-printable.
Definition: kmime_codecs.h:57
virtual const char * name() const =0
virtual TQCString encodeToTQCString(const TQByteArray &src, bool withCRLF=false) const
Even more convenient, but also a bit slower and more memory intensive, since it allocates storage for...
virtual bool decode(const char *&scursor, const char *const send, char *&dcursor, const char *const dend, bool withCRLF=false) const
Convenience wrapper that can be used for small chunks of data when you can provide a large enough buf...
virtual bool encode(const char *&scursor, const char *const send, char *&dcursor, const char *const dend, bool withCRLF=false) const
Convenience wrapper that can be used for small chunks of data when you can provide a large enough buf...
Stateful decoder class, modelled after TQTextDecoder.
Definition: kmime_codecs.h:268
virtual bool decode(const char *&scursor, const char *const send, char *&dcursor, const char *const dend)=0
Decode a chunk of data, maintaining state information between calls.
virtual bool finish(char *&dcursor, const char *const dend)=0
Call this method to finalize the output stream.
Stateful encoder class, modelled after TQTextEncoder.
Definition: kmime_codecs.h:300
virtual bool finish(char *&dcursor, const char *const dend)=0
Call this method to finalize the output stream.
virtual bool encode(const char *&scursor, const char *const send, char *&dcursor, const char *const dend)=0
Encode a chunk of data, maintaining state information between calls.
bool flushOutputBuffer(char *&dcursor, const char *const dend)
Writes characters from the output buffer to the output stream.