00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 #include "kmime_headers.h"
00019
00020 #include "kmime_util.h"
00021 #include "kmime_content.h"
00022 #include "kmime_codecs.h"
00023 #include "kmime_header_parsing.h"
00024 #include "kmime_warning.h"
00025
00026 #include "kqcstringsplitter.h"
00027
00028 #include <qtextcodec.h>
00029 #include <qstring.h>
00030 #include <qcstring.h>
00031 #include <qstringlist.h>
00032 #include <qvaluelist.h>
00033
00034 #include <kglobal.h>
00035 #include <kcharsets.h>
00036 #include <krfcdate.h>
00037
00038 #include <assert.h>
00039
00040
00041 using namespace KMime;
00042 using namespace KMime::Headers;
00043 using namespace KMime::Types;
00044 using namespace KMime::HeaderParsing;
00045
00046 namespace KMime {
00047 namespace Headers {
00048
00049
00050 QCString Base::rfc2047Charset()
00051 {
00052 if( (e_ncCS==0) || forceCS() )
00053 return defaultCS();
00054 else
00055 return QCString(e_ncCS);
00056 }
00057
00058
00059 void Base::setRFC2047Charset(const QCString &cs)
00060 {
00061 e_ncCS=cachedCharset(cs);
00062 }
00063
00064
00065 bool Base::forceCS()
00066 {
00067 return ( p_arent!=0 ? p_arent->forceDefaultCS() : false );
00068 }
00069
00070
00071 QCString Base::defaultCS()
00072 {
00073 return ( p_arent!=0 ? p_arent->defaultCharset() : Latin1 );
00074 }
00075
00076
00077
00078
00079 namespace Generics {
00080
00081
00082
00083 void GUnstructured::from7BitString( const QCString & str )
00084 {
00085 d_ecoded = decodeRFC2047String( str, &e_ncCS, defaultCS(), forceCS() );
00086 }
00087
00088 QCString GUnstructured::as7BitString( bool withHeaderType )
00089 {
00090 QCString result;
00091 if ( withHeaderType )
00092 result = typeIntro();
00093 result += encodeRFC2047String( d_ecoded, e_ncCS ) ;
00094
00095 return result;
00096 }
00097
00098 void GUnstructured::fromUnicodeString( const QString & str,
00099 const QCString & suggestedCharset )
00100 {
00101 d_ecoded = str;
00102 e_ncCS = cachedCharset( suggestedCharset );
00103 }
00104
00105 QString GUnstructured::asUnicodeString()
00106 {
00107 return d_ecoded;
00108 }
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130 bool MailboxList::parse( const char* & scursor, const char * const send,
00131 bool isCRLF ) {
00132
00133
00134
00135
00136
00137 QValueList<Address> maybeAddressList;
00138 if ( !parseAddressList( scursor, send, maybeAddressList, isCRLF ) )
00139 return false;
00140
00141 mMailboxList.clear();
00142
00143
00144 QValueList<Address>::Iterator it;
00145 for ( it = maybeAddressList.begin(); it != maybeAddressList.end() ; ++it ) {
00146 if ( !(*it).displayName.isEmpty() ) {
00147 KMIME_WARN << "mailbox groups in header disallowing them! Name: \""
00148 << (*it).displayName << "\"" << endl;
00149 }
00150 mMailboxList += (*it).mailboxList;
00151 }
00152 return true;
00153 }
00154
00155
00156
00157
00158
00159
00160
00161 bool SingleMailbox::parse( const char* & scursor, const char * const send,
00162 bool isCRLF ) {
00163 if ( !MailboxList::parse( scursor, send, isCRLF ) ) return false;
00164
00165 if ( mMailboxList.count() > 1 ) {
00166 KMIME_WARN << "multiple mailboxes in header allowing only a single one!"
00167 << endl;
00168 }
00169 return true;
00170 }
00171
00172
00173
00174
00175
00176
00177
00178 bool AddressList::parse( const char* & scursor, const char * const send,
00179 bool isCRLF ) {
00180
00181 QValueList<Address> maybeAddressList;
00182 if ( !parseAddressList( scursor, send, maybeAddressList, isCRLF ) )
00183 return false;
00184
00185 mAddressList = maybeAddressList;
00186 return true;
00187 }
00188
00189
00190
00191
00192
00193
00194
00195 bool GToken::parse( const char* & scursor, const char * const send,
00196 bool isCRLF ) {
00197
00198 eatCFWS( scursor, send, isCRLF );
00199
00200 if ( scursor == send ) return false;
00201
00202 QPair<const char*,int> maybeToken;
00203 if ( !parseToken( scursor, send, maybeToken, false ) )
00204 return false;
00205 mToken = QCString( maybeToken.first, maybeToken.second );
00206
00207
00208 eatCFWS( scursor, send, isCRLF );
00209 if ( scursor != send ) {
00210 KMIME_WARN << "trailing garbage after token in header allowing "
00211 "only a single token!" << endl;
00212 }
00213 return true;
00214 }
00215
00216
00217
00218
00219
00220
00221
00222 bool GPhraseList::parse( const char* & scursor, const char * const send,
00223 bool isCRLF ) {
00224
00225 mPhraseList.clear();
00226
00227 while ( scursor != send ) {
00228 eatCFWS( scursor, send, isCRLF );
00229
00230 if ( scursor == send ) return true;
00231
00232 if ( *scursor != ',' ) { scursor++; continue; }
00233
00234 QString maybePhrase;
00235 if ( !parsePhrase( scursor, send, maybePhrase, isCRLF ) )
00236 return false;
00237 mPhraseList.append( maybePhrase );
00238
00239 eatCFWS( scursor, send, isCRLF );
00240
00241 if ( scursor == send ) return true;
00242
00243 if ( *scursor != ',' ) scursor++;
00244 }
00245 return true;
00246 }
00247
00248
00249
00250
00251
00252
00253
00254 bool GDotAtom::parse( const char* & scursor, const char * const send,
00255 bool isCRLF ) {
00256
00257 QString maybeDotAtom;
00258 if ( !parseDotAtom( scursor, send, maybeDotAtom, isCRLF ) )
00259 return false;
00260
00261 mDotAtom = maybeDotAtom;
00262
00263 eatCFWS( scursor, send, isCRLF );
00264 if ( scursor != send ) {
00265 KMIME_WARN << "trailing garbage after dot-atom in header allowing "
00266 "only a single dot-atom!" << endl;
00267 }
00268 return true;
00269 }
00270
00271
00272
00273
00274
00275
00276
00277
00278
00279
00280
00281
00282
00283
00284 bool GContentType::parse( const char* & scursor, const char * const send,
00285 bool isCRLF ) {
00286
00287
00288
00289 mMimeType = 0;
00290 mMimeSubType = 0;
00291 mParameterHash.clear();
00292
00293 eatCFWS( scursor, send, isCRLF );
00294 if ( scursor == send ) {
00295
00296 return false;
00297 }
00298
00299
00300
00301
00302
00303 QPair<const char*,int> maybeMimeType;
00304 if ( !parseToken( scursor, send, maybeMimeType, false ) )
00305 return false;
00306
00307 mMimeType = QCString( maybeMimeType.first, maybeMimeType.second ).lower();
00308
00309
00310
00311
00312
00313 eatCFWS( scursor, send, isCRLF );
00314 if ( scursor == send || *scursor != '/' ) return false;
00315 scursor++;
00316 eatCFWS( scursor, send, isCRLF );
00317 if ( scursor == send ) return false;
00318
00319 QPair<const char*,int> maybeSubType;
00320 if ( !parseToken( scursor, send, maybeSubType, false ) )
00321 return false;
00322
00323 mMimeSubType = QCString( maybeSubType.first, maybeSubType.second ).lower();
00324
00325
00326
00327
00328
00329 eatCFWS( scursor, send, isCRLF );
00330 if ( scursor == send ) return true;
00331
00332 if ( *scursor != ';' ) return false;
00333 scursor++;
00334
00335 if ( !parseParameterList( scursor, send, mParameterHash, isCRLF ) )
00336 return false;
00337
00338 return true;
00339 }
00340
00341
00342
00343
00344
00345
00346
00347 bool GCISTokenWithParameterList::parse( const char* & scursor,
00348 const char * const send, bool isCRLF ) {
00349
00350 mToken = 0;
00351 mParameterHash.clear();
00352
00353
00354
00355
00356
00357 eatCFWS( scursor, send, isCRLF );
00358 if ( scursor == send ) return false;
00359
00360 QPair<const char*,int> maybeToken;
00361 if ( !parseToken( scursor, send, maybeToken, false ) )
00362 return false;
00363
00364 mToken = QCString( maybeToken.first, maybeToken.second ).lower();
00365
00366
00367
00368
00369
00370 eatCFWS( scursor, send, isCRLF );
00371 if ( scursor == send ) return true;
00372
00373 if ( *scursor != ';' ) return false;
00374 scursor++;
00375
00376 if ( !parseParameterList( scursor, send, mParameterHash, isCRLF ) )
00377 return false;
00378
00379 return true;
00380 }
00381
00382
00383
00384
00385
00386
00387
00388 bool GIdent::parse( const char* & scursor, const char * const send, bool isCRLF ) {
00389
00390
00391
00392
00393
00394
00395
00396
00397 mMsgIdList.clear();
00398
00399 while ( scursor != send ) {
00400 eatCFWS( scursor, send, isCRLF );
00401
00402 if ( scursor == send ) return true;
00403
00404 if ( *scursor == ',' ) { scursor++; continue; }
00405
00406 AddrSpec maybeMsgId;
00407 if ( !parseAngleAddr( scursor, send, maybeMsgId, isCRLF ) )
00408 return false;
00409 mMsgIdList.append( maybeMsgId );
00410
00411 eatCFWS( scursor, send, isCRLF );
00412
00413 if ( scursor == send ) return true;
00414
00415 if ( *scursor == ',' ) scursor++;
00416 }
00417 return true;
00418 }
00419
00420
00421
00422
00423
00424
00425
00426 bool GSingleIdent::parse( const char* & scursor, const char * const send, bool isCRLF ) {
00427
00428 if ( !GIdent::parse( scursor, send, isCRLF ) ) return false;
00429
00430 if ( mMsgIdList.count() > 1 ) {
00431 KMIME_WARN << "more than one msg-id in header "
00432 "allowing only a single one!" << endl;
00433 }
00434 return true;
00435 }
00436
00437
00438
00439
00440
00441
00442 }
00443
00444
00445
00446
00447 bool ReturnPath::parse( const char* & scursor, const char * const send, bool isCRLF ) {
00448
00449 eatCFWS( scursor, send, isCRLF );
00450 if ( scursor == send ) return false;
00451
00452 const char * oldscursor = scursor;
00453
00454 Mailbox maybeMailbox;
00455 if ( !parseMailbox( scursor, send, maybeMailbox, isCRLF ) ) {
00456
00457 scursor = oldscursor;
00458 if ( *scursor != '<' ) return false;
00459 scursor++;
00460 eatCFWS( scursor, send, isCRLF );
00461 if ( scursor == send || *scursor != '>' ) return false;
00462 scursor++;
00463
00464
00465 AddrSpec emptyAddrSpec;
00466 maybeMailbox.displayName = QString::null;
00467 maybeMailbox.addrSpec = emptyAddrSpec;
00468 } else
00469
00470 if ( !maybeMailbox.displayName.isEmpty() ) {
00471 KMIME_WARN << "display-name \"" << maybeMailbox.displayName
00472 << "\" in Return-Path!" << endl;
00473 }
00474
00475
00476 eatCFWS( scursor, send, isCRLF );
00477
00478 if ( scursor != send ) {
00479 KMIME_WARN << "trailing garbage after angle-addr in Return-Path!" << endl;
00480 }
00481 return true;
00482 }
00483
00484
00485
00486
00487
00488
00489
00490
00491 void Generic::setType(const char *type)
00492 {
00493 if(t_ype)
00494 delete[] t_ype;
00495 if(type) {
00496 t_ype=new char[strlen(type)+1];
00497 strcpy(t_ype, type);
00498 }
00499 else
00500 t_ype=0;
00501 }
00502
00503
00504
00505
00506 #if !defined(KMIME_NEW_STYLE_CLASSTREE)
00507
00508
00509 void MessageID::from7BitString(const QCString &s)
00510 {
00511 m_id=s;
00512 }
00513
00514
00515 QCString MessageID::as7BitString(bool incType)
00516 {
00517 if(incType)
00518 return ( typeIntro()+m_id );
00519 else
00520 return m_id;
00521 }
00522
00523
00524 void MessageID::fromUnicodeString(const QString &s, const QCString&)
00525 {
00526 m_id=s.latin1();
00527 }
00528
00529
00530 QString MessageID::asUnicodeString()
00531 {
00532 return QString::fromLatin1(m_id);
00533 }
00534
00535
00536 void MessageID::generate(const QCString &fqdn)
00537 {
00538 m_id="<"+uniqueString()+"@"+fqdn+">";
00539 }
00540
00541
00542 #endif
00543
00544
00545
00546
00547 void Control::from7BitString(const QCString &s)
00548 {
00549 c_trlMsg=s;
00550 }
00551
00552
00553 QCString Control::as7BitString(bool incType)
00554 {
00555 if(incType)
00556 return ( typeIntro()+c_trlMsg );
00557 else
00558 return c_trlMsg;
00559 }
00560
00561
00562 void Control::fromUnicodeString(const QString &s, const QCString&)
00563 {
00564 c_trlMsg=s.latin1();
00565 }
00566
00567
00568 QString Control::asUnicodeString()
00569 {
00570 return QString::fromLatin1(c_trlMsg);
00571 }
00572
00573
00574
00575
00576
00577 #if !defined(KMIME_NEW_STYLE_CLASSTREE)
00578
00579 void AddressField::from7BitString(const QCString &s)
00580 {
00581 int pos1=0, pos2=0, type=0;
00582 QCString n;
00583
00584
00585 if(s.find( QRegExp("*@*(*)", false, true) )!=-1) type=2;
00586 else if(s.find( QRegExp("*<*@*>", false, true) )!=-1) type=1;
00587 else if(s.find( QRegExp("*@*", false, true) )!=-1) type=0;
00588 else {
00589 n_ame=decodeRFC2047String(s, &e_ncCS, defaultCS(), forceCS());
00590 return;
00591 }
00592
00593 switch(type) {
00594
00595 case 0:
00596 e_mail=s.copy();
00597 break;
00598
00599 case 1:
00600 pos1=0;
00601 pos2=s.find('<');
00602 if(pos2!=-1) {
00603 n=s.mid(pos1, pos2-pos1).stripWhiteSpace();
00604 pos1=pos2+1;
00605 pos2=s.find('>', pos1);
00606 if(pos2!=-1)
00607 e_mail=s.mid(pos1, pos2-pos1);
00608 }
00609 else return;
00610 break;
00611
00612 case 2:
00613 pos1=0;
00614 pos2=s.find('(');
00615 if(pos2!=-1) {
00616 e_mail=s.mid(pos1, pos2-pos1).stripWhiteSpace();
00617 pos1=pos2+1;
00618 pos2=s.find(')', pos1);
00619 if(pos2!=-1)
00620 n=s.mid(pos1, pos2-pos1).stripWhiteSpace();
00621 }
00622 break;
00623
00624 default: break;
00625 }
00626
00627 if(!n.isEmpty()) {
00628 removeQuots(n);
00629 n_ame=decodeRFC2047String(n, &e_ncCS, defaultCS(), forceCS());
00630 }
00631 }
00632
00633
00634 QCString AddressField::as7BitString(bool incType)
00635 {
00636 QCString ret;
00637
00638 if(incType && type()[0]!='\0')
00639 ret=typeIntro();
00640
00641 if(n_ame.isEmpty())
00642 ret+=e_mail;
00643 else {
00644 if (isUsAscii(n_ame)) {
00645 QCString tmp(n_ame.latin1());
00646 addQuotes(tmp, false);
00647 ret+=tmp;
00648 } else {
00649 ret+=encodeRFC2047String(n_ame, e_ncCS, true);
00650 }
00651 if (!e_mail.isEmpty())
00652 ret += " <"+e_mail+">";
00653 }
00654
00655 return ret;
00656 }
00657
00658
00659 void AddressField::fromUnicodeString(const QString &s, const QCString &cs)
00660 {
00661 int pos1=0, pos2=0, type=0;
00662 QCString n;
00663
00664 e_ncCS=cachedCharset(cs);
00665
00666
00667 if(s.find( QRegExp("*@*(*)", false, true) )!=-1) type=2;
00668 else if(s.find( QRegExp("*<*@*>", false, true) )!=-1) type=1;
00669 else if(s.find( QRegExp("*@*", false, true) )!=-1) type=0;
00670 else {
00671 n_ame=s;
00672 return;
00673 }
00674
00675 switch(type) {
00676
00677 case 0:
00678 e_mail=s.latin1();
00679 break;
00680
00681 case 1:
00682 pos1=0;
00683 pos2=s.find('<');
00684 if(pos2!=-1) {
00685 n_ame=s.mid(pos1, pos2-pos1).stripWhiteSpace();
00686 pos1=pos2+1;
00687 pos2=s.find('>', pos1);
00688 if(pos2!=-1)
00689 e_mail=s.mid(pos1, pos2-pos1).latin1();
00690 }
00691 else return;
00692 break;
00693
00694 case 2:
00695 pos1=0;
00696 pos2=s.find('(');
00697 if(pos2!=-1) {
00698 e_mail=s.mid(pos1, pos2-pos1).stripWhiteSpace().latin1();
00699 pos1=pos2+1;
00700 pos2=s.find(')', pos1);
00701 if(pos2!=-1)
00702 n_ame=s.mid(pos1, pos2-pos1).stripWhiteSpace();
00703 }
00704 break;
00705
00706 default: break;
00707 }
00708
00709 if(!n_ame.isEmpty())
00710 removeQuots(n_ame);
00711 }
00712
00713
00714 QString AddressField::asUnicodeString()
00715 {
00716 if(n_ame.isEmpty())
00717 return QString(e_mail);
00718 else {
00719 QString s = n_ame;
00720 if (!e_mail.isEmpty())
00721 s += " <"+e_mail+">";
00722 return s;
00723 }
00724 }
00725
00726
00727 QCString AddressField::nameAs7Bit()
00728 {
00729 return encodeRFC2047String(n_ame, e_ncCS);
00730 }
00731
00732
00733 void AddressField::setNameFrom7Bit(const QCString &s)
00734 {
00735 n_ame=decodeRFC2047String(s, &e_ncCS, defaultCS(), forceCS());
00736 }
00737
00738
00739 #endif
00740
00741
00742
00743
00744 bool MailCopiesTo::isValid()
00745 {
00746 if (hasEmail())
00747 return true;
00748
00749 if ((n_ame == "nobody") ||
00750 (n_ame == "never") ||
00751 (n_ame == "poster") ||
00752 (n_ame == "always"))
00753 return true;
00754 else
00755 return false;
00756 }
00757
00758
00759 bool MailCopiesTo::alwaysCopy()
00760 {
00761 return (hasEmail() || (n_ame == "poster") || (n_ame == "always"));
00762 }
00763
00764
00765 bool MailCopiesTo::neverCopy()
00766 {
00767 return ((n_ame == "nobody") || (n_ame == "never"));
00768 }
00769
00770
00771
00772
00773
00774
00775
00776
00777 void Date::from7BitString(const QCString &s)
00778 {
00779 t_ime=KRFCDate::parseDate(s);
00780 }
00781
00782
00783 QCString Date::as7BitString(bool incType)
00784 {
00785 if(incType)
00786 return ( typeIntro()+KRFCDate::rfc2822DateString(t_ime) );
00787 else
00788 return QCString(KRFCDate::rfc2822DateString(t_ime));
00789 }
00790
00791
00792 void Date::fromUnicodeString(const QString &s, const QCString&)
00793 {
00794 from7BitString( QCString(s.latin1()) );
00795 }
00796
00797
00798 QString Date::asUnicodeString()
00799 {
00800 return QString::fromLatin1(as7BitString(false));
00801 }
00802
00803
00804 QDateTime Date::qdt()
00805 {
00806 QDateTime dt;
00807 dt.setTime_t(t_ime);
00808 return dt;
00809 }
00810
00811
00812 int Date::ageInDays()
00813 {
00814 QDate today=QDate::currentDate();
00815 return ( qdt().date().daysTo(today) );
00816 }
00817
00818
00819
00820
00821
00822 #if !defined(KMIME_NEW_STYLE_CLASSTREE)
00823
00824
00825 void To::from7BitString(const QCString &s)
00826 {
00827 if(a_ddrList)
00828 a_ddrList->clear();
00829 else {
00830 a_ddrList=new QPtrList<AddressField>;
00831 a_ddrList->setAutoDelete(true);
00832 }
00833
00834 KQCStringSplitter split;
00835 split.init(s, ",");
00836 bool splitOk=split.first();
00837 if(!splitOk)
00838 a_ddrList->append( new AddressField(p_arent, s ));
00839 else {
00840 do {
00841 a_ddrList->append( new AddressField(p_arent, split.string()) );
00842 } while(split.next());
00843 }
00844
00845 e_ncCS=cachedCharset(a_ddrList->first()->rfc2047Charset());
00846 }
00847
00848
00849 QCString To::as7BitString(bool incType)
00850 {
00851 QCString ret;
00852
00853 if(incType)
00854 ret+=typeIntro();
00855
00856 if (a_ddrList) {
00857 AddressField *it=a_ddrList->first();
00858 if (it)
00859 ret+=it->as7BitString(false);
00860 for (it=a_ddrList->next() ; it != 0; it=a_ddrList->next() )
00861 ret+=","+it->as7BitString(false);
00862 }
00863
00864 return ret;
00865 }
00866
00867
00868 void To::fromUnicodeString(const QString &s, const QCString &cs)
00869 {
00870 if(a_ddrList)
00871 a_ddrList->clear();
00872 else {
00873 a_ddrList=new QPtrList<AddressField>;
00874 a_ddrList->setAutoDelete(true);
00875 }
00876
00877 QStringList l=QStringList::split(",", s);
00878
00879 QStringList::Iterator it=l.begin();
00880 for(; it!=l.end(); ++it)
00881 a_ddrList->append(new AddressField( p_arent, (*it), cs ));
00882
00883 e_ncCS=cachedCharset(cs);
00884 }
00885
00886
00887 QString To::asUnicodeString()
00888 {
00889 if(!a_ddrList)
00890 return QString::null;
00891
00892 QString ret;
00893 AddressField *it=a_ddrList->first();
00894
00895 if (it)
00896 ret+=it->asUnicodeString();
00897 for (it=a_ddrList->next() ; it != 0; it=a_ddrList->next() )
00898 ret+=","+it->asUnicodeString();
00899 return ret;
00900 }
00901
00902
00903 void To::addAddress(const AddressField &a)
00904 {
00905 if(!a_ddrList) {
00906 a_ddrList=new QPtrList<AddressField>;
00907 a_ddrList->setAutoDelete(true);
00908 }
00909
00910 AddressField *add=new AddressField(a);
00911 add->setParent(p_arent);
00912 a_ddrList->append(add);
00913 }
00914
00915
00916 void To::emails(QStrList *l)
00917 {
00918 l->clear();
00919
00920 for (AddressField *it=a_ddrList->first(); it != 0; it=a_ddrList->next() )
00921 if( it->hasEmail() )
00922 l->append( it->email() );
00923 }
00924
00925
00926 #endif
00927
00928
00929
00930
00931 void Newsgroups::from7BitString(const QCString &s)
00932 {
00933 g_roups=s;
00934 e_ncCS=cachedCharset("UTF-8");
00935 }
00936
00937
00938 QCString Newsgroups::as7BitString(bool incType)
00939 {
00940 if(incType)
00941 return (typeIntro()+g_roups);
00942 else
00943 return g_roups;
00944 }
00945
00946
00947 void Newsgroups::fromUnicodeString(const QString &s, const QCString&)
00948 {
00949 g_roups=s.utf8();
00950 e_ncCS=cachedCharset("UTF-8");
00951 }
00952
00953
00954 QString Newsgroups::asUnicodeString()
00955 {
00956 return QString::fromUtf8(g_roups);
00957 }
00958
00959
00960 QCString Newsgroups::firstGroup()
00961 {
00962 int pos=0;
00963 if(!g_roups.isEmpty()) {
00964 pos=g_roups.find(',');
00965 if(pos==-1)
00966 return g_roups;
00967 else
00968 return g_roups.left(pos);
00969 }
00970 else
00971 return QCString();
00972 }
00973
00974
00975 QStringList Newsgroups::getGroups()
00976 {
00977 QStringList temp = QStringList::split(',', g_roups);
00978 QStringList ret;
00979 QString s;
00980
00981 for (QStringList::Iterator it = temp.begin(); it != temp.end(); ++it ) {
00982 s = (*it).simplifyWhiteSpace();
00983 ret.append(s);
00984 }
00985
00986 return ret;
00987 }
00988
00989
00990
00991
00992
00993
00994
00995 void Lines::from7BitString(const QCString &s)
00996 {
00997 l_ines=s.toInt();
00998 e_ncCS=cachedCharset(Latin1);
00999 }
01000
01001
01002 QCString Lines::as7BitString(bool incType)
01003 {
01004 QCString num;
01005 num.setNum(l_ines);
01006
01007 if(incType)
01008 return ( typeIntro()+num );
01009 else
01010 return num;
01011 }
01012
01013
01014 void Lines::fromUnicodeString(const QString &s, const QCString&)
01015 {
01016 l_ines=s.toInt();
01017 e_ncCS=cachedCharset(Latin1);
01018 }
01019
01020
01021 QString Lines::asUnicodeString()
01022 {
01023 QString num;
01024 num.setNum(l_ines);
01025
01026 return num;
01027 }
01028
01029
01030
01031
01032
01033 #if !defined(KMIME_NEW_STYLE_CLASSTREE)
01034
01035
01036 void References::from7BitString(const QCString &s)
01037 {
01038 r_ef=s;
01039 e_ncCS=cachedCharset(Latin1);
01040 }
01041
01042
01043 QCString References::as7BitString(bool incType)
01044 {
01045 if(incType)
01046 return ( typeIntro()+r_ef );
01047 else
01048 return r_ef;
01049 }
01050
01051
01052 void References::fromUnicodeString(const QString &s, const QCString&)
01053 {
01054 r_ef=s.latin1();
01055 e_ncCS=cachedCharset(Latin1);
01056 }
01057
01058
01059 QString References::asUnicodeString()
01060 {
01061 return QString::fromLatin1(r_ef);
01062 }
01063
01064
01065 int References::count()
01066 {
01067 int cnt1=0, cnt2=0;
01068 unsigned int r_efLen=r_ef.length();
01069 char *dataPtr=r_ef.data();
01070 for(unsigned int i=0; i<r_efLen; i++) {
01071 if(dataPtr[i]=='<') cnt1++;
01072 else if(dataPtr[i]=='>') cnt2++;
01073 }
01074
01075 if(cnt1<cnt2) return cnt1;
01076 else return cnt2;
01077 }
01078
01079
01080 QCString References::first()
01081 {
01082 p_os=-1;
01083 return next();
01084 }
01085
01086
01087 QCString References::next()
01088 {
01089 int pos1=0, pos2=0;
01090 QCString ret;
01091
01092 if(p_os!=0) {
01093 pos2=r_ef.findRev('>', p_os);
01094 p_os=0;
01095 if(pos2!=-1) {
01096 pos1=r_ef.findRev('<', pos2);
01097 if(pos1!=-1) {
01098 ret=r_ef.mid(pos1, pos2-pos1+1);
01099 p_os=pos1;
01100 }
01101 }
01102 }
01103 return ret;
01104 }
01105
01106
01107 QCString References::at(unsigned int i)
01108 {
01109 QCString ret;
01110 int pos1=0, pos2=0;
01111 unsigned int cnt=0;
01112
01113 while(pos1!=-1 && cnt < i+1) {
01114 pos2=pos1-1;
01115 pos1=r_ef.findRev('<', pos2);
01116 cnt++;
01117 }
01118
01119 if(pos1!=-1) {
01120 pos2=r_ef.find('>', pos1);
01121 if(pos2!=-1)
01122 ret=r_ef.mid(pos1, pos2-pos1+1);
01123 }
01124
01125 return ret;
01126 }
01127
01128
01129 void References::append(const QCString &s)
01130 {
01131 QString temp=r_ef.data();
01132 temp += " ";
01133 temp += s.data();
01134 QStringList lst=QStringList::split(' ',temp);
01135 QRegExp exp("^<.+@.+>$");
01136
01137
01138 QStringList::Iterator it = lst.begin();
01139 while (it != lst.end()) {
01140 if (-1==(*it).find(exp))
01141 it = lst.remove(it);
01142 else
01143 it++;
01144 }
01145
01146 if (lst.isEmpty()) {
01147 r_ef = s.copy();
01148 return;
01149 } else
01150 r_ef = "";
01151
01152 temp = lst.first();
01153 r_ef = temp.latin1();
01154 lst.remove(temp);
01155 int insPos = r_ef.length();
01156
01157 for (int i=1;i<=3;i++) {
01158 if (!lst.isEmpty()) {
01159 temp = lst.last();
01160 r_ef.insert(insPos,(QString(" %1").arg(temp)).latin1());
01161 lst.remove(temp);
01162 } else
01163 break;
01164 }
01165
01166 while (!lst.isEmpty()) {
01167 temp = lst.last();
01168 if ((15+r_ef.length()+temp.length())<1000) {
01169 r_ef.insert(insPos,(QString(" %1").arg(temp)).latin1());
01170 lst.remove(temp);
01171 } else
01172 return;
01173 }
01174 }
01175
01176
01177 #endif
01178
01179
01180
01181
01182 void UserAgent::from7BitString(const QCString &s)
01183 {
01184 u_agent=s;
01185 e_ncCS=cachedCharset(Latin1);
01186 }
01187
01188
01189 QCString UserAgent::as7BitString(bool incType)
01190 {
01191 if(incType)
01192 return ( typeIntro()+u_agent );
01193 else
01194 return u_agent;
01195 }
01196
01197
01198 void UserAgent::fromUnicodeString(const QString &s, const QCString&)
01199 {
01200 u_agent=s.latin1();
01201 e_ncCS=cachedCharset(Latin1);
01202 }
01203
01204
01205 QString UserAgent::asUnicodeString()
01206 {
01207 return QString::fromLatin1(u_agent);
01208 }
01209
01210
01211
01212
01213
01214 #if !defined(KMIME_NEW_STYLE_CLASSTREE)
01215
01216
01217 void ContentType::from7BitString(const QCString &s)
01218 {
01219 int pos=s.find(';');
01220
01221 if(pos==-1)
01222 m_imeType=s.simplifyWhiteSpace();
01223 else {
01224 m_imeType=s.left(pos).simplifyWhiteSpace();
01225 p_arams=s.mid(pos, s.length()-pos).simplifyWhiteSpace();
01226 }
01227
01228 if(isMultipart())
01229 c_ategory=CCcontainer;
01230 else
01231 c_ategory=CCsingle;
01232
01233 e_ncCS=cachedCharset(Latin1);
01234 }
01235
01236
01237 QCString ContentType::as7BitString(bool incType)
01238 {
01239 if(incType)
01240 return (typeIntro()+m_imeType+p_arams);
01241 else
01242 return (m_imeType+p_arams);
01243 }
01244
01245
01246 void ContentType::fromUnicodeString(const QString &s, const QCString&)
01247 {
01248 from7BitString( QCString(s.latin1()) );
01249 }
01250
01251
01252 QString ContentType::asUnicodeString()
01253 {
01254 return QString::fromLatin1(as7BitString(false));
01255 }
01256
01257
01258 QCString ContentType::mediaType()
01259 {
01260 int pos=m_imeType.find('/');
01261 if(pos==-1)
01262 return m_imeType;
01263 else
01264 return m_imeType.left(pos);
01265 }
01266
01267
01268 QCString ContentType::subType()
01269 {
01270 int pos=m_imeType.find('/');
01271 if(pos==-1)
01272 return QCString();
01273 else
01274 return m_imeType.mid(pos, m_imeType.length()-pos);
01275 }
01276
01277
01278 void ContentType::setMimeType(const QCString &s)
01279 {
01280 p_arams.resize(0);
01281 m_imeType=s;
01282
01283 if(isMultipart())
01284 c_ategory=CCcontainer;
01285 else
01286 c_ategory=CCsingle;
01287 }
01288
01289
01290 bool ContentType::isMediatype(const char *s)
01291 {
01292 return ( strncasecmp(m_imeType.data(), s, strlen(s)) );
01293 }
01294
01295
01296 bool ContentType::isSubtype(const char *s)
01297 {
01298 char *c=strchr(m_imeType.data(), '/');
01299
01300 if( (c==0) || (*(c+1)=='\0') )
01301 return false;
01302 else
01303 return ( strcasecmp(c+1, s)==0 );
01304 }
01305
01306
01307 bool ContentType::isText()
01308 {
01309 return (strncasecmp(m_imeType.data(), "text", 4)==0);
01310 }
01311
01312
01313 bool ContentType::isPlainText()
01314 {
01315 return (strcasecmp(m_imeType.data(), "text/plain")==0);
01316 }
01317
01318
01319 bool ContentType::isHTMLText()
01320 {
01321 return (strcasecmp(m_imeType.data(), "text/html")==0);
01322 }
01323
01324
01325 bool ContentType::isImage()
01326 {
01327 return (strncasecmp(m_imeType.data(), "image", 5)==0);
01328 }
01329
01330
01331 bool ContentType::isMultipart()
01332 {
01333 return (strncasecmp(m_imeType.data(), "multipart", 9)==0);
01334 }
01335
01336
01337 bool ContentType::isPartial()
01338 {
01339 return (strcasecmp(m_imeType.data(), "message/partial")==0);
01340 }
01341
01342
01343 QCString ContentType::charset()
01344 {
01345 QCString ret=getParameter("charset");
01346 if( ret.isEmpty() || forceCS() ) {
01347 ret=defaultCS();
01348 }
01349 return ret;
01350 }
01351
01352
01353 void ContentType::setCharset(const QCString &s)
01354 {
01355 setParameter("charset", s);
01356 }
01357
01358
01359 QCString ContentType::boundary()
01360 {
01361 return getParameter("boundary");
01362 }
01363
01364
01365 void ContentType::setBoundary(const QCString &s)
01366 {
01367 setParameter("boundary", s, true);
01368 }
01369
01370
01371 QString ContentType::name()
01372 {
01373 const char *dummy=0;
01374 return ( decodeRFC2047String(getParameter("name"), &dummy, defaultCS(), forceCS()) );
01375 }
01376
01377
01378 void ContentType::setName(const QString &s, const QCString &cs)
01379 {
01380 e_ncCS=cs;
01381
01382 if (isUsAscii(s)) {
01383 QCString tmp(s.latin1());
01384 addQuotes(tmp, true);
01385 setParameter("name", tmp, false);
01386 } else {
01387
01388 setParameter("name", encodeRFC2047String(s, cs), true);
01389 }
01390 }
01391
01392
01393 QCString ContentType::id()
01394 {
01395 return (getParameter("id"));
01396 }
01397
01398
01399 void ContentType::setId(const QCString &s)
01400 {
01401 setParameter("id", s, true);
01402 }
01403
01404
01405 int ContentType::partialNumber()
01406 {
01407 QCString p=getParameter("number");
01408 if(!p.isEmpty())
01409 return p.toInt();
01410 else
01411 return -1;
01412 }
01413
01414
01415 int ContentType::partialCount()
01416 {
01417 QCString p=getParameter("total");
01418 if(!p.isEmpty())
01419 return p.toInt();
01420 else
01421 return -1;
01422 }
01423
01424
01425 void ContentType::setPartialParams(int total, int number)
01426 {
01427 QCString num;
01428 num.setNum(number);
01429 setParameter("number", num);
01430 num.setNum(total);
01431 setParameter("total", num);
01432 }
01433
01434
01435 QCString ContentType::getParameter(const char *name)
01436 {
01437 QCString ret;
01438 int pos1=0, pos2=0;
01439 pos1=p_arams.find(name, 0, false);
01440 if(pos1!=-1) {
01441 if( (pos2=p_arams.find(';', pos1))==-1 )
01442 pos2=p_arams.length();
01443 pos1+=strlen(name)+1;
01444 ret=p_arams.mid(pos1, pos2-pos1);
01445 removeQuots(ret);
01446 }
01447 return ret;
01448 }
01449
01450
01451 void ContentType::setParameter(const QCString &name, const QCString &value, bool doubleQuotes)
01452 {
01453 int pos1=0, pos2=0;
01454 QCString param;
01455
01456 if(doubleQuotes)
01457 param=name+"=\""+value+"\"";
01458 else
01459 param=name+"="+value;
01460
01461 pos1=p_arams.find(name, 0, false);
01462 if(pos1==-1) {
01463 p_arams+="; "+param;
01464 }
01465 else {
01466 pos2=p_arams.find(';', pos1);
01467 if(pos2==-1)
01468 pos2=p_arams.length();
01469 p_arams.remove(pos1, pos2-pos1);
01470 p_arams.insert(pos1, param);
01471 }
01472 }
01473
01474
01475
01476
01477
01478
01479
01480 typedef struct { const char *s; int e; } encTableType;
01481
01482 static const encTableType encTable[] = { { "7Bit", CE7Bit },
01483 { "8Bit", CE8Bit },
01484 { "quoted-printable", CEquPr },
01485 { "base64", CEbase64 },
01486 { "x-uuencode", CEuuenc },
01487 { "binary", CEbinary },
01488 { 0, 0} };
01489
01490
01491 void CTEncoding::from7BitString(const QCString &s)
01492 {
01493 QCString stripped(s.simplifyWhiteSpace());
01494 c_te=CE7Bit;
01495 for(int i=0; encTable[i].s!=0; i++)
01496 if(strcasecmp(stripped.data(), encTable[i].s)==0) {
01497 c_te=(contentEncoding)encTable[i].e;
01498 break;
01499 }
01500 d_ecoded=( c_te==CE7Bit || c_te==CE8Bit );
01501
01502 e_ncCS=cachedCharset(Latin1);
01503 }
01504
01505
01506 QCString CTEncoding::as7BitString(bool incType)
01507 {
01508 QCString str;
01509 for(int i=0; encTable[i].s!=0; i++)
01510 if(c_te==encTable[i].e) {
01511 str=encTable[i].s;
01512 break;
01513 }
01514
01515 if(incType)
01516 return ( typeIntro()+str );
01517 else
01518 return str;
01519 }
01520
01521
01522 void CTEncoding::fromUnicodeString(const QString &s, const QCString&)
01523 {
01524 from7BitString( QCString(s.latin1()) );
01525 }
01526
01527
01528 QString CTEncoding::asUnicodeString()
01529 {
01530 return QString::fromLatin1(as7BitString(false));
01531 }
01532
01533
01534
01535
01536
01537
01538
01539 void CDisposition::from7BitString(const QCString &s)
01540 {
01541 if(strncasecmp(s.data(), "attachment", 10)==0)
01542 d_isp=CDattachment;
01543 else d_isp=CDinline;
01544
01545 int pos=s.find("filename=", 0, false);
01546 QCString fn;
01547 if(pos>-1) {
01548 pos+=9;
01549 fn=s.mid(pos, s.length()-pos);
01550 removeQuots(fn);
01551 f_ilename=decodeRFC2047String(fn, &e_ncCS, defaultCS(), forceCS());
01552 }
01553 }
01554
01555
01556 QCString CDisposition::as7BitString(bool incType)
01557 {
01558 QCString ret;
01559 if(d_isp==CDattachment)
01560 ret="attachment";
01561 else
01562 ret="inline";
01563
01564 if(!f_ilename.isEmpty()) {
01565 if (isUsAscii(f_ilename)) {
01566 QCString tmp(f_ilename.latin1());
01567 addQuotes(tmp, true);
01568 ret+="; filename="+tmp;
01569 } else {
01570
01571 ret+="; filename=\""+encodeRFC2047String(f_ilename, e_ncCS)+"\"";
01572 }
01573 }
01574
01575 if(incType)
01576 return ( typeIntro()+ret );
01577 else
01578 return ret;
01579 }
01580
01581
01582 void CDisposition::fromUnicodeString(const QString &s, const QCString &cs)
01583 {
01584 if(strncasecmp(s.latin1(), "attachment", 10)==0)
01585 d_isp=CDattachment;
01586 else d_isp=CDinline;
01587
01588 int pos=s.find("filename=", 0, false);
01589 if(pos>-1) {
01590 pos+=9;
01591 f_ilename=s.mid(pos, s.length()-pos);
01592 removeQuots(f_ilename);
01593 }
01594
01595 e_ncCS=cachedCharset(cs);
01596 }
01597
01598
01599 QString CDisposition::asUnicodeString()
01600 {
01601 QString ret;
01602 if(d_isp==CDattachment)
01603 ret="attachment";
01604 else
01605 ret="inline";
01606
01607 if(!f_ilename.isEmpty())
01608 ret+="; filename=\""+f_ilename+"\"";
01609
01610 return ret;
01611 }
01612
01613
01614 #endif
01615 }
01616
01617 }