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 
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 
00118   CREATE_BODY_PART_FORMATTER(MessageRfc822)
00119 
00120   CREATE_BODY_PART_FORMATTER(MultiPartMixed)
00121   CREATE_BODY_PART_FORMATTER(MultiPartAlternative)
00122   CREATE_BODY_PART_FORMATTER(MultiPartSigned)
00123   CREATE_BODY_PART_FORMATTER(MultiPartEncrypted)
00124 
00125   typedef TextPlainBodyPartFormatter ApplicationPgpBodyPartFormatter;
00126 
00127 
00128 #undef CREATE_BODY_PART_FORMATTER
00129 } // anon namespace
00130 
00131 // FIXME: port some more KMail::BodyPartFormatters to KMail::Interface::BodyPartFormatters
00132 void KMail::BodyPartFormatterFactoryPrivate::kmail_create_builtin_bodypart_formatters( KMail::BodyPartFormatterFactoryPrivate::TypeRegistry * reg ) {
00133   if ( !reg ) return;
00134   (*reg)["application"]["octet-stream"] = new AnyTypeBodyPartFormatter();
00135 }
00136 
00137 typedef const KMail::BodyPartFormatter * (*BodyPartFormatterCreator)();
00138 
00139 struct SubtypeBuiltin {
00140   const char * subtype;
00141   BodyPartFormatterCreator create;
00142 };
00143 
00144 static const SubtypeBuiltin applicationSubtypeBuiltins[] = {
00145   { "octet-stream", &ApplicationOctetStreamBodyPartFormatter::create },
00146   { "pkcs7-mime", &ApplicationPkcs7MimeBodyPartFormatter::create },
00147   { "x-pkcs7-mime", &ApplicationPkcs7MimeBodyPartFormatter::create },
00148   { "vnd.de.bund.bsi.chiasmus-text", &ApplicationChiasmusTextBodyPartFormatter::create },
00149   { "pgp", &ApplicationPgpBodyPartFormatter::create },
00150 };
00151 
00152 static const SubtypeBuiltin textSubtypeBuiltins[] = {
00153   { "html", &TextHtmlBodyPartFormatter::create },
00154   //{ "enriched", &TextEnrichedBodyPartFormatter::create },
00155   { "x-vcard", &AnyTypeBodyPartFormatter::create },
00156   { "vcard", &AnyTypeBodyPartFormatter::create },
00157   { "rtf", &AnyTypeBodyPartFormatter::create },
00158   { "*", &TextPlainBodyPartFormatter::create },
00159 };
00160 
00161 static const SubtypeBuiltin multipartSubtypeBuiltins[] = {
00162   { "mixed", &MultiPartMixedBodyPartFormatter::create },
00163   { "alternative", &MultiPartAlternativeBodyPartFormatter::create },
00164   //{ "digest", &MultiPartDigestFormatter::create },
00165   //{ "parallel", &MultiPartParallelFormatter::create },
00166   //{ "related", &MultiPartRelatedFormatter::create },
00167   { "signed", &MultiPartSignedBodyPartFormatter::create },
00168   { "encrypted", &MultiPartEncryptedBodyPartFormatter::create },
00169   //{ "report", &MultiPartReportFormatter::create },
00170 };
00171 
00172 static const SubtypeBuiltin messageSubtypeBuiltins[] = {
00173   { "rfc822", &MessageRfc822BodyPartFormatter::create },
00174 };
00175 
00176 static const SubtypeBuiltin imageSubtypeBuiltins[] = {
00177   { "*", &ImageTypeBodyPartFormatter::create },
00178 };
00179 
00180 static const SubtypeBuiltin anySubtypeBuiltins[] = {
00181   { "*", &AnyTypeBodyPartFormatter::create },
00182 };
00183 
00184 #ifdef DIM
00185 #undef DIM
00186 #endif
00187 #define DIM(x) sizeof(x) / sizeof(*x)
00188 
00189 static const struct {
00190   const char * type;
00191   const SubtypeBuiltin * subtypes;
00192   unsigned int num_subtypes;
00193 } builtins[] = {
00194   { "application", applicationSubtypeBuiltins, DIM(applicationSubtypeBuiltins) },
00195   { "text", textSubtypeBuiltins, DIM(textSubtypeBuiltins) },
00196   { "multipart", multipartSubtypeBuiltins, DIM(multipartSubtypeBuiltins) },
00197   { "message", messageSubtypeBuiltins, DIM(messageSubtypeBuiltins) },
00198   { "image", imageSubtypeBuiltins, DIM(imageSubtypeBuiltins) },
00199   //{ "audio", audioSubtypeBuiltins, DIM(audioSubtypeBuiltins) },
00200   //{ "model", modelSubtypeBuiltins, DIM(modelSubtypeBuiltins) },
00201   //{ "video", videoSubtypeBuiltins, DIM(videoSubtypeBuiltins) },
00202   { "*", anySubtypeBuiltins, DIM(anySubtypeBuiltins) },
00203 };
00204 
00205 #undef DIM
00206 
00207 const KMail::BodyPartFormatter * KMail::BodyPartFormatter::createFor( int type, int subtype ) {
00208   DwString t, st;
00209   DwTypeEnumToStr( type, t );
00210   DwSubtypeEnumToStr( subtype, st );
00211   return createFor( t.c_str(), st.c_str() );
00212 }
00213 
00214 static const KMail::BodyPartFormatter * createForText( const char * subtype ) {
00215   if ( subtype && *subtype )
00216     switch ( subtype[0] ) {
00217     case 'h':
00218     case 'H':
00219       if ( kasciistricmp( subtype, "html" ) == 0 )
00220     return TextHtmlBodyPartFormatter::create();
00221       break;
00222     case 'r':
00223     case 'R':
00224       if ( kasciistricmp( subtype, "rtf" ) == 0 )
00225     return AnyTypeBodyPartFormatter::create();
00226       break;
00227     case 'x':
00228     case 'X':
00229     case 'v':
00230     case 'V':
00231       if ( kasciistricmp( subtype, "x-vcard" ) == 0 ||
00232        kasciistricmp( subtype, "vcard" ) == 0 )
00233     return AnyTypeBodyPartFormatter::create();
00234       break;
00235     }
00236 
00237   return TextPlainBodyPartFormatter::create();
00238 }
00239 
00240 static const KMail::BodyPartFormatter * createForImage( const char * ) {
00241   return ImageTypeBodyPartFormatter::create();
00242 }
00243 
00244 static const KMail::BodyPartFormatter * createForMessage( const char * subtype ) {
00245   if ( kasciistricmp( subtype, "rfc822" ) == 0 )
00246     return MessageRfc822BodyPartFormatter::create();
00247   return AnyTypeBodyPartFormatter::create();
00248 }
00249 
00250 static const KMail::BodyPartFormatter * createForMultiPart( const char * subtype ) {
00251   if ( subtype && *subtype )
00252     switch ( subtype[0] ) {
00253     case 'a':
00254     case 'A':
00255       if ( kasciistricmp( subtype, "alternative" ) == 0 )
00256     return MultiPartAlternativeBodyPartFormatter::create();
00257       break;
00258     case 'e':
00259     case 'E':
00260       if ( kasciistricmp( subtype, "encrypted" ) == 0 )
00261     return MultiPartEncryptedBodyPartFormatter::create();
00262       break;
00263     case 's':
00264     case 'S':
00265       if ( kasciistricmp( subtype, "signed" ) == 0 )
00266     return MultiPartSignedBodyPartFormatter::create();
00267       break;
00268     }
00269 
00270   return MultiPartMixedBodyPartFormatter::create();
00271 }
00272 
00273 static const KMail::BodyPartFormatter * createForApplication( const char * subtype ) {
00274   if ( subtype && *subtype )
00275     switch ( subtype[0] ) {
00276     case 'p':
00277     case 'P':
00278       if ( kasciistricmp( subtype, "pgp" ) == 0 )
00279     return ApplicationPgpBodyPartFormatter::create();
00280       // fall through
00281     case 'x':
00282     case 'X':
00283       if ( kasciistricmp( subtype, "pkcs7-mime" ) == 0 ||
00284        kasciistricmp( subtype, "x-pkcs7-mime" ) == 0 )
00285     return ApplicationPkcs7MimeBodyPartFormatter::create();
00286       break;
00287     case 'm':
00288     case 'M':
00289       //if ( kasciistricmp( subtype, "ms-tnef" ) == 0 )
00290       //  return ApplicationMsTnefBodyPartFormatter::create();
00291       break;
00292     case 'v':
00293     case 'V':
00294       if ( kasciistricmp( subtype, "vnd.de.bund.bsi.chiasmus-text") == 0)
00295         return ApplicationChiasmusTextBodyPartFormatter::create();
00296       break;
00297     }
00298 
00299   return AnyTypeBodyPartFormatter::create();
00300 }
00301 
00302 // OK, replace this with a factory with plugin support later on...
00303 const KMail::BodyPartFormatter * KMail::BodyPartFormatter::createFor( const char * type, const char * subtype ) {
00304   if ( type && *type )
00305     switch ( type[0] ) {
00306     case 'a': // application
00307     case 'A':
00308       if ( kasciistricmp( type, "application" ) == 0 )
00309     return createForApplication( subtype );
00310       break;
00311     case 'i': // image
00312     case 'I':
00313       if ( kasciistricmp( type, "image" ) == 0 )
00314     return createForImage( subtype );
00315       break;
00316     case 'm': // multipart / message
00317     case 'M':
00318       if ( kasciistricmp( type, "multipart" ) == 0 )
00319     return createForMultiPart( subtype );
00320       else if ( kasciistricmp( type, "message" ) == 0 )
00321     return createForMessage( subtype );
00322       break;
00323     case 't': // text
00324     case 'T':
00325       if ( kasciistricmp( type, "text" ) == 0 )
00326     return createForText( subtype );
00327       break;
00328     }
00329 
00330   return AnyTypeBodyPartFormatter::create();
00331 }
00332 
KDE Home | KDE Accessibility Home | Description of Access Keys