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