KIMAP2

getmetadatajob.cpp
1 /*
2  Copyright (c) 2009 Andras Mantia <[email protected]>
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 "getmetadatajob.h"
21 
22 #include "kimap_debug.h"
23 
24 #include "metadatajobbase_p.h"
25 #include "message_p.h"
26 #include "session_p.h"
27 #include "rfccodecs.h"
28 
29 namespace KIMAP2
30 {
31 class GetMetaDataJobPrivate : public MetaDataJobBasePrivate
32 {
33 public:
34  GetMetaDataJobPrivate(Session *session, const QString &name) : MetaDataJobBasePrivate(session, name), maxSize(-1), depth("0") { }
35  ~GetMetaDataJobPrivate() { }
36 
37  qint64 maxSize;
38  QByteArray depth;
39  QSet<QByteArray> entries;
40  QSet<QByteArray> attributes;
42  // ^ mailbox ^ entry ^attribute ^ value
43 };
44 }
45 
46 using namespace KIMAP2;
47 
48 GetMetaDataJob::GetMetaDataJob(Session *session)
49  : MetaDataJobBase(*new GetMetaDataJobPrivate(session, "GetMetaData"))
50 {
51 }
52 
53 GetMetaDataJob::~GetMetaDataJob()
54 {
55 }
56 
57 static QList<QByteArray> sort(const QSet<QByteArray> &set)
58 {
59  QList<QByteArray> sortedEntries = set.toList();
60  qSort(sortedEntries);
61  return sortedEntries;
62 }
63 
64 void GetMetaDataJob::doStart()
65 {
67  QByteArray parameters;
68  parameters = '\"' + KIMAP2::encodeImapFolderName(d->mailBox.toUtf8()) + "\" ";
69 
70  QByteArray command = "GETMETADATA";
71  if (d->serverCapability == Annotatemore) {
72  d->m_name = "GetAnnotation";
73  command = "GETANNOTATION";
74  if (d->entries.size() > 1) {
75  parameters += '(';
76  }
77  Q_FOREACH (const QByteArray &entry, sort(d->entries)) {
78  parameters += '\"' + entry + "\" ";
79  }
80  if (d->entries.size() > 1) {
81  parameters[parameters.length() - 1 ] = ')';
82  parameters += ' ';
83  }
84 
85  if (d->attributes.size() > 1) {
86  parameters += '(';
87  }
88  Q_FOREACH (const QByteArray &attribute, sort(d->attributes)) {
89  parameters += '\"' + attribute + "\" ";
90  }
91  if (d->attributes.size() > 1) {
92  parameters[parameters.length() - 1 ] = ')';
93  } else {
94  parameters.truncate(parameters.length() - 1);
95  }
96 
97  } else {
98 
99  QByteArray options;
100  if (d->depth != "0") {
101  options = "DEPTH " + d->depth;
102  }
103  if (d->maxSize != -1) {
104  if (!options.isEmpty()) {
105  options += ' ';
106  }
107  options += "MAXSIZE " + QByteArray::number(d->maxSize);
108  }
109 
110  if (!options.isEmpty()) {
111  parameters = "(" + options + ") " + parameters;
112  }
113 
114  if (d->entries.size() >= 1) {
115  parameters += '(';
116  Q_FOREACH (const QByteArray &entry, sort(d->entries)) {
117  parameters += entry + " ";
118  }
119  parameters[parameters.length() - 1 ] = ')';
120  } else {
121  parameters.truncate(parameters.length() - 1);
122  }
123  }
124 
125  d->sendCommand(command, parameters);
126 // qCDebug(KIMAP2_LOG) << "SENT: " << command << " " << parameters;
127 }
128 
129 void GetMetaDataJob::handleResponse(const Message &response)
130 {
132 // qCDebug(KIMAP2_LOG) << "GOT: " << response.toString();
133 
134  //TODO: handle NO error messages having [METADATA MAXSIZE NNN], [METADATA TOOMANY], [METADATA NOPRIVATE] (see rfc5464)
135  // or [ANNOTATEMORE TOOBIG], [ANNOTATEMORE TOOMANY] respectively
136  if (handleErrorReplies(response) == NotHandled) {
137  if (response.content.size() >= 4) {
138  if (d->serverCapability == Annotatemore && response.content[1].toString() == "ANNOTATION") {
139  QString mailBox = QString::fromUtf8(KIMAP2::decodeImapFolderName(response.content[2].toString()));
140 
141  int i = 3;
142  while (i < response.content.size() - 1) {
143  QByteArray entry = response.content[i].toString();
144  QList<QByteArray> attributes = response.content[i + 1].toList();
145  int j = 0;
146  while (j < attributes.size() - 1) {
147  d->metadata[mailBox][entry][attributes[j]] = attributes[j + 1];
148  j += 2;
149  }
150  i += 2;
151  }
152  } else if (d->serverCapability == Metadata && response.content[1].toString() == "METADATA") {
153  QString mailBox = QString::fromUtf8(KIMAP2::decodeImapFolderName(response.content[2].toString()));
154 
155  const QList<QByteArray> &entries = response.content[3].toList();
156  int i = 0;
157  while (i < entries.size() - 1) {
158  const QByteArray &value = entries[i + 1];
159  QByteArray &targetValue = d->metadata[mailBox][entries[i]][""];
160  if (value != "NIL") { //This just indicates no value
161  targetValue = value;
162  }
163  i += 2;
164  }
165  }
166  }
167  }
168 }
169 
170 void GetMetaDataJob::addEntry(const QByteArray &entry, const QByteArray &attribute)
171 {
173  if (d->serverCapability == Annotatemore && attribute.isNull()) {
174  qCWarning(KIMAP2_LOG) << "In ANNOTATEMORE mode an attribute must be specified with addEntry!";
175  }
176  d->entries.insert(entry);
177  d->attributes.insert(attribute);
178 }
179 
181 {
183  d->entries.insert(d->removePrefix(entry));
184  d->attributes.insert(d->getAttribute(entry));
185 }
186 
188 {
190  d->maxSize = size;
191 }
192 
194 {
196 
197  switch (depth) {
198  case OneLevel:
199  d->depth = "1"; //krazy:exclude=doublequote_chars
200  break;
201  case AllLevels:
202  d->depth = "infinity";
203  break;
204  default:
205  d->depth = "0"; //krazy:exclude=doublequote_chars
206  }
207 }
208 
209 QByteArray GetMetaDataJob::metaData(const QString &mailBox, const QByteArray &entry, const QByteArray &attribute) const
210 {
211  Q_D(const GetMetaDataJob);
212  QByteArray attr = attribute;
213 
214  if (d->serverCapability == Metadata) {
215  attr = "";
216  }
217 
219  if (d->metadata.contains(mailBox)) {
220  if (d->metadata[mailBox].contains(entry)) {
221  result = d->metadata[mailBox][entry].value(attr);
222  }
223  }
224  return result;
225 }
226 
228 {
229  qCDebug(KIMAP2_LOG) << entry;
230  Q_D(const GetMetaDataJob);
231  return d->metadata.value(d->mailBox).value(d->removePrefix(entry)).value(d->getAttribute(entry));
232 }
233 
235 {
236  Q_D(const GetMetaDataJob);
237  return d->metadata[mailBox];
238 }
239 
241 {
242  Q_D(const GetMetaDataJob);
243  return allMetaDataForMailbox(d->mailBox);
244 }
245 
247 {
248  Q_D(const GetMetaDataJob);
249  const QMap<QByteArray, QMap<QByteArray, QByteArray> > &entries = d->metadata[mailbox];
251  foreach (const QByteArray &entry, entries.keys()) {
252  const QMap<QByteArray, QByteArray> &values = entries[entry];
253  foreach (const QByteArray &attribute, values.keys()) {
254  map.insert(d->addPrefix(entry, attribute), values[attribute]);
255  }
256  }
257  return map;
258 }
259 
261 {
262  Q_D(const GetMetaDataJob);
264 
266  while (i.hasNext()) {
267  i.next();
268  mailboxHash.insert(i.key(), allMetaDataForMailbox(i.key()));
269  }
270  return mailboxHash;
271 }
272 
bool isNull() const const
KIMAP2_EXPORT QString encodeImapFolderName(const QString &src)
Converts an Unicode IMAP mailbox to a QString which can be used in IMAP communication.
Definition: rfccodecs.cpp:192
QString fromUtf8(const char *str, int size)
void result(KJob *job)
Fetches mailbox metadata.
KIMAP2_DEPRECATED QByteArray metaData(const QString &mailBox, const QByteArray &entry, const QByteArray &attribute=QByteArray()) const
Get a single metadata entry.
Base class for jobs that operate on mailbox metadata.
QByteArray number(int n, int base)
Depth
Used to specify the depth of the metadata heirachy to walk.
@ Annotatemore
Used to indicate that the server supports the draft-daboo-imap-annotatemore-07 version of the extensi...
bool hasNext() const const
void addRequestedEntry(const QByteArray &entry)
Add an entry to the query list.
QList< T > toList() const const
QHash< QString, QMap< QByteArray, QByteArray > > allMetaDataForMailboxes() const
Get all the metadata for for all mailboxes.
void setDepth(Depth depth)
Sets whether to retrieve children or descendants of the requested entries.
QHash::iterator insert(const Key &key, const T &value)
int size() const const
QMap< QByteArray, QByteArray > allMetaDataForMailbox(const QString &mailbox) const
Get all the metadata for the mailbox.
@ AllLevels
The requested entries and all their descendants.
QString mailBox() const
The mailbox that will be acted upon.
KIMAP2_DEPRECATED void addEntry(const QByteArray &entry, const QByteArray &attribute=QByteArray())
Add an entry to the query list.
@ Metadata
Used to indicate that the server supports the RFC 5464 version of the extension.
QMapIterator::Item next()
bool isEmpty() const const
@ OneLevel
The requested entries and all their direct children.
QList< Key > keys() const const
const Key & key() const const
const char * name(StandardAction id)
void setMaximumSize(qint64 size)
Limits the size of returned metadata entries.
int length() const const
void truncate(int pos)
QMap< QByteArray, QByteArray > allMetaData() const
Get all the metadata for the mailbox set with setMailBox().
Provides handlers for various RFC/MIME encodings.
QVector< V > values(const QMultiHash< K, V > &c)
Q_D(Todo)
This file is part of the KDE documentation.
Documentation copyright © 1996-2023 The KDE developers.
Generated on Sun Dec 3 2023 03:50:35 by doxygen 1.8.17 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.