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.2.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Wed Jul 25 11:16:57 2007 by doxygen 1.4.2 written by Dimitri van Heesch, © 1997-2003