kmail

bodypartformatter.cpp
1/*
2 bodypartformatter.cpp
3
4 This file is part of KMail, the KDE mail client.
5 Copyright (c) 2003 Marc Mutz <mutz@kde.org>
6
7 KMail 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 KMail 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 program; 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 program 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#ifdef HAVE_CONFIG_H
33#include <config.h>
34#endif
35
36#include "bodypartformatter.h"
37#include "bodypartformatterfactory_p.h"
38#include "interfaces/bodypartformatter.h"
39
40#include "objecttreeparser.h"
41#include "partNode.h"
42#include "callback.h"
43
44#include <mimelib/enum.h>
45#include <mimelib/string.h>
46#include <mimelib/utility.h>
47
48#include <kdebug.h>
49
50namespace {
51 class AnyTypeBodyPartFormatter
52 : public KMail::BodyPartFormatter,
53 public KMail::Interface::BodyPartFormatter {
54 static const AnyTypeBodyPartFormatter * self;
55 public:
56 Result format( KMail::Interface::BodyPart *, KMail::HtmlWriter *, KMail::Callback & ) const {
57 kdDebug(5006) << "AnyTypeBodyPartFormatter::format() acting as a KMail::Interface::BodyPartFormatter!" << endl;
58 return AsIcon;
59 }
60
61 bool process( KMail::ObjectTreeParser *, partNode *, KMail::ProcessResult & result ) const {
62 result.setNeverDisplayInline( true );
63 return false;
64 }
65 static const KMail::BodyPartFormatter * create() {
66 if ( !self )
67 self = new AnyTypeBodyPartFormatter();
68 return self;
69 }
70 };
71
72 const AnyTypeBodyPartFormatter * AnyTypeBodyPartFormatter::self = 0;
73
74
75 class ImageTypeBodyPartFormatter : public KMail::BodyPartFormatter {
76 static const ImageTypeBodyPartFormatter * self;
77 public:
78 bool process( KMail::ObjectTreeParser *, partNode *, KMail::ProcessResult & result ) const {
79 result.setIsImage( true );
80 return false;
81 }
82 static const KMail::BodyPartFormatter * create() {
83 if ( !self )
84 self = new ImageTypeBodyPartFormatter();
85 return self;
86 }
87 };
88
89 const ImageTypeBodyPartFormatter * ImageTypeBodyPartFormatter::self = 0;
90
91#define CREATE_BODY_PART_FORMATTER(subtype) \
92 class subtype##BodyPartFormatter : public KMail::BodyPartFormatter { \
93 static const subtype##BodyPartFormatter * self; \
94 public: \
95 bool process( KMail::ObjectTreeParser *, partNode *, KMail::ProcessResult & ) const; \
96 static const KMail::BodyPartFormatter * create() { \
97 if ( !self ) \
98 self = new subtype##BodyPartFormatter(); \
99 return self; \
100 } \
101 }; \
102 \
103 const subtype##BodyPartFormatter * subtype##BodyPartFormatter::self; \
104 \
105 bool subtype##BodyPartFormatter::process( KMail::ObjectTreeParser * otp, partNode * node, KMail::ProcessResult & result ) const { \
106 return otp->process##subtype##Subtype( node, result ); \
107 }
108
109 CREATE_BODY_PART_FORMATTER(TextPlain)
110 CREATE_BODY_PART_FORMATTER(TextHtml)
111 //CREATE_BODY_PART_FORMATTER(TextEnriched)
112
113 CREATE_BODY_PART_FORMATTER(ApplicationOctetStream)
114 CREATE_BODY_PART_FORMATTER(ApplicationPkcs7Mime)
115 CREATE_BODY_PART_FORMATTER(ApplicationChiasmusText)
116 //CREATE_BODY_PART_FORMATTER(ApplicationPgp)
117 CREATE_BODY_PART_FORMATTER(ApplicationMsTnef)
118
119 CREATE_BODY_PART_FORMATTER(MessageRfc822)
120
121 CREATE_BODY_PART_FORMATTER(MultiPartMixed)
122 CREATE_BODY_PART_FORMATTER(MultiPartAlternative)
123 CREATE_BODY_PART_FORMATTER(MultiPartSigned)
124 CREATE_BODY_PART_FORMATTER(MultiPartEncrypted)
125
126 typedef TextPlainBodyPartFormatter ApplicationPgpBodyPartFormatter;
127
128
129#undef CREATE_BODY_PART_FORMATTER
130} // anon namespace
131
132// FIXME: port some more KMail::BodyPartFormatters to KMail::Interface::BodyPartFormatters
133void KMail::BodyPartFormatterFactoryPrivate::kmail_create_builtin_bodypart_formatters( KMail::BodyPartFormatterFactoryPrivate::TypeRegistry * reg ) {
134 if ( !reg ) return;
135 (*reg)["application"]["octet-stream"] = new AnyTypeBodyPartFormatter();
136}
137
138typedef const KMail::BodyPartFormatter * (*BodyPartFormatterCreator)();
139
140struct SubtypeBuiltin {
141 const char * subtype;
142 BodyPartFormatterCreator create;
143};
144
145static const SubtypeBuiltin applicationSubtypeBuiltins[] = {
146 { "octet-stream", &ApplicationOctetStreamBodyPartFormatter::create },
147 { "pkcs7-mime", &ApplicationPkcs7MimeBodyPartFormatter::create },
148 { "x-pkcs7-mime", &ApplicationPkcs7MimeBodyPartFormatter::create },
149 { "vnd.de.bund.bsi.chiasmus-text", &ApplicationChiasmusTextBodyPartFormatter::create },
150 { "pgp", &ApplicationPgpBodyPartFormatter::create },
151 { "ms-tnef", &ApplicationMsTnefBodyPartFormatter::create }
152};
153
154static const SubtypeBuiltin textSubtypeBuiltins[] = {
155 { "html", &TextHtmlBodyPartFormatter::create },
156 //{ "enriched", &TextEnrichedBodyPartFormatter::create },
157 { "x-vcard", &AnyTypeBodyPartFormatter::create },
158 { "vcard", &AnyTypeBodyPartFormatter::create },
159 { "rtf", &AnyTypeBodyPartFormatter::create },
160 { "*", &TextPlainBodyPartFormatter::create },
161};
162
163static const SubtypeBuiltin multipartSubtypeBuiltins[] = {
164 { "mixed", &MultiPartMixedBodyPartFormatter::create },
165 { "alternative", &MultiPartAlternativeBodyPartFormatter::create },
166 //{ "digest", &MultiPartDigestFormatter::create },
167 //{ "parallel", &MultiPartParallelFormatter::create },
168 //{ "related", &MultiPartRelatedFormatter::create },
169 { "signed", &MultiPartSignedBodyPartFormatter::create },
170 { "encrypted", &MultiPartEncryptedBodyPartFormatter::create },
171 //{ "report", &MultiPartReportFormatter::create },
172};
173
174static const SubtypeBuiltin messageSubtypeBuiltins[] = {
175 { "rfc822", &MessageRfc822BodyPartFormatter::create },
176};
177
178static const SubtypeBuiltin imageSubtypeBuiltins[] = {
179 { "*", &ImageTypeBodyPartFormatter::create },
180};
181
182static const SubtypeBuiltin anySubtypeBuiltins[] = {
183 { "*", &AnyTypeBodyPartFormatter::create },
184};
185
186#ifdef DIM
187#undef DIM
188#endif
189#define DIM(x) sizeof(x) / sizeof(*x)
190
191static const struct {
192 const char * type;
193 const SubtypeBuiltin * subtypes;
194 unsigned int num_subtypes;
195} builtins[] = {
196 { "application", applicationSubtypeBuiltins, DIM(applicationSubtypeBuiltins) },
197 { "text", textSubtypeBuiltins, DIM(textSubtypeBuiltins) },
198 { "multipart", multipartSubtypeBuiltins, DIM(multipartSubtypeBuiltins) },
199 { "message", messageSubtypeBuiltins, DIM(messageSubtypeBuiltins) },
200 { "image", imageSubtypeBuiltins, DIM(imageSubtypeBuiltins) },
201 //{ "audio", audioSubtypeBuiltins, DIM(audioSubtypeBuiltins) },
202 //{ "model", modelSubtypeBuiltins, DIM(modelSubtypeBuiltins) },
203 //{ "video", videoSubtypeBuiltins, DIM(videoSubtypeBuiltins) },
204 { "*", anySubtypeBuiltins, DIM(anySubtypeBuiltins) },
205};
206
207#undef DIM
208
209const KMail::BodyPartFormatter * KMail::BodyPartFormatter::createFor( int type, int subtype ) {
210 DwString t, st;
211 DwTypeEnumToStr( type, t );
212 DwSubtypeEnumToStr( subtype, st );
213 return createFor( t.c_str(), st.c_str() );
214}
215
216static const KMail::BodyPartFormatter * createForText( const char * subtype ) {
217 if ( subtype && *subtype )
218 switch ( subtype[0] ) {
219 case 'h':
220 case 'H':
221 if ( kasciistricmp( subtype, "html" ) == 0 )
222 return TextHtmlBodyPartFormatter::create();
223 break;
224 case 'r':
225 case 'R':
226 if ( kasciistricmp( subtype, "rtf" ) == 0 )
227 return AnyTypeBodyPartFormatter::create();
228 break;
229 case 'x':
230 case 'X':
231 case 'v':
232 case 'V':
233 if ( kasciistricmp( subtype, "x-vcard" ) == 0 ||
234 kasciistricmp( subtype, "vcard" ) == 0 )
235 return AnyTypeBodyPartFormatter::create();
236 break;
237 }
238
239 return TextPlainBodyPartFormatter::create();
240}
241
242static const KMail::BodyPartFormatter * createForImage( const char * ) {
243 return ImageTypeBodyPartFormatter::create();
244}
245
246static const KMail::BodyPartFormatter * createForMessage( const char * subtype ) {
247 if ( kasciistricmp( subtype, "rfc822" ) == 0 )
248 return MessageRfc822BodyPartFormatter::create();
249 return AnyTypeBodyPartFormatter::create();
250}
251
252static const KMail::BodyPartFormatter * createForMultiPart( const char * subtype ) {
253 if ( subtype && *subtype )
254 switch ( subtype[0] ) {
255 case 'a':
256 case 'A':
257 if ( kasciistricmp( subtype, "alternative" ) == 0 )
258 return MultiPartAlternativeBodyPartFormatter::create();
259 break;
260 case 'e':
261 case 'E':
262 if ( kasciistricmp( subtype, "encrypted" ) == 0 )
263 return MultiPartEncryptedBodyPartFormatter::create();
264 break;
265 case 's':
266 case 'S':
267 if ( kasciistricmp( subtype, "signed" ) == 0 )
268 return MultiPartSignedBodyPartFormatter::create();
269 break;
270 }
271
272 return MultiPartMixedBodyPartFormatter::create();
273}
274
275static const KMail::BodyPartFormatter * createForApplication( const char * subtype ) {
276 if ( subtype && *subtype )
277 switch ( subtype[0] ) {
278 case 'p':
279 case 'P':
280 if ( kasciistricmp( subtype, "pgp" ) == 0 )
281 return ApplicationPgpBodyPartFormatter::create();
282 // fall through
283 case 'x':
284 case 'X':
285 if ( kasciistricmp( subtype, "pkcs7-mime" ) == 0 ||
286 kasciistricmp( subtype, "x-pkcs7-mime" ) == 0 )
287 return ApplicationPkcs7MimeBodyPartFormatter::create();
288 break;
289 case 'm':
290 case 'M':
291 if ( kasciistricmp( subtype, "ms-tnef" ) == 0 )
292 return ApplicationMsTnefBodyPartFormatter::create();
293 break;
294 case 'v':
295 case 'V':
296 if ( kasciistricmp( subtype, "vnd.de.bund.bsi.chiasmus-text") == 0)
297 return ApplicationChiasmusTextBodyPartFormatter::create();
298 break;
299 }
300
301 return AnyTypeBodyPartFormatter::create();
302}
303
304// OK, replace this with a factory with plugin support later on...
305const KMail::BodyPartFormatter * KMail::BodyPartFormatter::createFor( const char * type, const char * subtype ) {
306 if ( type && *type )
307 switch ( type[0] ) {
308 case 'a': // application
309 case 'A':
310 if ( kasciistricmp( type, "application" ) == 0 )
311 return createForApplication( subtype );
312 break;
313 case 'i': // image
314 case 'I':
315 if ( kasciistricmp( type, "image" ) == 0 )
316 return createForImage( subtype );
317 break;
318 case 'm': // multipart / message
319 case 'M':
320 if ( kasciistricmp( type, "multipart" ) == 0 )
321 return createForMultiPart( subtype );
322 else if ( kasciistricmp( type, "message" ) == 0 )
323 return createForMessage( subtype );
324 break;
325 case 't': // text
326 case 'T':
327 if ( kasciistricmp( type, "text" ) == 0 )
328 return createForText( subtype );
329 break;
330 }
331
332 return AnyTypeBodyPartFormatter::create();
333}
334
This class is used for callback hooks needed by bodypart formatter plugins.
Definition: callback.h:55
An interface to HTML sinks.
Definition: htmlwriter.h:99
interface of message body parts.
Definition: bodypart.h:75