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