kmail

urlhandlermanager.cpp

00001 /*  -*- c++ -*-
00002     urlhandlermanager.cpp
00003 
00004     This file is part of KMail, the KDE mail client.
00005     Copyright (c) 2002-2003 Klar�lvdalens Datakonsult AB
00006     Copyright (c) 2003      Marc Mutz <mutz@kde.org>
00007 
00008     KMail is free software; you can redistribute it and/or modify it
00009     under the terms of the GNU General Public License, version 2, as
00010     published by the Free Software Foundation.
00011 
00012     KMail is distributed in the hope that it will be useful, but
00013     WITHOUT ANY WARRANTY; without even the implied warranty of
00014     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00015     General Public License for more details.
00016 
00017     You should have received a copy of the GNU General Public License
00018     along with this program; if not, write to the Free Software
00019     Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
00020 
00021     In addition, as a special exception, the copyright holders give
00022     permission to link the code of this program with any edition of
00023     the Qt library by Trolltech AS, Norway (or with modified versions
00024     of Qt that use the same license as Qt), and distribute linked
00025     combinations including the two.  You must obey the GNU General
00026     Public License in all respects for all of the code used other than
00027     Qt.  If you modify this file, you may extend this exception to
00028     your version of the file, but you are not obligated to do so.  If
00029     you do not wish to do so, delete this exception statement from
00030     your version.
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 #include "stl_util.h"
00047 
00048 #include <kurldrag.h>
00049 #include <kimproxy.h>
00050 #include <kurl.h>
00051 
00052 #include <algorithm>
00053 using std::for_each;
00054 using std::remove;
00055 using std::find;
00056 
00057 KMail::URLHandlerManager * KMail::URLHandlerManager::self = 0;
00058 
00059 namespace {
00060   class KMailProtocolURLHandler : public KMail::URLHandler {
00061   public:
00062     KMailProtocolURLHandler() : KMail::URLHandler() {}
00063     ~KMailProtocolURLHandler() {}
00064 
00065     bool handleClick( const KURL &, KMReaderWin * ) const;
00066     bool handleContextMenuRequest( const KURL & url, const QPoint &, KMReaderWin * ) const {
00067       return url.protocol() == "kmail";
00068     }
00069     QString statusBarMessage( const KURL &, KMReaderWin * ) const;
00070   };
00071 
00072   class ExpandCollapseQuoteURLManager : public KMail::URLHandler {
00073   public:
00074     ExpandCollapseQuoteURLManager() : KMail::URLHandler() {}
00075     ~ExpandCollapseQuoteURLManager() {}
00076 
00077     bool handleClick( const KURL &, KMReaderWin * ) const;
00078     bool handleContextMenuRequest( const KURL &, const QPoint &, KMReaderWin * ) const {
00079       return false;
00080     }
00081     QString statusBarMessage( const KURL &, KMReaderWin * ) const;
00082 
00083   };
00084 
00085   class SMimeURLHandler : public KMail::URLHandler {
00086   public:
00087     SMimeURLHandler() : KMail::URLHandler() {}
00088     ~SMimeURLHandler() {}
00089 
00090     bool handleClick( const KURL &, KMReaderWin * ) const;
00091     bool handleContextMenuRequest( const KURL &, const QPoint &, KMReaderWin * ) const {
00092       return false;
00093     }
00094     QString statusBarMessage( const KURL &, KMReaderWin * ) const;
00095   };
00096 
00097   class MailToURLHandler : public KMail::URLHandler {
00098   public:
00099     MailToURLHandler() : KMail::URLHandler() {}
00100     ~MailToURLHandler() {}
00101 
00102     bool handleClick( const KURL &, KMReaderWin * ) const { return false; }
00103     bool handleContextMenuRequest( const KURL &, const QPoint &, KMReaderWin * ) const {
00104       return false;
00105     }
00106     QString statusBarMessage( const KURL &, KMReaderWin * ) const;
00107   };
00108 
00109   class HtmlAnchorHandler : public KMail::URLHandler {
00110   public:
00111     HtmlAnchorHandler() : KMail::URLHandler() {}
00112     ~HtmlAnchorHandler() {}
00113 
00114     bool handleClick( const KURL &, KMReaderWin * ) const;
00115     bool handleContextMenuRequest( const KURL &, const QPoint &, KMReaderWin * ) const {
00116       return false;
00117     }
00118     QString statusBarMessage( const KURL &, KMReaderWin * ) const { return QString::null; }
00119   };
00120 
00121   class AttachmentURLHandler : public KMail::URLHandler {
00122   public:
00123     AttachmentURLHandler() : KMail::URLHandler() {}
00124     ~AttachmentURLHandler() {}
00125 
00126     bool handleClick( const KURL &, KMReaderWin * ) const;
00127     bool handleShiftClick( const KURL &url, KMReaderWin *window ) const;
00128     bool handleDrag( const KURL &url, KMReaderWin *window ) const;
00129     bool willHandleDrag( const KURL &url, KMReaderWin *window ) const;
00130     bool handleContextMenuRequest( const KURL &, const QPoint &, KMReaderWin * ) const;
00131     QString statusBarMessage( const KURL &, KMReaderWin * ) const;
00132   private:
00133     partNode* partNodeForUrl( const KURL &url, KMReaderWin *w ) const;
00134     bool attachmentIsInHeader( const KURL &url ) const;
00135   };
00136 
00137   class ShowAuditLogURLHandler : public KMail::URLHandler {
00138   public:
00139       ShowAuditLogURLHandler() : KMail::URLHandler() {}
00140       ~ShowAuditLogURLHandler() {}
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 
00147   class FallBackURLHandler : public KMail::URLHandler {
00148   public:
00149     FallBackURLHandler() : KMail::URLHandler() {}
00150     ~FallBackURLHandler() {}
00151 
00152     bool handleClick( const KURL &, KMReaderWin * ) const;
00153     bool handleContextMenuRequest( const KURL &, const QPoint &, KMReaderWin * ) const;
00154     QString statusBarMessage( const KURL & url, KMReaderWin * ) const {
00155       return url.prettyURL();
00156     }
00157   };
00158 
00159 } // anon namespace
00160 
00161 
00162 //
00163 //
00164 // BodyPartURLHandlerManager
00165 //
00166 //
00167 
00168 class KMail::URLHandlerManager::BodyPartURLHandlerManager : public KMail::URLHandler {
00169 public:
00170   BodyPartURLHandlerManager() : KMail::URLHandler() {}
00171   ~BodyPartURLHandlerManager();
00172 
00173   bool handleClick( const KURL &, KMReaderWin * ) const;
00174   bool handleContextMenuRequest( const KURL &, const QPoint &, KMReaderWin * ) const;
00175   QString statusBarMessage( const KURL &, KMReaderWin * ) const;
00176 
00177   void registerHandler( const Interface::BodyPartURLHandler * handler );
00178   void unregisterHandler( const Interface::BodyPartURLHandler * handler );
00179 
00180 private:
00181   typedef QValueVector<const Interface::BodyPartURLHandler*> BodyPartHandlerList;
00182   BodyPartHandlerList mHandlers;
00183 };
00184 
00185 KMail::URLHandlerManager::BodyPartURLHandlerManager::~BodyPartURLHandlerManager() {
00186   for_each( mHandlers.begin(), mHandlers.end(),
00187         DeleteAndSetToZero<Interface::BodyPartURLHandler>() );
00188 }
00189 
00190 void KMail::URLHandlerManager::BodyPartURLHandlerManager::registerHandler( const Interface::BodyPartURLHandler * handler ) {
00191   if ( !handler )
00192     return;
00193   unregisterHandler( handler ); // don't produce duplicates
00194   mHandlers.push_back( handler );
00195 }
00196 
00197 void KMail::URLHandlerManager::BodyPartURLHandlerManager::unregisterHandler( const Interface::BodyPartURLHandler * handler ) {
00198   // don't delete them, only remove them from the list!
00199   mHandlers.erase( remove( mHandlers.begin(), mHandlers.end(), handler ), mHandlers.end() );
00200 }
00201 
00202 static partNode * partNodeFromXKMailUrl( const KURL & url, KMReaderWin * w, QString * path ) {
00203   assert( path );
00204 
00205   if ( !w || url.protocol() != "x-kmail" )
00206     return 0;
00207   const QString urlPath = url.path();
00208 
00209   // urlPath format is: /bodypart/<random number>/<part id>/<path>
00210 
00211   kdDebug( 5006 ) << "BodyPartURLHandler: urlPath == \"" << urlPath << "\"" << endl;
00212   if ( !urlPath.startsWith( "/bodypart/" ) )
00213     return 0;
00214 
00215   const QStringList urlParts = QStringList::split( '/', urlPath.mid( 10 ), true );
00216   if ( urlParts.size() != 3 )
00217     return 0;
00218   bool ok = false;
00219   const int part_id = urlParts[1].toInt( &ok );
00220   if ( !ok )
00221     return 0;
00222   *path = KURL::decode_string( urlParts[2] );
00223   return w->partNodeForId( part_id );
00224 }
00225 
00226 bool KMail::URLHandlerManager::BodyPartURLHandlerManager::handleClick( const KURL & url, KMReaderWin * w ) const {
00227   QString path;
00228   partNode * node = partNodeFromXKMailUrl( url, w, &path );
00229   if ( !node )
00230     return false;
00231   KMMessage *msg = w->message();
00232   if ( !msg ) return false;
00233   Callback callback( msg, w );
00234   KMail::PartNodeBodyPart part( *node, w->overrideCodec() );
00235   for ( BodyPartHandlerList::const_iterator it = mHandlers.begin() ; it != mHandlers.end() ; ++it )
00236     if ( (*it)->handleClick( &part, path, callback ) )
00237       return true;
00238   return false;
00239 }
00240 
00241 bool KMail::URLHandlerManager::BodyPartURLHandlerManager::handleContextMenuRequest( const KURL & url, const QPoint & p, KMReaderWin * w ) const {
00242   QString path;
00243   partNode * node = partNodeFromXKMailUrl( url, w, &path );
00244   if ( !node )
00245     return false;
00246 
00247   KMail::PartNodeBodyPart part( *node, w->overrideCodec() );
00248   for ( BodyPartHandlerList::const_iterator it = mHandlers.begin() ; it != mHandlers.end() ; ++it )
00249     if ( (*it)->handleContextMenuRequest( &part, path, p ) )
00250       return true;
00251   return false;
00252 }
00253 
00254 QString KMail::URLHandlerManager::BodyPartURLHandlerManager::statusBarMessage( const KURL & url, KMReaderWin * w ) const {
00255   QString path;
00256   partNode * node = partNodeFromXKMailUrl( url, w, &path );
00257   if ( !node )
00258     return QString::null;
00259 
00260   KMail::PartNodeBodyPart part( *node, w->overrideCodec() );
00261   for ( BodyPartHandlerList::const_iterator it = mHandlers.begin() ; it != mHandlers.end() ; ++it ) {
00262     const QString msg = (*it)->statusBarMessage( &part, path );
00263     if ( !msg.isEmpty() )
00264       return msg;
00265   }
00266   return QString::null;
00267 }
00268 
00269 //
00270 //
00271 // URLHandlerManager
00272 //
00273 //
00274 
00275 KMail::URLHandlerManager::URLHandlerManager() {
00276   registerHandler( new KMailProtocolURLHandler() );
00277   registerHandler( new ExpandCollapseQuoteURLManager() );
00278   registerHandler( new SMimeURLHandler() );
00279   registerHandler( new MailToURLHandler() );
00280   registerHandler( new HtmlAnchorHandler() );
00281   registerHandler( new AttachmentURLHandler() );
00282   registerHandler( mBodyPartURLHandlerManager = new BodyPartURLHandlerManager() );
00283   registerHandler( new ShowAuditLogURLHandler() );
00284   registerHandler( new FallBackURLHandler() );
00285 }
00286 
00287 KMail::URLHandlerManager::~URLHandlerManager() {
00288   for_each( mHandlers.begin(), mHandlers.end(),
00289         DeleteAndSetToZero<URLHandler>() );
00290 }
00291 
00292 void KMail::URLHandlerManager::registerHandler( const URLHandler * handler ) {
00293   if ( !handler )
00294     return;
00295   unregisterHandler( handler ); // don't produce duplicates
00296   mHandlers.push_back( handler );
00297 }
00298 
00299 void KMail::URLHandlerManager::unregisterHandler( const URLHandler * handler ) {
00300   // don't delete them, only remove them from the list!
00301   mHandlers.erase( remove( mHandlers.begin(), mHandlers.end(), handler ), mHandlers.end() );
00302 }
00303 
00304 void KMail::URLHandlerManager::registerHandler( const Interface::BodyPartURLHandler * handler ) {
00305   if ( mBodyPartURLHandlerManager )
00306     mBodyPartURLHandlerManager->registerHandler( handler );
00307 }
00308 
00309 void KMail::URLHandlerManager::unregisterHandler( const Interface::BodyPartURLHandler * handler ) {
00310   if ( mBodyPartURLHandlerManager )
00311     mBodyPartURLHandlerManager->unregisterHandler( handler );
00312 }
00313 
00314 bool KMail::URLHandlerManager::handleClick( const KURL & url, KMReaderWin * w ) const {
00315   for ( HandlerList::const_iterator it = mHandlers.begin() ; it != mHandlers.end() ; ++it )
00316     if ( (*it)->handleClick( url, w ) )
00317       return true;
00318   return false;
00319 }
00320 
00321 bool KMail::URLHandlerManager::handleShiftClick( const KURL &url, KMReaderWin *window ) const
00322 {
00323   for ( HandlerList::const_iterator it = mHandlers.begin() ; it != mHandlers.end() ; ++it )
00324     if ( (*it)->handleShiftClick( url, window ) )
00325       return true;
00326   return false;
00327 }
00328 
00329 bool KMail::URLHandlerManager::willHandleDrag( const KURL &url, KMReaderWin *window ) const
00330 {
00331   for ( HandlerList::const_iterator it = mHandlers.begin() ; it != mHandlers.end() ; ++it )
00332     if ( (*it)->willHandleDrag( url, window ) )
00333       return true;
00334   return false;
00335 }
00336 
00337 bool KMail::URLHandlerManager::handleDrag( const KURL &url, KMReaderWin *window ) const
00338 {
00339   for ( HandlerList::const_iterator it = mHandlers.begin() ; it != mHandlers.end() ; ++it )
00340     if ( (*it)->handleDrag( url, window ) )
00341       return true;
00342   return false;
00343 }
00344 
00345 bool KMail::URLHandlerManager::handleContextMenuRequest( const KURL & url, const QPoint & p, KMReaderWin * w ) const {
00346   for ( HandlerList::const_iterator it = mHandlers.begin() ; it != mHandlers.end() ; ++it )
00347     if ( (*it)->handleContextMenuRequest( url, p, w ) )
00348       return true;
00349   return false;
00350 }
00351 
00352 QString KMail::URLHandlerManager::statusBarMessage( const KURL & url, KMReaderWin * w ) const {
00353   for ( HandlerList::const_iterator it = mHandlers.begin() ; it != mHandlers.end() ; ++it ) {
00354     const QString msg = (*it)->statusBarMessage( url, w );
00355     if ( !msg.isEmpty() )
00356       return msg;
00357   }
00358   return QString::null;
00359 }
00360 
00361 
00362 //
00363 //
00364 // URLHandler
00365 //
00366 //
00367 
00368 // these includes are temporary and should not be needed for the code
00369 // above this line, so they appear only here:
00370 #include "kmmessage.h"
00371 #include "kmreaderwin.h"
00372 #include "partNode.h"
00373 #include "kmmsgpart.h"
00374 
00375 #include <ui/messagebox.h>
00376 
00377 #include <klocale.h>
00378 #include <kprocess.h>
00379 #include <kmessagebox.h>
00380 #include <khtml_part.h>
00381 
00382 #include <qstring.h>
00383 
00384 namespace {
00385   bool KMailProtocolURLHandler::handleClick( const KURL & url, KMReaderWin * w ) const {
00386     if ( url.protocol() == "kmail" ) {
00387       if ( !w )
00388         return false;
00389 
00390       if ( url.path() == "showHTML" ) {
00391         w->setHtmlOverride( !w->htmlOverride() );
00392         w->update( true );
00393         return true;
00394       }
00395 
00396       if ( url.path() == "loadExternal" ) {
00397         w->setHtmlLoadExtOverride( !w->htmlLoadExtOverride() );
00398         w->update( true );
00399         return true;
00400       }
00401 
00402       if ( url.path() == "goOnline" ) {
00403         kmkernel->resumeNetworkJobs();
00404         return true;
00405       }
00406 
00407       if ( url.path() == "decryptMessage" ) {
00408         w->setDecryptMessageOverwrite( true );
00409         w->update( true );
00410         return true;
00411       }
00412 
00413       if ( url.path() == "showSignatureDetails" ) {
00414         w->setShowSignatureDetails( true );
00415         w->update( true );
00416         return true;
00417       }
00418 
00419       if ( url.path() == "hideSignatureDetails" ) {
00420         w->setShowSignatureDetails( false );
00421         w->update( true );
00422         return true;
00423       }
00424 
00425       if ( url.path() == "showAttachmentQuicklist" ) {
00426       w->saveRelativePosition();
00427       w->setShowAttachmentQuicklist( true );
00428       w->update( true );
00429       return true;
00430       }
00431 
00432       if ( url.path() == "hideAttachmentQuicklist" ) {
00433       w->saveRelativePosition();
00434       w->setShowAttachmentQuicklist( false );
00435       w->update( true );
00436       return true;
00437       }
00438 
00439 //       if ( url.path() == "startIMApp" )
00440 //       {
00441 //         kmkernel->imProxy()->startPreferredApp();
00442 //         return true;
00443 //       }
00444 //       //FIXME: handle startIMApp urls in their own handler, or rename this one
00445     }
00446     return false;
00447   }
00448 
00449   QString KMailProtocolURLHandler::statusBarMessage( const KURL & url, KMReaderWin * ) const {
00450     if ( url.protocol() == "kmail" )
00451     {
00452       if ( url.path() == "showHTML" )
00453         return i18n("Turn on HTML rendering for this message.");
00454       if ( url.path() == "loadExternal" )
00455         return i18n("Load external references from the Internet for this message.");
00456       if ( url.path() == "goOnline" )
00457         return i18n("Work online.");
00458       if ( url.path() == "decryptMessage" )
00459         return i18n("Decrypt message.");
00460       if ( url.path() == "showSignatureDetails" )
00461         return i18n("Show signature details.");
00462       if ( url.path() == "hideSignatureDetails" )
00463         return i18n("Hide signature details.");
00464       if ( url.path() == "hideAttachmentQuicklist" )
00465         return i18n( "Hide attachment list" );
00466       if ( url.path() == "showAttachmentQuicklist" )
00467         return i18n( "Show attachment list" );
00468     }
00469     return QString::null ;
00470   }
00471 }
00472 
00473 namespace {
00474 
00475   bool ExpandCollapseQuoteURLManager::handleClick(
00476       const KURL & url, KMReaderWin * w ) const
00477   {
00478     //  kmail:levelquote/?num      -> the level quote to collapse.
00479     //  kmail:levelquote/?-num      -> expand all levels quote.
00480     if ( url.protocol() == "kmail" && url.path()=="levelquote" )
00481     {
00482       QString levelStr= url.query().mid( 1,url.query().length() );
00483       bool isNumber;
00484       int levelQuote= levelStr.toInt(&isNumber);
00485       if ( isNumber )
00486         w->slotLevelQuote( levelQuote );
00487       return true;
00488     }
00489     return false;
00490   }
00491   QString ExpandCollapseQuoteURLManager::statusBarMessage(
00492       const KURL & url, KMReaderWin * ) const
00493   {
00494       if ( url.protocol() == "kmail" && url.path() == "levelquote" )
00495       {
00496         QString query= url.query();
00497         if ( query.length()>=2 ) {
00498           if ( query[ 1 ] =='-'  ) {
00499             return i18n("Expand all quoted text.");
00500           }
00501           else {
00502             return i18n("Collapse quoted text.");
00503           }
00504         }
00505       }
00506       return QString::null ;
00507   }
00508 
00509 }
00510 
00511 // defined in kmreaderwin.cpp...
00512 extern bool foundSMIMEData( const QString aUrl, QString & displayName,
00513                 QString & libName, QString & keyId );
00514 
00515 namespace {
00516   bool SMimeURLHandler::handleClick( const KURL & url, KMReaderWin * w ) const {
00517     if ( !url.hasRef() )
00518       return false;
00519     QString displayName, libName, keyId;
00520     if ( !foundSMIMEData( url.path() + '#' + url.ref(), displayName, libName, keyId ) )
00521       return false;
00522     KProcess cmp;
00523     cmp << "kleopatra" << "-query" << keyId;
00524     if ( !cmp.start( KProcess::DontCare ) )
00525       KMessageBox::error( w, i18n("Could not start certificate manager. "
00526                   "Please check your installation."),
00527               i18n("KMail Error") );
00528     return true;
00529   }
00530 
00531   QString SMimeURLHandler::statusBarMessage( const KURL & url, KMReaderWin * ) const {
00532     QString displayName, libName, keyId;
00533     if ( !foundSMIMEData( url.path() + '#' + url.ref(), displayName, libName, keyId ) )
00534       return QString::null;
00535     return i18n("Show certificate 0x%1").arg( keyId );
00536   }
00537 }
00538 
00539 namespace {
00540   bool HtmlAnchorHandler::handleClick( const KURL & url, KMReaderWin * w ) const {
00541     if ( url.hasHost() || url.path() != "/" || !url.hasRef() )
00542       return false;
00543     if ( w && !w->htmlPart()->gotoAnchor( url.ref() ) )
00544       static_cast<QScrollView*>( w->htmlPart()->widget() )->ensureVisible( 0, 0 );
00545     return true;
00546   }
00547 }
00548 
00549 namespace {
00550   QString MailToURLHandler::statusBarMessage( const KURL & url, KMReaderWin * ) const {
00551     if ( url.protocol() != "mailto" )
00552       return QString::null;
00553     return KMMessage::decodeMailtoUrl( url.url() );
00554   }
00555 }
00556 
00557 namespace {
00558 
00559   partNode* AttachmentURLHandler::partNodeForUrl( const KURL &url, KMReaderWin *w ) const
00560   {
00561     if ( !w || !w->message() )
00562       return 0;
00563     if ( url.protocol() != "attachment" )
00564       return 0;
00565 
00566     bool ok;
00567     int nodeId = url.path().toInt( &ok );
00568     if ( !ok )
00569       return 0;
00570 
00571     partNode * node = w->partNodeForId( nodeId );
00572     return node;
00573   }
00574 
00575   bool AttachmentURLHandler::attachmentIsInHeader( const KURL &url ) const
00576   {
00577     bool inHeader = false;
00578     const QString place = url.queryItem( "place" ).lower();
00579     if ( place != QString::null ) {
00580       inHeader = ( place == "header" );
00581     }
00582     return inHeader;
00583   }
00584 
00585   bool AttachmentURLHandler::handleClick( const KURL & url, KMReaderWin * w ) const
00586   {
00587     partNode * node = partNodeForUrl( url, w );
00588     if ( !node )
00589       return false;
00590 
00591     const bool inHeader = attachmentIsInHeader( url );
00592     const bool shouldShowDialog = !node->isDisplayedEmbedded() || !inHeader;
00593     if ( inHeader )
00594       w->scrollToAttachment( node );
00595     if ( shouldShowDialog )
00596       w->openAttachment( node->nodeId(), w->tempFileUrlFromPartNode( node ).path() );
00597     return true;
00598   }
00599 
00600   bool AttachmentURLHandler::handleShiftClick( const KURL &url, KMReaderWin *window ) const
00601   {
00602     partNode * node = partNodeForUrl( url, window );
00603     if ( !node )
00604       return false;
00605     if ( !window )
00606       return false;
00607     window->saveAttachment( window->tempFileUrlFromPartNode( node ) );
00608     return true;
00609   }
00610 
00611   bool AttachmentURLHandler::willHandleDrag( const KURL &url, KMReaderWin *window ) const
00612   {
00613     return partNodeForUrl( url, window ) != 0;
00614   }
00615 
00616   bool AttachmentURLHandler::handleDrag( const KURL &url, KMReaderWin *window ) const
00617   {
00618     partNode * node = partNodeForUrl( url, window );
00619     if ( !node )
00620       return false;
00621 
00622     KURL file = window->tempFileUrlFromPartNode( node ).path();
00623     if ( !file.isEmpty() ) {
00624       QString icon = node->msgPart().iconName( KIcon::Small );
00625       KURLDrag* urlDrag = new KURLDrag( file, window );
00626       if ( !icon.isEmpty() ) {
00627         QPixmap iconMap( icon );
00628         urlDrag->setPixmap( iconMap );
00629       }
00630       urlDrag->drag();
00631       return true;
00632     }
00633     else
00634       return false;
00635   }
00636 
00637   bool AttachmentURLHandler::handleContextMenuRequest( const KURL & url, const QPoint & p, KMReaderWin * w ) const
00638   {
00639     partNode * node = partNodeForUrl( url, w );
00640     if ( !node )
00641       return false;
00642 
00643     w->showAttachmentPopup( node->nodeId(), w->tempFileUrlFromPartNode( node ).path(), p );
00644     return true;
00645   }
00646 
00647   QString AttachmentURLHandler::statusBarMessage( const KURL & url, KMReaderWin * w ) const
00648   {
00649     partNode * node = partNodeForUrl( url, w );
00650     if ( !node )
00651       return QString::null;
00652 
00653     const KMMessagePart & msgPart = node->msgPart();
00654     QString name = msgPart.fileName();
00655     if ( name.isEmpty() )
00656       name = msgPart.name();
00657     if ( !name.isEmpty() )
00658       return i18n( "Attachment: %1" ).arg( name );
00659     return i18n( "Attachment #%1 (unnamed)" ).arg( KMReaderWin::msgPartFromUrl( url ) );
00660   }
00661 }
00662 
00663 namespace {
00664   static QString extractAuditLog( const KURL & url ) {
00665     if ( url.protocol() != "kmail" || url.path() != "showAuditLog" )
00666       return QString();
00667     assert( !url.queryItem( "log" ).isEmpty() );
00668     return url.queryItem( "log" );
00669   }
00670 
00671   bool ShowAuditLogURLHandler::handleClick( const KURL & url, KMReaderWin * w ) const {
00672     const QString auditLog = extractAuditLog( url );
00673     if ( auditLog.isEmpty() )
00674         return false;
00675     Kleo::MessageBox::auditLog( w, auditLog );
00676     return true;
00677   }
00678 
00679   bool ShowAuditLogURLHandler::handleContextMenuRequest( const KURL & url, const QPoint &, KMReaderWin * w ) const
00680   {
00681     Q_UNUSED( w );
00682     // disable RMB for my own links:
00683     return !extractAuditLog( url ).isEmpty();
00684   }
00685 
00686   QString ShowAuditLogURLHandler::statusBarMessage( const KURL & url, KMReaderWin * ) const {
00687     if ( extractAuditLog( url ).isEmpty() )
00688       return QString();
00689     else
00690       return i18n("Show GnuPG Audit Log for this operation");
00691   }
00692 }
00693 
00694 namespace {
00695   bool FallBackURLHandler::handleClick( const KURL & url, KMReaderWin * w ) const {
00696     if ( w )
00697       w->emitUrlClicked( url, Qt::LeftButton );
00698     return true;
00699   }
00700 
00701   bool FallBackURLHandler::handleContextMenuRequest( const KURL & url, const QPoint & p, KMReaderWin * w ) const {
00702     if ( w )
00703       w->emitPopupMenu( url, p );
00704     return true;
00705   }
00706 }