00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032 #ifdef HAVE_CONFIG_H
00033 #include <config.h>
00034 #endif
00035
00036 #include "headerstyle.h"
00037
00038 #include "headerstrategy.h"
00039 #include "kmkernel.h"
00040 #include "linklocator.h"
00041 #include "kmmessage.h"
00042 #include "spamheaderanalyzer.h"
00043 #include "globalsettings.h"
00044
00045 #include <libemailfunctions/email.h>
00046 #include <libkdepim/kxface.h>
00047 using namespace KPIM;
00048
00049 #include <mimelib/string.h>
00050 #include <mimelib/field.h>
00051 #include <mimelib/headers.h>
00052
00053 #include <kdebug.h>
00054 #include <klocale.h>
00055 #include <kglobal.h>
00056 #include <kimproxy.h>
00057 #include <kabc/stdaddressbook.h>
00058 #include <kabc/addresseelist.h>
00059 #include <kmdcodec.h>
00060 #include <qdatetime.h>
00061 #include <qbuffer.h>
00062 #include <qbitmap.h>
00063 #include <qimage.h>
00064 #include <qapplication.h>
00065 #include <qregexp.h>
00066
00067 #include <kstandarddirs.h>
00068
00069 namespace KMail {
00070
00071
00072
00073
00074 static inline QString directionOf( const QString & str ) {
00075 return str.isRightToLeft() ? "rtl" : "ltr" ;
00076 }
00077
00078 #if 0
00079
00080
00081
00082 static QString convertToHtmlBlock( const QString & str, bool useSpan=false ) {
00083 QString dir = directionOf( str );
00084 QString format = "<%1 dir=\"%3\">%4</%2>";
00085 return format.arg( useSpan ? "span" : "div" )
00086 .arg( useSpan ? "span" : "div" )
00087 .arg( dir )
00088 .arg( LinkLocator::convertToHtml( str ) );
00089 }
00090 #endif
00091
00092
00093 static QString strToHtml( const QString & str,
00094 int flags = LinkLocator::PreserveSpaces ) {
00095 return LinkLocator::convertToHtml( str, flags );
00096 }
00097
00098
00099
00100
00101
00102
00103 class BriefHeaderStyle : public HeaderStyle {
00104 friend class ::KMail::HeaderStyle;
00105 protected:
00106 BriefHeaderStyle() : HeaderStyle() {}
00107 virtual ~BriefHeaderStyle() {}
00108
00109 public:
00110 const char * name() const { return "brief"; }
00111 const HeaderStyle * next() const { return plain(); }
00112 const HeaderStyle * prev() const { return fancy(); }
00113
00114 QString format( const KMMessage * message, const HeaderStrategy * strategy,
00115 const QString & vCardName, bool printing, bool topLevel ) const;
00116 };
00117
00118 QString BriefHeaderStyle::format( const KMMessage * message,
00119 const HeaderStrategy * strategy,
00120 const QString & vCardName, bool printing, bool topLevel ) const {
00121 Q_UNUSED( topLevel );
00122 if ( !message ) return QString::null;
00123 if ( !strategy )
00124 strategy = HeaderStrategy::brief();
00125
00126
00127
00128
00129 QString dir = QApplication::reverseLayout() ? "rtl" : "ltr" ;
00130
00131
00132
00133
00134
00135
00136
00137 QString subjectDir;
00138 if (!message->subject().isEmpty())
00139 subjectDir = directionOf( message->cleanSubject() );
00140 else
00141 subjectDir = directionOf( i18n("No Subject") );
00142
00143
00144 QString dateString;
00145 if( printing ) {
00146 QDateTime dateTime;
00147 KLocale * locale = KGlobal::locale();
00148 dateTime.setTime_t( message->date() );
00149 dateString = locale->formatDateTime( dateTime );
00150 } else {
00151 dateString = message->dateStr();
00152 }
00153
00154 QString headerStr = "<div class=\"header\" dir=\"" + dir + "\">\n";
00155
00156 if ( strategy->showHeader( "subject" ) )
00157 headerStr += "<div dir=\"" + subjectDir + "\">\n"
00158 "<b style=\"font-size:130%\">" +
00159 strToHtml( message->subject() ) +
00160 "</b></div>\n";
00161
00162 QStringList headerParts;
00163
00164 if ( strategy->showHeader( "from" ) ) {
00165 QString fromStr = message->from();
00166 if ( fromStr.isEmpty() )
00167 fromStr = message->fromStrip();
00168 QString fromPart = KMMessage::emailAddrAsAnchor( fromStr, true );
00169 if ( !vCardName.isEmpty() )
00170 fromPart += " <a href=\"" + vCardName + "\">" + i18n("[vCard]") + "</a>";
00171 headerParts << fromPart;
00172 }
00173
00174 if ( strategy->showHeader( "cc" ) && !message->cc().isEmpty() )
00175 headerParts << i18n("CC: ") + KMMessage::emailAddrAsAnchor( message->cc(), true );
00176
00177 if ( strategy->showHeader( "bcc" ) && !message->bcc().isEmpty() )
00178 headerParts << i18n("BCC: ") + KMMessage::emailAddrAsAnchor( message->bcc(), true );
00179
00180 if ( strategy->showHeader( "date" ) )
00181 headerParts << strToHtml(message->dateShortStr());
00182
00183
00184 headerStr += " (" + headerParts.grep( QRegExp( "\\S" ) ).join( ",\n" ) + ')';
00185
00186 headerStr += "</div>\n";
00187
00188
00189
00190 return headerStr;
00191 }
00192
00193
00194
00195
00196
00197
00198
00199 class PlainHeaderStyle : public HeaderStyle {
00200 friend class ::KMail::HeaderStyle;
00201 protected:
00202 PlainHeaderStyle() : HeaderStyle() {}
00203 virtual ~PlainHeaderStyle() {}
00204
00205 public:
00206 const char * name() const { return "plain"; }
00207 const HeaderStyle * next() const { return fancy(); }
00208 const HeaderStyle * prev() const { return brief(); }
00209
00210 QString format( const KMMessage * message, const HeaderStrategy * strategy,
00211 const QString & vCardName, bool printing, bool topLevel ) const;
00212
00213 private:
00214 QString formatAllMessageHeaders( const KMMessage * message ) const;
00215 };
00216
00217 QString PlainHeaderStyle::format( const KMMessage * message,
00218 const HeaderStrategy * strategy,
00219 const QString & vCardName, bool printing, bool topLevel ) const {
00220 Q_UNUSED( topLevel );
00221 if ( !message ) return QString::null;
00222 if ( !strategy )
00223 strategy = HeaderStrategy::rich();
00224
00225
00226
00227
00228 QString dir = ( QApplication::reverseLayout() ? "rtl" : "ltr" );
00229
00230
00231
00232
00233
00234
00235
00236 QString subjectDir;
00237 if (!message->subject().isEmpty())
00238 subjectDir = directionOf( message->cleanSubject() );
00239 else
00240 subjectDir = directionOf( i18n("No Subject") );
00241
00242
00243 QString dateString;
00244 if( printing ) {
00245 QDateTime dateTime;
00246 KLocale* locale = KGlobal::locale();
00247 dateTime.setTime_t( message->date() );
00248 dateString = locale->formatDateTime( dateTime );
00249 }
00250 else {
00251 dateString = message->dateStr();
00252 }
00253
00254 QString headerStr;
00255
00256 if ( strategy->headersToDisplay().isEmpty()
00257 && strategy->defaultPolicy() == HeaderStrategy::Display ) {
00258
00259
00260 headerStr= QString("<div class=\"header\" dir=\"ltr\">");
00261 headerStr += formatAllMessageHeaders( message );
00262 return headerStr + "</div>";
00263 }
00264
00265 headerStr = QString("<div class=\"header\" dir=\"%1\">").arg(dir);
00266
00267
00268 if ( strategy->showHeader( "subject" ) )
00269 headerStr += QString("<div dir=\"%1\"><b style=\"font-size:130%\">" +
00270 strToHtml(message->subject()) + "</b></div>\n")
00271 .arg(subjectDir);
00272
00273 if ( strategy->showHeader( "date" ) )
00274 headerStr.append(i18n("Date: ") + strToHtml(dateString)+"<br>\n");
00275
00276 #if 0
00277
00278 QString presence;
00279 QString kabcUid;
00280 if ( strategy->showHeader( "status" ) )
00281 {
00282 KABC::AddressBook *addressBook = KABC::StdAddressBook::self( true );
00283 KABC::AddresseeList addresses = addressBook->findByEmail( KPIM::getFirstEmailAddress( message->from() ) );
00284 ::KIMProxy *imProxy = KMKernel::self()->imProxy();
00285 kabcUid = addresses[0].uid();
00286 presence = imProxy->presenceString( kabcUid );
00287 }
00288 #endif
00289
00290 if ( strategy->showHeader( "from" ) ) {
00291 QString fromStr = message->from();
00292 if ( fromStr.isEmpty() )
00293 fromStr = message->fromStrip();
00294 headerStr.append(i18n("From: ") +
00295 KMMessage::emailAddrAsAnchor( fromStr, false, "", true ) );
00296 if ( !vCardName.isEmpty() )
00297 headerStr.append(" <a href=\"" + vCardName +
00298 "\">" + i18n("[vCard]") + "</a>" );
00299 #if 0
00300 if ( !presence.isEmpty() && strategy->showHeader( "status" ) )
00301 headerStr.append(" (<span name=\"presence-" + kabcUid + "\">" + presence + "</span>)" );
00302 #endif
00303
00304 if ( strategy->showHeader( "organization" )
00305 && !message->headerField("Organization").isEmpty())
00306 headerStr.append(" (" +
00307 strToHtml(message->headerField("Organization")) + ")");
00308 headerStr.append("<br>\n");
00309 }
00310
00311 if ( strategy->showHeader( "to" ) )
00312 headerStr.append(i18n("To: ")+
00313 KMMessage::emailAddrAsAnchor(message->to(),false) + "<br>\n");
00314
00315 if ( strategy->showHeader( "cc" ) && !message->cc().isEmpty() )
00316 headerStr.append(i18n("CC: ")+
00317 KMMessage::emailAddrAsAnchor(message->cc(),false) + "<br>\n");
00318
00319 if ( strategy->showHeader( "bcc" ) && !message->bcc().isEmpty() )
00320 headerStr.append(i18n("BCC: ")+
00321 KMMessage::emailAddrAsAnchor(message->bcc(),false) + "<br>\n");
00322
00323 if ( strategy->showHeader( "reply-to" ) && !message->replyTo().isEmpty())
00324 headerStr.append(i18n("Reply to: ")+
00325 KMMessage::emailAddrAsAnchor(message->replyTo(),false) + "<br>\n");
00326
00327 headerStr += "</div>\n";
00328
00329 return headerStr;
00330 }
00331
00332 QString PlainHeaderStyle::formatAllMessageHeaders( const KMMessage * message ) const {
00333 const DwHeaders & headers = message->headers();
00334 QString result;
00335
00336 for ( const DwField * field = headers.FirstField() ; field ; field = field->Next() ) {
00337 result += ( field->FieldNameStr() + ": " ).c_str();
00338 result += strToHtml( field->FieldBodyStr().c_str() );
00339 result += "<br>\n";
00340 }
00341
00342 return result;
00343 }
00344
00345
00346
00347
00348
00349
00350 class FancyHeaderStyle : public HeaderStyle {
00351 friend class ::KMail::HeaderStyle;
00352 protected:
00353 FancyHeaderStyle() : HeaderStyle() {}
00354 virtual ~FancyHeaderStyle() {}
00355
00356 public:
00357 const char * name() const { return "fancy"; }
00358 const HeaderStyle * next() const { return enterprise(); }
00359 const HeaderStyle * prev() const { return plain(); }
00360
00361 QString format( const KMMessage * message, const HeaderStrategy * strategy,
00362 const QString & vCardName, bool printing, bool topLevel ) const;
00363 static QString imgToDataUrl( const QImage & image,
00364 const char *fmt = "PNG" );
00365
00366 private:
00367 static QString drawSpamMeter( double percent, const QString & filterHeader );
00368
00369 };
00370
00371 QString FancyHeaderStyle::drawSpamMeter( double percent,
00372 const QString & filterHeader )
00373 {
00374 QImage meterBar( 20, 1, 8, 24 );
00375 const unsigned short gradient[20][3] = {
00376 { 0, 255, 0 },
00377 { 27, 254, 0 },
00378 { 54, 252, 0 },
00379 { 80, 250, 0 },
00380 { 107, 249, 0 },
00381 { 135, 247, 0 },
00382 { 161, 246, 0 },
00383 { 187, 244, 0 },
00384 { 214, 242, 0 },
00385 { 241, 241, 0 },
00386 { 255, 228, 0 },
00387 { 255, 202, 0 },
00388 { 255, 177, 0 },
00389 { 255, 151, 0 },
00390 { 255, 126, 0 },
00391 { 255, 101, 0 },
00392 { 255, 76, 0 },
00393 { 255, 51, 0 },
00394 { 255, 25, 0 },
00395 { 255, 0, 0 }
00396 };
00397 meterBar.setColor( 21, qRgb( 255, 255, 255 ) );
00398 meterBar.setColor( 22, qRgb( 170, 170, 170 ) );
00399 if ( percent < 0 )
00400 meterBar.fill( 22 );
00401 else {
00402 meterBar.fill( 21 );
00403 int max = QMIN( 20, static_cast<int>( percent ) / 5 );
00404 for ( int i = 0; i < max; ++i ) {
00405 meterBar.setColor( i+1, qRgb( gradient[i][0], gradient[i][1],
00406 gradient[i][2] ) );
00407 meterBar.setPixel( i, 0, i+1 );
00408 }
00409 }
00410 QString titleText = i18n("%1% probability of being spam.\n\nFull report:\n%2")
00411 .arg( QString::number( percent ), filterHeader );
00412 return QString("<img src=\"%1\" width=\"%2\" height=\"%3\" style=\"border: 1px solid black;\" title=\"%4\"> ")
00413 .arg( imgToDataUrl( meterBar, "PPM" ), QString::number( 20 ),
00414 QString::number( 5 ), titleText );
00415 }
00416
00417
00418 QString FancyHeaderStyle::format( const KMMessage * message,
00419 const HeaderStrategy * strategy,
00420 const QString & vCardName, bool printing, bool topLevel ) const {
00421 Q_UNUSED( topLevel );
00422 if ( !message ) return QString::null;
00423 if ( !strategy )
00424 strategy = HeaderStrategy::rich();
00425
00426 KConfigGroup configReader( KMKernel::config(), "Reader" );
00427
00428
00429
00430
00431
00432 QString dir = ( QApplication::reverseLayout() ? "rtl" : "ltr" );
00433 QString headerStr = QString("<div class=\"fancy header\" dir=\"%1\">\n").arg(dir);
00434
00435
00436
00437
00438
00439
00440
00441 QString subjectDir;
00442 if ( !message->subject().isEmpty() )
00443 subjectDir = directionOf( message->cleanSubject() );
00444 else
00445 subjectDir = directionOf( i18n("No Subject") );
00446
00447
00448 QString dateString;
00449 if( printing ) {
00450 QDateTime dateTime;
00451 KLocale* locale = KGlobal::locale();
00452 dateTime.setTime_t( message->date() );
00453 dateString = locale->formatDateTime( dateTime );
00454 }
00455 else {
00456 dateString = message->dateStr();
00457 }
00458
00459
00460
00461
00462
00463
00464 QString spamHTML;
00465
00466 if ( configReader.readBoolEntry( "showSpamStatus", true ) ) {
00467 SpamScores scores = SpamHeaderAnalyzer::getSpamScores( message );
00468 for ( SpamScoresIterator it = scores.begin(); it != scores.end(); ++it )
00469 spamHTML += (*it).agent() + " " +
00470 drawSpamMeter( (*it).score(), (*it).spamHeader() );
00471 }
00472
00473 QString userHTML;
00474 QString presence;
00475
00476
00477
00478 ::KIMProxy *imProxy = KMKernel::self()->imProxy();
00479 QString kabcUid;
00480 KABC::AddressBook *addressBook = KABC::StdAddressBook::self( true );
00481 KABC::AddresseeList addresses = addressBook->findByEmail( KPIM::getFirstEmailAddress( message->from() ) );
00482
00483 QString photoURL;
00484 int photoWidth = 60;
00485 int photoHeight = 60;
00486 if( addresses.count() == 1 )
00487 {
00488
00489 kabcUid = addresses[0].uid();
00490
00491 if ( imProxy->initialize() ) {
00492
00493 presence = imProxy->presenceString( kabcUid );
00494 if ( !presence.isEmpty() )
00495 {
00496 QString presenceIcon = QString::fromLatin1( " <img src=\"%1\"/>" )
00497 .arg( imgToDataUrl( imProxy->presenceIcon( kabcUid ).convertToImage() ) );
00498 presence += presenceIcon;
00499 }
00500 }
00501
00502 if ( addresses[0].photo().isIntern() )
00503 {
00504
00505
00506 QImage photo = addresses[0].photo().data();
00507 if ( !photo.isNull() )
00508 {
00509 photoWidth = photo.width();
00510 photoHeight = photo.height();
00511
00512 if ( photoHeight > 60 ) {
00513 double ratio = ( double )photoHeight / ( double )photoWidth;
00514 photoHeight = 60;
00515 photoWidth = (int)( 60 / ratio );
00516 photo = photo.smoothScale( photoWidth, photoHeight );
00517 }
00518 photoURL = imgToDataUrl( photo );
00519 }
00520 }
00521 else
00522 {
00523
00524 photoURL = addresses[0].photo().url();
00525 if ( photoURL.startsWith("/") )
00526 photoURL.prepend( "file:" );
00527 }
00528 }
00529 else
00530 {
00531 kdDebug( 5006 ) << "Multiple / No addressees matched email address; Count is " << addresses.count() << endl;
00532 userHTML = " ";
00533 }
00534
00535 if( photoURL.isEmpty() ) {
00536
00537 QString faceheader = message->headerField( "Face" );
00538 if ( !faceheader.isEmpty() ) {
00539 QImage faceimage;
00540
00541 kdDebug( 5006 ) << "Found Face: header" << endl;
00542
00543 QCString facestring = faceheader.utf8();
00544
00545
00546 if ( facestring.length() < 993 ) {
00547 QByteArray facearray;
00548 KCodecs::base64Decode(facestring, facearray);
00549
00550 QImage faceimage;
00551 if ( faceimage.loadFromData( facearray, "png" ) ) {
00552
00553 if ( (48 == faceimage.width()) && (48 == faceimage.height()) ) {
00554 photoURL = imgToDataUrl( faceimage );
00555 photoWidth = 48;
00556 photoHeight = 48;
00557 } else {
00558 kdDebug( 5006 ) << "Face: header image is" << faceimage.width() << "by" << faceimage.height() <<"not 48x48 Pixels" << endl;
00559 }
00560 } else {
00561 kdDebug( 5006 ) << "Failed to load decoded png from Face: header" << endl;
00562 }
00563 } else {
00564 kdDebug( 5006 ) << "Face: header too long at " << facestring.length() << endl;
00565 }
00566 }
00567 }
00568
00569 if( photoURL.isEmpty() )
00570 {
00571
00572 QString xfaceURL;
00573 QString xfhead = message->headerField( "X-Face" );
00574 if ( !xfhead.isEmpty() )
00575 {
00576 KXFace xf;
00577 photoURL = imgToDataUrl( xf.toImage( xfhead ) );
00578 photoWidth = 48;
00579 photoHeight = 48;
00580
00581 }
00582 }
00583
00584 if( !photoURL.isEmpty() )
00585 {
00586
00587 userHTML = QString("<img src=\"%1\" width=\"%2\" height=\"%3\">")
00588 .arg( photoURL ).arg( photoWidth ).arg( photoHeight );
00589 if ( presence.isEmpty() ) {
00590 userHTML = QString("<div class=\"senderpic\">") + userHTML + "</div>";
00591 } else {
00592 userHTML = QString( "<div class=\"senderpic\">"
00593 "<a href=\"im:%1\">%2<div class=\"senderstatus\">"
00594 "<span name=\"presence-%3\">%4</span></div></a>"
00595 "</div>" ).arg( kabcUid )
00596 .arg( userHTML )
00597 .arg( kabcUid )
00598 .arg( presence );
00599 }
00600 } else {
00601
00602 if ( !presence.isEmpty() )
00603 userHTML = QString( "<a href=\"im:%1\"><div class=\"senderstatus\">"
00604 "<span name=\"presence-%2\">%3</span></div></a>" )
00605 .arg( kabcUid )
00606 .arg( kabcUid )
00607 .arg( presence );
00608 }
00609 #if 0
00610
00611 if ( imProxy->imAppsAvailable() )
00612 presence = "<a name=\"launchim\" href=\"kmail:startIMApp\">" + i18n("Launch IM") + "</a></span>";
00613
00614
00615 kdDebug( 5006 ) << "final presence: '" << presence << "'" << endl;
00616 #endif
00617
00618
00619
00620
00621 if ( strategy->showHeader( "subject" ) ) {
00622 const int flags = LinkLocator::PreserveSpaces |
00623 ( GlobalSettings::self()->showEmoticons() ?
00624 LinkLocator::ReplaceSmileys : 0 );
00625 headerStr += QString("<div dir=\"%1\">%2</div>\n")
00626 .arg(subjectDir)
00627 .arg(message->subject().isEmpty()?
00628 i18n("No Subject") :
00629 strToHtml( message->subject(), flags ));
00630 }
00631 headerStr += "<table class=\"outer\"><tr><td width=\"100%\"><table>\n";
00632
00633
00634
00635
00636 if ( strategy->showHeader( "from" ) ) {
00637 QString fromStr = message->from();
00638 if ( fromStr.isEmpty() )
00639 fromStr = message->fromStrip();
00640 headerStr += QString("<tr><th>%1</th>\n"
00641 "<td>")
00642 .arg(i18n("From: "))
00643 + KMMessage::emailAddrAsAnchor( fromStr, false )
00644 + ( !message->headerField( "Resent-From" ).isEmpty() ? " "
00645 + i18n("(resent from %1)")
00646 .arg( KMMessage::emailAddrAsAnchor(
00647 message->headerField( "Resent-From" ),false) )
00648 : QString("") )
00649 + ( !vCardName.isEmpty() ? " <a href=\"" + vCardName + "\">"
00650 + i18n("[vCard]") + "</a>"
00651 : QString("") )
00652 #if 0
00653 + ( ( !presence.isEmpty() )
00654 ? " (<span name=\"presence-" + kabcUid + "\">" + presence + "</span>)"
00655 : QString("") )
00656 #endif
00657 + ( message->headerField("Organization").isEmpty()
00658 ? QString("")
00659 : " ("
00660 + strToHtml(message->headerField("Organization"))
00661 + ")")
00662 + "</td></tr>\n";
00663 }
00664
00665 if ( strategy->showHeader( "to" ) )
00666 headerStr.append(QString("<tr><th>%1</th>\n"
00667 "<td>%2</td></tr>\n")
00668 .arg(i18n("To: "))
00669 .arg(KMMessage::emailAddrAsAnchor(message->to(),false)));
00670
00671
00672 if ( strategy->showHeader( "cc" ) && !message->cc().isEmpty())
00673 headerStr.append(QString("<tr><th>%1</th>\n"
00674 "<td>%2</td></tr>\n")
00675 .arg(i18n("CC: "))
00676 .arg(KMMessage::emailAddrAsAnchor(message->cc(),false)));
00677
00678
00679 if ( strategy->showHeader( "bcc" ) && !message->bcc().isEmpty())
00680 headerStr.append(QString("<tr><th>%1</th>\n"
00681 "<td>%2</td></tr>\n")
00682 .arg(i18n("BCC: "))
00683 .arg(KMMessage::emailAddrAsAnchor(message->bcc(),false)));
00684
00685 if ( strategy->showHeader( "date" ) )
00686 headerStr.append(QString("<tr><th>%1</th>\n"
00687 "<td dir=\"%2\">%3</td></tr>\n")
00688 .arg(i18n("Date: "))
00689 .arg( directionOf( message->dateStr() ) )
00690 .arg(strToHtml(dateString)));
00691
00692 if ( GlobalSettings::self()->showUserAgent() ) {
00693 if ( strategy->showHeader( "user-agent" ) ) {
00694 if ( !message->headerField("User-Agent").isEmpty() ) {
00695 headerStr.append(QString("<tr><th>%1</th>\n"
00696 "<td>%2</td></tr>\n")
00697 .arg(i18n("User-Agent: "))
00698 .arg( strToHtml( message->headerField("User-Agent") ) ) );
00699 }
00700 }
00701
00702 if ( strategy->showHeader( "x-mailer" ) ) {
00703 if ( !message->headerField("X-Mailer").isEmpty() ) {
00704 headerStr.append(QString("<tr><th>%1</th>\n"
00705 "<td>%2</td></tr>\n")
00706 .arg(i18n("X-Mailer: "))
00707 .arg( strToHtml( message->headerField("X-Mailer") ) ) );
00708 }
00709 }
00710 }
00711 if (configReader.readBoolEntry( "showSpamStatus", true ) ) {
00712 if (strategy->showHeader( "x-text-classification" ) && strategy->showHeader( "x-popfile-link" ) )
00713 {
00714 if ( ! message->headerField( "X-Text-Classification" ).isEmpty() && ! message->headerField( "X-POPFile-Link" ).isEmpty() )
00715 {
00716 headerStr.append(QString("<tr><th>%1</th>\n"
00717 "<td>%2 (<a href=\"%3\">%4</a>)</td></tr>\n")
00718 .arg("Popfile:")
00719 .arg( strToHtml( message->headerField("X-Text-Classification") ) )
00720 .arg( message->headerField("X-POPFile-Link") )
00721 .arg(i18n("Reclassify") ) );
00722 }
00723 }
00724 }
00725
00726
00727
00728
00729
00730
00731
00732
00733
00734 headerStr.append( QString("<tr><td colspan=\"2\"><div id=\"attachmentInjectionPoint\"></div></td></tr>" ) );
00735 headerStr.append(
00736 QString( "</table></td><td align=\"center\">%1</td></tr></table>\n" ).arg(userHTML) );
00737
00738 if ( !spamHTML.isEmpty() )
00739 headerStr.append( QString( "<div class=\"spamheader\" dir=\"%1\"><b>%2</b> <span style=\"padding-left: 20px;\">%3</span></div>\n")
00740 .arg( subjectDir, i18n("Spam Status:"), spamHTML ) );
00741
00742 headerStr += "</div>\n\n";
00743 return headerStr;
00744 }
00745
00746 QString FancyHeaderStyle::imgToDataUrl( const QImage &image, const char* fmt )
00747 {
00748 QByteArray ba;
00749 QBuffer buffer( ba );
00750 buffer.open( IO_WriteOnly );
00751 image.save( &buffer, fmt );
00752 return QString::fromLatin1("data:image/%1;base64,%2")
00753 .arg( fmt, KCodecs::base64Encode( ba ) );
00754 }
00755
00756
00757
00758 class EnterpriseHeaderStyle : public HeaderStyle {
00759 friend class ::KMail::HeaderStyle;
00760 protected:
00761 EnterpriseHeaderStyle() : HeaderStyle() {}
00762 virtual ~EnterpriseHeaderStyle() {}
00763
00764 public:
00765 const char * name() const { return "enterprise"; }
00766 const HeaderStyle * next() const { return brief(); }
00767 const HeaderStyle * prev() const { return fancy(); }
00768
00769 QString format( const KMMessage * message, const HeaderStrategy * strategy,
00770 const QString & vCardName, bool printing, bool topLevel ) const;
00771 };
00772
00773 QString EnterpriseHeaderStyle::format( const KMMessage * message,
00774 const HeaderStrategy * strategy,
00775 const QString & vCardName, bool printing, bool topLevel ) const {
00776 if ( !message ) return QString::null;
00777 if ( !strategy )
00778 strategy = HeaderStrategy::brief();
00779
00780
00781
00782
00783 QString dir = QApplication::reverseLayout() ? "rtl" : "ltr" ;
00784
00785
00786
00787
00788
00789
00790
00791 QString subjectDir;
00792 if (!message->subject().isEmpty())
00793 subjectDir = directionOf( message->cleanSubject() );
00794 else
00795 subjectDir = directionOf( i18n("No Subject") );
00796
00797
00798 QColor fontColor(Qt::white);
00799 QString linkColor = "class =\"white\"";
00800 const QColor activeColor = qApp->palette().active().highlight();
00801 QColor activeColorDark = activeColor.dark(130);
00802
00803 if( !topLevel ){
00804 activeColorDark = activeColor.dark(50);
00805 fontColor = QColor(Qt::black);
00806 linkColor = "class =\"black\"";
00807 }
00808
00809
00810 QString dateString;
00811 if( printing ) {
00812 QDateTime dateTime;
00813 KLocale * locale = KGlobal::locale();
00814 dateTime.setTime_t( message->date() );
00815 dateString = locale->formatDateTime( dateTime );
00816 } else {
00817 dateString = message->dateStr();
00818 }
00819
00820 QString imgpath(locate("data","kmail/pics/"));
00821 imgpath.append("enterprise_");
00822 const QString borderSettings(" padding-top: 0px; padding-bottom: 0px; border-width: 0px ");
00823 QString headerStr ("");
00824
00825
00826 if(topLevel)
00827 headerStr +=
00828 "<div style=\"position: fixed; top: 0px; left: 0px; background-color: #606060; "
00829 "background-image: url("+imgpath+"shadow_left.png); width: 10px; min-height: 100%;\"> </div>"
00830 "<div style=\"position: fixed; top: 0px; right: 0px; background-color: #606060; "
00831 "background-image: url("+imgpath+"shadow_right.png); width: 10px; min-height: 100%;\"> </div>";
00832
00833 headerStr += ""
00834 "<div style=\"margin-left: 10px; top: 0px;\"><span style=\"font-size: 10px; font-weight: bold;\">"+dateString+"</span></div>"
00835
00836 "<table style=\"background: "+activeColorDark.name()+"; border-collapse:collapse; top: 14px; min-width: 200px; \" cellpadding=0> \n"
00837 " <tr> \n"
00838 " <td style=\"min-width: 6px; background-image: url("+imgpath+"top_left.png); \"></td> \n"
00839 " <td style=\"height: 6px; width: 100%; background: url("+imgpath+"top.png); \"></td> \n"
00840 " <td style=\"min-width: 6px; background: url("+imgpath+"top_right.png); \"></td> </tr> \n"
00841 " <tr> \n"
00842 " <td style=\"min-width: 6px; max-width: 6px; background: url("+imgpath+"left.png); \"></td> \n"
00843 " <td style=\"\"> \n"
00844 " <table style=\"color: "+fontColor.name()+" ! important; margin: 1px; border-spacing: 0px;\" cellpadding=0> \n";
00845
00846
00847
00848 if ( strategy->showHeader( "subject" ) ){
00849 headerStr +=
00850 " <tr> \n"
00851 " <td style=\"font-size: 6px; text-align: right; padding-left: 5px; padding-right: 24px; "+borderSettings+"\"></td> \n"
00852 " <td style=\"font-weight: bolder; font-size: 120%; padding-right: 91px; "+borderSettings+"\">"+message->subject()+"</td> \n"
00853 " </tr> \n";
00854 }
00855
00856
00857 if ( strategy->showHeader( "from" ) ){
00858 QString fromStr = message->from();
00859 if ( fromStr.isEmpty() )
00860 fromStr = message->fromStrip();
00861
00862 QString fromPart = KMMessage::emailAddrAsAnchor( fromStr, true, linkColor );
00863 if ( !vCardName.isEmpty() )
00864 fromPart += " <a href=\"" + vCardName + "\" "+linkColor+">" + i18n("[vCard]") + "</a>";
00865
00866
00867 headerStr +=
00868 " <tr> \n"
00869 " <td style=\"font-size: 6px; padding-left: 5px; padding-right: 24px; text-align: right; "+borderSettings+"\">"+i18n("From: ")+"</td> \n"
00870 " <td style=\""+borderSettings+"\">"+ fromPart +"</td> "
00871 " </tr> ";
00872 }
00873
00874
00875 if( strategy->showHeader( "to" ) )
00876 headerStr +=
00877 " <tr> "
00878 " <td style=\"font-size: 6px; text-align: right; padding-left: 5px; padding-right: 24px; " + borderSettings + "\">" + i18n("To: ") + "</td> "
00879 " <td style=\"" + borderSettings + "\">" +
00880 KMMessage::emailAddrAsAnchor( message->to(), false, linkColor ) +
00881 " </td> "
00882 " </tr>\n";
00883
00884
00885 if ( strategy->showHeader( "cc" ) && !message->cc().isEmpty() )
00886 headerStr +=
00887 " <tr> "
00888 " <td style=\"font-size: 6px; text-align: right; padding-left: 5px; padding-right: 24px; " + borderSettings + "\">" + i18n("CC: ") + "</td> "
00889 " <td style=\"" + borderSettings + "\">" +
00890 KMMessage::emailAddrAsAnchor( message->cc(), true, linkColor ) +
00891 " </td> "
00892 " </tr>\n";
00893
00894
00895 if ( strategy->showHeader( "bcc" ) && !message->bcc().isEmpty() )
00896 headerStr +=
00897 " <tr> "
00898 " <td style=\"font-size: 6px; text-align: right; padding-left: 5px; padding-right: 24px; " + borderSettings + "\">" + i18n("BCC: ") + "</td> "
00899 " <td style=\"" + borderSettings + "\">" +
00900 KMMessage::emailAddrAsAnchor( message->bcc(), true, linkColor ) +
00901 " </td> "
00902 " </tr>\n";
00903
00904
00905 headerStr +=
00906 " </table> \n"
00907 " </td> \n"
00908 " <td style=\"min-width: 6px; max-height: 15px; background: url("+imgpath+"right.png); \"></td> \n"
00909 " </tr> \n"
00910 " <tr> \n"
00911 " <td style=\"min-width: 6px; background: url("+imgpath+"s_left.png); \"></td> \n"
00912 " <td style=\"height: 35px; width: 80%; background: url("+imgpath+"sbar.png);\"> \n"
00913 " <img src=\""+imgpath+"sw.png\" style=\"margin: 0px; height: 30px; overflow:hidden; \"> \n"
00914 " <img src=\""+imgpath+"sp_right.png\" style=\"float: right; \"> </td> \n"
00915 " <td style=\"min-width: 6px; background: url("+imgpath+"s_right.png); \"></td> \n"
00916 " </tr> \n"
00917 " </table> \n";
00918
00919
00920 if(topLevel) {
00921 headerStr +=
00922 "<div class=\"noprint\" style=\"position: absolute; top: -14px; right: 30px; width: 91px; height: 91px;\">\n"
00923 "<img style=\"float: right;\" src=\""+imgpath+"icon.png\">\n"
00924 "</div>\n";
00925
00926
00927 headerStr +=
00928 "<div class=\"noprint\" style=\"position: absolute; top: 60px; right: 20px; width: 91px; height: 200px;\">"
00929 "<div id=\"attachmentInjectionPoint\"></div>"
00930 "</div>\n";
00931 }
00932
00933 if ( printing ) {
00934
00935
00936 headerStr += "<div style=\"padding: 6px; padding-left: 10px;\">";
00937 } else {
00938 headerStr += "<div style=\"padding: 6px;\">";
00939 }
00940
00941
00942
00943
00944
00945 return headerStr;
00946 }
00947
00948
00949
00950
00951
00952
00953
00954 HeaderStyle::HeaderStyle() {
00955
00956 }
00957
00958 HeaderStyle::~HeaderStyle() {
00959
00960 }
00961
00962 const HeaderStyle * HeaderStyle::create( Type type ) {
00963 switch ( type ) {
00964 case Brief: return brief();
00965 case Plain: return plain();
00966 case Fancy: return fancy();
00967 case Enterprise: return enterprise();
00968 }
00969 kdFatal( 5006 ) << "HeaderStyle::create(): Unknown header style ( type == "
00970 << (int)type << " ) requested!" << endl;
00971 return 0;
00972 }
00973
00974 const HeaderStyle * HeaderStyle::create( const QString & type ) {
00975 QString lowerType = type.lower();
00976 if ( lowerType == "brief" ) return brief();
00977 if ( lowerType == "plain" ) return plain();
00978 if ( lowerType == "enterprise" ) return enterprise();
00979
00980
00981
00982 return fancy();
00983 }
00984
00985 static const HeaderStyle * briefStyle = 0;
00986 static const HeaderStyle * plainStyle = 0;
00987 static const HeaderStyle * fancyStyle = 0;
00988 static const HeaderStyle * enterpriseStyle = 0;
00989
00990 const HeaderStyle * HeaderStyle::brief() {
00991 if ( !briefStyle )
00992 briefStyle = new BriefHeaderStyle();
00993 return briefStyle;
00994 }
00995
00996 const HeaderStyle * HeaderStyle::plain() {
00997 if ( !plainStyle )
00998 plainStyle = new PlainHeaderStyle();
00999 return plainStyle;
01000 }
01001
01002 const HeaderStyle * HeaderStyle::fancy() {
01003 if ( !fancyStyle )
01004 fancyStyle = new FancyHeaderStyle();
01005 return fancyStyle;
01006 }
01007
01008 const HeaderStyle * HeaderStyle::enterprise() {
01009 if ( !enterpriseStyle )
01010 enterpriseStyle = new EnterpriseHeaderStyle();
01011 return enterpriseStyle;
01012 }
01013
01014 }