33 #include "kmime_header_parsing.h" 35 #include "kmime_codecs.h" 36 #include "kmime_util.h" 37 #include "kmime_warning.h" 39 #include <tdeglobal.h> 40 #include <kcharsets.h> 42 #include <tqtextcodec.h> 44 #include <tqcstring.h> 45 #include <tqstringlist.h> 50 using namespace KMime; 57 TQString AddrSpec::asString() const { 58 bool needsQuotes = false; 60 result.reserve( localPart.length() + domain.length() + 1 ); 61 for ( unsigned int i = 0 ; i < localPart.length() ; ++i ) { 62 const char ch = localPart[i].latin1(); 63 if ( ch == '.' || isAText( ch ) ) 67 if ( ch == '\\' || ch == '"' ) 73 return '"' + result + "\"@" + domain; 75 return result + '@' + domain; 80 namespace HeaderParsing { 83 bool parseEncodedWord( const char* & scursor, const char * const send, 84 TQString & result, TQCString & language ) { 87 assert( *(scursor-1) == '=' ); 97 kdDebug() << "first" << endl; 98 KMIME_WARN_PREMATURE_END_OF(EncodedWord); 104 const char * charsetStart = scursor; 105 const char * languageStart = 0; 109 for ( ; scursor != send ; scursor++ ) 110 if ( *scursor == '?') 112 else if ( *scursor == '*' && !languageStart ) 113 languageStart = scursor + 1; 116 if ( scursor == send || *scursor != '?' ) { 117 kdDebug() << "second" << endl; 118 KMIME_WARN_PREMATURE_END_OF(EncodedWord); 124 TQCString maybeLanguage( languageStart, scursor - languageStart + 1 ); 127 TQCString maybeCharset( charsetStart, ( languageStart ? languageStart : scursor + 1 ) - charsetStart ); 137 const char * encodingStart = scursor; 140 for ( ; scursor != send ; scursor++ ) 141 if ( *scursor == '?' ) break; 144 if ( scursor == send || *scursor != '?' ) { 145 kdDebug() << "third" << endl; 146 KMIME_WARN_PREMATURE_END_OF(EncodedWord); 151 TQCString maybeEncoding( encodingStart, scursor - encodingStart + 1 ); 154 kdDebug() << "parseEncodedWord: found charset == \"" << maybeCharset 155 << "\"; language == \"" << maybeLanguage 156 << "\"; encoding == \"" << maybeEncoding << "\"" << endl; 166 const char * encodedTextStart = scursor; 169 for ( ; scursor != send ; scursor++ ) 170 if ( *scursor == '?' ) break; 174 if ( scursor == send || *scursor != '?' ) { 175 kdDebug() << "fourth" << endl; 176 KMIME_WARN_PREMATURE_END_OF(EncodedWord); 181 if ( scursor == send || *scursor != '=' ) { 182 kdDebug() << "fifth" << endl; 183 KMIME_WARN_PREMATURE_END_OF(EncodedWord); 189 const char * const encodedTextEnd = scursor - 2; 198 Codec * codec = Codec::codecForName( maybeEncoding ); 200 KMIME_WARN_UNKNOWN(Encoding,maybeEncoding); 205 Decoder * dec = codec->makeDecoder(); 209 bool matchOK = false; 211 *textCodec = TDEGlobal::charsets()->codecForName( maybeCharset, matchOK ); 213 if ( !matchOK || !textCodec ) { 214 KMIME_WARN_UNKNOWN(Charset,maybeCharset); 219 kdDebug() << "mimeName(): \"" << textCodec->mimeName() << "\"" << endl; 222 int encodedTextLength = encodedTextEnd - encodedTextStart; 223 TQByteArray buffer( codec->maxDecodedSizeFor( encodedTextLength ) ); 224 TQByteArray::Iterator bit = buffer.begin(); 225 TQByteArray::ConstIterator bend = buffer.end(); 232 if ( !dec-> decode( encodedTextStart, encodedTextEnd, bit, bend ) ) 233 KMIME_WARN << codec-> name() << " codec lies about it's maxDecodedSizeFor( " 234 << encodedTextLength << " )\nresult may be truncated" << endl; 236 result = textCodec->toUnicode( buffer.begin(), bit - buffer.begin() ); 238 kdDebug() << "result now: \"" << result << "\"" << endl; 241 language = maybeLanguage; 246 static inline void eatWhiteSpace( const char* & scursor, const char * const send ) { 247 while ( scursor != send 248 && ( *scursor == ' ' || *scursor == '\n' || 249 *scursor == '\t' || *scursor == '\r' ) ) 253 bool parseAtom( const char * & scursor, const char * const send, 254 TQString & result, bool allow8Bit ) 256 TQPair<const char*,int> maybeResult; 258 if ( parseAtom( scursor, send, maybeResult, allow8Bit ) ) { 259 result += TQString::fromLatin1( maybeResult.first, maybeResult.second ); 266 bool parseAtom( const char * & scursor, const char * const send, 267 TQPair<const char*,int> & result, bool allow8Bit ) { 268 bool success = false; 269 const char * start = scursor; 271 while ( scursor != send ) { 272 signed char ch = *scursor++; 273 if ( ch > 0 && isAText(ch) ) { 276 } else if ( allow8Bit && ch < 0 ) { 288 result.first = start; 289 result.second = scursor - start; 293 bool parseToken( const char * & scursor, const char * const send, 294 TQString & result, bool allow8Bit ) 296 TQPair<const char*,int> maybeResult; 298 if ( parseToken( scursor, send, maybeResult, allow8Bit ) ) { 299 result += TQString::fromLatin1( maybeResult.first, maybeResult.second ); 306 bool parseToken( const char * & scursor, const char * const send, 307 TQPair<const char*,int> & result, bool allow8Bit ) 309 bool success = false; 310 const char * start = scursor; 312 while ( scursor != send ) { 313 signed char ch = *scursor++; 314 if ( ch > 0 && isTText(ch) ) { 317 } else if ( allow8Bit && ch < 0 ) { 329 result.first = start; 330 result.second = scursor - start; 334 #define READ_ch_OR_FAIL if ( scursor == send ) { \ 335 KMIME_WARN_PREMATURE_END_OF(GenericQuotedString); \ 345 bool parseGenericQuotedString( const char* & scursor, const char * const send, 346 TQString & result, bool isCRLF, 347 const char openChar, const char closeChar ) 356 assert( *(scursor-1) == openChar || *(scursor-1) == closeChar ); 358 while ( scursor != send ) { 361 if ( ch == closeChar || ch == openChar ) { 371 KMIME_WARN_IF_8BIT(ch); 372 result += TQChar(ch); 386 result += TQChar( '\r'); 392 if ( ch == ' ' || ch == '\t' ) { 396 result += TQChar(ch); 401 KMIME_WARN_NON_FOLDING(CRLF); 419 if ( !isCRLF && ( ch == ' ' || ch == '\t' ) ) { 422 result += TQChar(ch); 426 result += TQChar( '\n'); 433 KMIME_WARN_IF_8BIT(ch); 434 result += TQChar(ch); 445 bool parseComment( const char* & scursor, const char * const send, 446 TQString & result, bool isCRLF, bool reallySave ) 448 int commentNestingDepth = 1; 449 const char * afterLastClosingParenPos = 0; 451 const char * oldscursor = scursor; 453 assert( *(scursor-1) == '(' ); 455 while ( commentNestingDepth ) { 457 if ( parseGenericQuotedString( scursor, send, cmntPart, isCRLF, '(', ')' ) ) { 458 assert( *(scursor-1) == ')' || *(scursor-1) == '(' ); 461 switch ( *(scursor-1) ) { 467 if ( commentNestingDepth > 1 ) 468 result += TQChar( ')'); 469 maybeCmnt = TQString(); 471 afterLastClosingParenPos = scursor; 472 --commentNestingDepth; 478 maybeCmnt += cmntPart; 479 maybeCmnt += TQChar( '('); 481 ++commentNestingDepth; 483 default: assert( 0 ); 487 if ( afterLastClosingParenPos ) 488 scursor = afterLastClosingParenPos; 490 scursor = oldscursor; 501 bool parsePhrase( const char* & scursor, const char * const send, 502 TQString & result, bool isCRLF ) 504 enum { None, Phrase, Atom, EncodedWord, QuotedString } found = None; 507 const char * successfullyParsed = 0; 509 const char * oldscursor; 512 bool lastWasEncodedWord = false; 514 while ( scursor != send ) { 515 char ch = *scursor++; 518 if ( found == None ) { 522 if ( scursor != send && ( *scursor == ' ' || *scursor == '\t' ) ) 526 successfullyParsed = scursor; 531 if ( parseGenericQuotedString( scursor, send, tmp, isCRLF, '"', '"' ) ) { 532 successfullyParsed = scursor; 533 assert( *(scursor-1) == '"' ); 536 found = QuotedString; 543 result += TQChar( ' '); 548 lastWasEncodedWord = false; 554 if ( found == None ) { 557 result += TQChar( ' '); 566 if ( parseComment( scursor, send, tmp, isCRLF, 568 successfullyParsed = scursor; 569 lastWasEncodedWord = false; 574 scursor = successfullyParsed; 581 oldscursor = scursor; 583 if ( parseEncodedWord( scursor, send, tmp, lang ) ) { 584 successfullyParsed = scursor; 593 if ( !lastWasEncodedWord ) 594 result += TQChar( ' '); 597 default: assert( 0 ); 599 lastWasEncodedWord = true; 604 scursor = oldscursor; 610 if ( parseAtom( scursor, send, tmp, true ) ) { 611 successfullyParsed = scursor; 621 result += TQChar( ' '); 626 lastWasEncodedWord = false; 632 scursor = successfullyParsed; 637 eatWhiteSpace( scursor, send ); 640 return ( found != None ); 644 bool parseDotAtom( const char* & scursor, const char * const send, 645 TQString & result, bool isCRLF ) 648 const char * successfullyParsed; 651 if ( !parseAtom( scursor, send, tmp, false ) ) 654 successfullyParsed = scursor; 656 while ( scursor != send ) { 657 eatCFWS( scursor, send, isCRLF ); 660 if ( scursor == send || *scursor != '.' ) return true; 663 eatCFWS( scursor, send, isCRLF ); 665 if ( scursor == send || !isAText( *scursor ) ) { 669 scursor = successfullyParsed; 675 if ( !parseAtom( scursor, send, maybeAtom, false ) ) { 676 scursor = successfullyParsed; 680 result += TQChar( '.'); 682 successfullyParsed = scursor; 685 scursor = successfullyParsed; 690 void eatCFWS( const char* & scursor, const char * const send, bool isCRLF ) { 693 while ( scursor != send ) { 694 const char * oldscursor = scursor; 696 char ch = *scursor++; 706 if ( parseComment( scursor, send, dummy, isCRLF, false ) ) 708 scursor = oldscursor; 712 scursor = oldscursor; 719 bool parseDomain( const char* & scursor, const char * const send, 720 TQString & result, bool isCRLF ) { 721 eatCFWS( scursor, send, isCRLF ); 722 if ( scursor == send ) return false; 730 if ( *scursor == '[' ) { 732 TQString maybeDomainLiteral; 735 while ( parseGenericQuotedString( scursor, send, maybeDomainLiteral, 736 isCRLF, '[', ']' ) ) { 737 if ( scursor == send ) { 739 if ( *(scursor-1) == ']' ) { 741 result = maybeDomainLiteral; 750 if ( *(scursor-1) == '[' ) { 751 maybeDomainLiteral += TQChar( '['); 755 result = maybeDomainLiteral; 760 TQString maybeDotAtom; 761 if ( parseDotAtom( scursor, send, maybeDotAtom, isCRLF ) ) { 762 result = maybeDotAtom; 769 bool parseObsRoute( const char* & scursor, const char* const send, 770 TQStringList & result, bool isCRLF, bool save ) { 771 while ( scursor != send ) { 772 eatCFWS( scursor, send, isCRLF ); 773 if ( scursor == send ) return false; 776 if ( *scursor == ',' ) { 778 if ( save ) result.append( TQString() ); 783 if ( *scursor == ':' ) { 785 if ( save ) result.append( TQString() ); 790 if ( *scursor != '@' ) 795 TQString maybeDomain; 796 if ( !parseDomain( scursor, send, maybeDomain, isCRLF ) ) return false; 797 if ( save ) result.append( maybeDomain ); 800 eatCFWS( scursor, send, isCRLF ); 801 if ( scursor == send ) return false; 802 if ( *scursor == ':' ) { scursor++; return true; } 803 if ( *scursor == ',' ) scursor++; 810 bool parseAddrSpec( const char* & scursor, const char * const send, 811 AddrSpec & result, bool isCRLF ) { 819 TQString maybeLocalPart; 822 while ( scursor != send ) { 824 eatCFWS( scursor, send, isCRLF ); 826 char ch = *scursor++; 829 maybeLocalPart += TQChar( '.'); 838 if ( parseGenericQuotedString( scursor, send, tmp, isCRLF, '"', '"' ) ) 839 maybeLocalPart += tmp; 847 if ( parseAtom( scursor, send, tmp, false ) ) 848 maybeLocalPart += tmp; 865 assert( *(scursor-1) == '@' ); 867 TQString maybeDomain; 868 if ( !parseDomain( scursor, send, maybeDomain, isCRLF ) ) 871 result.localPart = maybeLocalPart; 872 result.domain = maybeDomain; 878 bool parseAngleAddr( const char* & scursor, const char * const send, 879 AddrSpec & result, bool isCRLF ) { 881 eatCFWS( scursor, send, isCRLF ); 882 if ( scursor == send || *scursor != '<' ) return false; 885 eatCFWS( scursor, send, isCRLF ); 886 if ( scursor == send ) return false; 888 if ( *scursor == '@' || *scursor == ',' ) { 890 KMIME_WARN << "obsolete source route found! ignoring." << endl; 892 if ( !parseObsRoute( scursor, send, dummy, 896 if ( scursor == send ) return false; 900 AddrSpec maybeAddrSpec; 901 if ( !parseAddrSpec( scursor, send, maybeAddrSpec, isCRLF ) ) return false; 903 eatCFWS( scursor, send, isCRLF ); 904 if ( scursor == send || *scursor != '>' ) return false; 907 result = maybeAddrSpec; 912 bool parseMailbox( const char* & scursor, const char * const send, 913 Mailbox & result, bool isCRLF ) { 921 eatCFWS( scursor, send, isCRLF ); 922 if ( scursor == send ) return false; 924 AddrSpec maybeAddrSpec; 927 const char * oldscursor = scursor; 928 if ( parseAddrSpec( scursor, send, maybeAddrSpec, isCRLF ) ) { 929 result.displayName = TQString(); 930 result.addrSpec = maybeAddrSpec; 933 scursor = oldscursor; 936 TQString maybeDisplayName; 937 if ( !parsePhrase( scursor, send, maybeDisplayName, isCRLF ) ) { 939 maybeDisplayName = TQString(); 940 scursor = oldscursor; 943 eatCFWS( scursor, send, isCRLF ); 944 if ( scursor == send ) return false; 948 if ( !parseAngleAddr( scursor, send, maybeAddrSpec, isCRLF ) ) 951 if ( maybeDisplayName.isNull() ) { 953 eatWhiteSpace( scursor, send ); 954 if ( scursor != send && *scursor == '(' ) { 956 if ( !parseComment( scursor, send, maybeDisplayName, isCRLF, true ) ) 961 result.displayName = maybeDisplayName; 962 result.addrSpec = maybeAddrSpec; 966 bool parseGroup( const char* & scursor, const char * const send, 967 Address & result, bool isCRLF ) { 973 eatCFWS( scursor, send, isCRLF ); 974 if ( scursor == send ) return false; 977 TQString maybeDisplayName; 978 if ( !parsePhrase( scursor, send, maybeDisplayName, isCRLF ) ) 982 eatCFWS( scursor, send, isCRLF ); 983 if ( scursor == send || *scursor != ':' ) return false; 985 result.displayName = maybeDisplayName; 989 while ( scursor != send ) { 990 eatCFWS( scursor, send, isCRLF ); 991 if ( scursor == send ) return false; 994 if ( *scursor == ',' ) { scursor++; continue; } 997 if ( *scursor == ';' ) { scursor++; return true; } 999 Mailbox maybeMailbox; 1000 if ( !parseMailbox( scursor, send, maybeMailbox, isCRLF ) ) 1002 result.mailboxList.append( maybeMailbox ); 1004 eatCFWS( scursor, send, isCRLF ); 1006 if ( scursor == send ) return false; 1008 if ( *scursor == ';' ) { scursor++; return true; } 1010 if ( *scursor == ',' ) scursor++; 1016 bool parseAddress( const char* & scursor, const char * const send, 1017 Address & result, bool isCRLF ) { 1020 eatCFWS( scursor, send, isCRLF ); 1021 if ( scursor == send ) return false; 1024 Mailbox maybeMailbox; 1025 const char * oldscursor = scursor; 1026 if ( parseMailbox( scursor, send, maybeMailbox, isCRLF ) ) { 1028 result.displayName = TQString(); 1029 result.mailboxList.append( maybeMailbox ); 1032 scursor = oldscursor; 1034 Address maybeAddress; 1037 if ( !parseGroup( scursor, send, maybeAddress, isCRLF ) ) 1040 result = maybeAddress; 1044 bool parseAddressList( const char* & scursor, const char * const send, 1045 AddressList & result, bool isCRLF ) { 1046 while ( scursor != send ) { 1047 eatCFWS( scursor, send, isCRLF ); 1049 if ( scursor == send ) return true; 1051 if ( *scursor == ',' ) { scursor++; continue; } 1054 Address maybeAddress; 1055 if ( !parseAddress( scursor, send, maybeAddress, isCRLF ) ) return false; 1056 result.append( maybeAddress ); 1058 eatCFWS( scursor, send, isCRLF ); 1060 if ( scursor == send ) return true; 1062 if ( *scursor == ',' ) scursor++; 1068 static TQString asterisk = TQString::fromLatin1( "*0*",1); 1069 static TQString asteriskZero = TQString::fromLatin1( "*0*",2); 1072 bool parseParameter( const char* & scursor, const char * const send, 1073 TQPair<TQString,TQStringOrTQPair> & result, bool isCRLF ) { 1084 eatCFWS( scursor, send, isCRLF ); 1085 if ( scursor == send ) return false; 1090 TQString maybeAttribute; 1091 if ( !parseToken( scursor, send, maybeAttribute, false ) ) 1094 eatCFWS( scursor, send, isCRLF ); 1096 if ( scursor == send || *scursor != '=' ) return false; 1099 eatCFWS( scursor, send, isCRLF ); 1100 if ( scursor == send ) { 1102 if ( maybeAttribute.endsWith( asterisk ) ) { 1103 KMIME_WARN << "attribute ends with \"*\", but value is empty! " 1104 "Chopping away \"*\"." << endl; 1105 maybeAttribute.truncate( maybeAttribute.length() - 1 ); 1107 result = qMakePair( maybeAttribute.lower(), TQStringOrTQPair() ); 1111 const char * oldscursor = scursor; 1116 TQStringOrTQPair maybeValue; 1117 if ( *scursor == '"' ) { 1120 if ( maybeAttribute.endsWith( asterisk ) ) { 1124 KMIME_WARN << "attribute ends with \"*\", but value is a quoted-string! " 1125 "Chopping away \"*\"." << endl; 1126 maybeAttribute.truncate( maybeAttribute.length() - 1 ); 1129 if ( !parseGenericQuotedString( scursor, send, maybeValue.qstring, isCRLF ) ) { 1130 scursor = oldscursor; 1131 result = qMakePair( maybeAttribute.lower(), TQStringOrTQPair() ); 1136 if ( !parseToken( scursor, send, maybeValue.qpair, false ) ) { 1137 scursor = oldscursor; 1138 result = qMakePair( maybeAttribute.lower(), TQStringOrTQPair() ); 1143 result = qMakePair( maybeAttribute.lower(), maybeValue ); 1149 bool parseRawParameterList( const char* & scursor, const char * const send, 1150 TQMap<TQString,TQStringOrTQPair> & result, 1162 while ( scursor != send ) { 1163 eatCFWS( scursor, send, isCRLF ); 1165 if ( scursor == send ) return true; 1167 if ( *scursor == ';' ) { scursor++; continue; } 1169 TQPair<TQString,TQStringOrTQPair> maybeParameter; 1170 if ( !parseParameter( scursor, send, maybeParameter, isCRLF ) ) { 1178 if ( maybeParameter.first.isNull() ) return false; 1179 while ( scursor != send ) { 1180 if ( *scursor++ == ';' ) goto IS_SEMICOLON; 1189 result.insert( maybeParameter.first, maybeParameter.second ); 1191 eatCFWS( scursor, send, isCRLF ); 1193 if ( scursor == send ) return true; 1195 if ( *scursor == ';' ) scursor++; 1201 static void decodeRFC2231Value( Codec* & rfc2231Codec, 1202 TQTextCodec* & textcodec, 1203 bool isContinuation, TQString & value, 1204 TQPair<const char*,int> & source ) { 1210 const char * decBegin = source.first; 1211 const char * decCursor = decBegin; 1212 const char * decEnd = decCursor + source.second; 1214 if ( !isContinuation ) { 1216 while ( decCursor != decEnd ) { 1217 if ( *decCursor == '\'' ) break; 1221 if ( decCursor == decEnd ) { 1224 KMIME_WARN << "No charset in extended-initial-value. " 1225 "Assuming \"iso-8859-1\"." << endl; 1226 value += TQString::fromLatin1( decBegin, source.second ); 1230 TQCString charset( decBegin, decCursor - decBegin + 1 ); 1232 const char * oldDecCursor = ++decCursor; 1234 while ( decCursor != decEnd ) { 1235 if ( *decCursor == '\'' ) break; 1238 if ( decCursor == decEnd ) { 1239 KMIME_WARN << "No language in extended-initial-value. " 1240 "Trying to recover." << endl; 1241 decCursor = oldDecCursor; 1252 bool matchOK = false; 1253 textcodec = TDEGlobal::charsets()->codecForName( charset, matchOK ); 1256 KMIME_WARN_UNKNOWN(Charset,charset); 1260 if ( !rfc2231Codec ) { 1261 rfc2231Codec = Codec::codecForName( "x-kmime-rfc2231"); 1262 assert( rfc2231Codec ); 1266 value += TQString::fromLatin1( decCursor, decEnd - decCursor ); 1270 Decoder * dec = rfc2231Codec->makeDecoder(); 1277 TQByteArray buffer( rfc2231Codec->maxDecodedSizeFor( decEnd - decCursor ) ); 1278 TQByteArray::Iterator bit = buffer.begin(); 1279 TQByteArray::ConstIterator bend = buffer.end(); 1281 if ( !dec-> decode( decCursor, decEnd, bit, bend ) ) 1282 KMIME_WARN << rfc2231Codec-> name() 1283 << " codec lies about it's maxDecodedSizeFor()\n" 1284 "result may be truncated" << endl; 1286 value += textcodec->toUnicode( buffer.begin(), bit - buffer.begin() ); 1288 kdDebug() << "value now: \"" << value << "\"" << endl; 1297 bool parseParameterList( const char* & scursor, const char * const send, 1298 TQMap<TQString,TQString> & result, bool isCRLF ) { 1300 TQMap<TQString,TQStringOrTQPair> rawParameterList; 1301 if (!parseRawParameterList( scursor, send, rawParameterList, isCRLF ) ) 1304 if ( rawParameterList.isEmpty() ) return true; 1311 Codec * rfc2231Codec = 0; 1312 TQTextCodec * textcodec = 0; 1315 enum Modes { NoMode = 0x0, Continued = 0x1, Encoded = 0x2 } mode; 1317 TQMapIterator<TQString,TQStringOrTQPair> it, end = rawParameterList.end(); 1319 for ( it = rawParameterList.begin() ; it != end ; ++it ) { 1320 if ( attribute.isNull() || !it.key().startsWith( attribute ) ) { 1326 if ( !attribute.isNull() ) result.insert( attribute, value ); 1329 attribute = it.key(); 1332 if ( attribute.endsWith( asterisk ) ) { 1333 attribute.truncate( attribute.length() - 1 ); 1334 mode = (Modes) (( int) mode | Encoded); 1337 if ( attribute.endsWith( asteriskZero ) ) { 1338 attribute.truncate( attribute.length() - 2 ); 1339 mode = (Modes) (( int) mode | Continued); 1344 if ( mode & Encoded ) { 1345 decodeRFC2231Value( rfc2231Codec, textcodec, 1347 value, (*it).qpair ); 1350 if ( (*it).qpair.first ) 1351 value += TQString::fromLatin1( (*it).qpair.first, (*it).qpair.second ); 1353 value += (*it).qstring; 1360 if ( !(mode & Continued) ) { 1362 result.insert( attribute, value ); 1364 attribute = TQString(); 1372 if ( it.key().endsWith( asterisk ) ) { 1374 decodeRFC2231Value( rfc2231Codec, textcodec, 1376 value, (*it).qpair ); 1379 if ( (*it).qpair.first ) 1380 value += TQString::fromLatin1( (*it).qpair.first, (*it).qpair.second ); 1382 value += (*it).qstring; 1388 if ( !attribute.isNull() ) 1389 result.insert( attribute, value ); 1394 static const char * stdDayNames[] = { 1395 "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" 1397 static const int stdDayNamesLen = sizeof stdDayNames / sizeof *stdDayNames; 1399 static bool parseDayName( const char* & scursor, const char * const send ) 1402 if ( send - scursor < 3 ) return false; 1404 for ( int i = 0 ; i < stdDayNamesLen ; ++i ) 1405 if ( tqstrnicmp( scursor, stdDayNames[i], 3 ) == 0 ) { 1407 kdDebug() << "found " << stdDayNames[i] << endl; 1415 static const char * stdMonthNames[] = { 1416 "Jan", "Feb", "Mar", "Apr", "May", "Jun", 1417 "Jul", "Aug", "Sep", "Oct", "Nov", "Dez" 1419 static const int stdMonthNamesLen = 1420 sizeof stdMonthNames / sizeof *stdMonthNames; 1422 static bool parseMonthName( const char* & scursor, const char * const send, 1426 if ( send - scursor < 3 ) return false; 1428 for ( result = 0 ; result < stdMonthNamesLen ; ++result ) 1429 if ( tqstrnicmp( scursor, stdMonthNames[result], 3 ) == 0 ) { 1438 static const struct { 1439 const char * tzName; 1440 long int secsEastOfGMT; 1487 static const int timeZonesLen = sizeof timeZones / sizeof *timeZones; 1489 static bool parseAlphaNumericTimeZone( const char* & scursor, 1490 const char * const send, 1491 long int & secsEastOfGMT, 1492 bool & timeZoneKnown ) 1494 TQPair<const char*,int> maybeTimeZone(0,0); 1495 if ( !parseToken( scursor, send, maybeTimeZone, false ) ) 1497 for ( int i = 0 ; i < timeZonesLen ; ++i ) 1498 if ( tqstrnicmp( timeZones[i].tzName, 1499 maybeTimeZone.first, maybeTimeZone.second ) == 0 ) { 1500 scursor += maybeTimeZone.second; 1501 secsEastOfGMT = timeZones[i].secsEastOfGMT; 1502 timeZoneKnown = true; 1507 KMIME_WARN_UNKNOWN(time zone,TQCString( maybeTimeZone.first, maybeTimeZone.second+1 )); 1509 timeZoneKnown = false; 1514 static int parseDigits( const char* & scursor, const char * const send, 1519 for ( ; scursor != send && isdigit( *scursor ) ; scursor++, digits++ ) { 1521 result += int( *scursor - '0' ); 1526 static bool parseTimeOfDay( const char* & scursor, const char * const send, 1527 int & hour, int & min, int & sec, bool isCRLF= false ) 1534 if ( !parseDigits( scursor, send, hour ) ) return false; 1536 eatCFWS( scursor, send, isCRLF ); 1537 if ( scursor == send || *scursor != ':' ) return false; 1540 eatCFWS( scursor, send, isCRLF ); 1541 if ( scursor == send ) return false; 1546 if ( !parseDigits( scursor, send, min ) ) return false; 1548 eatCFWS( scursor, send, isCRLF ); 1549 if ( scursor == send ) return true; 1554 if ( *scursor == ':' ) { 1557 eatCFWS( scursor, send, isCRLF ); 1558 if ( scursor == send ) return false; 1560 if ( !parseDigits( scursor, send, sec ) ) return false; 1569 bool parseTime( const char* & scursor, const char * send, 1570 int & hour, int & min, int & sec, long int & secsEastOfGMT, 1571 bool & timeZoneKnown, bool isCRLF ) 1583 eatCFWS( scursor, send, isCRLF ); 1584 if ( scursor == send ) return false; 1586 if ( !parseTimeOfDay( scursor, send, hour, min, sec, isCRLF ) ) 1589 eatCFWS( scursor, send, isCRLF ); 1590 if ( scursor == send ) { 1591 timeZoneKnown = false; 1596 timeZoneKnown = true; 1597 if ( *scursor == '+' || *scursor == '-' ) { 1599 const char sign = *scursor++; 1602 if ( parseDigits( scursor, send, maybeTimeZone ) != 4 ) return false; 1603 secsEastOfGMT = 60 * ( maybeTimeZone / 100 * 60 + maybeTimeZone % 100 ); 1604 if ( sign == '-' ) { 1605 secsEastOfGMT *= -1; 1606 if ( secsEastOfGMT == 0 ) 1607 timeZoneKnown = false; 1611 if ( !parseAlphaNumericTimeZone( scursor, send, secsEastOfGMT, timeZoneKnown ) ) 1618 bool parseDateTime( const char* & scursor, const char * const send, 1619 Types::DateTime & result, bool isCRLF ) 1631 struct tm maybeDateTime = { 1632 #ifdef HAVE_TM_GMTOFF 1635 0, 0, 0, 0, 0, 0, 0, 0, 0 1638 eatCFWS( scursor, send, isCRLF ); 1639 if ( scursor == send ) return false; 1644 if ( parseDayName( scursor, send ) ) { 1645 eatCFWS( scursor, send, isCRLF ); 1646 if ( scursor == send ) return false; 1648 if ( *scursor == ',' ) { 1650 eatCFWS( scursor, send, isCRLF ); 1658 if ( !parseDigits( scursor, send, maybeDay ) ) return false; 1660 eatCFWS( scursor, send, isCRLF ); 1661 if ( scursor == send ) return false; 1664 maybeDateTime.tm_mday = maybeDay; 1670 if ( !parseMonthName( scursor, send, maybeMonth ) ) return false; 1671 if ( scursor == send ) return false; 1672 assert( maybeMonth >= 0 ); assert( maybeMonth <= 11 ); 1674 eatCFWS( scursor, send, isCRLF ); 1675 if ( scursor == send ) return false; 1678 maybeDateTime.tm_mon = maybeMonth; 1684 if ( !parseDigits( scursor, send, maybeYear ) ) return false; 1686 if ( maybeYear < 50 ) 1688 else if ( maybeYear < 1000 ) 1691 if ( maybeYear < 1900 ) return false; 1693 eatCFWS( scursor, send, isCRLF ); 1694 if ( scursor == send ) return false; 1697 maybeDateTime.tm_year = maybeYear - 1900; 1702 int maybeHour, maybeMinute, maybeSecond; 1703 long int secsEastOfGMT; 1704 bool timeZoneKnown = true; 1706 if ( !parseTime( scursor, send, 1707 maybeHour, maybeMinute, maybeSecond, 1708 secsEastOfGMT, timeZoneKnown, isCRLF ) ) 1712 maybeDateTime.tm_hour = maybeHour; 1713 maybeDateTime.tm_min = maybeMinute; 1714 maybeDateTime.tm_sec = maybeSecond; 1715 maybeDateTime.tm_isdst = DateFormatter::isDaylight(); 1717 result.time = mktime( &maybeDateTime ); 1718 if ( result.time == (time_t)(-1) ) return false; 1722 result.secsEastOfGMT = secsEastOfGMT; 1723 result.timeZoneKnown = timeZoneKnown; 1729 bool tryToMakeAnySenseOfDateString( const char* & scursor, 1730 const char * const send, 1731 time_t & result, bool isCRLF )
Abstract base class of codecs like base64 and quoted-printable.
Stateful decoder class, modelled after TQTextDecoder.
virtual const char * name() const =0
virtual bool decode(const char *&scursor, const char *const send, char *&dcursor, const char *const dend)=0 Decode a chunk of data, maintaining state information between calls.
|