• Skip to content
  • Skip to link menu
KDE API Reference
  • KDE API Reference
  • kdepimlibs API Reference
  • KDE Home
  • Contact Us
 

akonadi

  • sources
  • kde-4.14
  • kdepimlibs
  • akonadi
itemcreatejob.cpp
1 /*
2  Copyright (c) 2006 - 2007 Volker Krause <vkrause@kde.org>
3  Copyright (c) 2007 Robert Zwerus <arzie@dds.nl>
4  Copyright (c) 2014 Daniel Vrátil <dvratil@redhat.com>
5 
6  This library is free software; you can redistribute it and/or modify it
7  under the terms of the GNU Library General Public License as published by
8  the Free Software Foundation; either version 2 of the License, or (at your
9  option) any later version.
10 
11  This library is distributed in the hope that it will be useful, but WITHOUT
12  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13  FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
14  License for more details.
15 
16  You should have received a copy of the GNU Library General Public License
17  along with this library; see the file COPYING.LIB. If not, write to the
18  Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19  02110-1301, USA.
20 */
21 
22 #include "itemcreatejob.h"
23 
24 #include "collection.h"
25 #include "imapparser_p.h"
26 #include "item.h"
27 #include "item_p.h"
28 #include "itemserializer_p.h"
29 #include "job_p.h"
30 #include "protocolhelper_p.h"
31 #include "gid/gidextractor_p.h"
32 
33 #include <QtCore/QDateTime>
34 #include <QtCore/QFile>
35 
36 #include <kdebug.h>
37 
38 using namespace Akonadi;
39 
40 class Akonadi::ItemCreateJobPrivate : public JobPrivate
41 {
42 public:
43  ItemCreateJobPrivate(ItemCreateJob *parent)
44  : JobPrivate(parent)
45  , mMergeOptions(ItemCreateJob::NoMerge)
46  , mItemReceived(false)
47  {
48  }
49 
50  QByteArray nextPartHeader();
51 
52  Collection mCollection;
53  Item mItem;
54  QSet<QByteArray> mParts;
55  Item::Id mUid;
56  QDateTime mDatetime;
57  QByteArray mPendingData;
58  ItemCreateJob::MergeOptions mMergeOptions;
59  bool mItemReceived;
60 };
61 
62 QByteArray ItemCreateJobPrivate::nextPartHeader()
63 {
64  QByteArray command;
65  if (!mParts.isEmpty()) {
66  QSetIterator<QByteArray> it(mParts);
67  const QByteArray label = it.next();
68  mParts.remove(label);
69 
70  mPendingData.clear();
71  int version = 0;
72  ItemSerializer::serialize(mItem, label, mPendingData, version);
73  command += ' ' + ProtocolHelper::encodePartIdentifier(ProtocolHelper::PartPayload, label, version);
74  if (mPendingData.size() > 0) {
75  command += " {" + QByteArray::number(mPendingData.size()) + "}\n";
76  } else {
77  if (mPendingData.isNull()) {
78  command += " NIL";
79  } else {
80  command += " \"\"";
81  }
82  command += nextPartHeader();
83  }
84  } else {
85  command += ")\n";
86  }
87  return command;
88 }
89 
90 ItemCreateJob::ItemCreateJob(const Item &item, const Collection &collection, QObject *parent)
91  : Job(new ItemCreateJobPrivate(this), parent)
92 {
93  Q_D(ItemCreateJob);
94 
95  Q_ASSERT(!item.mimeType().isEmpty());
96  d->mItem = item;
97  d->mParts = d->mItem.loadedPayloadParts();
98  d->mCollection = collection;
99 }
100 
101 ItemCreateJob::~ItemCreateJob()
102 {
103 }
104 
105 void ItemCreateJob::doStart()
106 {
107  Q_D(ItemCreateJob);
108 
109  QByteArray remoteId;
110 
111  QList<QByteArray> flags;
112  flags.append("\\MimeType[" + d->mItem.mimeType().toLatin1() + ']');
113  const QString gid = GidExtractor::getGid(d->mItem);
114  if (!gid.isNull()) {
115  flags.append(ImapParser::quote("\\Gid[" + gid.toUtf8() + ']'));
116  }
117  if (!d->mItem.remoteId().isEmpty()) {
118  flags.append(ImapParser::quote("\\RemoteId[" + d->mItem.remoteId().toUtf8() + ']'));
119  }
120  if (!d->mItem.remoteRevision().isEmpty()) {
121  flags.append(ImapParser::quote("\\RemoteRevision[" + d->mItem.remoteRevision().toUtf8() + ']'));
122  }
123  const bool mergeByGid = (d->mMergeOptions & GID) && !d->mItem.gid().isEmpty();
124  const bool mergeByRid = (d->mMergeOptions & RID) && !d->mItem.remoteId().isEmpty();
125  const bool mergeSilent = (d->mMergeOptions & Silent);
126  const bool merge = mergeByGid || mergeByRid;
127  if (d->mItem.d_func()->mFlagsOverwritten || !merge) {
128  flags += d->mItem.flags().toList();
129  } else {
130  Q_FOREACH(const QByteArray &flag, d->mItem.d_func()->mAddedFlags.toList()) {
131  flags += "+" + flag;
132  }
133  Q_FOREACH(const QByteArray &flag, d->mItem.d_func()->mDeletedFlags.toList()) {
134  flags += "-" + flag;
135  }
136  }
137  if (d->mItem.d_func()->mTagsOverwritten || !merge) {
138  Q_FOREACH(const Akonadi::Tag &tag, d->mItem.d_func()->mAddedTags) {
139  if (tag.gid().isEmpty() && !tag.remoteId().isEmpty()) {
140  flags += "\\RTag[" + tag.remoteId() + ']';
141  } else if (!tag.gid().isEmpty()) {
142  flags += "\\Tag[" + tag.gid() + ']';
143  }
144  }
145  } else {
146  Q_FOREACH(const Akonadi::Tag &tag, d->mItem.d_func()->mAddedTags) {
147  if (tag.gid().isEmpty() && !tag.remoteId().isEmpty()) {
148  flags += "+\\RTag[" + tag.remoteId() + ']';
149  } else if (!tag.gid().isEmpty()) {
150  flags += "+\\Tag[" + tag.gid() + ']';
151  }
152  }
153  Q_FOREACH(const Akonadi::Tag &tag, d->mItem.d_func()->mDeletedTags) {
154  if (tag.gid().isEmpty() && !tag.remoteId().isEmpty()) {
155  flags += "-\\RTag[" + tag.remoteId() + ']';
156  } else if (!tag.gid().isEmpty()) {
157  flags += "-\\Tag[" + tag.gid() + ']';
158  }
159  }
160  }
161 
162  QByteArray command = d->newTag();
163  if (merge) {
164  QList<QByteArray> mergeArgs;
165  if (mergeByGid) {
166  mergeArgs << "GID";
167  }
168  if (mergeByRid) {
169  mergeArgs << "REMOTEID";
170  }
171  if (mergeSilent) {
172  mergeArgs << "SILENT";
173  }
174  command += " MERGE (" + ImapParser::join(mergeArgs, " ") + ") ";
175  } else {
176  command += " X-AKAPPEND ";
177  }
178 
179  command += QByteArray::number(d->mCollection.id())
180  + ' ' + QByteArray::number(d->mItem.size())
181  + " (" + ImapParser::join(flags, " ") + ")"
182  + " ("; // list of parts
183  const QByteArray attrs = ProtocolHelper::attributesToByteArray(d->mItem, true);
184  if (!attrs.isEmpty()) {
185  command += attrs;
186  }
187 
188  command += d->nextPartHeader();
189 
190  d->writeData(command);
191 }
192 
193 void ItemCreateJob::doHandleResponse(const QByteArray &tag, const QByteArray &data)
194 {
195  Q_D(ItemCreateJob);
196 
197  if (tag == "+") { // ready for literal data
198  if (data.startsWith("STREAM")) {
199  QByteArray error;
200  if (!ProtocolHelper::streamPayloadToFile(data, d->mPendingData, error)) {
201  d->writeData("* NO " + error);
202  return;
203  }
204  } else {
205  d->writeData(d->mPendingData);
206  }
207  d->writeData(d->nextPartHeader());
208  return;
209  }
210  if (tag == "*") {
211  int begin = data.indexOf("FETCH");
212  if (begin >= 0) {
213  QList<QByteArray> fetchResponse;
214  ImapParser::parseParenthesizedList(data, fetchResponse, begin + 6);
215 
216  Item item;
217  ProtocolHelper::parseItemFetchResult(fetchResponse, item);
218  if (!item.isValid()) {
219  // Error, maybe?
220  return;
221  }
222  d->mItemReceived = true;
223  d->mItem = item;
224  }
225  return;
226  }
227  if (tag == d->tag()) {
228  int uidNextPos = data.indexOf("UIDNEXT");
229  if (uidNextPos != -1) {
230  bool ok = false;
231  ImapParser::parseNumber(data, d->mUid, &ok, uidNextPos + 7);
232  if (!ok) {
233  kDebug() << "Invalid UIDNEXT response to APPEND command: "
234  << tag << data;
235  }
236  }
237  int dateTimePos = data.indexOf("DATETIME");
238  if (dateTimePos != -1) {
239  int resultPos = ImapParser::parseDateTime(data, d->mDatetime, dateTimePos + 8);
240  if (resultPos == (dateTimePos + 8)) {
241  kDebug() << "Invalid DATETIME response to APPEND command: "
242  << tag << data;
243  }
244  }
245  }
246 }
247 
248 void ItemCreateJob::setMerge(ItemCreateJob::MergeOptions options)
249 {
250  Q_D(ItemCreateJob);
251 
252  d->mMergeOptions = options;
253 }
254 
255 Item ItemCreateJob::item() const
256 {
257  Q_D(const ItemCreateJob);
258 
259  if (d->mItemReceived) {
260  return d->mItem;
261  }
262 
263  if (d->mUid == 0) {
264  return Item();
265  }
266 
267  Item item(d->mItem);
268  item.setId(d->mUid);
269  item.setRevision(0);
270  item.setModificationTime(d->mDatetime);
271  item.setParentCollection(d->mCollection);
272  item.setStorageCollectionId(d->mCollection.id());
273 
274  return item;
275 }
QByteArray::clear
void clear()
Akonadi::ItemCreateJob::item
Item item() const
Returns the created item with the new unique id, or an invalid item if the job failed.
Definition: itemcreatejob.cpp:255
QByteArray
Akonadi::Collection
Represents a collection of PIM items.
Definition: collection.h:75
QByteArray::isEmpty
bool isEmpty() const
QByteArray::startsWith
bool startsWith(const QByteArray &ba) const
Akonadi::ProtocolHelper::attributesToByteArray
static QByteArray attributesToByteArray(const Entity &entity, bool ns=false)
Convert attributes to their protocol representation.
Definition: protocolhelper.cpp:232
Akonadi::Job
Base class for all actions in the Akonadi storage.
Definition: job.h:86
QString::isNull
bool isNull() const
Akonadi::ItemCreateJob::GID
Merge by GID.
Definition: itemcreatejob.h:101
QByteArray::indexOf
int indexOf(char ch, int from) const
QList::append
void append(const T &value)
QObject
QByteArray::number
QByteArray number(int n, int base)
Akonadi::ProtocolHelper::encodePartIdentifier
static QByteArray encodePartIdentifier(PartNamespace ns, const QByteArray &label, int version=0)
Encodes part label and namespace.
Definition: protocolhelper.cpp:252
QSet< QByteArray >
QString
QList< QByteArray >
Akonadi::ItemCreateJob
Job that creates a new item in the Akonadi storage.
Definition: itemcreatejob.h:73
QSetIterator
Akonadi::GidExtractor::getGid
static QString getGid(const Item &item)
Extracts the gid from item.
Definition: gidextractor.cpp:39
Akonadi::ItemCreateJob::doHandleResponse
virtual void doHandleResponse(const QByteArray &tag, const QByteArray &data)
This method should be reimplemented in the concrete jobs in case you want to handle incoming data...
Definition: itemcreatejob.cpp:193
Akonadi::ItemCreateJob::doStart
virtual void doStart()
This method must be reimplemented in the concrete jobs.
Definition: itemcreatejob.cpp:105
Akonadi::ItemCreateJob::ItemCreateJob
ItemCreateJob(const Item &item, const Collection &collection, QObject *parent=0)
Creates a new item create job.
Definition: itemcreatejob.cpp:90
Akonadi::JobPrivate
Definition: job_p.h:31
Akonadi::Tag
An Akonadi Tag.
Definition: tag.h:43
Akonadi::ItemCreateJob::RID
Merge by remote id.
Definition: itemcreatejob.h:100
Akonadi::ItemSerializer::serialize
static void serialize(const Item &item, const QByteArray &label, QByteArray &data, int &version)
throws ItemSerializerException on failure
Definition: itemserializer.cpp:116
Akonadi::ProtocolHelper::parseItemFetchResult
static void parseItemFetchResult(const QList< QByteArray > &lineTokens, Item &item, ProtocolHelperValuePool *valuePool=0)
Parses a single line from an item fetch job result into an Item object.
Definition: protocolhelper.cpp:503
Akonadi::ItemCreateJob::~ItemCreateJob
~ItemCreateJob()
Destroys the item create job.
Definition: itemcreatejob.cpp:101
QByteArray::remove
QByteArray & remove(int pos, int len)
Akonadi::ItemCreateJob::Silent
Only return the id of the merged/created item.
Definition: itemcreatejob.h:102
QDateTime
Akonadi::ItemCreateJob::setMerge
void setMerge(MergeOptions options)
Merge this item into an existing one if available.
Definition: itemcreatejob.cpp:248
QString::toUtf8
QByteArray toUtf8() const
This file is part of the KDE documentation.
Documentation copyright © 1996-2020 The KDE developers.
Generated on Mon Jun 22 2020 13:38:03 by doxygen 1.8.7 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.

akonadi

Skip menu "akonadi"
  • Main Page
  • Namespace List
  • Namespace Members
  • Alphabetical List
  • Class List
  • Class Hierarchy
  • Class Members
  • File List
  • Modules
  • Related Pages

kdepimlibs API Reference

Skip menu "kdepimlibs API Reference"
  • akonadi
  •   contact
  •   kmime
  •   socialutils
  • kabc
  • kalarmcal
  • kblog
  • kcal
  • kcalcore
  • kcalutils
  • kholidays
  • kimap
  • kioslave
  •   imap4
  •   mbox
  •   nntp
  • kldap
  • kmbox
  • kmime
  • kontactinterface
  • kpimidentities
  • kpimtextedit
  • kpimutils
  • kresources
  • ktnef
  • kxmlrpcclient
  • mailtransport
  • microblog
  • qgpgme
  • syndication
  •   atom
  •   rdf
  •   rss2

Search



Report problems with this website to our bug tracking system.
Contact the specific authors with questions and comments about the page contents.

KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal