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