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

KMIME Library

  • sources
  • kde-4.14
  • kdepimlibs
  • kmime
kmime_content.cpp
Go to the documentation of this file.
1 /*
2  kmime_content.cpp
3 
4  KMime, the KDE Internet mail/usenet news message library.
5  Copyright (c) 2001 the KMime authors.
6  See file AUTHORS for details
7  Copyright (c) 2006 Volker Krause <vkrause@kde.org>
8  Copyright (c) 2009 Constantin Berzan <exit3219@gmail.com>
9 
10  This library is free software; you can redistribute it and/or
11  modify it under the terms of the GNU Library General Public
12  License as published by the Free Software Foundation; either
13  version 2 of the License, or (at your option) any later version.
14 
15  This library is distributed in the hope that it will be useful,
16  but WITHOUT ANY WARRANTY; without even the implied warranty of
17  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18  Library General Public License for more details.
19 
20  You should have received a copy of the GNU Library General Public License
21  along with this library; see the file COPYING.LIB. If not, write to
22  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
23  Boston, MA 02110-1301, USA.
24 */
37 #include "kmime_content.h"
38 #include "kmime_content_p.h"
39 #include "kmime_codecs.h"
40 #include "kmime_message.h"
41 #include "kmime_header_parsing.h"
42 #include "kmime_header_parsing_p.h"
43 #include "kmime_parsers.h"
44 #include "kmime_util_p.h"
45 
46 #include <kcharsets.h>
47 #include <kcodecs.h>
48 #include <kglobal.h>
49 #include <klocale.h>
50 #include <klocalizedstring.h>
51 #include <kdebug.h>
52 
53 #include <QtCore/QTextCodec>
54 #include <QtCore/QTextStream>
55 #include <QtCore/QByteArray>
56 
57 using namespace KMime;
58 
59 namespace KMime {
60 
61 Content::Content()
62  : d_ptr( new ContentPrivate( this ) )
63 {
64 }
65 
66 Content::Content( Content *parent )
67  : d_ptr( new ContentPrivate( this ) )
68 {
69  d_ptr->parent = parent;
70 }
71 
72 Content::Content( const QByteArray &h, const QByteArray &b )
73  : d_ptr( new ContentPrivate( this ) )
74 {
75  d_ptr->head = h;
76  d_ptr->body = b;
77 }
78 
79 Content::Content( const QByteArray &h, const QByteArray &b, Content *parent )
80  : d_ptr( new ContentPrivate( this ) )
81 {
82  d_ptr->head = h;
83  d_ptr->body = b;
84  d_ptr->parent = parent;
85 }
86 
87 Content::Content( ContentPrivate *d )
88  : d_ptr( d )
89 {
90 }
91 
92 Content::~Content()
93 {
94  qDeleteAll( h_eaders );
95  h_eaders.clear();
96  delete d_ptr;
97  d_ptr = 0;
98 }
99 
100 bool Content::hasContent() const
101 {
102  return !d_ptr->head.isEmpty() || !d_ptr->body.isEmpty() || !d_ptr->contents().isEmpty();
103 }
104 
105 void Content::setContent( const QList<QByteArray> &l )
106 {
107  Q_D( Content );
108  //qDebug("Content::setContent( const QList<QByteArray> &l ) : start");
109  d->head.clear();
110  d->body.clear();
111 
112  //usage of textstreams is much faster than simply appending the strings
113  QTextStream hts( &( d->head ), QIODevice::WriteOnly );
114  QTextStream bts( &( d->body ), QIODevice::WriteOnly );
115  hts.setCodec( "ISO 8859-1" );
116  bts.setCodec( "ISO 8859-1" );
117 
118  bool isHead = true;
119  foreach ( const QByteArray& line, l ) {
120  if ( isHead && line.isEmpty() ) {
121  isHead = false;
122  continue;
123  }
124  if ( isHead ) {
125  hts << line << "\n";
126  } else {
127  bts << line << "\n";
128  }
129  }
130 
131  //qDebug("Content::setContent( const QList<QByteArray> & l ) : finished");
132 }
133 
134 void Content::setContent( const QByteArray &s )
135 {
136  Q_D( Content );
137  KMime::HeaderParsing::extractHeaderAndBody( s, d->head, d->body );
138 }
139 
140 QByteArray Content::head() const
141 {
142  return d_ptr->head;
143 }
144 
145 void Content::setHead( const QByteArray &head )
146 {
147  d_ptr->head = head;
148  if ( !head.endsWith( '\n' ) ) {
149  d_ptr->head += '\n';
150  }
151 }
152 
153 QByteArray Content::body() const
154 {
155  return d_ptr->body;
156 }
157 
158 void Content::setBody( const QByteArray &body )
159 {
160  d_ptr->body = body;
161 }
162 
163 QByteArray Content::preamble() const
164 {
165  return d_ptr->preamble;
166 }
167 
168 void Content::setPreamble( const QByteArray &preamble )
169 {
170  d_ptr->preamble = preamble;
171 }
172 
173 
174 QByteArray Content::epilogue() const
175 {
176  return d_ptr->epilogue;
177 }
178 
179 void Content::setEpilogue( const QByteArray &epilogue )
180 {
181  d_ptr->epilogue = epilogue;
182 }
183 
184 void Content::parse()
185 {
186  Q_D( Content );
187 
188  // Clean up old headers and parse them again.
189  qDeleteAll( h_eaders );
190  h_eaders.clear();
191  h_eaders = HeaderParsing::parseHeaders( d->head );
192  foreach ( Headers::Base *h, h_eaders ) {
193  h->setParent( this );
194  }
195 
196  // If we are frozen, save the body as-is. This is done because parsing
197  // changes the content (it loses preambles and epilogues, converts uuencode->mime, etc.)
198  if ( d->frozen ) {
199  d->frozenBody = d->body;
200  }
201 
202  // Clean up old sub-Contents and parse them again.
203  qDeleteAll( d->multipartContents );
204  d->multipartContents.clear();
205  d->clearBodyMessage();
206  Headers::ContentType *ct = contentType();
207  if ( ct->isText() ) {
208  // This content is either text, or of unknown type.
209 
210  if ( d->parseUuencoded() ) {
211  // This is actually uuencoded content generated by broken software.
212  } else if ( d->parseYenc() ) {
213  // This is actually yenc content generated by broken software.
214  } else {
215  // This is just plain text.
216  }
217  } else if ( ct->isMultipart() ) {
218  // This content claims to be MIME multipart.
219 
220  if ( d->parseMultipart() ) {
221  // This is actual MIME multipart content.
222  } else {
223  // Parsing failed; treat this content as "text/plain".
224  ct->setMimeType( "text/plain" );
225  ct->setCharset( "US-ASCII" );
226  }
227  } else {
228  // This content is something else, like an encapsulated message or a binary attachment
229  // or something like that
230  if ( bodyIsMessage() ) {
231  d->bodyAsMessage = Message::Ptr( new Message );
232  d->bodyAsMessage->setContent( d->body );
233  d->bodyAsMessage->setFrozen( d->frozen );
234  d->bodyAsMessage->parse();
235  d->bodyAsMessage->d_ptr->parent = this;
236 
237  // Clear the body, as it is now represented by d->bodyAsMessage. This is the same behavior
238  // as with multipart contents, since parseMultipart() clears the body as well
239  d->body.clear();
240  }
241  }
242 }
243 
244 bool Content::isFrozen() const
245 {
246  return d_ptr->frozen;
247 }
248 
249 void Content::setFrozen( bool frozen )
250 {
251  d_ptr->frozen = frozen;
252 }
253 
254 void Content::assemble()
255 {
256  Q_D( Content );
257  if ( d->frozen ) {
258  return;
259  }
260 
261  d->head = assembleHeaders();
262  foreach ( Content *c, contents() ) {
263  c->assemble();
264  }
265 }
266 
267 QByteArray Content::assembleHeaders()
268 {
269  QByteArray newHead;
270  foreach ( const Headers::Base *h, h_eaders ) {
271  if ( !h->isEmpty() ) {
272  newHead += h->as7BitString() + '\n';
273  }
274  }
275 
276  return newHead;
277 }
278 
279 void Content::clear()
280 {
281  Q_D( Content );
282  qDeleteAll( h_eaders );
283  h_eaders.clear();
284  clearContents();
285  d->head.clear();
286  d->body.clear();
287 }
288 
289 void Content::clearContents( bool del )
290 {
291  Q_D( Content );
292  if ( del ) {
293  qDeleteAll( d->multipartContents );
294  }
295  d->multipartContents.clear();
296  d->clearBodyMessage();
297 }
298 
299 QByteArray Content::encodedContent( bool useCrLf )
300 {
301  QByteArray encodedContentData = head(); // return value; initialise with the head data
302  const QByteArray encodedBodyData = encodedBody();
303 
304  /* Make sure, that head and body have at least two newlines as seperator, otherwise add one.
305  * If we have enough newlines as sperator, than we should not change the number of newlines
306  * to not break digital signatures
307  */
308  if (!encodedContentData.endsWith("\n\n") &&
309  !encodedBodyData.startsWith("\n\n") &&
310  !(encodedContentData.endsWith("\n") && encodedBodyData.startsWith("\n"))){
311  encodedContentData += '\n';
312  }
313  encodedContentData += encodedBodyData;
314 
315  if ( useCrLf ) {
316  return LFtoCRLF( encodedContentData );
317  } else {
318  return encodedContentData;
319  }
320 }
321 
322 QByteArray Content::encodedBody()
323 {
324  Q_D( Content );
325  QByteArray e;
326  // Body.
327  if ( d->frozen ) {
328  // This Content is frozen.
329  if ( d->frozenBody.isEmpty() ) {
330  // This Content has never been parsed.
331  e += d->body;
332  } else {
333  // Use the body as it was before parsing.
334  e += d->frozenBody;
335  }
336  } else if ( bodyIsMessage() && d->bodyAsMessage ) {
337  // This is an encapsulated message
338  // No encoding needed, as the ContentTransferEncoding can only be 7bit
339  // for encapsulated messages
340  e += d->bodyAsMessage->encodedContent();
341  } else if ( !d->body.isEmpty() ) {
342  // This is a single-part Content.
343  Headers::ContentTransferEncoding *enc = contentTransferEncoding();
344 
345  if ( enc->needToEncode() ) {
346  if ( enc->encoding() == Headers::CEquPr ) {
347  e += KCodecs::quotedPrintableEncode( d->body, false );
348  } else {
349  e += KCodecs::base64Encode( d->body, true );
350  e += '\n';
351  }
352  } else {
353  e += d->body;
354  }
355  }
356 
357  if ( !d->frozen && !d->multipartContents.isEmpty() ) {
358  // This is a multipart Content.
359  Headers::ContentType *ct=contentType();
360  QByteArray boundary = "\n--" + ct->boundary();
361 
362  if ( !d->preamble.isEmpty() ) {
363  e += d->preamble;
364  }
365 
366  //add all (encoded) contents separated by boundaries
367  foreach ( Content *c, d->multipartContents ) {
368  e += boundary + '\n';
369  e += c->encodedContent( false ); // don't convert LFs here, we do that later!!!!!
370  }
371  //finally append the closing boundary
372  e += boundary+"--\n";
373 
374  if ( !d->epilogue.isEmpty() ) {
375  e += d->epilogue;
376  }
377  }
378  return e;
379 }
380 
381 QByteArray Content::decodedContent()
382 {
383  QByteArray ret;
384  Headers::ContentTransferEncoding *ec=contentTransferEncoding();
385  bool removeTrailingNewline=false;
386 
387  if ( d_ptr->body.length() == 0 ) {
388  return ret;
389  }
390 
391  if ( ec->decoded() ) {
392  ret = d_ptr->body;
393  //Laurent Fix bug #311267
394  //removeTrailingNewline = true;
395  } else {
396  switch ( ec->encoding() ) {
397  case Headers::CEbase64 :
398  {
399  KMime::Codec *codec = KMime::Codec::codecForName( "base64" );
400  Q_ASSERT( codec );
401  ret.resize( codec->maxDecodedSizeFor( d_ptr->body.size() ) );
402  KMime::Decoder* decoder = codec->makeDecoder();
403  QByteArray::const_iterator inputIt = d_ptr->body.constBegin();
404  QByteArray::iterator resultIt = ret.begin();
405  decoder->decode( inputIt, d_ptr->body.constEnd(), resultIt, ret.end() );
406  ret.truncate( resultIt - ret.begin() );
407  break;
408  }
409  case Headers::CEquPr :
410  ret = KCodecs::quotedPrintableDecode( d_ptr->body );
411  removeTrailingNewline = true;
412  break;
413  case Headers::CEuuenc :
414  KCodecs::uudecode( d_ptr->body, ret );
415  break;
416  case Headers::CEbinary :
417  ret = d_ptr->body;
418  removeTrailingNewline = false;
419  break;
420  default :
421  ret = d_ptr->body;
422  removeTrailingNewline = true;
423  }
424  }
425 
426  if ( removeTrailingNewline && ( ret.size() > 0 ) && ( ret[ret.size() - 1] == '\n' ) ) {
427  ret.resize( ret.size() - 1 );
428  }
429 
430  return ret;
431 }
432 
433 QString Content::decodedText( bool trimText, bool removeTrailingNewlines )
434 {
435  if ( !decodeText() ) { //this is not a text content !!
436  return QString();
437  }
438 
439  bool ok = true;
440  QTextCodec *codec =
441  KGlobal::charsets()->codecForName( QLatin1String( contentType()->charset() ), ok );
442  if ( !ok || codec == NULL ) { // no suitable codec found => try local settings and hope the best ;-)
443  codec = KGlobal::locale()->codecForEncoding();
444  QByteArray chset = KGlobal::locale()->encoding();
445  contentType()->setCharset( chset );
446  }
447 
448  QString s = codec->toUnicode( d_ptr->body.data(), d_ptr->body.length() );
449 
450  if ( trimText || removeTrailingNewlines ) {
451  int i;
452  for ( i = s.length() - 1; i >= 0; --i ) {
453  if ( trimText ) {
454  if ( !s[i].isSpace() ) {
455  break;
456  }
457  }
458  else {
459  if ( s[i] != QLatin1Char( '\n' ) ) {
460  break;
461  }
462  }
463  }
464  s.truncate( i + 1 );
465  } else {
466  if ( s.right( 1 ) == QLatin1String( "\n" ) ) {
467  s.truncate( s.length() - 1 ); // remove trailing new-line
468  }
469  }
470 
471  return s;
472 }
473 
474 void Content::fromUnicodeString( const QString &s )
475 {
476  bool ok = true;
477  QTextCodec *codec =
478  KGlobal::charsets()->codecForName( QLatin1String( contentType()->charset() ), ok );
479 
480  if ( !ok ) { // no suitable codec found => try local settings and hope the best ;-)
481  codec = KGlobal::locale()->codecForEncoding();
482  QByteArray chset = KGlobal::locale()->encoding();
483  contentType()->setCharset( chset );
484  }
485 
486  d_ptr->body = codec->fromUnicode( s );
487  contentTransferEncoding()->setDecoded( true ); //text is always decoded
488 }
489 
490 Content *Content::textContent()
491 {
492  Content *ret=0;
493 
494  //return the first content with mimetype=text/*
495  if ( contentType()->isText() ) {
496  ret = this;
497  } else {
498  foreach ( Content *c, d_ptr->contents() ) {
499  if ( ( ret = c->textContent() ) != 0 ) {
500  break;
501  }
502  }
503  }
504  return ret;
505 }
506 
507 Content::List Content::attachments( bool incAlternatives )
508 {
509  List attachments;
510  if ( d_ptr->contents().isEmpty() ) {
511  attachments.append( this );
512  } else {
513  foreach ( Content *c, d_ptr->contents() ) {
514  if ( !incAlternatives &&
515  c->contentType()->category() == Headers::CCalternativePart ) {
516  continue;
517  } else {
518  attachments += c->attachments( incAlternatives );
519  }
520  }
521  }
522 
523  if ( isTopLevel() ) {
524  Content *text = textContent();
525  if ( text ) {
526  attachments.removeAll( text );
527  }
528  }
529  return attachments;
530 }
531 
532 Content::List Content::contents() const
533 {
534  return d_ptr->contents();
535 }
536 
537 void Content::addContent( Content *c, bool prepend )
538 {
539  Q_D( Content );
540 
541  // This method makes no sense for encapsulated messages
542  Q_ASSERT( !bodyIsMessage() );
543 
544  // If this message is single-part; make it multipart first.
545  if( d->multipartContents.isEmpty() && !contentType()->isMultipart() ) {
546  // The current body will be our first sub-Content.
547  Content *main = new Content( this );
548 
549  // Move the MIME headers to the newly created sub-Content.
550  // NOTE: The other headers (RFC5322 headers like From:, To:, as well as X-headers
551  // are not moved to the subcontent; they remain with the top-level content.
552  for ( Headers::Base::List::iterator it = h_eaders.begin();
553  it != h_eaders.end(); ) {
554  if ( (*it)->isMimeHeader() ) {
555  // Add to new content.
556  main->setHeader( *it );
557  // Remove from this content.
558  it = h_eaders.erase( it );
559  } else {
560  ++it;
561  }
562  }
563 
564  // Adjust the Content-Type of the newly created sub-Content.
565  main->contentType()->setCategory( Headers::CCmixedPart );
566 
567  // Move the body to the new subcontent.
568  main->setBody( d->body );
569  d->body.clear();
570 
571  // Add the subcontent.
572  d->multipartContents.append( main );
573 
574  // Convert this content to "multipart/mixed".
575  Headers::ContentType *ct = contentType();
576  ct->setMimeType( "multipart/mixed" );
577  ct->setBoundary( multiPartBoundary() );
578  ct->setCategory( Headers::CCcontainer );
579  contentTransferEncoding()->clear(); // 7Bit, decoded.
580  }
581 
582  // Add the new content.
583  if( prepend ) {
584  d->multipartContents.prepend( c );
585  } else {
586  d->multipartContents.append( c );
587  }
588 
589  if( c->parent() != this ) {
590  // If the content was part of something else, this will remove it from there.
591  c->setParent( this );
592  }
593 }
594 
595 void Content::replaceContent(Content *oldContent, Content *newContent)
596 {
597  Q_D( Content );
598  if ( d->multipartContents.isEmpty() || !d->multipartContents.contains( oldContent ) ) {
599  return;
600  }
601 
602  d->multipartContents.removeAll( oldContent );
603  delete oldContent;
604  d->multipartContents.append( newContent );
605  if( newContent->parent() != this ) {
606  // If the content was part of something else, this will remove it from there.
607  newContent->setParent( this );
608  }
609 }
610 
611 void Content::removeContent( Content *c, bool del )
612 {
613  Q_D( Content );
614  if ( d->multipartContents.isEmpty() || !d->multipartContents.contains( c ) ) {
615  return;
616  }
617 
618  // This method makes no sense for encapsulated messages.
619  // Should be covered by the above assert already, though.
620  Q_ASSERT( !bodyIsMessage() );
621 
622  d->multipartContents.removeAll( c );
623  if ( del ) {
624  delete c;
625  } else {
626  c->d_ptr->parent = 0;
627  }
628 
629  // If only one content is left, turn this content into a single-part.
630  if( d->multipartContents.count() == 1 ) {
631  Content *main = d->multipartContents.first();
632 
633  // Move all headers from the old subcontent to ourselves.
634  // NOTE: This also sets the new Content-Type.
635  foreach( Headers::Base *h, main->h_eaders ) {
636  setHeader( h ); // Will remove the old one if present.
637  }
638  main->h_eaders.clear();
639 
640  // Move the body.
641  d->body = main->body();
642 
643  // Delete the old subcontent.
644  delete main;
645  d->multipartContents.clear();
646  }
647 
648 }
649 
650 void Content::changeEncoding( Headers::contentEncoding e )
651 {
652  // This method makes no sense for encapsulated messages, they are always 7bit
653  // encoded.
654  Q_ASSERT( !bodyIsMessage() );
655 
656  Headers::ContentTransferEncoding *enc = contentTransferEncoding();
657  if( enc->encoding() == e ) {
658  // Nothing to do.
659  return;
660  }
661 
662  if( decodeText() ) {
663  // This is textual content. Textual content is stored decoded.
664  Q_ASSERT( enc->decoded() );
665  enc->setEncoding( e );
666  } else {
667  // This is non-textual content. Re-encode it.
668  if( e == Headers::CEbase64 ) {
669  d_ptr->body = KCodecs::base64Encode( decodedContent(), true );
670  d_ptr->body.append( "\n" );
671  enc->setEncoding( e );
672  enc->setDecoded( false );
673  } else {
674  // It only makes sense to convert binary stuff to base64.
675  Q_ASSERT( false );
676  }
677  }
678 }
679 
680 void Content::toStream( QTextStream &ts, bool scrambleFromLines )
681 {
682  QByteArray ret = encodedContent( false );
683 
684  if ( scrambleFromLines ) {
685  // FIXME Why are only From lines with a preceding empty line considered?
686  // And, of course, all lines starting with >*From have to be escaped
687  // because otherwise the transformation is not revertable.
688  ret.replace( "\n\nFrom ", "\n\n>From ");
689  }
690  ts << ret;
691 }
692 
693 Headers::Generic *Content::getNextHeader( QByteArray &head )
694 {
695  return d_ptr->nextHeader( head );
696 }
697 
698 Headers::Generic *Content::nextHeader( QByteArray &head )
699 {
700  return d_ptr->nextHeader( head );
701 }
702 
703 Headers::Generic *ContentPrivate::nextHeader( QByteArray &_head )
704 {
705  Headers::Base *header = HeaderParsing::extractFirstHeader( _head );
706  if ( !header ) {
707  return 0;
708  }
709  // Convert it from the real class to Generic.
710  Headers::Generic *ret = new Headers::Generic( header->type(), q_ptr );
711  ret->from7BitString( header->as7BitString() );
712  return ret;
713 }
714 
715 Headers::Base *Content::getHeaderByType( const char *type )
716 {
717  return headerByType( type );
718 }
719 
720 Headers::Base *Content::headerByType( const char *type )
721 {
722  Q_ASSERT( type && *type );
723 
724  foreach( Headers::Base *h, h_eaders ) {
725  if( h->is( type ) ) {
726  return h; // Found.
727  }
728  }
729 
730  return 0; // Not found.
731 }
732 
733 Headers::Base::List Content::headersByType( const char *type )
734 {
735  Q_ASSERT( type && *type );
736 
737  Headers::Base::List result;
738 
739  foreach( Headers::Base *h, h_eaders ) {
740  if( h->is( type ) ) {
741  result << h;
742  }
743  }
744 
745  return result;
746 }
747 
748 void Content::setHeader( Headers::Base *h )
749 {
750  Q_ASSERT( h );
751  removeHeader( h->type() );
752  appendHeader( h );
753 }
754 
755 void Content::appendHeader( Headers::Base *h )
756 {
757  h_eaders.append( h );
758  h->setParent( this );
759 }
760 
761 void Content::prependHeader( Headers::Base *h )
762 {
763  h_eaders.prepend( h );
764  h->setParent( this );
765 }
766 
767 bool Content::removeHeader( const char *type )
768 {
769  for ( Headers::Base::List::iterator it = h_eaders.begin();
770  it != h_eaders.end(); ++it )
771  if ( (*it)->is(type) ) {
772  delete (*it);
773  h_eaders.erase( it );
774  return true;
775  }
776 
777  return false;
778 }
779 
780 bool Content::hasHeader( const char *type )
781 {
782  return headerByType( type ) != 0;
783 }
784 
785 int Content::size()
786 {
787  int ret = d_ptr->body.length();
788 
789  if ( contentTransferEncoding()->encoding() == Headers::CEbase64 ) {
790  KMime::Codec *codec = KMime::Codec::codecForName( "base64" );
791  return codec->maxEncodedSizeFor(ret);
792  }
793 
794  // Not handling quoted-printable here since that requires actually
795  // converting the content, and that is O(size_of_content).
796  // For quoted-printable, this is only an approximate size.
797 
798  return ret;
799 }
800 
801 int Content::storageSize() const
802 {
803  const Q_D( Content );
804  int s = d->head.size();
805 
806  if ( d->contents().isEmpty() ) {
807  s += d->body.size();
808  } else {
809 
810  // FIXME: This should take into account the boundary headers that are added in
811  // encodedContent!
812  foreach ( Content *c, d->contents() ) {
813  s += c->storageSize();
814  }
815  }
816 
817  return s;
818 }
819 
820 int Content::lineCount() const
821 {
822  const Q_D( Content );
823  int ret = 0;
824  if ( !isTopLevel() ) {
825  ret += d->head.count( '\n' );
826  }
827  ret += d->body.count( '\n' );
828 
829  foreach ( Content *c, d->contents() ) {
830  ret += c->lineCount();
831  }
832 
833  return ret;
834 }
835 
836 QByteArray Content::rawHeader( const char *name ) const
837 {
838  return KMime::extractHeader( d_ptr->head, name );
839 }
840 
841 QList<QByteArray> Content::rawHeaders( const char *name ) const
842 {
843  return KMime::extractHeaders( d_ptr->head, name );
844 }
845 
846 bool Content::decodeText()
847 {
848  Q_D( Content );
849  Headers::ContentTransferEncoding *enc = contentTransferEncoding();
850 
851  if ( !contentType()->isText() ) {
852  return false; //non textual data cannot be decoded here => use decodedContent() instead
853  }
854  if ( enc->decoded() ) {
855  return true; //nothing to do
856  }
857 
858  switch( enc->encoding() )
859  {
860  case Headers::CEbase64 :
861  d->body = KCodecs::base64Decode( d->body );
862  break;
863  case Headers::CEquPr :
864  d->body = KCodecs::quotedPrintableDecode( d->body );
865  break;
866  case Headers::CEuuenc :
867  d->body = KCodecs::uudecode( d->body );
868  break;
869  case Headers::CEbinary :
870  // nothing to decode
871  default :
872  break;
873  }
874  if (!d->body.endsWith("\n")) {
875  d->body.append( "\n" );
876  }
877  enc->setDecoded( true );
878  return true;
879 }
880 
881 QByteArray Content::defaultCharset() const
882 {
883  return d_ptr->defaultCS;
884 }
885 
886 void Content::setDefaultCharset( const QByteArray &cs )
887 {
888  d_ptr->defaultCS = KMime::cachedCharset( cs );
889 
890  foreach ( Content *c, d_ptr->contents() ) {
891  c->setDefaultCharset( cs );
892  }
893 
894  // reparse the part and its sub-parts in order
895  // to clear cached header values
896  parse();
897 }
898 
899 bool Content::forceDefaultCharset() const
900 {
901  return d_ptr->forceDefaultCS;
902 }
903 
904 void Content::setForceDefaultCharset( bool b )
905 {
906  d_ptr->forceDefaultCS = b;
907 
908  foreach ( Content *c, d_ptr->contents() ) {
909  c->setForceDefaultCharset( b );
910  }
911 
912  // reparse the part and its sub-parts in order
913  // to clear cached header values
914  parse();
915 }
916 
917 Content * KMime::Content::content( const ContentIndex &index ) const
918 {
919  if ( !index.isValid() ) {
920  return const_cast<KMime::Content*>( this );
921  }
922  ContentIndex idx = index;
923  unsigned int i = idx.pop() - 1; // one-based -> zero-based index
924  if ( i < (unsigned int)d_ptr->contents().size() ) {
925  return d_ptr->contents()[i]->content( idx );
926  } else {
927  return 0;
928  }
929 }
930 
931 ContentIndex KMime::Content::indexForContent( Content * content ) const
932 {
933  int i = d_ptr->contents().indexOf( content );
934  if ( i >= 0 ) {
935  ContentIndex ci;
936  ci.push( i + 1 ); // zero-based -> one-based index
937  return ci;
938  }
939  // not found, we need to search recursively
940  for ( int i = 0; i < d_ptr->contents().size(); ++i ) {
941  ContentIndex ci = d_ptr->contents()[i]->indexForContent( content );
942  if ( ci.isValid() ) {
943  // found it
944  ci.push( i + 1 ); // zero-based -> one-based index
945  return ci;
946  }
947  }
948  return ContentIndex(); // not found
949 }
950 
951 bool Content::isTopLevel() const
952 {
953  return d_ptr->parent == 0;
954 }
955 
956 void Content::setParent( Content *parent )
957 {
958  // Make sure the Content is only in the contents list of one parent object
959  Content *oldParent = d_ptr->parent;
960  if ( oldParent ) {
961  if ( !oldParent->contents().isEmpty() && oldParent->contents().contains( this ) ) {
962  oldParent->removeContent( this );
963  }
964  }
965 
966  d_ptr->parent = parent;
967  if ( parent ) {
968  if ( !parent->contents().isEmpty() && !parent->contents().contains( this ) ) {
969  parent->addContent( this );
970  }
971  }
972 }
973 
974 Content *Content::parent() const
975 {
976  return d_ptr->parent;
977 }
978 
979 Content *Content::topLevel() const
980 {
981  Content *top = const_cast<Content*>(this);
982  Content *c = parent();
983  while ( c ) {
984  top = c;
985  c = c->parent();
986  }
987 
988  return top;
989 }
990 
991 ContentIndex Content::index() const
992 {
993  Content* top = topLevel();
994  if ( top ) {
995  return top->indexForContent( const_cast<Content*>(this) );
996  }
997 
998  return indexForContent( const_cast<Content*>(this) );
999 }
1000 
1001 Message::Ptr Content::bodyAsMessage() const
1002 {
1003  if ( bodyIsMessage() && d_ptr->bodyAsMessage ) {
1004  return d_ptr->bodyAsMessage;
1005  } else {
1006  return Message::Ptr();
1007  }
1008 }
1009 
1010 bool Content::bodyIsMessage() const
1011 {
1012  // Use const_case here to work around API issue that neither header() nor hasHeader() are
1013  // const, even though they should be
1014  return const_cast<Content*>( this )->header<Headers::ContentType>( false ) &&
1015  const_cast<Content*>( this )->header<Headers::ContentType>( true )
1016  ->mimeType().toLower() == "message/rfc822";
1017 }
1018 
1019 // @cond PRIVATE
1020 #define kmime_mk_header_accessor( type, method ) \
1021 Headers::type *Content::method( bool create ) { \
1022  return header<Headers::type>( create ); \
1023 }
1024 
1025 kmime_mk_header_accessor( ContentType, contentType )
1026 kmime_mk_header_accessor( ContentTransferEncoding, contentTransferEncoding )
1027 kmime_mk_header_accessor( ContentDisposition, contentDisposition )
1028 kmime_mk_header_accessor( ContentDescription, contentDescription )
1029 kmime_mk_header_accessor( ContentLocation, contentLocation )
1030 kmime_mk_header_accessor( ContentID, contentID )
1031 
1032 #undef kmime_mk_header_accessor
1033 // @endcond
1034 
1035 
1036 void ContentPrivate::clearBodyMessage()
1037 {
1038  bodyAsMessage.reset();
1039 }
1040 
1041 Content::List ContentPrivate::contents() const
1042 {
1043  Q_ASSERT( multipartContents.isEmpty() || !bodyAsMessage );
1044  if ( bodyAsMessage )
1045  return Content::List() << bodyAsMessage.get();
1046  else
1047  return multipartContents;
1048 }
1049 
1050 bool ContentPrivate::parseUuencoded()
1051 {
1052  Q_Q( Content );
1053  Parser::UUEncoded uup( body, KMime::extractHeader( head, "Subject" ) );
1054  if( !uup.parse() ) {
1055  return false; // Parsing failed.
1056  }
1057 
1058  Headers::ContentType *ct = q->contentType();
1059  ct->clear();
1060 
1061  if( uup.isPartial() ) {
1062  // This seems to be only a part of the message, so we treat it as "message/partial".
1063  ct->setMimeType( "message/partial" );
1064  //ct->setId( uniqueString() ); not needed yet
1065  ct->setPartialParams( uup.partialCount(), uup.partialNumber() );
1066  q->contentTransferEncoding()->setEncoding( Headers::CE7Bit );
1067  } else {
1068  // This is a complete message, so treat it as "multipart/mixed".
1069  body.clear();
1070  ct->setMimeType( "multipart/mixed" );
1071  ct->setBoundary( multiPartBoundary() );
1072  ct->setCategory( Headers::CCcontainer );
1073  q->contentTransferEncoding()->clear(); // 7Bit, decoded.
1074 
1075  // Add the plain text part first.
1076  Q_ASSERT( multipartContents.count() == 0 );
1077  {
1078  Content *c = new Content( q );
1079  c->contentType()->setMimeType( "text/plain" );
1080  c->contentTransferEncoding()->setEncoding( Headers::CE7Bit );
1081  c->setBody( uup.textPart() );
1082  multipartContents.append( c );
1083  }
1084 
1085  // Now add each of the binary parts as sub-Contents.
1086  for( int i = 0; i < uup.binaryParts().count(); ++i ) {
1087  Content *c = new Content( q );
1088  c->contentType()->setMimeType( uup.mimeTypes().at( i ) );
1089  c->contentType()->setName( QLatin1String( uup.filenames().at( i ) ), QByteArray( /*charset*/ ) );
1090  c->contentTransferEncoding()->setEncoding( Headers::CEuuenc );
1091  c->contentTransferEncoding()->setDecoded( false );
1092  c->contentDisposition()->setDisposition( Headers::CDattachment );
1093  c->contentDisposition()->setFilename( QLatin1String( uup.filenames().at( i ) ) );
1094  c->setBody( uup.binaryParts().at( i ) );
1095  c->changeEncoding( Headers::CEbase64 ); // Convert to base64.
1096  multipartContents.append( c );
1097  }
1098  }
1099 
1100  return true; // Parsing successful.
1101 }
1102 
1103 bool ContentPrivate::parseYenc()
1104 {
1105  Q_Q( Content );
1106  Parser::YENCEncoded yenc( body );
1107  if ( !yenc.parse() ) {
1108  return false; // Parsing failed.
1109  }
1110 
1111  Headers::ContentType *ct = q->contentType();
1112  ct->clear();
1113 
1114  if ( yenc.isPartial() ) {
1115  // Assume there is exactly one decoded part. Treat this as "message/partial".
1116  ct->setMimeType( "message/partial" );
1117  //ct->setId( uniqueString() ); not needed yet
1118  ct->setPartialParams( yenc.partialCount(), yenc.partialNumber() );
1119  q->contentTransferEncoding()->setEncoding( Headers::CEbinary );
1120  q->changeEncoding( Headers::CEbase64 ); // Convert to base64.
1121  } else {
1122  // This is a complete message, so treat it as "multipart/mixed".
1123  body.clear();
1124  ct->setMimeType( "multipart/mixed" );
1125  ct->setBoundary( multiPartBoundary() );
1126  ct->setCategory( Headers::CCcontainer );
1127  q->contentTransferEncoding()->clear(); // 7Bit, decoded.
1128 
1129  // Add the plain text part first.
1130  Q_ASSERT( multipartContents.count() == 0 );
1131  {
1132  Content *c = new Content( q );
1133  c->contentType()->setMimeType( "text/plain" );
1134  c->contentTransferEncoding()->setEncoding( Headers::CE7Bit );
1135  c->setBody( yenc.textPart() );
1136  multipartContents.append( c );
1137  }
1138 
1139  // Now add each of the binary parts as sub-Contents.
1140  for ( int i=0; i<yenc.binaryParts().count(); i++ ) {
1141  Content *c = new Content( q );
1142  c->contentType()->setMimeType( yenc.mimeTypes().at( i ) );
1143  c->contentType()->setName( QLatin1String( yenc.filenames().at( i ) ), QByteArray( /*charset*/ ) );
1144  c->contentTransferEncoding()->setEncoding( Headers::CEbinary );
1145  c->contentDisposition()->setDisposition( Headers::CDattachment );
1146  c->contentDisposition()->setFilename( QLatin1String( yenc.filenames().at( i ) ) );
1147  c->setBody( yenc.binaryParts().at( i ) ); // Yenc bodies are binary.
1148  c->changeEncoding( Headers::CEbase64 ); // Convert to base64.
1149  multipartContents.append( c );
1150  }
1151  }
1152 
1153  return true; // Parsing successful.
1154 }
1155 
1156 bool ContentPrivate::parseMultipart()
1157 {
1158  Q_Q( Content );
1159  const Headers::ContentType *ct = q->contentType();
1160  const QByteArray boundary = ct->boundary();
1161  if ( boundary.isEmpty() ) {
1162  return false; // Parsing failed; invalid multipart content.
1163  }
1164  Parser::MultiPart mpp( body, boundary );
1165  if ( !mpp.parse() ) {
1166  return false; // Parsing failed.
1167  }
1168 
1169  preamble = mpp.preamble();
1170  epilogue = mpp.epilouge();
1171 
1172  // Determine the category of the subparts (used in attachments()).
1173  Headers::contentCategory cat;
1174  if ( ct->isSubtype( "alternative" ) ) {
1175  cat = Headers::CCalternativePart;
1176  } else {
1177  cat = Headers::CCmixedPart; // Default to "mixed".
1178  }
1179 
1180  // Create a sub-Content for every part.
1181  Q_ASSERT( multipartContents.isEmpty() );
1182  body.clear();
1183  QList<QByteArray> parts = mpp.parts();
1184  foreach ( const QByteArray &part, mpp.parts() ) {
1185  Content *c = new Content( q );
1186  c->setContent( part );
1187  c->setFrozen( frozen );
1188  c->parse();
1189  c->contentType()->setCategory( cat );
1190  multipartContents.append( c );
1191  }
1192 
1193  return true; // Parsing successful.
1194 }
1195 
1196 } // namespace KMime
kmime_codecs.h
This file is part of the API for handling MIME data and defines the Codec class.
QTextStream::setCodec
void setCodec(QTextCodec *codec)
KMime::Content::addContent
void addContent(Content *content, bool prepend=false)
Adds a new sub-Content.
Definition: kmime_content.cpp:537
QList::clear
void clear()
KMime::Headers::Base::as7BitString
virtual QByteArray as7BitString(bool withHeaderType=true) const =0
Returns the encoded header.
QTextCodec::fromUnicode
QByteArray fromUnicode(const QString &str) const
KMime::Headers::ContentTransferEncoding::encoding
contentEncoding encoding() const
Returns the encoding specified in this header.
Definition: kmime_headers.cpp:2088
KMime::Content::encodedBody
QByteArray encodedBody()
Like encodedContent(), with the difference that only the body will be returned, i.e.
Definition: kmime_content.cpp:322
KMime::Content::assembleHeaders
virtual QByteArray assembleHeaders()
Reimplement this method if you need to assemble additional headers in a derived class.
Definition: kmime_content.cpp:267
QString::truncate
void truncate(int position)
KMime::Headers::ContentType::isMultipart
bool isMultipart() const
Returns true if the associated MIME entity is a mulitpart container.
Definition: kmime_headers.cpp:1824
kmime_content.h
This file is part of the API for handling MIME data and defines the Content class.
KMime::Content::contents
List contents() const
For multipart contents, this will return a list of all multipart child contents.
Definition: kmime_content.cpp:532
KMime::Content::defaultCharset
QByteArray defaultCharset() const
Returns the charset that is used to decode RFC2047 strings in all headers and to decode the body if t...
Definition: kmime_content.cpp:881
KMime::Headers::ContentType::isText
bool isText() const
Returns true if the associated MIME entity is a text.
Definition: kmime_headers.cpp:1804
QByteArray
KMime::Parser::UUEncoded
Helper-class: tries to extract the data from a possibly uuencoded message.
Definition: kmime_parsers.h:97
KMime::Headers::ContentType::setMimeType
void setMimeType(const QByteArray &mimeType)
Sets the mimetype and clears already existing parameters.
Definition: kmime_headers.cpp:1771
KMime::Content::setEpilogue
void setEpilogue(const QByteArray &epilogue)
Sets the MIME preamble.
Definition: kmime_content.cpp:179
KMime::Content::List
QList< KMime::Content * > List
Describes a list of Content objects.
Definition: kmime_content.h:119
KMime::Content::setForceDefaultCharset
virtual void setForceDefaultCharset(bool b)
Enables/disables the force mode, housekeeping.
Definition: kmime_content.cpp:904
KMime::Content::setHeader
virtual void setHeader(Headers::Base *h)
Sets the specified header to this Content.
Definition: kmime_content.cpp:748
KMime::Content::isFrozen
bool isFrozen() const
Returns whether this Content is frozen.
Definition: kmime_content.cpp:244
KMime::Codec::maxDecodedSizeFor
virtual int maxDecodedSizeFor(int insize, bool withCRLF=false) const =0
Computes the maximum size, in characters, needed for the deccoding.
KMime::Content::setFrozen
void setFrozen(bool frozen=true)
Freezes this Content if frozen is true; otherwise unfreezes it.
Definition: kmime_content.cpp:249
KMime::Content::rawHeaders
KMIME_DEPRECATED QList< QByteArray > rawHeaders(const char *name) const
Returns a list of raw strings representing all header of type name.
Definition: kmime_content.cpp:841
QByteArray::isEmpty
bool isEmpty() const
KMime::Content::hasHeader
bool hasHeader(const char *type)
Definition: kmime_content.cpp:780
KMime::ContentIndex::isValid
bool isValid() const
Returns true if this index is non-empty (valid).
Definition: kmime_contentindex.cpp:76
KMime::ContentIndex::pop
unsigned int pop()
Removes and returns the top-most index.
Definition: kmime_contentindex.cpp:81
KMime::Headers::ContentType::setCharset
void setCharset(const QByteArray &s)
Sets the charset.
Definition: kmime_headers.cpp:1844
QByteArray::startsWith
bool startsWith(const QByteArray &ba) const
KMime::Content::nextHeader
KMIME_DEPRECATED Headers::Generic * nextHeader(QByteArray &head)
Extracts and removes the next header from head.
Definition: kmime_content.cpp:698
KMime::ContentIndex::push
void push(unsigned int index)
Adds index to the content index.
Definition: kmime_contentindex.cpp:86
KMime::Content::setHead
void setHead(const QByteArray &head)
Sets the Content header raw data.
Definition: kmime_content.cpp:145
KMime::Content::body
QByteArray body() const
Returns the Content body raw data.
Definition: kmime_content.cpp:153
QList::erase
iterator erase(iterator pos)
KMime::Content::index
ContentIndex index() const
Returns the index of this Content based on the topLevel() object.
Definition: kmime_content.cpp:991
KMime::Content::setContent
void setContent(const QList< QByteArray > &l)
Sets the Content to the given raw data, containing the Content head and body separated by two linefee...
Definition: kmime_content.cpp:105
KMime::Content::contentDisposition
Headers::ContentDisposition * contentDisposition(bool create=true)
Returns the Content-Disposition header.
KMime::Headers::ContentType::isSubtype
bool isSubtype(const char *subtype) const
Tests if the mime sub-type equals subtype.
Definition: kmime_headers.cpp:1792
KMime::Content::encodedContent
QByteArray encodedContent(bool useCrLf=false)
Returns a QByteArray containing the encoded Content, including the Content header and all sub-Content...
Definition: kmime_content.cpp:299
KMime::Headers::ContentType::setName
void setName(const QString &s, const QByteArray &cs)
Sets the name to s using charset cs.
Definition: kmime_headers.cpp:1864
KMime::Content::decodedText
QString decodedText(bool trimText=false, bool removeTrailingNewlines=false)
Returns the decoded text.
Definition: kmime_content.cpp:433
KMime::Headers::ContentDisposition::setDisposition
void setDisposition(contentDisposition disp)
Sets the content disposition.
Definition: kmime_headers.cpp:2195
QTextStream
KMime::Codec::maxEncodedSizeFor
virtual int maxEncodedSizeFor(int insize, bool withCRLF=false) const =0
Computes the maximum size, in characters, needed for the encoding.
QByteArray::resize
void resize(int size)
KMime::Content::hasContent
bool hasContent() const
Returns true if this Content object is not empty.
Definition: kmime_content.cpp:100
KMime::Headers::ContentTransferEncoding::clear
virtual void clear()
Deletes.
Definition: kmime_headers.cpp:2080
KMime::Headers::ContentTransferEncoding::setDecoded
void setDecoded(bool decoded=true)
Set whether the Content containing this header is already decoded.
Definition: kmime_headers.cpp:2111
KMime::Content::decodedContent
QByteArray decodedContent()
Returns the decoded Content body.
Definition: kmime_content.cpp:381
KMime::Content::size
int size()
Returns the size of the Content body after encoding.
Definition: kmime_content.cpp:785
QList::append
void append(const T &value)
KMime::Headers::Generic
Represents an arbitrary header, that can contain any header-field.
Definition: kmime_headers.h:1239
KMime::Content::content
Content * content(const ContentIndex &index) const
Returns the Content specified by the given index.
Definition: kmime_content.cpp:917
KMime::Content::parse
virtual void parse()
Parses the Content.
Definition: kmime_content.cpp:184
KMime::Content::rawHeader
KMIME_DEPRECATED QByteArray rawHeader(const char *name) const
Returns the raw string representing the header of type name.
Definition: kmime_content.cpp:836
KMime::Codec
An abstract base class of codecs for common mail transfer encodings.
Definition: kmime_codecs.h:83
KMime::Content::fromUnicodeString
void fromUnicodeString(const QString &s)
Sets the Content body to the given string using charset of the content type.
Definition: kmime_content.cpp:474
KMime::Headers::Base
Baseclass of all header-classes.
Definition: kmime_headers.h:124
KMime::Headers::ContentTransferEncoding::decoded
bool decoded() const
Returns whether the Content containing this header is already decoded.
Definition: kmime_headers.cpp:2106
KMime::Decoder
Stateful CTE decoder class.
Definition: kmime_codecs.h:341
QList::isEmpty
bool isEmpty() const
KMime::Codec::codecForName
static Codec * codecForName(const char *name)
Returns a codec associated with the specified name.
Definition: kmime_codecs.cpp:82
KMime::Content::setPreamble
void setPreamble(const QByteArray &preamble)
Sets the MIME preamble.
Definition: kmime_content.cpp:168
QList::removeAll
int removeAll(const T &value)
KMime::Content::setBody
void setBody(const QByteArray &body)
Sets the Content body raw data.
Definition: kmime_content.cpp:158
KMime::Headers::Base::setParent
void setParent(KMime::Content *parent)
Sets the parent for this header to parent.
Definition: kmime_headers.cpp:173
QByteArray::replace
QByteArray & replace(int pos, int len, const char *after)
KMime::Parser::MultiPart
Helper-class: splits a multipart-message into single parts as described in RFC 2046.
Definition: kmime_parsers.h:37
KMime::Content::~Content
virtual ~Content()
Destroys this Content object.
Definition: kmime_content.cpp:92
KMime::Codec::makeDecoder
virtual Decoder * makeDecoder(bool withCRLF=false) const =0
Creates the decoder for the codec.
QByteArray::truncate
void truncate(int pos)
KMime::Headers::Generics::Unstructured::from7BitString
virtual void from7BitString(const QByteArray &s)
Parses the given string.
Definition: kmime_headers.cpp:255
KMime::Headers::ContentType::setPartialParams
void setPartialParams(int total, int number)
Sets parameters of a partial MIME entity.
Definition: kmime_headers.cpp:1912
KMime::Message::Ptr
boost::shared_ptr< Message > Ptr
A shared pointer to a message object.
Definition: kmime_message.h:92
QString
QList< QByteArray >
KMime::Content::decodeText
bool decodeText()
Returns whether this object holds text content.
Definition: kmime_content.cpp:846
QTextCodec
KMime::Content::bodyIsMessage
bool bodyIsMessage() const
Definition: kmime_content.cpp:1010
KMime::Content::contentTransferEncoding
Headers::ContentTransferEncoding * contentTransferEncoding(bool create=true)
Returns the Content-Transfer-Encoding header.
QList::iterator
KMime::Headers::ContentType::setBoundary
void setBoundary(const QByteArray &s)
Sets the mulitpart container boundary.
Definition: kmime_headers.cpp:1854
KMime::Content::isTopLevel
virtual bool isTopLevel() const
Returns true if this is the top-level node in the MIME tree.
Definition: kmime_content.cpp:951
KMime::Content::assemble
virtual void assemble()
Generates the MIME content.
Definition: kmime_content.cpp:254
QString::right
QString right(int n) const
KMime::Headers::Base::isEmpty
virtual bool isEmpty() const =0
Checks if this header contains any data.
KMime::Content::contentType
Headers::ContentType * contentType(bool create=true)
Returns the Content-Type header.
KMime::Content::forceDefaultCharset
bool forceDefaultCharset() const
Use the default charset even if a different charset is declared in the article.
Definition: kmime_content.cpp:899
KMime::Content::changeEncoding
void changeEncoding(Headers::contentEncoding e)
Changes the encoding of this Content to e.
Definition: kmime_content.cpp:650
QList::end
iterator end()
KMime::Content::toStream
void toStream(QTextStream &ts, bool scrambleFromLines=false)
Saves the encoded Content to the given textstream.
Definition: kmime_content.cpp:680
KMime::Headers::Base::is
bool is(const char *t) const
Checks if this header is of type t.
Definition: kmime_headers.cpp:207
QLatin1Char
KMime::Content::storageSize
int storageSize() const
Returns the size of this Content and all sub-Contents.
Definition: kmime_content.cpp:801
QList::contains
bool contains(const T &value) const
KMime::Content::preamble
QByteArray preamble() const
Returns the MIME preamble.
Definition: kmime_content.cpp:163
KMime::Content::epilogue
QByteArray epilogue() const
Returns the MIME preamble.
Definition: kmime_content.cpp:174
KMime::Content::topLevel
Content * topLevel() const
Returns the toplevel content object, 0 if there is no such object.
Definition: kmime_content.cpp:979
KMime::Content::head
QByteArray head() const
Returns the Content header raw data.
Definition: kmime_content.cpp:140
KMime::Content::getNextHeader
KMIME_DEPRECATED Headers::Generic * getNextHeader(QByteArray &head)
Extracts and removes the next header from head.
Definition: kmime_content.cpp:693
KMime::Content::Content
Content()
Creates an empty Content object.
Definition: kmime_content.cpp:61
KMime::Message
Represents a (email) message.
Definition: kmime_message.h:81
KMime::Content::removeContent
void removeContent(Content *content, bool del=false)
Removes the given sub-Content.
Definition: kmime_content.cpp:611
KMime::Content::h_eaders
Headers::Base::List h_eaders
The list of headers in this Content.
Definition: kmime_content.h:816
KMime::Headers::ContentType::boundary
QByteArray boundary() const
Returns the boundary (for mulitpart containers).
Definition: kmime_headers.cpp:1849
KMime::Content::setDefaultCharset
void setDefaultCharset(const QByteArray &cs)
Sets the default charset.
Definition: kmime_content.cpp:886
KMime::Decoder::decode
virtual bool decode(const char *&scursor, const char *const send, char *&dcursor, const char *const dend)=0
Decodes a chunk of data, maintaining state information between calls.
KMime::Headers::ContentTransferEncoding::needToEncode
bool needToEncode() const
Returns whether the Content containing this header needs to be encoded (i.e., if decoded() is true an...
Definition: kmime_headers.cpp:2117
KMime::Content::removeHeader
virtual bool removeHeader(const char *type)
Searches for the first header of type type, and deletes it, removing it from this Content...
Definition: kmime_content.cpp:767
QLatin1String
KMime::Content::setParent
void setParent(Content *parent)
Sets a new parent to the Content and add to its contents list.
Definition: kmime_content.cpp:956
KMime::Content::bodyAsMessage
boost::shared_ptr< Message > bodyAsMessage() const
If this content is an encapsulated message, in which case bodyIsMessage() will return true...
Definition: kmime_content.cpp:1001
KMime::Content::clear
virtual void clear()
Clears the content, deleting all headers and sub-Contents.
Definition: kmime_content.cpp:279
KMime::Content::attachments
List attachments(bool incAlternatives=false)
Returns a list of attachments.
Definition: kmime_content.cpp:507
KMime::Content::textContent
Content * textContent()
Returns the first Content with mimetype text/.
Definition: kmime_content.cpp:490
QTextCodec::codecForName
QTextCodec * codecForName(const QByteArray &name)
KMime::Content::indexForContent
ContentIndex indexForContent(Content *content) const
Returns the ContentIndex for the given Content, or an invalid index if the Content is not found withi...
Definition: kmime_content.cpp:931
KMime::Parser::YENCEncoded
Helper-class: tries to extract the data from a possibly yenc encoded message.
Definition: kmime_parsers.h:112
QString::length
int length() const
KMime::Content
A class that encapsulates MIME encoded Content.
Definition: kmime_content.h:112
KMime::Headers::ContentTransferEncoding::setEncoding
void setEncoding(contentEncoding e)
Sets the encoding to e.
Definition: kmime_headers.cpp:2093
KMime::Content::prependHeader
void prependHeader(Headers::Base *h)
Prepends the specified header to the headers of this Content.
Definition: kmime_content.cpp:761
KMime::Content::appendHeader
void appendHeader(Headers::Base *h)
Appends the specified header to the headers of this Content.
Definition: kmime_content.cpp:755
KMime::Content::parent
Content * parent() const
Returns the parent content object, or 0 if the content doesn't have a parent.
Definition: kmime_content.cpp:974
QList::prepend
void prepend(const T &value)
KMime::Content::getHeaderByType
virtual KMIME_DEPRECATED Headers::Base * getHeaderByType(const char *type)
Tries to find a type header in the Content and returns it.
Definition: kmime_content.cpp:715
KMime::Content::headersByType
virtual QList< Headers::Base * > headersByType(const char *type)
Returns all type headers in the Content.
Definition: kmime_content.cpp:733
KMime::Headers::ContentTransferEncoding
Represents a "Content-Transfer-Encoding" header.
Definition: kmime_headers.h:890
QByteArray::size
int size() const
KMime::Headers::ContentType::clear
virtual void clear()
Deletes.
Definition: kmime_headers.cpp:1716
KMime::Content::clearContents
void clearContents(bool del=true)
Removes all sub-Contents from this content.
Definition: kmime_content.cpp:289
KMime::Headers::ContentType
Represents a "Content-Type" header.
Definition: kmime_headers.h:1031
KMime::Headers::Base::type
virtual const char * type() const
Returns the type of this header (e.g.
Definition: kmime_headers.cpp:202
QList::begin
iterator begin()
QByteArray::endsWith
bool endsWith(const QByteArray &ba) const
QTextCodec::toUnicode
QString toUnicode(const QByteArray &a) const
KMime::Content::lineCount
int lineCount() const
Line count of this Content and all sub-Contents.
Definition: kmime_content.cpp:820
KMime::Headers::ContentDisposition::setFilename
void setFilename(const QString &filename)
Sets the suggested filename for the associated MIME part.
Definition: kmime_headers.cpp:2206
KMime::ContentIndex
A class to uniquely identify message parts (Content) in a hierarchy.
Definition: kmime_contentindex.h:54
KMime::Content::headerByType
virtual Headers::Base * headerByType(const char *type)
Returns the first header of type type, if it exists.
Definition: kmime_content.cpp:720
This file is part of the KDE documentation.
Documentation copyright © 1996-2020 The KDE developers.
Generated on Mon Jun 22 2020 13:37:18 by doxygen 1.8.7 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.

KMIME Library

Skip menu "KMIME Library"
  • Main Page
  • Alphabetical List
  • Class List
  • Class Hierarchy
  • Class Members
  • File List
  • Related Pages

kdepimlibs API Reference

Skip menu "kdepimlibs API Reference"
  • akonadi
  •   contact
  •   kmime
  •   socialutils
  • kabc
  • kalarmcal
  • kblog
  • kcal
  • kcalcore
  • kcalutils
  • kholidays
  • kimap
  • kioslave
  •   imap4
  •   mbox
  •   nntp
  • kldap
  • kmbox
  • kmime
  • kontactinterface
  • kpimidentities
  • kpimtextedit
  • kpimutils
  • kresources
  • ktnef
  • kxmlrpcclient
  • mailtransport
  • microblog
  • qgpgme
  • syndication
  •   atom
  •   rdf
  •   rss2

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