diff options
Diffstat (limited to 'kioslave/smtp/request.cc')
-rw-r--r-- | kioslave/smtp/request.cc | 189 |
1 files changed, 189 insertions, 0 deletions
diff --git a/kioslave/smtp/request.cc b/kioslave/smtp/request.cc new file mode 100644 index 000000000..566d2c758 --- /dev/null +++ b/kioslave/smtp/request.cc @@ -0,0 +1,189 @@ +/* -*- c++ -*- + request.cc + + This file is part of kio_smtp, the KDE SMTP kioslave. + Copyright (c) 2003 Marc Mutz <[email protected]> + + 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; + + const QStringList query = QStringList::split( '&', url.query().mid(1) ); +#ifndef NDEBUG + kdDebug(7112) << "Parsing request from query:\n" + query.join("\n" ) << endl; +#endif + for ( QStringList::const_iterator it = query.begin() ; it != query.end() ; ++it ) { + int equalsPos = (*it).find( '=' ); + if ( equalsPos <= 0 ) + continue; + + const QString key = (*it).left( equalsPos ).lower(); + const QString value = KURL::decode_string( (*it).mid( equalsPos + 1 ) ); + + 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; + } + + QCString Request::heloHostnameCString() const { + return KIDNA::toAsciiCString( heloHostname() ); + } + + static bool isUsAscii( const QString & s ) { + for ( uint i = 0 ; i < s.length() ; ++i ) + if ( s[i].unicode() > 127 ) return false; + return true; + } + + + + static inline bool isSpecial( char ch ) { + static const QCString specials = "()<>[]:;@\\,.\""; + return specials.find( ch ) >= 0; + } + + + + static inline bool needsQuoting( char ch ) { + return ch == '\\' || ch == '"' || ch == '\n' ; + } + + + + static inline QCString rfc2047Encode( const QString & s ) { + QCString r = KCodecs::base64Encode( s.stripWhiteSpace().utf8(), false ); + return "=?utf-8?b?" + r + "?=" ; // use base64 since that always gives a valid encoded-word + } + + + + static QCString quote( const QString & s ) { + assert( isUsAscii( s ) ); + + QCString r( s.length() * 2 ); + 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; + } + + + + static QCString formatFromAddress( const QString & fromRealName, const QString & fromAddress ) { + if ( fromRealName.isEmpty() ) + return fromAddress.latin1(); // no real name: return "[email protected]" + + // return "Joe User <[email protected]>", "\"User, Joe\" <[email protected]>" + // or "=?utf-8?q?Joe_User?= <[email protected]>", depending on real name's nature. + QCString r = isUsAscii( fromRealName ) ? quote( fromRealName ) : rfc2047Encode( fromRealName ); + return r + " <" + fromAddress.latin1() + '>'; + } + + + + static QCString formatSubject( QString s ) { + if ( isUsAscii( s ) ) + return s.remove( '\n' ).latin1(); // don't break header folding, + // so remove any line break + // that happen to be around + else + return rfc2047Encode( s ); + } + + + + QCString Request::headerFields( const QString & fromRealName ) const { + if ( !emitHeaders() ) + return 0; + + assert( hasFromAddress() ); // should have been checked for by + // caller (MAIL FROM comes before DATA) + + QCString result = "From: " + formatFromAddress( fromRealName, fromAddress() ) + "\r\n"; + + if ( !subject().isEmpty() ) + result += "Subject: " + formatSubject( subject() ) + "\r\n"; + if ( !to().empty() ) + result += QCString( "To: " ) + to().join( ",\r\n\t" /* line folding */ ).latin1() + "\r\n"; + if ( !cc().empty() ) + result += QCString( "Cc: " ) + cc().join( ",\r\n\t" /* line folding */ ).latin1() + "\r\n"; + return result; + } + +} // namespace KioSMTP |