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 TQt library by Trolltech AS, Norway (or with modified versions 00023 of TQt that use the same license as TQt), 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 TQt. 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