~ubuntu-branches/ubuntu/lucid/kdebase/lucid

« back to all changes in this revision

Viewing changes to kioslave/smtp/request.cc

  • Committer: Bazaar Package Importer
  • Author(s): Ana Beatriz Guerrero Lopez
  • Date: 2009-04-05 05:22:13 UTC
  • mfrom: (0.4.2 experimental) (0.2.2 upstream)
  • mto: This revision was merged to the branch mainline in revision 235.
  • Revision ID: james.westby@ubuntu.com-20090405052213-39thr4l6p2ss07uj
Tags: 4:4.2.2-1
* New upstream release:
  - khtml fixes. (Closes: #290285, #359680)
  - Default konsole sessions can be deleted. (Closes: #286342)
  - Tag widget uses standard application palette. (Closes: #444800)
  - ... and surely many more but we have lost track...

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*  -*- c++ -*-
2
 
    request.cc
3
 
 
4
 
    This file is part of kio_smtp, the KDE SMTP kioslave.
5
 
    Copyright (c) 2003 Marc Mutz <mutz@kde.org>
6
 
 
7
 
    This program is free software; you can redistribute it and/or modify it
8
 
    under the terms of the GNU General Public License, version 2, as
9
 
    published by the Free Software Foundation.
10
 
 
11
 
    This program is distributed in the hope that it will be useful, but
12
 
    WITHOUT ANY WARRANTY; without even the implied warranty of
13
 
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14
 
    General Public License for more details.
15
 
 
16
 
    You should have received a copy of the GNU General Public License
17
 
    along with this program; if not, write to the Free Software
18
 
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
19
 
 
20
 
    In addition, as a special exception, the copyright holders give
21
 
    permission to link the code of this program with any edition of
22
 
    the Qt library by Trolltech AS, Norway (or with modified versions
23
 
    of Qt that use the same license as Qt), and distribute linked
24
 
    combinations including the two.  You must obey the GNU General
25
 
    Public License in all respects for all of the code used other than
26
 
    Qt.  If you modify this file, you may extend this exception to
27
 
    your version of the file, but you are not obligated to do so.  If
28
 
    you do not wish to do so, delete this exception statement from
29
 
    your version.
30
 
*/
31
 
 
32
 
#include <config.h>
33
 
 
34
 
#include "request.h"
35
 
 
36
 
#include <kurl.h>
37
 
#include <kidna.h>
38
 
#include <kmdcodec.h>
39
 
#include <kdebug.h>
40
 
 
41
 
#include <assert.h>
42
 
 
43
 
namespace KioSMTP {
44
 
 
45
 
  Request Request::fromURL( const KURL & url ) {
46
 
    Request request;
47
 
 
48
 
    const QStringList query = QStringList::split( '&', url.query().mid(1) );
49
 
#ifndef NDEBUG
50
 
    kdDebug(7112) << "Parsing request from query:\n" + query.join("\n" ) << endl;
51
 
#endif
52
 
    for ( QStringList::const_iterator it = query.begin() ; it != query.end() ; ++it ) {
53
 
      int equalsPos = (*it).find( '=' );
54
 
      if ( equalsPos <= 0 )
55
 
        continue;
56
 
 
57
 
      const QString key = (*it).left( equalsPos ).lower();
58
 
      const QString value = KURL::decode_string( (*it).mid( equalsPos + 1 ) );
59
 
 
60
 
      if ( key == "to" )
61
 
        request.addTo( value );
62
 
      else if ( key == "cc" )
63
 
        request.addCc( value );
64
 
      else if ( key == "bcc" )
65
 
        request.addBcc( value );
66
 
      else if ( key == "headers" ) {
67
 
        request.setEmitHeaders( value == "0" );
68
 
        request.setEmitHeaders( false ); // ### ???
69
 
      }
70
 
      else if ( key == "subject" )
71
 
        request.setSubject( value );
72
 
      else if ( key == "from" )
73
 
        request.setFromAddress( value );
74
 
      else if ( key == "profile" )
75
 
        request.setProfileName( value );
76
 
      else if ( key == "hostname" )
77
 
        request.setHeloHostname( value );
78
 
      else if ( key == "body" )
79
 
        request.set8BitBody( value.upper() == "8BIT" );
80
 
      else if ( key == "size" )
81
 
        request.setSize( value.toUInt() );
82
 
      else
83
 
        kdWarning(7112) << "while parsing query: unknown query item \""
84
 
                        << key << "\" with value \"" << value << "\"" << endl;
85
 
    }
86
 
 
87
 
    return request;
88
 
  }
89
 
 
90
 
  QCString Request::heloHostnameCString() const {
91
 
    return KIDNA::toAsciiCString( heloHostname() );
92
 
  }
93
 
 
94
 
  static bool isUsAscii( const QString & s ) {
95
 
    for ( uint i = 0 ; i < s.length() ; ++i )
96
 
      if ( s[i].unicode() > 127 ) return false;
97
 
    return true;
98
 
  }
99
 
 
100
 
 
101
 
 
102
 
  static inline bool isSpecial( char ch ) {
103
 
    static const QCString specials = "()<>[]:;@\\,.\"";
104
 
    return specials.find( ch ) >= 0;
105
 
  }
106
 
 
107
 
 
108
 
 
109
 
  static inline bool needsQuoting( char ch ) {
110
 
    return ch == '\\' || ch == '"' || ch == '\n' ;
111
 
  }
112
 
 
113
 
 
114
 
 
115
 
  static inline QCString rfc2047Encode( const QString & s ) {
116
 
    QCString r = KCodecs::base64Encode( s.stripWhiteSpace().utf8(), false );
117
 
    return "=?utf-8?b?" + r + "?=" ; // use base64 since that always gives a valid encoded-word
118
 
  }
119
 
 
120
 
 
121
 
 
122
 
  static QCString quote( const QString & s ) {
123
 
    assert( isUsAscii( s ) );
124
 
 
125
 
    QCString r( s.length() * 2 );
126
 
    bool needsQuotes = false;
127
 
 
128
 
    unsigned int j = 0;
129
 
    for ( unsigned int i = 0 ; i < s.length() ; ++i ) {
130
 
      char ch = s[i].latin1();
131
 
      if ( isSpecial( ch ) ) {
132
 
        if ( needsQuoting( ch ) )
133
 
          r[j++] = '\\';
134
 
        needsQuotes = true;
135
 
      }
136
 
      r[j++] = ch;
137
 
    }
138
 
    r.truncate( j );
139
 
 
140
 
    if ( needsQuotes )
141
 
      return '"' + r + '"';
142
 
    else
143
 
      return r;
144
 
  }
145
 
 
146
 
 
147
 
 
148
 
  static QCString formatFromAddress( const QString & fromRealName, const QString & fromAddress ) {
149
 
    if ( fromRealName.isEmpty() )
150
 
      return fromAddress.latin1(); // no real name: return "joe@user.org"
151
 
 
152
 
    // return "Joe User <joe@user.org>", "\"User, Joe\" <joe@user.org>"
153
 
    // or "=?utf-8?q?Joe_User?= <joe@user.org>", depending on real name's nature.
154
 
    QCString r = isUsAscii( fromRealName ) ? quote( fromRealName ) : rfc2047Encode( fromRealName );
155
 
    return r + " <" + fromAddress.latin1() + '>';
156
 
  }
157
 
 
158
 
 
159
 
 
160
 
  static QCString formatSubject( QString s ) {
161
 
    if ( isUsAscii( s ) )
162
 
      return s.remove( '\n' ).latin1(); // don't break header folding,
163
 
                                        // so remove any line break
164
 
                                        // that happen to be around
165
 
    else
166
 
      return rfc2047Encode( s );
167
 
  }
168
 
 
169
 
 
170
 
 
171
 
  QCString Request::headerFields( const QString & fromRealName ) const {
172
 
    if ( !emitHeaders() )
173
 
      return 0;
174
 
 
175
 
    assert( hasFromAddress() ); // should have been checked for by
176
 
                                // caller (MAIL FROM comes before DATA)
177
 
 
178
 
    QCString result = "From: " + formatFromAddress( fromRealName, fromAddress() ) + "\r\n";
179
 
 
180
 
    if ( !subject().isEmpty() )
181
 
      result += "Subject: " + formatSubject( subject() ) + "\r\n";
182
 
    if ( !to().empty() )
183
 
      result += QCString( "To: " ) + to().join( ",\r\n\t" /* line folding */ ).latin1() + "\r\n";
184
 
    if ( !cc().empty() )
185
 
      result += QCString( "Cc: " ) + cc().join( ",\r\n\t" /* line folding */ ).latin1() + "\r\n";
186
 
    return result;
187
 
  }
188
 
 
189
 
} // namespace KioSMTP