summaryrefslogtreecommitdiffstats
path: root/libkmime/tests/test_kmime_header_parsing.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'libkmime/tests/test_kmime_header_parsing.cpp')
-rw-r--r--libkmime/tests/test_kmime_header_parsing.cpp431
1 files changed, 431 insertions, 0 deletions
diff --git a/libkmime/tests/test_kmime_header_parsing.cpp b/libkmime/tests/test_kmime_header_parsing.cpp
new file mode 100644
index 000000000..3839bff7e
--- /dev/null
+++ b/libkmime/tests/test_kmime_header_parsing.cpp
@@ -0,0 +1,431 @@
+
+#include <../kmime_headers.h>
+#include <../kmime_header_parsing.h>
+
+#include <kinstance.h>
+
+#include <qfile.h>
+#include <qcstring.h>
+//#include <qstring.h>
+
+//#include <stdio.h>
+#include <iostream>
+#include <cstdlib>
+#include <cassert>
+
+#define _GNU_SOURCE
+#include <getopt.h>
+
+using namespace KMime::HeaderParsing;
+using namespace std;
+
+static const char * tokenTypes[] = {
+ "encoded-word",
+ "atom",
+ "token",
+ "quoted-string",
+ "domain-literal",
+ "comment",
+ "phrase",
+ "dot-atom",
+ "domain",
+ "obs-route",
+ "addr-spec",
+ "angle-addr",
+ "mailbox",
+ "group",
+ "address",
+ "address-list",
+ "parameter",
+ "raw-parameter-list",
+ "parameter-list",
+ "time",
+ "date-time"
+};
+static const int tokenTypesLen = sizeof tokenTypes / sizeof *tokenTypes;
+
+void usage( const char * msg=0 ) {
+ if ( msg && *msg )
+ cerr << msg << endl;
+ cerr <<
+ "usage: test_kmime_header_parsing "
+ "(--token <tokentype>|--headerfield <fieldtype>|--header)\n"
+ "\n"
+ " --token <tokentype> interpret input as <tokentype> and output\n"
+ " (-t) in parsed form. Currently defined values of\n"
+ " <tokentype> are:" << endl;
+ for ( int i = 0 ; i < tokenTypesLen ; ++i )
+ cerr << " " << tokenTypes[i] << endl;
+ cerr << "\n"
+ " --headerfield <fieldtype> interpret input as header field <fieldtype>\n"
+ " (-f) and output in parsed form.\n"
+ "\n"
+ " --header parse an RFC2822 header. Iterates over all\n"
+ " (-h) header fields and outputs them in parsed form." << endl;
+ exit(1);
+}
+
+ostream & operator<<( ostream & stream, const QString & str ) {
+ return stream << str.utf8().data();
+}
+
+int main( int argc, char * argv[] ) {
+ if ( argc == 1 || argc > 3 ) usage();
+ //
+ // process options:
+ //
+ enum { None, Token, HeaderField, Header } action = None;
+ const char * argument = 0;
+ bool withCRLF = false;
+ while( true ) {
+ int option_index = 0;
+ static const struct option long_options[] = {
+ // actions:
+ { "token", 1, 0, 't' },
+ { "headerfield", 1, 0, 'f' },
+ { "header", 0, 0, 'h' },
+ { "crlf", 0, 0, 'c' },
+ { 0, 0, 0, 0 }
+ };
+
+ int c = getopt_long( argc, argv, "cf:ht:", long_options, &option_index );
+ if ( c == -1 ) break;
+
+ switch ( c ) {
+ case 'c': // --crlf
+ withCRLF = true;
+ break;
+ case 't': // --token <tokentype>
+ action = Token;
+ argument = optarg;
+ break;
+ case 'f': // --headerfield <headertype>
+ usage( "--headerfield is not yet implemented!" );
+ break;
+ case 'h': // --header
+ usage( "--header is not yet implemented!" );
+ break;
+ default:
+ usage( "unknown option encountered!" );
+ }
+ }
+
+ if ( optind < argc ) usage( "non-option argument encountered!" );
+
+ assert( action == Token );
+
+ int index;
+ for ( index = 0 ; index < tokenTypesLen ; ++index )
+ if ( !qstricmp( tokenTypes[index], argument ) ) break;
+
+ if ( index >= tokenTypesLen ) usage( "unknown token type" );
+
+ KInstance instance( "test_kmime_header_parsing" );
+
+ QFile stdIn;
+ stdIn.open( IO_ReadOnly, stdin );
+ const QByteArray indata = stdIn.readAll();
+ stdIn.close();
+ QByteArray::ConstIterator iit = indata.begin();
+ const QByteArray::ConstIterator iend = indata.end();
+
+ switch ( index ) {
+ case 0:
+ { // encoded-word
+ QString result;
+ QCString language;
+ // must have checked for initial '=' already:
+ bool ok = indata.size() >= 1 && *iit++ == '=' &&
+ parseEncodedWord( iit, iend, result, language );
+
+ cout << ( ok ? "OK" : "BAD" ) << endl
+ << "result:\n" << result << endl
+ << "language:\n" << language.data() << endl;
+ }
+ break;
+ case 1:
+ { // atom
+ QString result = "with 8bit: ";
+ bool ok = parseAtom( iit, iend, result, true );
+
+ cout << ( ok ? "OK" : "BAD" ) << endl
+ << "result:\n" << result << endl;
+
+ result = "without 8bit: ";
+#ifdef COMPILE_FAIL
+ ok = parseAtom( indata.begin(), iend, result, false );
+#else
+ iit = indata.begin();
+ ok = parseAtom( iit, iend, result, false );
+#endif
+
+ cout << ( ok ? "OK" : "BAD" ) << endl
+ << "result:\n" << result << endl;
+ }
+ break;
+ case 2:
+ { // token
+ QString result = "with 8bit: ";
+ bool ok = parseToken( iit, iend, result, true );
+
+ cout << ( ok ? "OK" : "BAD" ) << endl
+ << "result:\n" << result << endl;
+
+ result = "without 8bit: ";
+#ifdef COMPILE_FAIL
+ ok = parseToken( indata.begin(), iend, result, false );
+#else
+ iit = indata.begin();
+ ok = parseToken( iit, iend, result, false );
+#endif
+
+ cout << ( ok ? "OK" : "BAD" ) << endl
+ << "result:\n" << result << endl;
+ }
+ break;
+ case 3:
+ { // quoted-string
+ QString result;
+ // must have checked for initial '"' already:
+ bool ok = *iit++ == '"' &&
+ parseGenericQuotedString( iit, iend, result, withCRLF, '"', '"' );
+
+ cout << ( ok ? "OK" : "BAD" ) << endl
+ << "result:\n" << result << endl;
+ }
+ break;
+ case 4:
+ { // domain-literal
+ QString result;
+ // must have checked for initial '[' already:
+ bool ok = *iit++ == '[' &&
+ parseGenericQuotedString( iit, iend, result, withCRLF, '[', ']' );
+
+ cout << ( ok ? "OK" : "BAD" ) << endl
+ << "result:\n" << result << endl;
+ }
+ break;
+ case 5:
+ { // comment
+ QString result;
+ // must have checked for initial '(' already:
+ bool ok = *iit++ == '(' &&
+ parseComment( iit, iend, result, withCRLF, true );
+
+ cout << ( ok ? "OK" : "BAD" ) << endl
+ << "result:\n" << result << endl;
+ }
+ break;
+ case 6:
+ { // phrase
+ QString result;
+ bool ok = parsePhrase( iit, iend, result, withCRLF );
+
+ cout << ( ok ? "OK" : "BAD" ) << endl
+ << "result:\n" << result << endl;
+ }
+ break;
+ case 7:
+ { // dot-atom
+ QString result;
+ bool ok = parseDotAtom( iit, iend, result, withCRLF );
+
+ cout << ( ok ? "OK" : "BAD" ) << endl
+ << "result:\n" << result << endl;
+ }
+ break;
+ case 8:
+ { // domain
+ QString result;
+ bool ok = parseDomain( iit, iend, result, withCRLF );
+
+ cout << ( ok ? "OK" : "BAD" ) << endl
+ << "result:\n" << result << endl;
+ }
+ break;
+ case 9:
+ { // obs-route
+ QStringList result;
+ bool ok = parseObsRoute( iit, iend, result, withCRLF, true /*save*/ );
+
+ cout << ( ok ? "OK" : "BAD" ) << endl
+ << "result: " << result.count() << " domains:" << endl;
+ for ( QStringList::ConstIterator it = result.begin() ;
+ it != result.end() ; ++it )
+ cout << (*it) << endl;
+ }
+ break;
+ case 10:
+ { // addr-spec
+ KMime::Types::AddrSpec result;
+ bool ok = parseAddrSpec( iit, iend, result, withCRLF );
+
+ cout << ( ok ? "OK" : "BAD" ) << endl
+ << "result.localPart:\n" << result.localPart << endl
+ << "result.domain:\n" << result.domain << endl;
+ }
+ break;
+ case 11:
+ { // angle-addr
+ KMime::Types::AddrSpec result;
+ bool ok = parseAngleAddr( iit, iend, result, withCRLF );
+
+ cout << ( ok ? "OK" : "BAD" ) << endl
+ << "result.localPart:\n" << result.localPart << endl
+ << "result.domain:\n" << result.domain << endl;
+ }
+ break;
+ case 12:
+ { // mailbox
+ KMime::Types::Mailbox result;
+ bool ok = parseMailbox( iit, iend, result, withCRLF );
+
+ cout << ( ok ? "OK" : "BAD" ) << endl
+ << "result.displayName:\n" << result.displayName << endl
+ << "result.addrSpec.localPart:\n" << result.addrSpec.localPart << endl
+ << "result.addrSpec.domain:\n" << result.addrSpec.domain << endl;
+ }
+ break;
+ case 13:
+ { // group
+ KMime::Types::Address result;
+ bool ok = parseGroup( iit, iend, result, withCRLF );
+
+ cout << ( ok ? "OK" : "BAD" ) << endl
+ << "result.displayName:\n" << result.displayName << endl;
+ int i = 0;
+ for ( QValueList<KMime::Types::Mailbox>::ConstIterator
+ it = result.mailboxList.begin();
+ it != result.mailboxList.end() ; ++it, ++i )
+ cout << "result.mailboxList[" << i << "].displayName:\n"
+ << (*it).displayName << endl
+ << "result.mailboxList[" << i << "].addrSpec.localPart:\n"
+ << (*it).addrSpec.localPart << endl
+ << "result.mailboxList[" << i << "].addrSpec.domain:\n"
+ << (*it).addrSpec.domain << endl;
+ }
+ break;
+ case 14:
+ { // address
+ KMime::Types::Address result;
+ bool ok = parseAddress( iit, iend, result, withCRLF );
+
+ cout << ( ok ? "OK" : "BAD" ) << endl
+ << "result.displayName:\n" << endl;
+ int i = 0;
+ for ( QValueList<KMime::Types::Mailbox>::ConstIterator
+ it = result.mailboxList.begin();
+ it != result.mailboxList.end() ; ++it, ++i )
+ cout << "result.mailboxList[" << i << "].displayName:\n"
+ << (*it).displayName << endl
+ << "result.mailboxList[" << i << "].addrSpec.localPart:\n"
+ << (*it).addrSpec.localPart << endl
+ << "result.mailboxList[" << i << "].addrSpec.domain:\n"
+ << (*it).addrSpec.domain << endl;
+ }
+ break;
+ case 15:
+ { // address-list
+ QValueList<KMime::Types::Address> result;
+ bool ok = parseAddressList( iit, iend, result, withCRLF );
+
+ cout << ( ok ? "OK" : "BAD" ) << endl;
+ int j = 0;
+ for ( QValueList<KMime::Types::Address>::ConstIterator
+ jt = result.begin() ; jt != result.end() ; ++jt, ++j ) {
+ cout << "result[" << j << "].displayName:\n"
+ << (*jt).displayName << endl;
+ int i = 0;
+ for ( QValueList<KMime::Types::Mailbox>::ConstIterator
+ it = (*jt).mailboxList.begin();
+ it != (*jt).mailboxList.end() ; ++it, ++i )
+ cout << "result[" << j << "].mailboxList[" << i << "].displayName:\n"
+ << (*it).displayName << endl
+ << "result[" << j << "].mailboxList[" << i << "].addrSpec.localPart:\n"
+ << (*it).addrSpec.localPart << endl
+ << "result[" << j << "].mailboxList[" << i << "].addrSpec.domain:\n"
+ << (*it).addrSpec.domain << endl;
+ }
+ }
+ break;
+ case 16:
+ { // parameter
+ QPair<QString,KMime::Types::QStringOrQPair> result;
+ bool ok = parseParameter( iit, iend, result, withCRLF );
+
+ cout << ( ok ? "OK" : "BAD" ) << endl
+ << "result.first (attribute):\n" << result.first << endl
+ << "result.second.qstring (value):\n" << result.second.qstring << endl
+ << "result.second.qpair (value):\n"
+ << QCString( result.second.qpair.first,
+ result.second.qpair.second+1 ).data() << endl;
+ }
+ break;
+ case 17:
+ { // raw-parameter-list
+ QMap<QString,KMime::Types::QStringOrQPair> result;
+ bool ok = parseRawParameterList( iit, iend, result, withCRLF );
+
+ cout << ( ok ? "OK" : "BAD" ) << endl
+ << "result: " << result.count() << " raw parameters:" << endl;
+ int i = 0;
+ for ( QMap<QString,KMime::Types::QStringOrQPair>::ConstIterator
+ it = result.begin() ; it != result.end() ; ++it, ++i )
+ cout << "result[" << i << "].key() (attribute):\n"
+ << it.key() << endl
+ << "result[" << i << "].data().qstring (value):\n"
+ << it.data().qstring << endl
+ << "result[" << i << "].data().qpair (value):\n"
+ << QCString( it.data().qpair.first,
+ it.data().qpair.second+1 ).data() << endl;
+ }
+ break;
+ case 18:
+ { // parameter-list
+ QMap<QString,QString> result;
+ bool ok = parseParameterList( iit, iend, result, withCRLF );
+
+ cout << ( ok ? "OK" : "BAD" ) << endl
+ << "result: " << result.count() << " parameters:" << endl;
+ int i = 0;
+ for ( QMap<QString,QString>::Iterator it = result.begin() ;
+ it != result.end() ; ++it, ++i )
+ cout << "result[" << i << "].key() (attribute):\n"
+ << it.key() << endl
+ << "result[" << i << "].data() (value):\n"
+ << it.data() << endl;
+ }
+ break;
+ case 19:
+ { // time
+ int hour, mins, secs;
+ long int secsEastOfGMT;
+ bool timeZoneKnown = true;
+
+ bool ok = parseTime( iit, iend, hour, mins, secs,
+ secsEastOfGMT, timeZoneKnown, withCRLF );
+
+ cout << ( ok ? "OK" : "BAD" ) << endl
+ << "result.hour: " << hour << endl
+ << "result.mins: " << mins << endl
+ << "result.secs: " << secs << endl
+ << "result.secsEastOfGMT: " << secsEastOfGMT << endl
+ << "result.timeZoneKnown: " << timeZoneKnown << endl;
+ }
+ break;
+ case 20:
+ { // date-time
+ KMime::Types::DateTime result;
+ bool ok = parseDateTime( iit, iend, result, withCRLF );
+
+ cout << ( ok ? "OK" : "BAD" ) << endl
+ << "result.time (in local timezone): " << ctime( &(result.time) )
+ << "result.secsEastOfGMT: " << result.secsEastOfGMT
+ << " (" << result.secsEastOfGMT/60 << "mins)" << endl
+ << "result.timeZoneKnown: " << result.timeZoneKnown << endl;
+ }
+ break;
+ default:
+ assert( 0 );
+ }
+}