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 "callback.h"
00045 #include "kimproxy.h"
00046 #include "stl_util.h"
00047
00048 #include <kurl.h>
00049
00050 #include <algorithm>
00051 using std::for_each;
00052 using std::remove;
00053 using std::find;
00054
00055 KMail::URLHandlerManager * KMail::URLHandlerManager::self = 0;
00056
00057 namespace {
00058 class ShowHtmlSwitchURLHandler : public KMail::URLHandler {
00059 public:
00060 ShowHtmlSwitchURLHandler() : KMail::URLHandler() {}
00061 ~ShowHtmlSwitchURLHandler() {}
00062
00063 bool handleClick( const KURL &, KMReaderWin * ) const;
00064 bool handleContextMenuRequest( const KURL &, const QPoint &, KMReaderWin * ) const {
00065 return false;
00066 }
00067 QString statusBarMessage( const KURL &, KMReaderWin * ) const;
00068 };
00069
00070 class SMimeURLHandler : public KMail::URLHandler {
00071 public:
00072 SMimeURLHandler() : KMail::URLHandler() {}
00073 ~SMimeURLHandler() {}
00074
00075 bool handleClick( const KURL &, KMReaderWin * ) const;
00076 bool handleContextMenuRequest( const KURL &, const QPoint &, KMReaderWin * ) const {
00077 return false;
00078 }
00079 QString statusBarMessage( const KURL &, KMReaderWin * ) const;
00080 };
00081
00082 class MailToURLHandler : public KMail::URLHandler {
00083 public:
00084 MailToURLHandler() : KMail::URLHandler() {}
00085 ~MailToURLHandler() {}
00086
00087 bool handleClick( const KURL &, KMReaderWin * ) const { return false; }
00088 bool handleContextMenuRequest( const KURL &, const QPoint &, KMReaderWin * ) const {
00089 return false;
00090 }
00091 QString statusBarMessage( const KURL &, KMReaderWin * ) const;
00092 };
00093
00094 class HtmlAnchorHandler : public KMail::URLHandler {
00095 public:
00096 HtmlAnchorHandler() : KMail::URLHandler() {}
00097 ~HtmlAnchorHandler() {}
00098
00099 bool handleClick( const KURL &, KMReaderWin * ) const;
00100 bool handleContextMenuRequest( const KURL &, const QPoint &, KMReaderWin * ) const {
00101 return false;
00102 }
00103 QString statusBarMessage( const KURL &, KMReaderWin * ) const { return QString::null; }
00104 };
00105
00106 class AttachmentURLHandler : public KMail::URLHandler {
00107 public:
00108 AttachmentURLHandler() : KMail::URLHandler() {}
00109 ~AttachmentURLHandler() {}
00110
00111 bool handleClick( const KURL &, KMReaderWin * ) const;
00112 bool handleContextMenuRequest( const KURL &, const QPoint &, KMReaderWin * ) const;
00113 QString statusBarMessage( const KURL &, KMReaderWin * ) const;
00114 };
00115
00116 class FallBackURLHandler : public KMail::URLHandler {
00117 public:
00118 FallBackURLHandler() : KMail::URLHandler() {}
00119 ~FallBackURLHandler() {}
00120
00121 bool handleClick( const KURL &, KMReaderWin * ) const;
00122 bool handleContextMenuRequest( const KURL &, const QPoint &, KMReaderWin * ) const;
00123 QString statusBarMessage( const KURL & url, KMReaderWin * ) const {
00124 return url.prettyURL();
00125 }
00126 };
00127
00128 }
00129
00130
00131
00132
00133
00134
00135
00136
00137 class KMail::URLHandlerManager::BodyPartURLHandlerManager : public KMail::URLHandler {
00138 public:
00139 BodyPartURLHandlerManager() : KMail::URLHandler() {}
00140 ~BodyPartURLHandlerManager();
00141
00142 bool handleClick( const KURL &, KMReaderWin * ) const;
00143 bool handleContextMenuRequest( const KURL &, const QPoint &, KMReaderWin * ) const;
00144 QString statusBarMessage( const KURL &, KMReaderWin * ) const;
00145
00146 void registerHandler( const Interface::BodyPartURLHandler * handler );
00147 void unregisterHandler( const Interface::BodyPartURLHandler * handler );
00148
00149 private:
00150 typedef QValueVector<const Interface::BodyPartURLHandler*> BodyPartHandlerList;
00151 BodyPartHandlerList mHandlers;
00152 };
00153
00154 KMail::URLHandlerManager::BodyPartURLHandlerManager::~BodyPartURLHandlerManager() {
00155 for_each( mHandlers.begin(), mHandlers.end(),
00156 DeleteAndSetToZero<Interface::BodyPartURLHandler> );
00157 }
00158
00159 void KMail::URLHandlerManager::BodyPartURLHandlerManager::registerHandler( const Interface::BodyPartURLHandler * handler ) {
00160 if ( !handler )
00161 return;
00162 unregisterHandler( handler );
00163 mHandlers.push_back( handler );
00164 }
00165
00166 void KMail::URLHandlerManager::BodyPartURLHandlerManager::unregisterHandler( const Interface::BodyPartURLHandler * handler ) {
00167
00168 mHandlers.erase( remove( mHandlers.begin(), mHandlers.end(), handler ), mHandlers.end() );
00169 }
00170
00171 static partNode * partNodeFromXKMailUrl( const KURL & url, KMReaderWin * w, QString * path ) {
00172 assert( path );
00173
00174 if ( !w || url.protocol() != "x-kmail" )
00175 return 0;
00176 const QString urlPath = url.path();
00177
00178
00179
00180 kdDebug( 5006 ) << "BodyPartURLHandler: urlPath == \"" << urlPath << "\"" << endl;
00181 if ( !urlPath.startsWith( "/bodypart/" ) )
00182 return 0;
00183
00184 const QStringList urlParts = QStringList::split( '/', urlPath.mid( 10 ), true );
00185 if ( urlParts.size() != 3 )
00186 return 0;
00187 bool ok = false;
00188 const int part_id = urlParts[1].toInt( &ok );
00189 if ( !ok )
00190 return 0;
00191 *path = KURL::decode_string( urlParts[2], 106 );
00192 return w->partNodeForId( part_id );
00193 }
00194
00195 bool KMail::URLHandlerManager::BodyPartURLHandlerManager::handleClick( const KURL & url, KMReaderWin * w ) const {
00196 QString path;
00197 partNode * node = partNodeFromXKMailUrl( url, w, &path );
00198 if ( !node )
00199 return false;
00200 KMMessage *msg = w->message();
00201 if ( !msg ) return false;
00202 Callback callback( msg );
00203 KMail::PartNodeBodyPart part( *node, w->overrideCodec() );
00204 for ( BodyPartHandlerList::const_iterator it = mHandlers.begin() ; it != mHandlers.end() ; ++it )
00205 if ( (*it)->handleClick( &part, path, callback ) )
00206 return true;
00207 return false;
00208 }
00209
00210 bool KMail::URLHandlerManager::BodyPartURLHandlerManager::handleContextMenuRequest( const KURL & url, const QPoint & p, KMReaderWin * w ) const {
00211 QString path;
00212 partNode * node = partNodeFromXKMailUrl( url, w, &path );
00213 if ( !node )
00214 return false;
00215
00216 KMail::PartNodeBodyPart part( *node, w->overrideCodec() );
00217 for ( BodyPartHandlerList::const_iterator it = mHandlers.begin() ; it != mHandlers.end() ; ++it )
00218 if ( (*it)->handleContextMenuRequest( &part, path, p ) )
00219 return true;
00220 return false;
00221 }
00222
00223 QString KMail::URLHandlerManager::BodyPartURLHandlerManager::statusBarMessage( const KURL & url, KMReaderWin * w ) const {
00224 QString path;
00225 partNode * node = partNodeFromXKMailUrl( url, w, &path );
00226 if ( !node )
00227 return QString::null;
00228
00229 KMail::PartNodeBodyPart part( *node, w->overrideCodec() );
00230 for ( BodyPartHandlerList::const_iterator it = mHandlers.begin() ; it != mHandlers.end() ; ++it ) {
00231 const QString msg = (*it)->statusBarMessage( &part, path );
00232 if ( !msg.isEmpty() )
00233 return msg;
00234 }
00235 return QString::null;
00236 }
00237
00238
00239
00240
00241
00242
00243
00244 KMail::URLHandlerManager::URLHandlerManager() {
00245 registerHandler( new ShowHtmlSwitchURLHandler() );
00246 registerHandler( new SMimeURLHandler() );
00247 registerHandler( new MailToURLHandler() );
00248 registerHandler( new HtmlAnchorHandler() );
00249 registerHandler( new AttachmentURLHandler() );
00250 registerHandler( mBodyPartURLHandlerManager = new BodyPartURLHandlerManager() );
00251 registerHandler( new FallBackURLHandler() );
00252 }
00253
00254 KMail::URLHandlerManager::~URLHandlerManager() {
00255 for_each( mHandlers.begin(), mHandlers.end(),
00256 DeleteAndSetToZero<URLHandler> );
00257 }
00258
00259 void KMail::URLHandlerManager::registerHandler( const URLHandler * handler ) {
00260 if ( !handler )
00261 return;
00262 unregisterHandler( handler );
00263 mHandlers.push_back( handler );
00264 }
00265
00266 void KMail::URLHandlerManager::unregisterHandler( const URLHandler * handler ) {
00267
00268 mHandlers.erase( remove( mHandlers.begin(), mHandlers.end(), handler ), mHandlers.end() );
00269 }
00270
00271 void KMail::URLHandlerManager::registerHandler( const Interface::BodyPartURLHandler * handler ) {
00272 if ( mBodyPartURLHandlerManager )
00273 mBodyPartURLHandlerManager->registerHandler( handler );
00274 }
00275
00276 void KMail::URLHandlerManager::unregisterHandler( const Interface::BodyPartURLHandler * handler ) {
00277 if ( mBodyPartURLHandlerManager )
00278 mBodyPartURLHandlerManager->unregisterHandler( handler );
00279 }
00280
00281 bool KMail::URLHandlerManager::handleClick( const KURL & url, KMReaderWin * w ) const {
00282 for ( HandlerList::const_iterator it = mHandlers.begin() ; it != mHandlers.end() ; ++it )
00283 if ( (*it)->handleClick( url, w ) )
00284 return true;
00285 return false;
00286 }
00287
00288 bool KMail::URLHandlerManager::handleContextMenuRequest( const KURL & url, const QPoint & p, KMReaderWin * w ) const {
00289 for ( HandlerList::const_iterator it = mHandlers.begin() ; it != mHandlers.end() ; ++it )
00290 if ( (*it)->handleContextMenuRequest( url, p, w ) )
00291 return true;
00292 return false;
00293 }
00294
00295 QString KMail::URLHandlerManager::statusBarMessage( const KURL & url, KMReaderWin * w ) const {
00296 for ( HandlerList::const_iterator it = mHandlers.begin() ; it != mHandlers.end() ; ++it ) {
00297 const QString msg = (*it)->statusBarMessage( url, w );
00298 if ( !msg.isEmpty() )
00299 return msg;
00300 }
00301 return QString::null;
00302 }
00303
00304
00305
00306
00307
00308
00309
00310
00311
00312
00313 #include "kmmessage.h"
00314 #include "kmkernel.h"
00315 #include "kmreaderwin.h"
00316 #include "partNode.h"
00317 #include "kmmsgpart.h"
00318
00319 #include <klocale.h>
00320 #include <kprocess.h>
00321 #include <kmessagebox.h>
00322 #include <khtml_part.h>
00323
00324 #include <qstring.h>
00325
00326 namespace {
00327 bool ShowHtmlSwitchURLHandler::handleClick( const KURL & url, KMReaderWin * w ) const {
00328 if ( url.protocol() == "kmail" )
00329 {
00330 if ( url.path() == "showHTML" )
00331 {
00332 if ( w ) {
00333 w->setHtmlOverride( !w->htmlOverride() );
00334 w->update( true );
00335 }
00336 return true;
00337 }
00338
00339
00340
00341
00342
00343
00344 }
00345 return false;
00346 }
00347
00348 QString ShowHtmlSwitchURLHandler::statusBarMessage( const KURL & url, KMReaderWin * ) const {
00349 return url.url() == "kmail:showHTML"
00350 ? i18n("Turn on HTML rendering for this message.")
00351 : QString::null ;
00352 }
00353 }
00354
00355
00356 extern bool foundSMIMEData( const QString aUrl, QString & displayName,
00357 QString & libName, QString & keyId );
00358
00359 namespace {
00360 bool SMimeURLHandler::handleClick( const KURL & url, KMReaderWin * w ) const {
00361 if ( !url.hasRef() )
00362 return false;
00363 QString displayName, libName, keyId;
00364 if ( !foundSMIMEData( url.path() + '#' + url.ref(), displayName, libName, keyId ) )
00365 return false;
00366 KProcess cmp;
00367 cmp << "kleopatra" << "-query" << keyId;
00368 if ( !cmp.start( KProcess::DontCare ) )
00369 KMessageBox::error( w, i18n("Could not start certificate manager. "
00370 "Please check your installation."),
00371 i18n("KMail Error") );
00372 return true;
00373 }
00374
00375 QString SMimeURLHandler::statusBarMessage( const KURL & url, KMReaderWin * ) const {
00376 QString displayName, libName, keyId;
00377 if ( !foundSMIMEData( url.path() + '#' + url.ref(), displayName, libName, keyId ) )
00378 return QString::null;
00379 return i18n("Show certificate 0x%1").arg( keyId );
00380 }
00381 }
00382
00383 namespace {
00384 bool HtmlAnchorHandler::handleClick( const KURL & url, KMReaderWin * w ) const {
00385 if ( url.hasHost() || url.path() != "/" || !url.hasRef() )
00386 return false;
00387 if ( w && !w->htmlPart()->gotoAnchor( url.ref() ) )
00388 static_cast<QScrollView*>( w->htmlPart()->widget() )->ensureVisible( 0, 0 );
00389 return true;
00390 }
00391 }
00392
00393 namespace {
00394 QString MailToURLHandler::statusBarMessage( const KURL & url, KMReaderWin * ) const {
00395 if ( url.protocol() != "mailto" )
00396 return QString::null;
00397 return KMMessage::decodeMailtoUrl( url.url() );
00398 }
00399 }
00400
00401 namespace {
00402 bool AttachmentURLHandler::handleClick( const KURL & url, KMReaderWin * w ) const {
00403 if ( !w || !w->message() )
00404 return false;
00405 const int id = KMReaderWin::msgPartFromUrl( url );
00406 if ( id <= 0 )
00407 return false;
00408 w->openAttachment( id, url.path() );
00409 return true;
00410 }
00411
00412 bool AttachmentURLHandler::handleContextMenuRequest( const KURL & url, const QPoint & p, KMReaderWin * w ) const {
00413 if ( !w || !w->message() )
00414 return false;
00415 const int id = KMReaderWin::msgPartFromUrl( url );
00416 if ( id <= 0 )
00417 return false;
00418 w->showAttachmentPopup( id, url.path(), p );
00419 return true;
00420 }
00421
00422 QString AttachmentURLHandler::statusBarMessage( const KURL & url, KMReaderWin * w ) const {
00423 if ( !w || !w->message() )
00424 return QString::null;
00425 const partNode * node = w->partNodeFromUrl( url );
00426 if ( !node )
00427 return QString::null;
00428 const KMMessagePart & msgPart = node->msgPart();
00429 QString name = msgPart.fileName();
00430 if ( name.isEmpty() )
00431 name = msgPart.name();
00432 if ( !name.isEmpty() )
00433 return i18n( "Attachment: %1" ).arg( name );
00434 return i18n( "Attachment #%1 (unnamed)" ).arg( KMReaderWin::msgPartFromUrl( url ) );
00435 }
00436 }
00437
00438 namespace {
00439 bool FallBackURLHandler::handleClick( const KURL & url, KMReaderWin * w ) const {
00440 if ( w )
00441 w->emitUrlClicked( url, Qt::LeftButton );
00442 return true;
00443 }
00444
00445 bool FallBackURLHandler::handleContextMenuRequest( const KURL & url, const QPoint & p, KMReaderWin * w ) const {
00446 if ( w )
00447 w->emitPopupMenu( url, p );
00448 return true;
00449 }
00450 }