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
00395
00396
00397
00398
00399
00400 }
00401 return false;
00402 }
00403
00404 QString KMailProtocolURLHandler::statusBarMessage( const KURL & url, KMReaderWin * ) const {
00405 if ( url.protocol() == "kmail" )
00406 {
00407 if ( url.path() == "showHTML" )
00408 return i18n("Turn on HTML rendering for this message.");
00409 if ( url.path() == "loadExternal" )
00410 return i18n("Load external references from the Internet for this message.");
00411 if ( url.path() == "goOnline" )
00412 return i18n("Work online.");
00413 if ( url.path() == "decryptMessage" )
00414 return i18n("Decrypt message.");
00415 if ( url.path() == "showSignatureDetails" )
00416 return i18n("Show signature details.");
00417 if ( url.path() == "hideSignatureDetails" )
00418 return i18n("Hide signature details.");
00419 }
00420 return QString::null ;
00421 }
00422 }
00423
00424 namespace {
00425
00426 bool ExpandCollapseQuoteURLManager::handleClick(
00427 const KURL & url, KMReaderWin * w ) const
00428 {
00429
00430
00431 if ( url.protocol() == "kmail" && url.path()=="levelquote" )
00432 {
00433 QString levelStr= url.query().mid( 1,url.query().length() );
00434 bool isNumber;
00435 int levelQuote= levelStr.toInt(&isNumber);
00436 if ( isNumber )
00437 w->slotLevelQuote( levelQuote );
00438 return true;
00439 }
00440 return false;
00441 }
00442 QString ExpandCollapseQuoteURLManager::statusBarMessage(
00443 const KURL & url, KMReaderWin * ) const
00444 {
00445 if ( url.protocol() == "kmail" && url.path() == "levelquote" )
00446 {
00447 QString query= url.query();
00448 if ( query.length()>=2 )
00449 if ( query[ 1 ] =='-' )
00450 return i18n("Expand all quoted text.");
00451 else
00452 return i18n("Collapse quoted text.");
00453 }
00454 return QString::null ;
00455 }
00456
00457 }
00458
00459
00460 extern bool foundSMIMEData( const QString aUrl, QString & displayName,
00461 QString & libName, QString & keyId );
00462
00463 namespace {
00464 bool SMimeURLHandler::handleClick( const KURL & url, KMReaderWin * w ) const {
00465 if ( !url.hasRef() )
00466 return false;
00467 QString displayName, libName, keyId;
00468 if ( !foundSMIMEData( url.path() + '#' + url.ref(), displayName, libName, keyId ) )
00469 return false;
00470 KProcess cmp;
00471 cmp << "kleopatra" << "-query" << keyId;
00472 if ( !cmp.start( KProcess::DontCare ) )
00473 KMessageBox::error( w, i18n("Could not start certificate manager. "
00474 "Please check your installation."),
00475 i18n("KMail Error") );
00476 return true;
00477 }
00478
00479 QString SMimeURLHandler::statusBarMessage( const KURL & url, KMReaderWin * ) const {
00480 QString displayName, libName, keyId;
00481 if ( !foundSMIMEData( url.path() + '#' + url.ref(), displayName, libName, keyId ) )
00482 return QString::null;
00483 return i18n("Show certificate 0x%1").arg( keyId );
00484 }
00485 }
00486
00487 namespace {
00488 bool HtmlAnchorHandler::handleClick( const KURL & url, KMReaderWin * w ) const {
00489 if ( url.hasHost() || url.path() != "/" || !url.hasRef() )
00490 return false;
00491 if ( w && !w->htmlPart()->gotoAnchor( url.ref() ) )
00492 static_cast<QScrollView*>( w->htmlPart()->widget() )->ensureVisible( 0, 0 );
00493 return true;
00494 }
00495 }
00496
00497 namespace {
00498 QString MailToURLHandler::statusBarMessage( const KURL & url, KMReaderWin * ) const {
00499 if ( url.protocol() != "mailto" )
00500 return QString::null;
00501 return KMMessage::decodeMailtoUrl( url.url() );
00502 }
00503 }
00504
00505 namespace {
00506 bool AttachmentURLHandler::handleClick( const KURL & url, KMReaderWin * w ) const {
00507 if ( !w || !w->message() )
00508 return false;
00509 const int id = KMReaderWin::msgPartFromUrl( url );
00510 if ( id <= 0 )
00511 return false;
00512 w->openAttachment( id, url.path() );
00513 return true;
00514 }
00515
00516 bool AttachmentURLHandler::handleContextMenuRequest( const KURL & url, const QPoint & p, KMReaderWin * w ) const {
00517 if ( !w || !w->message() )
00518 return false;
00519 const int id = KMReaderWin::msgPartFromUrl( url );
00520 if ( id <= 0 )
00521 return false;
00522 w->showAttachmentPopup( id, url.path(), p );
00523 return true;
00524 }
00525
00526 QString AttachmentURLHandler::statusBarMessage( const KURL & url, KMReaderWin * w ) const {
00527 if ( !w || !w->message() )
00528 return QString::null;
00529 const partNode * node = w->partNodeFromUrl( url );
00530 if ( !node )
00531 return QString::null;
00532 const KMMessagePart & msgPart = node->msgPart();
00533 QString name = msgPart.fileName();
00534 if ( name.isEmpty() )
00535 name = msgPart.name();
00536 if ( !name.isEmpty() )
00537 return i18n( "Attachment: %1" ).arg( name );
00538 return i18n( "Attachment #%1 (unnamed)" ).arg( KMReaderWin::msgPartFromUrl( url ) );
00539 }
00540 }
00541
00542 namespace {
00543 static QString extractAuditLog( const KURL & url ) {
00544 if ( url.protocol() != "kmail" || url.path() != "showAuditLog" )
00545 return QString();
00546 assert( !url.queryItem( "log" ).isEmpty() );
00547 return url.queryItem( "log" );
00548 }
00549
00550 bool ShowAuditLogURLHandler::handleClick( const KURL & url, KMReaderWin * w ) const {
00551 const QString auditLog = extractAuditLog( url );
00552 if ( auditLog.isEmpty() )
00553 return false;
00554 Kleo::MessageBox::auditLog( w, auditLog );
00555 return true;
00556 }
00557
00558 bool ShowAuditLogURLHandler::handleContextMenuRequest( const KURL & url, const QPoint &, KMReaderWin * w ) const {
00559
00560 return !extractAuditLog( url ).isEmpty();
00561 }
00562
00563 QString ShowAuditLogURLHandler::statusBarMessage( const KURL & url, KMReaderWin * ) const {
00564 if ( extractAuditLog( url ).isEmpty() )
00565 return QString();
00566 else
00567 return i18n("Show GnuPG Audit Log for this operation");
00568 }
00569 }
00570
00571 namespace {
00572 bool FallBackURLHandler::handleClick( const KURL & url, KMReaderWin * w ) const {
00573 if ( w )
00574 w->emitUrlClicked( url, Qt::LeftButton );
00575 return true;
00576 }
00577
00578 bool FallBackURLHandler::handleContextMenuRequest( const KURL & url, const QPoint & p, KMReaderWin * w ) const {
00579 if ( w )
00580 w->emitPopupMenu( url, p );
00581 return true;
00582 }
00583 }