• 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
nodehelper.cpp
Go to the documentation of this file.
1 /* -*- mode: C++; c-file-style: "gnu" -*-
2  Copyright (C) 2009 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.net
3  Copyright (c) 2009 Andras Mantia <andras@kdab.net>
4 
5  This program is free software; you can redistribute it and/or modify
6  it under the terms of the GNU General Public License as published by
7  the Free Software Foundation; either version 2 of the License, or
8  (at your option) any later version.
9 
10  This program is distributed in the hope that it will be useful,
11  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  GNU General Public License for more details.
14 
15  You should have received a copy of the GNU General Public License along
16  with this program; if not, write to the Free Software Foundation, Inc.,
17  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18 */
19 
20 
21 #include "nodehelper.h"
22 #include "utils/iconnamecache.h"
23 #include "settings/globalsettings.h"
24 #include "partmetadata.h"
25 #include "interfaces/bodypart.h"
26 #include "utils/util.h"
27 #include "pimcommon/temporaryfile/attachmenttemporaryfilesdirs.h"
28 
29 #include <messagecore/helpers/nodehelper.h>
30 #include <messagecore/utils/stringutil.h>
31 #include "messagecore/settings/globalsettings.h"
32 
33 #include <kmime/kmime_content.h>
34 #include <kmime/kmime_message.h>
35 #include <kmime/kmime_headers.h>
36 #include <kmimetype.h>
37 #include <kdebug.h>
38 #include <kascii.h>
39 #include <ktemporaryfile.h>
40 #include <klocale.h>
41 #include <kcharsets.h>
42 #include <kde_file.h>
43 #include <kpimutils/kfileio.h>
44 
45 #include <QDir>
46 #include <QTextCodec>
47 
48 #include <string>
49 #include <sstream>
50 #include <algorithm>
51 
52 
53 namespace MessageViewer {
54 
55 QStringList replySubjPrefixes(QStringList() << QLatin1String("Re\\s*:") << QLatin1String("Re\\[\\d+\\]:") << QLatin1String("Re\\d+:"));
56 QStringList forwardSubjPrefixes( QStringList() << QLatin1String("Fwd:") << QLatin1String("FW:"));
57 
58 NodeHelper::NodeHelper() :
59  mAttachmentFilesDir(new PimCommon::AttachmentTemporaryFilesDirs())
60 {
61  //TODO(Andras) add methods to modify these prefixes
62 
63  mLocalCodec = QTextCodec::codecForName( KGlobal::locale()->encoding() );
64 
65  // In the case of Japan. Japanese locale name is "eucjp" but
66  // The Japanese mail systems normally used "iso-2022-jp" of locale name.
67  // We want to change locale name from eucjp to iso-2022-jp at KMail only.
68 
69  // (Introduction to i18n, 6.6 Limit of Locale technology):
70  // EUC-JP is the de-facto standard for UNIX systems, ISO 2022-JP
71  // is the standard for Internet, and Shift-JIS is the encoding
72  // for Windows and Macintosh.
73  if ( mLocalCodec ) {
74  if ( mLocalCodec->name().toLower() == "eucjp"
75 #if defined Q_WS_WIN || defined Q_WS_MACX
76  || mLocalCodec->name().toLower() == "shift-jis" // OK?
77 #endif
78  )
79  {
80  mLocalCodec = QTextCodec::codecForName("jis7");
81  // QTextCodec *cdc = QTextCodec::codecForName("jis7");
82  // QTextCodec::setCodecForLocale(cdc);
83  // KGlobal::locale()->setEncoding(cdc->mibEnum());
84  }
85  }
86 }
87 
88 NodeHelper::~NodeHelper()
89 {
90  //Don't delete it it will delete in class with a deleteLater;
91  if (mAttachmentFilesDir) {
92  mAttachmentFilesDir->removeTempFiles();
93  mAttachmentFilesDir = 0;
94  }
95 }
96 
97 void NodeHelper::setNodeProcessed(KMime::Content* node, bool recurse )
98 {
99  if ( !node )
100  return;
101  mProcessedNodes.append( node );
102  //kDebug() << "Node processed: " << node->index().toString() << node->contentType()->as7BitString();
103  //<< " decodedContent" << node->decodedContent();
104  if ( recurse ) {
105  KMime::Content::List contents = node->contents();
106  Q_FOREACH( KMime::Content *c, contents )
107  {
108  setNodeProcessed( c, true );
109  }
110  }
111 }
112 
113 void NodeHelper::setNodeUnprocessed(KMime::Content* node, bool recurse )
114 {
115  if ( !node )
116  return;
117  mProcessedNodes.removeAll( node );
118 
119  //avoid double addition of extra nodes, eg. encrypted attachments
120  const QMap<KMime::Content*, QList<KMime::Content*> >::iterator it = mExtraContents.find( node );
121  if ( it != mExtraContents.end() ) {
122  Q_FOREACH( KMime::Content* c, it.value() ) {
123  KMime::Content * p = c->parent();
124  if ( p )
125  p->removeContent( c );
126  }
127  qDeleteAll( it.value() );
128  //kDebug() << "mExtraContents deleted for" << it.key();
129  mExtraContents.erase( it );
130  }
131 
132  //kDebug() << "Node UNprocessed: " << node;
133  if ( recurse ) {
134  KMime::Content::List contents = node->contents();
135  Q_FOREACH( KMime::Content *c, contents )
136  {
137  setNodeUnprocessed( c, true );
138  }
139  }
140 }
141 
142 bool NodeHelper::nodeProcessed( KMime::Content* node ) const
143 {
144  if ( !node )
145  return true;
146  return mProcessedNodes.contains( node );
147 }
148 
149 static void clearBodyPartMemento(QMap<QByteArray, Interface::BodyPartMemento*> & bodyPartMementoMap)
150 {
151  for ( QMap<QByteArray, Interface::BodyPartMemento*>::iterator
152  it = bodyPartMementoMap.begin(), end = bodyPartMementoMap.end();
153  it != end; ++it ) {
154  Interface::BodyPartMemento *memento = it.value();
155  memento->detach();
156  delete memento;
157  }
158  bodyPartMementoMap.clear();
159 }
160 
161 
162 void NodeHelper::clear()
163 {
164  mProcessedNodes.clear();
165  mEncryptionState.clear();
166  mSignatureState.clear();
167  mOverrideCodecs.clear();
168  std::for_each( mBodyPartMementoMap.begin(), mBodyPartMementoMap.end(),
169  &clearBodyPartMemento );
170  mBodyPartMementoMap.clear();
171  QMap<KMime::Content*, QList<KMime::Content*> >::ConstIterator end( mExtraContents.constEnd() );
172 
173  for ( QMap<KMime::Content*, QList<KMime::Content*> >::ConstIterator it = mExtraContents.constBegin(); it != end; ++it) {
174  Q_FOREACH( KMime::Content* c, it.value() ) {
175  KMime::Content * p = c->parent();
176  if ( p )
177  p->removeContent( c );
178  }
179  qDeleteAll( it.value() );
180  kDebug() << "mExtraContents deleted for" << it.key();
181  }
182  mExtraContents.clear();
183  mDisplayEmbeddedNodes.clear();
184  mDisplayHiddenNodes.clear();
185 }
186 
187 
188 void NodeHelper::setEncryptionState( KMime::Content* node, const KMMsgEncryptionState state )
189 {
190  mEncryptionState[node] = state;
191 }
192 
193 KMMsgEncryptionState NodeHelper::encryptionState( KMime::Content *node ) const
194 {
195  return mEncryptionState.value( node, KMMsgNotEncrypted );
196 }
197 
198 void NodeHelper::setSignatureState( KMime::Content* node, const KMMsgSignatureState state )
199 {
200  mSignatureState[node] = state;
201 }
202 
203 KMMsgSignatureState NodeHelper::signatureState( KMime::Content *node ) const
204 {
205  return mSignatureState.value( node, KMMsgNotSigned );
206 }
207 
208 PartMetaData NodeHelper::partMetaData(KMime::Content* node)
209 {
210  return mPartMetaDatas.value( node, PartMetaData() );
211 }
212 
213 void NodeHelper::setPartMetaData(KMime::Content* node, const PartMetaData& metaData)
214 {
215  mPartMetaDatas.insert( node, metaData );
216 }
217 
218 QString NodeHelper::writeNodeToTempFile(KMime::Content* node)
219 {
220  // If the message part is already written to a file, no point in doing it again.
221  // This function is called twice actually, once from the rendering of the attachment
222  // in the body and once for the header.
223  KUrl existingFileName = tempFileUrlFromNode( node );
224  if ( !existingFileName.isEmpty() ) {
225  return existingFileName.toLocalFile();
226  }
227 
228  QString fname = createTempDir( persistentIndex( node ) );
229  if ( fname.isEmpty() )
230  return QString();
231 
232  QString fileName = NodeHelper::fileName( node );
233  // strip off a leading path
234  int slashPos = fileName.lastIndexOf( QLatin1Char('/') );
235  if( -1 != slashPos )
236  fileName = fileName.mid( slashPos + 1 );
237  if( fileName.isEmpty() )
238  fileName = QLatin1String("unnamed");
239  fname += QLatin1Char('/') + fileName;
240 
241  //kDebug() << "Create temp file: " << fname;
242  QByteArray data = node->decodedContent();
243  if ( node->contentType()->isText() && data.size() > 0 ) {
244  // convert CRLF to LF before writing text attachments to disk
245  data = KMime::CRLFtoLF( data );
246  }
247  if( !KPIMUtils::kByteArrayToFile( data, fname, false, false, false ) )
248  return QString();
249  mAttachmentFilesDir->addTempFile( fname );
250  // make file read-only so that nobody gets the impression that he might
251  // edit attached files (cf. bug #52813)
252  ::chmod( QFile::encodeName( fname ), S_IRUSR );
253 
254  return fname;
255 }
256 
257 
258 
259 KUrl NodeHelper::tempFileUrlFromNode( const KMime::Content *node )
260 {
261  if (!node)
262  return KUrl();
263 
264  const QString index = persistentIndex( node );
265 
266  foreach ( const QString &path, mAttachmentFilesDir->temporaryFiles() ) {
267  const int right = path.lastIndexOf( QLatin1Char('/') );
268  int left = path.lastIndexOf( QLatin1String(".index."), right );
269  if ( left != -1 )
270  left += 7;
271 
272  QStringRef storedIndex( &path, left, right - left );
273  if ( left != -1 && storedIndex == index )
274  return KUrl( path );
275  }
276  return KUrl();
277 }
278 
279 
280 QString NodeHelper::createTempDir( const QString &param )
281 {
282  KTemporaryFile *tempFile = new KTemporaryFile();
283  tempFile->setSuffix( QLatin1String(".index.") + param );
284  tempFile->open();
285  QString fname = tempFile->fileName();
286  delete tempFile;
287 
288  if ( ::access( QFile::encodeName( fname ), W_OK ) != 0 ) {
289  // Not there or not writable
290  if( KDE_mkdir( QFile::encodeName( fname ), 0 ) != 0 ||
291  ::chmod( QFile::encodeName( fname ), S_IRWXU ) != 0 ) {
292  return QString(); //failed create
293  }
294  }
295 
296  Q_ASSERT( !fname.isNull() );
297 
298  mAttachmentFilesDir->addTempDir( fname );
299  return fname;
300 }
301 
302 void NodeHelper::forceCleanTempFiles()
303 {
304  mAttachmentFilesDir->forceCleanTempFiles();
305  delete mAttachmentFilesDir;
306  mAttachmentFilesDir = 0;
307 }
308 
309 void NodeHelper::removeTempFiles()
310 {
311  //Don't delete it it will delete in class
312  mAttachmentFilesDir->removeTempFiles();
313  mAttachmentFilesDir = new PimCommon::AttachmentTemporaryFilesDirs();
314 }
315 
316 void NodeHelper::addTempFile( const QString& file )
317 {
318  mAttachmentFilesDir->addTempFile( file );
319 }
320 
321 bool NodeHelper::isToltecMessage( KMime::Content* node )
322 {
323  if ( !node->contentType( false ) )
324  return false;
325 
326  if ( node->contentType()->mediaType().toLower() != "multipart" ||
327  node->contentType()->subType().toLower() != "mixed" )
328  return false;
329 
330  if ( node->contents().size() != 3 )
331  return false;
332 
333  const KMime::Headers::Base *libraryHeader = node->headerByType( "X-Library" );
334  if ( !libraryHeader )
335  return false;
336 
337  if ( QString::fromLatin1( libraryHeader->as7BitString( false ) ).toLower() !=
338  QLatin1String( "toltec" ) )
339  return false;
340 
341  const KMime::Headers::Base *kolabTypeHeader = node->headerByType( "X-Kolab-Type" );
342  if ( !kolabTypeHeader )
343  return false;
344 
345  if ( !QString::fromLatin1( kolabTypeHeader->as7BitString( false ) ).toLower().startsWith(
346  QLatin1String( "application/x-vnd.kolab" ) ) )
347  return false;
348 
349  return true;
350 }
351 
352 bool NodeHelper::isInEncapsulatedMessage( KMime::Content* node )
353 {
354  const KMime::Content * const topLevel = node->topLevel();
355  const KMime::Content * cur = node;
356  while ( cur && cur != topLevel ) {
357  const bool parentIsMessage = cur->parent() && cur->parent()->contentType( false ) &&
358  cur->parent()->contentType()->mimeType().toLower() == "message/rfc822";
359  if ( parentIsMessage && cur->parent() != topLevel ) {
360  return true;
361  }
362  cur = cur->parent();
363  }
364  return false;
365 }
366 
367 
368 QByteArray NodeHelper::charset( KMime::Content *node )
369 {
370  if ( node->contentType( false ) )
371  return node->contentType( false )->charset();
372  else
373  return node->defaultCharset();
374 }
375 
376 KMMsgEncryptionState NodeHelper::overallEncryptionState( KMime::Content *node ) const
377 {
378  KMMsgEncryptionState myState = KMMsgEncryptionStateUnknown;
379  if ( !node )
380  return myState;
381 
382  if( encryptionState( node ) == KMMsgNotEncrypted ) {
383  // NOTE: children are tested ONLY when parent is not encrypted
384  KMime::Content *child = MessageCore::NodeHelper::firstChild( node );
385  if ( child )
386  myState = overallEncryptionState( child );
387  else
388  myState = KMMsgNotEncrypted;
389  }
390  else { // part is partially or fully encrypted
391  myState = encryptionState( node );
392  }
393  // siblings are tested always
394  KMime::Content * next = MessageCore::NodeHelper::nextSibling( node );
395  if( next ) {
396  KMMsgEncryptionState otherState = overallEncryptionState( next );
397  switch( otherState ) {
398  case KMMsgEncryptionStateUnknown:
399  break;
400  case KMMsgNotEncrypted:
401  if( myState == KMMsgFullyEncrypted )
402  myState = KMMsgPartiallyEncrypted;
403  else if( myState != KMMsgPartiallyEncrypted )
404  myState = KMMsgNotEncrypted;
405  break;
406  case KMMsgPartiallyEncrypted:
407  myState = KMMsgPartiallyEncrypted;
408  break;
409  case KMMsgFullyEncrypted:
410  if( myState != KMMsgFullyEncrypted )
411  myState = KMMsgPartiallyEncrypted;
412  break;
413  case KMMsgEncryptionProblematic:
414  break;
415  }
416  }
417 
418 //kDebug() <<"\n\n KMMsgEncryptionState:" << myState;
419 
420  return myState;
421 }
422 
423 
424 KMMsgSignatureState NodeHelper::overallSignatureState( KMime::Content* node ) const
425 {
426  KMMsgSignatureState myState = KMMsgSignatureStateUnknown;
427  if ( !node )
428  return myState;
429 
430  if( signatureState( node ) == KMMsgNotSigned ) {
431  // children are tested ONLY when parent is not signed
432  KMime::Content* child = MessageCore::NodeHelper::firstChild( node );
433  if( child )
434  myState = overallSignatureState( child );
435  else
436  myState = KMMsgNotSigned;
437  }
438  else { // part is partially or fully signed
439  myState = signatureState( node );
440  }
441  // siblings are tested always
442  KMime::Content *next = MessageCore::NodeHelper::nextSibling( node );
443  if( next ) {
444  KMMsgSignatureState otherState = overallSignatureState( next );
445  switch( otherState ) {
446  case KMMsgSignatureStateUnknown:
447  break;
448  case KMMsgNotSigned:
449  if( myState == KMMsgFullySigned )
450  myState = KMMsgPartiallySigned;
451  else if( myState != KMMsgPartiallySigned )
452  myState = KMMsgNotSigned;
453  break;
454  case KMMsgPartiallySigned:
455  myState = KMMsgPartiallySigned;
456  break;
457  case KMMsgFullySigned:
458  if( myState != KMMsgFullySigned )
459  myState = KMMsgPartiallySigned;
460  break;
461  case KMMsgSignatureProblematic:
462  break;
463  }
464  }
465 
466 //kDebug() <<"\n\n KMMsgSignatureState:" << myState;
467 
468  return myState;
469 }
470 
471 QString NodeHelper::iconName( KMime::Content *node, int size )
472 {
473  if ( !node )
474  return QString();
475 
476  QByteArray mimeType = node->contentType()->mimeType();
477  if(mimeType.isNull() || mimeType == "application/octet-stream" ) {
478  const QString mime = Util::mimetype(node->contentDisposition()->filename())->name();
479  mimeType = mime.toLatin1();
480  }
481  kAsciiToLower( mimeType.data() );
482  return Util::fileNameForMimetype( QLatin1String(mimeType), size, node->contentDisposition()->filename(),
483  node->contentType()->name() );
484 }
485 
486 void NodeHelper::magicSetType( KMime::Content* node, bool aAutoDecode )
487 {
488  const QByteArray body = ( aAutoDecode ) ? node->decodedContent() : node->body() ;
489  KMimeType::Ptr mime = KMimeType::findByContent( body );
490 
491  QString mimetype = mime->name();
492  node->contentType()->setMimeType( mimetype.toLatin1() );
493 }
494 
495 // static
496 QString NodeHelper::replacePrefixes( const QString& str,
497  const QStringList& prefixRegExps,
498  bool replace,
499  const QString& newPrefix )
500 {
501  bool recognized = false;
502  // construct a big regexp that
503  // 1. is anchored to the beginning of str (sans whitespace)
504  // 2. matches at least one of the part regexps in prefixRegExps
505  QString bigRegExp = QString::fromLatin1("^(?:\\s+|(?:%1))+\\s*")
506  .arg( prefixRegExps.join(QLatin1String(")|(?:")) );
507  QRegExp rx( bigRegExp, Qt::CaseInsensitive );
508  if ( !rx.isValid() ) {
509  kWarning() << "bigRegExp = \""
510  << bigRegExp << "\"\n"
511  << "prefix regexp is invalid!";
512  // try good ole Re/Fwd:
513  recognized = str.startsWith( newPrefix );
514  } else { // valid rx
515  QString tmp = str;
516  if ( rx.indexIn( tmp ) == 0 ) {
517  recognized = true;
518  if ( replace )
519  return tmp.replace( 0, rx.matchedLength(), newPrefix + QLatin1Char(' ') );
520  }
521  }
522  if ( !recognized )
523  return newPrefix + QLatin1Char(' ') + str;
524  else
525  return str;
526 }
527 
528 QString NodeHelper::cleanSubject( KMime::Message *message )
529 {
530  return cleanSubject( message, replySubjPrefixes + forwardSubjPrefixes,
531  true, QString() ).trimmed();
532 }
533 
534 QString NodeHelper::cleanSubject( KMime::Message *message,
535  const QStringList &prefixRegExps,
536  bool replace,
537  const QString &newPrefix )
538 {
539  QString cleanStr;
540  if ( message ) {
541  cleanStr =
542  NodeHelper::replacePrefixes(
543  message->subject()->asUnicodeString(), prefixRegExps, replace, newPrefix );
544  }
545  return cleanStr;
546 }
547 
548 void NodeHelper::setOverrideCodec( KMime::Content * node, const QTextCodec* codec )
549 {
550  if ( !node )
551  return;
552 
553  mOverrideCodecs[node] = codec;
554 }
555 
556 const QTextCodec * NodeHelper::codec( KMime::Content* node )
557 {
558  if (! node )
559  return mLocalCodec;
560 
561  const QTextCodec *c = mOverrideCodecs.value( node, 0 );
562  if ( !c ) {
563  // no override-codec set for this message, try the CT charset parameter:
564  c = codecForName( node->contentType()->charset() );
565  }
566  if ( !c ) {
567  // Ok, no override and nothing in the message, let's use the fallback
568  // the user configured
569  c = codecForName( MessageCore::GlobalSettings::self()->fallbackCharacterEncoding().toLatin1() );
570  }
571  if ( !c ) {
572  // no charset means us-ascii (RFC 2045), so using local encoding should
573  // be okay
574  c = mLocalCodec;
575  }
576  return c;
577 }
578 
579 const QTextCodec* NodeHelper::codecForName(const QByteArray& _str)
580 {
581  if (_str.isEmpty())
582  return 0;
583  QByteArray codec = _str;
584  kAsciiToLower(codec.data());
585  return KGlobal::charsets()->codecForName(QLatin1String(codec));
586 }
587 
588 QString NodeHelper::fileName( const KMime::Content *node )
589 {
590  QString name = const_cast<KMime::Content*>( node )->contentDisposition()->filename();
591  if ( name.isEmpty() )
592  name = const_cast<KMime::Content*>( node )->contentType()->name();
593 
594  name = name.trimmed();
595  return name;
596 }
597 
598 //FIXME(Andras) review it (by Marc?) to see if I got it right. This is supposed to be the partNode::internalBodyPartMemento replacement
599 Interface::BodyPartMemento *NodeHelper::bodyPartMemento( KMime::Content *node,
600  const QByteArray &which ) const
601 {
602  const QMap< QString, QMap<QByteArray,Interface::BodyPartMemento*> >::const_iterator nit
603  = mBodyPartMementoMap.find( persistentIndex( node ) );
604  if ( nit == mBodyPartMementoMap.end() )
605  return 0;
606  const QMap<QByteArray,Interface::BodyPartMemento*>::const_iterator it =
607  nit->find( which.toLower() );
608  return it != nit->end() ? it.value() : 0 ;
609 }
610 
611  //FIXME(Andras) review it (by Marc?) to see if I got it right. This is supposed to be the partNode::internalSetBodyPartMemento replacement
612 void NodeHelper::setBodyPartMemento( KMime::Content* node, const QByteArray &which,
613  Interface::BodyPartMemento *memento )
614 {
615  QMap<QByteArray,Interface::BodyPartMemento*> & mementos
616  = mBodyPartMementoMap[persistentIndex(node)];
617 
618  const QMap<QByteArray,Interface::BodyPartMemento*>::iterator it =
619  mementos.lowerBound( which.toLower() );
620 
621  if ( it != mementos.end() && it.key() == which.toLower() ) {
622  delete it.value();
623  if ( memento ) {
624  it.value() = memento;
625  } else {
626  mementos.erase( it );
627  }
628  } else {
629  mementos.insert( which.toLower(), memento );
630  }
631 }
632 
633 bool NodeHelper::isNodeDisplayedEmbedded( KMime::Content* node ) const
634 {
635  //kDebug() << "IS NODE: " << mDisplayEmbeddedNodes.contains( node );
636  return mDisplayEmbeddedNodes.contains( node );
637 }
638 
639 void NodeHelper::setNodeDisplayedEmbedded( KMime::Content* node, bool displayedEmbedded )
640 {
641  //kDebug() << "SET NODE: " << node << displayedEmbedded;
642  if ( displayedEmbedded )
643  mDisplayEmbeddedNodes.insert( node );
644  else
645  mDisplayEmbeddedNodes.remove( node );
646 }
647 
648 bool NodeHelper::isNodeDisplayedHidden( KMime::Content* node ) const
649 {
650  return mDisplayHiddenNodes.contains( node );
651 }
652 
653 void NodeHelper::setNodeDisplayedHidden( KMime::Content* node, bool displayedHidden )
654 {
655  if( displayedHidden ) {
656  mDisplayHiddenNodes.insert( node );
657  } else {
658  mDisplayEmbeddedNodes.remove( node );
659  }
660 }
661 
668 QString NodeHelper::persistentIndex( const KMime::Content * node ) const
669 {
670  if ( !node )
671  return QString();
672 
673  QString indexStr = node->index().toString();
674  const KMime::Content * const topLevel = node->topLevel();
675  //if the node is an extra node, prepend the index of the extra node to the url
676  Q_FOREACH( const QList<KMime::Content*> & extraNodes, mExtraContents ) {
677  const int extraNodesSize( extraNodes.size() );
678  for ( int i = 0; i < extraNodesSize; ++i )
679  if ( topLevel == extraNodes.at(i) )
680  return indexStr.prepend( QString::fromLatin1("%1:").arg(i) );
681  }
682  return indexStr;
683 }
684 
685 QString NodeHelper::asHREF( const KMime::Content* node, const QString &place )
686 {
687  return QString::fromLatin1( "attachment:%1?place=%2" ).arg( persistentIndex( node ), place );
688 }
689 
690 QString NodeHelper::fixEncoding( const QString &encoding )
691 {
692  QString returnEncoding = encoding;
693  // According to http://www.iana.org/assignments/character-sets, uppercase is
694  // preferred in MIME headers
695  if ( returnEncoding.toUpper().contains( QLatin1String("ISO ") ) ) {
696  returnEncoding = returnEncoding.toUpper();
697  returnEncoding.replace( QLatin1String("ISO "), QLatin1String("ISO-") );
698  }
699  return returnEncoding;
700 }
701 
702 
703 //-----------------------------------------------------------------------------
704 QString NodeHelper::encodingForName( const QString &descriptiveName )
705 {
706  QString encoding = KGlobal::charsets()->encodingForName( descriptiveName );
707  return NodeHelper::fixEncoding( encoding );
708 }
709 
710 QStringList NodeHelper::supportedEncodings(bool usAscii)
711 {
712  QStringList encodingNames = KGlobal::charsets()->availableEncodingNames();
713  QStringList encodings;
714  QMap<QString,bool> mimeNames;
715  QStringList::ConstIterator constEnd( encodingNames.constEnd() );
716  for (QStringList::ConstIterator it = encodingNames.constBegin();
717  it != constEnd; ++it)
718  {
719  QTextCodec *codec = KGlobal::charsets()->codecForName(*it);
720  QString mimeName = (codec) ? QString::fromLatin1(codec->name()).toLower() : (*it);
721  if (!mimeNames.contains(mimeName) )
722  {
723  encodings.append( KGlobal::charsets()->descriptionForEncoding(*it) );
724  mimeNames.insert( mimeName, true );
725  }
726  }
727  encodings.sort();
728  if (usAscii)
729  encodings.prepend(KGlobal::charsets()->descriptionForEncoding(QLatin1String("us-ascii")) );
730  return encodings;
731 }
732 
733 
734 QByteArray NodeHelper::autoDetectCharset(const QByteArray &_encoding, const QStringList &encodingList, const QString &text)
735 {
736  QStringList charsets = encodingList;
737  if (!_encoding.isEmpty())
738  {
739  QString currentCharset = QString::fromLatin1(_encoding);
740  charsets.removeAll(currentCharset);
741  charsets.prepend(currentCharset);
742  }
743 
744  QStringList::ConstIterator it = charsets.constBegin();
745  QStringList::ConstIterator end = charsets.constEnd();
746  for (; it != end; ++it)
747  {
748  QByteArray encoding = (*it).toLatin1();
749  if (encoding == "locale")
750  {
751  encoding = QTextCodec::codecForName( KGlobal::locale()->encoding() )->name();
752  kAsciiToLower(encoding.data());
753  }
754  if (text.isEmpty())
755  return encoding;
756  if (encoding == "us-ascii") {
757  bool ok;
758  (void) toUsAscii(text, &ok);
759  if (ok)
760  return encoding;
761  }
762  else
763  {
764  const QTextCodec *codec = codecForName(encoding);
765  if (!codec) {
766  kDebug() << "Auto-Charset: Something is wrong and I cannot get a codec:" << encoding;
767  } else {
768  if (codec->canEncode(text))
769  return encoding;
770  }
771  }
772  }
773  return 0;
774 }
775 
776 QByteArray NodeHelper::toUsAscii(const QString& _str, bool *ok)
777 {
778  bool all_ok =true;
779  QString result = _str;
780  const int len = result.length();
781  for (int i = 0; i < len; ++i)
782  if (result.at(i).unicode() >= 128) {
783  result[i] = '?';
784  all_ok = false;
785  }
786  if (ok)
787  *ok = all_ok;
788  return result.toLatin1();
789 }
790 
791 QString NodeHelper::fromAsString( KMime::Content* node )
792 {
793  KMime::Message* topLevel = dynamic_cast<KMime::Message*>( node->topLevel() );
794  if ( topLevel )
795  return topLevel->from()->asUnicodeString();
796  return QString();
797 }
798 
799 void NodeHelper::attachExtraContent( KMime::Content *topLevelNode, KMime::Content* content )
800 {
801  //kDebug() << "mExtraContents added for" << topLevelNode << " extra content: " << content;
802  mExtraContents[topLevelNode].append( content );
803 }
804 
805 void NodeHelper::removeAllExtraContent( KMime::Content *topLevelNode )
806 {
807  const QMap< KMime::Content*, QList<KMime::Content*> >::iterator it
808  = mExtraContents.find( topLevelNode );
809  if ( it != mExtraContents.end() ) {
810  qDeleteAll( *it );
811  mExtraContents.erase( it );
812  }
813 }
814 
815 QList< KMime::Content* > NodeHelper::extraContents( KMime::Content *topLevelnode ) const
816 {
817  const QMap< KMime::Content*, QList<KMime::Content*> >::const_iterator it
818  = mExtraContents.find( topLevelnode );
819  if ( it == mExtraContents.end() )
820  return QList<KMime::Content*>();
821  else
822  return *it;
823 }
824 
825 bool NodeHelper::isPermanentWithExtraContent( KMime::Content* node ) const
826 {
827  const QMap< KMime::Content*, QList<KMime::Content*> >::const_iterator it
828  = mExtraContents.find( node );
829  return it != mExtraContents.end() && !it->empty();
830 }
831 
832 
833 void NodeHelper::mergeExtraNodes( KMime::Content *node )
834 {
835  if ( !node )
836  return;
837 
838  QList<KMime::Content* > extraNodes = extraContents( node );
839  Q_FOREACH( KMime::Content* extra, extraNodes ) {
840  if( node->bodyIsMessage() ) {
841  kWarning() << "Asked to attach extra content to a kmime::message, this does not make sense. Attaching to:" << node <<
842  node->encodedContent() << "\n====== with =======\n" << extra << extra->encodedContent();
843  continue;
844  }
845  KMime::Content *c = new KMime::Content( node );
846  c->setContent( extra->encodedContent() );
847  c->parse();
848  node->addContent( c );
849  }
850 
851  Q_FOREACH( KMime::Content* child, node->contents() ) {
852  mergeExtraNodes( child );
853  }
854 }
855 
856 void NodeHelper::cleanFromExtraNodes( KMime::Content* node )
857 {
858  if ( !node )
859  return;
860  QList<KMime::Content* > extraNodes = extraContents( node );
861  Q_FOREACH( KMime::Content* extra, extraNodes ) {
862  QByteArray s = extra->encodedContent();
863  QList<KMime::Content* > children = node->contents();
864  Q_FOREACH( KMime::Content *c, children ) {
865  if ( c->encodedContent() == s ) {
866  node->removeContent( c );
867  }
868  }
869  }
870  Q_FOREACH( KMime::Content* child, node->contents() ) {
871  cleanFromExtraNodes( child );
872  }
873 }
874 
875 
876 KMime::Message* NodeHelper::messageWithExtraContent( KMime::Content* topLevelNode )
877 {
878  /*The merge is done in several steps:
879  1) merge the extra nodes into topLevelNode
880  2) copy the modified (merged) node tree into a new node tree
881  3) restore the original node tree in topLevelNode by removing the extra nodes from it
882 
883  The reason is that extra nodes are assigned by pointer value to the nodes in the original tree.
884  */
885  if (!topLevelNode)
886  return 0;
887 
888  mergeExtraNodes( topLevelNode );
889 
890  KMime::Message *m = new KMime::Message;
891  m->setContent( topLevelNode->encodedContent() );
892  m->parse();
893 
894  cleanFromExtraNodes( topLevelNode );
895 // qDebug() << "MESSAGE WITH EXTRA: " << m->encodedContent();
896 // qDebug() << "MESSAGE WITHOUT EXTRA: " << topLevelNode->encodedContent();
897 
898  return m;
899 }
900 
901 NodeHelper::AttachmentDisplayInfo NodeHelper::attachmentDisplayInfo( KMime::Content* node )
902 {
903  AttachmentDisplayInfo info;
904  info.icon = iconName( node, KIconLoader::Small );
905  const QString name = node->contentType()->name();
906  info.label = name.isEmpty() ? fileName( node ) : name;
907  if( info.label.isEmpty() ) {
908  info.label = node->contentDescription()->asUnicodeString();
909  }
910 
911  bool typeBlacklisted = node->contentType()->mediaType().toLower() == "multipart";
912  if ( !typeBlacklisted ) {
913  typeBlacklisted = MessageCore::StringUtil::isCryptoPart( QLatin1String(node->contentType()->mediaType()),
914  QLatin1String(node->contentType()->subType()),
915  node->contentDisposition()->filename() );
916  }
917  typeBlacklisted = typeBlacklisted || node == node->topLevel();
918  const bool firstTextChildOfEncapsulatedMsg =
919  node->contentType()->mediaType().toLower() == "text" &&
920  node->contentType()->subType().toLower() == "plain" &&
921  node->parent() && node->parent()->contentType()->mediaType().toLower() == "message";
922  typeBlacklisted = typeBlacklisted || firstTextChildOfEncapsulatedMsg;
923  info.displayInHeader = !info.label.isEmpty() && !info.icon.isEmpty() && !typeBlacklisted;
924  return info;
925 }
926 
927 KMime::Content * NodeHelper::decryptedNodeForContent( KMime::Content * content ) const
928 {
929  const QList<KMime::Content*> xc = extraContents( content );
930  if ( !xc.empty() ) {
931  if ( xc.size() == 1 ) {
932  return xc.front();
933  } else {
934  kWarning() << "WTF, encrypted node has multiple extra contents?";
935  }
936  }
937  return 0;
938 }
939 
940 bool NodeHelper::unencryptedMessage_helper( KMime::Content *node, QByteArray &resultingData, bool addHeaders,
941  int recursionLevel )
942 {
943  bool returnValue = false;
944  if ( node ) {
945  KMime::Content *curNode = node;
946  KMime::Content *decryptedNode = 0;
947  const QByteArray type = node->contentType( false ) ? QByteArray( node->contentType()->mediaType() ).toLower() : "text";
948  const QByteArray subType = node->contentType( false ) ? node->contentType()->subType().toLower() : "plain";
949  const bool isMultipart = node->contentType( false ) && node->contentType()->isMultipart();
950  bool isSignature = false;
951 
952  //kDebug() << "(" << recursionLevel << ") Looking at" << type << "/" << subType;
953 
954  if ( isMultipart ) {
955  if ( subType == "signed" ) {
956  isSignature = true;
957  } else if ( subType == "encrypted" ) {
958  decryptedNode = decryptedNodeForContent( curNode );
959  }
960  } else if ( type == "application" ) {
961  if ( subType == "octet-stream" ) {
962  decryptedNode = decryptedNodeForContent( curNode );
963  } else if ( subType == "pkcs7-signature" ) {
964  isSignature = true;
965  } else if ( subType == "pkcs7-mime" ) {
966  // note: subtype pkcs7-mime can also be signed
967  // and we do NOT want to remove the signature!
968  if ( encryptionState( curNode ) != KMMsgNotEncrypted ) {
969  decryptedNode = decryptedNodeForContent( curNode );
970  }
971  }
972  }
973 
974  if ( decryptedNode ) {
975  //kDebug() << "Current node has an associated decrypted node, adding a modified header "
976  // "and then processing the children.";
977 
978  Q_ASSERT( addHeaders );
979  KMime::Content headers;
980  headers.setHead( curNode->head() );
981  headers.parse();
982  if ( decryptedNode->contentType( false ) ) {
983  headers.contentType()->from7BitString( decryptedNode->contentType()->as7BitString( false ) );
984  } else {
985  headers.removeHeader( headers.contentType()->type() );
986  }
987  if ( decryptedNode->contentTransferEncoding( false ) ) {
988  headers.contentTransferEncoding()->from7BitString( decryptedNode->contentTransferEncoding()->as7BitString( false ) );
989  } else {
990  headers.removeHeader( headers.contentTransferEncoding()->type() );
991  }
992  if ( decryptedNode->contentDisposition( false ) ) {
993  headers.contentDisposition()->from7BitString( decryptedNode->contentDisposition()->as7BitString( false ) );
994  } else {
995  headers.removeHeader( headers.contentDisposition()->type() );
996  }
997  if ( decryptedNode->contentDescription( false ) ) {
998  headers.contentDescription()->from7BitString( decryptedNode->contentDescription()->as7BitString( false ) );
999  } else {
1000  headers.removeHeader( headers.contentDescription()->type() );
1001  }
1002  headers.assemble();
1003 
1004  resultingData += headers.head() + '\n';
1005  unencryptedMessage_helper( decryptedNode, resultingData, false, recursionLevel + 1 );
1006 
1007  returnValue = true;
1008  }
1009 
1010  else if ( isSignature ) {
1011  //kDebug() << "Current node is a signature, adding it as-is.";
1012  // We can't change the nodes under the signature, as that would invalidate it. Add the signature
1013  // and its child as-is
1014  if ( addHeaders ) {
1015  resultingData += curNode->head() + '\n';
1016  }
1017  resultingData += curNode->encodedBody();
1018  returnValue = false;
1019  }
1020 
1021  else if ( isMultipart ) {
1022  //kDebug() << "Current node is a multipart node, adding its header and then processing all children.";
1023  // Normal multipart node, add the header and all of its children
1024  bool somethingChanged = false;
1025  if ( addHeaders ) {
1026  resultingData += curNode->head() + '\n';
1027  }
1028  const QByteArray boundary = curNode->contentType()->boundary();
1029  foreach( KMime::Content *child, curNode->contents() ) {
1030  resultingData += "\n--" + boundary + '\n';
1031  const bool changed = unencryptedMessage_helper( child, resultingData, true, recursionLevel + 1 );
1032  if ( changed ) {
1033  somethingChanged = true;
1034  }
1035  }
1036  resultingData += "\n--" + boundary + "--\n\n";
1037  returnValue = somethingChanged;
1038  }
1039 
1040  else if ( curNode->bodyIsMessage() ) {
1041  //kDebug() << "Current node is a message, adding the header and then processing the child.";
1042  if ( addHeaders ) {
1043  resultingData += curNode->head() + '\n';
1044  }
1045 
1046  returnValue = unencryptedMessage_helper( curNode->bodyAsMessage().get(), resultingData, true, recursionLevel + 1 );
1047  }
1048 
1049  else {
1050  //kDebug() << "Current node is an ordinary leaf node, adding it as-is.";
1051  if ( addHeaders ) {
1052  resultingData += curNode->head() + '\n';
1053  }
1054  resultingData += curNode->body();
1055  returnValue = false;
1056  }
1057  }
1058 
1059  //kDebug() << "(" << recursionLevel << ") done.";
1060  return returnValue;
1061 }
1062 
1063 KMime::Message::Ptr NodeHelper::unencryptedMessage( const KMime::Message::Ptr& originalMessage )
1064 {
1065  QByteArray resultingData;
1066  const bool messageChanged = unencryptedMessage_helper( originalMessage.get(), resultingData, true );
1067  if ( messageChanged ) {
1068 #if 0
1069  kDebug() << "Resulting data is:" << resultingData;
1070  QFile bla("stripped.mbox");
1071  bla.open(QIODevice::WriteOnly);
1072  bla.write(resultingData);
1073  bla.close();
1074 #endif
1075  KMime::Message::Ptr newMessage( new KMime::Message );
1076  newMessage->setContent( resultingData );
1077  newMessage->parse();
1078  return newMessage;
1079  } else {
1080  return KMime::Message::Ptr();
1081  }
1082 }
1083 
1084 }
MessageViewer::NodeHelper::unencryptedMessage
KMime::Message::Ptr unencryptedMessage(const KMime::Message::Ptr &originalMessage)
This function returns the unencrypted message that is based on originalMessage.
Definition: nodehelper.cpp:1063
QList::clear
void clear()
globalsettings.h
MessageViewer::PartMetaData
Definition: partmetadata.h:31
MessageViewer::NodeHelper::attachExtraContent
void attachExtraContent(KMime::Content *topLevelNode, KMime::Content *content)
Attach an extra node to an existing node.
Definition: nodehelper.cpp:799
MessageViewer::Util::fileNameForMimetype
QString MESSAGEVIEWER_EXPORT fileNameForMimetype(const QString &mimeType, int iconSize, const QString &fallbackFileName1=QString(), const QString &fallbackFileName2=QString())
Finds the filename of an icon based on the given mimetype or filenames.
Definition: util.cpp:93
QString::toUpper
QString toUpper() const
QMap::erase
iterator erase(iterator pos)
iconnamecache.h
QMap::contains
bool contains(const Key &key) const
QTextCodec::name
virtual QByteArray name() const =0
MessageViewer::NodeHelper::AttachmentDisplayInfo::icon
QString icon
Definition: nodehelper.h:255
MessageViewer::NodeHelper::overallSignatureState
KMMsgSignatureState overallSignatureState(KMime::Content *node) const
Definition: nodehelper.cpp:424
QMap::empty
bool empty() const
QByteArray::toLower
QByteArray toLower() const
MessageViewer::NodeHelper::supportedEncodings
static QStringList supportedEncodings(bool usAscii)
Return a list of the supported encodings.
Definition: nodehelper.cpp:710
MessageViewer::NodeHelper::decryptedNodeForContent
KMime::Content * decryptedNodeForContent(KMime::Content *content) const
Definition: nodehelper.cpp:927
QByteArray
MessageViewer::NodeHelper::partMetaData
PartMetaData partMetaData(KMime::Content *node)
Definition: nodehelper.cpp:208
MessageViewer::NodeHelper::extraContents
QList< KMime::Content * > extraContents(KMime::Content *topLevelNode) const
Get the extra nodes attached to the.
Definition: nodehelper.cpp:815
QString::prepend
QString & prepend(QChar ch)
QMap::constBegin
const_iterator constBegin() const
MessageViewer::KMMsgSignatureState
KMMsgSignatureState
Flags for the signature state.
Definition: nodehelper.h:61
QList::at
const T & at(int i) const
QMap
QByteArray::isNull
bool isNull() const
QByteArray::isEmpty
bool isEmpty() const
partmetadata.h
MessageViewer::NodeHelper::toUsAscii
static QByteArray toUsAscii(const QString &_str, bool *ok)
Definition: nodehelper.cpp:776
MessageViewer::KMMsgPartiallySigned
Definition: nodehelper.h:65
QStringList::join
QString join(const QString &separator) const
nodehelper.h
QSet::insert
const_iterator insert(const T &value)
MessageViewer::KMMsgPartiallyEncrypted
Definition: nodehelper.h:55
QMap::clear
void clear()
MessageViewer::NodeHelper::NodeHelper
NodeHelper()
Definition: nodehelper.cpp:58
QFile
QList::size
int size() const
QString::lastIndexOf
int lastIndexOf(QChar ch, int from, Qt::CaseSensitivity cs) const
QString::isNull
bool isNull() const
QStringRef
MessageViewer::KMMsgSignatureStateUnknown
Definition: nodehelper.h:63
QRegExp::matchedLength
int matchedLength() const
QRegExp::indexIn
int indexIn(const QString &str, int offset, CaretMode caretMode) const
MessageViewer::KMMsgNotSigned
Definition: nodehelper.h:64
QRegExp
MessageViewer::KMMsgFullySigned
Definition: nodehelper.h:66
QList::append
void append(const T &value)
QList::empty
bool empty() const
MessageViewer::KMMsgNotEncrypted
Definition: nodehelper.h:54
MessageViewer::NodeHelper::forceCleanTempFiles
void forceCleanTempFiles()
Definition: nodehelper.cpp:302
MessageViewer::NodeHelper::messageWithExtraContent
KMime::Message * messageWithExtraContent(KMime::Content *topLevelNode)
Return a modified message (node tree) starting from.
Definition: nodehelper.cpp:876
QString::isEmpty
bool isEmpty() const
QList::removeAll
int removeAll(const T &value)
QString::trimmed
QString trimmed() const
QMap::constEnd
const_iterator constEnd() const
bodypart.h
QString::startsWith
bool startsWith(const QString &s, Qt::CaseSensitivity cs) const
MessageViewer::NodeHelper::addTempFile
void addTempFile(const QString &file)
Add a file to the list of managed temporary files.
Definition: nodehelper.cpp:316
QMap::const_iterator
MessageViewer::NodeHelper::setOverrideCodec
void setOverrideCodec(KMime::Content *node, const QTextCodec *codec)
Set the charset the user selected for the message to display.
Definition: nodehelper.cpp:548
MessageViewer::NodeHelper::autoDetectCharset
static QByteArray autoDetectCharset(const QByteArray &_encoding, const QStringList &encodingList, const QString &text)
Definition: nodehelper.cpp:734
QList::front
T & front()
MessageViewer::NodeHelper::nodeProcessed
bool nodeProcessed(KMime::Content *node) const
Definition: nodehelper.cpp:142
QString
QList< KMime::Content * >
QMap::end
iterator end()
QChar::unicode
ushort unicode() const
QTextCodec
util.h
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
QFile::open
virtual bool open(QFlags< QIODevice::OpenModeFlag > mode)
MessageViewer::NodeHelper::AttachmentDisplayInfo
Definition: nodehelper.h:252
QMap::lowerBound
iterator lowerBound(const Key &key)
MessageViewer::NodeHelper::codecForName
static const QTextCodec * codecForName(const QByteArray &_str)
Return a QTextCodec for the specified charset.
Definition: nodehelper.cpp:579
QMap::begin
iterator begin()
QStringList
MessageViewer::NodeHelper::encryptionState
KMMsgEncryptionState encryptionState(KMime::Content *node) const
Definition: nodehelper.cpp:193
MessageViewer::NodeHelper::asHREF
QString asHREF(const KMime::Content *node, const QString &place)
Definition: nodehelper.cpp:685
MessageViewer::replySubjPrefixes
QStringList replySubjPrefixes(QStringList()<< QLatin1String("Re\\s*:")<< QLatin1String("Re\\[\\d+\\]:")<< QLatin1String("Re\\d+:"))
MessageViewer::NodeHelper::setBodyPartMemento
void setBodyPartMemento(KMime::Content *node, const QByteArray &which, Interface::BodyPartMemento *memento)
Definition: nodehelper.cpp:612
MessageViewer::NodeHelper::encodingForName
static QString encodingForName(const QString &descriptiveName)
Drop-in replacement for KCharsets::encodingForName().
Definition: nodehelper.cpp:704
MessageViewer::NodeHelper::isNodeDisplayedHidden
bool isNodeDisplayedHidden(KMime::Content *node) const
Definition: nodehelper.cpp:648
QString::toLower
QString toLower() const
QString::contains
bool contains(QChar ch, Qt::CaseSensitivity cs) const
QLatin1Char
QList::contains
bool contains(const T &value) const
QFile::close
virtual void close()
QSet::contains
bool contains(const T &value) const
MessageViewer::Util::mimetype
MESSAGEVIEWER_EXPORT KMimeType::Ptr mimetype(const QString &name)
Search mimetype from filename when mimetype is empty or application/octet-stream. ...
Definition: util.cpp:569
MessageViewer::KMMsgSignatureProblematic
Definition: nodehelper.h:67
QMap::key
const Key key(const T &value) const
MessageViewer::NodeHelper::setSignatureState
void setSignatureState(KMime::Content *node, const KMMsgSignatureState state)
Definition: nodehelper.cpp:198
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
MessageViewer::NodeHelper::bodyPartMemento
Interface::BodyPartMemento * bodyPartMemento(KMime::Content *node, const QByteArray &which) const
Definition: nodehelper.cpp:599
QString::replace
QString & replace(int position, int n, QChar after)
MessageViewer::NodeHelper::cleanSubject
static QString cleanSubject(KMime::Message *message)
Return this mails subject, with all "forward" and "reply" prefixes removed.
Definition: nodehelper.cpp:528
MessageViewer::NodeHelper::overallEncryptionState
KMMsgEncryptionState overallEncryptionState(KMime::Content *node) const
Definition: nodehelper.cpp:376
MessageViewer::NodeHelper::charset
static QByteArray charset(KMime::Content *node)
Returns the charset for the given node.
Definition: nodehelper.cpp:368
MessageViewer::Interface::BodyPartMemento
interface of classes that implement status for BodyPartFormatters.
Definition: bodypart.h:55
type
const char * type
Definition: bodypartformatter.cpp:192
MessageViewer::NodeHelper::setPartMetaData
void setPartMetaData(KMime::Content *node, const PartMetaData &metaData)
Definition: nodehelper.cpp:213
QString::toLatin1
QByteArray toLatin1() const
MessageViewer::NodeHelper::fromAsString
static QString fromAsString(KMime::Content *node)
Definition: nodehelper.cpp:791
QString::mid
QString mid(int position, int n) const
QSet::remove
bool remove(const T &value)
MessageViewer::NodeHelper::isToltecMessage
static bool isToltecMessage(KMime::Content *node)
Definition: nodehelper.cpp:321
MessageViewer::NodeHelper::removeAllExtraContent
void removeAllExtraContent(KMime::Content *topLevelNode)
Definition: nodehelper.cpp:805
QLatin1String
MessageViewer::NodeHelper::setNodeDisplayedHidden
void setNodeDisplayedHidden(KMime::Content *node, bool displayedHidden)
Definition: nodehelper.cpp:653
MessageViewer::NodeHelper::setNodeDisplayedEmbedded
void setNodeDisplayedEmbedded(KMime::Content *node, bool displayedEmbedded)
Definition: nodehelper.cpp:639
MessageViewer::clearBodyPartMemento
static void clearBodyPartMemento(QMap< QByteArray, Interface::BodyPartMemento * > &bodyPartMementoMap)
Definition: nodehelper.cpp:149
MessageViewer::KMMsgFullyEncrypted
Definition: nodehelper.h:56
MessageViewer::Interface::BodyPartMemento::detach
virtual void detach()=0
MessageViewer::NodeHelper::~NodeHelper
~NodeHelper()
Definition: nodehelper.cpp:88
QString::at
const QChar at(int position) const
QRegExp::isValid
bool isValid() const
QTextCodec::codecForName
QTextCodec * codecForName(const QByteArray &name)
QList::ConstIterator
typedef ConstIterator
MessageViewer::KMMsgEncryptionState
KMMsgEncryptionState
Flags for the encryption state.
Definition: nodehelper.h:51
QString::length
int length() const
QTextCodec::canEncode
bool canEncode(QChar ch) const
QByteArray::data
char * data()
MessageViewer::NodeHelper::iconName
static QString iconName(KMime::Content *node, int size=KIconLoader::Desktop)
Definition: nodehelper.cpp:471
MessageViewer::NodeHelper::setNodeUnprocessed
void setNodeUnprocessed(KMime::Content *node, bool recurse)
Definition: nodehelper.cpp:113
MessageViewer::KMMsgEncryptionStateUnknown
Definition: nodehelper.h:53
MessageViewer::NodeHelper::setNodeProcessed
void setNodeProcessed(KMime::Content *node, bool recurse)
Definition: nodehelper.cpp:97
QIODevice::write
qint64 write(const char *data, qint64 maxSize)
MessageViewer::NodeHelper::removeTempFiles
void removeTempFiles()
Cleanup the attachment temp files.
Definition: nodehelper.cpp:309
QString::fromLatin1
QString fromLatin1(const char *str, int size)
QStringList::sort
void sort()
MessageViewer::NodeHelper::AttachmentDisplayInfo::displayInHeader
bool displayInHeader
Definition: nodehelper.h:256
QList::prepend
void prepend(const T &value)
MessageViewer::NodeHelper::signatureState
KMMsgSignatureState signatureState(KMime::Content *node) const
Definition: nodehelper.cpp:203
QMap::insert
iterator insert(const Key &key, const T &value)
MessageViewer::NodeHelper::AttachmentDisplayInfo::label
QString label
Definition: nodehelper.h:254
MessageViewer::NodeHelper::isInEncapsulatedMessage
static bool isInEncapsulatedMessage(KMime::Content *node)
Definition: nodehelper.cpp:352
MessageViewer::NodeHelper::codec
const QTextCodec * codec(KMime::Content *node)
Get a QTextCodec suitable for this message part.
Definition: nodehelper.cpp:556
QList::constEnd
const_iterator constEnd() const
MessageViewer::NodeHelper::isNodeDisplayedEmbedded
bool isNodeDisplayedEmbedded(KMime::Content *node) const
Definition: nodehelper.cpp:633
QSet::clear
void clear()
QList::constBegin
const_iterator constBegin() const
MessageViewer::forwardSubjPrefixes
QStringList forwardSubjPrefixes(QStringList()<< QLatin1String("Fwd:")<< QLatin1String("FW:"))
QByteArray::size
int size() const
MessageViewer::KMMsgEncryptionProblematic
Definition: nodehelper.h:57
MessageViewer::NodeHelper::replacePrefixes
static QString replacePrefixes(const QString &str, const QStringList &prefixRegExps, bool replace, const QString &newPrefix)
Check for prefixes prefixRegExps in str.
Definition: nodehelper.cpp:496
MessageViewer::NodeHelper::attachmentDisplayInfo
static AttachmentDisplayInfo attachmentDisplayInfo(KMime::Content *node)
Definition: nodehelper.cpp:901
QString::arg
QString arg(qlonglong a, int fieldWidth, int base, const QChar &fillChar) const
QMap::find
iterator find(const Key &key)
MessageViewer::NodeHelper::clear
void clear()
Definition: nodehelper.cpp:162
MessageViewer::NodeHelper::fixEncoding
static QString fixEncoding(const QString &encoding)
Fixes an encoding received by a KDE function and returns the proper, MIME-compilant encoding name ins...
Definition: nodehelper.cpp:690
QMap::iterator
MessageViewer::NodeHelper::createTempDir
QString createTempDir(const QString &param=QString())
Creates a temporary dir for saving attachments, etc.
Definition: nodehelper.cpp:280
MessageViewer::NodeHelper::isPermanentWithExtraContent
bool isPermanentWithExtraContent(KMime::Content *node) const
Returns true if the given node at least one extra content node, implying that the given node is an en...
Definition: nodehelper.cpp:825
QFile::encodeName
QByteArray encodeName(const QString &fileName)
MessageViewer::NodeHelper::setEncryptionState
void setEncryptionState(KMime::Content *node, const KMMsgEncryptionState state)
Definition: nodehelper.cpp:188
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::NodeHelper::magicSetType
void magicSetType(KMime::Content *node, bool autoDecode=true)
Set the 'Content-Type' by mime-magic from the contents of the body.
Definition: nodehelper.cpp:486
QMap::value
const T value(const Key &key) const
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