kmail Library API Documentation

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