kmail

bodypartformatter.cpp

00001 /*  -*- c++ -*-
00002     bodypartformatter.cpp
00003 
00004     This file is part of KMail, the KDE mail client.
00005     Copyright (c) 2003 Marc Mutz <mutz@kde.org>
00006 
00007     KMail is free software; you can redistribute it and/or modify it
00008     under the terms of the GNU General Public License, version 2, as
00009     published by the Free Software Foundation.
00010 
00011     KMail is distributed in the hope that it will be useful, but
00012     WITHOUT ANY WARRANTY; without even the implied warranty of
00013     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00014     General Public License for more details.
00015 
00016     You should have received a copy of the GNU General Public License
00017     along with this program; if not, write to the Free Software
00018     Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
00019 
00020     In addition, as a special exception, the copyright holders give
00021     permission to link the code of this program with any edition of
00022     the Qt library by Trolltech AS, Norway (or with modified versions
00023     of Qt that use the same license as Qt), and distribute linked
00024     combinations including the two.  You must obey the GNU General
00025     Public License in all respects for all of the code used other than
00026     Qt.  If you modify this file, you may extend this exception to
00027     your version of the file, but you are not obligated to do so.  If
00028     you do not wish to do so, delete this exception statement from
00029     your version.
00030 */
00031 
00032 #ifdef HAVE_CONFIG_H
00033 #include <config.h>
00034 #endif
00035 
00036 #include "bodypartformatter.h"
00037 #include "bodypartformatterfactory_p.h"
00038 #include "interfaces/bodypartformatter.h"
00039 
00040 #include "objecttreeparser.h"
00041 #include "partNode.h"
00042 #include "callback.h"
00043 
00044 #include <mimelib/enum.h>
00045 #include <mimelib/string.h>
00046 #include <mimelib/utility.h>
00047 
00048 #include <kdebug.h>
00049 #include <kasciistricmp.h>
00050 
00051 namespace {
00052   class AnyTypeBodyPartFormatter
00053     : public KMail::BodyPartFormatter,
00054       public KMail::Interface::BodyPartFormatter {
00055     static const AnyTypeBodyPartFormatter * self;
00056   public:
00057     Result format( KMail::Interface::BodyPart *, KMail::HtmlWriter *, KMail::Callback & ) const {
00058       kdDebug(5006) << "AnyTypeBodyPartFormatter::format() acting as a KMail::Interface::BodyPartFormatter!" << endl;
00059       return AsIcon;
00060     }
00061 
00062     bool process( KMail::ObjectTreeParser *, partNode *, KMail::ProcessResult & result ) const {
00063       result.setNeverDisplayInline( true );
00064       return false;
00065     }
00066     static const KMail::BodyPartFormatter * create() {
00067       if ( !self )
00068     self = new AnyTypeBodyPartFormatter();
00069       return self;
00070     }
00071   };
00072 
00073   const AnyTypeBodyPartFormatter * AnyTypeBodyPartFormatter::self = 0;
00074 
00075 
00076   class ImageTypeBodyPartFormatter : public KMail::BodyPartFormatter {
00077     static const ImageTypeBodyPartFormatter * self;
00078   public:
00079     bool process( KMail::ObjectTreeParser *, partNode *, KMail::ProcessResult & result ) const {
00080       result.setIsImage( true );
00081       return false;
00082     }
00083     static const KMail::BodyPartFormatter * create() {
00084       if ( !self )
00085     self = new ImageTypeBodyPartFormatter();
00086       return self;
00087     }
00088   };
00089 
00090   const ImageTypeBodyPartFormatter * ImageTypeBodyPartFormatter::self = 0;
00091 
00092 #define CREATE_BODY_PART_FORMATTER(subtype) \
00093   class subtype##BodyPartFormatter : public KMail::BodyPartFormatter { \
00094     static const subtype##BodyPartFormatter * self; \
00095   public: \
00096     bool process( KMail::ObjectTreeParser *, partNode *, KMail::ProcessResult & ) const; \
00097     static const KMail::BodyPartFormatter * create() { \
00098       if ( !self ) \
00099     self = new subtype##BodyPartFormatter(); \
00100       return self; \
00101     } \
00102   }; \
00103   \
00104   const subtype##BodyPartFormatter * subtype##BodyPartFormatter::self; \
00105   \
00106   bool subtype##BodyPartFormatter::process( KMail::ObjectTreeParser * otp, partNode * node, KMail::ProcessResult & result ) const { \
00107     return otp->process##subtype##Subtype( node, result ); \
00108   }
00109 
00110   CREATE_BODY_PART_FORMATTER(TextPlain)
00111   CREATE_BODY_PART_FORMATTER(TextHtml)
00112   //CREATE_BODY_PART_FORMATTER(TextEnriched)
00113 
00114   CREATE_BODY_PART_FORMATTER(ApplicationOctetStream)
00115   CREATE_BODY_PART_FORMATTER(ApplicationPkcs7Mime)
00116   CREATE_BODY_PART_FORMATTER(ApplicationChiasmusText)
00117   //CREATE_BODY_PART_FORMATTER(ApplicationPgp)
00118   CREATE_BODY_PART_FORMATTER(ApplicationMsTnef)
00119 
00120   CREATE_BODY_PART_FORMATTER(MessageRfc822)
00121 
00122   CREATE_BODY_PART_FORMATTER(MultiPartMixed)
00123   CREATE_BODY_PART_FORMATTER(MultiPartAlternative)
00124   CREATE_BODY_PART_FORMATTER(MultiPartSigned)
00125   CREATE_BODY_PART_FORMATTER(MultiPartEncrypted)
00126 
00127   typedef TextPlainBodyPartFormatter ApplicationPgpBodyPartFormatter;
00128 
00129 
00130 #undef CREATE_BODY_PART_FORMATTER
00131 } // anon namespace
00132 
00133 // FIXME: port some more KMail::BodyPartFormatters to KMail::Interface::BodyPartFormatters
00134 void KMail::BodyPartFormatterFactoryPrivate::kmail_create_builtin_bodypart_formatters( KMail::BodyPartFormatterFactoryPrivate::TypeRegistry * reg ) {
00135   if ( !reg ) return;
00136   (*reg)["application"]["octet-stream"] = new AnyTypeBodyPartFormatter();
00137 }
00138 
00139 typedef const KMail::BodyPartFormatter * (*BodyPartFormatterCreator)();
00140 
00141 struct SubtypeBuiltin {
00142   const char * subtype;
00143   BodyPartFormatterCreator create;
00144 };
00145 
00146 static const SubtypeBuiltin applicationSubtypeBuiltins[] = {
00147   { "octet-stream", &ApplicationOctetStreamBodyPartFormatter::create },
00148   { "pkcs7-mime", &ApplicationPkcs7MimeBodyPartFormatter::create },
00149   { "x-pkcs7-mime", &ApplicationPkcs7MimeBodyPartFormatter::create },
00150   { "vnd.de.bund.bsi.chiasmus-text", &ApplicationChiasmusTextBodyPartFormatter::create },
00151   { "pgp", &ApplicationPgpBodyPartFormatter::create },
00152   { "ms-tnef", &ApplicationMsTnefBodyPartFormatter::create }
00153 };
00154 
00155 static const SubtypeBuiltin textSubtypeBuiltins[] = {
00156   { "html", &TextHtmlBodyPartFormatter::create },
00157   //{ "enriched", &TextEnrichedBodyPartFormatter::create },
00158   { "x-vcard", &AnyTypeBodyPartFormatter::create },
00159   { "vcard", &AnyTypeBodyPartFormatter::create },
00160   { "rtf", &AnyTypeBodyPartFormatter::create },
00161   { "*", &TextPlainBodyPartFormatter::create },
00162 };
00163 
00164 static const SubtypeBuiltin multipartSubtypeBuiltins[] = {
00165   { "mixed", &MultiPartMixedBodyPartFormatter::create },
00166   { "alternative", &MultiPartAlternativeBodyPartFormatter::create },
00167   //{ "digest", &MultiPartDigestFormatter::create },
00168   //{ "parallel", &MultiPartParallelFormatter::create },
00169   //{ "related", &MultiPartRelatedFormatter::create },
00170   { "signed", &MultiPartSignedBodyPartFormatter::create },
00171   { "encrypted", &MultiPartEncryptedBodyPartFormatter::create },
00172   //{ "report", &MultiPartReportFormatter::create },
00173 };
00174 
00175 static const SubtypeBuiltin messageSubtypeBuiltins[] = {
00176   { "rfc822", &MessageRfc822BodyPartFormatter::create },
00177 };
00178 
00179 static const SubtypeBuiltin imageSubtypeBuiltins[] = {
00180   { "*", &ImageTypeBodyPartFormatter::create },
00181 };
00182 
00183 static const SubtypeBuiltin anySubtypeBuiltins[] = {
00184   { "*", &AnyTypeBodyPartFormatter::create },
00185 };
00186 
00187 #ifdef DIM
00188 #undef DIM
00189 #endif
00190 #define DIM(x) sizeof(x) / sizeof(*x)
00191 
00192 static const struct {
00193   const char * type;
00194   const SubtypeBuiltin * subtypes;
00195   unsigned int num_subtypes;
00196 } builtins[] = {
00197   { "application", applicationSubtypeBuiltins, DIM(applicationSubtypeBuiltins) },
00198   { "text", textSubtypeBuiltins, DIM(textSubtypeBuiltins) },
00199   { "multipart", multipartSubtypeBuiltins, DIM(multipartSubtypeBuiltins) },
00200   { "message", messageSubtypeBuiltins, DIM(messageSubtypeBuiltins) },
00201   { "image", imageSubtypeBuiltins, DIM(imageSubtypeBuiltins) },
00202   //{ "audio", audioSubtypeBuiltins, DIM(audioSubtypeBuiltins) },
00203   //{ "model", modelSubtypeBuiltins, DIM(modelSubtypeBuiltins) },
00204   //{ "video", videoSubtypeBuiltins, DIM(videoSubtypeBuiltins) },
00205   { "*", anySubtypeBuiltins, DIM(anySubtypeBuiltins) },
00206 };
00207 
00208 #undef DIM
00209 
00210 const KMail::BodyPartFormatter * KMail::BodyPartFormatter::createFor( int type, int subtype ) {
00211   DwString t, st;
00212   DwTypeEnumToStr( type, t );
00213   DwSubtypeEnumToStr( subtype, st );
00214   return createFor( t.c_str(), st.c_str() );
00215 }
00216 
00217 static const KMail::BodyPartFormatter * createForText( const char * subtype ) {
00218   if ( subtype && *subtype )
00219     switch ( subtype[0] ) {
00220     case 'h':
00221     case 'H':
00222       if ( kasciistricmp( subtype, "html" ) == 0 )
00223     return TextHtmlBodyPartFormatter::create();
00224       break;
00225     case 'r':
00226     case 'R':
00227       if ( kasciistricmp( subtype, "rtf" ) == 0 )
00228     return AnyTypeBodyPartFormatter::create();
00229       break;
00230     case 'x':
00231     case 'X':
00232     case 'v':
00233     case 'V':
00234       if ( kasciistricmp( subtype, "x-vcard" ) == 0 ||
00235        kasciistricmp( subtype, "vcard" ) == 0 )
00236     return AnyTypeBodyPartFormatter::create();
00237       break;
00238     }
00239 
00240   return TextPlainBodyPartFormatter::create();
00241 }
00242 
00243 static const KMail::BodyPartFormatter * createForImage( const char * ) {
00244   return ImageTypeBodyPartFormatter::create();
00245 }
00246 
00247 static const KMail::BodyPartFormatter * createForMessage( const char * subtype ) {
00248   if ( kasciistricmp( subtype, "rfc822" ) == 0 )
00249     return MessageRfc822BodyPartFormatter::create();
00250   return AnyTypeBodyPartFormatter::create();
00251 }
00252 
00253 static const KMail::BodyPartFormatter * createForMultiPart( const char * subtype ) {
00254   if ( subtype && *subtype )
00255     switch ( subtype[0] ) {
00256     case 'a':
00257     case 'A':
00258       if ( kasciistricmp( subtype, "alternative" ) == 0 )
00259     return MultiPartAlternativeBodyPartFormatter::create();
00260       break;
00261     case 'e':
00262     case 'E':
00263       if ( kasciistricmp( subtype, "encrypted" ) == 0 )
00264     return MultiPartEncryptedBodyPartFormatter::create();
00265       break;
00266     case 's':
00267     case 'S':
00268       if ( kasciistricmp( subtype, "signed" ) == 0 )
00269     return MultiPartSignedBodyPartFormatter::create();
00270       break;
00271     }
00272 
00273   return MultiPartMixedBodyPartFormatter::create();
00274 }
00275 
00276 static const KMail::BodyPartFormatter * createForApplication( const char * subtype ) {
00277   if ( subtype && *subtype )
00278     switch ( subtype[0] ) {
00279     case 'p':
00280     case 'P':
00281       if ( kasciistricmp( subtype, "pgp" ) == 0 )
00282     return ApplicationPgpBodyPartFormatter::create();
00283       // fall through
00284     case 'x':
00285     case 'X':
00286       if ( kasciistricmp( subtype, "pkcs7-mime" ) == 0 ||
00287        kasciistricmp( subtype, "x-pkcs7-mime" ) == 0 )
00288     return ApplicationPkcs7MimeBodyPartFormatter::create();
00289       break;
00290     case 'm':
00291     case 'M':
00292       if ( kasciistricmp( subtype, "ms-tnef" ) == 0 )
00293         return ApplicationMsTnefBodyPartFormatter::create();
00294       break;
00295     case 'v':
00296     case 'V':
00297       if ( kasciistricmp( subtype, "vnd.de.bund.bsi.chiasmus-text") == 0)
00298         return ApplicationChiasmusTextBodyPartFormatter::create();
00299       break;
00300     }
00301 
00302   return AnyTypeBodyPartFormatter::create();
00303 }
00304 
00305 // OK, replace this with a factory with plugin support later on...
00306 const KMail::BodyPartFormatter * KMail::BodyPartFormatter::createFor( const char * type, const char * subtype ) {
00307   if ( type && *type )
00308     switch ( type[0] ) {
00309     case 'a': // application
00310     case 'A':
00311       if ( kasciistricmp( type, "application" ) == 0 )
00312     return createForApplication( subtype );
00313       break;
00314     case 'i': // image
00315     case 'I':
00316       if ( kasciistricmp( type, "image" ) == 0 )
00317     return createForImage( subtype );
00318       break;
00319     case 'm': // multipart / message
00320     case 'M':
00321       if ( kasciistricmp( type, "multipart" ) == 0 )
00322     return createForMultiPart( subtype );
00323       else if ( kasciistricmp( type, "message" ) == 0 )
00324     return createForMessage( subtype );
00325       break;
00326     case 't': // text
00327     case 'T':
00328       if ( kasciistricmp( type, "text" ) == 0 )
00329     return createForText( subtype );
00330       break;
00331     }
00332 
00333   return AnyTypeBodyPartFormatter::create();
00334 }
00335