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

« back to all changes in this revision

Viewing changes to akonadi/resources/maildir/maildirresource.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 "maildirresource.h"
21
 
#include "settings.h"
22
 
#include "settingsadaptor.h"
23
 
#include "configdialog.h"
24
 
 
25
 
#include <QtCore/QDir>
26
 
#include <QtDBus/QDBusConnection>
27
 
 
28
 
#include <akonadi/kmime/messageparts.h>
29
 
#include <akonadi/changerecorder.h>
30
 
#include <akonadi/itemfetchscope.h>
31
 
#include <kdebug.h>
32
 
#include <kurl.h>
33
 
#include <kfiledialog.h>
34
 
#include <klocale.h>
35
 
 
36
 
#include <KWindowSystem>
37
 
 
38
 
#include "libmaildir/maildir.h"
39
 
 
40
 
#include <kmime/kmime_message.h>
41
 
 
42
 
#include <boost/shared_ptr.hpp>
43
 
typedef boost::shared_ptr<KMime::Message> MessagePtr;
44
 
 
45
 
using namespace Akonadi;
46
 
using KPIM::Maildir;
47
 
 
48
 
static QString maildirPath( const QString &remoteId )
49
 
{
50
 
  const int pos = remoteId.lastIndexOf( QDir::separator() );
51
 
  if ( pos >= 0 )
52
 
    return remoteId.left( pos );
53
 
  return QString();
54
 
}
55
 
 
56
 
static QString maildirId( const QString &remoteId )
57
 
{
58
 
  const int pos = remoteId.lastIndexOf( QDir::separator() );
59
 
  if ( pos >= 0 )
60
 
    return remoteId.mid( pos + 1 );
61
 
  return QString();
62
 
}
63
 
 
64
 
static QString maildirSubdirPath( const QString &parentPath, const QString &subName )
65
 
{
66
 
  QString basePath = maildirPath( parentPath );
67
 
  if ( !basePath.endsWith( QDir::separator() ) )
68
 
    basePath += QDir::separator();
69
 
  const QString name = maildirId( parentPath );
70
 
  return basePath + '.' + name + ".directory" + QDir::separator() + subName;
71
 
}
72
 
 
73
 
MaildirResource::MaildirResource( const QString &id )
74
 
    :ResourceBase( id )
75
 
{
76
 
  new SettingsAdaptor( Settings::self() );
77
 
  QDBusConnection::sessionBus().registerObject( QLatin1String( "/Settings" ),
78
 
                              Settings::self(), QDBusConnection::ExportAdaptors );
79
 
  connect( this, SIGNAL(reloadConfiguration()), SLOT(ensureDirExists()) );
80
 
 
81
 
  // We need to enable this here, otherwise we neither get the remote ID of the
82
 
  // parent collection when a collection changes, nor the full item when an item
83
 
  // is added.
84
 
  changeRecorder()->fetchCollection( true );
85
 
  changeRecorder()->itemFetchScope().fetchFullPayload( true );
86
 
}
87
 
 
88
 
MaildirResource::~ MaildirResource()
89
 
{
90
 
}
91
 
 
92
 
bool MaildirResource::retrieveItem( const Akonadi::Item &item, const QSet<QByteArray> &parts )
93
 
{
94
 
  Q_UNUSED( parts );
95
 
 
96
 
  const QString dir = maildirPath( item.remoteId() );
97
 
  const QString entry = maildirId( item.remoteId() );
98
 
 
99
 
  Maildir md( dir );
100
 
  if ( !md.isValid() ) {
101
 
    cancelTask( i18n( "Unable to fetch item: The maildir folder \"%1\" is not valid.",
102
 
                      md.path() ) );
103
 
    return false;
104
 
  }
105
 
 
106
 
  const QByteArray data = md.readEntry( entry );
107
 
  KMime::Message *mail = new KMime::Message();
108
 
  mail->setContent( KMime::CRLFtoLF( data ) );
109
 
  mail->parse();
110
 
 
111
 
  Item i( item );
112
 
  i.setPayload( MessagePtr( mail ) );
113
 
  itemRetrieved( i );
114
 
  return true;
115
 
}
116
 
 
117
 
void MaildirResource::aboutToQuit()
118
 
