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