• Skip to content
  • Skip to link menu
KDE API Reference
  • KDE API Reference
  • kdepim API Reference
  • KDE Home
  • Contact Us
 

messageviewer

  • sources
  • kde-4.14
  • kdepim
  • messageviewer
  • viewer
urlhandlermanager.cpp
Go to the documentation of this file.
1 
2 /* -*- c++ -*-
3  urlhandlermanager.cpp
4 
5  This file is part of KMail, the KDE mail client.
6  Copyright (c) 2003 Marc Mutz <mutz@kde.org>
7  Copyright (C) 2002-2003, 2009 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.net
8  Copyright (c) 2009 Andras Mantia <andras@kdab.net>
9 
10  KMail is free software; you can redistribute it and/or modify it
11  under the terms of the GNU General Public License, version 2, as
12  published by the Free Software Foundation.
13 
14  KMail is distributed in the hope that it will be useful, but
15  WITHOUT ANY WARRANTY; without even the implied warranty of
16  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17  General Public License for more details.
18 
19  You should have received a copy of the GNU General Public License
20  along with this program; if not, write to the Free Software
21  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22 
23  In addition, as a special exception, the copyright holders give
24  permission to link the code of this program with any edition of
25  the Qt library by Trolltech AS, Norway (or with modified versions
26  of Qt that use the same license as Qt), and distribute linked
27  combinations including the two. You must obey the GNU General
28  Public License in all respects for all of the code used other than
29  Qt. If you modify this file, you may extend this exception to
30  your version of the file, but you are not obligated to do so. If
31  you do not wish to do so, delete this exception statement from
32  your version.
33 */
34 
35 
36 
37 
38 #include "urlhandlermanager.h"
39 
40 #include "interfaces/urlhandler.h"
41 #include "interfaces/bodyparturlhandler.h"
42 #include "partnodebodypart.h"
43 #include "viewer/viewer_p.h"
44 #include "viewer/mailwebview.h"
45 #include "viewer/nodehelper.h"
46 #include "utils/util.h"
47 #include "stl_util.h"
48 
49 #include <messagecore/utils/stringutil.h>
50 #include <libkdepim/misc/broadcaststatus.h>
51 #include <libkdepim/job/openemailaddressjob.h>
52 
53 #include <akonadi/contact/contactsearchjob.h>
54 
55 #include <kmime/kmime_content.h>
56 #include <KPIMUtils/Email>
57 #include <KPIMUtils/KFileIO>
58 
59 #include <KMenu>
60 #include <KMimeType>
61 #include <KRun>
62 #include <KStandardDirs>
63 #include <KUrl>
64 
65 #include <QApplication>
66 #include <QClipboard>
67 #include <QProcess>
68 #include <QFile>
69 #include <QMimeData>
70 #include <QDrag>
71 
72 #include <algorithm>
73 
74 using std::for_each;
75 using std::remove;
76 using std::find;
77 using namespace MessageViewer;
78 using namespace MessageCore;
79 
80 URLHandlerManager * URLHandlerManager::self = 0;
81 
82 namespace {
83 class KMailProtocolURLHandler : public URLHandler {
84 public:
85  KMailProtocolURLHandler() : URLHandler() {}
86  ~KMailProtocolURLHandler() {}
87 
88  bool handleClick( const KUrl &, ViewerPrivate * ) const;
89  bool handleContextMenuRequest( const KUrl & url, const QPoint &, ViewerPrivate * ) const {
90  return url.protocol() == QLatin1String( "kmail" );
91  }
92  QString statusBarMessage( const KUrl &, ViewerPrivate * ) const;
93 };
94 
95 class ExpandCollapseQuoteURLManager : public URLHandler {
96 public:
97  ExpandCollapseQuoteURLManager() : URLHandler() {}
98  ~ExpandCollapseQuoteURLManager() {}
99 
100  bool handleClick( const KUrl &, ViewerPrivate * ) const;
101  bool handleContextMenuRequest( const KUrl &, const QPoint &, ViewerPrivate * ) const {
102  return false;
103  }
104  QString statusBarMessage( const KUrl &, ViewerPrivate * ) const;
105 
106 };
107 
108 class SMimeURLHandler : public URLHandler {
109 public:
110  SMimeURLHandler() : URLHandler() {}
111  ~SMimeURLHandler() {}
112 
113  bool handleClick( const KUrl &, ViewerPrivate * ) const;
114  bool handleContextMenuRequest( const KUrl &, const QPoint &, ViewerPrivate * ) const {
115  return false;
116  }
117  QString statusBarMessage( const KUrl &, ViewerPrivate * ) const;
118 };
119 
120 class MailToURLHandler : public URLHandler {
121 public:
122  MailToURLHandler() : URLHandler() {}
123  ~MailToURLHandler() {}
124 
125  bool handleClick( const KUrl &, ViewerPrivate * ) const { return false; }
126  bool handleContextMenuRequest( const KUrl &, const QPoint &, ViewerPrivate * ) const {
127  return false;
128  }
129  QString statusBarMessage( const KUrl &, ViewerPrivate * ) const;
130 };
131 
132 class ContactUidURLHandler : public URLHandler {
133 public:
134  ContactUidURLHandler() : URLHandler() {}
135  ~ContactUidURLHandler() {}
136 
137  bool handleClick( const KUrl &, ViewerPrivate * ) const;
138  bool handleContextMenuRequest( const KUrl &url, const QPoint &p, ViewerPrivate * ) const;
139  QString statusBarMessage( const KUrl &, ViewerPrivate * ) const;
140 };
141 
142 class HtmlAnchorHandler : public URLHandler {
143 public:
144  HtmlAnchorHandler() : URLHandler() {}
145  ~HtmlAnchorHandler() {}
146 
147  bool handleClick( const KUrl &, ViewerPrivate * ) const;
148  bool handleContextMenuRequest( const KUrl &, const QPoint &, ViewerPrivate * ) const {
149  return false;
150  }
151  QString statusBarMessage( const KUrl &, ViewerPrivate * ) const { return QString(); }
152 };
153 
154 class AttachmentURLHandler : public URLHandler {
155 public:
156  AttachmentURLHandler() : URLHandler() {}
157  ~AttachmentURLHandler() {}
158 
159  bool handleClick( const KUrl &, ViewerPrivate * ) const;
160  bool handleShiftClick( const KUrl &, ViewerPrivate *window ) const;
161  bool handleContextMenuRequest( const KUrl &, const QPoint &, ViewerPrivate * ) const;
162  bool handleDrag( const KUrl &url, ViewerPrivate *window ) const;
163  bool willHandleDrag( const KUrl &url, ViewerPrivate *window ) const;
164  QString statusBarMessage( const KUrl &, ViewerPrivate * ) const;
165 private:
166  KMime::Content* nodeForUrl( const KUrl &url, ViewerPrivate *w ) const;
167  bool attachmentIsInHeader( const KUrl &url ) const;
168 };
169 
170 class ShowAuditLogURLHandler : public URLHandler {
171 public:
172  ShowAuditLogURLHandler() : URLHandler() {}
173  ~ShowAuditLogURLHandler() {}
174 
175  bool handleClick( const KUrl &, ViewerPrivate * ) const;
176  bool handleContextMenuRequest( const KUrl &, const QPoint &, ViewerPrivate * ) const;
177  QString statusBarMessage( const KUrl &, ViewerPrivate * ) const;
178 };
179 
180 // Handler that prevents dragging of internal images added by KMail, such as the envelope image
181 // in the enterprise header
182 class InternalImageURLHandler : public URLHandler {
183 public:
184  InternalImageURLHandler() : URLHandler()
185  {}
186  ~InternalImageURLHandler()
187  {}
188  bool handleDrag( const KUrl &url, ViewerPrivate *window ) const;
189  bool willHandleDrag( const KUrl &url, ViewerPrivate *window ) const;
190  bool handleClick( const KUrl &, ViewerPrivate * ) const
191  { return false; }
192  bool handleContextMenuRequest( const KUrl &, const QPoint &, ViewerPrivate * ) const
193  { return false; }
194  QString statusBarMessage( const KUrl &, ViewerPrivate * ) const
195  { return QString(); }
196 };
197 
198 class KRunURLHandler : public URLHandler {
199 public:
200  KRunURLHandler() : URLHandler()
201  {}
202  ~KRunURLHandler()
203  {}
204 
205  bool handleClick( const KUrl &, ViewerPrivate * ) const;
206  bool handleContextMenuRequest( const KUrl &, const QPoint &, ViewerPrivate * ) const {
207  return false;
208  }
209  QString statusBarMessage( const KUrl &, ViewerPrivate * ) const { return QString(); }
210 };
211 
212 } // anon namespace
213 
214 
215 //
216 //
217 // BodyPartURLHandlerManager
218 //
219 //
220 
221 class URLHandlerManager::BodyPartURLHandlerManager : public URLHandler {
222 public:
223  BodyPartURLHandlerManager() : URLHandler() {}
224  ~BodyPartURLHandlerManager();
225 
226  bool handleClick( const KUrl &, ViewerPrivate * ) const;
227  bool handleContextMenuRequest( const KUrl &, const QPoint &, ViewerPrivate * ) const;
228  QString statusBarMessage( const KUrl &, ViewerPrivate * ) const;
229 
230  void registerHandler( const Interface::BodyPartURLHandler * handler );
231  void unregisterHandler( const Interface::BodyPartURLHandler * handler );
232 
233 private:
234  typedef QVector<const Interface::BodyPartURLHandler*> BodyPartHandlerList;
235  BodyPartHandlerList mHandlers;
236 };
237 
238 URLHandlerManager::BodyPartURLHandlerManager::~BodyPartURLHandlerManager() {
239  for_each( mHandlers.begin(), mHandlers.end(),
240  DeleteAndSetToZero<Interface::BodyPartURLHandler>() );
241 }
242 
243 void URLHandlerManager::BodyPartURLHandlerManager::registerHandler( const Interface::BodyPartURLHandler * handler ) {
244  if ( !handler )
245  return;
246  unregisterHandler( handler ); // don't produce duplicates
247  mHandlers.push_back( handler );
248 }
249 
250 void URLHandlerManager::BodyPartURLHandlerManager::unregisterHandler( const Interface::BodyPartURLHandler * handler ) {
251  // don't delete them, only remove them from the list!
252  mHandlers.erase( remove( mHandlers.begin(), mHandlers.end(), handler ), mHandlers.end() );
253 }
254 
255 static KMime::Content * partNodeFromXKMailUrl( const KUrl & url, ViewerPrivate * w, QString * path ) {
256  assert( path );
257 
258  if ( !w || url.protocol() != QLatin1String( "x-kmail" ) )
259  return 0;
260  const QString urlPath = url.path();
261 
262  // urlPath format is: /bodypart/<random number>/<part id>/<path>
263 
264  kDebug() << "BodyPartURLHandler: urlPath ==" << urlPath;
265  if ( !urlPath.startsWith( QLatin1String("/bodypart/") ) )
266  return 0;
267 
268  const QStringList urlParts = urlPath.mid( 10 ).split( QLatin1Char('/') );
269  if ( urlParts.size() != 3 )
270  return 0;
271  //KMime::ContentIndex index( urlParts[1] );
272  *path = KUrl::fromPercentEncoding( urlParts[2].toLatin1() );
273  return w->nodeFromUrl( urlParts[1] );
274 }
275 
276 bool URLHandlerManager::BodyPartURLHandlerManager::handleClick( const KUrl & url, ViewerPrivate * w ) const {
277  QString path;
278  KMime::Content * node = partNodeFromXKMailUrl( url, w, &path );
279  if ( !node )
280  return false;
281 
282  PartNodeBodyPart part( w->message().get(), node, w->nodeHelper(), w->overrideCodec() );
283  BodyPartHandlerList::const_iterator end( mHandlers.constEnd() );
284 
285  for ( BodyPartHandlerList::const_iterator it = mHandlers.constBegin() ; it != end ; ++it ) {
286  if ( (*it)->handleClick( w->viewer(), &part, path ) )
287  return true;
288  }
289 
290  return false;
291 }
292 
293 bool URLHandlerManager::BodyPartURLHandlerManager::handleContextMenuRequest( const KUrl & url, const QPoint & p, ViewerPrivate * w ) const {
294  QString path;
295  KMime::Content * node = partNodeFromXKMailUrl( url, w, &path );
296  if ( !node )
297  return false;
298 
299  PartNodeBodyPart part( w->message().get(), node, w->nodeHelper(), w->overrideCodec() );
300  BodyPartHandlerList::const_iterator end( mHandlers.constEnd() );
301  for ( BodyPartHandlerList::const_iterator it = mHandlers.constBegin() ; it != end ; ++it )
302  if ( (*it)->handleContextMenuRequest( &part, path, p ) )
303  return true;
304  return false;
305 }
306 
307 QString URLHandlerManager::BodyPartURLHandlerManager::statusBarMessage( const KUrl & url, ViewerPrivate * w ) const {
308  QString path;
309  KMime::Content * node = partNodeFromXKMailUrl( url, w, &path );
310  if ( !node )
311  return QString();
312 
313  PartNodeBodyPart part( w->message().get(), node, w->nodeHelper(), w->overrideCodec() );
314  BodyPartHandlerList::const_iterator end( mHandlers.constEnd() );
315  for ( BodyPartHandlerList::const_iterator it = mHandlers.constBegin() ; it != end ; ++it ) {
316  const QString msg = (*it)->statusBarMessage( &part, path );
317  if ( !msg.isEmpty() )
318  return msg;
319  }
320  return QString();
321 }
322 
323 //
324 //
325 // URLHandlerManager
326 //
327 //
328 
329 URLHandlerManager::URLHandlerManager() {
330  registerHandler( new KMailProtocolURLHandler() );
331  registerHandler( new ExpandCollapseQuoteURLManager() );
332  registerHandler( new SMimeURLHandler() );
333  registerHandler( new MailToURLHandler() );
334  registerHandler( new ContactUidURLHandler() );
335  registerHandler( new HtmlAnchorHandler() );
336  registerHandler( new AttachmentURLHandler() );
337  registerHandler( mBodyPartURLHandlerManager = new BodyPartURLHandlerManager() );
338  registerHandler( new ShowAuditLogURLHandler() );
339  registerHandler( new InternalImageURLHandler );
340  registerHandler( new KRunURLHandler() );
341 }
342 
343 URLHandlerManager::~URLHandlerManager() {
344  for_each( mHandlers.begin(), mHandlers.end(),
345  DeleteAndSetToZero<URLHandler>() );
346 }
347 
348 void URLHandlerManager::registerHandler( const URLHandler * handler ) {
349  if ( !handler )
350  return;
351  unregisterHandler( handler ); // don't produce duplicates
352  mHandlers.push_back( handler );
353 }
354 
355 void URLHandlerManager::unregisterHandler( const URLHandler * handler ) {
356  // don't delete them, only remove them from the list!
357  mHandlers.erase( remove( mHandlers.begin(), mHandlers.end(), handler ), mHandlers.end() );
358 }
359 
360 void URLHandlerManager::registerHandler( const Interface::BodyPartURLHandler * handler ) {
361  if ( mBodyPartURLHandlerManager )
362  mBodyPartURLHandlerManager->registerHandler( handler );
363 }
364 
365 void URLHandlerManager::unregisterHandler( const Interface::BodyPartURLHandler * handler ) {
366  if ( mBodyPartURLHandlerManager )
367  mBodyPartURLHandlerManager->unregisterHandler( handler );
368 }
369 
370 bool URLHandlerManager::handleClick( const KUrl & url, ViewerPrivate * w ) const {
371  HandlerList::const_iterator end( mHandlers.constEnd() );
372  for ( HandlerList::const_iterator it = mHandlers.constBegin() ; it != end ; ++it )
373  if ( (*it)->handleClick( url, w ) )
374  return true;
375  return false;
376 }
377 
378 bool URLHandlerManager::handleShiftClick( const KUrl &url, ViewerPrivate *window ) const
379 {
380  HandlerList::const_iterator end( mHandlers.constEnd() );
381  for ( HandlerList::const_iterator it = mHandlers.constBegin() ; it != end ; ++it )
382  if ( (*it)->handleShiftClick( url, window ) )
383  return true;
384  return false;
385 }
386 
387 bool URLHandlerManager::willHandleDrag( const KUrl &url, ViewerPrivate *window ) const
388 {
389  HandlerList::const_iterator end( mHandlers.constEnd() );
390 
391  for ( HandlerList::const_iterator it = mHandlers.constBegin() ; it != end ; ++it )
392  if ( (*it)->willHandleDrag( url, window ) )
393  return true;
394  return false;
395 }
396 
397 bool URLHandlerManager::handleDrag( const KUrl &url, ViewerPrivate *window ) const
398 {
399  HandlerList::const_iterator end( mHandlers.constEnd() );
400  for ( HandlerList::const_iterator it = mHandlers.constBegin() ; it != end ; ++it )
401  if ( (*it)->handleDrag( url, window ) )
402  return true;
403  return false;
404 }
405 
406 bool URLHandlerManager::handleContextMenuRequest( const KUrl & url, const QPoint & p, ViewerPrivate * w ) const {
407 
408  HandlerList::const_iterator end( mHandlers.constEnd() );
409  for ( HandlerList::const_iterator it = mHandlers.constBegin() ; it != end ; ++it )
410  if ( (*it)->handleContextMenuRequest( url, p, w ) )
411  return true;
412  return false;
413 }
414 
415 QString URLHandlerManager::statusBarMessage( const KUrl & url, ViewerPrivate * w ) const {
416  HandlerList::const_iterator end( mHandlers.constEnd() );
417  for ( HandlerList::const_iterator it = mHandlers.constBegin() ; it != end ; ++it ) {
418  const QString msg = (*it)->statusBarMessage( url, w );
419  if ( !msg.isEmpty() )
420  return msg;
421  }
422  return QString();
423 }
424 
425 
426 //
427 //
428 // URLHandler
429 //
430 //
431 
432 #include <ui/messagebox.h>
433 
434 #include <klocale.h>
435 #include <kmessagebox.h>
436 
437 namespace {
438 bool KMailProtocolURLHandler::handleClick( const KUrl & url, ViewerPrivate * w ) const {
439  if ( url.protocol() == QLatin1String( "kmail" ) ) {
440  if ( !w )
441  return false;
442  const QString urlPath( url.path() );
443  if ( urlPath == QLatin1String( "showHTML" ) ) {
444  w->setDisplayFormatMessageOverwrite( MessageViewer::Viewer::Html );
445  w->update( Viewer::Force );
446  return true;
447  }
448  else if ( urlPath == QLatin1String( "goOnline" ) ) {
449  w->goOnline();
450  return true;
451  }
452  else if ( urlPath == QLatin1String( "goResourceOnline" ) ) {
453  w->goResourceOnline();
454  return true;
455  }
456  else if ( urlPath == QLatin1String( "loadExternal" ) ) {
457  w->setHtmlLoadExtOverride( !w->htmlLoadExtOverride() );
458  w->update( Viewer::Force );
459  return true;
460  }
461  else if ( urlPath == QLatin1String( "decryptMessage" ) ) {
462  w->setDecryptMessageOverwrite( true );
463  w->update( Viewer::Force );
464  return true;
465  }
466  else if ( urlPath == QLatin1String( "showSignatureDetails" ) ) {
467  w->setShowSignatureDetails( true );
468  w->update( Viewer::Force );
469  return true;
470  }
471  else if ( urlPath == QLatin1String( "hideSignatureDetails" ) ) {
472  w->setShowSignatureDetails( false );
473  w->update( Viewer::Force );
474  return true;
475  }
476  else if ( urlPath == QLatin1String( "showAttachmentQuicklist" ) ) {
477  w->setShowAttachmentQuicklist( true );
478  w->update( Viewer::Force );
479  return true;
480  }
481  else if ( urlPath == QLatin1String( "hideAttachmentQuicklist" ) ) {
482  w->setShowAttachmentQuicklist( false );
483  w->update( Viewer::Force );
484  return true;
485  }
486  else if ( urlPath == QLatin1String( "showFullToAddressList" ) ) {
487  w->setShowFullToAddressList( true );
488  w->update( Viewer::Force );
489  return true;
490  }
491  else if ( urlPath == QLatin1String( "hideFullToAddressList" ) ) {
492  w->setShowFullToAddressList( false );
493  w->update( Viewer::Force );
494  return true;
495  }
496  else if ( urlPath == QLatin1String( "showFullCcAddressList" ) ) {
497  w->setShowFullCcAddressList( true );
498  w->update( Viewer::Force );
499  return true;
500  }
501  else if ( urlPath == QLatin1String( "hideFullCcAddressList" ) ) {
502  w->setShowFullCcAddressList( false );
503  w->update( Viewer::Force );
504  return true;
505  }
506  else if ( urlPath == QLatin1String( "showRawToltecMail" ) ) {
507  w->setShowRawToltecMail( true );
508  w->update( Viewer::Force );
509  return true;
510  }
511  }
512  return false;
513 }
514 
515 QString KMailProtocolURLHandler::statusBarMessage( const KUrl & url, ViewerPrivate * ) const {
516  if ( url.protocol() == QLatin1String( "kmail" ) )
517  {
518  const QString urlPath( url.path() );
519  if ( urlPath == QLatin1String( "showHTML" ) )
520  return i18n("Turn on HTML rendering for this message.");
521  else if ( urlPath == QLatin1String( "loadExternal" ) )
522  return i18n("Load external references from the Internet for this message.");
523  else if ( urlPath == QLatin1String( "goOnline" ) )
524  return i18n("Work online.");
525  else if ( urlPath == QLatin1String( "goResourceOnline" ) )
526  return i18n("Make account online.");
527  else if ( urlPath == QLatin1String( "decryptMessage" ) )
528  return i18n("Decrypt message.");
529  else if ( urlPath == QLatin1String( "showSignatureDetails" ) )
530  return i18n("Show signature details.");
531  else if ( urlPath == QLatin1String( "hideSignatureDetails" ) )
532  return i18n("Hide signature details.");
533  else if ( urlPath == QLatin1String( "showAttachmentQuicklist" ) )
534  return i18n( "Show attachment list." );
535  else if ( urlPath == QLatin1String( "hideAttachmentQuicklist" ) )
536  return i18n( "Hide attachment list." );
537  else if ( urlPath == QLatin1String( "showFullToAddressList" ) )
538  return i18n( "Show full \"To\" list" );
539  else if ( urlPath == QLatin1String( "hideFullToAddressList" ) )
540  return i18n( "Hide full \"To\" list" );
541  else if ( urlPath == QLatin1String( "showFullCcAddressList" ) )
542  return i18n( "Show full \"Cc\" list" );
543  else if ( urlPath == QLatin1String( "hideFullCcAddressList" ) )
544  return i18n( "Hide full \"Cc\" list" );
545  else if ( urlPath == QLatin1String( "showRawToltecMail" ) )
546  return i18n( "Show Raw Message" );
547  else return QString();
548  }
549  return QString() ;
550 }
551 }
552 
553 namespace {
554 
555 bool ExpandCollapseQuoteURLManager::handleClick(
556  const KUrl & url, ViewerPrivate * w ) const
557 {
558  // kmail:levelquote/?num -> the level quote to collapse.
559  // kmail:levelquote/?-num -> expand all levels quote.
560  if ( url.protocol() == QLatin1String( "kmail" ) && url.path()==QLatin1String( "levelquote" ) )
561  {
562  const QString levelStr= url.query().mid( 1,url.query().length() );
563  bool isNumber = false;
564  const int levelQuote= levelStr.toInt(&isNumber);
565  if ( isNumber )
566  w->slotLevelQuote( levelQuote );
567  return true;
568  }
569  return false;
570 }
571 QString ExpandCollapseQuoteURLManager::statusBarMessage(
572  const KUrl & url, ViewerPrivate * ) const
573 {
574  if ( url.protocol() == QLatin1String( "kmail" ) && url.path() == QLatin1String( "levelquote" ) )
575  {
576  const QString query= url.query();
577  if ( query.length()>=2 ) {
578  if ( query[ 1 ] ==QLatin1Char( '-' ) ) {
579  return i18n("Expand all quoted text.");
580  }
581  else {
582  return i18n("Collapse quoted text.");
583  }
584  }
585  }
586  return QString() ;
587 }
588 
589 }
590 
591 bool foundSMIMEData( const QString &aUrl,
592  QString& displayName,
593  QString& libName,
594  QString& keyId )
595 {
596  static QString showCertMan(QLatin1String("showCertificate#"));
597  displayName.clear();
598  libName.clear();
599  keyId.clear();
600  int i1 = aUrl.indexOf( showCertMan );
601  if( -1 < i1 ) {
602  i1 += showCertMan.length();
603  int i2 = aUrl.indexOf(QLatin1String(" ### "), i1);
604  if( i1 < i2 )
605  {
606  displayName = aUrl.mid( i1, i2-i1 );
607  i1 = i2+5;
608  i2 = aUrl.indexOf(QLatin1String(" ### "), i1);
609  if( i1 < i2 )
610  {
611  libName = aUrl.mid( i1, i2-i1 );
612  i2 += 5;
613 
614  keyId = aUrl.mid( i2 );
615  /*
616  int len = aUrl.length();
617  if( len > i2+1 ) {
618  keyId = aUrl.mid( i2, 2 );
619  i2 += 2;
620  while( len > i2+1 ) {
621  keyId += ':';
622  keyId += aUrl.mid( i2, 2 );
623  i2 += 2;
624  }
625  }
626  */
627  }
628  }
629  }
630  return !keyId.isEmpty();
631 }
632 
633 
634 namespace {
635 bool SMimeURLHandler::handleClick( const KUrl & url, ViewerPrivate * w ) const {
636  if ( !url.hasRef() )
637  return false;
638  QString displayName, libName, keyId;
639  if ( !foundSMIMEData( url.path() + QLatin1Char('#') +
640  QUrl::fromPercentEncoding( url.ref().toLatin1() ),
641  displayName, libName, keyId ) )
642  return false;
643  QStringList lst;
644  lst << QLatin1String("-parent-windowid") << QString::number((qlonglong)w->viewer()->mainWindow()->winId() ) << QLatin1String("-query") << keyId;
645  if ( !QProcess::startDetached( QLatin1String("kleopatra"),lst) )
646  KMessageBox::error( w->mMainWindow, i18n("Could not start certificate manager. "
647  "Please check your installation."),
648  i18n("KMail Error") );
649  return true;
650 }
651 
652 QString SMimeURLHandler::statusBarMessage( const KUrl & url, ViewerPrivate * ) const {
653  QString displayName, libName, keyId;
654  if ( !foundSMIMEData( url.path() + QLatin1Char('#') +
655  QUrl::fromPercentEncoding( url.ref().toLatin1() ),
656  displayName, libName, keyId ) )
657  return QString();
658  return i18n("Show certificate 0x%1", keyId );
659 }
660 }
661 
662 namespace {
663 bool HtmlAnchorHandler::handleClick( const KUrl & url, ViewerPrivate * w ) const {
664  if ( url.hasHost() || !url.hasRef() )
665  return false;
666 
667  w->htmlPart()->scrollToAnchor( url.ref() );
668  return true;
669 }
670 }
671 
672 namespace {
673 QString MailToURLHandler::statusBarMessage( const KUrl & url, ViewerPrivate * ) const {
674  if ( url.protocol() == QLatin1String( "mailto" ) )
675  return KPIMUtils::decodeMailtoUrl( url );
676  return QString();
677 }
678 }
679 
680 namespace {
681 static QString searchFullEmailByUid( const QString &uid )
682 {
683  QString fullEmail;
684  Akonadi::ContactSearchJob *job = new Akonadi::ContactSearchJob();
685  job->setLimit( 1 );
686  job->setQuery( Akonadi::ContactSearchJob::ContactUid, uid, Akonadi::ContactSearchJob::ExactMatch );
687  job->exec();
688  const KABC::Addressee::List res = job->contacts();
689  if ( !res.isEmpty() ) {
690  KABC::Addressee addr = res.first();
691  fullEmail = addr.fullEmail();
692  }
693  return fullEmail;
694 }
695 
696 static void runKAddressBook( const KUrl &url )
697 {
698  KPIM::OpenEmailAddressJob *job = new KPIM::OpenEmailAddressJob( url.path(), 0 );
699  job->start();
700 }
701 
702 bool ContactUidURLHandler::handleClick( const KUrl &url, ViewerPrivate * ) const
703 {
704  if ( url.protocol() == QLatin1String( "uid" ) ) {
705  runKAddressBook( url );
706  return true;
707  } else {
708  return false;
709  }
710 }
711 
712 bool ContactUidURLHandler::handleContextMenuRequest( const KUrl &url, const QPoint &p,
713  ViewerPrivate * ) const
714 {
715  if ( url.protocol() != QLatin1String( "uid" ) || url.path().isEmpty() ) {
716  return false;
717  }
718 
719  KMenu *menu = new KMenu();
720  QAction *open =
721  menu->addAction( KIcon( QLatin1String("view-pim-contacts") ), i18n( "&Open in Address Book" ) );
722 #ifndef QT_NO_CLIPBOARD
723  QAction *copy =
724  menu->addAction( KIcon( QLatin1String("edit-copy") ), i18n( "&Copy Email Address" ) );
725 #endif
726 
727  QAction *a = menu->exec( p );
728  if ( a == open ) {
729  runKAddressBook( url );
730 #ifndef QT_NO_CLIPBOARD
731  } else if ( a == copy ) {
732  const QString fullEmail = searchFullEmailByUid( url.path() );
733  if ( !fullEmail.isEmpty() ) {
734  QClipboard *clip = QApplication::clipboard();
735  clip->setText( fullEmail, QClipboard::Clipboard );
736  clip->setText( fullEmail, QClipboard::Selection );
737  KPIM::BroadcastStatus::instance()->setStatusMsg( i18n( "Address copied to clipboard." ) );
738  }
739 #endif
740  }
741  delete menu;
742 
743  return true;
744 }
745 
746 QString ContactUidURLHandler::statusBarMessage( const KUrl &url, ViewerPrivate * ) const
747 {
748  if ( url.protocol() == QLatin1String( "uid" ) ) {
749  return i18n( "Lookup the contact in KAddressbook" );
750  } else {
751  return QString();
752  }
753 }
754 }
755 
756 namespace {
757 KMime::Content* AttachmentURLHandler::nodeForUrl( const KUrl &url, ViewerPrivate *w ) const
758 {
759  if ( !w || !w->mMessage )
760  return 0;
761  if ( url.protocol() == QLatin1String( "attachment" ) )
762  {
763  KMime::Content * node = w->nodeFromUrl( url );
764  return node;
765  }
766  return 0;
767 }
768 
769 bool AttachmentURLHandler::attachmentIsInHeader( const KUrl &url ) const
770 {
771  bool inHeader = false;
772  const QString place = url.queryItem( QLatin1String("place") ).toLower();
773  if ( !place.isNull() ) {
774  inHeader = ( place == QLatin1String( "header" ) );
775  }
776  return inHeader;
777 }
778 
779 bool AttachmentURLHandler::handleClick( const KUrl & url, ViewerPrivate * w ) const
780 {
781  KMime::Content *node = nodeForUrl( url, w );
782  if ( !node )
783  return false;
784  const bool inHeader = attachmentIsInHeader( url );
785  const bool shouldShowDialog = !w->nodeHelper()->isNodeDisplayedEmbedded( node ) || !inHeader;
786  if ( inHeader )
787  w->scrollToAttachment( node );
788  if ( shouldShowDialog )
789  // PENDING(romain_kdab) : replace with toLocalFile() ?
790  w->openAttachment( node, w->nodeHelper()->tempFileUrlFromNode( node ).path() );
791 
792  return true;
793 }
794 
795 bool AttachmentURLHandler::handleShiftClick( const KUrl &url, ViewerPrivate *window ) const
796 {
797  KMime::Content *node = nodeForUrl( url, window );
798  if ( !node )
799  return false;
800  if ( !window )
801  return false;
802  KUrl currentUrl;
803  if (Util::saveContents( window->viewer(), QList<KMime::Content*>() << node, currentUrl )) {
804  window->viewer()->showOpenAttachmentFolderWidget(currentUrl);
805  }
806 
807  return true;
808 }
809 
810 bool AttachmentURLHandler::willHandleDrag( const KUrl &url, ViewerPrivate *window ) const
811 {
812  return nodeForUrl( url, window ) != 0;
813 }
814 
815 bool AttachmentURLHandler::handleDrag( const KUrl &url, ViewerPrivate *window ) const
816 {
817 #ifndef QT_NO_DRAGANDDROP
818  KMime::Content *node = nodeForUrl( url, window );
819  if ( !node )
820  return false;
821  if ( node->header<KMime::Headers::Subject>() ) {
822  if (!node->contents().isEmpty()) {
823  node = node->contents().first();
824  window->nodeHelper()->writeNodeToTempFile(node);
825  }
826  }
827  const KUrl tUrl = window->nodeHelper()->tempFileUrlFromNode( node );
828  const QString fileName = tUrl.path();
829  if ( !fileName.isEmpty() ) {
830  QFile f(fileName);
831  f.setPermissions(QFile::ReadOwner|QFile::WriteOwner|QFile::ReadUser|QFile::ReadGroup|QFile::ReadOther);
832  const QString icon = window->nodeHelper()->iconName( node, KIconLoader::Small );
833  QDrag *drag = new QDrag( window->viewer() );
834  QMimeData *mimeData = new QMimeData();
835  mimeData->setUrls( QList<QUrl>() << tUrl );
836  drag->setMimeData( mimeData );
837  if ( !icon.isEmpty() ) {
838  drag->setPixmap( QPixmap( icon ) );
839  }
840  drag->start();
841  return true;
842  }
843  else
844 #endif
845  return false;
846 }
847 
848 bool AttachmentURLHandler::handleContextMenuRequest( const KUrl & url, const QPoint & p, ViewerPrivate * w ) const
849 {
850  KMime::Content *node = nodeForUrl( url, w );
851  if ( !node )
852  return false;
853  // PENDING(romain_kdab) : replace with toLocalFile() ?
854  w->showAttachmentPopup( node, w->nodeHelper()->tempFileUrlFromNode( node ).path(), p );
855  return true;
856 }
857 
858 QString AttachmentURLHandler::statusBarMessage( const KUrl & url, ViewerPrivate * w ) const
859 {
860  KMime::Content *node = nodeForUrl( url, w );
861  if ( !node )
862  return QString();
863  const QString name = MessageViewer::NodeHelper::fileName( node );
864  if ( !name.isEmpty() )
865  return i18n( "Attachment: %1", name );
866  else if ( dynamic_cast<KMime::Message*>( node ) ) {
867  if ( node->header<KMime::Headers::Subject>() ) {
868  return i18n( "Encapsulated Message (Subject: %1)",
869  node->header<KMime::Headers::Subject>()->asUnicodeString() );
870  } else {
871  return i18n( "Encapsulated Message" );
872  }
873  }
874  return i18n( "Unnamed attachment" );
875 }
876 }
877 
878 namespace {
879 static QString extractAuditLog( const KUrl & url ) {
880  if ( url.protocol() != QLatin1String( "kmail" )
881  || url.path() != QLatin1String( "showAuditLog" ) )
882  return QString();
883  assert( !url.queryItem( QLatin1String("log") ).isEmpty() );
884  return url.queryItem( QLatin1String("log") );
885 }
886 
887 bool ShowAuditLogURLHandler::handleClick( const KUrl & url, ViewerPrivate * w ) const {
888  const QString auditLog = extractAuditLog( url );
889  if ( auditLog.isEmpty() )
890  return false;
891  Kleo::MessageBox::auditLog( w->mMainWindow, auditLog );
892  return true;
893 }
894 
895 bool ShowAuditLogURLHandler::handleContextMenuRequest( const KUrl & url, const QPoint &, ViewerPrivate * w ) const {
896  Q_UNUSED( w );
897  // disable RMB for my own links:
898  return !extractAuditLog( url ).isEmpty();
899 }
900 
901 QString ShowAuditLogURLHandler::statusBarMessage( const KUrl & url, ViewerPrivate * ) const {
902  if ( extractAuditLog( url ).isEmpty() )
903  return QString();
904  else
905  return i18n("Show GnuPG Audit Log for this operation");
906 }
907 }
908 
909 namespace {
910 bool InternalImageURLHandler::handleDrag( const KUrl &url, ViewerPrivate *window ) const
911 {
912  Q_UNUSED( window );
913  Q_UNUSED( url );
914 
915  // This will only be called when willHandleDrag() was true. Return false here, that will
916  // notify ViewerPrivate::eventFilter() that no drag was started.
917  return false;
918 }
919 
920 bool InternalImageURLHandler::willHandleDrag( const KUrl &url, ViewerPrivate *window ) const
921 {
922  Q_UNUSED( window );
923  if ( url.protocol() == QLatin1String( "data" ) && url.path().startsWith( QLatin1String("image") ) )
924  return true;
925 
926  const QString imagePath = KStandardDirs::locate( "data", QLatin1String("libmessageviewer/pics/") );
927  return url.path().contains( imagePath );
928 }
929 }
930 
931 namespace {
932 bool KRunURLHandler::handleClick( const KUrl & url, ViewerPrivate * w ) const
933 {
934  const QString protocol(url.protocol() );
935  if ( ( protocol == QLatin1String( "http" ) ) || ( protocol == QLatin1String( "https" ) ) ||
936  ( protocol == QLatin1String( "ftp" ) ) || ( protocol == QLatin1String( "file" ) ) ||
937  ( protocol == QLatin1String( "ftps" ) ) || ( protocol == QLatin1String( "sftp" ) ) ||
938  ( protocol == QLatin1String( "help" ) ) || ( protocol == QLatin1String( "vnc" ) ) ||
939  ( protocol == QLatin1String( "smb" ) ) || ( protocol == QLatin1String( "fish" ) ) ||
940  ( protocol == QLatin1String( "news" ) ) )
941  {
942  KPIM::BroadcastStatus::instance()->setTransientStatusMsg( i18n("Opening URL..."));
943  QTimer::singleShot( 2000, KPIM::BroadcastStatus::instance(), SLOT(reset()) );
944 
945  KMimeType::Ptr mime = KMimeType::findByUrl( url );
946  if (mime->name() == QLatin1String("application/x-desktop") ||
947  mime->name() == QLatin1String("application/x-executable") ||
948  mime->name() == QLatin1String("application/x-ms-dos-executable") ||
949  mime->name() == QLatin1String("application/x-shellscript") )
950  {
951  if ( KMessageBox::warningYesNo( 0, i18nc( "@info", "Do you really want to execute <filename>%1</filename>?",
952  url.pathOrUrl() ), QString(), KGuiItem(i18n("Execute")), KStandardGuiItem::cancel() ) != KMessageBox::Yes)
953  return true;
954  }
955  if ( !MessageViewer::Util::handleUrlWithQDesktopServices( url.pathOrUrl() ) ) {
956  KRun *runner = new KRun( url, w->viewer() ); // will delete itself
957  runner->setRunExecutables( false );
958  }
959 
960  return true;
961  }
962  else return false;
963 }
964 }
MessageViewer::ViewerPrivate::setShowSignatureDetails
void setShowSignatureDetails(bool showDetails=true)
Show signature details.
foundSMIMEData
bool foundSMIMEData(const QString &aUrl, QString &displayName, QString &libName, QString &keyId)
Definition: urlhandlermanager.cpp:591
QString::indexOf
int indexOf(QChar ch, int from, Qt::CaseSensitivity cs) const
MessageViewer::URLHandlerManager::statusBarMessage
QString statusBarMessage(const KUrl &url, ViewerPrivate *w=0) const
Definition: urlhandlermanager.cpp:415
MessageViewer::ViewerPrivate::mMessage
KMime::Message::Ptr mMessage
Definition: viewer_p.h:635
MessageViewer::PartNodeBodyPart
an implementation of the BodyPart interface using KMime::Content's
Definition: partnodebodypart.h:55
stl_util.h
QDrag::setMimeData
void setMimeData(QMimeData *data)
QDrag::start
Qt::DropAction start(QFlags< Qt::DropAction > request)
MessageViewer::URLHandlerManager::registerHandler
void registerHandler(const URLHandler *handler)
Definition: urlhandlermanager.cpp:348
MessageViewer::ViewerPrivate::goResourceOnline
void goResourceOnline()
QString::split
QStringList split(const QString &sep, SplitBehavior behavior, Qt::CaseSensitivity cs) const
MessageViewer::URLHandlerManager::handleShiftClick
bool handleShiftClick(const KUrl &url, ViewerPrivate *window=0) const
Definition: urlhandlermanager.cpp:378
QDrag::setPixmap
void setPixmap(const QPixmap &pixmap)
QProcess::startDetached
bool startDetached(const QString &program, const QStringList &arguments, const QString &workingDirectory, qint64 *pid)
MessageViewer::ViewerPrivate::scrollToAttachment
void scrollToAttachment(KMime::Content *node)
MessageViewer::ViewerPrivate::setDecryptMessageOverwrite
void setDecryptMessageOverwrite(bool overwrite=true)
Enforce message decryption.
MessageViewer::Viewer::mainWindow
QWidget * mainWindow()
Definition: viewer.cpp:296
MessageViewer::ViewerPrivate::setHtmlLoadExtOverride
void setHtmlLoadExtOverride(bool override)
Override default load external references setting.
MessageViewer::ViewerPrivate::htmlLoadExtOverride
bool htmlLoadExtOverride() const
Get the load external references override setting.
MessageViewer::URLHandlerManager::~URLHandlerManager
~URLHandlerManager()
Definition: urlhandlermanager.cpp:343
QPoint
nodehelper.h
partnodebodypart.h
MessageViewer::ViewerPrivate::nodeFromUrl
KMime::Content * nodeFromUrl(const KUrl &url)
Returns message part from given URL or null if invalid.
QMimeData
QFile
MessageViewer::Util::saveContents
bool MESSAGEVIEWER_EXPORT saveContents(QWidget *parent, const QList< KMime::Content * > &contents, KUrl &currentFolder)
Definition: util.cpp:190
QList::size
int size() const
bodyparturlhandler.h
QString::isNull
bool isNull() const
QClipboard
QString::clear
void clear()
MessageViewer::ViewerPrivate
Private class for the Viewer, the main widget in the messageviewer library.
Definition: viewer_p.h:180
viewer_p.h
QString::number
QString number(int n, int base)
MessageViewer::DeleteAndSetToZero
Definition: stl_util.h:38
QApplication::clipboard
QClipboard * clipboard()
MessageViewer::MailWebView::scrollToAnchor
void scrollToAnchor(const QString &anchor)
Definition: mailwebview_textbrowser.cpp:168
MessageViewer::ViewerPrivate::mMainWindow
QWidget * mMainWindow
Definition: viewer_p.h:665
QString::toInt
int toInt(bool *ok, int base) const
QDrag
QString::isEmpty
bool isEmpty() const
MessageViewer::ViewerPrivate::goOnline
void goOnline()
MessageViewer::Interface::BodyPartURLHandler
An interface to body part reader link handlers.
Definition: bodyparturlhandler.h:71
QString::startsWith
bool startsWith(const QString &s, Qt::CaseSensitivity cs) const
MessageViewer::ViewerPrivate::setShowRawToltecMail
void setShowRawToltecMail(bool showRawToltecMail)
Definition: viewer_p.h:423
MessageViewer::URLHandlerManager
Singleton to manage the list of URLHandlers.
Definition: urlhandlermanager.h:59
MessageViewer::ViewerPrivate::htmlPart
MailWebView * htmlPart() const
Access to the MailWebView used for the viewer.
Definition: viewer_p.h:213
QWidget::winId
WId winId() const
MessageViewer::URLHandlerManager::handleContextMenuRequest
bool handleContextMenuRequest(const KUrl &url, const QPoint &p, ViewerPrivate *w=0) const
Definition: urlhandlermanager.cpp:406
QString
QList< KMime::Content * >
MessageViewer::ViewerPrivate::viewer
Viewer * viewer() const
Definition: viewer_p.h:240
QUrl::fromPercentEncoding
QString fromPercentEncoding(const QByteArray &input)
MessageViewer::ViewerPrivate::nodeHelper
NodeHelper * nodeHelper() const
Definition: viewer_p.h:238
util.h
MessageViewer::ViewerPrivate::overrideCodec
const QTextCodec * overrideCodec() const
Get codec corresponding to the currently selected override character encoding.
MessageViewer::NodeHelper::tempFileUrlFromNode
KUrl tempFileUrlFromNode(const KMime::Content *node)
Returns the temporary file path and name where this node was saved, or an empty url if it wasn't save...
Definition: nodehelper.cpp:259
MessageViewer::ViewerPrivate::setDisplayFormatMessageOverwrite
void setDisplayFormatMessageOverwrite(Viewer::DisplayFormatMessage format)
Override default html mail setting.
QStringList
QPixmap
QString::toLower
QString toLower() const
MessageViewer::ViewerPrivate::slotLevelQuote
void slotLevelQuote(int l)
MessageViewer::Viewer::showOpenAttachmentFolderWidget
void showOpenAttachmentFolderWidget(const KUrl &url)
Definition: viewer.cpp:709
QLatin1Char
MessageViewer::URLHandler
An interface to reader link handlers.
Definition: urlhandler.h:51
MessageViewer::NodeHelper::writeNodeToTempFile
QString writeNodeToTempFile(KMime::Content *node)
Writes the given message part to a temporary file and returns the name of this file or QString() if w...
Definition: nodehelper.cpp:218
partNodeFromXKMailUrl
static KMime::Content * partNodeFromXKMailUrl(const KUrl &url, ViewerPrivate *w, QString *path)
Definition: urlhandlermanager.cpp:255
MessageViewer::ViewerPrivate::setShowAttachmentQuicklist
void setShowAttachmentQuicklist(bool showAttachmentQuicklist=true)
QString::mid
QString mid(int position, int n) const
QVector< const Interface::BodyPartURLHandler * >
MessageViewer::ViewerPrivate::showAttachmentPopup
void showAttachmentPopup(KMime::Content *node, const QString &name, const QPoint &p)
QLatin1String
MessageViewer::ViewerPrivate::setShowFullToAddressList
void setShowFullToAddressList(bool showFullToAddressList=true)
Show or hide the full list of "To" addresses.
MessageViewer::ViewerPrivate::update
void update(MessageViewer::Viewer::UpdateMode updateMode=Viewer::Delayed)
Re-parse the current message.
MessageViewer::URLHandlerManager::handleDrag
bool handleDrag(const KUrl &url, ViewerPrivate *window=0) const
Definition: urlhandlermanager.cpp:397
QAction
mailwebview.h
QString::length
int length() const
MessageViewer::NodeHelper::iconName
static QString iconName(KMime::Content *node, int size=KIconLoader::Desktop)
Definition: nodehelper.cpp:471
MessageViewer::ViewerPrivate::setShowFullCcAddressList
void setShowFullCcAddressList(bool showFullCcAddressList=true)
Show or hide the full list of "To" addresses.
MessageViewer::ViewerPrivate::openAttachment
void openAttachment(KMime::Content *node, const QString &fileName)
Open the attachment pointed to the node.
MessageViewer::ViewerPrivate::message
KMime::Message::Ptr message() const
Definition: viewer_p.h:244
urlhandlermanager.h
QClipboard::setText
void setText(const QString &text, Mode mode)
MessageViewer::Viewer::Force
Definition: viewer.h:133
MessageViewer::Viewer::Html
Definition: viewer.h:111
MessageViewer::NodeHelper::isNodeDisplayedEmbedded
bool isNodeDisplayedEmbedded(KMime::Content *node) const
Definition: nodehelper.cpp:633
urlhandler.h
MessageViewer::URLHandlerManager::handleClick
bool handleClick(const KUrl &url, ViewerPrivate *w=0) const
Definition: urlhandlermanager.cpp:370
MessageViewer::Util::handleUrlWithQDesktopServices
bool MESSAGEVIEWER_EXPORT handleUrlWithQDesktopServices(const KUrl &url)
Delegates opening a URL to the QDesktopServices mechanisms for that on Windows and MacOSX...
Definition: util.cpp:142
MessageViewer::NodeHelper::fileName
static QString fileName(const KMime::Content *node)
Returns a usable filename for a node, that can be the filename from the content disposition header...
Definition: nodehelper.cpp:588
MessageViewer::URLHandlerManager::unregisterHandler
void unregisterHandler(const URLHandler *handler)
Definition: urlhandlermanager.cpp:355
MessageViewer::URLHandlerManager::willHandleDrag
bool willHandleDrag(const KUrl &url, ViewerPrivate *window=0) const
Definition: urlhandlermanager.cpp:387
QTimer::singleShot
singleShot
This file is part of the KDE documentation.
Documentation copyright © 1996-2020 The KDE developers.
Generated on Mon Jun 22 2020 13:32:45 by doxygen 1.8.7 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.

messageviewer

Skip menu "messageviewer"
  • Main Page
  • Namespace List
  • Namespace Members
  • Alphabetical List
  • Class List
  • Class Hierarchy
  • Class Members
  • File List
  • File Members
  • Related Pages

kdepim API Reference

Skip menu "kdepim API Reference"
  • akonadi_next
  • akregator
  • blogilo
  • calendarsupport
  • console
  •   kabcclient
  •   konsolekalendar
  • kaddressbook
  • kalarm
  •   lib
  • kdgantt2
  • kjots
  • kleopatra
  • kmail
  • knode
  • knotes
  • kontact
  • korgac
  • korganizer
  • ktimetracker
  • libkdepim
  • libkleo
  • libkpgp
  • mailcommon
  • messagelist
  • messageviewer
  • pimprint

Search



Report problems with this website to our bug tracking system.
Contact the specific authors with questions and comments about the page contents.

KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal