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