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 
50 namespace {
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
133 void KMail::BodyPartFormatterFactoryPrivate::kmail_create_builtin_bodypart_formatters( KMail::BodyPartFormatterFactoryPrivate::TypeRegistry * reg ) {
134  if ( !reg ) return;
135  (*reg)["application"]["octet-stream"] = new AnyTypeBodyPartFormatter();
136 }
137 
138 typedef const KMail::BodyPartFormatter * (*BodyPartFormatterCreator)();
139 
140 struct SubtypeBuiltin {
141  const char * subtype;
142  BodyPartFormatterCreator create;
143 };
144 
145 static 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 
154 static 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 
163 static 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 
174 static const SubtypeBuiltin messageSubtypeBuiltins[] = {
175  { "rfc822", &MessageRfc822BodyPartFormatter::create },
176 };
177 
178 static const SubtypeBuiltin imageSubtypeBuiltins[] = {
179  { "*", &ImageTypeBodyPartFormatter::create },
180 };
181 
182 static 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 
191 static 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 
209 const 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 
216 static 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 
242 static const KMail::BodyPartFormatter * createForImage( const char * ) {
243  return ImageTypeBodyPartFormatter::create();
244 }
245 
246 static const KMail::BodyPartFormatter * createForMessage( const char * subtype ) {
247  if ( kasciistricmp( subtype, "rfc822" ) == 0 )
248  return MessageRfc822BodyPartFormatter::create();
249  return AnyTypeBodyPartFormatter::create();
250 }
251 
252 static 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 
275 static 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...
305 const 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