libkdenetwork Library API Documentation

kmime_headers.cpp

00001 /* 00002 kmime_headers.cpp 00003 00004 KMime, the KDE internet mail/usenet news message library. 00005 Copyright (c) 2001-2002 the KMime authors. 00006 See file AUTHORS for details 00007 00008 This program is free software; you can redistribute it and/or modify 00009 it under the terms of the GNU General Public License as published by 00010 the Free Software Foundation; either version 2 of the License, or 00011 (at your option) any later version. 00012 You should have received a copy of the GNU General Public License 00013 along with this program; if not, write to the Free Software Foundation, 00014 Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, US 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 //-----<Base>---------------------------------- 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 //-----</Base>--------------------------------- 00078 00079 namespace Generics { 00080 00081 //-----<GUnstructured>------------------------- 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 //-----</GUnstructured>------------------------- 00111 00112 00113 00114 //-----<GStructured>------------------------- 00115 00116 //-----</GStructured>------------------------- 00117 00118 00119 00120 00121 //-----<GAddress>------------------------- 00122 00123 00124 //-----</GAddress>------------------------- 00125 00126 00127 00128 //-----<MailboxList>------------------------- 00129 00130 bool MailboxList::parse( const char* & scursor, const char * const send, 00131 bool isCRLF ) { 00132 // examples: 00133 // from := "From:" mailbox-list CRLF 00134 // sender := "Sender:" mailbox CRLF 00135 00136 // parse an address-list: 00137 QValueList<Address> maybeAddressList; 00138 if ( !parseAddressList( scursor, send, maybeAddressList, isCRLF ) ) 00139 return false; 00140 00141 mMailboxList.clear(); 00142 00143 // extract the mailboxes and complain if there are groups: 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 //-----</MailboxList>------------------------- 00156 00157 00158 00159 //-----<SingleMailbox>------------------------- 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 //-----</SingleMailbox>------------------------- 00173 00174 00175 00176 //-----<AddressList>------------------------- 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 //-----</AddressList>------------------------- 00190 00191 00192 00193 //-----<GToken>------------------------- 00194 00195 bool GToken::parse( const char* & scursor, const char * const send, 00196 bool isCRLF ) { 00197 00198 eatCFWS( scursor, send, isCRLF ); 00199 // must not be empty: 00200 if ( scursor == send ) return false; 00201 00202 QPair<const char*,int> maybeToken; 00203 if ( !parseToken( scursor, send, maybeToken, false /* no 8bit chars */ ) ) 00204 return false; 00205 mToken = QCString( maybeToken.first, maybeToken.second ); 00206 00207 // complain if trailing garbage is found: 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 //-----</GToken>------------------------- 00217 00218 00219 00220 //-----<GPhraseList>------------------------- 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 // empty entry ending the list: OK. 00230 if ( scursor == send ) return true; 00231 // empty entry: ignore. 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 // non-empty entry ending the list: OK. 00241 if ( scursor == send ) return true; 00242 // comma separating the phrases: eat. 00243 if ( *scursor != ',' ) scursor++; 00244 } 00245 return true; 00246 } 00247 00248 //-----</GPhraseList>------------------------- 00249 00250 00251 00252 //-----<GDotAtom>------------------------- 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 //-----</GDotAtom>------------------------- 00272 00273 00274 00275 //-----<GParametrized>------------------------- 00276 00277 //-----</GParametrized>------------------------- 00278 00279 00280 00281 00282 //-----</GContentType>------------------------- 00283 00284 bool GContentType::parse( const char* & scursor, const char * const send, 00285 bool isCRLF ) { 00286 00287 // content-type: type "/" subtype *(";" parameter) 00288 00289 mMimeType = 0; 00290 mMimeSubType = 0; 00291 mParameterHash.clear(); 00292 00293 eatCFWS( scursor, send, isCRLF ); 00294 if ( scursor == send ) { 00295 // empty header 00296 return false; 00297 } 00298 00299 // 00300 // type 00301 // 00302 00303 QPair<const char*,int> maybeMimeType; 00304 if ( !parseToken( scursor, send, maybeMimeType, false /* no 8Bit */ ) ) 00305 return false; 00306 00307 mMimeType = QCString( maybeMimeType.first, maybeMimeType.second ).lower(); 00308 00309 // 00310 // subtype 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 /* no 8bit */ ) ) 00321 return false; 00322 00323 mMimeSubType = QCString( maybeSubType.first, maybeSubType.second ).lower(); 00324 00325 // 00326 // parameter list 00327 // 00328 00329 eatCFWS( scursor, send, isCRLF ); 00330 if ( scursor == send ) return true; // no parameters 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 //-----</GContentType>------------------------- 00342 00343 00344 00345 //-----<GTokenWithParameterList>------------------------- 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 // token 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 /* no 8Bit */ ) ) 00362 return false; 00363 00364 mToken = QCString( maybeToken.first, maybeToken.second ).lower(); 00365 00366 // 00367 // parameter list 00368 // 00369 00370 eatCFWS( scursor, send, isCRLF ); 00371 if ( scursor == send ) return true; // no parameters 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 //-----</GTokenWithParameterList>------------------------- 00383 00384 00385 00386 //-----<GIdent>------------------------- 00387 00388 bool GIdent::parse( const char* & scursor, const char * const send, bool isCRLF ) { 00389 00390 // msg-id := "<" id-left "@" id-right ">" 00391 // id-left := dot-atom-text / no-fold-quote / local-part 00392 // id-right := dot-atom-text / no-fold-literal / domain 00393 // 00394 // equivalent to: 00395 // msg-id := angle-addr 00396 00397 mMsgIdList.clear(); 00398 00399 while ( scursor != send ) { 00400 eatCFWS( scursor, send, isCRLF ); 00401 // empty entry ending the list: OK. 00402 if ( scursor == send ) return true; 00403 // empty entry: ignore. 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 // header end ending the list: OK. 00413 if ( scursor == send ) return true; 00414 // regular item separator: eat it. 00415 if ( *scursor == ',' ) scursor++; 00416 } 00417 return true; 00418 } 00419 00420 //-----</GIdent>------------------------- 00421 00422 00423 00424 //-----<GSingleIdent>------------------------- 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 //-----</GSingleIdent>------------------------- 00438 00439 00440 00441 00442 } // namespace Generics 00443 00444 00445 //-----<ReturnPath>------------------------- 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 // mailbox parsing failed, but check for empty brackets: 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 // prepare a Null mailbox: 00465 AddrSpec emptyAddrSpec; 00466 maybeMailbox.displayName = QString::null; 00467 maybeMailbox.addrSpec = emptyAddrSpec; 00468 } else 00469 // check that there was no display-name: 00470 if ( !maybeMailbox.displayName.isEmpty() ) { 00471 KMIME_WARN << "display-name \"" << maybeMailbox.displayName 00472 << "\" in Return-Path!" << endl; 00473 } 00474 00475 // see if that was all: 00476 eatCFWS( scursor, send, isCRLF ); 00477 // and warn if it wasn't: 00478 if ( scursor != send ) { 00479 KMIME_WARN << "trailing garbage after angle-addr in Return-Path!" << endl; 00480 } 00481 return true; 00482 } 00483 00484 //-----</ReturnPath>------------------------- 00485 00486 00487 00488 00489 //-----<Generic>------------------------------- 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 //-----<Generic>------------------------------- 00504 00505 00506 #if !defined(KMIME_NEW_STYLE_CLASSTREE) 00507 //-----<MessageID>----------------------------- 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(); //Message-Ids can only contain us-ascii chars 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 //-----</MessageID>---------------------------- 00542 #endif 00543 00544 00545 //-----<Control>------------------------------- 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 //-----</Control>------------------------------ 00574 00575 00576 00577 #if !defined(KMIME_NEW_STYLE_CLASSTREE) 00578 //-----<AddressField>-------------------------- 00579 void AddressField::from7BitString(const QCString &s) 00580 { 00581 int pos1=0, pos2=0, type=0; 00582 QCString n; 00583 00584 //so what do we have here ? 00585 if(s.find( QRegExp("*@*(*)", false, true) )!=-1) type=2; // From: foo@bar.com (John Doe) 00586 else if(s.find( QRegExp("*<*@*>", false, true) )!=-1) type=1; // From: John Doe <foo@bar.com> 00587 else if(s.find( QRegExp("*@*", false, true) )!=-1) type=0; // From: foo@bar.com 00588 else { //broken From header => just decode it 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 //so what do we have here ? 00667 if(s.find( QRegExp("*@*(*)", false, true) )!=-1) type=2; // From: foo@bar.com (John Doe) 00668 else if(s.find( QRegExp("*<*@*>", false, true) )!=-1) type=1; // From: John Doe <foo@bar.com> 00669 else if(s.find( QRegExp("*@*", false, true) )!=-1) type=0; // From: foo@bar.com 00670 else { //broken From header => just copy it 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 //-----</AddressField>------------------------- 00739 #endif 00740 00741 00742 //-----<MailCopiesTo>-------------------------- 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 //-----</MailCopiesTo>------------------------- 00771 00772 00773 00774 00775 //-----<Date>---------------------------------- 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 //-----</Date>--------------------------------- 00819 00820 00821 00822 #if !defined(KMIME_NEW_STYLE_CLASSTREE) 00823 //-----<To>------------------------------------ 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 //-----</To>----------------------------------- 00926 #endif 00927 00928 00929 //-----<Newsgroups>---------------------------- 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 //-----</Newsgroups>--------------------------- 00990 00991 00992 00993 //-----<Lines>--------------------------------- 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 //-----</Lines>-------------------------------- 01030 01031 01032 01033 #if !defined(KMIME_NEW_STYLE_CLASSTREE) 01034 //-----<References>---------------------------- 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 // remove bogus references 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(); // shouldn't happen... 01148 return; 01149 } else 01150 r_ef = ""; 01151 01152 temp = lst.first(); // include the first id 01153 r_ef = temp.latin1(); 01154 lst.remove(temp); // avoids duplicates 01155 int insPos = r_ef.length(); 01156 01157 for (int i=1;i<=3;i++) { // include the last three ids 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()) { // now insert the rest, up to 1000 characters 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 //-----</References>--------------------------- 01177 #endif 01178 01179 01180 //-----<UserAgent>----------------------------- 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 //-----</UserAgent>---------------------------- 01211 01212 01213 01214 #if !defined(KMIME_NEW_STYLE_CLASSTREE) 01215 //-----<Content-Type>-------------------------- 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() ) { //we return the default-charset if necessary 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 // FIXME: encoded words can't be enclosed in quotes!! 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 //-----</Content-Type>------------------------- 01475 01476 01477 01478 //-----<CTEncoding>---------------------------- 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 //-----</CTEncoding>--------------------------- 01534 01535 01536 01537 //-----<CDisposition>-------------------------- 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 // FIXME: encoded words can't be enclosed in quotes!! 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 //-----</CDisposition>------------------------- 01614 #endif 01615 } // namespace Headers 01616 01617 } // namespace KMime
KDE Logo
This file is part of the documentation for libkdenetwork Library Version 3.3.0.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Thu Oct 21 19:46:16 2004 by doxygen 1.3.7 written by Dimitri van Heesch, © 1997-2003