1/*
2 kmime_content.h
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*/
25/**
26 @file
27 This file is part of the API for handling @ref MIME data and
28 defines the Content class.
29
30 @brief
31 Defines the Content class.
32
33 @authors the KMime authors (see AUTHORS file),
34 Volker Krause \<vkrause@kde.org\>
35
36TODO: possible glossary terms:
37 content
38 encoding, transfer type, disposition, description
39 header
40 body
41 attachment
42 charset
43 article
44 string representation
45 broken-down object representation
46*/
47
48#ifndef __KMIME_CONTENT_H__
49#define __KMIME_CONTENT_H__
50
51#include "kmime_export.h"
52#include "kmime_contentindex.h"
53#include "kmime_util.h"
54#include "kmime_headers.h"
55
56#include <QtCore/QTextStream>
57#include <QtCore/QByteArray>
58#include <QtCore/QList>
59
60#include <boost/shared_ptr.hpp>
61
62
63namespace KMime {
64
65class ContentPrivate;
66class Message;
67
68/**
69 @brief
70 A class that encapsulates @ref MIME encoded Content.
71
72 A Content object holds two representations of a content:
73 - the string representation: This is the content encoded as a string ready
74 for transport. Accessible through the encodedContent() method.
75 - the broken-down representation: This is the tree of objects (headers,
76 sub-Contents and (if present) the encapsulated message) that this Content is made of.
77 Accessible through methods like header(), contents() and bodyAsMessage().
78
79 The parse() function updates the broken-down representation of the Content
80 from its string representation. Calling it is necessary to access the
81 headers, sub-Contents or the encapsulated message of this Content.
82
83 The assemble() function updates the string representation of the Content
84 from its broken-down representation. Calling it is necessary for
85 encodedContent() to reflect any changes made to the broken-down representation of the Content.
86
87 There are two basic types of a Content:
88 - A leaf Content: This is a content that is neither a multipart content nor an encapsulated
89 message. Because of this, it will not have any children, it has no sub-contents
90 and is therefore a leaf content.
91 Only leaf contents have a body that is not empty, i.e. functions that operate
92 on the body, such as body(), size() and decodedContent(), will work only on
93 leaf contents.
94 - A non-leaf Content: This is a content that itself doesn't have any body, but that does have
95 sub-contents.
96 This is the case for contents that are of mimetype multipart/ or of mimetype
97 message/rfc822. In case of a multipart content, contents() will return the
98 multipart child contents. In case of an encapsulated message, the message
99 can be accessed with bodyAsMessage(), and contents() will have one entry
100 that is the message as well.
101 On a non-leaf content, body() will have an empty return value and other
102 functions working on the body will not work.
103 A call to parse() is required before the child multipart contents or the
104 encapsulated message is created.
105*/
106/*
107 KDE5:
108 * Do not convert singlepart <-> multipart automatically.
109 * A bunch of methods probably don't need to be virtual (since they're not needed
110 in either Message or NewsArticle).
111*/
112class KMIME_EXPORT Content
113{
114 public:
115
116 /**
117 Describes a list of Content objects.
118 */
119 typedef QList<KMime::Content*> List;
120
121 /**
122 Creates an empty Content object.
123 */
124 Content();
125
126 /**
127 Creates an empty Content object with a specified parent.
128 @param parent the parent Content object
129 @since 4.3
130 */
131 explicit Content( Content* parent ); // KDE5: Merge with the above.
132
133 /**
134 Creates a Content object containing the given raw data.
135
136 @param head is a QByteArray containing the header data.
137 @param body is a QByteArray containing the body data.
138 */
139 Content( const QByteArray &head, const QByteArray &body );
140
141 /**
142 Creates a Content object containing the given raw data.
143
144 @param head is a QByteArray containing the header data.
145 @param body is a QByteArray containing the body data.
146 @param parent the parent Content object
147 @since 4.3
148 */
149 // KDE5: Merge with the above.
150 Content( const QByteArray &head, const QByteArray &body, Content *parent );
151
152 /**
153 Destroys this Content object.
154 */
155 virtual ~Content();
156
157 /**
158 Returns true if this Content object is not empty.
159 */
160 bool hasContent() const;
161
162 /**
163 Sets the Content to the given raw data, containing the Content head and
164 body separated by two linefeeds.
165
166 This method operates on the string representation of the Content. Call
167 parse() if you want to access individual headers, sub-Contents or the
168 encapsulated message.
169
170 @param l is a list of the raw Content data, split by lines.
171 */
172 void setContent( const QList<QByteArray> &l );
173
174 /**
175 Sets the Content to the given raw data, containing the Content head and
176 body separated by two linefeeds.
177
178 This method operates on the string representation of the Content. Call
179 parse() if you want to access individual headers, sub-Contents or the
180 encapsulated message.
181
182 @note The passed data must not contain any CRLF sequences, only LF.
183 Use CRLFtoLF for conversion before passing in the data.
184
185 @param s is a QByteArray containing the raw Content data.
186 */
187 void setContent( const QByteArray &s );
188
189 /**
190 * Parses the Content.
191 *
192 * This means the broken-down object representation of the Content is
193 * updated from the string representation of the Content.
194 *
195 * Call this if you want to access or change headers, sub-Contents or the encapsulated
196 * message.
197 *
198 * @note Calling parse() twice will not work for multipart contents or for contents of which
199 * the body is an encapsulated message. The reason is that the first parse() will delete
200 * the body, so there is no body to work on for the second call of parse().
201 *
202 * @note Calling this will reset the message returned by bodyAsMessage(), as
203 * the message is re-parsed as well.
204 * Also, all old sub-contents will be deleted, so any old Content pointer will become
205 * invalid.
206 */
207 virtual void parse();
208
209 /**
210 Returns whether this Content is frozen.
211 A frozen content is immutable, i.e. calling assemble() will never modify
212 its head or body, and encodedContent() will return the same data before
213 and after parsing.
214
215 @since 4.4.
216 @see setFrozen().
217 */
218 bool isFrozen() const;
219
220 /**
221 Freezes this Content if @p frozen is true; otherwise unfreezes it.
222 @param frozen freeze content if @c true, otherwise unfreeze
223 @since 4.4
224 @see isFrozen().
225 */
226 void setFrozen( bool frozen = true );
227
228 /**
229 Generates the MIME content.
230 This means the string representation of this Content is updated from the
231 broken-down object representation.
232 Call this if you have made changes to the content, and want
233 encodedContent() to reflect those changes.
234
235 @note assemble() has no effect if the Content isFrozen(). You may want
236 to freeze, for instance, signed sub-Contents, to make sure they are kept
237 unmodified.
238
239 @note If this content is an encapsulated message, i.e. bodyIsMessage() returns true,
240 then calling assemble() will also assemble the message returned by bodyAsMessage().
241
242 @warning assemble() may change the order of the headers, and other
243 details such as where folding occurs. This may break things like
244 signature verification, so you should *ONLY* call assemble() when you
245 have actually modified the content.
246 */
247 virtual void assemble();
248
249 /**
250 Clears the content, deleting all headers and sub-Contents.
251 */
252 // KDE5: make non-virtual.
253 virtual void clear();
254
255 /**
256 Removes all sub-Contents from this content. Deletes them if @p del is true.
257 This is different from calling removeContent() on each sub-Content, because
258 removeContent() will convert this to a single-part Content if only one
259 sub-Content is left. Calling clearContents() does NOT make this Content
260 single-part.
261
262 @param del Whether to delete the sub-Contents.
263 @see removeContent()
264 @since 4.4
265 */
266 void clearContents( bool del = true );
267
268 /**
269 Returns the Content header raw data.
270
271 @see setHead().
272 */
273 QByteArray head() const;
274
275 /**
276 Sets the Content header raw data.
277
278 This method operates on the string representation of the Content. Call
279 parse() if you want to access individual headers.
280
281 @param head is a QByteArray containing the header data.
282
283 @see head().
284 */
285 void setHead( const QByteArray &head );
286
287 /**
288 Extracts and removes the next header from @p head.
289 The caller is responsible for deleting the returned header.
290
291 @deprecated Use KMime::HeaderParsing::extractFirstHeader().
292 @param head is a QByteArray containing the header data.
293 */
294 KMIME_DEPRECATED Headers::Generic *getNextHeader( QByteArray &head );
295
296 /**
297 Extracts and removes the next header from @p head.
298 The caller is responsible for deleting the returned header.
299 @since 4.2
300 @deprecated Use KMime::HeaderParsing::extractFirstHeader().
301 @param head is a QByteArray containing the header data.
302 */
303 // KDE5: Remove this. This method has nothing to do with *this object.
304 KMIME_DEPRECATED Headers::Generic *nextHeader( QByteArray &head );
305
306 /**
307 Tries to find a @p type header in the Content and returns it.
308 @param type the header type to find
309 @deprecated Use headerByType( const char * )
310 */
311 // KDE5: Make non-virtual.
312 KMIME_DEPRECATED virtual Headers::Base *getHeaderByType( const char *type );
313
314 /**
315 Returns the first header of type @p type, if it exists. Otherwise returns 0.
316 Note that the returned header may be empty.
317 @param type the header type to find
318 @since 4.2
319 */
320 // KDE5: Make non-virtual.
321 virtual Headers::Base *headerByType( const char *type );
322
323 /**
324 Returns the first header of type T, if it exists.
325 If the header does not exist and @p create is true, creates an empty header
326 and returns it. Otherwise returns 0.
327 Note that the returned header may be empty.
328 @param create Whether to create the header if it does not exist.
329 @since 4.4.
330
331 KDE5: BIC: FIXME: Why is the default argument false here? That is inconsistent with the
332 methods in KMime::Message!
333 */
334 template <typename T> T *header( bool create = false );
335
336 /**
337 Returns all @p type headers in the Content.
338 Take care that this result is not cached, so could be slow.
339 @param type the header type to find
340 @since 4.2
341 */
342 virtual QList<Headers::Base*> headersByType( const char *type );
343
344 /**
345 Sets the specified header to this Content.
346 Any previous header of the same type is removed.
347 If you need multiple headers of the same type, use appendHeader() or
348 prependHeader().
349
350 @param h The header to set.
351 @see appendHeader()
352 @see removeHeader()
353 @since 4.4
354 */
355 // KDE5: make non-virtual.
356 virtual void setHeader( Headers::Base *h );
357
358 /**
359 Appends the specified header to the headers of this Content.
360 @param h The header to append.
361 @since 4.4
362 */
363 void appendHeader( Headers::Base *h );
364
365 /**
366 Prepends the specified header to the headers of this Content.
367 @param h The header to prepend.
368 @since 4.4
369 */
370 void prependHeader( Headers::Base *h );
371
372 /**
373 Searches for the first header of type @p type, and deletes it, removing
374 it from this Content.
375 @param type The type of the header to look for.
376 @return true if a header was found and removed.
377 */
378 // TODO probably provide removeHeader<T>() too.
379 // KDE5: make non-virtual.
380 virtual bool removeHeader( const char *type );
381
382 /**
383 @return true if this Content has a header of type @p type.
384 @param type The type of the header to look for.
385 */
386 // TODO probably provide hasHeader<T>() too.
387 // TODO: KDE5: make const
388 bool hasHeader( const char *type );
389
390 /**
391 Returns the Content-Type header.
392
393 @param create If true, create the header if it doesn't exist yet.
394 */
395 Headers::ContentType *contentType( bool create = true );
396
397 /**
398 Returns the Content-Transfer-Encoding header.
399
400 @param create If true, create the header if it doesn't exist yet.
401 */
402 Headers::ContentTransferEncoding *contentTransferEncoding( bool create = true );
403
404 /**
405 Returns the Content-Disposition header.
406
407 @param create If true, create the header if it doesn't exist yet.
408 */
409 Headers::ContentDisposition *contentDisposition( bool create = true );
410
411 /**
412 Returns the Content-Description header.
413
414 @param create If true, create the header if it doesn't exist yet.
415 */
416 Headers::ContentDescription *contentDescription( bool create = true );
417
418 /**
419 Returns the Content-Location header.
420
421 @param create If true, create the header if it doesn't exist yet.
422 @since 4.2
423 */
424 Headers::ContentLocation *contentLocation( bool create = true );
425
426 /**
427 Returns the Content-ID header.
428 @param create if true, create the header if it does not exist yet.
429 @since 4.4
430 */
431 Headers::ContentID *contentID( bool create = true );
432
433 /**
434 Returns the size of the Content body after encoding.
435 (If the encoding is quoted-printable, this is only an approximate size.)
436 This will return 0 for multipart contents or for encapsulated messages.
437 */
438 int size();
439
440 /**
441 Returns the size of this Content and all sub-Contents.
442 */
443 int storageSize() const;
444
445 /**
446 Line count of this Content and all sub-Contents.
447 */
448 int lineCount() const;
449
450 /**
451 Returns the Content body raw data.
452
453 Note that this will be empty for multipart contents or for encapsulated messages,
454 after parse() has been called.
455
456 @see setBody().
457 */
458 QByteArray body() const;
459
460 /**
461 Sets the Content body raw data.
462
463 This method operates on the string representation of the Content. Call
464 parse() if you want to access individual sub-Contents or the encapsulated message.
465
466 @param body is a QByteArray containing the body data.
467
468 @see body().
469 */
470 void setBody( const QByteArray &body );
471
472 /**
473 Returns the MIME preamble.
474
475 @return a QByteArray containing the MIME preamble.
476
477 @since 4.9
478 */
479 QByteArray preamble() const;
480
481 /**
482 Sets the MIME preamble.
483
484 @param preamble a QByteArray containing what will be used as the
485 MIME preamble.
486
487 @since 4.9
488 */
489
490 void setPreamble( const QByteArray &preamble );
491
492 /**
493 Returns the MIME preamble.
494
495 @return a QByteArray containing the MIME epilogue.
496
497 @since 4.9
498 */
499 QByteArray epilogue() const;
500
501 /**
502 Sets the MIME preamble.
503
504 @param epilogue a QByteArray containing what will be used as the
505 MIME epilogue.
506
507 @since 4.9
508 */
509 void setEpilogue( const QByteArray &epilogue );
510
511 /**
512 Returns a QByteArray containing the encoded Content, including the
513 Content header and all sub-Contents.
514
515 If you make changes to the broken-down representation of the message, be
516 sure to first call assemble() before calling encodedContent(), otherwise
517 the result will not be up-to-date.
518
519 If this content is an encapsulated message, i.e. bodyIsMessage() returns true,
520 then encodedContent() will use the message returned by bodyAsMessage() as the
521 body of the result, calling encodedContent() on the message.
522
523 @param useCrLf If true, use @ref CRLF instead of @ref LF for linefeeds.
524 */
525 QByteArray encodedContent( bool useCrLf = false );
526
527 /**
528 * Like encodedContent(), with the difference that only the body will be returned, i.e. the
529 * headers are excluded.
530 *
531 * @since 4.6
532 */
533 QByteArray encodedBody();
534
535 /**
536 * Returns the decoded Content body.
537 *
538 * Note that this will be empty for multipart contents or for encapsulated messages,
539 * after parse() has been called.
540 */
541 // TODO: KDE5: BIC: Rename this to decodedBody(), since only the body is returned.
542 // In contrast, setContent() sets the head and the body!
543 // Also, try to make this const.
544 QByteArray decodedContent();
545
546 /**
547 Returns the decoded text. Additional to decodedContent(), this also
548 applies charset decoding. If this is not a text Content, decodedText()
549 returns an empty QString.
550
551 @param trimText If true, then the decoded text will have all trailing
552 whitespace removed.
553 @param removeTrailingNewlines If true, then the decoded text will have
554 all consecutive trailing newlines removed.
555
556 The last trailing new line of the decoded text is always removed.
557
558 */
559 // TODO: KDE5: BIC: Convert to enums. Also, what if trimText = true but removeTrailingNewlines
560 // is false?
561 QString decodedText( bool trimText = false,
562 bool removeTrailingNewlines = false );
563
564 /**
565 Sets the Content body to the given string using charset of the content type.
566
567 If the charset can not be found, the system charset is taken and the content type header is
568 changed to that charset.
569 The charset of the content type header should be set to a charset that can encode the given
570 string before calling this method.
571
572 This method does not set the content transfer encoding automatically, it needs to be set
573 to a suitable value that can encode the given string before calling this method.
574
575 This method only makes sense for single-part contents, do not try to pass a multipart body
576 or an encapsulated message here, that wouldn't work.
577
578 @param s Unicode-encoded string.
579 */
580 void fromUnicodeString( const QString &s );
581
582 /**
583 Returns the first Content with mimetype text/.
584 */
585 Content *textContent();
586
587 /**
588 Returns a list of attachments.
589
590 @param incAlternatives If true, include multipart/alternative parts.
591 */
592 List attachments( bool incAlternatives = false );
593
594 /**
595 * For multipart contents, this will return a list of all multipart child contents.
596 * For contents that are of mimetype message/rfc822, this will return a list with one entry,
597 * and that entry is the encapsulated message, as it would be returned by bodyAsMessage().
598 */
599 List contents() const;
600
601 /**
602 Adds a new sub-Content. If the sub-Content is already part of another
603 Content object, it is removed from there and its parent is updated.
604 If the current Content object is single-part, it is converted to
605 multipart/mixed first.
606
607 @warning If the single-part to multipart conversion happens, all
608 pointers you may have into this object (such as headers) will become
609 invalid!
610
611 @param content The new sub-Content.
612 @param prepend If true, prepend to the Content list; otherwise append.
613 to the Content list.
614
615 @see removeContent().
616 */
617 // KDE5: Do not convert single-part->multipart automatically.
618 void addContent( Content *content, bool prepend = false );
619
620 /**
621 Removes the given sub-Content. If only one sub-Content is left, the
622 current Content object is converted into a single-part Content.
623
624 @warning If the multipart to single-part conversion happens, the head
625 and body of the single remaining sub-Content are copied over, and the
626 sub-Content is deleted. All pointers to it or into it (such as headers)
627 will become invalid!
628
629 @param content The Content to remove.
630 @param del If true, delete the removed Content object. Otherwise set its
631 parent to 0.
632
633 @see addContent().
634 @see clearContents().
635 */
636 // KDE5: Do not convert multipart->single-part automatically.
637 void removeContent( Content *content, bool del = false );
638
639 /**
640 Changes the encoding of this Content to @p e. If the Content is binary,
641 this actually re-encodes the data to use the new encoding.
642
643 @param e The new encoding to use.
644 */
645 void changeEncoding( Headers::contentEncoding e );
646
647 /**
648 Saves the encoded Content to the given textstream
649
650 @param ts is the stream where the Content should be written to.
651 @param scrambleFromLines: If true, replace "\nFrom " with "\n>From "
652 in the stream. This is needed to avoid problem with mbox-files
653 */
654 void toStream( QTextStream &ts, bool scrambleFromLines = false );
655
656 // NOTE: The charset methods below are accessed by the headers which
657 // have this Content as a parent.
658
659 /**
660 Returns the charset that is used to decode RFC2047 strings in all headers and to decode
661 the body if the charset is not declared explictly.
662 It is also used as the charset when encoding RFC2047 strings in headers.
663
664 @see setDefaultCharset()
665 */
666 // TODO: Split this up into a charset for encoding and one for decoding, and make the one for
667 // encoding UTF-8 by default.
668 QByteArray defaultCharset() const;
669
670 /**
671 Sets the default charset.
672
673 @param cs is a QByteArray containing the new default charset.
674
675 @see defaultCharset().
676 */
677 void setDefaultCharset( const QByteArray &cs );
678
679 /**
680 Use the default charset even if a different charset is
681 declared in the article.
682
683 @see setForceDefaultCharset().
684 */
685 bool forceDefaultCharset() const;
686
687 /**
688 Enables/disables the force mode, housekeeping.
689 works correctly only when the article is completely empty or
690 completely loaded.
691
692 @param b If true, force the default charset to be used.
693
694 @see forceDefaultCharset().
695 */
696 virtual void setForceDefaultCharset( bool b );
697
698 /**
699 Returns the Content specified by the given index.
700 If the index does not point to a Content, 0 is returned. If the index
701 is invalid (empty), this Content is returned.
702
703 @param index The Content index.
704 */
705 Content *content( const ContentIndex &index ) const;
706
707 /**
708 Returns the ContentIndex for the given Content, or an invalid index
709 if the Content is not found within the hierarchy.
710 @param content the Content object to search.
711 */
712 ContentIndex indexForContent( Content *content ) const;
713
714 /**
715 Returns true if this is the top-level node in the MIME tree. The top-level node is always
716 a Message or NewsArticle. However, a node can be a Message without being a top-level node when
717 it is an encapsulated message.
718 */
719 virtual bool isTopLevel() const;
720
721 /**
722 * Sets a new parent to the Content and add to its contents list. If it already had a parent, it is removed from the
723 * old parents contents list.
724 * @param parent the new parent
725 * @since 4.3
726 */
727 void setParent( Content *parent );
728
729 /**
730 * Returns the parent content object, or 0 if the content doesn't have a parent.
731 * @since 4.3
732 */
733 Content* parent() const;
734
735 /**
736 * Returns the toplevel content object, 0 if there is no such object.
737 * @since 4.3
738 */
739 Content* topLevel() const;
740
741 /**
742 * Returns the index of this Content based on the topLevel() object.
743 * @since 4.3
744 */
745 ContentIndex index() const;
746
747 /**
748 * @return true if this content is an encapsulated message, i.e. if it has the mimetype
749 * message/rfc822.
750 *
751 * @since 4.5
752 */
753 //AK_REVIEW: move to MessageViewer/ObjectTreeParser
754 bool bodyIsMessage() const;
755
756 /**
757 * If this content is an encapsulated message, in which case bodyIsMessage() will return
758 * true, the message represented by the body of this content will be returned.
759 * The returned message is already fully parsed.
760 * Calling this method is the aquivalent of calling contents().first() and casting the result
761 * to a KMime::Message*. bodyAsMessage() has the advantage that it will return a shared pointer
762 * that will not be destroyed when the container message is destroyed or re-parsed.
763 *
764 * The message that is returned here is created when calling parse(), so make sure to call
765 * parse() first. Since each parse() creates a new message object, a different message object
766 * will be returned each time you call parse().
767 *
768 * If you make changes to the returned message, you need to call assemble() on this content
769 * or on the message if you want that encodedContent() reflects these changes. This also means
770 * that calling assemble() on this content will assemble the returned message.
771 *
772 * @since 4.5
773 */
774 //AK_REVIEW: move to MessageViewer/ObjectTreeParser
775 boost::shared_ptr<Message> bodyAsMessage() const;
776
777 protected:
778 /**
779 Reimplement this method if you need to assemble additional headers in a
780 derived class. Don't forget to call the implementation of the base class.
781 @return The raw, assembled headers.
782 */
783 virtual QByteArray assembleHeaders();
784
785 /**
786 Returns the raw string representing the header of type @p name.
787 @param name the header type to find
788 @deprecated Use KMime::extractHeader() directly instead.
789 */
790 KMIME_DEPRECATED QByteArray rawHeader( const char *name ) const;
791
792 /**
793 Returns a list of raw strings representing all header of type @p name.
794 @deprecated Use KMime::extractHeaders() directly instead.
795 */
796 KMIME_DEPRECATED QList<QByteArray> rawHeaders( const char *name ) const;
797
798 /**
799 Returns whether this object holds text content.
800 */
801 // KDE5: Not needed outside. Move to Private class.
802 bool decodeText();
803
804 /**
805 Returns the first header of type T, if it exists.
806 @deprecated Use header() instead.
807 */
808 template <class T> KMIME_DEPRECATED T *headerInstance( T *ptr, bool create );
809
810 /**
811 The list of headers in this Content.
812 Do not use this directly.
813 */
814 // KDE5: Not needed outside. Move to Private class.
815 Headers::Base::List h_eaders;
816
817 //@cond PRIVATE
818 ContentPrivate *d_ptr;
819 explicit Content( ContentPrivate *d );
820 //@endcond
821
822 private:
823 Q_DECLARE_PRIVATE( Content )
824 Q_DISABLE_COPY( Content )
825};
826
827// some compilers (for instance Compaq C++) need template inline functions
828// here rather than in the *.cpp file
829
830template <class T> T *Content::headerInstance( T */*ptr*/, bool create )
831{
832 return header<T>( create );
833}
834
835template <typename T> T *Content::header( bool create )
836{
837 Headers::Base *h = headerByType( T::staticType() );
838 if ( h ) {
839 // Make sure the header is actually of the right type.
840 Q_ASSERT( dynamic_cast<T*>( h ) );
841 } else if ( create ) {
842 h = new T( this );
843 setHeader( h );
844 }
845 return static_cast<T*>( h );
846}
847
848} // namespace KMime
849
850#endif // __KMIME_CONTENT_H__
851