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
00033 #ifdef HAVE_CONFIG_H
00034 #include <config.h>
00035 #endif
00036
00037 #include "urlhandlermanager.h"
00038
00039 #include "interfaces/urlhandler.h"
00040 #include "interfaces/bodyparturlhandler.h"
00041 #include "partNode.h"
00042 #include "partnodebodypart.h"
00043 #include "kmreaderwin.h"
00044 #include "kmkernel.h"
00045 #include "callback.h"
00046
00047 #include <kimproxy.h>
00048 #include "stl_util.h"
00049 #include <kurl.h>
00050
00051 #include <algorithm>
00052 using std::for_each;
00053 using std::remove;
00054 using std::find;
00055
00056 KMail::URLHandlerManager * KMail::URLHandlerManager::self = 0;
00057
00058 namespace {
00059 class KMailProtocolURLHandler : public KMail::URLHandler {
00060 public:
00061 KMailProtocolURLHandler() : KMail::URLHandler() {}
00062 ~KMailProtocolURLHandler() {}
00063
00064 bool handleClick( const KURL &, KMReaderWin * ) const;
00065 bool handleContextMenuRequest( const KURL & url, const QPoint &, KMReaderWin * ) const {
00066 return url.protocol() == "kmail";
00067 }
00068 QString statusBarMessage( const KURL &, KMReaderWin * ) const;
00069 };
00070
00071 class ExpandCollapseQuoteURLManager : public KMail::URLHandler {
00072 public:
00073 ExpandCollapseQuoteURLManager() : KMail::URLHandler() {}
00074 ~ExpandCollapseQuoteURLManager() {}
00075
00076 bool handleClick( const KURL &, KMReaderWin * ) const;
00077 bool handleContextMenuRequest( const KURL &, const QPoint &, KMReaderWin * ) const {
00078 return false;
00079 }
00080 QString statusBarMessage( const KURL &, KMReaderWin * ) const;
00081
00082 };
00083
00084 class SMimeURLHandler : public KMail::URLHandler {
00085 public:
00086 SMimeURLHandler() : KMail::URLHandler() {}
00087 ~SMimeURLHandler() {}
00088
00089 bool handleClick( const KURL &, KMReaderWin * ) const;
00090 bool handleContextMenuRequest( const KURL &, const QPoint &, KMReaderWin * ) const {
00091 return false;
00092 }
00093 QString statusBarMessage( const KURL &, KMReaderWin * ) const;
00094 };
00095
00096 class MailToURLHandler : public KMail::URLHandler {
00097 public:
00098 MailToURLHandler() : KMail::URLHandler() {}
00099 ~MailToURLHandler() {}
00100
00101 bool handleClick( const KURL &, KMReaderWin * ) const { return false; }
00102 bool handleContextMenuRequest( const KURL &, const QPoint &, KMReaderWin * ) const {
00103 return false;
00104 }
00105 QString statusBarMessage( const KURL &, KMReaderWin * ) const;
00106 };
00107
00108 class HtmlAnchorHandler : public KMail::URLHandler {
00109 public:
00110 HtmlAnchorHandler() : KMail::URLHandler() {}
00111 ~HtmlAnchorHandler() {}
00112
00113 bool handleClick( const KURL &, KMReaderWin * ) const;
00114 bool handleContextMenuRequest( const KURL &, const QPoint &, KMReaderWin * ) const {
00115 return false;
00116 }
00117 QString statusBarMessage( const KURL &, KMReaderWin * ) const { return QString::null; }
00118 };
00119
00120 class AttachmentURLHandler : public KMail::URLHandler {
00121 public:
00122 AttachmentURLHandler() : KMail::URLHandler() {}
00123 ~AttachmentURLHandler() {}
00124
00125 bool handleClick( const KURL &, KMReaderWin * ) const;
00126 bool handleContextMenuRequest( const KURL &, const QPoint &, KMReaderWin * ) const;
00127 QString statusBarMessage( const KURL &, KMReaderWin * ) const;
00128 private:
00129 partNode* partNodeForUrl( const KURL &url, KMReaderWin *w ) const;
00130 bool attachmentIsInHeader( const KURL &url ) const;
00131 };
00132
00133 class ShowAuditLogURLHandler : public KMail::URLHandler {
00134 public:
00135 ShowAuditLogURLHandler() : KMail::URLHandler() {}
00136 ~ShowAuditLogURLHandler() {}
00137
00138 bool handleClick( const KURL &, KMReaderWin * ) const;
00139 bool handleContextMenuRequest( const KURL &, const QPoint &, KMReaderWin * ) const;
00140 QString statusBarMessage( const KURL &, KMReaderWin * ) const;
00141 };
00142
00143 class FallBackURLHandler : public KMail::URLHandler {
00144 public:
00145 FallBackURLHandler() : KMail::URLHandler() {}
00146 ~FallBackURLHandler() {}
00147
00148 bool handleClick( const KURL &, KMReaderWin * ) const;
00149 bool handleContextMenuRequest( const KURL &, const QPoint &, KMReaderWin * ) const;
00150 QString statusBarMessage( const KURL & url, KMReaderWin * ) const {
00151 return url.prettyURL();
00152 }
00153 };
00154
00155 }
00156
00157
00158
00159
00160
00161
00162
00163
00164 class KMail::URLHandlerManager::BodyPartURLHandlerManager : public KMail::URLHandler {
00165 public:
00166 BodyPartURLHandlerManager() : KMail::URLHandler() {}
00167 ~BodyPartURLHandlerManager();
00168
00169 bool handleClick( const KURL &, KMReaderWin * ) const;
00170 bool handleContextMenuRequest( const KURL &, const QPoint &, KMReaderWin * ) const;
00171 QString statusBarMessage( const KURL &, KMReaderWin * ) const;
00172
00173 void registerHandler( const Interface::BodyPartURLHandler * handler );
00174 void unregisterHandler( const Interface::BodyPartURLHandler * handler );
00175
00176 private:
00177 typedef QValueVector<const Interface::BodyPartURLHandler*> BodyPartHandlerList;
00178 BodyPartHandlerList mHandlers;
00179 };
00180
00181 KMail::URLHandlerManager::BodyPartURLHandlerManager::~BodyPartURLHandlerManager() {
00182 for_each( mHandlers.begin(), mHandlers.end(),
00183 DeleteAndSetToZero<Interface::BodyPartURLHandler>() );
00184 }
00185
00186 void KMail::URLHandlerManager::BodyPartURLHandlerManager::registerHandler( const Interface::BodyPartURLHandler * handler ) {
00187 if ( !handler )
00188 return;
00189 unregisterHandler( handler );
00190 mHandlers.push_back( handler );
00191 }
00192
00193 void KMail::URLHandlerManager::BodyPartURLHandlerManager::unregisterHandler( const Interface::BodyPartURLHandler * handler ) {
00194
00195 mHandlers.erase( remove( mHandlers.begin(), mHandlers.end(), handler ), mHandlers.end() );
00196 }
00197
00198 static partNode * partNodeFromXKMailUrl( const KURL & url, KMReaderWin * w, QString * path ) {
00199 assert( path );
00200
00201 if ( !w || url.protocol() != "x-kmail" )
00202 return 0;
00203 const QString urlPath = url.path();
00204
00205
00206
00207 kdDebug( 5006 ) << "BodyPartURLHandler: urlPath == \"" << urlPath << "\"" << endl;
00208 if ( !urlPath.startsWith( "/bodypart/" ) )
00209 return 0;
00210
00211 const QStringList urlParts = QStringList::split( '/', urlPath.mid( 10 ), true );
00212 if ( urlParts.size() != 3 )
00213 return 0;
00214 bool ok = false;
00215 const int part_id = urlParts[1].toInt( &ok );
00216 if ( !ok )
00217 return 0;
00218 *path = KURL::decode_string( urlParts[2], 106 );
00219 return w->partNodeForId( part_id );
00220 }
00221
00222 bool KMail::URLHandlerManager::BodyPartURLHandlerManager::handleClick( const KURL & url, KMReaderWin * w ) const {
00223 QString path;
00224 partNode * node = partNodeFromXKMailUrl( url, w, &path );
00225 if ( !node )
00226 return false;
00227 KMMessage *msg = w->message();
00228 if ( !msg ) return false;
00229 Callback callback( msg, w );
00230 KMail::PartNodeBodyPart part( *node, w->overrideCodec() );
00231 for ( BodyPartHandlerList::const_iterator it = mHandlers.begin() ; it != mHandlers.end() ; ++it )
00232 if ( (*it)->handleClick( &part, path, callback ) )
00233 return true;
00234 return false;
00235 }
00236
00237 bool KMail::URLHandlerManager::BodyPartURLHandlerManager::handleContextMenuRequest( const KURL & url, const QPoint & p, KMReaderWin * w ) const {
00238 QString path;
00239 partNode * node = partNodeFromXKMailUrl( url, w, &path );
00240 if ( !node )
00241 return false;
00242
00243 KMail::PartNodeBodyPart part( *node, w->overrideCodec() );
00244 for ( BodyPartHandlerList::const_iterator it = mHandlers.begin() ; it != mHandlers.end() ; ++it )
00245 if ( (*it)->handleContextMenuRequest( &part, path, p ) )
00246 return true;
00247 return false;
00248 }
00249
00250 QString KMail::URLHandlerManager::BodyPartURLHandlerManager::statusBarMessage( const KURL & url, KMReaderWin * w ) const {
00251 QString path;
00252 partNode * node = partNodeFromXKMailUrl( url, w, &path );
00253 if ( !node )
00254 return QString::null;
00255
00256 KMail::PartNodeBodyPart part( *node, w->overrideCodec() );
00257 for ( BodyPartHandlerList::const_iterator it = mHandlers.begin() ; it != mHandlers.end() ; ++it ) {
00258 const QString msg = (*it)->statusBarMessage( &part, path );
00259 if ( !msg.isEmpty() )
00260 return msg;
00261 }
00262 return QString::null;
00263 }
00264
00265
00266
00267
00268
00269
00270
00271 KMail::URLHandlerManager::URLHandlerManager() {
00272 registerHandler( new KMailProtocolURLHandler() );
00273 registerHandler( new ExpandCollapseQuoteURLManager() );
00274 registerHandler( new SMimeURLHandler() );
00275 registerHandler( new MailToURLHandler() );
00276 registerHandler( new HtmlAnchorHandler() );
00277 registerHandler( new AttachmentURLHandler() );
00278 registerHandler( mBodyPartURLHandlerManager = new BodyPartURLHandlerManager() );
00279 registerHandler( new ShowAuditLogURLHandler() );
00280 registerHandler( new FallBackURLHandler() );
00281 }
00282
00283 KMail::URLHandlerManager::~URLHandlerManager() {
00284 for_each( mHandlers.begin(), mHandlers.end(),
00285 DeleteAndSetToZero<URLHandler>() );
00286 }
00287
00288 void KMail::URLHandlerManager::registerHandler( const URLHandler * handler ) {
00289 if ( !handler )
00290 return;
00291 unregisterHandler( handler );
00292 mHandlers.push_back( handler );
00293 }
00294
00295 void KMail::URLHandlerManager::unregisterHandler( const URLHandler * handler ) {
00296
00297 mHandlers.erase( remove( mHandlers.begin(), mHandlers.end(), handler ), mHandlers.end() );
00298 }
00299
00300 void KMail::URLHandlerManager::registerHandler( const Interface::BodyPartURLHandler * handler ) {
00301 if ( mBodyPartURLHandlerManager )
00302 mBodyPartURLHandlerManager->registerHandler( handler );
00303 }
00304
00305 void KMail::URLHandlerManager::unregisterHandler( const Interface::BodyPartURLHandler * handler ) {
00306 if ( mBodyPartURLHandlerManager )
00307 mBodyPartURLHandlerManager->unregisterHandler( handler );
00308 }
00309
00310 bool KMail::URLHandlerManager::handleClick( const KURL & url, KMReaderWin * w ) const {
00311 for ( HandlerList::const_iterator it = mHandlers.begin() ; it != mHandlers.end() ; ++it )
00312 if ( (*it)->handleClick( url, w ) )
00313 return true;
00314 return false;
00315 }
00316
00317 bool KMail::URLHandlerManager::handleContextMenuRequest( const KURL & url, const QPoint & p, KMReaderWin * w ) const {
00318 for ( HandlerList::const_iterator it = mHandlers.begin() ; it != mHandlers.end() ; ++it )
00319 if ( (*it)->handleContextMenuRequest( url, p, w ) )
00320 return true;
00321 return false;
00322 }
00323
00324 QString KMail::URLHandlerManager::statusBarMessage( const KURL & url, KMReaderWin * w ) const {
00325 for ( HandlerList::const_iterator it = mHandlers.begin() ; it != mHandlers.end() ; ++it ) {
00326 const QString msg = (*it)->statusBarMessage( url, w );
00327 if ( !msg.isEmpty() )
00328 return msg;
00329 }
00330 return QString::null;
00331 }
00332
00333
00334
00335
00336
00337
00338
00339
00340
00341
00342 #include "kmmessage.h"
00343 #include "kmreaderwin.h"
00344 #include "partNode.h"
00345 #include "kmmsgpart.h"
00346
00347 #include <ui/messagebox.h>
00348
00349 #include <klocale.h>
00350 #include <kprocess.h>
00351 #include <kmessagebox.h>
00352 #include <khtml_part.h>
00353
00354 #include <qstring.h>
00355
00356 namespace {
00357 bool KMailProtocolURLHandler::handleClick( const KURL & url, KMReaderWin * w ) const {
00358 if ( url.protocol() == "kmail" ) {
00359 if ( !w )
00360 return false;
00361
00362 if ( url.path() == "showHTML" ) {
00363 w->setHtmlOverride( !w->htmlOverride() );
00364 w->update( true );
00365 return true;
00366 }
00367
00368 if ( url.path() == "loadExternal" ) {
00369 w->setHtmlLoadExtOverride( !w->htmlLoadExtOverride() );
00370 w->update( true );
00371 return true;
00372 }
00373
00374 if ( url.path() == "goOnline" ) {
00375 kmkernel->resumeNetworkJobs();
00376 return true;
00377 }
00378
00379 if ( url.path() == "decryptMessage" ) {
00380 w->setDecryptMessageOverwrite( true );
00381 w->update( true );
00382 return true;
00383 }
00384
00385 if ( url.path() == "showSignatureDetails" ) {
00386 w->setShowSignatureDetails( true );
00387 w->update( true );
00388 return true;
00389 }
00390
00391 if ( url.path() == "hideSignatureDetails" ) {
00392 w->setShowSignatureDetails( false );
00393 w->update( true );
00394 return true;
00395 }
00396
00397 if ( url.path() == "showAttachmentQuicklist" ) {
00398 w->saveRelativePosition();
00399 w->setShowAttachmentQuicklist( true );
00400 w->update( true );
00401 return true;
00402 }
00403
00404 if ( url.path() == "hideAttachmentQuicklist" ) {
00405 w->saveRelativePosition();
00406 w->setShowAttachmentQuicklist( false );
00407 w->update( true );
00408 return true;
00409 }
00410
00411
00412
00413
00414
00415
00416
00417 }
00418 return false;
00419 }
00420
00421 QString KMailProtocolURLHandler::statusBarMessage( const KURL & url, KMReaderWin * ) const {
00422 if ( url.protocol() == "kmail" )
00423 {
00424 if ( url.path() == "showHTML" )
00425 return i18n("Turn on HTML rendering for this message.");
00426 if ( url.path() == "loadExternal" )
00427 return i18n("Load external references from the Internet for this message.");
00428 if ( url.path() == "goOnline" )
00429 return i18n("Work online.");
00430 if ( url.path() == "decryptMessage" )
00431 return i18n("Decrypt message.");
00432 if ( url.path() == "showSignatureDetails" )
00433 return i18n("Show signature details.");
00434 if ( url.path() == "hideSignatureDetails" )
00435 return i18n("Hide signature details.");
00436 }
00437 return QString::null ;
00438 }
00439 }
00440
00441 namespace {
00442
00443 bool ExpandCollapseQuoteURLManager::handleClick(
00444 const KURL & url, KMReaderWin * w ) const
00445 {
00446
00447
00448 if ( url.protocol() == "kmail" && url.path()=="levelquote" )
00449 {
00450 QString levelStr= url.query().mid( 1,url.query().length() );
00451 bool isNumber;
00452 int levelQuote= levelStr.toInt(&isNumber);
00453 if ( isNumber )
00454 w->slotLevelQuote( levelQuote );
00455 return true;
00456 }
00457 return false;
00458 }
00459 QString ExpandCollapseQuoteURLManager::statusBarMessage(
00460 const KURL & url, KMReaderWin * ) const
00461 {
00462 if ( url.protocol() == "kmail" && url.path() == "levelquote" )
00463 {
00464 QString query= url.query();
00465 if ( query.length()>=2 ) {
00466 if ( query[ 1 ] =='-' ) {
00467 return i18n("Expand all quoted text.");
00468 }
00469 else {
00470 return i18n("Collapse quoted text.");
00471 }
00472 }
00473 }
00474 return QString::null ;
00475 }
00476
00477 }
00478
00479
00480 extern bool foundSMIMEData( const QString aUrl, QString & displayName,
00481 QString & libName, QString & keyId );
00482
00483 namespace {
00484 bool SMimeURLHandler::handleClick( const KURL & url, KMReaderWin * w ) const {
00485 if ( !url.hasRef() )
00486 return false;
00487 QString displayName, libName, keyId;
00488 if ( !foundSMIMEData( url.path() + '#' + url.ref(), displayName, libName, keyId ) )
00489 return false;
00490 KProcess cmp;
00491 cmp << "kleopatra" << "-query" << keyId;
00492 if ( !cmp.start( KProcess::DontCare ) )
00493 KMessageBox::error( w, i18n("Could not start certificate manager. "
00494 "Please check your installation."),
00495 i18n("KMail Error") );
00496 return true;
00497 }
00498
00499 QString SMimeURLHandler::statusBarMessage( const KURL & url, KMReaderWin * ) const {
00500 QString displayName, libName, keyId;
00501 if ( !foundSMIMEData( url.path() + '#' + url.ref(), displayName, libName, keyId ) )
00502 return QString::null;
00503 return i18n("Show certificate 0x%1").arg( keyId );
00504 }
00505 }
00506
00507 namespace {
00508 bool HtmlAnchorHandler::handleClick( const KURL & url, KMReaderWin * w ) const {
00509 if ( url.hasHost() || url.path() != "/" || !url.hasRef() )
00510 return false;
00511 if ( w && !w->htmlPart()->gotoAnchor( url.ref() ) )
00512 static_cast<QScrollView*>( w->htmlPart()->widget() )->ensureVisible( 0, 0 );
00513 return true;
00514 }
00515 }
00516
00517 namespace {
00518 QString MailToURLHandler::statusBarMessage( const KURL & url, KMReaderWin * ) const {
00519 if ( url.protocol() != "mailto" )
00520 return QString::null;
00521 return KMMessage::decodeMailtoUrl( url.url() );
00522 }
00523 }
00524
00525 namespace {
00526
00527 partNode* AttachmentURLHandler::partNodeForUrl( const KURL &url, KMReaderWin *w ) const
00528 {
00529 if ( !w || !w->message() )
00530 return 0;
00531 if ( url.protocol() != "attachment" )
00532 return 0;
00533
00534 bool ok;
00535 int nodeId = url.path().toInt( &ok );
00536 if ( !ok )
00537 return 0;
00538
00539 partNode * node = w->partNodeForId( nodeId );
00540 return node;
00541 }
00542
00543 bool AttachmentURLHandler::attachmentIsInHeader( const KURL &url ) const
00544 {
00545 bool inHeader = false;
00546 const QString place = url.queryItem( "place" ).lower();
00547 if ( place != QString::null ) {
00548 inHeader = ( place == "header" );
00549 }
00550 return inHeader;
00551 }
00552
00553 bool AttachmentURLHandler::handleClick( const KURL & url, KMReaderWin * w ) const
00554 {
00555 partNode * node = partNodeForUrl( url, w );
00556 if ( !node )
00557 return false;
00558
00559 const bool inHeader = attachmentIsInHeader( url );
00560 const bool shouldShowDialog = !node->isDisplayedEmbedded() || !inHeader;
00561 if ( inHeader )
00562 w->scrollToAttachment( node );
00563 if ( shouldShowDialog )
00564 w->openAttachment( node->nodeId(), w->tempFileUrlFromPartNode( node ).path() );
00565 return true;
00566 }
00567
00568 bool AttachmentURLHandler::handleContextMenuRequest( const KURL & url, const QPoint & p, KMReaderWin * w ) const
00569 {
00570 partNode * node = partNodeForUrl( url, w );
00571 if ( !node )
00572 return false;
00573
00574 w->showAttachmentPopup( node->nodeId(), w->tempFileUrlFromPartNode( node ).path(), p );
00575 return true;
00576 }
00577
00578 QString AttachmentURLHandler::statusBarMessage( const KURL & url, KMReaderWin * w ) const
00579 {
00580 partNode * node = partNodeForUrl( url, w );
00581 if ( !node )
00582 return QString::null;
00583
00584 const KMMessagePart & msgPart = node->msgPart();
00585 QString name = msgPart.fileName();
00586 if ( name.isEmpty() )
00587 name = msgPart.name();
00588 if ( !name.isEmpty() )
00589 return i18n( "Attachment: %1" ).arg( name );
00590 return i18n( "Attachment #%1 (unnamed)" ).arg( KMReaderWin::msgPartFromUrl( url ) );
00591 }
00592 }
00593
00594 namespace {
00595 static QString extractAuditLog( const KURL & url ) {
00596 if ( url.protocol() != "kmail" || url.path() != "showAuditLog" )
00597 return QString();
00598 assert( !url.queryItem( "log" ).isEmpty() );
00599 return url.queryItem( "log" );
00600 }
00601
00602 bool ShowAuditLogURLHandler::handleClick( const KURL & url, KMReaderWin * w ) const {
00603 const QString auditLog = extractAuditLog( url );
00604 if ( auditLog.isEmpty() )
00605 return false;
00606 Kleo::MessageBox::auditLog( w, auditLog );
00607 return true;
00608 }
00609
00610 bool ShowAuditLogURLHandler::handleContextMenuRequest( const KURL & url, const QPoint &, KMReaderWin * w ) const
00611 {
00612 Q_UNUSED( w );
00613
00614 return !extractAuditLog( url ).isEmpty();
00615 }
00616
00617 QString ShowAuditLogURLHandler::statusBarMessage( const KURL & url, KMReaderWin * ) const {
00618 if ( extractAuditLog( url ).isEmpty() )
00619 return QString();
00620 else
00621 return i18n("Show GnuPG Audit Log for this operation");
00622 }
00623 }
00624
00625 namespace {
00626 bool FallBackURLHandler::handleClick( const KURL & url, KMReaderWin * w ) const {
00627 if ( w )
00628 w->emitUrlClicked( url, Qt::LeftButton );
00629 return true;
00630 }
00631
00632 bool FallBackURLHandler::handleContextMenuRequest( const KURL & url, const QPoint & p, KMReaderWin * w ) const {
00633 if ( w )
00634 w->emitPopupMenu( url, p );
00635 return true;
00636 }
00637 }