1 | /* -*- c++ -*- |
2 | kmime_headers.cpp |
3 | |
4 | KMime, the KDE Internet mail/usenet news message library. |
5 | Copyright (c) 2001-2002 the KMime authors. |
6 | See file AUTHORS for details |
7 | Copyright (c) 2006 Volker Krause <vkrause@kde.org> |
8 | |
9 | This library is free software; you can redistribute it and/or |
10 | modify it under the terms of the GNU Library General Public |
11 | License as published by the Free Software Foundation; either |
12 | version 2 of the License, or (at your option) any later version. |
13 | |
14 | This library is distributed in the hope that it will be useful, |
15 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
16 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
17 | Library General Public License for more details. |
18 | |
19 | You should have received a copy of the GNU Library General Public License |
20 | along with this library; see the file COPYING.LIB. If not, write to |
21 | the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, |
22 | Boston, MA 02110-1301, USA. |
23 | */ |
24 | /** |
25 | @file |
26 | This file is part of the API for handling @ref MIME data and |
27 | defines the various header classes: |
28 | - header's base class defining the common interface |
29 | - generic base classes for different types of fields |
30 | - incompatible, Structured-based field classes |
31 | - compatible, Unstructured-based field classes |
32 | |
33 | @brief |
34 | Defines the various headers classes. |
35 | |
36 | @authors the KMime authors (see AUTHORS file), |
37 | Volker Krause \<vkrause@kde.org\> |
38 | */ |
39 | |
40 | #include "kmime_headers.h" |
41 | #include "kmime_headers_p.h" |
42 | |
43 | #include "kmime_util.h" |
44 | #include "kmime_util_p.h" |
45 | #include "kmime_content.h" |
46 | #include "kmime_codecs.h" |
47 | #include "kmime_header_parsing.h" |
48 | #include "kmime_headerfactory_p.h" |
49 | #include "kmime_warning.h" |
50 | |
51 | #include <QtCore/QTextCodec> |
52 | #include <QtCore/QString> |
53 | #include <QtCore/QStringList> |
54 | |
55 | #include <kglobal.h> |
56 | #include <kcharsets.h> |
57 | |
58 | #include <assert.h> |
59 | #include <ctype.h> |
60 | |
61 | template <typename T> |
62 | bool () |
63 | { |
64 | const T dummy; |
65 | if ( QByteArray( dummy.type() ).isEmpty() ) { |
66 | // This is a generic header. |
67 | return false; |
68 | } |
69 | return KMime::HeaderFactory::self()->registerHeader<T>(); |
70 | } |
71 | |
72 | // macro to register a header with HeaderFactory |
73 | #define kmime_register_header( subclass ) \ |
74 | namespace { const bool dummyForRegistering##subclass = registerHeaderHelper<subclass>(); } |
75 | |
76 | // macro to generate a default constructor implementation |
77 | #define kmime_mk_trivial_ctor( subclass, baseclass ) \ |
78 | subclass::subclass( Content *parent ) : baseclass( parent ) \ |
79 | { \ |
80 | clear(); \ |
81 | } \ |
82 | \ |
83 | subclass::subclass( Content *parent, const QByteArray &s ) : baseclass( parent ) \ |
84 | { \ |
85 | from7BitString( s ); \ |
86 | } \ |
87 | \ |
88 | subclass::subclass( Content *parent, const QString &s, const QByteArray &charset ) : \ |
89 | baseclass( parent ) \ |
90 | { \ |
91 | fromUnicodeString( s, charset ); \ |
92 | } \ |
93 | \ |
94 | subclass::~subclass() {} \ |
95 | \ |
96 | kmime_register_header( subclass ) |
97 | // end kmime_mk_trivial_ctor |
98 | |
99 | |
100 | #define kmime_mk_trivial_ctor_with_dptr( subclass, baseclass ) \ |
101 | subclass::subclass( Content *parent ) : baseclass( new subclass##Private, parent ) \ |
102 | { \ |
103 | clear(); \ |
104 | } \ |
105 | \ |
106 | subclass::subclass( Content *parent, const QByteArray &s ) : baseclass( new subclass##Private, parent ) \ |
107 | { \ |
108 | from7BitString( s ); \ |
109 | } \ |
110 | \ |
111 | subclass::subclass( Content *parent, const QString &s, const QByteArray &charset ) : \ |
112 | baseclass( new subclass##Private, parent ) \ |
113 | { \ |
114 | fromUnicodeString( s, charset ); \ |
115 | } \ |
116 | \ |
117 | subclass::~subclass() {} \ |
118 | \ |
119 | kmime_register_header( subclass ) |
120 | // end kmime_mk_trivial_ctor_with_dptr |
121 | |
122 | |
123 | #define kmime_mk_trivial_ctor_with_name( subclass, baseclass, name ) \ |
124 | kmime_mk_trivial_ctor( subclass, baseclass ) \ |
125 | \ |
126 | const char *subclass::() const \ |
127 | { \ |
128 | return staticType(); \ |
129 | } \ |
130 | const char *subclass::() { return #name; } |
131 | |
132 | #define kmime_mk_trivial_ctor_with_name_and_dptr( subclass, baseclass, name ) \ |
133 | kmime_mk_trivial_ctor_with_dptr( subclass, baseclass ) \ |
134 | const char *subclass::() const { return staticType(); } \ |
135 | const char *subclass::() { return #name; } |
136 | |
137 | #define kmime_mk_dptr_ctor( subclass, baseclass ) \ |
138 | subclass::subclass( subclass##Private *d, KMime::Content *parent ) : baseclass( d, parent ) {} |
139 | |
140 | using namespace KMime; |
141 | using namespace KMime::Headers; |
142 | using namespace KMime::Types; |
143 | using namespace KMime::HeaderParsing; |
144 | |
145 | namespace KMime { |
146 | namespace Headers { |
147 | //-----<Base>---------------------------------- |
148 | Base::( KMime::Content *parent ) : |
149 | d_ptr( new BasePrivate ) |
150 | { |
151 | Q_D( Base ); |
152 | d->parent = parent; |
153 | } |
154 | |
155 | Base::( BasePrivate *dd, KMime::Content *parent ) : |
156 | d_ptr( dd ) |
157 | { |
158 | Q_D( Base ); |
159 | d->parent = parent; |
160 | } |
161 | |
162 | Base::() |
163 | { |
164 | delete d_ptr; |
165 | d_ptr = 0; |
166 | } |
167 | |
168 | KMime::Content *Base::() const |
169 | { |
170 | return d_ptr->parent; |
171 | } |
172 | |
173 | void Base::( KMime::Content *parent ) |
174 | { |
175 | d_ptr->parent = parent; |
176 | } |
177 | |
178 | QByteArray Base::() const |
179 | { |
180 | if ( d_ptr->encCS.isEmpty() || forceDefaultCharset() ) { |
181 | return defaultCharset(); |
182 | } else { |
183 | return d_ptr->encCS; |
184 | } |
185 | } |
186 | |
187 | void Base::( const QByteArray &cs ) |
188 | { |
189 | d_ptr->encCS = cachedCharset( cs ); |
190 | } |
191 | |
192 | bool Base::() const |
193 | { |
194 | return ( parent() != 0 ? parent()->forceDefaultCharset() : false ); |
195 | } |
196 | |
197 | QByteArray Base::() const |
198 | { |
199 | return ( parent() != 0 ? parent()->defaultCharset() : Latin1 ); |
200 | } |
201 | |
202 | const char *Base::() const |
203 | { |
204 | return "" ; |
205 | } |
206 | |
207 | bool Base::( const char *t ) const |
208 | { |
209 | return qstricmp( t, type() ) == 0; |
210 | } |
211 | |
212 | bool Base::() const |
213 | { |
214 | return qstrnicmp( type(), "Content-" , 8 ) == 0; |
215 | } |
216 | |
217 | bool Base::() const |
218 | { |
219 | return qstrncmp( type(), "X-" , 2 ) == 0; |
220 | } |
221 | |
222 | QByteArray Base::() const |
223 | { |
224 | return QByteArray( type() ) + ": " ; |
225 | } |
226 | |
227 | //-----</Base>--------------------------------- |
228 | |
229 | namespace Generics { |
230 | |
231 | //-----<Unstructured>------------------------- |
232 | |
233 | //@cond PRIVATE |
234 | kmime_mk_dptr_ctor( , Base ) |
235 | //@endcond |
236 | |
237 | Unstructured::( Content *p ) : Base( new UnstructuredPrivate, p ) |
238 | { |
239 | } |
240 | |
241 | Unstructured::( Content *p, const QByteArray &s ) : Base( new UnstructuredPrivate, p ) |
242 | { |
243 | from7BitString( s ); |
244 | } |
245 | |
246 | Unstructured::( Content *p, const QString &s, const QByteArray &cs ) : Base( new UnstructuredPrivate, p ) |
247 | { |
248 | fromUnicodeString( s, cs ); |
249 | } |
250 | |
251 | Unstructured::() |
252 | { |
253 | } |
254 | |
255 | void Unstructured::( const QByteArray &s ) |
256 | { |
257 | Q_D( Unstructured ); |
258 | d->decoded = decodeRFC2047String( s, d->encCS, defaultCharset(), forceDefaultCharset() ); |
259 | } |
260 | |
261 | QByteArray Unstructured::( bool ) const |
262 | { |
263 | const Q_D( Unstructured ); |
264 | QByteArray result; |
265 | if ( withHeaderType ) { |
266 | result = typeIntro(); |
267 | } |
268 | result += encodeRFC2047String( d->decoded, d->encCS ) ; |
269 | |
270 | return result; |
271 | } |
272 | |
273 | void Unstructured::( const QString &s, const QByteArray &b ) |
274 | { |
275 | Q_D( Unstructured ); |
276 | d->decoded = s; |
277 | d->encCS = cachedCharset( b ); |
278 | } |
279 | |
280 | QString Unstructured::() const |
281 | { |
282 | return d_func()->decoded; |
283 | } |
284 | |
285 | void Unstructured::() |
286 | { |
287 | Q_D( Unstructured ); |
288 | d->decoded.truncate( 0 ); |
289 | } |
290 | |
291 | bool Unstructured::() const |
292 | { |
293 | return d_func()->decoded.isEmpty(); |
294 | } |
295 | |
296 | //-----</Unstructured>------------------------- |
297 | |
298 | //-----<Structured>------------------------- |
299 | |
300 | Structured::( Content *p ) : Base( new StructuredPrivate, p ) |
301 | { |
302 | } |
303 | |
304 | Structured::( Content *p, const QByteArray &s ) : Base( new StructuredPrivate, p ) |
305 | { |
306 | from7BitString( s ); |
307 | } |
308 | |
309 | Structured::( Content *p, const QString &s, const QByteArray &cs ) : Base( new StructuredPrivate, p ) |
310 | { |
311 | fromUnicodeString( s, cs ); |
312 | } |
313 | |
314 | kmime_mk_dptr_ctor( , Base ) |
315 | |
316 | Structured::() |
317 | { |
318 | } |
319 | |
320 | void Structured::( const QByteArray &s ) |
321 | { |
322 | Q_D( Structured ); |
323 | if ( d->encCS.isEmpty() ) { |
324 | d->encCS = defaultCharset(); |
325 | } |
326 | const char *cursor = s.constData(); |
327 | parse( cursor, cursor + s.length() ); |
328 | } |
329 | |
330 | QString Structured::() const |
331 | { |
332 | return QString::fromLatin1( as7BitString( false ) ); |
333 | } |
334 | |
335 | void Structured::( const QString &s, const QByteArray &b ) |
336 | { |
337 | Q_D( Structured ); |
338 | d->encCS = cachedCharset( b ); |
339 | from7BitString( s.toLatin1() ); |
340 | } |
341 | |
342 | //-----</Structured>------------------------- |
343 | |
344 | //-----<Address>------------------------- |
345 | |
346 | Address::( Content *p ) : Structured( new AddressPrivate, p ) |
347 | { |
348 | } |
349 | |
350 | Address::( Content *p, const QByteArray &s ) : Structured( new AddressPrivate, p ) |
351 | { |
352 | from7BitString( s ); |
353 | } |
354 | |
355 | Address::( Content *p, const QString &s, const QByteArray &cs ) : Structured( new AddressPrivate, p ) |
356 | { |
357 | fromUnicodeString( s, cs ); |
358 | } |
359 | |
360 | kmime_mk_dptr_ctor( , Structured ) |
361 | |
362 | Address:: () |
363 | { |
364 | } |
365 | |
366 | // helper method used in AddressList and MailboxList |
367 | static bool ( const QByteArray &address, |
368 | const QString &displayName, Types::Mailbox &mbox ) |
369 | { |
370 | Types::AddrSpec addrSpec; |
371 | mbox.setName( displayName ); |
372 | const char *cursor = address.constData(); |
373 | if ( !parseAngleAddr( cursor, cursor + address.length(), addrSpec ) ) { |
374 | if ( !parseAddrSpec( cursor, cursor + address.length(), addrSpec ) ) { |
375 | kWarning() << "Invalid address" ; |
376 | return false; |
377 | } |
378 | } |
379 | mbox.setAddress( addrSpec ); |
380 | return true; |
381 | } |
382 | |
383 | //-----</Address>------------------------- |
384 | |
385 | //-----<MailboxList>------------------------- |
386 | |
387 | kmime_mk_trivial_ctor_with_dptr( , Address ) |
388 | kmime_mk_dptr_ctor( , Address ) |
389 | |
390 | QByteArray MailboxList::( bool ) const |
391 | { |
392 | const Q_D( MailboxList ); |
393 | if ( isEmpty() ) { |
394 | return QByteArray(); |
395 | } |
396 | |
397 | QByteArray rv; |
398 | if ( withHeaderType ) { |
399 | rv = typeIntro(); |
400 | } |
401 | foreach ( const Types::Mailbox &mbox, d->mailboxList ) { |
402 | rv += mbox.as7BitString( d->encCS ); |
403 | rv += ", " ; |
404 | } |
405 | rv.resize( rv.length() - 2 ); |
406 | return rv; |
407 | } |
408 | |
409 | void MailboxList::( const QString &s, const QByteArray &b ) |
410 | { |
411 | Q_D( MailboxList ); |
412 | d->encCS = cachedCharset( b ); |
413 | from7BitString( encodeRFC2047Sentence( s, b ) ); |
414 | } |
415 | |
416 | QString MailboxList::() const |
417 | { |
418 | return prettyAddresses().join( QLatin1String( ", " ) ); |
419 | } |
420 | |
421 | void MailboxList::() |
422 | { |
423 | Q_D( MailboxList ); |
424 | d->mailboxList.clear(); |
425 | } |
426 | |
427 | bool MailboxList::() const |
428 | { |
429 | return d_func()->mailboxList.isEmpty(); |
430 | } |
431 | |
432 | void MailboxList::( const Types::Mailbox &mbox ) |
433 | { |
434 | Q_D( MailboxList ); |
435 | d->mailboxList.append( mbox ); |
436 | } |
437 | |
438 | void MailboxList::( const QByteArray &address, |
439 | const QString &displayName ) |
440 | { |
441 | Q_D( MailboxList ); |
442 | Types::Mailbox mbox; |
443 | if ( stringToMailbox( address, displayName, mbox ) ) { |
444 | d->mailboxList.append( mbox ); |
445 | } |
446 | } |
447 | |
448 | QList< QByteArray > MailboxList::() const |
449 | { |
450 | QList<QByteArray> rv; |
451 | foreach ( const Types::Mailbox &mbox, d_func()->mailboxList ) { |
452 | rv.append( mbox.address() ); |
453 | } |
454 | return rv; |
455 | } |
456 | |
457 | QStringList MailboxList::() const |
458 | { |
459 | QStringList rv; |
460 | foreach ( const Types::Mailbox &mbox, d_func()->mailboxList ) { |
461 | rv.append( mbox.name() ); |
462 | } |
463 | return rv; |
464 | } |
465 | |
466 | QStringList MailboxList::() const |
467 | { |
468 | QStringList rv; |
469 | foreach ( const Types::Mailbox &mbox, d_func()->mailboxList ) { |
470 | rv.append( mbox.prettyAddress() ); |
471 | } |
472 | return rv; |
473 | } |
474 | |
475 | Types::Mailbox::List MailboxList::() const |
476 | { |
477 | return d_func()->mailboxList; |
478 | } |
479 | |
480 | bool MailboxList::( const char* &scursor, const char *const send, |
481 | bool isCRLF ) |
482 | { |
483 | Q_D( MailboxList ); |
484 | // examples: |
485 | // from := "From:" mailbox-list CRLF |
486 | // sender := "Sender:" mailbox CRLF |
487 | |
488 | // parse an address-list: |
489 | QList<Types::Address> maybeAddressList; |
490 | if ( !parseAddressList( scursor, send, maybeAddressList, isCRLF ) ) { |
491 | return false; |
492 | } |
493 | |
494 | d->mailboxList.clear(); |
495 | |
496 | // extract the mailboxes and complain if there are groups: |
497 | QList<Types::Address>::Iterator it; |
498 | for ( it = maybeAddressList.begin(); it != maybeAddressList.end() ; ++it ) { |
499 | if ( !( *it ).displayName.isEmpty() ) { |
500 | KMIME_WARN << "mailbox groups in header disallowing them! Name: \"" |
501 | << ( *it ).displayName << "\"" << endl; |
502 | } |
503 | d->mailboxList += ( *it ).mailboxList; |
504 | } |
505 | return true; |
506 | } |
507 | |
508 | //-----</MailboxList>------------------------- |
509 | |
510 | //-----<SingleMailbox>------------------------- |
511 | |
512 | //@cond PRIVATE |
513 | kmime_mk_trivial_ctor_with_dptr( , MailboxList ) |
514 | //@endcond |
515 | |
516 | bool SingleMailbox::( const char* &scursor, const char *const send, |
517 | bool isCRLF ) |
518 | { |
519 | Q_D( MailboxList ); |
520 | if ( !MailboxList::parse( scursor, send, isCRLF ) ) { |
521 | return false; |
522 | } |
523 | |
524 | if ( d->mailboxList.count() > 1 ) { |
525 | KMIME_WARN << "multiple mailboxes in header allowing only a single one!" |
526 | << endl; |
527 | } |
528 | return true; |
529 | } |
530 | |
531 | //-----</SingleMailbox>------------------------- |
532 | |
533 | //-----<AddressList>------------------------- |
534 | |
535 | //@cond PRIVATE |
536 | kmime_mk_trivial_ctor_with_dptr( , Address ) |
537 | kmime_mk_dptr_ctor( , Address ) |
538 | //@endcond |
539 | |
540 | QByteArray AddressList::( bool ) const |
541 | { |
542 | const Q_D( AddressList ); |
543 | if ( d->addressList.isEmpty() ) { |
544 | return QByteArray(); |
545 | } |
546 | |
547 | QByteArray rv; |
548 | if ( withHeaderType ) { |
549 | rv = typeIntro(); |
550 | } |
551 | foreach ( const Types::Address &addr, d->addressList ) { |
552 | foreach ( const Types::Mailbox &mbox, addr.mailboxList ) { |
553 | rv += mbox.as7BitString( d->encCS ); |
554 | rv += ", " ; |
555 | } |
556 | } |
557 | rv.resize( rv.length() - 2 ); |
558 | return rv; |
559 | } |
560 | |
561 | void AddressList::( const QString &s, const QByteArray &b ) |
562 | { |
563 | Q_D( AddressList ); |
564 | d->encCS = cachedCharset( b ); |
565 | from7BitString( encodeRFC2047Sentence( s, b ) ); |
566 | } |
567 | |
568 | QString AddressList::() const |
569 | { |
570 | return prettyAddresses().join( QLatin1String( ", " ) ); |
571 | } |
572 | |
573 | void AddressList::() |
574 | { |
575 | Q_D( AddressList ); |
576 | d->addressList.clear(); |
577 | } |
578 | |
579 | bool AddressList::() const |
580 | { |
581 | return d_func()->addressList.isEmpty(); |
582 | } |
583 | |
584 | void AddressList::( const Types::Mailbox &mbox ) |
585 | { |
586 | Q_D( AddressList ); |
587 | Types::Address addr; |
588 | addr.mailboxList.append( mbox ); |
589 | d->addressList.append( addr ); |
590 | } |
591 | |
592 | void AddressList::( const QByteArray &address, |
593 | const QString &displayName ) |
594 | { |
595 | Q_D( AddressList ); |
596 | Types::Address addr; |
597 | Types::Mailbox mbox; |
598 | if ( stringToMailbox( address, displayName, mbox ) ) { |
599 | addr.mailboxList.append( mbox ); |
600 | d->addressList.append( addr ); |
601 | } |
602 | } |
603 | |
604 | QList< QByteArray > AddressList::() const |
605 | { |
606 | QList<QByteArray> rv; |
607 | foreach ( const Types::Address &addr, d_func()->addressList ) { |
608 | foreach ( const Types::Mailbox &mbox, addr.mailboxList ) { |
609 | rv.append( mbox.address() ); |
610 | } |
611 | } |
612 | return rv; |
613 | } |
614 | |
615 | QStringList AddressList::() const |
616 | { |
617 | QStringList rv; |
618 | foreach ( const Types::Address &addr, d_func()->addressList ) { |
619 | foreach ( const Types::Mailbox &mbox, addr.mailboxList ) { |
620 | rv.append( mbox.name() ); |
621 | } |
622 | } |
623 | return rv; |
624 | } |
625 | |
626 | QStringList AddressList::() const |
627 | { |
628 | QStringList rv; |
629 | foreach ( const Types::Address &addr, d_func()->addressList ) { |
630 | foreach ( const Types::Mailbox &mbox, addr.mailboxList ) { |
631 | rv.append( mbox.prettyAddress() ); |
632 | } |
633 | } |
634 | return rv; |
635 | } |
636 | |
637 | Types::Mailbox::List AddressList::() const |
638 | { |
639 | Types::Mailbox::List rv; |
640 | foreach ( const Types::Address &addr, d_func()->addressList ) { |
641 | foreach ( const Types::Mailbox &mbox, addr.mailboxList ) { |
642 | rv.append( mbox ); |
643 | } |
644 | } |
645 | return rv; |
646 | } |
647 | |
648 | bool AddressList::( const char* &scursor, const char *const send, |
649 | bool isCRLF ) |
650 | { |
651 | Q_D( AddressList ); |
652 | QList<Types::Address> maybeAddressList; |
653 | if ( !parseAddressList( scursor, send, maybeAddressList, isCRLF ) ) { |
654 | return false; |
655 | } |
656 | |
657 | d->addressList = maybeAddressList; |
658 | return true; |
659 | } |
660 | |
661 | //-----</AddressList>------------------------- |
662 | |
663 | //-----<Token>------------------------- |
664 | |
665 | //@cond PRIVATE |
666 | kmime_mk_trivial_ctor_with_dptr( , Structured ) |
667 | kmime_mk_dptr_ctor( , Structured ) |
668 | //@endcond |
669 | |
670 | QByteArray Token::( bool ) const |
671 | { |
672 | if ( isEmpty() ) { |
673 | return QByteArray(); |
674 | } |
675 | if ( withHeaderType ) { |
676 | return typeIntro() + d_func()->token; |
677 | } |
678 | return d_func()->token; |
679 | } |
680 | |
681 | void Token::() |
682 | { |
683 | Q_D( Token ); |
684 | d->token.clear(); |
685 | } |
686 | |
687 | bool Token::() const |
688 | { |
689 | return d_func()->token.isEmpty(); |
690 | } |
691 | |
692 | QByteArray Token::() const |
693 | { |
694 | return d_func()->token; |
695 | } |
696 | |
697 | void Token::( const QByteArray &t ) |
698 | { |
699 | Q_D( Token ); |
700 | d->token = t; |
701 | } |
702 | |
703 | bool Token::( const char* &scursor, const char *const send, bool isCRLF ) |
704 | { |
705 | Q_D( Token ); |
706 | clear(); |
707 | eatCFWS( scursor, send, isCRLF ); |
708 | // must not be empty: |
709 | if ( scursor == send ) { |
710 | return false; |
711 | } |
712 | |
713 | QPair<const char*, int> maybeToken; |
714 | if ( !parseToken( scursor, send, maybeToken, false /* no 8bit chars */ ) ) { |
715 | return false; |
716 | } |
717 | d->token = QByteArray( maybeToken.first, maybeToken.second ); |
718 | |
719 | // complain if trailing garbage is found: |
720 | eatCFWS( scursor, send, isCRLF ); |
721 | if ( scursor != send ) { |
722 | KMIME_WARN << "trailing garbage after token in header allowing " |
723 | "only a single token!" << endl; |
724 | } |
725 | return true; |
726 | } |
727 | |
728 | //-----</Token>------------------------- |
729 | |
730 | //-----<PhraseList>------------------------- |
731 | |
732 | //@cond PRIVATE |
733 | kmime_mk_trivial_ctor_with_dptr( , Structured ) |
734 | //@endcond |
735 | |
736 | QByteArray PhraseList::( bool ) const |
737 | { |
738 | const Q_D( PhraseList ); |
739 | if ( isEmpty() ) { |
740 | return QByteArray(); |
741 | } |
742 | |
743 | QByteArray rv; |
744 | if ( withHeaderType ) { |
745 | rv = typeIntro(); |
746 | } |
747 | |
748 | for ( int i = 0; i < d->phraseList.count(); ++i ) { |
749 | // FIXME: only encode when needed, quote when needed, etc. |
750 | rv += encodeRFC2047String( d->phraseList[i], d->encCS, false, false ); |
751 | if ( i != d->phraseList.count() - 1 ) { |
752 | rv += ", " ; |
753 | } |
754 | } |
755 | |
756 | return rv; |
757 | } |
758 | |
759 | QString PhraseList::() const |
760 | { |
761 | return d_func()->phraseList.join( QLatin1String( ", " ) ); |
762 | } |
763 | |
764 | void PhraseList::() |
765 | { |
766 | Q_D( PhraseList ); |
767 | d->phraseList.clear(); |
768 | } |
769 | |
770 | bool PhraseList::() const |
771 | { |
772 | return d_func()->phraseList.isEmpty(); |
773 | } |
774 | |
775 | QStringList PhraseList::() const |
776 | { |
777 | return d_func()->phraseList; |
778 | } |
779 | |
780 | bool PhraseList::( const char* &scursor, const char *const send, |
781 | bool isCRLF ) |
782 | { |
783 | Q_D( PhraseList ); |
784 | d->phraseList.clear(); |
785 | |
786 | while ( scursor != send ) { |
787 | eatCFWS( scursor, send, isCRLF ); |
788 | // empty entry ending the list: OK. |
789 | if ( scursor == send ) { |
790 | return true; |
791 | } |
792 | // empty entry: ignore. |
793 | if ( *scursor == ',' ) { |
794 | scursor++; |
795 | continue; |
796 | } |
797 | |
798 | QString maybePhrase; |
799 | if ( !parsePhrase( scursor, send, maybePhrase, isCRLF ) ) { |
800 | return false; |
801 | } |
802 | d->phraseList.append( maybePhrase ); |
803 | |
804 | eatCFWS( scursor, send, isCRLF ); |
805 | // non-empty entry ending the list: OK. |
806 | if ( scursor == send ) { |
807 | return true; |
808 | } |
809 | // comma separating the phrases: eat. |
810 | if ( *scursor == ',' ) { |
811 | scursor++; |
812 | } |
813 | } |
814 | return true; |
815 | } |
816 | |
817 | //-----</PhraseList>------------------------- |
818 | |
819 | //-----<DotAtom>------------------------- |
820 | |
821 | //@cond PRIVATE |
822 | kmime_mk_trivial_ctor_with_dptr( , Structured ) |
823 | //@endcond |
824 | |
825 | QByteArray DotAtom::( bool ) const |
826 | { |
827 | if ( isEmpty() ) { |
828 | return QByteArray(); |
829 | } |
830 | |
831 | QByteArray rv; |
832 | if ( withHeaderType ) { |
833 | rv += typeIntro(); |
834 | } |
835 | |
836 | rv += d_func()->dotAtom.toLatin1(); // FIXME: encoding? |
837 | return rv; |
838 | } |
839 | |
840 | QString DotAtom::() const |
841 | { |
842 | return d_func()->dotAtom; |
843 | } |
844 | |
845 | void DotAtom::() |
846 | { |
847 | Q_D( DotAtom ); |
848 | d->dotAtom.clear(); |
849 | } |
850 | |
851 | bool DotAtom::() const |
852 | { |
853 | return d_func()->dotAtom.isEmpty(); |
854 | } |
855 | |
856 | bool DotAtom::( const char* &scursor, const char *const send, |
857 | bool isCRLF ) |
858 | { |
859 | Q_D( DotAtom ); |
860 | QString maybeDotAtom; |
861 | if ( !parseDotAtom( scursor, send, maybeDotAtom, isCRLF ) ) { |
862 | return false; |
863 | } |
864 | |
865 | d->dotAtom = maybeDotAtom; |
866 | |
867 | eatCFWS( scursor, send, isCRLF ); |
868 | if ( scursor != send ) { |
869 | KMIME_WARN << "trailing garbage after dot-atom in header allowing " |
870 | "only a single dot-atom!" << endl; |
871 | } |
872 | return true; |
873 | } |
874 | |
875 | //-----</DotAtom>------------------------- |
876 | |
877 | //-----<Parametrized>------------------------- |
878 | |
879 | //@cond PRIVATE |
880 | kmime_mk_trivial_ctor_with_dptr( , Structured ) |
881 | kmime_mk_dptr_ctor( , Structured ) |
882 | //@endcond |
883 | |
884 | QByteArray Parametrized::( bool ) const |
885 | { |
886 | const Q_D( Parametrized ); |
887 | if ( isEmpty() ) { |
888 | return QByteArray(); |
889 | } |
890 | |
891 | QByteArray rv; |
892 | if ( withHeaderType ) { |
893 | rv += typeIntro(); |
894 | } |
895 | |
896 | bool first = true; |
897 | for ( QMap<QString, QString>::ConstIterator it = d->parameterHash.constBegin(); |
898 | it != d->parameterHash.constEnd(); ++it ) { |
899 | if ( !first ) { |
900 | rv += "; " ; |
901 | } else { |
902 | first = false; |
903 | } |
904 | if ( isUsAscii( it.value() ) ) { |
905 | rv += it.key().toLatin1() + '='; |
906 | QByteArray tmp = it.value().toLatin1(); |
907 | addQuotes( tmp, true ); // force quoting, eg. for whitespaces in parameter value |
908 | rv += tmp; |
909 | } else { |
910 | if ( useOutlookAttachmentEncoding() ) { |
911 | rv += it.key().toLatin1() + '='; |
912 | kDebug() << "doing:" << it.value() << QLatin1String( d->encCS ); |
913 | rv += "\"" + encodeRFC2047String( it.value(), d->encCS ) + "\"" ; |
914 | } else { |
915 | rv += it.key().toLatin1() + "*=" ; |
916 | rv += encodeRFC2231String( it.value(), d->encCS ); |
917 | } |
918 | } |
919 | } |
920 | |
921 | return rv; |
922 | } |
923 | |
924 | QString Parametrized::( const QString &key ) const |
925 | { |
926 | return d_func()->parameterHash.value( key.toLower() ); |
927 | } |
928 | |
929 | bool Parametrized::( const QString &key ) const |
930 | { |
931 | return d_func()->parameterHash.contains( key.toLower() ); |
932 | } |
933 | |
934 | void Parametrized::( const QString &key, const QString &value ) |
935 | { |
936 | Q_D( Parametrized ); |
937 | d->parameterHash.insert( key.toLower(), value ); |
938 | } |
939 | |
940 | bool Parametrized::() const |
941 | { |
942 | return d_func()->parameterHash.isEmpty(); |
943 | } |
944 | |
945 | void Parametrized::() |
946 | { |
947 | Q_D( Parametrized ); |
948 | d->parameterHash.clear(); |
949 | } |
950 | |
951 | bool Parametrized::( const char *& scursor, const char * const send, |
952 | bool isCRLF ) |
953 | { |
954 | Q_D( Parametrized ); |
955 | d->parameterHash.clear(); |
956 | QByteArray charset; |
957 | if ( !parseParameterListWithCharset( scursor, send, d->parameterHash, charset, isCRLF ) ) { |
958 | return false; |
959 | } |
960 | d->encCS = charset; |
961 | return true; |
962 | } |
963 | |
964 | //-----</Parametrized>------------------------- |
965 | |
966 | //-----<Ident>------------------------- |
967 | |
968 | //@cond PRIVATE |
969 | kmime_mk_trivial_ctor_with_dptr( , Address ) |
970 | kmime_mk_dptr_ctor( , Address ) |
971 | //@endcond |
972 | |
973 | QByteArray Ident::( bool ) const |
974 | { |
975 | const Q_D( Ident ); |
976 | if ( d->msgIdList.isEmpty() ) { |
977 | return QByteArray(); |
978 | } |
979 | |
980 | QByteArray rv; |
981 | if ( withHeaderType ) { |
982 | rv = typeIntro(); |
983 | } |
984 | foreach ( const Types::AddrSpec &addr, d->msgIdList ) { |
985 | if ( !addr.isEmpty() ) { |
986 | const QString asString = addr.asString(); |
987 | rv += '<'; |
988 | if ( !asString.isEmpty() ) { |
989 | rv += asString.toLatin1(); // FIXME: change parsing to use QByteArrays |
990 | } |
991 | rv += "> " ; |
992 | } |
993 | } |
994 | if ( !rv.isEmpty() ) { |
995 | rv.resize( rv.length() - 1 ); |
996 | } |
997 | return rv; |
998 | } |
999 | |
1000 | void Ident::() |
1001 | { |
1002 | Q_D( Ident ); |
1003 | d->msgIdList.clear(); |
1004 | d->cachedIdentifier.clear(); |
1005 | } |
1006 | |
1007 | bool Ident::() const |
1008 | { |
1009 | return d_func()->msgIdList.isEmpty(); |
1010 | } |
1011 | |
1012 | bool Ident::( const char* &scursor, const char * const send, bool isCRLF ) |
1013 | { |
1014 | Q_D( Ident ); |
1015 | // msg-id := "<" id-left "@" id-right ">" |
1016 | // id-left := dot-atom-text / no-fold-quote / local-part |
1017 | // id-right := dot-atom-text / no-fold-literal / domain |
1018 | // |
1019 | // equivalent to: |
1020 | // msg-id := angle-addr |
1021 | |
1022 | d->msgIdList.clear(); |
1023 | d->cachedIdentifier.clear(); |
1024 | |
1025 | while ( scursor != send ) { |
1026 | eatCFWS( scursor, send, isCRLF ); |
1027 | // empty entry ending the list: OK. |
1028 | if ( scursor == send ) { |
1029 | return true; |
1030 | } |
1031 | // empty entry: ignore. |
1032 | if ( *scursor == ',' ) { |
1033 | scursor++; |
1034 | continue; |
1035 | } |
1036 | |
1037 | AddrSpec maybeMsgId; |
1038 | if ( !parseAngleAddr( scursor, send, maybeMsgId, isCRLF ) ) { |
1039 | return false; |
1040 | } |
1041 | d->msgIdList.append( maybeMsgId ); |
1042 | |
1043 | eatCFWS( scursor, send, isCRLF ); |
1044 | // header end ending the list: OK. |
1045 | if ( scursor == send ) { |
1046 | return true; |
1047 | } |
1048 | // regular item separator: eat it. |
1049 | if ( *scursor == ',' ) { |
1050 | scursor++; |
1051 | } |
1052 | } |
1053 | return true; |
1054 | } |
1055 | |
1056 | QList<QByteArray> Ident::() const |
1057 | { |
1058 | QList<QByteArray> rv; |
1059 | foreach ( const Types::AddrSpec &addr, d_func()->msgIdList ) { |
1060 | if ( !addr.isEmpty() ) { |
1061 | const QString asString = addr.asString(); |
1062 | if ( !asString.isEmpty() ) { |
1063 | rv.append( asString.toLatin1() ); // FIXME: change parsing to use QByteArrays |
1064 | } |
1065 | } |
1066 | } |
1067 | return rv; |
1068 | } |
1069 | |
1070 | void Ident::( const QByteArray &id ) |
1071 | { |
1072 | Q_D( Ident ); |
1073 | QByteArray tmp = id; |
1074 | if ( !tmp.startsWith( '<' ) ) { |
1075 | tmp.prepend( '<' ); |
1076 | } |
1077 | if ( !tmp.endsWith( '>' ) ) { |
1078 | tmp.append( '>' ); |
1079 | } |
1080 | AddrSpec msgId; |
1081 | const char *cursor = tmp.constData(); |
1082 | if ( parseAngleAddr( cursor, cursor + tmp.length(), msgId ) ) { |
1083 | d->msgIdList.append( msgId ); |
1084 | } else { |
1085 | kWarning() << "Unable to parse address spec!" ; |
1086 | } |
1087 | } |
1088 | |
1089 | //-----</Ident>------------------------- |
1090 | |
1091 | //-----<SingleIdent>------------------------- |
1092 | |
1093 | //@cond PRIVATE |
1094 | kmime_mk_trivial_ctor_with_dptr( , Ident ) |
1095 | kmime_mk_dptr_ctor( , Ident ) |
1096 | //@endcond |
1097 | |
1098 | QByteArray SingleIdent::() const |
1099 | { |
1100 | if ( d_func()->msgIdList.isEmpty() ) { |
1101 | return QByteArray(); |
1102 | } |
1103 | |
1104 | if ( d_func()->cachedIdentifier.isEmpty() ) { |
1105 | const Types::AddrSpec &addr = d_func()->msgIdList.first(); |
1106 | if ( !addr.isEmpty() ) { |
1107 | const QString asString = addr.asString(); |
1108 | if ( !asString.isEmpty() ) { |
1109 | d_func()->cachedIdentifier = asString.toLatin1();// FIXME: change parsing to use QByteArrays |
1110 | } |
1111 | } |
1112 | } |
1113 | |
1114 | return d_func()->cachedIdentifier; |
1115 | } |
1116 | |
1117 | void SingleIdent::( const QByteArray &id ) |
1118 | { |
1119 | Q_D( SingleIdent ); |
1120 | d->msgIdList.clear(); |
1121 | d->cachedIdentifier.clear(); |
1122 | appendIdentifier( id ); |
1123 | } |
1124 | |
1125 | bool SingleIdent::( const char* &scursor, const char * const send, |
1126 | bool isCRLF ) |
1127 | { |
1128 | Q_D( SingleIdent ); |
1129 | if ( !Ident::parse( scursor, send, isCRLF ) ) { |
1130 | return false; |
1131 | } |
1132 | |
1133 | if ( d->msgIdList.count() > 1 ) { |
1134 | KMIME_WARN << "more than one msg-id in header " |
1135 | << "allowing only a single one!" << endl; |
1136 | } |
1137 | return true; |
1138 | } |
1139 | |
1140 | //-----</SingleIdent>------------------------- |
1141 | |
1142 | } // namespace Generics |
1143 | |
1144 | //-----<ReturnPath>------------------------- |
1145 | |
1146 | //@cond PRIVATE |
1147 | kmime_mk_trivial_ctor_with_name_and_dptr( , Generics::Address, Return-Path ) |
1148 | //@endcond |
1149 | |
1150 | QByteArray ReturnPath::( bool ) const |
1151 | { |
1152 | if ( isEmpty() ) { |
1153 | return QByteArray(); |
1154 | } |
1155 | |
1156 | QByteArray rv; |
1157 | if ( withHeaderType ) { |
1158 | rv += typeIntro(); |
1159 | } |
1160 | rv += '<' + d_func()->mailbox.as7BitString( d_func()->encCS ) + '>'; |
1161 | return rv; |
1162 | } |
1163 | |
1164 | void ReturnPath::() |
1165 | { |
1166 | Q_D( ReturnPath ); |
1167 | d->mailbox.setAddress( Types::AddrSpec() ); |
1168 | d->mailbox.setName( QString() ); |
1169 | } |
1170 | |
1171 | bool ReturnPath::() const |
1172 | { |
1173 | const Q_D( ReturnPath ); |
1174 | return !d->mailbox.hasAddress() && !d->mailbox.hasName(); |
1175 | } |
1176 | |
1177 | bool ReturnPath::( const char* &scursor, const char * const send, |
1178 | bool isCRLF ) |
1179 | { |
1180 | Q_D( ReturnPath ); |
1181 | eatCFWS( scursor, send, isCRLF ); |
1182 | if ( scursor == send ) { |
1183 | return false; |
1184 | } |
1185 | |
1186 | const char * oldscursor = scursor; |
1187 | |
1188 | Mailbox maybeMailbox; |
1189 | if ( !parseMailbox( scursor, send, maybeMailbox, isCRLF ) ) { |
1190 | // mailbox parsing failed, but check for empty brackets: |
1191 | scursor = oldscursor; |
1192 | if ( *scursor != '<' ) { |
1193 | return false; |
1194 | } |
1195 | scursor++; |
1196 | eatCFWS( scursor, send, isCRLF ); |
1197 | if ( scursor == send || *scursor != '>' ) { |
1198 | return false; |
1199 | } |
1200 | scursor++; |
1201 | |
1202 | // prepare a Null mailbox: |
1203 | AddrSpec emptyAddrSpec; |
1204 | maybeMailbox.setName( QString() ); |
1205 | maybeMailbox.setAddress( emptyAddrSpec ); |
1206 | } else { |
1207 | // check that there was no display-name: |
1208 | if ( maybeMailbox.hasName() ) { |
1209 | KMIME_WARN << "display-name \"" << maybeMailbox.name() |
1210 | << "\" in Return-Path!" << endl; |
1211 | } |
1212 | } |
1213 | d->mailbox = maybeMailbox; |
1214 | |
1215 | // see if that was all: |
1216 | eatCFWS( scursor, send, isCRLF ); |
1217 | // and warn if it wasn't: |
1218 | if ( scursor != send ) { |
1219 | KMIME_WARN << "trailing garbage after angle-addr in Return-Path!" << endl; |
1220 | } |
1221 | return true; |
1222 | } |
1223 | |
1224 | //-----</ReturnPath>------------------------- |
1225 | |
1226 | //-----<Generic>------------------------------- |
1227 | |
1228 | // NOTE: Do *not* register Generic with HeaderFactory, since its type() is changeable. |
1229 | |
1230 | Generic::() : Generics::Unstructured( new GenericPrivate ) |
1231 | { |
1232 | } |
1233 | |
1234 | Generic::( const char *t ) : Generics::Unstructured( new GenericPrivate ) |
1235 | { |
1236 | setType( t ); |
1237 | } |
1238 | |
1239 | Generic::( const char *t, Content *p ) |
1240 | : Generics::Unstructured( new GenericPrivate, p ) |
1241 | { |
1242 | setType( t ); |
1243 | } |
1244 | |
1245 | Generic::( const char *t, Content *p, const QByteArray &s ) |
1246 | : Generics::Unstructured( new GenericPrivate, p ) |
1247 | { |
1248 | from7BitString( s ); |
1249 | setType( t ); |
1250 | } |
1251 | |
1252 | Generic::( const char *t, Content *p, const QString &s, const QByteArray &cs ) |
1253 | : Generics::Unstructured( new GenericPrivate, p ) |
1254 | { |
1255 | fromUnicodeString( s, cs ); |
1256 | setType( t ); |
1257 | } |
1258 | |
1259 | Generic::() |
1260 | { |
1261 | } |
1262 | |
1263 | void Generic::() |
1264 | { |
1265 | Q_D( Generic ); |
1266 | delete[] d->type; |
1267 | d->type = 0; |
1268 | Unstructured::clear(); |
1269 | } |
1270 | |
1271 | bool Generic::() const |
1272 | { |
1273 | return d_func()->type == 0 || Unstructured::isEmpty(); |
1274 | } |
1275 | |
1276 | const char *Generic::() const |
1277 | { |
1278 | return d_func()->type; |
1279 | } |
1280 | |
1281 | void Generic::( const char *type ) |
1282 | { |
1283 | Q_D( Generic ); |
1284 | if ( d->type ) { |
1285 | delete[] d->type; |
1286 | } |
1287 | if ( type ) { |
1288 | d->type = new char[strlen( type )+1]; |
1289 | strcpy( d->type, type ); |
1290 | } else { |
1291 | d->type = 0; |
1292 | } |
1293 | } |
1294 | |
1295 | //-----<Generic>------------------------------- |
1296 | |
1297 | //-----<MessageID>----------------------------- |
1298 | |
1299 | //@cond PRIVATE |
1300 | kmime_mk_trivial_ctor_with_name( , Generics::SingleIdent, Message-ID ) |
1301 | //@endcond |
1302 | |
1303 | void MessageID::( const QByteArray &fqdn ) |
1304 | { |
1305 | setIdentifier( '<' + uniqueString() + '@' + fqdn + '>' ); |
1306 | } |
1307 | |
1308 | //-----</MessageID>---------------------------- |
1309 | |
1310 | //-----<Control>------------------------------- |
1311 | |
1312 | //@cond PRIVATE |
1313 | kmime_mk_trivial_ctor_with_name_and_dptr( , Generics::Structured, Control ) |
1314 | //@endcond |
1315 | |
1316 | QByteArray Control::( bool ) const |
1317 | { |
1318 | const Q_D( Control ); |
1319 | if ( isEmpty() ) { |
1320 | return QByteArray(); |
1321 | } |
1322 | |
1323 | QByteArray rv; |
1324 | if ( withHeaderType ) { |
1325 | rv += typeIntro(); |
1326 | } |
1327 | |
1328 | rv += d->name; |
1329 | if ( !d->parameter.isEmpty() ) { |
1330 | rv += ' ' + d->parameter; |
1331 | } |
1332 | return rv; |
1333 | } |
1334 | |
1335 | void Control::() |
1336 | { |
1337 | Q_D( Control ); |
1338 | d->name.clear(); |
1339 | d->parameter.clear(); |
1340 | } |
1341 | |
1342 | bool Control::() const |
1343 | { |
1344 | return d_func()->name.isEmpty(); |
1345 | } |
1346 | |
1347 | QByteArray Control::() const |
1348 | { |
1349 | return d_func()->name; |
1350 | } |
1351 | |
1352 | QByteArray Control::() const |
1353 | { |
1354 | return d_func()->parameter; |
1355 | } |
1356 | |
1357 | bool Control::() const |
1358 | { |
1359 | return d_func()->name.toLower() == "cancel" ; |
1360 | } |
1361 | |
1362 | void Control::( const QByteArray &msgid ) |
1363 | { |
1364 | Q_D( Control ); |
1365 | d->name = "cancel" ; |
1366 | d->parameter = msgid; |
1367 | } |
1368 | |
1369 | bool Control::( const char* &scursor, const char *const send, bool isCRLF ) |
1370 | { |
1371 | Q_D( Control ); |
1372 | clear(); |
1373 | eatCFWS( scursor, send, isCRLF ); |
1374 | if ( scursor == send ) { |
1375 | return false; |
1376 | } |
1377 | const char *start = scursor; |
1378 | while ( scursor != send && !isspace( *scursor ) ) { |
1379 | ++scursor; |
1380 | } |
1381 | d->name = QByteArray( start, scursor - start ); |
1382 | eatCFWS( scursor, send, isCRLF ); |
1383 | d->parameter = QByteArray( scursor, send - scursor ); |
1384 | return true; |
1385 | } |
1386 | |
1387 | //-----</Control>------------------------------ |
1388 | |
1389 | //-----<MailCopiesTo>-------------------------- |
1390 | |
1391 | //@cond PRIVATE |
1392 | kmime_mk_trivial_ctor_with_name_and_dptr( , |
1393 | Generics::AddressList, Mail-Copies-To ) |
1394 | //@endcond |
1395 | |
1396 | QByteArray MailCopiesTo::( bool ) const |
1397 | { |
1398 | QByteArray rv; |
1399 | if ( withHeaderType ) { |
1400 | rv += typeIntro(); |
1401 | } |
1402 | if ( !AddressList::isEmpty() ) { |
1403 | rv += AddressList::as7BitString( false ); |
1404 | } else { |
1405 | if ( d_func()->alwaysCopy ) { |
1406 | rv += "poster" ; |
1407 | } else if ( d_func()->neverCopy ) { |
1408 | rv += "nobody" ; |
1409 | } |
1410 | } |
1411 | return rv; |
1412 | } |
1413 | |
1414 | QString MailCopiesTo::() const |
1415 | { |
1416 | if ( !AddressList::isEmpty() ) { |
1417 | return AddressList::asUnicodeString(); |
1418 | } |
1419 | if ( d_func()->alwaysCopy ) { |
1420 | return QLatin1String( "poster" ); |
1421 | } |
1422 | if ( d_func()->neverCopy ) { |
1423 | return QLatin1String( "nobody" ); |
1424 | } |
1425 | return QString(); |
1426 | } |
1427 | |
1428 | void MailCopiesTo::() |
1429 | { |
1430 | Q_D( MailCopiesTo ); |
1431 | AddressList::clear(); |
1432 | d->alwaysCopy = false; |
1433 | d->neverCopy = false; |
1434 | } |
1435 | |
1436 | bool MailCopiesTo::() const |
1437 | { |
1438 | return AddressList::isEmpty() && !( d_func()->alwaysCopy || d_func()->neverCopy ); |
1439 | } |
1440 | |
1441 | bool MailCopiesTo::() const |
1442 | { |
1443 | return !AddressList::isEmpty() || d_func()->alwaysCopy; |
1444 | } |
1445 | |
1446 | void MailCopiesTo::() |
1447 | { |
1448 | Q_D( MailCopiesTo ); |
1449 | clear(); |
1450 | d->alwaysCopy = true; |
1451 | } |
1452 | |
1453 | bool MailCopiesTo::() const |
1454 | { |
1455 | return d_func()->neverCopy; |
1456 | } |
1457 | |
1458 | void MailCopiesTo::() |
1459 | { |
1460 | Q_D( MailCopiesTo ); |
1461 | clear(); |
1462 | d->neverCopy = true; |
1463 | } |
1464 | |
1465 | bool MailCopiesTo::( const char *& scursor, const char * const send, |
1466 | bool isCRLF ) |
1467 | { |
1468 | Q_D( MailCopiesTo ); |
1469 | clear(); |
1470 | if ( send - scursor == 5 ) { |
1471 | if ( qstrnicmp( "never" , scursor, 5 ) == 0 ) { |
1472 | d->neverCopy = true; |
1473 | return true; |
1474 | } |
1475 | } |
1476 | if ( send - scursor == 6 ) { |
1477 | if ( qstrnicmp( "always" , scursor, 6 ) == 0 || qstrnicmp( "poster" , scursor, 6 ) == 0 ) { |
1478 | d->alwaysCopy = true; |
1479 | return true; |
1480 | } |
1481 | if ( qstrnicmp( "nobody" , scursor, 6 ) == 0 ) { |
1482 | d->neverCopy = true; |
1483 | return true; |
1484 | } |
1485 | } |
1486 | return AddressList::parse( scursor, send, isCRLF ); |
1487 | } |
1488 | |
1489 | //-----</MailCopiesTo>------------------------- |
1490 | |
1491 | //-----<Date>---------------------------------- |
1492 | |
1493 | //@cond PRIVATE |
1494 | kmime_mk_trivial_ctor_with_name_and_dptr( , Generics::Structured, Date ) |
1495 | //@endcond |
1496 | |
1497 | QByteArray Date::( bool ) const |
1498 | { |
1499 | if ( isEmpty() ) { |
1500 | return QByteArray(); |
1501 | } |
1502 | |
1503 | QByteArray rv; |
1504 | if ( withHeaderType ) { |
1505 | rv += typeIntro(); |
1506 | } |
1507 | rv += d_func()->dateTime.toString( KDateTime::RFCDateDay ).toLatin1(); |
1508 | return rv; |
1509 | } |
1510 | |
1511 | void Date::() |
1512 | { |
1513 | Q_D( Date ); |
1514 | d->dateTime = KDateTime(); |
1515 | } |
1516 | |
1517 | bool Date::() const |
1518 | { |
1519 | return d_func()->dateTime.isNull() || !d_func()->dateTime.isValid(); |
1520 | } |
1521 | |
1522 | KDateTime Date::() const |
1523 | { |
1524 | return d_func()->dateTime; |
1525 | } |
1526 | |
1527 | void Date::( const KDateTime &dt ) |
1528 | { |
1529 | Q_D( Date ); |
1530 | d->dateTime = dt; |
1531 | } |
1532 | |
1533 | int Date::() const |
1534 | { |
1535 | QDate today = QDate::currentDate(); |
1536 | return dateTime().date().daysTo( today ); |
1537 | } |
1538 | |
1539 | bool Date::( const char* &scursor, const char *const send, bool isCRLF ) |
1540 | { |
1541 | Q_D( Date ); |
1542 | return parseDateTime( scursor, send, d->dateTime, isCRLF ); |
1543 | } |
1544 | |
1545 | //-----</Date>--------------------------------- |
1546 | |
1547 | //-----<Newsgroups>---------------------------- |
1548 | |
1549 | //@cond PRIVATE |
1550 | kmime_mk_trivial_ctor_with_name_and_dptr( , Generics::Structured, Newsgroups ) |
1551 | kmime_mk_trivial_ctor_with_name( , Newsgroups, Followup-To ) |
1552 | //@endcond |
1553 | |
1554 | QByteArray Newsgroups::( bool ) const |
1555 | { |
1556 | const Q_D( Newsgroups ); |
1557 | if ( isEmpty() ) { |
1558 | return QByteArray(); |
1559 | } |
1560 | |
1561 | QByteArray rv; |
1562 | if ( withHeaderType ) { |
1563 | rv += typeIntro(); |
1564 | } |
1565 | |
1566 | for ( int i = 0; i < d->groups.count(); ++i ) { |
1567 | rv += d->groups[ i ]; |
1568 | if ( i != d->groups.count() - 1 ) { |
1569 | rv += ','; |
1570 | } |
1571 | } |
1572 | return rv; |
1573 | } |
1574 | |
1575 | void Newsgroups::( const QString &s, const QByteArray &b ) |
1576 | { |
1577 | Q_UNUSED( b ); |
1578 | Q_D( Newsgroups ); |
1579 | from7BitString( s.toUtf8() ); |
1580 | d->encCS = cachedCharset( "UTF-8" ); |
1581 | } |
1582 | |
1583 | QString Newsgroups::() const |
1584 | { |
1585 | return QString::fromUtf8( as7BitString( false ) ); |
1586 | } |
1587 | |
1588 | void Newsgroups::() |
1589 | { |
1590 | Q_D( Newsgroups ); |
1591 | d->groups.clear(); |
1592 | } |
1593 | |
1594 | bool Newsgroups::() const |
1595 | { |
1596 | return d_func()->groups.isEmpty(); |
1597 | } |
1598 | |
1599 | QList<QByteArray> Newsgroups::() const |
1600 | { |
1601 | return d_func()->groups; |
1602 | } |
1603 | |
1604 | void Newsgroups::( const QList<QByteArray> &groups ) |
1605 | { |
1606 | Q_D( Newsgroups ); |
1607 | d->groups = groups; |
1608 | } |
1609 | |
1610 | bool Newsgroups::() const |
1611 | { |
1612 | return d_func()->groups.count() >= 2; |
1613 | } |
1614 | |
1615 | bool Newsgroups::( const char* &scursor, const char *const send, bool isCRLF ) |
1616 | { |
1617 | Q_D( Newsgroups ); |
1618 | clear(); |
1619 | forever { |
1620 | eatCFWS( scursor, send, isCRLF ); |
1621 | if ( scursor != send && *scursor == ',' ) { |
1622 | ++scursor; |
1623 | } |
1624 | eatCFWS( scursor, send, isCRLF ); |
1625 | if ( scursor == send ) { |
1626 | return true; |
1627 | } |
1628 | const char *start = scursor; |
1629 | while ( scursor != send && !isspace( *scursor ) && *scursor != ',' ) { |
1630 | ++scursor; |
1631 | } |
1632 | QByteArray group( start, scursor - start ); |
1633 | d->groups.append( group ); |
1634 | } |
1635 | return true; |
1636 | } |
1637 | |
1638 | //-----</Newsgroups>--------------------------- |
1639 | |
1640 | //-----<Lines>--------------------------------- |
1641 | |
1642 | //@cond PRIVATE |
1643 | kmime_mk_trivial_ctor_with_name_and_dptr( , Generics::Structured, Lines ) |
1644 | //@endcond |
1645 | |
1646 | QByteArray Lines::( bool ) const |
1647 | { |
1648 | if ( isEmpty() ) { |
1649 | return QByteArray(); |
1650 | } |
1651 | |
1652 | QByteArray num; |
1653 | num.setNum( d_func()->lines ); |
1654 | |
1655 | if ( withHeaderType ) { |
1656 | return typeIntro() + num; |
1657 | } |
1658 | return num; |
1659 | } |
1660 | |
1661 | QString Lines::() const |
1662 | { |
1663 | if ( isEmpty() ) { |
1664 | return QString(); |
1665 | } |
1666 | return QString::number( d_func()->lines ); |
1667 | } |
1668 | |
1669 | void Lines::() |
1670 | { |
1671 | Q_D( Lines ); |
1672 | d->lines = -1; |
1673 | } |
1674 | |
1675 | bool Lines::() const |
1676 | { |
1677 | return d_func()->lines == -1; |
1678 | } |
1679 | |
1680 | int Lines::() const |
1681 | { |
1682 | return d_func()->lines; |
1683 | } |
1684 | |
1685 | void Lines::( int lines ) |
1686 | { |
1687 | Q_D( Lines ); |
1688 | d->lines = lines; |
1689 | } |
1690 | |
1691 | bool Lines::( const char* &scursor, const char* const send, bool isCRLF ) |
1692 | { |
1693 | Q_D( Lines ); |
1694 | eatCFWS( scursor, send, isCRLF ); |
1695 | if ( parseDigits( scursor, send, d->lines ) == 0 ) { |
1696 | clear(); |
1697 | return false; |
1698 | } |
1699 | return true; |
1700 | } |
1701 | |
1702 | //-----</Lines>-------------------------------- |
1703 | |
1704 | //-----<Content-Type>-------------------------- |
1705 | |
1706 | //@cond PRIVATE |
1707 | kmime_mk_trivial_ctor_with_name_and_dptr( , Generics::Parametrized, |
1708 | Content-Type ) |
1709 | //@endcond |
1710 | |
1711 | bool ContentType::() const |
1712 | { |
1713 | return d_func()->mimeType.isEmpty(); |
1714 | } |
1715 | |
1716 | void ContentType::() |
1717 | { |
1718 | Q_D( ContentType ); |
1719 | d->category = CCsingle; |
1720 | d->mimeType.clear(); |
1721 | Parametrized::clear(); |
1722 | } |
1723 | |
1724 | QByteArray ContentType::( bool ) const |
1725 | { |
1726 | if ( isEmpty() ) { |
1727 | return QByteArray(); |
1728 | } |
1729 | |
1730 | QByteArray rv; |
1731 | if ( withHeaderType ) { |
1732 | rv += typeIntro(); |
1733 | } |
1734 | |
1735 | rv += mimeType(); |
1736 | if ( !Parametrized::isEmpty() ) { |
1737 | rv += "; " + Parametrized::as7BitString( false ); |
1738 | } |
1739 | |
1740 | return rv; |
1741 | } |
1742 | |
1743 | QByteArray ContentType::() const |
1744 | { |
1745 | Q_D( const ContentType ); |
1746 | return d->mimeType; |
1747 | } |
1748 | |
1749 | QByteArray ContentType::() const |
1750 | { |
1751 | Q_D( const ContentType ); |
1752 | const int pos = d->mimeType.indexOf( '/' ); |
1753 | if ( pos < 0 ) { |
1754 | return d->mimeType; |
1755 | } else { |
1756 | return d->mimeType.left( pos ); |
1757 | } |
1758 | } |
1759 | |
1760 | QByteArray ContentType::() const |
1761 | { |
1762 | Q_D( const ContentType ); |
1763 | const int pos = d->mimeType.indexOf( '/' ); |
1764 | if ( pos < 0 ) { |
1765 | return QByteArray(); |
1766 | } else { |
1767 | return d->mimeType.mid( pos + 1 ); |
1768 | } |
1769 | } |
1770 | |
1771 | void ContentType::( const QByteArray &mimeType ) |
1772 | { |
1773 | Q_D( ContentType ); |
1774 | d->mimeType = mimeType; |
1775 | Parametrized::clear(); |
1776 | |
1777 | if ( isMultipart() ) { |
1778 | d->category = CCcontainer; |
1779 | } else { |
1780 | d->category = CCsingle; |
1781 | } |
1782 | } |
1783 | |
1784 | bool ContentType::( const char *mediatype ) const |
1785 | { |
1786 | Q_D( const ContentType ); |
1787 | const int len = strlen( mediatype ); |
1788 | return qstrnicmp( d->mimeType.constData(), mediatype, len ) == 0 && |
1789 | ( d->mimeType.at( len ) == '/' || d->mimeType.size() == len ); |
1790 | } |
1791 | |
1792 | bool ContentType::( const char *subtype ) const |
1793 | { |
1794 | Q_D( const ContentType ); |
1795 | const int pos = d->mimeType.indexOf( '/' ); |
1796 | if ( pos < 0 ) { |
1797 | return false; |
1798 | } |
1799 | const int len = strlen( subtype ); |
1800 | return qstrnicmp( d->mimeType.constData() + pos + 1, subtype, len ) == 0 && |
1801 | d->mimeType.size() == pos + len + 1; |
1802 | } |
1803 | |
1804 | bool ContentType::() const |
1805 | { |
1806 | return ( isMediatype( "text" ) || isEmpty() ); |
1807 | } |
1808 | |
1809 | bool ContentType::() const |
1810 | { |
1811 | return ( qstricmp( d_func()->mimeType.constData(), "text/plain" ) == 0 || isEmpty() ); |
1812 | } |
1813 | |
1814 | bool ContentType::() const |
1815 | { |
1816 | return qstricmp( d_func()->mimeType.constData(), "text/html" ) == 0; |
1817 | } |
1818 | |
1819 | bool ContentType::() const |
1820 | { |
1821 | return isMediatype( "image" ); |
1822 | } |
1823 | |
1824 | bool ContentType::() const |
1825 | { |
1826 | return isMediatype( "multipart" ); |
1827 | } |
1828 | |
1829 | bool ContentType::() const |
1830 | { |
1831 | return qstricmp( d_func()->mimeType.constData(), "message/partial" ) == 0; |
1832 | } |
1833 | |
1834 | QByteArray ContentType::() const |
1835 | { |
1836 | QByteArray ret = parameter( QLatin1String( "charset" ) ).toLatin1(); |
1837 | if ( ret.isEmpty() || forceDefaultCharset() ) { |
1838 | //return the default-charset if necessary |
1839 | ret = defaultCharset(); |
1840 | } |
1841 | return ret; |
1842 | } |
1843 | |
1844 | void ContentType::( const QByteArray &s ) |
1845 | { |
1846 | setParameter( QLatin1String( "charset" ), QString::fromLatin1( s ) ); |
1847 | } |
1848 | |
1849 | QByteArray ContentType::() const |
1850 | { |
1851 | return parameter( QLatin1String( "boundary" ) ).toLatin1(); |
1852 | } |
1853 | |
1854 | void ContentType::( const QByteArray &s ) |
1855 | { |
1856 | setParameter( QLatin1String( "boundary" ), QString::fromLatin1( s ) ); |
1857 | } |
1858 | |
1859 | QString ContentType::() const |
1860 | { |
1861 | return parameter( QLatin1String( "name" ) ); |
1862 | } |
1863 | |
1864 | void ContentType::( const QString &s, const QByteArray &cs ) |
1865 | { |
1866 | Q_D( ContentType ); |
1867 | d->encCS = cs; |
1868 | setParameter( QLatin1String( "name" ), s ); |
1869 | } |
1870 | |
1871 | QByteArray ContentType::() const |
1872 | { |
1873 | return parameter( QLatin1String( "id" ) ).toLatin1(); |
1874 | } |
1875 | |
1876 | void ContentType::( const QByteArray &s ) |
1877 | { |
1878 | setParameter( QLatin1String( "id" ), QString::fromLatin1( s ) ); |
1879 | } |
1880 | |
1881 | int ContentType::() const |
1882 | { |
1883 | QByteArray p = parameter( QLatin1String( "number" ) ).toLatin1(); |
1884 | if ( !p.isEmpty() ) { |
1885 | return p.toInt(); |
1886 | } else { |
1887 | return -1; |
1888 | } |
1889 | } |
1890 | |
1891 | int ContentType::() const |
1892 | { |
1893 | QByteArray p = parameter( QLatin1String( "total" ) ).toLatin1(); |
1894 | if ( !p.isEmpty() ) { |
1895 | return p.toInt(); |
1896 | } else { |
1897 | return -1; |
1898 | } |
1899 | } |
1900 | |
1901 | contentCategory ContentType::() const |
1902 | { |
1903 | return d_func()->category; |
1904 | } |
1905 | |
1906 | void ContentType::( contentCategory c ) |
1907 | { |
1908 | Q_D( ContentType ); |
1909 | d->category = c; |
1910 | } |
1911 | |
1912 | void ContentType::( int total, int number ) |
1913 | { |
1914 | setParameter( QLatin1String( "number" ), QString::number( number ) ); |
1915 | setParameter( QLatin1String( "total" ), QString::number( total ) ); |
1916 | } |
1917 | |
1918 | bool ContentType::( const char* &scursor, const char * const send, |
1919 | bool isCRLF ) |
1920 | { |
1921 | Q_D( ContentType ); |
1922 | // content-type: type "/" subtype *(";" parameter) |
1923 | |
1924 | clear(); |
1925 | eatCFWS( scursor, send, isCRLF ); |
1926 | if ( scursor == send ) { |
1927 | return false; // empty header |
1928 | } |
1929 | |
1930 | // type |
1931 | QPair<const char*, int> maybeMimeType; |
1932 | if ( !parseToken( scursor, send, maybeMimeType, false /* no 8Bit */ ) ) { |
1933 | return false; |
1934 | } |
1935 | |
1936 | // subtype |
1937 | eatCFWS( scursor, send, isCRLF ); |
1938 | if ( scursor == send || *scursor != '/' ) { |
1939 | return false; |
1940 | } |
1941 | scursor++; |
1942 | eatCFWS( scursor, send, isCRLF ); |
1943 | if ( scursor == send ) { |
1944 | return false; |
1945 | } |
1946 | |
1947 | QPair<const char*, int> maybeSubType; |
1948 | if ( !parseToken( scursor, send, maybeSubType, false /* no 8bit */ ) ) { |
1949 | return false; |
1950 | } |
1951 | |
1952 | d->mimeType.reserve( maybeMimeType.second + maybeSubType.second + 1 ); |
1953 | d->mimeType = QByteArray( maybeMimeType.first, maybeMimeType.second ).toLower() |
1954 | + '/' + QByteArray( maybeSubType.first, maybeSubType.second ).toLower(); |
1955 | |
1956 | // parameter list |
1957 | eatCFWS( scursor, send, isCRLF ); |
1958 | if ( scursor == send ) { |
1959 | goto success; // no parameters |
1960 | } |
1961 | |
1962 | if ( *scursor != ';' ) { |
1963 | return false; |
1964 | } |
1965 | scursor++; |
1966 | |
1967 | if ( !Parametrized::parse( scursor, send, isCRLF ) ) { |
1968 | return false; |
1969 | } |
1970 | |
1971 | // adjust category |
1972 | success: |
1973 | if ( isMultipart() ) { |
1974 | d->category = CCcontainer; |
1975 | } else { |
1976 | d->category = CCsingle; |
1977 | } |
1978 | return true; |
1979 | } |
1980 | |
1981 | //-----</Content-Type>------------------------- |
1982 | |
1983 | //-----<ContentID>---------------------- |
1984 | |
1985 | kmime_mk_trivial_ctor_with_name_and_dptr( , SingleIdent, Content-ID ) |
1986 | kmime_mk_dptr_ctor( , SingleIdent ) |
1987 | |
1988 | bool ContentID::( const char* &scursor, const char *const send, bool isCRLF ) |
1989 | { |
1990 | Q_D ( ContentID ); |
1991 | // Content-id := "<" contentid ">" |
1992 | // contentid := now whitespaces |
1993 | |
1994 | const char* origscursor = scursor; |
1995 | if ( !SingleIdent::parse ( scursor, send, isCRLF ) ) { |
1996 | scursor = origscursor; |
1997 | d->msgIdList.clear(); |
1998 | d->cachedIdentifier.clear(); |
1999 | |
2000 | while ( scursor != send ) { |
2001 | eatCFWS ( scursor, send, isCRLF ); |
2002 | // empty entry ending the list: OK. |
2003 | if ( scursor == send ) { |
2004 | return true; |
2005 | } |
2006 | // empty entry: ignore. |
2007 | if ( *scursor == ',' ) { |
2008 | scursor++; |
2009 | continue; |
2010 | } |
2011 | |
2012 | AddrSpec maybeContentId; |
2013 | // Almost parseAngleAddr |
2014 | if ( scursor == send || *scursor != '<' ) { |
2015 | return false; |
2016 | } |
2017 | scursor++; // eat '<' |
2018 | |
2019 | eatCFWS ( scursor, send, isCRLF ); |
2020 | if ( scursor == send ) { |
2021 | return false; |
2022 | } |
2023 | |
2024 | // Save chars untill '>'' |
2025 | QString result; |
2026 | if( !parseDotAtom(scursor, send, result, false) ) { |
2027 | return false; |
2028 | } |
2029 | |
2030 | eatCFWS ( scursor, send, isCRLF ); |
2031 | if ( scursor == send || *scursor != '>' ) { |
2032 | return false; |
2033 | } |
2034 | scursor++; |
2035 | // /Almost parseAngleAddr |
2036 | |
2037 | maybeContentId.localPart = result; |
2038 | d->msgIdList.append ( maybeContentId ); |
2039 | |
2040 | eatCFWS ( scursor, send, isCRLF ); |
2041 | // header end ending the list: OK. |
2042 | if ( scursor == send ) { |
2043 | return true; |
2044 | } |
2045 | // regular item separator: eat it. |
2046 | if ( *scursor == ',' ) { |
2047 | scursor++; |
2048 | } |
2049 | } |
2050 | return true; |
2051 | } |
2052 | else |
2053 | { |
2054 | return true; |
2055 | } |
2056 | } |
2057 | |
2058 | //-----</ContentID>---------------------- |
2059 | |
2060 | //-----<ContentTransferEncoding>---------------------------- |
2061 | |
2062 | //@cond PRIVATE |
2063 | kmime_mk_trivial_ctor_with_name_and_dptr( , |
2064 | Generics::Token, Content-Transfer-Encoding ) |
2065 | //@endcond |
2066 | |
2067 | typedef struct { const char *; int ; } ; |
2068 | |
2069 | static const encTableType [] = |
2070 | { |
2071 | { "7Bit" , CE7Bit }, |
2072 | { "8Bit" , CE8Bit }, |
2073 | { "quoted-printable" , CEquPr }, |
2074 | { "base64" , CEbase64 }, |
2075 | { "x-uuencode" , CEuuenc }, |
2076 | { "binary" , CEbinary }, |
2077 | { 0, 0} |
2078 | }; |
2079 | |
2080 | void ContentTransferEncoding::() |
2081 | { |
2082 | Q_D( ContentTransferEncoding ); |
2083 | d->decoded = true; |
2084 | d->cte = CE7Bit; |
2085 | Token::clear(); |
2086 | } |
2087 | |
2088 | contentEncoding ContentTransferEncoding::() const |
2089 | { |
2090 | return d_func()->cte; |
2091 | } |
2092 | |
2093 | void ContentTransferEncoding::( contentEncoding e ) |
2094 | { |
2095 | Q_D( ContentTransferEncoding ); |
2096 | d->cte = e; |
2097 | |
2098 | for ( int i = 0; encTable[i].s != 0; ++i ) { |
2099 | if ( d->cte == encTable[i].e ) { |
2100 | setToken( encTable[i].s ); |
2101 | break; |
2102 | } |
2103 | } |
2104 | } |
2105 | |
2106 | bool ContentTransferEncoding::() const |
2107 | { |
2108 | return d_func()->decoded; |
2109 | } |
2110 | |
2111 | void ContentTransferEncoding::( bool decoded ) |
2112 | { |
2113 | Q_D( ContentTransferEncoding ); |
2114 | d->decoded = decoded; |
2115 | } |
2116 | |
2117 | bool ContentTransferEncoding::() const |
2118 | { |
2119 | const Q_D( ContentTransferEncoding ); |
2120 | return d->decoded && ( d->cte == CEquPr || d->cte == CEbase64 ); |
2121 | } |
2122 | |
2123 | bool ContentTransferEncoding::( const char *& scursor, |
2124 | const char * const send, bool isCRLF ) |
2125 | { |
2126 | Q_D( ContentTransferEncoding ); |
2127 | clear(); |
2128 | if ( !Token::parse( scursor, send, isCRLF ) ) { |
2129 | return false; |
2130 | } |
2131 | |
2132 | // TODO: error handling in case of an unknown encoding? |
2133 | for ( int i = 0; encTable[i].s != 0; ++i ) { |
2134 | if ( qstricmp( token().constData(), encTable[i].s ) == 0 ) { |
2135 | d->cte = ( contentEncoding )encTable[i].e; |
2136 | break; |
2137 | } |
2138 | } |
2139 | d->decoded = ( d->cte == CE7Bit || d->cte == CE8Bit ); |
2140 | return true; |
2141 | } |
2142 | |
2143 | //-----</ContentTransferEncoding>--------------------------- |
2144 | |
2145 | //-----<ContentDisposition>-------------------------- |
2146 | |
2147 | //@cond PRIVATE |
2148 | kmime_mk_trivial_ctor_with_name_and_dptr( , |
2149 | Generics::Parametrized, Content-Disposition ) |
2150 | //@endcond |
2151 | |
2152 | QByteArray ContentDisposition::( bool ) const |
2153 | { |
2154 | if ( isEmpty() ) { |
2155 | return QByteArray(); |
2156 | } |
2157 | |
2158 | QByteArray rv; |
2159 | if ( withHeaderType ) { |
2160 | rv += typeIntro(); |
2161 | } |
2162 | |
2163 | if ( d_func()->disposition == CDattachment ) { |
2164 | rv += "attachment" ; |
2165 | } else if ( d_func()->disposition == CDinline ) { |
2166 | rv += "inline" ; |
2167 | } else { |
2168 | return QByteArray(); |
2169 | } |
2170 | |
2171 | if ( !Parametrized::isEmpty() ) { |
2172 | rv += "; " + Parametrized::as7BitString( false ); |
2173 | } |
2174 | |
2175 | return rv; |
2176 | } |
2177 | |
2178 | bool ContentDisposition::() const |
2179 | { |
2180 | return d_func()->disposition == CDInvalid; |
2181 | } |
2182 | |
2183 | void ContentDisposition::() |
2184 | { |
2185 | Q_D( ContentDisposition ); |
2186 | d->disposition = CDInvalid; |
2187 | Parametrized::clear(); |
2188 | } |
2189 | |
2190 | contentDisposition ContentDisposition::() const |
2191 | { |
2192 | return d_func()->disposition; |
2193 | } |
2194 | |
2195 | void ContentDisposition::( contentDisposition disp ) |
2196 | { |
2197 | Q_D( ContentDisposition ); |
2198 | d->disposition = disp; |
2199 | } |
2200 | |
2201 | QString KMime::Headers::ContentDisposition::() const |
2202 | { |
2203 | return parameter( QLatin1String( "filename" ) ); |
2204 | } |
2205 | |
2206 | void ContentDisposition::( const QString &filename ) |
2207 | { |
2208 | setParameter( QLatin1String( "filename" ), filename ); |
2209 | } |
2210 | |
2211 | bool ContentDisposition::( const char *& scursor, const char * const send, |
2212 | bool isCRLF ) |
2213 | { |
2214 | Q_D( ContentDisposition ); |
2215 | clear(); |
2216 | |
2217 | // token |
2218 | QByteArray token; |
2219 | eatCFWS( scursor, send, isCRLF ); |
2220 | if ( scursor == send ) { |
2221 | return false; |
2222 | } |
2223 | |
2224 | QPair<const char*, int> maybeToken; |
2225 | if ( !parseToken( scursor, send, maybeToken, false /* no 8Bit */ ) ) { |
2226 | return false; |
2227 | } |
2228 | |
2229 | token = QByteArray( maybeToken.first, maybeToken.second ).toLower(); |
2230 | if ( token == "inline" ) { |
2231 | d->disposition = CDinline; |
2232 | } else if ( token == "attachment" ) { |
2233 | d->disposition = CDattachment; |
2234 | } else { |
2235 | return false; |
2236 | } |
2237 | |
2238 | // parameter list |
2239 | eatCFWS( scursor, send, isCRLF ); |
2240 | if ( scursor == send ) { |
2241 | return true; // no parameters |
2242 | } |
2243 | |
2244 | if ( *scursor != ';' ) { |
2245 | return false; |
2246 | } |
2247 | scursor++; |
2248 | |
2249 | return Parametrized::parse( scursor, send, isCRLF ); |
2250 | } |
2251 | |
2252 | //-----</ContentDisposition>------------------------- |
2253 | |
2254 | //@cond PRIVATE |
2255 | kmime_mk_trivial_ctor_with_name( , Generics::Unstructured, Subject ) |
2256 | //@endcond |
2257 | |
2258 | bool Subject::() const |
2259 | { |
2260 | return asUnicodeString().indexOf( QLatin1String( "Re:" ), 0, Qt::CaseInsensitive ) == 0; |
2261 | } |
2262 | |
2263 | Base* ( const QByteArray& type ) |
2264 | { |
2265 | return HeaderFactory::self()->createHeader( type ); |
2266 | } |
2267 | |
2268 | |
2269 | //@cond PRIVATE |
2270 | kmime_mk_trivial_ctor_with_name( , |
2271 | Generics::Unstructured, Content-Description ) |
2272 | kmime_mk_trivial_ctor_with_name( , |
2273 | Generics::Unstructured, Content-Location ) |
2274 | kmime_mk_trivial_ctor_with_name( , Generics::MailboxList, From ) |
2275 | kmime_mk_trivial_ctor_with_name( , Generics::SingleMailbox, Sender ) |
2276 | kmime_mk_trivial_ctor_with_name( , Generics::AddressList, To ) |
2277 | kmime_mk_trivial_ctor_with_name( , Generics::AddressList, Cc ) |
2278 | kmime_mk_trivial_ctor_with_name( , Generics::AddressList, Bcc ) |
2279 | kmime_mk_trivial_ctor_with_name( , Generics::AddressList, Reply-To ) |
2280 | kmime_mk_trivial_ctor_with_name( , Generics::PhraseList, Keywords ) |
2281 | kmime_mk_trivial_ctor_with_name( , Generics::DotAtom, MIME-Version ) |
2282 | kmime_mk_trivial_ctor_with_name( , Generics::SingleIdent, Supersedes ) |
2283 | kmime_mk_trivial_ctor_with_name( , Generics::Ident, In-Reply-To ) |
2284 | kmime_mk_trivial_ctor_with_name( , Generics::Ident, References ) |
2285 | kmime_mk_trivial_ctor_with_name( , Generics::Unstructured, Organization ) |
2286 | kmime_mk_trivial_ctor_with_name( , Generics::Unstructured, User-Agent ) |
2287 | //@endcond |
2288 | |
2289 | } // namespace Headers |
2290 | |
2291 | } // namespace KMime |
2292 | |