|
|
|
/*
|
|
|
|
kmime_headers.cpp
|
|
|
|
|
|
|
|
KMime, the KDE internet mail/usenet news message library.
|
|
|
|
Copyright (c) 2001-2002 the KMime authors.
|
|
|
|
See file AUTHORS for details
|
|
|
|
|
|
|
|
This program is free software; you can redistribute it and/or modify
|
|
|
|
it under the terms of the GNU General Public License as published by
|
|
|
|
the Free Software Foundation; either version 2 of the License, or
|
|
|
|
(at your option) any later version.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
|
|
along with this program; if not, write to the Free Software Foundation,
|
|
|
|
Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, US
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
#include "kmime_headers.h"
|
|
|
|
|
|
|
|
#include "kmime_util.h"
|
|
|
|
#include "kmime_content.h"
|
|
|
|
#include "kmime_codecs.h"
|
|
|
|
#include "kmime_header_parsing.h"
|
|
|
|
#include "kmime_warning.h"
|
|
|
|
|
|
|
|
#include "kqcstringsplitter.h"
|
|
|
|
|
|
|
|
#include <tqtextcodec.h>
|
|
|
|
#include <tqstring.h>
|
|
|
|
#include <tqcstring.h>
|
|
|
|
#include <tqstringlist.h>
|
|
|
|
#include <tqvaluelist.h>
|
|
|
|
|
|
|
|
#include <kglobal.h>
|
|
|
|
#include <kcharsets.h>
|
|
|
|
#include <krfcdate.h>
|
|
|
|
|
|
|
|
#include <assert.h>
|
|
|
|
|
|
|
|
|
|
|
|
using namespace KMime;
|
|
|
|
using namespace KMime::Headers;
|
|
|
|
using namespace KMime::Types;
|
|
|
|
using namespace KMime::HeaderParsing;
|
|
|
|
|
|
|
|
namespace KMime {
|
|
|
|
namespace Headers {
|
|
|
|
//-----<Base>----------------------------------
|
|
|
|
|
|
|
|
TQCString Base::rfc2047Charset()
|
|
|
|
{
|
|
|
|
if( (e_ncCS==0) || forceCS() )
|
|
|
|
return defaultCS();
|
|
|
|
else
|
|
|
|
return TQCString(e_ncCS);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void Base::setRFC2047Charset(const TQCString &cs)
|
|
|
|
{
|
|
|
|
e_ncCS=cachedCharset(cs);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
bool Base::forceCS()
|
|
|
|
{
|
|
|
|
return ( p_arent!=0 ? p_arent->forceDefaultCS() : false );
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
TQCString Base::defaultCS()
|
|
|
|
{
|
|
|
|
return ( p_arent!=0 ? p_arent->defaultCharset() : Latin1 );
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//-----</Base>---------------------------------
|
|
|
|
|
|
|
|
namespace Generics {
|
|
|
|
|
|
|
|
//-----<GUnstructured>-------------------------
|
|
|
|
|
|
|
|
void GUnstructured::from7BitString( const TQCString & str )
|
|
|
|
{
|
|
|
|
d_ecoded = decodeRFC2047String( str, &e_ncCS, defaultCS(), forceCS() );
|
|
|
|
}
|
|
|
|
|
|
|
|
TQCString GUnstructured::as7BitString( bool withHeaderType )
|
|
|
|
{
|
|
|
|
TQCString result;
|
|
|
|
if ( withHeaderType )
|
|
|
|
result = typeIntro();
|
|
|
|
result += encodeRFC2047String( d_ecoded, e_ncCS ) ;
|
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
void GUnstructured::fromUnicodeString( const TQString & str,
|
|
|
|
const TQCString & suggestedCharset )
|
|
|
|
{
|
|
|
|
d_ecoded = str;
|
|
|
|
e_ncCS = cachedCharset( suggestedCharset );
|
|
|
|
}
|
|
|
|
|
|
|
|
TQString GUnstructured::asUnicodeString()
|
|
|
|
{
|
|
|
|
return d_ecoded;
|
|
|
|
}
|
|
|
|
|
|
|
|
//-----</GUnstructured>-------------------------
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//-----<GStructured>-------------------------
|
|
|
|
|
|
|
|
//-----</GStructured>-------------------------
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//-----<GAddress>-------------------------
|
|
|
|
|
|
|
|
|
|
|
|
//-----</GAddress>-------------------------
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//-----<MailboxList>-------------------------
|
|
|
|
|
|
|
|
bool MailboxList::parse( const char* & scursor, const char * const send,
|
|
|
|
bool isCRLF ) {
|
|
|
|
// examples:
|
|
|
|
// from := "From:" mailbox-list CRLF
|
|
|
|
// sender := "Sender:" mailbox CRLF
|
|
|
|
|
|
|
|
// parse an address-list:
|
|
|
|
TQValueList<Address> maybeAddressList;
|
|
|
|
if ( !parseAddressList( scursor, send, maybeAddressList, isCRLF ) )
|
|
|
|
return false;
|
|
|
|
|
|
|
|
mMailboxList.clear();
|
|
|
|
|
|
|
|
// extract the mailboxes and complain if there are groups:
|
|
|
|
TQValueList<Address>::Iterator it;
|
|
|
|
for ( it = maybeAddressList.begin(); it != maybeAddressList.end() ; ++it ) {
|
|
|
|
if ( !(*it).displayName.isEmpty() ) {
|
|
|
|
KMIME_WARN << "mailbox groups in header disallowing them! Name: \""
|
|
|
|
<< (*it).displayName << "\"" << endl;
|
|
|
|
}
|
|
|
|
mMailboxList += (*it).mailboxList;
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
//-----</MailboxList>-------------------------
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//-----<SingleMailbox>-------------------------
|
|
|
|
|
|
|
|
bool SingleMailbox::parse( const char* & scursor, const char * const send,
|
|
|
|
bool isCRLF ) {
|
|
|
|
if ( !MailboxList::parse( scursor, send, isCRLF ) ) return false;
|
|
|
|
|
|
|
|
if ( mMailboxList.count() > 1 ) {
|
|
|
|
KMIME_WARN << "multiple mailboxes in header allowing only a single one!"
|
|
|
|
<< endl;
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
//-----</SingleMailbox>-------------------------
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//-----<AddressList>-------------------------
|
|
|
|
|
|
|
|
bool AddressList::parse( const char* & scursor, const char * const send,
|
|
|
|
bool isCRLF ) {
|
|
|
|
|
|
|
|
TQValueList<Address> maybeAddressList;
|
|
|
|
if ( !parseAddressList( scursor, send, maybeAddressList, isCRLF ) )
|
|
|
|
return false;
|
|
|
|
|
|
|
|
mAddressList = maybeAddressList;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
//-----</AddressList>-------------------------
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//-----<GToken>-------------------------
|
|
|
|
|
|
|
|
bool GToken::parse( const char* & scursor, const char * const send,
|
|
|
|
bool isCRLF ) {
|
|
|
|
|
|
|
|
eatCFWS( scursor, send, isCRLF );
|
|
|
|
// must not be empty:
|
|
|
|
if ( scursor == send ) return false;
|
|
|
|
|
|
|
|
TQPair<const char*,int> maybeToken;
|
|
|
|
if ( !parseToken( scursor, send, maybeToken, false /* no 8bit chars */ ) )
|
|
|
|
return false;
|
|
|
|
mToken = TQCString( maybeToken.first, maybeToken.second );
|
|
|
|
|
|
|
|
// complain if trailing garbage is found:
|
|
|
|
eatCFWS( scursor, send, isCRLF );
|
|
|
|
if ( scursor != send ) {
|
|
|
|
KMIME_WARN << "trailing garbage after token in header allowing "
|
|
|
|
"only a single token!" << endl;
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
//-----</GToken>-------------------------
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//-----<GPhraseList>-------------------------
|
|
|
|
|
|
|
|
bool GPhraseList::parse( const char* & scursor, const char * const send,
|
|
|
|
bool isCRLF ) {
|
|
|
|
|
|
|
|
mPhraseList.clear();
|
|
|
|
|
|
|
|
while ( scursor != send ) {
|
|
|
|
eatCFWS( scursor, send, isCRLF );
|
|
|
|
// empty entry ending the list: OK.
|
|
|
|
if ( scursor == send ) return true;
|
|
|
|
// empty entry: ignore.
|
|
|
|
if ( *scursor != ',' ) { scursor++; continue; }
|
|
|
|
|
|
|
|
TQString maybePhrase;
|
|
|
|
if ( !parsePhrase( scursor, send, maybePhrase, isCRLF ) )
|
|
|
|
return false;
|
|
|
|
mPhraseList.append( maybePhrase );
|
|
|
|
|
|
|
|
eatCFWS( scursor, send, isCRLF );
|
|
|
|
// non-empty entry ending the list: OK.
|
|
|
|
if ( scursor == send ) return true;
|
|
|
|
// comma separating the phrases: eat.
|
|
|
|
if ( *scursor != ',' ) scursor++;
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
//-----</GPhraseList>-------------------------
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//-----<GDotAtom>-------------------------
|
|
|
|
|
|
|
|
bool GDotAtom::parse( const char* & scursor, const char * const send,
|
|
|
|
bool isCRLF ) {
|
|
|
|
|
|
|
|
TQString maybeDotAtom;
|
|
|
|
if ( !parseDotAtom( scursor, send, maybeDotAtom, isCRLF ) )
|
|
|
|
return false;
|
|
|
|
|
|
|
|
mDotAtom = maybeDotAtom;
|
|
|
|
|
|
|
|
eatCFWS( scursor, send, isCRLF );
|
|
|
|
if ( scursor != send ) {
|
|
|
|
KMIME_WARN << "trailing garbage after dot-atom in header allowing "
|
|
|
|
"only a single dot-atom!" << endl;
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
//-----</GDotAtom>-------------------------
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//-----<GParametrized>-------------------------
|
|
|
|
|
|
|
|
//-----</GParametrized>-------------------------
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//-----</GContentType>-------------------------
|
|
|
|
|
|
|
|
bool GContentType::parse( const char* & scursor, const char * const send,
|
|
|
|
bool isCRLF ) {
|
|
|
|
|
|
|
|
// content-type: type "/" subtype *(";" parameter)
|
|
|
|
|
|
|
|
mMimeType = 0;
|
|
|
|
mMimeSubType = 0;
|
|
|
|
mParameterHash.clear();
|
|
|
|
|
|
|
|
eatCFWS( scursor, send, isCRLF );
|
|
|
|
if ( scursor == send ) {
|
|
|
|
// empty header
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
//
|
|
|
|
// type
|
|
|
|
//
|
|
|
|
|
|
|
|
TQPair<const char*,int> maybeMimeType;
|
|
|
|
if ( !parseToken( scursor, send, maybeMimeType, false /* no 8Bit */ ) )
|
|
|
|
return false;
|
|
|
|
|
|
|
|
mMimeType = TQCString( maybeMimeType.first, maybeMimeType.second ).lower();
|
|
|
|
|
|
|
|
//
|
|
|
|
// subtype
|
|
|
|
//
|
|
|
|
|
|
|
|
eatCFWS( scursor, send, isCRLF );
|
|
|
|
if ( scursor == send || *scursor != '/' ) return false;
|
|
|
|
scursor++;
|
|
|
|
eatCFWS( scursor, send, isCRLF );
|
|
|
|
if ( scursor == send ) return false;
|
|
|
|
|
|
|
|
TQPair<const char*,int> maybeSubType;
|
|
|
|
if ( !parseToken( scursor, send, maybeSubType, false /* no 8bit */ ) )
|
|
|
|
return false;
|
|
|
|
|
|
|
|
mMimeSubType = TQCString( maybeSubType.first, maybeSubType.second ).lower();
|
|
|
|
|
|
|
|
//
|
|
|
|
// parameter list
|
|
|
|
//
|
|
|
|
|
|
|
|
eatCFWS( scursor, send, isCRLF );
|
|
|
|
if ( scursor == send ) return true; // no parameters
|
|
|
|
|
|
|
|
if ( *scursor != ';' ) return false;
|
|
|
|
scursor++;
|
|
|
|
|
|
|
|
if ( !parseParameterList( scursor, send, mParameterHash, isCRLF ) )
|
|
|
|
return false;
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
//-----</GContentType>-------------------------
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//-----<GTokenWithParameterList>-------------------------
|
|
|
|
|
|
|
|
bool GCISTokenWithParameterList::parse( const char* & scursor,
|
|
|
|
const char * const send, bool isCRLF ) {
|
|
|
|
|
|
|
|
mToken = 0;
|
|
|
|
mParameterHash.clear();
|
|
|
|
|
|
|
|
//
|
|
|
|
// token
|
|
|
|
//
|
|
|
|
|
|
|
|
eatCFWS( scursor, send, isCRLF );
|
|
|
|
if ( scursor == send ) return false;
|
|
|
|
|
|
|
|
TQPair<const char*,int> maybeToken;
|
|
|
|
if ( !parseToken( scursor, send, maybeToken, false /* no 8Bit */ ) )
|
|
|
|
return false;
|
|
|
|
|
|
|
|
mToken = TQCString( maybeToken.first, maybeToken.second ).lower();
|
|
|
|
|
|
|
|
//
|
|
|
|
// parameter list
|
|
|
|
//
|
|
|
|
|
|
|
|
eatCFWS( scursor, send, isCRLF );
|
|
|
|
if ( scursor == send ) return true; // no parameters
|
|
|
|
|
|
|
|
if ( *scursor != ';' ) return false;
|
|
|
|
scursor++;
|
|
|
|
|
|
|
|
if ( !parseParameterList( scursor, send, mParameterHash, isCRLF ) )
|
|
|
|
return false;
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
//-----</GTokenWithParameterList>-------------------------
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//-----<GIdent>-------------------------
|
|
|
|
|
|
|
|
bool GIdent::parse( const char* & scursor, const char * const send, bool isCRLF ) {
|
|
|
|
|
|
|
|
// msg-id := "<" id-left "@" id-right ">"
|
|
|
|
// id-left := dot-atom-text / no-fold-quote / local-part
|
|
|
|
// id-right := dot-atom-text / no-fold-literal / domain
|
|
|
|
//
|
|
|
|
// equivalent to:
|
|
|
|
// msg-id := angle-addr
|
|
|
|
|
|
|
|
mMsgIdList.clear();
|
|
|
|
|
|
|
|
while ( scursor != send ) {
|
|
|
|
eatCFWS( scursor, send, isCRLF );
|
|
|
|
// empty entry ending the list: OK.
|
|
|
|
if ( scursor == send ) return true;
|
|
|
|
// empty entry: ignore.
|
|
|
|
if ( *scursor == ',' ) { scursor++; continue; }
|
|
|
|
|
|
|
|
AddrSpec maybeMsgId;
|
|
|
|
if ( !parseAngleAddr( scursor, send, maybeMsgId, isCRLF ) )
|
|
|
|
return false;
|
|
|
|
mMsgIdList.append( maybeMsgId );
|
|
|
|
|
|
|
|
eatCFWS( scursor, send, isCRLF );
|
|
|
|
// header end ending the list: OK.
|
|
|
|
if ( scursor == send ) return true;
|
|
|
|
// regular item separator: eat it.
|
|
|
|
if ( *scursor == ',' ) scursor++;
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
//-----</GIdent>-------------------------
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//-----<GSingleIdent>-------------------------
|
|
|
|
|
|
|
|
bool GSingleIdent::parse( const char* & scursor, const char * const send, bool isCRLF ) {
|
|
|
|
|
|
|
|
if ( !GIdent::parse( scursor, send, isCRLF ) ) return false;
|
|
|
|
|
|
|
|
if ( mMsgIdList.count() > 1 ) {
|
|
|
|
KMIME_WARN << "more than one msg-id in header "
|
|
|
|
"allowing only a single one!" << endl;
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
//-----</GSingleIdent>-------------------------
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
} // namespace Generics
|
|
|
|
|
|
|
|
|
|
|
|
//-----<ReturnPath>-------------------------
|
|
|
|
|
|
|
|
bool ReturnPath::parse( const char* & scursor, const char * const send, bool isCRLF ) {
|
|
|
|
|
|
|
|
eatCFWS( scursor, send, isCRLF );
|
|
|
|
if ( scursor == send ) return false;
|
|
|
|
|
|
|
|
const char * oldscursor = scursor;
|
|
|
|
|
|
|
|
Mailbox maybeMailbox;
|
|
|
|
if ( !parseMailbox( scursor, send, maybeMailbox, isCRLF ) ) {
|
|
|
|
// mailbox parsing failed, but check for empty brackets:
|
|
|
|
scursor = oldscursor;
|
|
|
|
if ( *scursor != '<' ) return false;
|
|
|
|
scursor++;
|
|
|
|
eatCFWS( scursor, send, isCRLF );
|
|
|
|
if ( scursor == send || *scursor != '>' ) return false;
|
|
|
|
scursor++;
|
|
|
|
|
|
|
|
// prepare a Null mailbox:
|
|
|
|
AddrSpec emptyAddrSpec;
|
|
|
|
maybeMailbox.displayName = TQString();
|
|
|
|
maybeMailbox.addrSpec = emptyAddrSpec;
|
|
|
|
} else
|
|
|
|
// check that there was no display-name:
|
|
|
|
if ( !maybeMailbox.displayName.isEmpty() ) {
|
|
|
|
KMIME_WARN << "display-name \"" << maybeMailbox.displayName
|
|
|
|
<< "\" in Return-Path!" << endl;
|
|
|
|
}
|
|
|
|
|
|
|
|
// see if that was all:
|
|
|
|
eatCFWS( scursor, send, isCRLF );
|
|
|
|
// and warn if it wasn't:
|
|
|
|
if ( scursor != send ) {
|
|
|
|
KMIME_WARN << "trailing garbage after angle-addr in Return-Path!" << endl;
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
//-----</ReturnPath>-------------------------
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//-----<Generic>-------------------------------
|
|
|
|
|
|
|
|
void Generic::setType(const char *type)
|
|
|
|
{
|
|
|
|
if(t_ype)
|
|
|
|
delete[] t_ype;
|
|
|
|
if(type) {
|
|
|
|
t_ype=new char[strlen(type)+1];
|
|
|
|
strcpy(t_ype, type);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
t_ype=0;
|
|
|
|
}
|
|
|
|
|
|
|
|
//-----<Generic>-------------------------------
|
|
|
|
|
|
|
|
|
|
|
|
#if !defined(KMIME_NEW_STYLE_CLASSTREE)
|
|
|
|
//-----<MessageID>-----------------------------
|
|
|
|
|
|
|
|
void MessageID::from7BitString(const TQCString &s)
|
|
|
|
{
|
|
|
|
m_id=s;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
TQCString MessageID::as7BitString(bool incType)
|
|
|
|
{
|
|
|
|
if(incType)
|
|
|
|
return ( typeIntro()+m_id );
|
|
|
|
else
|
|
|
|
return m_id;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void MessageID::fromUnicodeString(const TQString &s, const TQCString&)
|
|
|
|
{
|
|
|
|
m_id=s.latin1(); //Message-Ids can only contain us-ascii chars
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
TQString MessageID::asUnicodeString()
|
|
|
|
{
|
|
|
|
return TQString::tqfromLatin1(m_id);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void MessageID::generate(const TQCString &fqdn)
|
|
|
|
{
|
|
|
|
m_id="<"+uniqueString()+"@"+fqdn+">";
|
|
|
|
}
|
|
|
|
|
|
|
|
//-----</MessageID>----------------------------
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
//-----<Control>-------------------------------
|
|
|
|
|
|
|
|
void Control::from7BitString(const TQCString &s)
|
|
|
|
{
|
|
|
|
c_trlMsg=s;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
TQCString Control::as7BitString(bool incType)
|
|
|
|
{
|
|
|
|
if(incType)
|
|
|
|
return ( typeIntro()+c_trlMsg );
|
|
|
|
else
|
|
|
|
return c_trlMsg;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void Control::fromUnicodeString(const TQString &s, const TQCString&)
|
|
|
|
{
|
|
|
|
c_trlMsg=s.latin1();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
TQString Control::asUnicodeString()
|
|
|
|
{
|
|
|
|
return TQString::tqfromLatin1(c_trlMsg);
|
|
|
|
}
|
|
|
|
|
|
|
|
//-----</Control>------------------------------
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#if !defined(KMIME_NEW_STYLE_CLASSTREE)
|
|
|
|
//-----<AddressField>--------------------------
|
|
|
|
void AddressField::from7BitString(const TQCString &s)
|
|
|
|
{
|
|
|
|
int pos1=0, pos2=0, type=0;
|
|
|
|
TQCString n;
|
|
|
|
|
|
|
|
//so what do we have here ?
|
|
|
|
if(s.tqfind( TQRegExp("*@*(*)", false, true) )!=-1) type=2; // From: foo@bar.com (John Doe)
|
|
|
|
else if(s.tqfind( TQRegExp("*<*@*>", false, true) )!=-1) type=1; // From: John Doe <foo@bar.com>
|
|
|
|
else if(s.tqfind( TQRegExp("*@*", false, true) )!=-1) type=0; // From: foo@bar.com
|
|
|
|
else { //broken From header => just decode it
|
|
|
|
n_ame=decodeRFC2047String(s, &e_ncCS, defaultCS(), forceCS());
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
switch(type) {
|
|
|
|
|
|
|
|
case 0:
|
|
|
|
e_mail=s.copy();
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 1:
|
|
|
|
pos1=0;
|
|
|
|
pos2=s.tqfind('<');
|
|
|
|
if(pos2!=-1) {
|
|
|
|
n=s.mid(pos1, pos2-pos1).stripWhiteSpace();
|
|
|
|
pos1=pos2+1;
|
|
|
|
pos2=s.tqfind('>', pos1);
|
|
|
|
if(pos2!=-1)
|
|
|
|
e_mail=s.mid(pos1, pos2-pos1).stripWhiteSpace();
|
|
|
|
}
|
|
|
|
else return;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 2:
|
|
|
|
pos1=0;
|
|
|
|
pos2=s.tqfind('(');
|
|
|
|
if(pos2!=-1) {
|
|
|
|
e_mail=s.mid(pos1, pos2-pos1).stripWhiteSpace();
|
|
|
|
pos1=pos2+1;
|
|
|
|
pos2=s.tqfind(')', pos1);
|
|
|
|
if(pos2!=-1)
|
|
|
|
n=s.mid(pos1, pos2-pos1).stripWhiteSpace();
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
default: break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(!n.isEmpty()) {
|
|
|
|
removeQuots(n);
|
|
|
|
n_ame=decodeRFC2047String(n, &e_ncCS, defaultCS(), forceCS());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
TQCString AddressField::as7BitString(bool incType)
|
|
|
|
{
|
|
|
|
TQCString ret;
|
|
|
|
|
|
|
|
if(incType && type()[0]!='\0')
|
|
|
|
ret=typeIntro();
|
|
|
|
|
|
|
|
if(n_ame.isEmpty())
|
|
|
|
ret+=e_mail;
|
|
|
|
else {
|
|
|
|
if (isUsAscii(n_ame)) {
|
|
|
|
TQCString tmp(n_ame.latin1());
|
|
|
|
addQuotes(tmp, false);
|
|
|
|
ret+=tmp;
|
|
|
|
} else {
|
|
|
|
ret+=encodeRFC2047String(n_ame, e_ncCS, true);
|
|
|
|
}
|
|
|
|
if (!e_mail.isEmpty())
|
|
|
|
ret += " <"+e_mail+">";
|
|
|
|
}
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void AddressField::fromUnicodeString(const TQString &s, const TQCString &cs)
|
|
|
|
{
|
|
|
|
int pos1=0, pos2=0, type=0;
|
|
|
|
TQCString n;
|
|
|
|
|
|
|
|
e_ncCS=cachedCharset(cs);
|
|
|
|
|
|
|
|
//so what do we have here ?
|
|
|
|
if(s.tqfind( TQRegExp("*@*(*)", false, true) )!=-1) type=2; // From: foo@bar.com (John Doe)
|
|
|
|
else if(s.tqfind( TQRegExp("*<*@*>", false, true) )!=-1) type=1; // From: John Doe <foo@bar.com>
|
|
|
|
else if(s.tqfind( TQRegExp("*@*", false, true) )!=-1) type=0; // From: foo@bar.com
|
|
|
|
else { //broken From header => just copy it
|
|
|
|
n_ame=s;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
switch(type) {
|
|
|
|
|
|
|
|
case 0:
|
|
|
|
e_mail=s.latin1();
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 1:
|
|
|
|
pos1=0;
|
|
|
|
pos2=s.tqfind('<');
|
|
|
|
if(pos2!=-1) {
|
|
|
|
n_ame=s.mid(pos1, pos2-pos1).stripWhiteSpace();
|
|
|
|
pos1=pos2+1;
|
|
|
|
pos2=s.tqfind('>', pos1);
|
|
|
|
if(pos2!=-1)
|
|
|
|
e_mail=s.mid(pos1, pos2-pos1).latin1();
|
|
|
|
}
|
|
|
|
else return;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 2:
|
|
|
|
pos1=0;
|
|
|
|
pos2=s.tqfind('(');
|
|
|
|
if(pos2!=-1) {
|
|
|
|
e_mail=s.mid(pos1, pos2-pos1).stripWhiteSpace().latin1();
|
|
|
|
pos1=pos2+1;
|
|
|
|
pos2=s.tqfind(')', pos1);
|
|
|
|
if(pos2!=-1)
|
|
|
|
n_ame=s.mid(pos1, pos2-pos1).stripWhiteSpace();
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
default: break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(!n_ame.isEmpty())
|
|
|
|
removeQuots(n_ame);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
TQString AddressField::asUnicodeString()
|
|
|
|
{
|
|
|
|
if(n_ame.isEmpty())
|
|
|
|
return TQString(e_mail);
|
|
|
|
else {
|
|
|
|
TQString s = n_ame;
|
|
|
|
if (!e_mail.isEmpty())
|
|
|
|
s += " <"+e_mail+">";
|
|
|
|
return s;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
TQCString AddressField::nameAs7Bit()
|
|
|
|
{
|
|
|
|
return encodeRFC2047String(n_ame, e_ncCS);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void AddressField::setNameFrom7Bit(const TQCString &s)
|
|
|
|
{
|
|
|
|
n_ame=decodeRFC2047String(s, &e_ncCS, defaultCS(), forceCS());
|
|
|
|
}
|
|
|
|
|
|
|
|
//-----</AddressField>-------------------------
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
//-----<MailCopiesTo>--------------------------
|
|
|
|
|
|
|
|
bool MailCopiesTo::isValid()
|
|
|
|
{
|
|
|
|
if (hasEmail())
|
|
|
|
return true;
|
|
|
|
|
|
|
|
if ((n_ame == "nobody") ||
|
|
|
|
(n_ame == "never") ||
|
|
|
|
(n_ame == "poster") ||
|
|
|
|
(n_ame == "always"))
|
|
|
|
return true;
|
|
|
|
else
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
bool MailCopiesTo::alwaysCopy()
|
|
|
|
{
|
|
|
|
return (hasEmail() || (n_ame == "poster") || (n_ame == "always"));
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
bool MailCopiesTo::neverCopy()
|
|
|
|
{
|
|
|
|
return ((n_ame == "nobody") || (n_ame == "never"));
|
|
|
|
}
|
|
|
|
|
|
|
|
//-----</MailCopiesTo>-------------------------
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//-----<Date>----------------------------------
|
|
|
|
|
|
|
|
void Date::from7BitString(const TQCString &s)
|
|
|
|
{
|
|
|
|
t_ime=KRFCDate::parseDate(s);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
TQCString Date::as7BitString(bool incType)
|
|
|
|
{
|
|
|
|
if(incType)
|
|
|
|
return ( typeIntro()+KRFCDate::rfc2822DateString(t_ime) );
|
|
|
|
else
|
|
|
|
return TQCString(KRFCDate::rfc2822DateString(t_ime));
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void Date::fromUnicodeString(const TQString &s, const TQCString&)
|
|
|
|
{
|
|
|
|
from7BitString( TQCString(s.latin1()) );
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
TQString Date::asUnicodeString()
|
|
|
|
{
|
|
|
|
return TQString::tqfromLatin1(as7BitString(false));
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
TQDateTime Date::qdt()
|
|
|
|
{
|
|
|
|
TQDateTime dt;
|
|
|
|
dt.setTime_t(t_ime);
|
|
|
|
return dt;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int Date::ageInDays()
|
|
|
|
{
|
|
|
|
TQDate today=TQDate::tqcurrentDate();
|
|
|
|
return ( qdt().date().daysTo(today) );
|
|
|
|
}
|
|
|
|
|
|
|
|
//-----</Date>---------------------------------
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#if !defined(KMIME_NEW_STYLE_CLASSTREE)
|
|
|
|
//-----<To>------------------------------------
|
|
|
|
|
|
|
|
void To::from7BitString(const TQCString &s)
|
|
|
|
{
|
|
|
|
if(a_ddrList)
|
|
|
|
a_ddrList->clear();
|
|
|
|
else {
|
|
|
|
a_ddrList=new TQPtrList<AddressField>;
|
|
|
|
a_ddrList->setAutoDelete(true);
|
|
|
|
}
|
|
|
|
|
|
|
|
KTQCStringSplitter split;
|
|
|
|
split.init(s, ",");
|
|
|
|
bool splitOk=split.first();
|
|
|
|
if(!splitOk)
|
|
|
|
a_ddrList->append( new AddressField(p_arent, s ));
|
|
|
|
else {
|
|
|
|
do {
|
|
|
|
a_ddrList->append( new AddressField(p_arent, split.string()) );
|
|
|
|
} while(split.next());
|
|
|
|
}
|
|
|
|
|
|
|
|
e_ncCS=cachedCharset(a_ddrList->first()->rfc2047Charset());
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
TQCString To::as7BitString(bool incType)
|
|
|
|
{
|
|
|
|
TQCString ret;
|
|
|
|
|
|
|
|
if(incType)
|
|
|
|
ret+=typeIntro();
|
|
|
|
|
|
|
|
if (a_ddrList) {
|
|
|
|
AddressField *it=a_ddrList->first();
|
|
|
|
if (it)
|
|
|
|
ret+=it->as7BitString(false);
|
|
|
|
for (it=a_ddrList->next() ; it != 0; it=a_ddrList->next() )
|
|
|
|
ret+=","+it->as7BitString(false);
|
|
|
|
}
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void To::fromUnicodeString(const TQString &s, const TQCString &cs)
|
|
|
|
{
|
|
|
|
if(a_ddrList)
|
|
|
|
a_ddrList->clear();
|
|
|
|
else {
|
|
|
|
a_ddrList=new TQPtrList<AddressField>;
|
|
|
|
a_ddrList->setAutoDelete(true);
|
|
|
|
}
|
|
|
|
|
|
|
|
TQStringList l=TQStringList::split(",", s);
|
|
|
|
|
|
|
|
TQStringList::Iterator it=l.begin();
|
|
|
|
for(; it!=l.end(); ++it)
|
|
|
|
a_ddrList->append(new AddressField( p_arent, (*it), cs ));
|
|
|
|
|
|
|
|
e_ncCS=cachedCharset(cs);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
TQString To::asUnicodeString()
|
|
|
|
{
|
|
|
|
if(!a_ddrList)
|
|
|
|
return TQString();
|
|
|
|
|
|
|
|
TQString ret;
|
|
|
|
AddressField *it=a_ddrList->first();
|
|
|
|
|
|
|
|
if (it)
|
|
|
|
ret+=it->asUnicodeString();
|
|
|
|
for (it=a_ddrList->next() ; it != 0; it=a_ddrList->next() )
|
|
|
|
ret+=","+it->asUnicodeString();
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void To::addAddress(const AddressField &a)
|
|
|
|
{
|
|
|
|
if(!a_ddrList) {
|
|
|
|
a_ddrList=new TQPtrList<AddressField>;
|
|
|
|
a_ddrList->setAutoDelete(true);
|
|
|
|
}
|
|
|
|
|
|
|
|
AddressField *add=new AddressField(a);
|
|
|
|
add->setParent(p_arent);
|
|
|
|
a_ddrList->append(add);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void To::emails(TQStrList *l)
|
|
|
|
{
|
|
|
|
l->clear();
|
|
|
|
|
|
|
|
for (AddressField *it=a_ddrList->first(); it != 0; it=a_ddrList->next() )
|
|
|
|
if( it->hasEmail() )
|
|
|
|
l->append( it->email() );
|
|
|
|
}
|
|
|
|
|
|
|
|
void To::names(TQStringList *l)
|
|
|
|
{
|
|
|
|
l->clear();
|
|
|
|
|
|
|
|
for (AddressField *it=a_ddrList->first(); it != 0 ; it=a_ddrList->next() )
|
|
|
|
if( it->hasName() )
|
|
|
|
l->append( it->name() );
|
|
|
|
}
|
|
|
|
|
|
|
|
void To::displayNames(TQStringList *l)
|
|
|
|
{
|
|
|
|
l->clear();
|
|
|
|
|
|
|
|
for (AddressField *it=a_ddrList->first(); it != 0 ; it=a_ddrList->next() )
|
|
|
|
l->append( it->asUnicodeString() );
|
|
|
|
}
|
|
|
|
|
|
|
|
//-----</To>-----------------------------------
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
//-----<Newsgroups>----------------------------
|
|
|
|
|
|
|
|
void Newsgroups::from7BitString(const TQCString &s)
|
|
|
|
{
|
|
|
|
g_roups=s;
|
|
|
|
e_ncCS=cachedCharset("UTF-8");
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
TQCString Newsgroups::as7BitString(bool incType)
|
|
|
|
{
|
|
|
|
if(incType)
|
|
|
|
return (typeIntro()+g_roups);
|
|
|
|
else
|
|
|
|
return g_roups;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void Newsgroups::fromUnicodeString(const TQString &s, const TQCString&)
|
|
|
|
{
|
|
|
|
g_roups=s.utf8();
|
|
|
|
e_ncCS=cachedCharset("UTF-8");
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
TQString Newsgroups::asUnicodeString()
|
|
|
|
{
|
|
|
|
return TQString::fromUtf8(g_roups);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
TQCString Newsgroups::firstGroup()
|
|
|
|
{
|
|
|
|
int pos=0;
|
|
|
|
if(!g_roups.isEmpty()) {
|
|
|
|
pos=g_roups.tqfind(',');
|
|
|
|
if(pos==-1)
|
|
|
|
return g_roups;
|
|
|
|
else
|
|
|
|
return g_roups.left(pos);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
return TQCString();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
TQStringList Newsgroups::getGroups()
|
|
|
|
{
|
|
|
|
TQStringList temp = TQStringList::split(',', g_roups);
|
|
|
|
TQStringList ret;
|
|
|
|
TQString s;
|
|
|
|
|
|
|
|
for (TQStringList::Iterator it = temp.begin(); it != temp.end(); ++it ) {
|
|
|
|
s = (*it).simplifyWhiteSpace();
|
|
|
|
ret.append(s);
|
|
|
|
}
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
//-----</Newsgroups>---------------------------
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//-----<Lines>---------------------------------
|
|
|
|
|
|
|
|
void Lines::from7BitString(const TQCString &s)
|
|
|
|
{
|
|
|
|
l_ines=s.toInt();
|
|
|
|
e_ncCS=cachedCharset(Latin1);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
TQCString Lines::as7BitString(bool incType)
|
|
|
|
{
|
|
|
|
TQCString num;
|
|
|
|
num.setNum(l_ines);
|
|
|
|
|
|
|
|
if(incType)
|
|
|
|
return ( typeIntro()+num );
|
|
|
|
else
|
|
|
|
return num;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void Lines::fromUnicodeString(const TQString &s, const TQCString&)
|
|
|
|
{
|
|
|
|
l_ines=s.toInt();
|
|
|
|
e_ncCS=cachedCharset(Latin1);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
TQString Lines::asUnicodeString()
|
|
|
|
{
|
|
|
|
TQString num;
|
|
|
|
num.setNum(l_ines);
|
|
|
|
|
|
|
|
return num;
|
|
|
|
}
|
|
|
|
|
|
|
|
//-----</Lines>--------------------------------
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#if !defined(KMIME_NEW_STYLE_CLASSTREE)
|
|
|
|
//-----<References>----------------------------
|
|
|
|
|
|
|
|
void References::from7BitString(const TQCString &s)
|
|
|
|
{
|
|
|
|
r_ef=s;
|
|
|
|
e_ncCS=cachedCharset(Latin1);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
TQCString References::as7BitString(bool incType)
|
|
|
|
{
|
|
|
|
if(incType)
|
|
|
|
return ( typeIntro()+r_ef );
|
|
|
|
else
|
|
|
|
return r_ef;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void References::fromUnicodeString(const TQString &s, const TQCString&)
|
|
|
|
{
|
|
|
|
r_ef=s.latin1();
|
|
|
|
e_ncCS=cachedCharset(Latin1);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
TQString References::asUnicodeString()
|
|
|
|
{
|
|
|
|
return TQString::tqfromLatin1(r_ef);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int References::count()
|
|
|
|
{
|
|
|
|
int cnt1=0, cnt2=0;
|
|
|
|
unsigned int r_efLen=r_ef.length();
|
|
|
|
char *dataPtr=r_ef.data();
|
|
|
|
for(unsigned int i=0; i<r_efLen; i++) {
|
|
|
|
if(dataPtr[i]=='<') cnt1++;
|
|
|
|
else if(dataPtr[i]=='>') cnt2++;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(cnt1<cnt2) return cnt1;
|
|
|
|
else return cnt2;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
TQCString References::first()
|
|
|
|
{
|
|
|
|
p_os=-1;
|
|
|
|
return next();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
TQCString References::next()
|
|
|
|
{
|
|
|
|
int pos1=0, pos2=0;
|
|
|
|
TQCString ret;
|
|
|
|
|
|
|
|
if(p_os!=0) {
|
|
|
|
pos2=r_ef.findRev('>', p_os);
|
|
|
|
p_os=0;
|
|
|
|
if(pos2!=-1) {
|
|
|
|
pos1=r_ef.findRev('<', pos2);
|
|
|
|
if(pos1!=-1) {
|
|
|
|
ret=r_ef.mid(pos1, pos2-pos1+1);
|
|
|
|
p_os=pos1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
TQCString References::at(unsigned int i)
|
|
|
|
{
|
|
|
|
TQCString ret;
|
|
|
|
int pos1=0, pos2=0;
|
|
|
|
unsigned int cnt=0;
|
|
|
|
|
|
|
|
while(pos1!=-1 && cnt < i+1) {
|
|
|
|
pos2=pos1-1;
|
|
|
|
pos1=r_ef.findRev('<', pos2);
|
|
|
|
cnt++;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(pos1!=-1) {
|
|
|
|
pos2=r_ef.tqfind('>', pos1);
|
|
|
|
if(pos2!=-1)
|
|
|
|
ret=r_ef.mid(pos1, pos2-pos1+1);
|
|
|
|
}
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void References::append(const TQCString &s)
|
|
|
|
{
|
|
|
|
TQString temp=r_ef.data();
|
|
|
|
temp += " ";
|
|
|
|
temp += s.data();
|
|
|
|
TQStringList lst=TQStringList::split(' ',temp);
|
|
|
|
TQRegExp exp("^<.+@.+>$");
|
|
|
|
|
|
|
|
// remove bogus references
|
|
|
|
TQStringList::Iterator it = lst.begin();
|
|
|
|
while (it != lst.end()) {
|
|
|
|
if (-1==(*it).tqfind(exp))
|
|
|
|
it = lst.remove(it);
|
|
|
|
else
|
|
|
|
it++;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (lst.isEmpty()) {
|
|
|
|
r_ef = s.copy(); // shouldn't happen...
|
|
|
|
return;
|
|
|
|
} else
|
|
|
|
r_ef = "";
|
|
|
|
|
|
|
|
temp = lst.first(); // include the first id
|
|
|
|
r_ef = temp.latin1();
|
|
|
|
lst.remove(temp); // avoids duplicates
|
|
|
|
int insPos = r_ef.length();
|
|
|
|
|
|
|
|
for (int i=1;i<=3;i++) { // include the last three ids
|
|
|
|
if (!lst.isEmpty()) {
|
|
|
|
temp = lst.last();
|
|
|
|
r_ef.insert(insPos,(TQString(" %1").arg(temp)).latin1());
|
|
|
|
lst.remove(temp);
|
|
|
|
} else
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
while (!lst.isEmpty()) { // now insert the rest, up to 1000 characters
|
|
|
|
temp = lst.last();
|
|
|
|
if ((15+r_ef.length()+temp.length())<1000) {
|
|
|
|
r_ef.insert(insPos,(TQString(" %1").arg(temp)).latin1());
|
|
|
|
lst.remove(temp);
|
|
|
|
} else
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//-----</References>---------------------------
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
//-----<UserAgent>-----------------------------
|
|
|
|
|
|
|
|
void UserAgent::from7BitString(const TQCString &s)
|
|
|
|
{
|
|
|
|
u_agent=s;
|
|
|
|
e_ncCS=cachedCharset(Latin1);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
TQCString UserAgent::as7BitString(bool incType)
|
|
|
|
{
|
|
|
|
if(incType)
|
|
|
|
return ( typeIntro()+u_agent );
|
|
|
|
else
|
|
|
|
return u_agent;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void UserAgent::fromUnicodeString(const TQString &s, const TQCString&)
|
|
|
|
{
|
|
|
|
u_agent=s.latin1();
|
|
|
|
e_ncCS=cachedCharset(Latin1);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
TQString UserAgent::asUnicodeString()
|
|
|
|
{
|
|
|
|
return TQString::tqfromLatin1(u_agent);
|
|
|
|
}
|
|
|
|
|
|
|
|
//-----</UserAgent>----------------------------
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#if !defined(KMIME_NEW_STYLE_CLASSTREE)
|
|
|
|
//-----<Content-Type>--------------------------
|
|
|
|
|
|
|
|
void ContentType::from7BitString(const TQCString &s)
|
|
|
|
{
|
|
|
|
int pos=s.tqfind(';');
|
|
|
|
|
|
|
|
if(pos==-1)
|
|
|
|
m_imeType=s.simplifyWhiteSpace();
|
|
|
|
else {
|
|
|
|
m_imeType=s.left(pos).simplifyWhiteSpace();
|
|
|
|
p_arams=s.mid(pos, s.length()-pos).simplifyWhiteSpace();
|
|
|
|
}
|
|
|
|
|
|
|
|
if(isMultipart())
|
|
|
|
c_ategory=CCcontainer;
|
|
|
|
else
|
|
|
|
c_ategory=CCsingle;
|
|
|
|
|
|
|
|
e_ncCS=cachedCharset(Latin1);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
TQCString ContentType::as7BitString(bool incType)
|
|
|
|
{
|
|
|
|
if(incType)
|
|
|
|
return (typeIntro()+m_imeType+p_arams);
|
|
|
|
else
|
|
|
|
return (m_imeType+p_arams);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void ContentType::fromUnicodeString(const TQString &s, const TQCString&)
|
|
|
|
{
|
|
|
|
from7BitString( TQCString(s.latin1()) );
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
TQString ContentType::asUnicodeString()
|
|
|
|
{
|
|
|
|
return TQString::tqfromLatin1(as7BitString(false));
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
TQCString ContentType::mediaType()
|
|
|
|
{
|
|
|
|
int pos=m_imeType.tqfind('/');
|
|
|
|
if(pos==-1)
|
|
|
|
return m_imeType;
|
|
|
|
else
|
|
|
|
return m_imeType.left(pos);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
TQCString ContentType::subType()
|
|
|
|
{
|
|
|
|
int pos=m_imeType.tqfind('/');
|
|
|
|
if(pos==-1)
|
|
|
|
return TQCString();
|
|
|
|
else
|
|
|
|
return m_imeType.mid(pos, m_imeType.length()-pos);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void ContentType::setMimeType(const TQCString &s)
|
|
|
|
{
|
|
|
|
p_arams.resize(0);
|
|
|
|
m_imeType=s;
|
|
|
|
|
|
|
|
if(isMultipart())
|
|
|
|
c_ategory=CCcontainer;
|
|
|
|
else
|
|
|
|
c_ategory=CCsingle;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
bool ContentType::isMediatype(const char *s)
|
|
|
|
{
|
|
|
|
return ( strncasecmp(m_imeType.data(), s, strlen(s)) );
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
bool ContentType::isSubtype(const char *s)
|
|
|
|
{
|
|
|
|
char *c=strchr(m_imeType.data(), '/');
|
|
|
|
|
|
|
|
if( (c==0) || (*(c+1)=='\0') )
|
|
|
|
return false;
|
|
|
|
else
|
|
|
|
return ( strcasecmp(c+1, s)==0 );
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
bool ContentType::isText()
|
|
|
|
{
|
|
|
|
return (strncasecmp(m_imeType.data(), "text", 4)==0);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
bool ContentType::isPlainText()
|
|
|
|
{
|
|
|
|
return (strcasecmp(m_imeType.data(), "text/plain")==0);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
bool ContentType::isHTMLText()
|
|
|
|
{
|
|
|
|
return (strcasecmp(m_imeType.data(), "text/html")==0);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
bool ContentType::isImage()
|
|
|
|
{
|
|
|
|
return (strncasecmp(m_imeType.data(), "image", 5)==0);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
bool ContentType::isMultipart()
|
|
|
|
{
|
|
|
|
return (strncasecmp(m_imeType.data(), "multipart", 9)==0);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
bool ContentType::isPartial()
|
|
|
|
{
|
|
|
|
return (strcasecmp(m_imeType.data(), "message/partial")==0);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
TQCString ContentType::charset()
|
|
|
|
{
|
|
|
|
TQCString ret=getParameter("charset");
|
|
|
|
if( ret.isEmpty() || forceCS() ) { //we return the default-charset if necessary
|
|
|
|
ret=defaultCS();
|
|
|
|
}
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void ContentType::setCharset(const TQCString &s)
|
|
|
|
{
|
|
|
|
setParameter("charset", s);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
TQCString ContentType::boundary()
|
|
|
|
{
|
|
|
|
return getParameter("boundary");
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void ContentType::setBoundary(const TQCString &s)
|
|
|
|
{
|
|
|
|
setParameter("boundary", s, true);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
TQString ContentType::name()
|
|
|
|
{
|
|
|
|
const char *dummy=0;
|
|
|
|
return ( decodeRFC2047String(getParameter("name"), &dummy, defaultCS(), forceCS()) );
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void ContentType::setName(const TQString &s, const TQCString &cs)
|
|
|
|
{
|
|
|
|
e_ncCS=cs;
|
|
|
|
|
|
|
|
if (isUsAscii(s)) {
|
|
|
|
TQCString tmp(s.latin1());
|
|
|
|
addQuotes(tmp, true);
|
|
|
|
setParameter("name", tmp, false);
|
|
|
|
} else {
|
|
|
|
// FIXME: encoded words can't be enclosed in quotes!!
|
|
|
|
setParameter("name", encodeRFC2047String(s, cs), true);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
TQCString ContentType::id()
|
|
|
|
{
|
|
|
|
return (getParameter("id"));
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void ContentType::setId(const TQCString &s)
|
|
|
|
{
|
|
|
|
setParameter("id", s, true);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int ContentType::partialNumber()
|
|
|
|
{
|
|
|
|
TQCString p=getParameter("number");
|
|
|
|
if(!p.isEmpty())
|
|
|
|
return p.toInt();
|
|
|
|
else
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int ContentType::partialCount()
|
|
|
|
{
|
|
|
|
TQCString p=getParameter("total");
|
|
|
|
if(!p.isEmpty())
|
|
|
|
return p.toInt();
|
|
|
|
else
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void ContentType::setPartialParams(int total, int number)
|
|
|
|
{
|
|
|
|
TQCString num;
|
|
|
|
num.setNum(number);
|
|
|
|
setParameter("number", num);
|
|
|
|
num.setNum(total);
|
|
|
|
setParameter("total", num);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
TQCString ContentType::getParameter(const char *name)
|
|
|
|
{
|
|
|
|
TQCString ret;
|
|
|
|
int pos1=0, pos2=0;
|
|
|
|
pos1=p_arams.tqfind(name, 0, false);
|
|
|
|
if(pos1!=-1) {
|
|
|
|
if( (pos2=p_arams.tqfind(';', pos1))==-1 )
|
|
|
|
pos2=p_arams.length();
|
|
|
|
pos1+=strlen(name)+1;
|
|
|
|
ret=p_arams.mid(pos1, pos2-pos1);
|
|
|
|
removeQuots(ret);
|
|
|
|
}
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void ContentType::setParameter(const TQCString &name, const TQCString &value, bool doubleQuotes)
|
|
|
|
{
|
|
|
|
int pos1=0, pos2=0;
|
|
|
|
TQCString param;
|
|
|
|
|
|
|
|
if(doubleQuotes)
|
|
|
|
param=name+"=\""+value+"\"";
|
|
|
|
else
|
|
|
|
param=name+"="+value;
|
|
|
|
|
|
|
|
pos1=p_arams.tqfind(name, 0, false);
|
|
|
|
if(pos1==-1) {
|
|
|
|
p_arams+="; "+param;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
pos2=p_arams.tqfind(';', pos1);
|
|
|
|
if(pos2==-1)
|
|
|
|
pos2=p_arams.length();
|
|
|
|
p_arams.remove(pos1, pos2-pos1);
|
|
|
|
p_arams.insert(pos1, param);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//-----</Content-Type>-------------------------
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//-----<CTEncoding>----------------------------
|
|
|
|
|
|
|
|
typedef struct { const char *s; int e; } encTableType;
|
|
|
|
|
|
|
|
static const encTableType encTable[] = { { "7Bit", CE7Bit },
|
|
|
|
{ "8Bit", CE8Bit },
|
|
|
|
{ "quoted-printable", CEquPr },
|
|
|
|
{ "base64", CEbase64 },
|
|
|
|
{ "x-uuencode", CEuuenc },
|
|
|
|
{ "binary", CEbinary },
|
|
|
|
{ 0, 0} };
|
|
|
|
|
|
|
|
|
|
|
|
void CTEncoding::from7BitString(const TQCString &s)
|
|
|
|
{
|
|
|
|
TQCString stripped(s.simplifyWhiteSpace());
|
|
|
|
c_te=CE7Bit;
|
|
|
|
for(int i=0; encTable[i].s!=0; i++)
|
|
|
|
if(strcasecmp(stripped.data(), encTable[i].s)==0) {
|
|
|
|
c_te=(contentEncoding)encTable[i].e;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
d_ecoded=( c_te==CE7Bit || c_te==CE8Bit );
|
|
|
|
|
|
|
|
e_ncCS=cachedCharset(Latin1);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
TQCString CTEncoding::as7BitString(bool incType)
|
|
|
|
{
|
|
|
|
TQCString str;
|
|
|
|
for(int i=0; encTable[i].s!=0; i++)
|
|
|
|
if(c_te==encTable[i].e) {
|
|
|
|
str=encTable[i].s;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(incType)
|
|
|
|
return ( typeIntro()+str );
|
|
|
|
else
|
|
|
|
return str;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void CTEncoding::fromUnicodeString(const TQString &s, const TQCString&)
|
|
|
|
{
|
|
|
|
from7BitString( TQCString(s.latin1()) );
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
TQString CTEncoding::asUnicodeString()
|
|
|
|
{
|
|
|
|
return TQString::tqfromLatin1(as7BitString(false));
|
|
|
|
}
|
|
|
|
|
|
|
|
//-----</CTEncoding>---------------------------
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//-----<CDisposition>--------------------------
|
|
|
|
|
|
|
|
void CDisposition::from7BitString(const TQCString &s)
|
|
|
|
{
|
|
|
|
if(strncasecmp(s.data(), "attachment", 10)==0)
|
|
|
|
d_isp=CDattachment;
|
|
|
|
else d_isp=CDinline;
|
|
|
|
|
|
|
|
int pos=s.tqfind("filename=", 0, false);
|
|
|
|
TQCString fn;
|
|
|
|
if(pos>-1) {
|
|
|
|
pos+=9;
|
|
|
|
fn=s.mid(pos, s.length()-pos);
|
|
|
|
removeQuots(fn);
|
|
|
|
f_ilename=decodeRFC2047String(fn, &e_ncCS, defaultCS(), forceCS());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
TQCString CDisposition::as7BitString(bool incType)
|
|
|
|
{
|
|
|
|
TQCString ret;
|
|
|
|
if(d_isp==CDattachment)
|
|
|
|
ret="attachment";
|
|
|
|
else
|
|
|
|
ret="inline";
|
|
|
|
|
|
|
|
if(!f_ilename.isEmpty()) {
|
|
|
|
if (isUsAscii(f_ilename)) {
|
|
|
|
TQCString tmp(f_ilename.latin1());
|
|
|
|
addQuotes(tmp, true);
|
|
|
|
ret+="; filename="+tmp;
|
|
|
|
} else {
|
|
|
|
// FIXME: encoded words can't be enclosed in quotes!!
|
|
|
|
ret+="; filename=\""+encodeRFC2047String(f_ilename, e_ncCS)+"\"";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if(incType)
|
|
|
|
return ( typeIntro()+ret );
|
|
|
|
else
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void CDisposition::fromUnicodeString(const TQString &s, const TQCString &cs)
|
|
|
|
{
|
|
|
|
if(strncasecmp(s.latin1(), "attachment", 10)==0)
|
|
|
|
d_isp=CDattachment;
|
|
|
|
else d_isp=CDinline;
|
|
|
|
|
|
|
|
int pos=s.tqfind("filename=", 0, false);
|
|
|
|
if(pos>-1) {
|
|
|
|
pos+=9;
|
|
|
|
f_ilename=s.mid(pos, s.length()-pos);
|
|
|
|
removeQuots(f_ilename);
|
|
|
|
}
|
|
|
|
|
|
|
|
e_ncCS=cachedCharset(cs);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
TQString CDisposition::asUnicodeString()
|
|
|
|
{
|
|
|
|
TQString ret;
|
|
|
|
if(d_isp==CDattachment)
|
|
|
|
ret="attachment";
|
|
|
|
else
|
|
|
|
ret="inline";
|
|
|
|
|
|
|
|
if(!f_ilename.isEmpty())
|
|
|
|
ret+="; filename=\""+f_ilename+"\"";
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
//-----</CDisposition>-------------------------
|
|
|
|
#endif
|
|
|
|
} // namespace Headers
|
|
|
|
|
|
|
|
} // namespace KMime
|