~ubuntu-branches/ubuntu/karmic/kdepim/karmic-backports

« back to all changes in this revision

Viewing changes to akonadi/plugins/akonadi_serializer_mail.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Christian Mangold
  • Date: 2009-07-10 06:34:50 UTC
  • mfrom: (1.1.40 upstream)
  • Revision ID: james.westby@ubuntu.com-20090710063450-neojgew2fh0n3y0u
Tags: 4:4.2.96-0ubuntu1
* New upstream release
* Bump kde build-deps to 4.2.96

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
    Copyright (c) 2007 Till Adam <adam@kde.org>
3
 
 
4
 
    This library is free software; you can redistribute it and/or modify it
5
 
    under the terms of the GNU Library General Public License as published by
6
 
    the Free Software Foundation; either version 2 of the License, or (at your
7
 
    option) any later version.
8
 
 
9
 
    This library is distributed in the hope that it will be useful, but WITHOUT
10
 
    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11
 
    FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Library General Public
12
 
    License for more details.
13
 
 
14
 
    You should have received a copy of the GNU Library General Public License
15
 
    along with this library; see the file COPYING.LIB.  If not, write to the
16
 
    Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
17
 
    02110-1301, USA.
18
 
*/
19
 
 
20
 
#include "akonadi_serializer_mail.h"
21
 
 
22
 
#include <QtCore/qplugin.h>
23
 
 
24
 
#include <kdebug.h>
25
 
#include <kmime/kmime_message.h>
26
 
#include <boost/shared_ptr.hpp>
27
 
 
28
 
#include <akonadi/item.h>
29
 
#include <akonadi/kmime/messageparts.h>
30
 
#include <akonadi/private/imapparser_p.h>
31
 
 
32
 
using namespace Akonadi;
33
 
using namespace KMime;
34
 
 
35
 
typedef boost::shared_ptr<KMime::Message> MessagePtr;
36
 
 
37
 
template <typename T> static void parseAddrList( const QList<QByteArray> &addrList, T *hdr )
38
 
{
39
 
  for ( QList<QByteArray>::ConstIterator it = addrList.constBegin(); it != addrList.constEnd(); ++it ) {
40
 
    QList<QByteArray> addr;
41
 
    ImapParser::parseParenthesizedList( *it, addr );
42
 
    if ( addr.count() != 4 ) {
43
 
      kWarning( 5264 ) << "Error parsing envelope address field: " << addr;
44
 
      continue;
45
 
    }
46
 
    KMime::Types::Mailbox addrField;
47
 
    addrField.setNameFrom7Bit( addr[0] );
48
 
    addrField.setAddress( addr[2] + '@' + addr[3] );
49
 
    hdr->addAddress( addrField );
50
 
  }
51
 
}
52
 
 
53
 
 
54
 
bool SerializerPluginMail::deserialize( Item& item, const QByteArray& label, QIODevice& data, int version )
55
 
{
56
 
    Q_UNUSED( version );
57
 
 
58
 
    if ( label != MessagePart::Body && label != MessagePart::Envelope && label != MessagePart::Header )
59
 
      return false;
60
 
 
61
 
    MessagePtr msg;
62
 
    if ( !item.hasPayload() ) {
63
 
        Message *m = new  Message();
64
 
        msg = MessagePtr( m );
65
 
        item.setPayload( msg );
66
 
    } else {
67
 
        msg = item.payload<MessagePtr>();
68
 
    }
69
 
 
70
 
    QByteArray buffer = data.readAll();
71
 
    if ( buffer.isEmpty() )
72
 
      return true;
73
 
    if ( label == MessagePart::Body ) {
74
 
      msg->setContent( buffer );
75
 
      msg->parse();
76
 
    } else if ( label == MessagePart::Header ) {
77
 
      if ( !msg->body().isEmpty() && !msg->contents().isEmpty() ) {
78
 
        msg->setHead( buffer );
79
 
        msg->parse();
80
 
      }
81
 
    } else if ( label == MessagePart::Envelope ) {
82
 
        QList<QByteArray> env;
83
 
        ImapParser::parseParenthesizedList( buffer, env );
84
 
        if ( env.count() < 10 ) {
85
 
          kWarning( 5264 ) << "Akonadi KMime Deserializer: Got invalid envelope: " << env;
86
 
          return false;
87
 
        }
88
 
        Q_ASSERT( env.count() >= 10 );
89
 
        // date
90
 
        msg->date()->from7BitString( env[0] );
91
 
        // subject
92
 
        msg->subject()->from7BitString( env[1] );
93
 
        // from
94
 
        QList<QByteArray> addrList;
95
 
        ImapParser::parseParenthesizedList( env[2], addrList );
96
 
        if ( !addrList.isEmpty() )
97
 
          parseAddrList( addrList, msg->from() );
98
 
        // sender
99
 
        ImapParser::parseParenthesizedList( env[2], addrList );
100
 
        if ( !addrList.isEmpty() )
101
 
          parseAddrList( addrList, msg->sender() );
102
 
        // reply-to
103
 
        ImapParser::parseParenthesizedList( env[4], addrList );
104
 
        if ( !addrList.isEmpty() )
105
 
          parseAddrList( addrList, msg->replyTo() );
106
 
        // to
107
 
        ImapParser::parseParenthesizedList( env[5], addrList );
108
 
        if ( !addrList.isEmpty() )
109
 
          parseAddrList( addrList, msg->to() );
110
 
        // cc
111
 
        ImapParser::parseParenthesizedList( env[6], addrList );
112
 
        if ( !addrList.isEmpty() )
113
 
          parseAddrList( addrList, msg->cc() );
114
 
        // bcc
115
 
        ImapParser::parseParenthesizedList( env[7], addrList );
116
 
        if ( !addrList.isEmpty() )
117
 
          parseAddrList( addrList, msg->bcc() );
118
 
        // in-reply-to
119
 
        msg->inReplyTo()->from7BitString( env[8] );
120
 
        // message id
121
 
        msg->messageID()->from7BitString( env[9] );
122
 
    }
123
 
 
124
 
    return true;
125
 
}
126
 
 
127
 
