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 "kmcommands.h"
00046 #include "broadcaststatus.h"
00047 #include "callback.h"
00048 #include "stl_util.h"
00049 
00050 #include <kabc/stdaddressbook.h>
00051 #include <kabc/addressee.h>
00052 #include <dcopclient.h>
00053 #include <kstandarddirs.h>
00054 #include <kurldrag.h>
00055 #include <kimproxy.h>
00056 #include <kpopupmenu.h>
00057 #include <krun.h>
00058 #include <kurl.h>
00059 
00060 #include <qclipboard.h>
00061 
00062 #include <algorithm>
00063 using std::for_each;
00064 using std::remove;
00065 using std::find;
00066 
00067 KMail::URLHandlerManager * KMail::URLHandlerManager::self = 0;
00068 
00069 namespace {
00070   class KMailProtocolURLHandler : public KMail::URLHandler {
00071   public:
00072     KMailProtocolURLHandler() : KMail::URLHandler() {}
00073     ~KMailProtocolURLHandler() {}
00074 
00075     bool handleClick( const KURL &, KMReaderWin * ) const;
00076     bool handleContextMenuRequest( const KURL & url, const QPoint &, KMReaderWin * ) const {
00077       return url.protocol() == "kmail";
00078     }
00079     QString statusBarMessage( const KURL &, KMReaderWin * ) const;
00080   };
00081 
00082   class ExpandCollapseQuoteURLManager : public KMail::URLHandler {
00083   public:
00084     ExpandCollapseQuoteURLManager() : KMail::URLHandler() {}
00085     ~ExpandCollapseQuoteURLManager() {}
00086 
00087     bool handleClick( const KURL &, KMReaderWin * ) const;
00088     bool handleContextMenuRequest( const KURL &, const QPoint &, KMReaderWin * ) const {
00089       return false;
00090     }
00091     QString statusBarMessage( const KURL &, KMReaderWin * ) const;
00092 
00093   };
00094 
00095   class SMimeURLHandler : public KMail::URLHandler {
00096   public:
00097     SMimeURLHandler() : KMail::URLHandler() {}
00098     ~SMimeURLHandler() {}
00099 
00100     bool handleClick( const KURL &, KMReaderWin * ) const;
00101     bool handleContextMenuRequest( const KURL &, const QPoint &, KMReaderWin * ) const {
00102       return false;
00103     }
00104     QString statusBarMessage( const KURL &, KMReaderWin * ) const;
00105   };
00106 
00107   class MailToURLHandler : public KMail::URLHandler {
00108   public:
00109     MailToURLHandler() : KMail::URLHandler() {}
00110     ~MailToURLHandler() {}
00111 
00112     bool handleClick( const KURL &, KMReaderWin * ) const { return false; }
00113     bool handleContextMenuRequest( const KURL &, const QPoint &, KMReaderWin * ) const {
00114       return false;
00115     }
00116     QString statusBarMessage( const KURL &, KMReaderWin * ) const;
00117   };
00118 
00119   class ContactUidURLHandler : public KMail::URLHandler {
00120   public:
00121     ContactUidURLHandler() : KMail::URLHandler() {}
00122     ~ContactUidURLHandler() {}
00123 
00124     bool handleClick( const KURL &, KMReaderWin * ) const;
00125     bool handleContextMenuRequest( const KURL &url, const QPoint &p, KMReaderWin * ) const;
00126     QString statusBarMessage( const KURL &, KMReaderWin * ) const;
00127   };
00128 
00129   class HtmlAnchorHandler : public KMail::URLHandler {
00130   public:
00131     HtmlAnchorHandler() : KMail::URLHandler() {}
00132     ~HtmlAnchorHandler() {}
00133 
00134     bool handleClick( const KURL &, KMReaderWin * ) const;
00135     bool handleContextMenuRequest( const KURL &, const QPoint &, KMReaderWin * ) const {
00136       return false;
00137     }
00138     QString statusBarMessage( const KURL &, KMReaderWin * ) const { return QString::null; }
00139   };
00140 
00141   class AttachmentURLHandler : public KMail::URLHandler {
00142   public:
00143     AttachmentURLHandler() : KMail::URLHandler() {}
00144     ~AttachmentURLHandler() {}
00145 
00146     bool handleClick( const KURL &, KMReaderWin * ) const;
00147     bool handleShiftClick( const KURL &url, KMReaderWin *window ) const;
00148     bool handleDrag( const KURL &url, const QString& imagePath, KMReaderWin *window ) const;
00149     bool willHandleDrag( const KURL &url, const QString& imagePath, KMReaderWin *window ) const;
00150     bool handleContextMenuRequest( const KURL &, const QPoint &, KMReaderWin * ) const;
00151     QString statusBarMessage( const KURL &, KMReaderWin * ) const;
00152   private:
00153     partNode* partNodeForUrl( const KURL &url, KMReaderWin *w ) const;
00154     bool attachmentIsInHeader( const KURL &url ) const;
00155   };
00156 
00157   class ShowAuditLogURLHandler : public KMail::URLHandler {
00158   public:
00159       ShowAuditLogURLHandler() : KMail::URLHandler() {}
00160       ~ShowAuditLogURLHandler() {}
00161 
00162       bool handleClick( const KURL &, KMReaderWin * ) const;
00163       bool handleContextMenuRequest( const KURL &, const QPoint &, KMReaderWin * ) const;
00164       QString statusBarMessage( const KURL &, KMReaderWin * ) const;
00165   };
00166 
00167   // Handler that prevents dragging of internal images added by KMail, such as the envelope image
00168   // in the enterprise header
00169   class InternalImageURLHandler : public KMail::URLHandler {
00170   public:
00171       InternalImageURLHandler() : KMail::URLHandler()
00172         {}
00173       ~InternalImageURLHandler()
00174         {}
00175       bool handleDrag( const KURL &url, const QString& imagePath, KMReaderWin *window ) const;
00176       bool willHandleDrag( const KURL &url, const QString& imagePath, KMReaderWin *window ) const;
00177       bool handleClick( const KURL &, KMReaderWin * ) const
00178         { return false; }
00179       bool handleContextMenuRequest( const KURL &, const QPoint &, KMReaderWin * ) const
00180         { return false; }
00181       QString statusBarMessage( const KURL &, KMReaderWin * ) const
00182         { return QString(); }
00183   };
00184 
00185   class FallBackURLHandler : public KMail::URLHandler {
00186   public:
00187     FallBackURLHandler() : KMail::URLHandler() {}
00188     ~FallBackURLHandler() {}
00189 
00190     bool handleClick( const KURL &, KMReaderWin * ) const;
00191     bool handleContextMenuRequest( const KURL &, const QPoint &, KMReaderWin * ) const;
00192     QString statusBarMessage( const KURL & url, KMReaderWin * ) const {
00193       return url.prettyURL();
00194     }
00195   };
00196 
00197 } // anon namespace
00198 
00199 
00200 //
00201 //
00202 // BodyPartURLHandlerManager
00203 //
00204 //
00205 
00206 class KMail::URLHandlerManager::BodyPartURLHandlerManager : public KMail::URLHandler {
00207 public:
00208   BodyPartURLHandlerManager() : KMail::URLHandler() {}
00209   ~BodyPartURLHandlerManager();
00210 
00211   bool handleClick( const KURL &, KMReaderWin * ) const;
00212   bool handleContextMenuRequest( const KURL &, const QPoint &, KMReaderWin * ) const;
00213   QString statusBarMessage( const KURL &, KMReaderWin * ) const;
00214 
00215   void registerHandler( const Interface::BodyPartURLHandler * handler );
00216   void unregisterHandler( const Interface::BodyPartURLHandler * handler );
00217 
00218 private:
00219   typedef QValueVector<const Interface::BodyPartURLHandler*> BodyPartHandlerList;
00220   BodyPartHandlerList mHandlers;
00221 };
00222 
00223 KMail::URLHandlerManager::BodyPartURLHandlerManager::~BodyPartURLHandlerManager() {
00224   for_each( mHandlers.begin(), mHandlers.end(),
00225         DeleteAndSetToZero<Interface::BodyPartURLHandler>() );
00226 }
00227 
00228 void KMail::URLHandlerManager::BodyPartURLHandlerManager::registerHandler( const Interface::BodyPartURLHandler * handler ) {
00229   if ( !handler )
00230     return;
00231   unregisterHandler( handler ); // don't produce duplicates
00232   mHandlers.push_back( handler );
00233 }
00234 
00235 void KMail::URLHandlerManager::BodyPartURLHandlerManager::unregisterHandler( const Interface::BodyPartURLHandler * handler ) {
00236   // don't delete them, only remove them from the list!
00237   mHandlers.erase( remove( mHandlers.begin(), mHandlers.end(), handler ), mHandlers.end() );
00238 }
00239 
00240 static partNode * partNodeFromXKMailUrl( const KURL & url, KMReaderWin * w, QString * path ) {
00241   assert( path );
00242 
00243   if ( !w || url.protocol() != "x-kmail" )
00244     return 0;
00245   const QString urlPath = url.path();
00246 
00247   // urlPath format is: /bodypart/<random number>/<part id>/<path>
00248 
00249   kdDebug( 5006 ) << "BodyPartURLHandler: urlPath == \"" << urlPath << "\"" << endl;
00250   if ( !urlPath.startsWith( "/bodypart/" ) )
00251     return 0;
00252 
00253   const QStringList urlParts = QStringList::split( '/', urlPath.mid( 10 ), true );
00254   if ( urlParts.size() != 3 )
00255     return 0;
00256   bool ok = false;
00257   const int part_id = urlParts[1].toInt( &ok );
00258   if ( !ok )
00259     return 0;
00260   *path = KURL::decode_string( urlParts[2] );
00261   return w->partNodeForId( part_id );
00262 }
00263 
00264 bool KMail::URLHandlerManager::BodyPartURLHandlerManager::handleClick( const KURL & url, KMReaderWin * w ) const {
00265   QString path;
00266   partNode * node = partNodeFromXKMailUrl( url, w, &path );
00267   if ( !node )
00268     return false;
00269   KMMessage *msg = w->message();
00270   if ( !msg ) return false;
00271   Callback callback( msg, w );
00272   KMail::PartNodeBodyPart part( *node, w->overrideCodec() );
00273   for ( BodyPartHandlerList::const_iterator it = mHandlers.begin() ; it != mHandlers.end() ; ++it )
00274     if ( (*it)->handleClick( &part, path, callback ) )
00275       return true;
00276   return false;
00277 }
00278 
00279 bool KMail::URLHandlerManager::BodyPartURLHandlerManager::handleContextMenuRequest( const KURL & url, const QPoint & p, KMReaderWin * w ) const {
00280   QString path;
00281   partNode * node = partNodeFromXKMailUrl( url, w, &path );
00282   if ( !node )
00283     return false;
00284 
00285   KMail::PartNodeBodyPart part( *node, w->overrideCodec() );
00286   for ( BodyPartHandlerList::const_iterator it = mHandlers.begin() ; it != mHandlers.end() ; ++it )
00287     if ( (*it)->handleContextMenuRequest( &part, path, p ) )
00288       return true;
00289   return false;
00290 }
00291 
00292 QString KMail::URLHandlerManager::BodyPartURLHandlerManager::statusBarMessage( const KURL & url, KMReaderWin * w ) const {
00293   QString path;
00294   partNode * node = partNodeFromXKMailUrl( url, w, &path );
00295   if ( !node )
00296     return QString::null;
00297 
00298   KMail::PartNodeBodyPart part( *node, w->overrideCodec() );
00299   for ( BodyPartHandlerList::const_iterator it = mHandlers.begin() ; it != mHandlers.end() ; ++it ) {
00300     const QString msg = (*it)->statusBarMessage( &part, path );
00301     if ( !msg.isEmpty() )
00302       return msg;
00303   }
00304   return QString::null;
00305 }
00306 
00307 //
00308 //
00309 // URLHandlerManager
00310 //
00311 //
00312 
00313 KMail::URLHandlerManager::URLHandlerManager() {
00314   registerHandler( new KMailProtocolURLHandler() );
00315   registerHandler( new ExpandCollapseQuoteURLManager() );
00316   registerHandler( new SMimeURLHandler() );
00317   registerHandler( new MailToURLHandler() );
00318   registerHandler( new ContactUidURLHandler() );
00319   registerHandler( new HtmlAnchorHandler() );
00320   registerHandler( new AttachmentURLHandler() );
00321   registerHandler( mBodyPartURLHandlerManager = new BodyPartURLHandlerManager() );
00322   registerHandler( new ShowAuditLogURLHandler() );
00323   registerHandler( new InternalImageURLHandler );
00324   registerHandler( new FallBackURLHandler() );
00325 }
00326 
00327 KMail::URLHandlerManager::~URLHandlerManager() {
00328   for_each( mHandlers.begin(), mHandlers.end(),
00329         DeleteAndSetToZero<URLHandler>() );
00330 }
00331 
00332 void KMail::URLHandlerManager::registerHandler( const URLHandler * handler ) {
00333   if ( !handler )
00334     return;
00335   unregisterHandler( handler ); // don't produce duplicates
00336   mHandlers.push_back( handler );
00337 }
00338 
00339 void KMail::URLHandlerManager::unregisterHandler( const URLHandler * handler ) {
00340   // don't delete them, only remove them from the list!
00341   mHandlers.erase( remove( mHandlers.begin(), mHandlers.end(), handler ), mHandlers.end() );
00342 }
00343 
00344 void KMail::URLHandlerManager::registerHandler( const Interface::BodyPartURLHandler * handler ) {
00345   if ( mBodyPartURLHandlerManager )
00346     mBodyPartURLHandlerManager->registerHandler( handler );
00347 }
00348 
00349 void KMail::URLHandlerManager::unregisterHandler( const Interface::BodyPartURLHandler * handler ) {
00350   if ( mBodyPartURLHandlerManager )
00351     mBodyPartURLHandlerManager->unregisterHandler( handler );
00352 }
00353 
00354 bool KMail::URLHandlerManager::handleClick( const KURL & url, KMReaderWin * w ) const {
00355   for ( HandlerList::const_iterator it = mHandlers.begin() ; it != mHandlers.end() ; ++it )
00356     if ( (*it)->handleClick( url, w ) )
00357       return true;
00358   return false;
00359 }
00360 
00361 bool KMail::URLHandlerManager::handleShiftClick( const KURL &url, KMReaderWin *window ) const
00362 {
00363   for ( HandlerList::const_iterator it = mHandlers.begin() ; it != mHandlers.end() ; ++it )
00364     if ( (*it)->handleShiftClick( url, window ) )
00365       return true;
00366   return false;
00367 }
00368 
00369 bool KMail::URLHandlerManager::willHandleDrag( const KURL &url, const QString& imagePath,
00370                                                KMReaderWin *window ) const
00371 {
00372   for ( HandlerList::const_iterator it = mHandlers.begin() ; it != mHandlers.end() ; ++it )
00373     if ( (*it)->willHandleDrag( url, imagePath, window ) )
00374       return true;
00375   return false;
00376 }
00377 
00378 bool KMail::URLHandlerManager::handleDrag( const KURL &url, const QString& imagePath,
00379                                            KMReaderWin *window ) const
00380 {
00381   for ( HandlerList::const_iterator it = mHandlers.begin() ; it != mHandlers.end() ; ++it )
00382     if ( (*it)->handleDrag( url, imagePath, window ) )
00383       return true;
00384   return false;
00385 }
00386 
00387 bool KMail::URLHandlerManager::handleContextMenuRequest( const KURL & url, const QPoint & p, KMReaderWin * w ) const {
00388   for ( HandlerList::const_iterator it = mHandlers.begin() ; it != mHandlers.end() ; ++it )
00389     if ( (*it)->handleContextMenuRequest( url, p, w ) )
00390       return true;
00391   return false;
00392 }
00393 
00394 QString KMail::URLHandlerManager::statusBarMessage( const KURL & url, KMReaderWin * w ) const {
00395   for ( HandlerList::const_iterator it = mHandlers.begin() ; it != mHandlers.end() ; ++it ) {
00396     const QString msg = (*it)->statusBarMessage( url, w );
00397     if ( !msg.isEmpty() )
00398       return msg;
00399   }
00400   return QString::null;
00401 }
00402 
00403 
00404 //
00405 //
00406 // URLHandler
00407 //
00408 //
00409 
00410 // these includes are temporary and should not be needed for the code
00411 // above this line, so they appear only here:
00412 #include "kmmessage.h"
00413 #include "kmreaderwin.h"
00414 #include "partNode.h"
00415 #include "kmmsgpart.h"
00416 
00417 #include <ui/messagebox.h>
00418 
00419 #include <klocale.h>
00420 #include <kprocess.h>
00421 #include <kmessagebox.h>
00422 #include <khtml_part.h>
00423 
00424 #include <qstring.h>
00425 
00426 namespace {
00427   bool KMailProtocolURLHandler::handleClick( const KURL & url, KMReaderWin * w ) const {
00428     if ( url.protocol() == "kmail" ) {
00429       if ( !w )
00430         return false;
00431 
00432       if ( url.path() == "showHTML" ) {
00433         w->setHtmlOverride( !w->htmlOverride() );
00434         w->update( true );
00435         return true;
00436       }
00437 
00438       if ( url.path() == "loadExternal" ) {
00439         w->setHtmlLoadExtOverride( !w->htmlLoadExtOverride() );
00440         w->update( true );
00441         return true;
00442       }
00443 
00444       if ( url.path() == "goOnline" ) {
00445         kmkernel->resumeNetworkJobs();
00446         return true;
00447       }
00448 
00449       if ( url.path() == "decryptMessage" ) {
00450         w->setDecryptMessageOverwrite( true );
00451         w->update( true );
00452         return true;
00453       }
00454 
00455       if ( url.path() == "showSignatureDetails" ) {
00456         w->setShowSignatureDetails( true );
00457         w->update( true );
00458         return true;
00459       }
00460 
00461       if ( url.path() == "hideSignatureDetails" ) {
00462         w->setShowSignatureDetails( false );
00463         w->update( true );
00464         return true;
00465       }
00466 
00467       if ( url.path() == "showAttachmentQuicklist" ) {
00468       w->saveRelativePosition();
00469       w->setShowAttachmentQuicklist( true );
00470       w->update( true );
00471       return true;
00472       }
00473 
00474       if ( url.path() == "hideAttachmentQuicklist" ) {
00475       w->saveRelativePosition();
00476       w->setShowAttachmentQuicklist( false );
00477       w->update( true );
00478       return true;
00479       }
00480 
00481       if ( url.path() == "showRawToltecMail" ) {
00482         w->saveRelativePosition();
00483         w->setShowRawToltecMail( true );
00484         w->update( true );
00485         return true;
00486       }
00487 
00488 //       if ( url.path() == "startIMApp" )
00489 //       {
00490 //         kmkernel->imProxy()->startPreferredApp();
00491 //         return true;
00492 //       }
00493 //       //FIXME: handle startIMApp urls in their own handler, or rename this one
00494     }
00495     return false;
00496   }
00497 
00498   QString KMailProtocolURLHandler::statusBarMessage( const KURL & url, KMReaderWin * ) const {
00499     if ( url.protocol() == "kmail" )
00500     {
00501       if ( url.path() == "showHTML" )
00502         return i18n("Turn on HTML rendering for this message.");
00503       if ( url.path() == "loadExternal" )
00504         return i18n("Load external references from the Internet for this message.");
00505       if ( url.path() == "goOnline" )
00506         return i18n("Work online.");
00507       if ( url.path() == "decryptMessage" )
00508         return i18n("Decrypt message.");
00509       if ( url.path() == "showSignatureDetails" )
00510         return i18n("Show signature details.");
00511       if ( url.path() == "hideSignatureDetails" )
00512         return i18n("Hide signature details.");
00513       if ( url.path() == "hideAttachmentQuicklist" )
00514         return i18n( "Hide attachment list" );
00515       if ( url.path() == "showAttachmentQuicklist" )
00516         return i18n( "Show attachment list" );
00517     }
00518     return QString::null ;
00519   }
00520 }
00521 
00522 namespace {
00523 
00524   bool ExpandCollapseQuoteURLManager::handleClick(
00525       const KURL & url, KMReaderWin * w ) const
00526   {
00527     //  kmail:levelquote/?num      -> the level quote to collapse.
00528     //  kmail:levelquote/?-num      -> expand all levels quote.
00529     if ( url.protocol() == "kmail" && url.path()=="levelquote" )
00530     {
00531       QString levelStr= url.query().mid( 1,url.query().length() );
00532       bool isNumber;
00533       int levelQuote= levelStr.toInt(&isNumber);
00534       if ( isNumber )
00535         w->slotLevelQuote( levelQuote );
00536       return true;
00537     }
00538     return false;
00539   }
00540   QString ExpandCollapseQuoteURLManager::statusBarMessage(
00541       const KURL & url, KMReaderWin * ) const
00542   {
00543       if ( url.protocol() == "kmail" && url.path() == "levelquote" )
00544       {
00545         QString query= url.query();
00546         if ( query.length()>=2 ) {
00547           if ( query[ 1 ] =='-'  ) {
00548             return i18n("Expand all quoted text.");
00549           }
00550           else {
00551             return i18n("Collapse quoted text.");
00552           }
00553         }
00554       }
00555       return QString::null ;
00556   }
00557 
00558 }
00559 
00560 // defined in kmreaderwin.cpp...
00561 extern bool foundSMIMEData( const QString aUrl, QString & displayName,
00562                 QString & libName, QString & keyId );
00563 
00564 namespace {
00565   bool SMimeURLHandler::handleClick( const KURL & url, KMReaderWin * w ) const {
00566     if ( !url.hasRef() )
00567       return false;
00568     QString displayName, libName, keyId;
00569     if ( !foundSMIMEData( url.path() + '#' + url.ref(), displayName, libName, keyId ) )
00570       return false;
00571     KProcess cmp;
00572     cmp << "kleopatra" << "-query" << keyId;
00573     if ( !cmp.start( KProcess::DontCare ) )
00574       KMessageBox::error( w, i18n("Could not start certificate manager. "
00575                   "Please check your installation."),
00576               i18n("KMail Error") );
00577     return true;
00578   }
00579 
00580   QString SMimeURLHandler::statusBarMessage( const KURL & url, KMReaderWin * ) const {
00581     QString displayName, libName, keyId;
00582     if ( !foundSMIMEData( url.path() + '#' + url.ref(), displayName, libName, keyId ) )
00583       return QString::null;
00584     return i18n("Show certificate 0x%1").arg( keyId );
00585   }
00586 }
00587 
00588 namespace {
00589   bool HtmlAnchorHandler::handleClick( const KURL & url, KMReaderWin * w ) const {
00590     if ( url.hasHost() || url.path() != "/" || !url.hasRef() )
00591       return false;
00592     if ( w && !w->htmlPart()->gotoAnchor( url.ref() ) )
00593       static_cast<QScrollView*>( w->htmlPart()->widget() )->ensureVisible( 0, 0 );
00594     return true;
00595   }
00596 }
00597 
00598 namespace {
00599   QString MailToURLHandler::statusBarMessage( const KURL & url, KMReaderWin * ) const {
00600     if ( url.protocol() != "mailto" )
00601       return QString::null;
00602     return KMMessage::decodeMailtoUrl( url.url() );
00603   }
00604 }
00605 
00606 namespace {
00607   static QString searchFullEmailByUid( const QString &uid )
00608   {
00609     QString fullEmail;
00610     KABC::AddressBook *add_book = KABC::StdAddressBook::self( true );
00611     KABC::Addressee o = add_book->findByUid( uid );
00612     if ( !o.isEmpty() ) {
00613       fullEmail = o.fullEmail();
00614     }
00615     return fullEmail;
00616   }
00617 
00618   static void runKAddressBook( const KURL &url )
00619   {
00620     QString uid = url.path();
00621     DCOPClient *client = KApplication::kApplication()->dcopClient();
00622     const QByteArray noParamData;
00623     const QByteArray paramData;
00624     QByteArray replyData;
00625     QCString replyTypeStr;
00626     bool foundAbbrowser = client->call( "kaddressbook", "KAddressBookIface",
00627                                         "interfaces()",  noParamData,
00628                                         replyTypeStr, replyData );
00629     if ( foundAbbrowser ) {
00630       // KAddressbook is already running, so just DCOP to it to bring up the contact editor
00631       DCOPRef kaddressbook( "kaddressbook", "KAddressBookIface" );
00632       kaddressbook.send( "showContactEditor", uid );
00633     } else {
00634       // KaddressBook is not already running.
00635       // Pass it the UID of the contact via the command line while starting it - its neater.
00636       // We start it without its main interface
00637       QString iconPath = KGlobal::iconLoader()->iconPath( "go", KIcon::Small );
00638       QString tmpStr = "kaddressbook --editor-only --uid ";
00639       tmpStr += KProcess::quote( uid );
00640       KRun::runCommand( tmpStr, "KAddressBook", iconPath );
00641     }
00642   }
00643 
00644   bool ContactUidURLHandler::handleClick( const KURL &url, KMReaderWin * ) const
00645   {
00646     if ( url.protocol() != "uid" ) {
00647       return false;
00648     } else {
00649       runKAddressBook( url );
00650       return true;
00651     }
00652   }
00653 
00654   bool ContactUidURLHandler::handleContextMenuRequest( const KURL &url, const QPoint &p,
00655                                                        KMReaderWin * ) const
00656   {
00657     if ( url.protocol() != "uid" || url.path().isEmpty() ) {
00658       return false;
00659     }
00660 
00661     KPopupMenu *menu = new KPopupMenu();
00662     menu->insertItem( i18n( "&Open in Address Book" ), 0 );
00663     menu->insertItem( i18n( "&Copy Email Address" ), 1 );
00664     menu->insertItem( i18n( "&New Message to..." ), 2 );
00665 
00666     switch( menu->exec( p, 0 ) ) {
00667     case 0: // open
00668       runKAddressBook( url );
00669       break;
00670     case 1: // copy
00671     {
00672       const QString fullEmail = searchFullEmailByUid( url.path() );
00673       if ( !fullEmail.isEmpty() ) {
00674         QClipboard *clip = QApplication::clipboard();
00675         clip->setSelectionMode( true );
00676         clip->setText( fullEmail );
00677         clip->setSelectionMode( false );
00678         clip->setText( fullEmail );
00679         KPIM::BroadcastStatus::instance()->setStatusMsg( i18n( "Address copied to clipboard." ) );
00680       }
00681       break;
00682     }
00683     case 2: // send
00684     {
00685       const QString fullEmail = searchFullEmailByUid( url.path() );
00686       if ( !fullEmail.isEmpty() ) {
00687         KURL url;
00688         url.setProtocol( "mailto" );
00689         url.setPath( fullEmail );
00690         KMCommand *command = new KMMailtoComposeCommand( url );
00691         command->start();
00692       }
00693       break;
00694     }
00695     default:
00696       break;
00697     }
00698     return true;
00699   }
00700 
00701   QString ContactUidURLHandler::statusBarMessage( const KURL &url, KMReaderWin * ) const
00702   {
00703     if ( url.protocol() != "uid" ) {
00704       return QString::null;
00705     } else {
00706       return i18n( "Lookup the contact in KAddressbook" );
00707     }
00708   }
00709 }
00710 
00711 namespace {
00712 
00713   partNode* AttachmentURLHandler::partNodeForUrl( const KURL &url, KMReaderWin *w ) const
00714   {
00715     if ( !w || !w->message() )
00716       return 0;
00717     if ( url.protocol() != "attachment" )
00718       return 0;
00719 
00720     bool ok;
00721     int nodeId = url.path().toInt( &ok );
00722     if ( !ok )
00723       return 0;
00724 
00725     partNode * node = w->partNodeForId( nodeId );
00726     return node;
00727   }
00728 
00729   bool AttachmentURLHandler::attachmentIsInHeader( const KURL &url ) const
00730   {
00731     bool inHeader = false;
00732     const QString place = url.queryItem( "place" ).lower();
00733     if ( place != QString::null ) {
00734       inHeader = ( place == "header" );
00735     }
00736     return inHeader;
00737   }
00738 
00739   bool AttachmentURLHandler::handleClick( const KURL & url, KMReaderWin * w ) const
00740   {
00741     partNode * node = partNodeForUrl( url, w );
00742     if ( !node )
00743       return false;
00744 
00745     const bool inHeader = attachmentIsInHeader( url );
00746     const bool shouldShowDialog = !node->isDisplayedEmbedded() || !inHeader;
00747     if ( inHeader )
00748       w->scrollToAttachment( node );
00749     if ( shouldShowDialog )
00750       w->openAttachment( node->nodeId(), w->tempFileUrlFromPartNode( node ).path() );
00751     return true;
00752   }
00753 
00754   bool AttachmentURLHandler::handleShiftClick( const KURL &url, KMReaderWin *window ) const
00755   {
00756     partNode * node = partNodeForUrl( url, window );
00757     if ( !node )
00758       return false;
00759     if ( !window )
00760       return false;
00761     window->saveAttachment( window->tempFileUrlFromPartNode( node ) );
00762     return true;
00763   }
00764 
00765   bool AttachmentURLHandler::willHandleDrag( const KURL &url, const QString& imagePath,
00766                                              KMReaderWin *window ) const
00767   {
00768     Q_UNUSED( imagePath );
00769     return partNodeForUrl( url, window ) != 0;
00770   }
00771 
00772   bool AttachmentURLHandler::handleDrag( const KURL &url, const QString& imagePath,
00773                                          KMReaderWin *window ) const
00774   {
00775     Q_UNUSED( imagePath );
00776     const partNode * node = partNodeForUrl( url, window );
00777     if ( !node )
00778       return false;
00779 
00780     KURL file = window->tempFileUrlFromPartNode( node ).path();
00781     if ( !file.isEmpty() ) {
00782       QString icon = node->msgPart().iconName( KIcon::Small );
00783       KURLDrag* urlDrag = new KURLDrag( file, window );
00784       if ( !icon.isEmpty() ) {
00785         QPixmap iconMap( icon );
00786         urlDrag->setPixmap( iconMap );
00787       }
00788       urlDrag->drag();
00789       return true;
00790     }
00791     else {
00792       return false;
00793     }
00794   }
00795 
00796   bool AttachmentURLHandler::handleContextMenuRequest( const KURL & url, const QPoint & p, KMReaderWin * w ) const
00797   {
00798     partNode * node = partNodeForUrl( url, w );
00799     if ( !node )
00800       return false;
00801 
00802     w->showAttachmentPopup( node->nodeId(), w->tempFileUrlFromPartNode( node ).path(), p );
00803     return true;
00804   }
00805 
00806   QString AttachmentURLHandler::statusBarMessage( const KURL & url, KMReaderWin * w ) const
00807   {
00808     partNode * node = partNodeForUrl( url, w );
00809     if ( !node )
00810       return QString::null;
00811 
00812     const KMMessagePart & msgPart = node->msgPart();
00813     QString name = msgPart.fileName();
00814     if ( name.isEmpty() )
00815       name = msgPart.name();
00816     if ( !name.isEmpty() )
00817       return i18n( "Attachment: %1" ).arg( name );
00818     return i18n( "Attachment #%1 (unnamed)" ).arg( KMReaderWin::msgPartFromUrl( url ) );
00819   }
00820 }
00821 
00822 namespace {
00823   static QString extractAuditLog( const KURL & url ) {
00824     if ( url.protocol() != "kmail" || url.path() != "showAuditLog" )
00825       return QString();
00826     assert( !url.queryItem( "log" ).isEmpty() );
00827     return url.queryItem( "log" );
00828   }
00829 
00830   bool ShowAuditLogURLHandler::handleClick( const KURL & url, KMReaderWin * w ) const {
00831     const QString auditLog = extractAuditLog( url );
00832     if ( auditLog.isEmpty() )
00833         return false;
00834     Kleo::MessageBox::auditLog( w, auditLog );
00835     return true;
00836   }
00837 
00838   bool ShowAuditLogURLHandler::handleContextMenuRequest( const KURL & url, const QPoint &, KMReaderWin * w ) const
00839   {
00840     Q_UNUSED( w );
00841     // disable RMB for my own links:
00842     return !extractAuditLog( url ).isEmpty();
00843   }
00844 
00845   QString ShowAuditLogURLHandler::statusBarMessage( const KURL & url, KMReaderWin * ) const {
00846     if ( extractAuditLog( url ).isEmpty() )
00847       return QString();
00848     else
00849       return i18n("Show GnuPG Audit Log for this operation");
00850   }
00851 }
00852 
00853 namespace {
00854   bool InternalImageURLHandler::handleDrag( const KURL &url, const QString& imagePath,
00855                                             KMReaderWin *window ) const
00856   {
00857     Q_UNUSED( window );
00858     Q_UNUSED( url );
00859     const QString kmailImagePath = locate( "data", "kmail/pics/" );
00860     if ( imagePath.contains( kmailImagePath ) ) {
00861       // Do nothing, don't start a drag
00862       return true;
00863     }
00864     return false;
00865   }
00866 
00867   bool InternalImageURLHandler::willHandleDrag( const KURL &url, const QString& imagePath,
00868                                                 KMReaderWin *window ) const
00869   {
00870     Q_UNUSED( window );
00871     Q_UNUSED( url );
00872     const QString kmailImagePath = locate( "data", "kmail/pics/" );
00873     return imagePath.contains( kmailImagePath );
00874   }
00875 }
00876 
00877 namespace {
00878   bool FallBackURLHandler::handleClick( const KURL & url, KMReaderWin * w ) const {
00879     if ( w )
00880       w->emitUrlClicked( url, Qt::LeftButton );
00881     return true;
00882   }
00883 
00884   bool FallBackURLHandler::handleContextMenuRequest( const KURL & url, const QPoint & p, KMReaderWin * w ) const {
00885     if ( w )
00886       w->emitPopupMenu( url, p );
00887     return true;
00888   }
00889 }
KDE Home | KDE Accessibility Home | Description of Access Keys