41 #include "kmime_headers_p.h"
43 #include "kmime_util.h"
44 #include "kmime_util_p.h"
47 #include "kmime_header_parsing.h"
49 #include "kmime_warning.h"
51 #include <QtCore/QTextCodec>
52 #include <QtCore/QString>
53 #include <QtCore/QStringList>
56 #include <kcharsets.h>
62 bool registerHeaderHelper()
65 if ( QByteArray( dummy.type() ).isEmpty() ) {
69 return KMime::HeaderFactory::self()->registerHeader<T>();
73 #define kmime_register_header( subclass ) \
74 namespace { const bool dummyForRegistering##subclass = registerHeaderHelper<subclass>(); }
77 #define kmime_mk_trivial_ctor( subclass, baseclass ) \
78 subclass::subclass( Content *parent ) : baseclass( parent ) \
83 subclass::subclass( Content *parent, const QByteArray &s ) : baseclass( parent ) \
85 from7BitString( s ); \
88 subclass::subclass( Content *parent, const QString &s, const QByteArray &charset ) : \
91 fromUnicodeString( s, charset ); \
94 subclass::~subclass() {} \
96 kmime_register_header( subclass )
100 #define kmime_mk_trivial_ctor_with_dptr( subclass, baseclass ) \
101 subclass::subclass( Content *parent ) : baseclass( new subclass##Private, parent ) \
106 subclass::subclass( Content *parent, const QByteArray &s ) : baseclass( new subclass##Private, parent ) \
108 from7BitString( s ); \
111 subclass::subclass( Content *parent, const QString &s, const QByteArray &charset ) : \
112 baseclass( new subclass##Private, parent ) \
114 fromUnicodeString( s, charset ); \
117 subclass::~subclass() {} \
119 kmime_register_header( subclass )
123 #define kmime_mk_trivial_ctor_with_name( subclass, baseclass, name ) \
124 kmime_mk_trivial_ctor( subclass, baseclass ) \
126 const char *subclass::type() const \
128 return staticType(); \
130 const char *subclass::staticType() { return #name; }
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::type() const { return staticType(); } \
135 const char *subclass::staticType() { return #name; }
137 #define kmime_mk_dptr_ctor( subclass, baseclass ) \
138 subclass::subclass( subclass##Private *d, KMime::Content *parent ) : baseclass( d, parent ) {}
140 using namespace KMime;
141 using namespace KMime::Headers;
142 using namespace KMime::Types;
143 using namespace KMime::HeaderParsing;
149 d_ptr( new BasePrivate )
209 return qstricmp( t,
type() ) == 0;
214 return qstrnicmp(
type(),
"Content-", 8 ) == 0;
219 return qstrncmp(
type(),
"X-", 2 ) == 0;
224 return QByteArray(
type() ) +
": ";
234 kmime_mk_dptr_ctor( Unstructured,
Base )
237 Unstructured::Unstructured(
Content *p ) :
Base( new UnstructuredPrivate, p )
241 Unstructured::Unstructured(
Content *p,
const QByteArray &s ) :
Base( new UnstructuredPrivate, p )
246 Unstructured::Unstructured(
Content *p,
const QString &s,
const QByteArray &cs ) :
Base( new UnstructuredPrivate, p )
251 Unstructured::~Unstructured()
255 void Unstructured::from7BitString(
const QByteArray &s )
261 QByteArray Unstructured::as7BitString(
bool withHeaderType )
const
265 if ( withHeaderType ) {
266 result = typeIntro();
273 void Unstructured::fromUnicodeString(
const QString &s,
const QByteArray &b )
280 QString Unstructured::asUnicodeString()
const
282 return d_func()->decoded;
285 void Unstructured::clear()
288 d->decoded.truncate( 0 );
291 bool Unstructured::isEmpty()
const
293 return d_func()->decoded.isEmpty();
300 Structured::Structured(
Content *p ) :
Base( new StructuredPrivate, p )
304 Structured::Structured(
Content *p,
const QByteArray &s ) :
Base( new StructuredPrivate, p )
309 Structured::Structured(
Content *p,
const QString &s,
const QByteArray &cs ) :
Base( new StructuredPrivate, p )
314 kmime_mk_dptr_ctor( Structured,
Base )
316 Structured::~Structured()
323 if ( d->encCS.isEmpty() ) {
326 const char *cursor = s.constData();
327 parse( cursor, cursor + s.length() );
350 Address::Address(
Content *p,
const QByteArray &s ) : Structured( new AddressPrivate, p )
355 Address::Address(
Content *p,
const QString &s,
const QByteArray &cs ) : Structured( new AddressPrivate, p )
360 kmime_mk_dptr_ctor( Address, Structured )
367 static bool stringToMailbox(
const QByteArray &address,
370 Types::AddrSpec addrSpec;
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";
387 kmime_mk_trivial_ctor_with_dptr( MailboxList, Address )
388 kmime_mk_dptr_ctor( MailboxList, Address )
390 QByteArray MailboxList::as7BitString(
bool withHeaderType )
const
392 const Q_D( MailboxList );
398 if ( withHeaderType ) {
405 rv.resize( rv.length() - 2 );
424 d->mailboxList.clear();
429 return d_func()->mailboxList.isEmpty();
435 d->mailboxList.append( mbox );
439 const QString &displayName )
443 if ( stringToMailbox( address, displayName, mbox ) ) {
444 d->mailboxList.append( mbox );
450 QList<QByteArray> rv;
461 rv.append( mbox.
name() );
477 return d_func()->mailboxList;
489 QList<Types::Address> maybeAddressList;
490 if ( !parseAddressList( scursor, send, maybeAddressList, isCRLF ) ) {
494 d->mailboxList.clear();
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;
503 d->mailboxList += ( *it ).mailboxList;
524 if ( d->mailboxList.count() > 1 ) {
525 KMIME_WARN <<
"multiple mailboxes in header allowing only a single one!"
540 QByteArray AddressList::as7BitString(
bool withHeaderType )
const
542 const Q_D( AddressList );
543 if ( d->addressList.isEmpty() ) {
548 if ( withHeaderType ) {
551 foreach (
const Types::Address &addr, d->addressList ) {
557 rv.resize( rv.length() - 2 );
576 d->addressList.clear();
581 return d_func()->addressList.isEmpty();
588 addr.mailboxList.append( mbox );
589 d->addressList.append( addr );
593 const QString &displayName )
598 if ( stringToMailbox( address, displayName, mbox ) ) {
599 addr.mailboxList.append( mbox );
600 d->addressList.append( addr );
606 QList<QByteArray> rv;
607 foreach (
const Types::Address &addr, d_func()->addressList ) {
618 foreach (
const Types::Address &addr, d_func()->addressList ) {
620 rv.append( mbox.
name() );
629 foreach (
const Types::Address &addr, d_func()->addressList ) {
639 Types::Mailbox::List rv;
640 foreach (
const Types::Address &addr, d_func()->addressList ) {
652 QList<Types::Address> maybeAddressList;
653 if ( !parseAddressList( scursor, send, maybeAddressList, isCRLF ) ) {
657 d->addressList = maybeAddressList;
670 QByteArray Token::as7BitString(
bool withHeaderType )
const
675 if ( withHeaderType ) {
676 return typeIntro() + d_func()->token;
678 return d_func()->token;
689 return d_func()->token.isEmpty();
694 return d_func()->token;
703 bool Token::parse(
const char* &scursor,
const char *
const send,
bool isCRLF )
707 eatCFWS( scursor, send, isCRLF );
709 if ( scursor == send ) {
713 QPair<const char*, int> maybeToken;
714 if ( !parseToken( scursor, send, maybeToken,
false ) ) {
717 d->token = QByteArray( maybeToken.first, maybeToken.second );
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;
736 QByteArray
PhraseList::as7BitString(
bool withHeaderType )
const
744 if ( withHeaderType ) {
748 for (
int i = 0; i < d->phraseList.count(); ++i ) {
751 if ( i != d->phraseList.count() - 1 ) {
761 return d_func()->phraseList.join( QLatin1String(
", " ) );
767 d->phraseList.clear();
772 return d_func()->phraseList.isEmpty();
777 return d_func()->phraseList;
784 d->phraseList.clear();
786 while ( scursor != send ) {
787 eatCFWS( scursor, send, isCRLF );
789 if ( scursor == send ) {
793 if ( *scursor ==
',' ) {
799 if ( !parsePhrase( scursor, send, maybePhrase, isCRLF ) ) {
802 d->phraseList.append( maybePhrase );
804 eatCFWS( scursor, send, isCRLF );
806 if ( scursor == send ) {
810 if ( *scursor ==
',' ) {
825 QByteArray
DotAtom::as7BitString(
bool withHeaderType )
const
832 if ( withHeaderType ) {
836 rv += d_func()->dotAtom.toLatin1();
842 return d_func()->dotAtom;
853 return d_func()->dotAtom.isEmpty();
860 QString maybeDotAtom;
861 if ( !parseDotAtom( scursor, send, maybeDotAtom, isCRLF ) ) {
865 d->dotAtom = maybeDotAtom;
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;
884 QByteArray Parametrized::as7BitString(
bool withHeaderType )
const
886 const Q_D( Parametrized );
892 if ( withHeaderType ) {
897 for ( QMap<QString, QString>::ConstIterator it = d->parameterHash.constBegin();
898 it != d->parameterHash.constEnd(); ++it ) {
905 rv += it.key().toLatin1() +
'=';
906 QByteArray tmp = it.value().toLatin1();
911 rv += it.key().toLatin1() +
'=';
912 kDebug() <<
"doing:" << it.value() << QLatin1String( d->encCS );
915 rv += it.key().toLatin1() +
"*=";
926 return d_func()->parameterHash.value( key.toLower() );
931 return d_func()->parameterHash.contains( key.toLower() );
937 d->parameterHash.insert( key.toLower(), value );
942 return d_func()->parameterHash.isEmpty();
948 d->parameterHash.clear();
955 d->parameterHash.clear();
957 if ( !parseParameterListWithCharset( scursor, send, d->parameterHash, charset, isCRLF ) ) {
973 QByteArray Ident::as7BitString(
bool withHeaderType )
const
976 if ( d->msgIdList.isEmpty() ) {
981 if ( withHeaderType ) {
984 foreach (
const Types::AddrSpec &addr, d->msgIdList ) {
985 if ( !addr.isEmpty() ) {
986 const QString asString = addr.asString();
988 if ( !asString.isEmpty() ) {
989 rv += asString.toLatin1();
994 if ( !rv.isEmpty() ) {
995 rv.resize( rv.length() - 1 );
1003 d->msgIdList.clear();
1004 d->cachedIdentifier.clear();
1009 return d_func()->msgIdList.isEmpty();
1012 bool Ident::parse(
const char* &scursor,
const char *
const send,
bool isCRLF )
1022 d->msgIdList.clear();
1023 d->cachedIdentifier.clear();
1025 while ( scursor != send ) {
1026 eatCFWS( scursor, send, isCRLF );
1028 if ( scursor == send ) {
1032 if ( *scursor ==
',' ) {
1037 AddrSpec maybeMsgId;
1038 if ( !parseAngleAddr( scursor, send, maybeMsgId, isCRLF ) ) {
1041 d->msgIdList.append( maybeMsgId );
1043 eatCFWS( scursor, send, isCRLF );
1045 if ( scursor == send ) {
1049 if ( *scursor ==
',' ) {
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() );
1073 QByteArray tmp = id;
1074 if ( !tmp.startsWith(
'<' ) ) {
1077 if ( !tmp.endsWith(
'>' ) ) {
1081 const char *cursor = tmp.constData();
1082 if ( parseAngleAddr( cursor, cursor + tmp.length(), msgId ) ) {
1083 d->msgIdList.append( msgId );
1085 kWarning() <<
"Unable to parse address spec!";
1098 QByteArray SingleIdent::identifier()
const
1100 if ( d_func()->msgIdList.isEmpty() ) {
1101 return QByteArray();
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();
1114 return d_func()->cachedIdentifier;
1120 d->msgIdList.clear();
1121 d->cachedIdentifier.clear();
1133 if ( d->msgIdList.count() > 1 ) {
1134 KMIME_WARN <<
"more than one msg-id in header "
1135 <<
"allowing only a single one!" << endl;
1153 return QByteArray();
1157 if ( withHeaderType ) {
1160 rv +=
'<' + d_func()->mailbox.as7BitString( d_func()->encCS ) +
'>';
1167 d->mailbox.setAddress( Types::AddrSpec() );
1168 d->mailbox.setName( QString() );
1174 return !d->mailbox.hasAddress() && !d->mailbox.hasName();
1181 eatCFWS( scursor, send, isCRLF );
1182 if ( scursor == send ) {
1186 const char * oldscursor = scursor;
1189 if ( !parseMailbox( scursor, send, maybeMailbox, isCRLF ) ) {
1191 scursor = oldscursor;
1192 if ( *scursor !=
'<' ) {
1196 eatCFWS( scursor, send, isCRLF );
1197 if ( scursor == send || *scursor !=
'>' ) {
1203 AddrSpec emptyAddrSpec;
1204 maybeMailbox.
setName( QString() );
1208 if ( maybeMailbox.
hasName() ) {
1209 KMIME_WARN <<
"display-name \"" << maybeMailbox.
name()
1210 <<
"\" in Return-Path!" << endl;
1213 d->mailbox = maybeMailbox;
1216 eatCFWS( scursor, send, isCRLF );
1218 if ( scursor != send ) {
1219 KMIME_WARN <<
"trailing garbage after angle-addr in Return-Path!" << endl;
1230 Generic::Generic() : Generics::Unstructured( new GenericPrivate )
1234 Generic::Generic(
const char *t ) : Generics::Unstructured( new GenericPrivate )
1239 Generic::Generic(
const char *t,
Content *p )
1240 : Generics::Unstructured( new GenericPrivate, p )
1245 Generic::Generic(
const char *t,
Content *p,
const QByteArray &s )
1246 : Generics::Unstructured( new GenericPrivate, p )
1252 Generic::Generic(
const char *t,
Content *p,
const QString &s,
const QByteArray &cs )
1253 : Generics::Unstructured( new GenericPrivate, p )
1268 Unstructured::clear();
1273 return d_func()->type == 0 || Unstructured::isEmpty();
1278 return d_func()->type;
1281 void Generic::setType(
const char *type )
1288 d->type =
new char[strlen( type )+1];
1289 strcpy( d->type, type );
1305 setIdentifier(
'<' +
uniqueString() +
'@' + fqdn +
'>' );
1316 QByteArray
Control::as7BitString(
bool withHeaderType )
const
1320 return QByteArray();
1324 if ( withHeaderType ) {
1329 if ( !d->parameter.isEmpty() ) {
1330 rv +=
' ' + d->parameter;
1339 d->parameter.clear();
1344 return d_func()->name.isEmpty();
1349 return d_func()->name;
1354 return d_func()->parameter;
1359 return d_func()->name.toLower() ==
"cancel";
1366 d->parameter = msgid;
1373 eatCFWS( scursor, send, isCRLF );
1374 if ( scursor == send ) {
1377 const char *start = scursor;
1378 while ( scursor != send && !isspace( *scursor ) ) {
1381 d->name = QByteArray( start, scursor - start );
1382 eatCFWS( scursor, send, isCRLF );
1383 d->parameter = QByteArray( scursor, send - scursor );
1392 kmime_mk_trivial_ctor_with_name_and_dptr(
MailCopiesTo,
1399 if ( withHeaderType ) {
1402 if ( !AddressList::isEmpty() ) {
1403 rv += AddressList::as7BitString(
false );
1405 if ( d_func()->alwaysCopy ) {
1407 }
else if ( d_func()->neverCopy ) {
1416 if ( !AddressList::isEmpty() ) {
1417 return AddressList::asUnicodeString();
1420 return QLatin1String(
"poster" );
1423 return QLatin1String(
"nobody" );
1431 AddressList::clear();
1432 d->alwaysCopy =
false;
1433 d->neverCopy =
false;
1438 return AddressList::isEmpty() && !( d_func()->alwaysCopy || d_func()->neverCopy );
1443 return !AddressList::isEmpty() || d_func()->alwaysCopy;
1450 d->alwaysCopy =
true;
1455 return d_func()->neverCopy;
1462 d->neverCopy =
true;
1470 if ( send - scursor == 5 ) {
1471 if ( qstrnicmp(
"never", scursor, 5 ) == 0 ) {
1472 d->neverCopy =
true;
1476 if ( send - scursor == 6 ) {
1477 if ( qstrnicmp(
"always", scursor, 6 ) == 0 || qstrnicmp(
"poster", scursor, 6 ) == 0 ) {
1478 d->alwaysCopy =
true;
1481 if ( qstrnicmp(
"nobody", scursor, 6 ) == 0 ) {
1482 d->neverCopy =
true;
1486 return AddressList::parse( scursor, send, isCRLF );
1497 QByteArray
Date::as7BitString(
bool withHeaderType )
const
1500 return QByteArray();
1504 if ( withHeaderType ) {
1507 rv += d_func()->dateTime.toString( KDateTime::RFCDateDay ).toLatin1();
1514 d->dateTime = KDateTime();
1519 return d_func()->dateTime.isNull() || !d_func()->dateTime.isValid();
1524 return d_func()->dateTime;
1535 QDate today = QDate::currentDate();
1536 return dateTime().date().daysTo( today );
1539 bool Date::parse(
const char* &scursor,
const char *
const send,
bool isCRLF )
1542 return parseDateTime( scursor, send, d->dateTime, isCRLF );
1554 QByteArray Newsgroups::as7BitString(
bool withHeaderType )
const
1556 const Q_D( Newsgroups );
1558 return QByteArray();
1562 if ( withHeaderType ) {
1566 for (
int i = 0; i < d->groups.count(); ++i ) {
1567 rv += d->groups[ i ];
1568 if ( i != d->groups.count() - 1 ) {
1596 return d_func()->groups.isEmpty();
1601 return d_func()->groups;
1612 return d_func()->groups.count() >= 2;
1620 eatCFWS( scursor, send, isCRLF );
1621 if ( scursor != send && *scursor ==
',' ) {
1624 eatCFWS( scursor, send, isCRLF );
1625 if ( scursor == send ) {
1628 const char *start = scursor;
1629 while ( scursor != send && !isspace( *scursor ) && *scursor !=
',' ) {
1632 QByteArray group( start, scursor - start );
1633 d->groups.append( group );
1646 QByteArray
Lines::as7BitString(
bool withHeaderType )
const
1649 return QByteArray();
1653 num.setNum( d_func()->lines );
1655 if ( withHeaderType ) {
1656 return typeIntro() + num;
1666 return QString::number( d_func()->lines );
1677 return d_func()->lines == -1;
1682 return d_func()->lines;
1691 bool Lines::parse(
const char* &scursor,
const char*
const send,
bool isCRLF )
1694 eatCFWS( scursor, send, isCRLF );
1695 if ( parseDigits( scursor, send, d->lines ) == 0 ) {
1713 return d_func()->
mimeType.isEmpty();
1719 d->category = CCsingle;
1720 d->mimeType.clear();
1721 Parametrized::clear();
1727 return QByteArray();
1731 if ( withHeaderType ) {
1736 if ( !Parametrized::isEmpty() ) {
1737 rv +=
"; " + Parametrized::as7BitString(
false );
1752 const int pos = d->mimeType.indexOf(
'/' );
1756 return d->mimeType.left( pos );
1763 const int pos = d->mimeType.indexOf(
'/' );
1765 return QByteArray();
1767 return d->mimeType.mid( pos + 1 );
1775 Parametrized::clear();
1778 d->category = CCcontainer;
1780 d->category = CCsingle;
1787 const int len = strlen( mediatype );
1788 return qstrnicmp( d->mimeType.constData(), mediatype, len ) == 0 &&
1789 ( d->mimeType.at( len ) ==
'/' || d->mimeType.size() == len );
1795 const int pos = d->mimeType.indexOf(
'/' );
1799 const int len = strlen( subtype );
1800 return qstrnicmp( d->mimeType.constData() + pos + 1, subtype, len ) == 0 &&
1801 d->mimeType.size() == pos + len + 1;
1811 return ( qstricmp( d_func()->
mimeType.constData(),
"text/plain" ) == 0 ||
isEmpty() );
1816 return qstricmp( d_func()->
mimeType.constData(),
"text/html" ) == 0;
1831 return qstricmp( d_func()->
mimeType.constData(),
"message/partial" ) == 0;
1836 QByteArray ret =
parameter( QLatin1String(
"charset" ) ).toLatin1();
1846 setParameter( QLatin1String(
"charset" ), QString::fromLatin1( s ) );
1851 return parameter( QLatin1String(
"boundary" ) ).toLatin1();
1856 setParameter( QLatin1String(
"boundary" ), QString::fromLatin1( s ) );
1861 return parameter( QLatin1String(
"name" ) );
1873 return parameter( QLatin1String(
"id" ) ).toLatin1();
1878 setParameter( QLatin1String(
"id" ), QString::fromLatin1( s ) );
1883 QByteArray p =
parameter( QLatin1String(
"number" ) ).toLatin1();
1884 if ( !p.isEmpty() ) {
1893 QByteArray p =
parameter( QLatin1String(
"total" ) ).toLatin1();
1894 if ( !p.isEmpty() ) {
1901 contentCategory ContentType::category()
const
1903 return d_func()->category;
1906 void ContentType::setCategory( contentCategory c )
1914 setParameter( QLatin1String(
"number" ), QString::number( number ) );
1915 setParameter( QLatin1String(
"total" ), QString::number( total ) );
1925 eatCFWS( scursor, send, isCRLF );
1926 if ( scursor == send ) {
1931 QPair<const char*, int> maybeMimeType;
1932 if ( !parseToken( scursor, send, maybeMimeType,
false ) ) {
1937 eatCFWS( scursor, send, isCRLF );
1938 if ( scursor == send || *scursor !=
'/' ) {
1942 eatCFWS( scursor, send, isCRLF );
1943 if ( scursor == send ) {
1947 QPair<const char*, int> maybeSubType;
1948 if ( !parseToken( scursor, send, maybeSubType,
false ) ) {
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();
1957 eatCFWS( scursor, send, isCRLF );
1958 if ( scursor == send ) {
1962 if ( *scursor !=
';' ) {
1967 if ( !Parametrized::parse( scursor, send, isCRLF ) ) {
1974 d->category = CCcontainer;
1976 d->category = CCsingle;
1985 kmime_mk_trivial_ctor_with_name_and_dptr(
ContentID, SingleIdent,
Content-ID )
1986 kmime_mk_dptr_ctor(
ContentID, SingleIdent )
1988 bool ContentID::parse( const
char* &scursor, const
char *const send,
bool isCRLF )
1994 const char* origscursor = scursor;
1995 if ( !SingleIdent::parse ( scursor, send, isCRLF ) ) {
1996 scursor = origscursor;
1997 d->msgIdList.clear();
1998 d->cachedIdentifier.clear();
2000 while ( scursor != send ) {
2001 eatCFWS ( scursor, send, isCRLF );
2003 if ( scursor == send ) {
2007 if ( *scursor ==
',' ) {
2012 AddrSpec maybeContentId;
2014 if ( scursor == send || *scursor !=
'<' ) {
2019 eatCFWS ( scursor, send, isCRLF );
2020 if ( scursor == send ) {
2026 if( !parseDotAtom(scursor, send, result,
false) ) {
2030 eatCFWS ( scursor, send, isCRLF );
2031 if ( scursor == send || *scursor !=
'>' ) {
2037 maybeContentId.localPart = result;
2038 d->msgIdList.append ( maybeContentId );
2040 eatCFWS ( scursor, send, isCRLF );
2042 if ( scursor == send ) {
2046 if ( *scursor ==
',' ) {
2067 typedef struct {
const char *s;
int e; } encTableType;
2069 static const encTableType encTable[] =
2073 {
"quoted-printable", CEquPr },
2074 {
"base64", CEbase64 },
2075 {
"x-uuencode", CEuuenc },
2076 {
"binary", CEbinary },
2090 return d_func()->cte;
2098 for (
int i = 0; encTable[i].s != 0; ++i ) {
2099 if ( d->cte == encTable[i].e ) {
2108 return d_func()->decoded;
2120 return d->decoded && ( d->cte == CEquPr || d->cte == CEbase64 );
2124 const char *
const send,
bool isCRLF )
2128 if ( !Token::parse( scursor, send, isCRLF ) ) {
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;
2139 d->decoded = ( d->cte == CE7Bit || d->cte == CE8Bit );
2155 return QByteArray();
2159 if ( withHeaderType ) {
2163 if ( d_func()->disposition == CDattachment ) {
2165 }
else if ( d_func()->disposition == CDinline ) {
2168 return QByteArray();
2171 if ( !Parametrized::isEmpty() ) {
2172 rv +=
"; " + Parametrized::as7BitString(
false );
2180 return d_func()->disposition == CDInvalid;
2186 d->disposition = CDInvalid;
2187 Parametrized::clear();
2192 return d_func()->disposition;
2198 d->disposition = disp;
2203 return parameter( QLatin1String(
"filename" ) );
2219 eatCFWS( scursor, send, isCRLF );
2220 if ( scursor == send ) {
2224 QPair<const char*, int> maybeToken;
2225 if ( !parseToken( scursor, send, maybeToken,
false ) ) {
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;
2239 eatCFWS( scursor, send, isCRLF );
2240 if ( scursor == send ) {
2244 if ( *scursor !=
';' ) {
2249 return Parametrized::parse( scursor, send, isCRLF );
2260 return asUnicodeString().indexOf( QLatin1String(
"Re:" ), 0, Qt::CaseInsensitive ) == 0;
2263 Base* createHeader(
const QByteArray& type )
2265 return HeaderFactory::self()->createHeader( type );
2273 Generics::Unstructured,
Content-Location )
2274 kmime_mk_trivial_ctor_with_name(
From, Generics::MailboxList, From )
2275 kmime_mk_trivial_ctor_with_name(
Sender, Generics::SingleMailbox, Sender )
2276 kmime_mk_trivial_ctor_with_name(
To, Generics::AddressList, To )
2277 kmime_mk_trivial_ctor_with_name(
Cc, Generics::AddressList, Cc )
2278 kmime_mk_trivial_ctor_with_name(
Bcc, Generics::AddressList, Bcc )
2279 kmime_mk_trivial_ctor_with_name(
ReplyTo, Generics::AddressList, Reply-To )
2280 kmime_mk_trivial_ctor_with_name(
Keywords, Generics::PhraseList, Keywords )
2281 kmime_mk_trivial_ctor_with_name(
MIMEVersion, Generics::DotAtom, MIME-Version )
2282 kmime_mk_trivial_ctor_with_name(
Supersedes, Generics::SingleIdent, Supersedes )
2283 kmime_mk_trivial_ctor_with_name(
InReplyTo, Generics::Ident, In-Reply-To )
2284 kmime_mk_trivial_ctor_with_name(
References, Generics::Ident, References )
2285 kmime_mk_trivial_ctor_with_name(
Organization, Generics::Unstructured, Organization )
2286 kmime_mk_trivial_ctor_with_name(
UserAgent, Generics::Unstructured, User-Agent )