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
00364
00365
00366
00367
00368
00369 }
00370 return false;
00371 }
00372
00373 QString ShowHtmlSwitchURLHandler::statusBarMessage( const KURL & url, KMReaderWin * ) const {
00374 if ( url.protocol() == "kmail" )
00375 {
00376 if ( url.path() == "showHTML" )
00377 return i18n("Turn on HTML rendering for this message.");
00378 if ( url.path() == "loadExternal" )
00379 return i18n("Load external references from the Internet for this message.");
00380 if ( url.path() == "goOnline" )
00381 return i18n("Work online");
00382 }
00383 return QString::null ;
00384 }
00385 }
00386
00387 namespace {
00388
00389 bool ExpandCollapseQuoteURLManager::handleClick(
00390 const KURL & url, KMReaderWin * w ) const
00391 {
00392
00393
00394 if ( url.protocol() == "kmail" && url.path()=="levelquote" )
00395 {
00396 QString levelStr= url.query().mid( 1,url.query().length() );
00397 bool isNumber;
00398 int levelQuote= levelStr.toInt(&isNumber);
00399 if ( isNumber )
00400 w->slotLevelQuote( levelQuote );
00401 return true;
00402 }
00403 return false;
00404 }
00405 QString ExpandCollapseQuoteURLManager::statusBarMessage(
00406 const KURL & url, KMReaderWin * ) const
00407 {
00408 if ( url.protocol() == "kmail" && url.path() == "levelquote" )
00409 {
00410 QString query= url.query();
00411 if ( query.length()>=2 )
00412 if ( query[ 1 ] =='-' )
00413 return i18n("Expand all quoted text.");
00414 else
00415 return i18n("Collapse quoted text.");
00416 }
00417 return QString::null ;
00418 }
00419
00420 }
00421
00422
00423 extern bool foundSMIMEData( const QString aUrl, QString & displayName,
00424 QString & libName, QString & keyId );
00425
00426 namespace {
00427 bool SMimeURLHandler::handleClick( const KURL & url, KMReaderWin * w ) const {
00428 if ( !url.hasRef() )
00429 return false;
00430 QString displayName, libName, keyId;
00431 if ( !foundSMIMEData( url.path() + '#' + url.ref(), displayName, libName, keyId ) )
00432 return false;
00433 KProcess cmp;
00434 cmp << "kleopatra" << "-query" << keyId;
00435 if ( !cmp.start( KProcess::DontCare ) )
00436 KMessageBox::error( w, i18n("Could not start certificate manager. "
00437 "Please check your installation."),
00438 i18n("KMail Error") );
00439 return true;
00440 }
00441
00442 QString SMimeURLHandler::statusBarMessage( const KURL & url, KMReaderWin * ) const {
00443 QString displayName, libName, keyId;
00444 if ( !foundSMIMEData( url.path() + '#' + url.ref(), displayName, libName, keyId ) )
00445 return QString::null;
00446 return i18n("Show certificate 0x%1").arg( keyId );
00447 }
00448 }
00449
00450 namespace {
00451 bool HtmlAnchorHandler::handleClick( const KURL & url, KMReaderWin * w ) const {
00452 if ( url.hasHost() || url.path() != "/" || !url.hasRef() )
00453 return false;
00454 if ( w && !w->htmlPart()->gotoAnchor( url.ref() ) )
00455 static_cast<QScrollView*>( w->htmlPart()->widget() )->ensureVisible( 0, 0 );
00456 return true;
00457 }
00458 }
00459
00460 namespace {
00461 QString MailToURLHandler::statusBarMessage( const KURL & url, KMReaderWin * ) const {
00462 if ( url.protocol() != "mailto" )
00463 return QString::null;
00464 return KMMessage::decodeMailtoUrl( url.url() );
00465 }
00466 }
00467
00468 namespace {
00469 bool AttachmentURLHandler::handleClick( const KURL & url, KMReaderWin * w ) const {
00470 if ( !w || !w->message() )
00471 return false;
00472 const int id = KMReaderWin::msgPartFromUrl( url );
00473 if ( id <= 0 )
00474 return false;
00475 w->openAttachment( id, url.path() );
00476 return true;
00477 }
00478
00479 bool AttachmentURLHandler::handleContextMenuRequest( const KURL & url, const QPoint & p, KMReaderWin * w ) const {
00480 if ( !w || !w->message() )
00481 return false;
00482 const int id = KMReaderWin::msgPartFromUrl( url );
00483 if ( id <= 0 )
00484 return false;
00485 w->showAttachmentPopup( id, url.path(), p );
00486 return true;
00487 }
00488
00489 QString AttachmentURLHandler::statusBarMessage( const KURL & url, KMReaderWin * w ) const {
00490 if ( !w || !w->message() )
00491 return QString::null;
00492 const partNode * node = w->partNodeFromUrl( url );
00493 if ( !node )
00494 return QString::null;
00495 const KMMessagePart & msgPart = node->msgPart();
00496 QString name = msgPart.fileName();
00497 if ( name.isEmpty() )
00498 name = msgPart.name();
00499 if ( !name.isEmpty() )
00500 return i18n( "Attachment: %1" ).arg( name );
00501 return i18n( "Attachment #%1 (unnamed)" ).arg( KMReaderWin::msgPartFromUrl( url ) );
00502 }
00503 }
00504
00505 namespace {
00506 bool FallBackURLHandler::handleClick( const KURL & url, KMReaderWin * w ) const {
00507 if ( w )
00508 w->emitUrlClicked( url, Qt::LeftButton );
00509 return true;
00510 }
00511
00512 bool FallBackURLHandler::handleContextMenuRequest( const KURL & url, const QPoint & p, KMReaderWin * w ) const {
00513 if ( w )
00514 w->emitPopupMenu( url, p );
00515 return true;
00516 }
00517 }