{
119
 
  // The settings may not have been saved if e.g. they have been modified via
120
 
  // DBus instead of the config dialog.
121
 
  Settings::self()->writeConfig();
122
 
  kDebug( 5254 ) << "Implement me!" ;
123
 
}
124
 
 
125
 
void MaildirResource::configure( WId windowId )
126
 
{
127
 
  ConfigDialog dlg;
128
 
  if ( windowId )
129
 
    KWindowSystem::setMainWindow( &dlg, windowId );
130
 
  dlg.exec();
131
 
 
132
 
  ensureDirExists();
133
 
  synchronizeCollectionTree();
134
 
}
135
 
 
136
 
void MaildirResource::itemAdded( const Akonadi::Item & item, const Akonadi::Collection& collection )
137
 
{
138
 
    Maildir dir( collection.remoteId() );
139
 
    QString errMsg;
140
 
    if ( Settings::readOnly() || !dir.isValid( errMsg ) ) {
141
 
      cancelTask( errMsg );
142
 
      return;
143
 
    }
144
 
    // we can only deal with mail
145
 
    if ( item.mimeType() != "message/rfc822" ) {
146
 
      cancelTask( i18n("Only email messages can be added to the Maildir resource.") );
147
 
      return;
148
 
    }
149
 
    const MessagePtr mail = item.payload<MessagePtr>();
150
 
    const QString rid = collection.remoteId() + QDir::separator() + dir.addEntry( mail->encodedContent() );
151
 
    Item i( item );
152
 
    i.setRemoteId( rid );
153
 
    changeCommitted( i );
154
 
}
155
 
 
156
 
void MaildirResource::itemChanged( const Akonadi::Item& item, const QSet<QByteArray>& parts )
157
 
{
158
 
    if ( Settings::self()->readOnly() || !parts.contains( MessagePart::Body ) ) {
159
 
      changeProcessed();
160
 
      return;
161
 
    }
162
 
 
163
 
    const QString path = maildirPath( item.remoteId() );
164
 
    const QString entry = maildirId( item.remoteId() );
165
 
 
166
 
    Maildir dir( path );
167
 
    QString errMsg;
168
 
    if ( !dir.isValid( errMsg ) ) {
169
 
        cancelTask( errMsg );
170
 
        return;
171
 
    }
172
 
    // we can only deal with mail
173
 
    if ( item.mimeType() != "message/rfc822" ) {
174
 
        cancelTask( i18n("Only email messages can be added to the Maildir resource.") );
175
 
        return;
176
 
    }
177
 
    const MessagePtr mail = item.payload<MessagePtr>();
178
 
    dir.writeEntry( entry, mail->encodedContent() );
179
 
    changeCommitted( item );
180
 
}
181
 
 
182
 
void MaildirResource::itemRemoved(const Akonadi::Item & item)
183
 
{
184
 
  if ( !Settings::self()->readOnly() ) {
185
 
    const QString path = maildirPath( item.remoteId() );
186
 
    const QString entry = maildirId( item.remoteId() );
187
 
 
188
 
    Maildir dir( path );
189
 
    QString errMsg;
190
 
    if ( !dir.isValid( errMsg ) ) {
191
 
      cancelTask( errMsg );
192
 
      return;
193
 
    }
194
 
    if ( !dir.removeEntry( entry ) ) {
195
 
      emit error( i18n("Failed to delete item: %1", item.remoteId()) );
196
 
    }
197
 
  }
198
 
  changeProcessed();
199
 
}
200
 
 
201
 
Collection::List listRecursive( const Collection &root, const Maildir &dir )
202
 
{
203
 
  Collection::List list;
204
 
  const QStringList mimeTypes = QStringList() << "message/rfc822" << Collection::mimeType();
205
 
  foreach ( const QString &sub, dir.subFolderList() ) {
206
 
    const QString path = maildirSubdirPath( root.remoteId(), sub );
207
 
    Maildir md( path );
208
 
    if ( !md.isValid() )
209
 
      continue;
210
 
    Collection c;
211
 
    c.setName( sub );
212
 
    c.setRemoteId( path );
213
 
    c.setParent( root );
214
 
    c.setContentMimeTypes( mimeTypes );
215
 
    list << c;
216
 
    list += listRecursive( c, md );
217
 
  }
218
 
  return list;
219
 
}
220
 
 
221
 
