kmail

bodypartformatter.cpp

Go to the documentation of this file.
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 
00043 #include <mimelib/enum.h>
00044 #include <mimelib/string.h>
00045 #include <mimelib/utility.h>
00046 
00047 #include <kdebug.h>
00048 #include <kasciistricmp.h>
00049 
00050 namespace {
00051   class AnyTypeBodyPartFormatter
00052     : public KMail::BodyPartFormatter,
00053       public KMail::Interface::BodyPartFormatter {
00054     static const AnyTypeBodyPartFormatter * self;
00055   public:
00056     Result format( KMail::Interface::BodyPart *, KMail::HtmlWriter * ) const {
00057       kdDebug(5006) << "AnyTypeBodyPartFormatter::format() acting as a KMail::Interface::BodyPartFormatter!" << endl;
00058       return AsIcon;
00059     }
00060 
00061     bool process( KMail::ObjectTreeParser *, partNode *, KMail::ProcessResult & result ) const {
00062       result.setNeverDisplayInline( true );
00063       return false;
00064     }
00065     static const KMail::BodyPartFormatter * create() {
00066       if ( !self )
00067     self = new AnyTypeBodyPartFormatter();
00068       return self;
00069     }
00070   };
00071 
00072   const AnyTypeBodyPartFormatter * AnyTypeBodyPartFormatter::self = 0;
00073 
00074 
00075   class ImageTypeBodyPartFormatter : public KMail::BodyPartFormatter {
00076     static const ImageTypeBodyPartFormatter * self;
00077   public:
00078     bool process( KMail::ObjectTreeParser *, partNode *, KMail::ProcessResult & result ) const {
00079       result.setIsImage( true );
00080       return false;
00081     }
00082     static const KMail::BodyPartFormatter * create() {
00083       if ( !self )
00084     self = new ImageTypeBodyPartFormatter();
00085       return self;
00086     }
00087   };
00088 
00089   const ImageTypeBodyPartFormatter * ImageTypeBodyPartFormatter::self = 0;
00090 
00091 #define CREATE_BODY_PART_FORMATTER(subtype) \
00092   class subtype##BodyPartFormatter : public KMail::BodyPartFormatter { \
00093     static const subtype##BodyPartFormatter * self; \
00094   public: \
00095     bool process( KMail::ObjectTreeParser *, partNode *, KMail::ProcessResult & ) const; \
00096     static const KMail::BodyPartFormatter * create() { \
00097       if ( !self ) \
00098     self = new subtype##BodyPartFormatter(); \
00099       return self; \
00100     } \
00101   }; \
00102   \
00103   const subtype##BodyPartFormatter * subtype##BodyPartFormatter::self; \
00104   \
00105   bool subtype##BodyPartFormatter::process( KMail::ObjectTreeParser * otp, partNode * node, KMail::ProcessResult & result ) const { \
00106     return otp->process##subtype##Subtype( node, result ); \
00107   }
00108 
00109   CREATE_BODY_PART_FORMATTER(TextPlain)
00110   CREATE_BODY_PART_FORMATTER(TextHtml)
00111   //CREATE_BODY_PART_FORMATTER(TextEnriched)
00112 
00113   CREATE_BODY_PART_FORMATTER(ApplicationOctetStream)
00114   CREATE_BODY_PART_FORMATTER(ApplicationPkcs7Mime)
00115   CREATE_BODY_PART_FORMATTER(ApplicationChiasmusText)
00116   //CREATE_BODY_PART_FORMATTER(ApplicationPgp)
00117   CREATE_BODY_PART_FORMATTER(ApplicationMsTnef)
00118 
00119   CREATE_BODY_PART_FORMATTER(MessageRfc822)
00120 
00121   CREATE_BODY_PART_FORMATTER(MultiPartMixed)
00122   CREATE_BODY_PART_FORMATTER(MultiPartAlternative)
00123   CREATE_BODY_PART_FORMATTER(MultiPartSigned)
00124   CREATE_BODY_PART_FORMATTER(MultiPartEncrypted)
00125 
00126   typedef TextPlainBodyPartFormatter ApplicationPgpBodyPartFormatter;
00127 
00128 
00129 #undef CREATE_BODY_PART_FORMATTER
00130 } // anon namespace
00131 
00132 // FIXME: port some more KMail::BodyPartFormatters to KMail::Interface::BodyPartFormatters
00133 void KMail::BodyPartFormatterFactoryPrivate::kmail_create_builtin_bodypart_formatters( KMail::BodyPartFormatterFactoryPrivate::TypeRegistry * reg ) {
00134   if ( !reg ) return;
00135   (*reg)["application"]["octet-stream"] = new AnyTypeBodyPartFormatter();
00136 }
00137 
00138 typedef const KMail::BodyPartFormatter * (*BodyPartFormatterCreator)();
00139 
00140 struct SubtypeBuiltin {
00141   const char * subtype;
00142   BodyPartFormatterCreator create;
00143 };
00144 
00145 static const SubtypeBuiltin applicationSubtypeBuiltins[] = {
00146   { "octet-stream", &ApplicationOctetStreamBodyPartFormatter::create },
00147   { "pkcs7-mime", &ApplicationPkcs7MimeBodyPartFormatter::create },
00148   { "x-pkcs7-mime", &ApplicationPkcs7MimeBodyPartFormatter::create },
00149   { "vnd.de.bund.bsi.chiasmus-text", &ApplicationChiasmusTextBodyPartFormatter::create },
00150   { "pgp", &ApplicationPgpBodyPartFormatter::create },
00151   { "ms-tnef", &ApplicationMsTnefBodyPartFormatter::create }
00152 };
00153 
00154 static const SubtypeBuiltin textSubtypeBuiltins[] = {
00155   { "html", &TextHtmlBodyPartFormatter::create },
00156   //{ "enriched", &TextEnrichedBodyPartFormatter::create },
00157   { "x-vcard", &AnyTypeBodyPartFormatter::create },
00158   { "vcard", &AnyTypeBodyPartFormatter::create },
00159   { "rtf", &AnyTypeBodyPartFormatter::create },
00160   { "*", &TextPlainBodyPartFormatter::create },
00161 };
00162 
00163 static const SubtypeBuiltin multipartSubtypeBuiltins[] = {
00164   { "mixed", &MultiPartMixedBodyPartFormatter::create },
00165   { "alternative", &MultiPartAlternativeBodyPartFormatter::create },
00166   //{ "digest", &MultiPartDigestFormatter::create },
00167   //{ "parallel", &MultiPartParallelFormatter::create },
00168   //{ "related", &MultiPartRelatedFormatter::create },
00169   { "signed", &MultiPartSignedBodyPartFormatter::create },
00170   { "encrypted", &MultiPartEncryptedBodyPartFormatter::create },
00171   //{ "report", &MultiPartReportFormatter::create },
00172 };
00173 
00174 static const SubtypeBuiltin messageSubtypeBuiltins[] = {
00175   { "rfc822", &MessageRfc822BodyPartFormatter::create },
00176 };
00177 
00178 static const SubtypeBuiltin imageSubtypeBuiltins[] = {
00179   { "*", &ImageTypeBodyPartFormatter::create },
00180 };
00181 
00182 static const SubtypeBuiltin anySubtypeBuiltins[] = {
00183   { "*", &AnyTypeBodyPartFormatter::create },
00184 };
00185 
00186 #ifdef DIM
00187 #undef DIM
00188 #endif
00189 #define DIM(x) sizeof(x) / sizeof(*x)
00190 
00191 static const struct {
00192   const char * type;
00193   const SubtypeBuiltin * subtypes;
00194   unsigned int num_subtypes;
00195 } builtins[] = {
00196   { "application", applicationSubtypeBuiltins, DIM(applicationSubtypeBuiltins) },
00197   { "text", textSubtypeBuiltins, DIM(textSubtypeBuiltins) },
00198   { "multipart", multipartSubtypeBuiltins, DIM(multipartSubtypeBuiltins) },
00199   { "message", messageSubtypeBuiltins, DIM(messageSubtypeBuiltins) },
00200   { "image", imageSubtypeBuiltins, DIM(imageSubtypeBuiltins) },
00201   //{ "audio", audioSubtypeBuiltins, DIM(audioSubtypeBuiltins) },
00202   //{ "model", modelSubtypeBuiltins, DIM(modelSubtypeBuiltins) },
00203   //{ "video", videoSubtypeBuiltins, DIM(videoSubtypeBuiltins) },
00204   { "*", anySubtypeBuiltins, DIM(anySubtypeBuiltins) },
00205 };
00206 
00207 #undef DIM
00208 
00209 const KMail::BodyPartFormatter * KMail::BodyPartFormatter::createFor( int type, int subtype ) {
00210   DwString t, st;
00211   DwTypeEnumToStr( type, t );
00212   DwSubtypeEnumToStr( subtype, st );
00213   return createFor( t.c_str(), st.c_str() );
00214 }
00215 
00216 static const KMail::BodyPartFormatter * createForText( const char * subtype ) {
00217   if ( subtype && *subtype )
00218     switch ( subtype[0] ) {
00219     case 'h':
00220     case 'H':
00221       if ( kasciistricmp( subtype, "html" ) == 0 )
00222     return TextHtmlBodyPartFormatter::create();
00223       break;
00224     case 'r':
00225     case 'R':
00226       if ( kasciistricmp( subtype, "rtf" ) == 0 )
00227     return AnyTypeBodyPartFormatter::create();
00228       break;
00229     case 'x':
00230     case 'X':
00231     case 'v':
00232     case 'V':
00233       if ( kasciistricmp( subtype, "x-vcard" ) == 0 ||
00234        kasciistricmp( subtype, "vcard" ) == 0 )
00235     return AnyTypeBodyPartFormatter::create();
00236       break;
00237     }
00238 
00239   return TextPlainBodyPartFormatter::create();
00240 }
00241 
00242 static const KMail::BodyPartFormatter * createForImage( const char * ) {
00243   return ImageTypeBodyPartFormatter::create();
00244 }
00245 
00246 static const KMail::BodyPartFormatter * createForMessage( const char * subtype ) {
00247   if ( kasciistricmp( subtype, "rfc822" ) == 0 )
00248     return MessageRfc822BodyPartFormatter::create();
00249   return AnyTypeBodyPartFormatter::create();
00250 }
00251 
00252 static const KMail::BodyPartFormatter * createForMultiPart( const char * subtype ) {
00253   if ( subtype && *subtype )
00254     switch ( subtype[0] ) {
00255     case 'a':
00256     case 'A':
00257       if ( kasciistricmp( subtype, "alternative" ) == 0 )
00258     return MultiPartAlternativeBodyPartFormatter::create();
00259       break;
00260     case 'e':
00261     case 'E':
00262       if ( kasciistricmp( subtype, "encrypted" ) == 0 )
00263     return MultiPartEncryptedBodyPartFormatter::create();
00264       break;
00265     case 's':
00266     case 'S':
00267       if ( kasciistricmp( subtype, "signed" ) == 0 )
00268     return MultiPartSignedBodyPartFormatter::create();
00269       break;
00270     }
00271 
00272   return MultiPartMixedBodyPartFormatter::create();
00273 }
00274 
00275 static const KMail::BodyPartFormatter * createForApplication( const char * subtype ) {
00276   if ( subtype && *subtype )
00277     switch ( subtype[0] ) {
00278     case 'p':
00279     case 'P':
00280       if ( kasciistricmp( subtype, "pgp" ) == 0 )
00281     return ApplicationPgpBodyPartFormatter::create();
00282       // fall through
00283     case 'x':
00284     case 'X':
00285       if ( kasciistricmp( subtype, "pkcs7-mime" ) == 0 ||
00286        kasciistricmp( subtype, "x-pkcs7-mime" ) == 0 )
00287     return ApplicationPkcs7MimeBodyPartFormatter::create();
00288       break;
00289     case 'm':
00290     case 'M':
00291       if ( kasciistricmp( subtype, "ms-tnef" ) == 0 )
00292         return ApplicationMsTnefBodyPartFormatter::create();
00293       break;
00294     case 'v':
00295     case 'V':
00296       if ( kasciistricmp( subtype, "vnd.de.bund.bsi.chiasmus-text") == 0)
00297         return ApplicationChiasmusTextBodyPartFormatter::create();
00298       break;
00299     }
00300 
00301   return AnyTypeBodyPartFormatter::create();
00302 }
00303 
00304 // OK, replace this with a factory with plugin support later on...
00305 const KMail::BodyPartFormatter * KMail::BodyPartFormatter::createFor( const char * type, const char * subtype ) {
00306   if ( type && *type )
00307     switch ( type[0] ) {
00308     case 'a': // application
00309     case 'A':
00310       if ( kasciistricmp( type, "application" ) == 0 )
00311     return createForApplication( subtype );
00312       break;
00313     case 'i': // image
00314     case 'I':
00315       if ( kasciistricmp( type, "image" ) == 0 )
00316     return createForImage( subtype );
00317       break;
00318     case 'm': // multipart / message
00319     case 'M':
00320       if ( kasciistricmp( type, "multipart" ) == 0 )
00321     return createForMultiPart( subtype );
00322       else if ( kasciistricmp( type, "message" ) == 0 )
00323     return createForMessage( subtype );
00324       break;
00325     case 't': // text
00326     case 'T':
00327       if ( kasciistricmp( type, "text" ) == 0 )
00328     return createForText( subtype );
00329       break;
00330     }
00331 
00332   return AnyTypeBodyPartFormatter::create();
00333 }
00334