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