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
48using namespace KMime;
49
50namespace KMime {
51
52// global list of KMime::Codec's
53TQAsciiDict<Codec>* Codec::all = 0;
54static KStaticDeleter<TQAsciiDict<Codec> > sdAll;
55#if defined(TQT_THREAD_SUPPORT)
56TQMutex* Codec::dictLock = 0;
57static KStaticDeleter<TQMutex> sdDictLock;
58#endif
59
60void 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
76Codec * 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
97Codec * Codec::codecForName( const TQCString & name ) {
98 return codecForName( name.data() );
99}
100
101bool 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
128TQByteArray 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
150TQCString 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
172TQByteArray 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
194bool 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.
223bool 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.