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 
51 namespace {
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
134 void KMail::BodyPartFormatterFactoryPrivate::kmail_create_builtin_bodypart_formatters( KMail::BodyPartFormatterFactoryPrivate::TypeRegistry * reg ) {
135  if ( !reg ) return;
136  (*reg)["application"]["octet-stream"] = new AnyTypeBodyPartFormatter();
137 }
138 
139 typedef const KMail::BodyPartFormatter * (*BodyPartFormatterCreator)();
140 
141 struct SubtypeBuiltin {
142  const char * subtype;
143  BodyPartFormatterCreator create;
144 };
145 
146 static 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 
155 static 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 
164 static 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 
175 static const SubtypeBuiltin messageSubtypeBuiltins[] = {
176  { "rfc822", &MessageRfc822BodyPartFormatter::create },
177 };
178 
179 static const SubtypeBuiltin imageSubtypeBuiltins[] = {
180  { "*", &ImageTypeBodyPartFormatter::create },
181 };
182 
183 static 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 
192 static 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 
210 const 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 
217 static 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 
243 static const KMail::BodyPartFormatter * createForImage( const char * ) {
244  return ImageTypeBodyPartFormatter::create();
245 }
246 
247 static const KMail::BodyPartFormatter * createForMessage( const char * subtype ) {
248  if ( kasciistricmp( subtype, "rfc822" ) == 0 )
249  return MessageRfc822BodyPartFormatter::create();
250  return AnyTypeBodyPartFormatter::create();
251 }
252 
253 static 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 
276 static 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...
306 const 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