You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
190 lines
5.7 KiB
190 lines
5.7 KiB
4 years ago
|
/*
|
||
4 years ago
|
request.cpp
|
||
15 years ago
|
|
||
12 years ago
|
This file is part of tdeio_smtp, the KDE SMTP tdeioslave.
|
||
15 years ago
|
Copyright (c) 2003 Marc Mutz <mutz@kde.org>
|
||
|
|
||
|
This program is free software; you can redistribute it and/or modify it
|
||
|
under the terms of the GNU General Public License, version 2, as
|
||
|
published by the Free Software Foundation.
|
||
|
|
||
|
This program is distributed in the hope that it will be useful, but
|
||
|
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||
|
General Public License for more details.
|
||
|
|
||
|
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 USA
|
||
|
|
||
|
In addition, as a special exception, the copyright holders give
|
||
|
permission to link the code of this program with any edition of
|
||
|
the Qt library by Trolltech AS, Norway (or with modified versions
|
||
|
of Qt that use the same license as Qt), and distribute linked
|
||
|
combinations including the two. You must obey the GNU General
|
||
|
Public License in all respects for all of the code used other than
|
||
|
Qt. If you modify this file, you may extend this exception to
|
||
|
your version of the file, but you are not obligated to do so. If
|
||
|
you do not wish to do so, delete this exception statement from
|
||
|
your version.
|
||
|
*/
|
||
|
|
||
|
#include <config.h>
|
||
|
|
||
|
#include "request.h"
|
||
|
|
||
|
#include <kurl.h>
|
||
|
#include <kidna.h>
|
||
|
#include <kmdcodec.h>
|
||
|
#include <kdebug.h>
|
||
|
|
||
|
#include <assert.h>
|
||
|
|
||
|
namespace KioSMTP {
|
||
|
|
||
|
Request Request::fromURL( const KURL & url ) {
|
||
|
Request request;
|
||
|
|
||
15 years ago
|
const TQStringList query = TQStringList::split( '&', url.query().mid(1) );
|
||
15 years ago
|
#ifndef NDEBUG
|
||
|
kdDebug(7112) << "Parsing request from query:\n" + query.join("\n" ) << endl;
|
||
|
#endif
|
||
15 years ago
|
for ( TQStringList::const_iterator it = query.begin() ; it != query.end() ; ++it ) {
|
||
13 years ago
|
int equalsPos = (*it).find( '=' );
|
||
15 years ago
|
if ( equalsPos <= 0 )
|
||
|
continue;
|
||
|
|
||
15 years ago
|
const TQString key = (*it).left( equalsPos ).lower();
|
||
|
const TQString value = KURL::decode_string( (*it).mid( equalsPos + 1 ) );
|
||
15 years ago
|
|
||
|
if ( key == "to" )
|
||
|
request.addTo( value );
|
||
|
else if ( key == "cc" )
|
||
|
request.addCc( value );
|
||
|
else if ( key == "bcc" )
|
||
|
request.addBcc( value );
|
||
|
else if ( key == "headers" ) {
|
||
|
request.setEmitHeaders( value == "0" );
|
||
|
request.setEmitHeaders( false ); // ### ???
|
||
|
}
|
||
|
else if ( key == "subject" )
|
||
|
request.setSubject( value );
|
||
|
else if ( key == "from" )
|
||
|
request.setFromAddress( value );
|
||
|
else if ( key == "profile" )
|
||
|
request.setProfileName( value );
|
||
|
else if ( key == "hostname" )
|
||
|
request.setHeloHostname( value );
|
||
|
else if ( key == "body" )
|
||
|
request.set8BitBody( value.upper() == "8BIT" );
|
||
|
else if ( key == "size" )
|
||
|
request.setSize( value.toUInt() );
|
||
|
else
|
||
|
kdWarning(7112) << "while parsing query: unknown query item \""
|
||
|
<< key << "\" with value \"" << value << "\"" << endl;
|
||
|
}
|
||
|
|
||
|
return request;
|
||
|
}
|
||
|
|
||
15 years ago
|
TQCString Request::heloHostnameCString() const {
|
||
15 years ago
|
return KIDNA::toAsciiCString( heloHostname() );
|
||
|
}
|
||
|
|
||
15 years ago
|
static bool isUsAscii( const TQString & s ) {
|
||
15 years ago
|
for ( uint i = 0 ; i < s.length() ; ++i )
|
||
13 years ago
|
if ( s[i].unicode() > 127 ) return false;
|
||
15 years ago
|
return true;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
static inline bool isSpecial( char ch ) {
|
||
15 years ago
|
static const TQCString specials = "()<>[]:;@\\,.\"";
|
||
13 years ago
|
return specials.find( ch ) >= 0;
|
||
15 years ago
|
}
|
||
|
|
||
|
|
||
|
|
||
|
static inline bool needsQuoting( char ch ) {
|
||
|
return ch == '\\' || ch == '"' || ch == '\n' ;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
15 years ago
|
static inline TQCString rfc2047Encode( const TQString & s ) {
|
||
|
TQCString r = KCodecs::base64Encode( s.stripWhiteSpace().utf8(), false );
|
||
15 years ago
|
return "=?utf-8?b?" + r + "?=" ; // use base64 since that always gives a valid encoded-word
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
15 years ago
|
static TQCString quote( const TQString & s ) {
|
||
15 years ago
|
assert( isUsAscii( s ) );
|
||
|
|
||
15 years ago
|
TQCString r( s.length() * 2 );
|
||
15 years ago
|
bool needsQuotes = false;
|
||
|
|
||
|
unsigned int j = 0;
|
||
|
for ( unsigned int i = 0 ; i < s.length() ; ++i ) {
|
||
|
char ch = s[i].latin1();
|
||
|
if ( isSpecial( ch ) ) {
|
||
|
if ( needsQuoting( ch ) )
|
||
|
r[j++] = '\\';
|
||
|
needsQuotes = true;
|
||
|
}
|
||
|
r[j++] = ch;
|
||
|
}
|
||
|
r.truncate( j );
|
||
|
|
||
|
if ( needsQuotes )
|
||
|
return '"' + r + '"';
|
||
|
else
|
||
|
return r;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
15 years ago
|
static TQCString formatFromAddress( const TQString & fromRealName, const TQString & fromAddress ) {
|
||
15 years ago
|
if ( fromRealName.isEmpty() )
|
||
|
return fromAddress.latin1(); // no real name: return "joe@user.org"
|
||
|
|
||
|
// return "Joe User <joe@user.org>", "\"User, Joe\" <joe@user.org>"
|
||
|
// or "=?utf-8?q?Joe_User?= <joe@user.org>", depending on real name's nature.
|
||
15 years ago
|
TQCString r = isUsAscii( fromRealName ) ? quote( fromRealName ) : rfc2047Encode( fromRealName );
|
||
15 years ago
|
return r + " <" + fromAddress.latin1() + '>';
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
15 years ago
|
static TQCString formatSubject( TQString s ) {
|
||
15 years ago
|
if ( isUsAscii( s ) )
|
||
14 years ago
|
return TQString(s.remove( '\n' )).latin1(); // don't break header folding,
|
||
15 years ago
|
// so remove any line break
|
||
|
// that happen to be around
|
||
|
else
|
||
|
return rfc2047Encode( s );
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
15 years ago
|
TQCString Request::headerFields( const TQString & fromRealName ) const {
|
||
15 years ago
|
if ( !emitHeaders() )
|
||
|
return 0;
|
||
|
|
||
|
assert( hasFromAddress() ); // should have been checked for by
|
||
|
// caller (MAIL FROM comes before DATA)
|
||
|
|
||
15 years ago
|
TQCString result = "From: " + formatFromAddress( fromRealName, fromAddress() ) + "\r\n";
|
||
15 years ago
|
|
||
|
if ( !subject().isEmpty() )
|
||
|
result += "Subject: " + formatSubject( subject() ) + "\r\n";
|
||
|
if ( !to().empty() )
|
||
15 years ago
|
result += TQCString( "To: " ) + to().join( ",\r\n\t" /* line folding */ ).latin1() + "\r\n";
|
||
15 years ago
|
if ( !cc().empty() )
|
||
15 years ago
|
result += TQCString( "Cc: " ) + cc().join( ",\r\n\t" /* line folding */ ).latin1() + "\r\n";
|
||
15 years ago
|
return result;
|
||
|
}
|
||
|
|
||
|
} // namespace KioSMTP
|