static QByteArray quoteImapListEntry( const QByteArray &b )
128
 
{
129
 
  if ( b.isEmpty() )
130
 
    return "NIL";
131
 
  return ImapParser::quote( b );
132
 
}
133
 
 
134
 
static QByteArray buildImapList( const QList<QByteArray> &list )
135
 
{
136
 
  if ( list.isEmpty() )
137
 
    return "NIL";
138
 
  return QByteArray( "(" ) + ImapParser::join( list, " " ) + QByteArray( ")" );
139
 
}
140
 
 
141
 
template <typename T> static QByteArray buildAddrStruct( T const *hdr )
142
 
{
143
 
  QList<QByteArray> addrList;
144
 
  KMime::Types::Mailbox::List mb = hdr->mailboxes();
145
 
  foreach ( const KMime::Types::Mailbox mbox, mb ) {
146
 
    QList<QByteArray> addrStruct;
147
 
    addrStruct << quoteImapListEntry( KMime::encodeRFC2047String( mbox.name(), "utf-8" ) );
148
 
    addrStruct << quoteImapListEntry( QByteArray() );
149
 
    addrStruct << quoteImapListEntry( mbox.addrSpec().localPart.toUtf8() );
150
 
    addrStruct << quoteImapListEntry( mbox.addrSpec().domain.toUtf8() );
151
 
    addrList << buildImapList( addrStruct );
152
 
  }
153
 
  return buildImapList( addrList );
154
 
}
155
 
 
156
 
void SerializerPluginMail::serialize( const Item& item, const QByteArray& label, QIODevice& data, int &version )
157
 
{
158
 
  Q_UNUSED( version );
159
 
 
160
 
  boost::shared_ptr<Message> m = item.payload< boost::shared_ptr<Message> >();
161
 
  m->assemble();
162
 
  if ( label == MessagePart::Body ) {
163
 
    data.write( m->encodedContent() );
164
 
  } else if ( label == MessagePart::Envelope ) {
165
 
    QList<QByteArray> env;
166
 
    env << quoteImapListEntry( m->date()->as7BitString( false ) );
167
 
    env << quoteImapListEntry( m->subject()->as7BitString( false ) );
168
 
    env << buildAddrStruct( m->from() );
169
 
    env << buildAddrStruct( m->sender() );
170
 
    env << buildAddrStruct( m->replyTo() );
171
 
    env << buildAddrStruct( m->to() );
172
 
    env << buildAddrStruct( m->cc() );
173
 
    env << buildAddrStruct( m->bcc() );
174
 
    env << quoteImapListEntry( m->inReplyTo()->as7BitString( false ) );
175
 
    env << quoteImapListEntry( m->messageID()->as7BitString( false ) );
176
 
    data.write( buildImapList( env ) );
177
 
  } else if ( label == MessagePart::Header ) {
178
 
    data.write( m->head() );
179
 
  }
180
 
}
181
 
 
182
 
QSet<QByteArray> SerializerPluginMail::parts(const Item & item) const
183
 
{
184
 
  if ( !item.hasPayload<MessagePtr>() )
185
 
    return QSet<QByteArray>();
186
 
  MessagePtr msg = item.payload<MessagePtr>();
187
 
  QSet<QByteArray> set;
188
 
  // FIXME: we actually want "has any header" here, but the kmime api doesn't offer that yet
189
 
  if ( msg->hasContent() || msg->hasHeader( "Message-ID" ) ) {
190
 
    set << MessagePart::Envelope << MessagePart::Header;
191
 
    if ( !msg->body().isEmpty() || !msg->contents().isEmpty() )
192
 
      set << MessagePart::Body;
193
 
  }
194
 
  return set;
195
 
}
196
 
 
197
 
Q_EXPORT_PLUGIN2( akonadi_serializer_mail, SerializerPluginMail )
198
 
 
199
 
#include "akonadi_serializer_mail.moc"