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).stripWhiteSpace();
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 void To::names(QStringList *l)
00926 {
00927 l->clear();
00928
00929 for (AddressField *it=a_ddrList->first(); it != 0 ; it=a_ddrList->next() )
00930 if( it->hasName() )
00931 l->append( it->name() );
00932 }
00933
00934 void To::displayNames(QStringList *l)
00935 {
00936 l->clear();
00937
00938 for (AddressField *it=a_ddrList->first(); it != 0 ; it=a_ddrList->next() )
00939 l->append( it->asUnicodeString() );
00940 }
00941
00942
00943 #endif
00944
00945
00946
00947
00948 void Newsgroups::from7BitString(const QCString &s)
00949 {
00950 g_roups=s;
00951 e_ncCS=cachedCharset("UTF-8");
00952 }
00953
00954
00955 QCString Newsgroups::as7BitString(bool incType)
00956 {
00957 if(incType)
00958 return (typeIntro()+g_roups);
00959 else
00960 return g_roups;
00961 }
00962
00963
00964 void Newsgroups::fromUnicodeString(const QString &s, const QCString&)
00965 {
00966 g_roups=s.utf8();
00967 e_ncCS=cachedCharset("UTF-8");
00968 }
00969
00970
00971 QString Newsgroups::asUnicodeString()
00972 {
00973 return QString::fromUtf8(g_roups);
00974 }
00975
00976
00977 QCString Newsgroups::firstGroup()
00978 {
00979 int pos=0;
00980 if(!g_roups.isEmpty()) {
00981 pos=g_roups.find(',');
00982 if(pos==-1)
00983 return g_roups;
00984 else
00985 return g_roups.left(pos);
00986 }
00987 else
00988 return QCString();
00989 }
00990
00991
00992 QStringList Newsgroups::getGroups()
00993 {
00994 QStringList temp = QStringList::split(',', g_roups);
00995 QStringList ret;
00996 QString s;
00997
00998 for (QStringList::Iterator it = temp.begin(); it != temp.end(); ++it ) {
00999 s = (*it).simplifyWhiteSpace();
01000 ret.append(s);
01001 }
01002
01003 return ret;
01004 }
01005
01006
01007
01008
01009
01010
01011
01012 void Lines::from7BitString(const QCString &s)
01013 {
01014 l_ines=s.toInt();
01015 e_ncCS=cachedCharset(Latin1);
01016 }
01017
01018
01019 QCString Lines::as7BitString(bool incType)
01020 {
01021 QCString num;
01022 num.setNum(l_ines);
01023
01024 if(incType)
01025 return ( typeIntro()+num );
01026 else
01027 return num;
01028 }
01029
01030
01031 void Lines::fromUnicodeString(const QString &s, const QCString&)
01032 {
01033 l_ines=s.toInt();
01034 e_ncCS=cachedCharset(Latin1);
01035 }
01036
01037
01038 QString Lines::asUnicodeString()
01039 {
01040 QString num;
01041 num.setNum(l_ines);
01042
01043 return num;
01044 }
01045
01046
01047
01048
01049
01050 #if !defined(KMIME_NEW_STYLE_CLASSTREE)
01051
01052
01053 void References::from7BitString(const QCString &s)
01054 {
01055 r_ef=s;
01056 e_ncCS=cachedCharset(Latin1);
01057 }
01058
01059
01060 QCString References::as7BitString(bool incType)
01061 {
01062 if(incType)
01063 return ( typeIntro()+r_ef );
01064 else
01065 return r_ef;
01066 }
01067
01068
01069 void References::fromUnicodeString(const QString &s, const QCString&)
01070 {
01071 r_ef=s.latin1();
01072 e_ncCS=cachedCharset(Latin1);
01073 }
01074
01075
01076 QString References::asUnicodeString()
01077 {
01078 return QString::fromLatin1(r_ef);
01079 }
01080
01081
01082 int References::count()
01083 {
01084 int cnt1=0, cnt2=0;
01085 unsigned int r_efLen=r_ef.length();
01086 char *dataPtr=r_ef.data();
01087 for(unsigned int i=0; i<r_efLen; i++) {
01088 if(dataPtr[i]=='<') cnt1++;
01089 else if(dataPtr[i]=='>') cnt2++;
01090 }
01091
01092 if(cnt1<cnt2) return cnt1;
01093 else return cnt2;
01094 }
01095
01096
01097 QCString References::first()
01098 {
01099 p_os=-1;
01100 return next();
01101 }
01102
01103
01104 QCString References::next()
01105 {
01106 int pos1=0, pos2=0;
01107 QCString ret;
01108
01109 if(p_os!=0) {
01110 pos2=r_ef.findRev('>', p_os);
01111 p_os=0;
01112 if(pos2!=-1) {
01113 pos1=r_ef.findRev('<', pos2);
01114 if(pos1!=-1) {
01115 ret=r_ef.mid(pos1, pos2-pos1+1);
01116 p_os=pos1;
01117 }
01118 }
01119 }
01120 return ret;
01121 }
01122
01123
01124 QCString References::at(unsigned int i)
01125 {
01126 QCString ret;
01127 int pos1=0, pos2=0;
01128 unsigned int cnt=0;
01129
01130 while(pos1!=-1 && cnt < i+1) {
01131 pos2=pos1-1;
01132 pos1=r_ef.findRev('<', pos2);
01133 cnt++;
01134 }
01135
01136 if(pos1!=-1) {
01137 pos2=r_ef.find('>', pos1);
01138 if(pos2!=-1)
01139 ret=r_ef.mid(pos1, pos2-pos1+1);
01140 }
01141
01142 return ret;
01143 }
01144
01145
01146 void References::append(const QCString &s)
01147 {
01148 QString temp=r_ef.data();
01149 temp += " ";
01150 temp += s.data();
01151 QStringList lst=QStringList::split(' ',temp);
01152 QRegExp exp("^<.+@.+>$");
01153
01154
01155 QStringList::Iterator it = lst.begin();
01156 while (it != lst.end()) {
01157 if (-1==(*it).find(exp))
01158 it = lst.remove(it);
01159 else
01160 it++;
01161 }
01162
01163 if (lst.isEmpty()) {
01164 r_ef = s.copy();
01165 return;
01166 } else
01167 r_ef = "";
01168
01169 temp = lst.first();
01170 r_ef = temp.latin1();
01171 lst.remove(temp);
01172 int insPos = r_ef.length();
01173
01174 for (int i=1;i<=3;i++) {
01175 if (!lst.isEmpty()) {
01176 temp = lst.last();
01177 r_ef.insert(insPos,(QString(" %1").arg(temp)).latin1());
01178 lst.remove(temp);
01179 } else
01180 break;
01181 }
01182
01183 while (!lst.isEmpty()) {
01184 temp = lst.last();
01185 if ((15+r_ef.length()+temp.length())<1000) {
01186 r_ef.insert(insPos,(QString(" %1").arg(temp)).latin1());
01187 lst.remove(temp);
01188 } else
01189 return;
01190 }
01191 }
01192
01193
01194 #endif
01195
01196
01197
01198
01199 void UserAgent::from7BitString(const QCString &s)
01200 {
01201 u_agent=s;
01202 e_ncCS=cachedCharset(Latin1);
01203 }
01204
01205
01206 QCString UserAgent::as7BitString(bool incType)
01207 {
01208 if(incType)
01209 return ( typeIntro()+u_agent );
01210 else
01211 return u_agent;
01212 }
01213
01214
01215 void UserAgent::fromUnicodeString(const QString &s, const QCString&)
01216 {
01217 u_agent=s.latin1();
01218 e_ncCS=cachedCharset(Latin1);
01219 }
01220
01221
01222 QString UserAgent::asUnicodeString()
01223 {
01224 return QString::fromLatin1(u_agent);
01225 }
01226
01227
01228
01229
01230
01231 #if !defined(KMIME_NEW_STYLE_CLASSTREE)
01232
01233
01234 void ContentType::from7BitString(const QCString &s)
01235 {
01236 int pos=s.find(';');
01237
01238 if(pos==-1)
01239 m_imeType=s.simplifyWhiteSpace();
01240 else {
01241 m_imeType=s.left(pos).simplifyWhiteSpace();
01242 p_arams=s.mid(pos, s.length()-pos).simplifyWhiteSpace();
01243 }
01244
01245 if(isMultipart())
01246 c_ategory=CCcontainer;
01247 else
01248 c_ategory=CCsingle;
01249
01250 e_ncCS=cachedCharset(Latin1);
01251 }
01252
01253
01254 QCString ContentType::as7BitString(bool incType)
01255 {
01256 if(incType)
01257 return (typeIntro()+m_imeType+p_arams);
01258 else
01259 return (m_imeType+p_arams);
01260 }
01261
01262
01263 void ContentType::fromUnicodeString(const QString &s, const QCString&)
01264 {
01265 from7BitString( QCString(s.latin1()) );
01266 }
01267
01268
01269 QString ContentType::asUnicodeString()
01270 {
01271 return QString::fromLatin1(as7BitString(false));
01272 }
01273
01274
01275 QCString ContentType::mediaType()
01276 {
01277 int pos=m_imeType.find('/');
01278 if(pos==-1)
01279 return m_imeType;
01280 else
01281 return m_imeType.left(pos);
01282 }
01283
01284
01285 QCString ContentType::subType()
01286 {
01287 int pos=m_imeType.find('/');
01288 if(pos==-1)
01289 return QCString();
01290 else
01291 return m_imeType.mid(pos, m_imeType.length()-pos);
01292 }
01293
01294
01295 void ContentType::setMimeType(const QCString &s)
01296 {
01297 p_arams.resize(0);
01298 m_imeType=s;
01299
01300 if(isMultipart())
01301 c_ategory=CCcontainer;
01302 else
01303 c_ategory=CCsingle;
01304 }
01305
01306
01307 bool ContentType::isMediatype(const char *s)
01308 {
01309 return ( strncasecmp(m_imeType.data(), s, strlen(s)) );
01310 }
01311
01312
01313 bool ContentType::isSubtype(const char *s)
01314 {
01315 char *c=strchr(m_imeType.data(), '/');
01316
01317 if( (c==0) || (*(c+1)=='\0') )
01318 return false;
01319 else
01320 return ( strcasecmp(c+1, s)==0 );
01321 }
01322
01323
01324 bool ContentType::isText()
01325 {
01326 return (strncasecmp(m_imeType.data(), "text", 4)==0);
01327 }
01328
01329
01330 bool ContentType::isPlainText()
01331 {
01332 return (strcasecmp(m_imeType.data(), "text/plain")==0);
01333 }
01334
01335
01336 bool ContentType::isHTMLText()
01337 {
01338 return (strcasecmp(m_imeType.data(), "text/html")==0);
01339 }
01340
01341
01342 bool ContentType::isImage()
01343 {
01344 return (strncasecmp(m_imeType.data(), "image", 5)==0);
01345 }
01346
01347
01348 bool ContentType::isMultipart()
01349 {
01350 return (strncasecmp(m_imeType.data(), "multipart", 9)==0);
01351 }
01352
01353
01354 bool ContentType::isPartial()
01355 {
01356 return (strcasecmp(m_imeType.data(), "message/partial")==0);
01357 }
01358
01359
01360 QCString ContentType::charset()
01361 {
01362 QCString ret=getParameter("charset");
01363 if( ret.isEmpty() || forceCS() ) {
01364 ret=defaultCS();
01365 }
01366 return ret;
01367 }
01368
01369
01370 void ContentType::setCharset(const QCString &s)
01371 {
01372 setParameter("charset", s);
01373 }
01374
01375
01376 QCString ContentType::boundary()
01377 {
01378 return getParameter("boundary");
01379 }
01380
01381
01382 void ContentType::setBoundary(const QCString &s)
01383 {
01384 setParameter("boundary", s, true);
01385 }
01386
01387
01388 QString ContentType::name()
01389 {
01390 const char *dummy=0;
01391 return ( decodeRFC2047String(getParameter("name"), &dummy, defaultCS(), forceCS()) );
01392 }
01393
01394
01395 void ContentType::setName(const QString &s, const QCString &cs)
01396 {
01397 e_ncCS=cs;
01398
01399 if (isUsAscii(s)) {
01400 QCString tmp(s.latin1());
01401 addQuotes(tmp, true);
01402 setParameter("name", tmp, false);
01403 } else {
01404
01405 setParameter("name", encodeRFC2047String(s, cs), true);
01406 }
01407 }
01408
01409
01410 QCString ContentType::id()
01411 {
01412 return (getParameter("id"));
01413 }
01414
01415
01416 void ContentType::setId(const QCString &s)
01417 {
01418 setParameter("id", s, true);
01419 }
01420
01421
01422 int ContentType::partialNumber()
01423 {
01424 QCString p=getParameter("number");
01425 if(!p.isEmpty())
01426 return p.toInt();
01427 else
01428 return -1;
01429 }
01430
01431
01432 int ContentType::partialCount()
01433 {
01434 QCString p=getParameter("total");
01435 if(!p.isEmpty())
01436 return p.toInt();
01437 else
01438 return -1;
01439 }
01440
01441
01442 void ContentType::setPartialParams(int total, int number)
01443 {
01444 QCString num;
01445 num.setNum(number);
01446 setParameter("number", num);
01447 num.setNum(total);
01448 setParameter("total", num);
01449 }
01450
01451
01452 QCString ContentType::getParameter(const char *name)
01453 {
01454 QCString ret;
01455 int pos1=0, pos2=0;
01456 pos1=p_arams.find(name, 0, false);
01457 if(pos1!=-1) {
01458 if( (pos2=p_arams.find(';', pos1))==-1 )
01459 pos2=p_arams.length();
01460 pos1+=strlen(name)+1;
01461 ret=p_arams.mid(pos1, pos2-pos1);
01462 removeQuots(ret);
01463 }
01464 return ret;
01465 }
01466
01467
01468 void ContentType::setParameter(const QCString &name, const QCString &value, bool doubleQuotes)
01469 {
01470 int pos1=0, pos2=0;
01471 QCString param;
01472
01473 if(doubleQuotes)
01474 param=name+"=\""+value+"\"";
01475 else
01476 param=name+"="+value;
01477
01478 pos1=p_arams.find(name, 0, false);
01479 if(pos1==-1) {
01480 p_arams+="; "+param;
01481 }
01482 else {
01483 pos2=p_arams.find(';', pos1);
01484 if(pos2==-1)
01485 pos2=p_arams.length();
01486 p_arams.remove(pos1, pos2-pos1);
01487 p_arams.insert(pos1, param);
01488 }
01489 }
01490
01491
01492
01493
01494
01495
01496
01497 typedef struct { const char *s; int e; } encTableType;
01498
01499 static const encTableType encTable[] = { { "7Bit", CE7Bit },
01500 { "8Bit", CE8Bit },
01501 { "quoted-printable", CEquPr },
01502 { "base64", CEbase64 },
01503 { "x-uuencode", CEuuenc },
01504 { "binary", CEbinary },
01505 { 0, 0} };
01506
01507
01508 void CTEncoding::from7BitString(const QCString &s)
01509 {
01510 QCString stripped(s.simplifyWhiteSpace());
01511 c_te=CE7Bit;
01512 for(int i=0; encTable[i].s!=0; i++)
01513 if(strcasecmp(stripped.data(), encTable[i].s)==0) {
01514 c_te=(contentEncoding)encTable[i].e;
01515 break;
01516 }
01517 d_ecoded=( c_te==CE7Bit || c_te==CE8Bit );
01518
01519 e_ncCS=cachedCharset(Latin1);
01520 }
01521
01522
01523 QCString CTEncoding::as7BitString(bool incType)
01524 {
01525 QCString str;
01526 for(int i=0; encTable[i].s!=0; i++)
01527 if(c_te==encTable[i].e) {
01528 str=encTable[i].s;
01529 break;
01530 }
01531
01532 if(incType)
01533 return ( typeIntro()+str );
01534 else
01535 return str;
01536 }
01537
01538
01539 void CTEncoding::fromUnicodeString(const QString &s, const QCString&)
01540 {
01541 from7BitString( QCString(s.latin1()) );
01542 }
01543
01544
01545 QString CTEncoding::asUnicodeString()
01546 {
01547 return QString::fromLatin1(as7BitString(false));
01548 }
01549
01550
01551
01552
01553
01554
01555
01556 void CDisposition::from7BitString(const QCString &s)
01557 {
01558 if(strncasecmp(s.data(), "attachment", 10)==0)
01559 d_isp=CDattachment;
01560 else d_isp=CDinline;
01561
01562 int pos=s.find("filename=", 0, false);
01563 QCString fn;
01564 if(pos>-1) {
01565 pos+=9;
01566 fn=s.mid(pos, s.length()-pos);
01567 removeQuots(fn);
01568 f_ilename=decodeRFC2047String(fn, &e_ncCS, defaultCS(), forceCS());
01569 }
01570 }
01571
01572
01573 QCString CDisposition::as7BitString(bool incType)
01574 {
01575 QCString ret;
01576 if(d_isp==CDattachment)
01577 ret="attachment";
01578 else
01579 ret="inline";
01580
01581 if(!f_ilename.isEmpty()) {
01582 if (isUsAscii(f_ilename)) {
01583 QCString tmp(f_ilename.latin1());
01584 addQuotes(tmp, true);
01585 ret+="; filename="+tmp;
01586 } else {
01587
01588 ret+="; filename=\""+encodeRFC2047String(f_ilename, e_ncCS)+"\"";
01589 }
01590 }
01591
01592 if(incType)
01593 return ( typeIntro()+ret );
01594 else
01595 return ret;
01596 }
01597
01598
01599 void CDisposition::fromUnicodeString(const QString &s, const QCString &cs)
01600 {
01601 if(strncasecmp(s.latin1(), "attachment", 10)==0)
01602 d_isp=CDattachment;
01603 else d_isp=CDinline;
01604
01605 int pos=s.find("filename=", 0, false);
01606 if(pos>-1) {
01607 pos+=9;
01608 f_ilename=s.mid(pos, s.length()-pos);
01609 removeQuots(f_ilename);
01610 }
01611
01612 e_ncCS=cachedCharset(cs);
01613 }
01614
01615
01616 QString CDisposition::asUnicodeString()
01617 {
01618 QString ret;
01619 if(d_isp==CDattachment)
01620 ret="attachment";
01621 else
01622 ret="inline";
01623
01624 if(!f_ilename.isEmpty())
01625 ret+="; filename=\""+f_ilename+"\"";
01626
01627 return ret;
01628 }
01629
01630
01631 #endif
01632 }
01633
01634 }