void MaildirResource::retrieveCollections()
222
 
{
223
 
  Maildir dir( Settings::self()->path() );
224
 
  QString errMsg;
225
 
  if ( !dir.isValid( errMsg ) ) {
226
 
    emit error( errMsg );
227
 
    collectionsRetrieved( Collection::List() );
228
 
  }
229
 
 
230
 
  Collection root;
231
 
  root.setParent( Collection::root() );
232
 
  root.setRemoteId( Settings::self()->path() );
233
 
  root.setName( name() );
234
 
  QStringList mimeTypes;
235
 
  mimeTypes << "message/rfc822" << Collection::mimeType();
236
 
  root.setContentMimeTypes( mimeTypes );
237
 
 
238
 
  Collection::List list;
239
 
  list << root;
240
 
  list += listRecursive( root, dir );
241
 
  collectionsRetrieved( list );
242
 
}
243
 
 
244
 
void MaildirResource::retrieveItems( const Akonadi::Collection & col )
245
 
{
246
 
  Maildir md( col.remoteId() );
247
 
  if ( !md.isValid() ) {
248
 
    emit error( i18n("Invalid maildir: %1", col.remoteId() ) );
249
 
    itemsRetrieved( Item::List() );
250
 
    return;
251
 
  }
252
 
  QStringList entryList = md.entryList();
253
 
 
254
 
  Item::List items;
255
 
  foreach ( const QString &entry, entryList ) {
256
 
    const QString rid = col.remoteId() + QDir::separator() + entry;
257
 
    Item item;
258
 
    item.setRemoteId( rid );
259
 
    item.setMimeType( "message/rfc822" );
260
 
    item.setSize( md.size( entry ) );
261
 
    KMime::Message *msg = new KMime::Message;
262
 
    msg->setHead( KMime::CRLFtoLF( md.readEntryHeaders( entry ) ) );
263
 
    msg->parse();
264
 
    item.setPayload( MessagePtr( msg ) );
265
 
    items << item;
266
 
  }
267
 
  itemsRetrieved( items );
268
 
}
269
 
 
270
 
void MaildirResource::collectionAdded(const Collection & collection, const Collection &parent)
271
 
{
272
 
  Maildir md( parent.remoteId() );
273
 
  kDebug( 5254 ) << md.subFolderList() << md.entryList();
274
 
  if ( Settings::self()->readOnly() || !md.isValid() ) {
275
 
    changeProcessed();
276
 
    return;
277
 
  }
278
 
  else {
279
 
 
280
 
    QString newFolderPath = md.addSubFolder( collection.name() );
281
 
    if ( newFolderPath.isEmpty() ) {
282
 
      changeProcessed();
283
 
      return;
284
 
    }
285
 
 
286
 
    kDebug( 5254 ) << md.subFolderList() << md.entryList();
287
 
 
288
 
    Collection col = collection;
289
 
    col.setRemoteId( newFolderPath );
290
 
    changeCommitted( col );
291
 
  }
292
 
 
293
 
}
294
 
 
295
 
void MaildirResource::collectionChanged(const Collection & collection)
296
 
{
297
 
  kDebug( 5254 ) << "Implement me!";
298
 
  AgentBase::Observer::collectionChanged( collection );
299
 
}
300
 
 
301
 
void MaildirResource::collectionRemoved( const Akonadi::Collection &collection )
302
 
{
303
 
  kDebug( 5254 ) << "Implement me!";
304
 
  AgentBase::Observer::collectionRemoved( collection );
305
 
}
306
 
 
307
 
void MaildirResource::ensureDirExists()
308
 
{
309
 
  Maildir root( Settings::self()->path() );
310
 
  if ( !root.isValid() ) {
311
 
    if ( !root.create() )
312
 
      emit status( Broken, i18n( "Unable to create maildir '%1'." ).arg( Settings::self()->path() ) );
313
 
  }
314
 
}
315
 
 
316
 
 
317
 
AKONADI_RESOURCE_MAIN( MaildirResource )
318
 
 
319
 
#include "maildirresource.moc"