KIMAP

getmetadatajob.cpp
1/*
2 SPDX-FileCopyrightText: 2009 Andras Mantia <amantia@kde.org>
3
4 SPDX-License-Identifier: LGPL-2.0-or-later
5*/
6
7#include "getmetadatajob.h"
8
9#include "kimap_debug.h"
10#include <KLocalizedString>
11
12#include "metadatajobbase_p.h"
13#include "response_p.h"
14#include "rfccodecs.h"
15#include "session_p.h"
16
17namespace KIMAP
18{
19class GetMetaDataJobPrivate : public MetaDataJobBasePrivate
20{
21public:
22 GetMetaDataJobPrivate(Session *session, const QString &name)
23 : MetaDataJobBasePrivate(session, name)
24 , depth("0")
25 {
26 }
27 ~GetMetaDataJobPrivate()
28 {
29 }
30
31 qint64 maxSize = -1;
32 QByteArray depth;
33 QSet<QByteArray> entries;
34 QSet<QByteArray> attributes;
36 // ^ mailbox ^ entry ^attribute ^ value
37};
38}
39
40using namespace KIMAP;
41
42GetMetaDataJob::GetMetaDataJob(Session *session)
43 : MetaDataJobBase(*new GetMetaDataJobPrivate(session, i18n("GetMetaData")))
44{
45}
46
47GetMetaDataJob::~GetMetaDataJob()
48{
49}
50
51static QList<QByteArray> sort(const QSet<QByteArray> &set)
52{
53 QList<QByteArray> sortedEntries = set.values();
54 std::sort(sortedEntries.begin(), sortedEntries.end());
55 return sortedEntries;
56}
57
58void GetMetaDataJob::doStart()
59{
61 QByteArray parameters;
62 parameters = '\"' + KIMAP::encodeImapFolderName(d->mailBox.toUtf8()) + "\" ";
63
64 QByteArray command = "GETMETADATA";
65 if (d->serverCapability == Annotatemore) {
66 d->m_name = i18n("GetAnnotation");
67 command = "GETANNOTATION";
68 if (d->entries.size() > 1) {
69 parameters += '(';
70 }
71 const auto sortedEntries = sort(d->entries);
72 for (const QByteArray &entry : sortedEntries) {
73 parameters += '\"' + entry + "\" ";
74 }
75 if (d->entries.size() > 1) {
76 parameters[parameters.length() - 1] = ')';
77 parameters += ' ';
78 }
79
80 if (d->attributes.size() > 1) {
81 parameters += '(';
82 }
83 const auto sortedAttributes = sort(d->attributes);
84 for (const QByteArray &attribute : sortedAttributes) {
85 parameters += '\"' + attribute + "\" ";
86 }
87 if (d->attributes.size() > 1) {
88 parameters[parameters.length() - 1] = ')';
89 } else {
90 parameters.chop(1);
91 }
92
93 } else {
94 QByteArray options;
95 if (d->depth != "0") {
96 options = "DEPTH " + d->depth;
97 }
98 if (d->maxSize != -1) {
99 if (!options.isEmpty()) {
100 options += ' ';
101 }
102 options += "MAXSIZE " + QByteArray::number(d->maxSize);
103 }
104
105 if (!options.isEmpty()) {
106 parameters = "(" + options + ") " + parameters;
107 }
108
109 if (d->entries.size() >= 1) {
110 parameters += '(';
111 const auto sortedEntries = sort(d->entries);
112 for (const QByteArray &entry : sortedEntries) {
113 parameters += entry + " ";
114 }
115 parameters[parameters.length() - 1] = ')';
116 } else {
117 parameters.chop(1);
118 }
119 }
120
121 d->tags << d->sessionInternal()->sendCommand(command, parameters);
122 // qCDebug(KIMAP_LOG) << "SENT: " << command << " " << parameters;
123}
124
125void GetMetaDataJob::handleResponse(const Response &response)
126{
128 // qCDebug(KIMAP_LOG) << "GOT: " << response.toString();
129
130 // TODO: handle NO error messages having [METADATA MAXSIZE NNN], [METADATA TOOMANY], [METADATA NOPRIVATE] (see rfc5464)
131 // or [ANNOTATEMORE TOOBIG], [ANNOTATEMORE TOOMANY] respectively
132 if (handleErrorReplies(response) == NotHandled) {
133 if (response.content.size() >= 4) {
134 if (d->serverCapability == Annotatemore && response.content[1].toString() == "ANNOTATION") {
135 QString mailBox = QString::fromUtf8(KIMAP::decodeImapFolderName(response.content[2].toString()));
136
137 int i = 3;
138 while (i < response.content.size() - 1) {
139 QByteArray entry = response.content[i].toString();
140 QList<QByteArray> attributes = response.content[i + 1].toList();
141 int j = 0;
142 while (j < attributes.size() - 1) {
143 d->metadata[mailBox][entry][attributes[j]] = attributes[j + 1];
144 j += 2;
145 }
146 i += 2;
147 }
148 } else if (d->serverCapability == Metadata && response.content[1].toString() == "METADATA") {
149 QString mailBox = QString::fromUtf8(KIMAP::decodeImapFolderName(response.content[2].toString()));
150
151 const QList<QByteArray> &entries = response.content[3].toList();
152 int i = 0;
153 while (i < entries.size() - 1) {
154 const QByteArray &value = entries[i + 1];
155 QByteArray &targetValue = d->metadata[mailBox][entries[i]][""];
156 if (value != "NIL") { // This just indicates no value
157 targetValue = value;
158 }
159 i += 2;
160 }
161 }
162 }
163 }
164}
165
166void GetMetaDataJob::addEntry(const QByteArray &entry, const QByteArray &attribute)
167{
169 if (d->serverCapability == Annotatemore && attribute.isNull()) {
170 qCWarning(KIMAP_LOG) << "In ANNOTATEMORE mode an attribute must be specified with addEntry!";
171 }
172 d->entries.insert(entry);
173 d->attributes.insert(attribute);
174}
175
177{
179 d->entries.insert(d->removePrefix(entry));
180 d->attributes.insert(d->getAttribute(entry));
181}
182
184{
186 d->maxSize = size;
187}
188
190{
192
193 switch (depth) {
194 case OneLevel:
195 d->depth = "1"; // krazy:exclude=doublequote_chars
196 break;
197 case AllLevels:
198 d->depth = "infinity";
199 break;
200 default:
201 d->depth = "0"; // krazy:exclude=doublequote_chars
202 }
203}
204
205QByteArray GetMetaDataJob::metaData(const QString &mailBox, const QByteArray &entry, const QByteArray &attribute) const
206{
207 Q_D(const GetMetaDataJob);
208 QByteArray attr = attribute;
209
210 if (d->serverCapability == Metadata) {
211 attr = "";
212 }
213
215 if (d->metadata.contains(mailBox)) {
216 if (d->metadata[mailBox].contains(entry)) {
217 result = d->metadata[mailBox][entry].value(attr);
218 }
219 }
220 return result;
221}
222
224{
225 qCDebug(KIMAP_LOG) << entry;
226 Q_D(const GetMetaDataJob);
227 return d->metadata.value(d->mailBox).value(d->removePrefix(entry)).value(d->getAttribute(entry));
228}
229
231{
232 Q_D(const GetMetaDataJob);
233 return d->metadata[mailBox];
234}
235
241
243{
244 Q_D(const GetMetaDataJob);
245 const QMap<QByteArray, QMap<QByteArray, QByteArray>> &entries = d->metadata[mailbox];
247 const auto entriesKeys = entries.keys();
248 for (const QByteArray &entry : entriesKeys) {
249 const QMap<QByteArray, QByteArray> &values = entries[entry];
250 const auto valuesKeys = values.keys();
251 for (const QByteArray &attribute : valuesKeys) {
252 map.insert(d->addPrefix(entry, attribute), values[attribute]);
253 }
254 }
255 return map;
256}
257
259{
260 Q_D(const GetMetaDataJob);
262
264 while (i.hasNext()) {
265 i.next();
266 mailboxHash.insert(i.key(), allMetaDataForMailbox(i.key()));
267 }
268 return mailboxHash;
269}
270
271#include "moc_getmetadatajob.cpp"
Fetches mailbox metadata.
Depth
Used to specify the depth of the metadata hierarchy to walk.
@ AllLevels
The requested entries and all their descendants.
@ OneLevel
The requested entries and all their direct children.
QMap< QByteArray, QByteArray > allMetaDataForMailbox(const QString &mailbox) const
Get all the metadata for the mailbox.
KIMAP_DEPRECATED void addEntry(const QByteArray &entry, const QByteArray &attribute=QByteArray())
Add an entry to the query list.
void addRequestedEntry(const QByteArray &entry)
Add an entry to the query list.
void setDepth(Depth depth)
Sets whether to retrieve children or descendants of the requested entries.
QHash< QString, QMap< QByteArray, QByteArray > > allMetaDataForMailboxes() const
Get all the metadata for for all mailboxes.
void setMaximumSize(qint64 size)
Limits the size of returned metadata entries.
KIMAP_DEPRECATED QByteArray metaData(const QString &mailBox, const QByteArray &entry, const QByteArray &attribute=QByteArray()) const
Get a single metadata entry.
QMap< QByteArray, QByteArray > allMetaData() const
Get all the metadata for the mailbox set with setMailBox().
Base class for jobs that operate on mailbox metadata.
QString mailBox() const
The mailbox that will be acted upon.
@ Annotatemore
Used to indicate that the server supports the draft-daboo-imap-annotatemore-07 version of the extensi...
@ Metadata
Used to indicate that the server supports the RFC 5464 version of the extension.
void result(KJob *job)
QString i18n(const char *text, const TYPE &arg...)
QString name(StandardShortcut id)
void chop(qsizetype n)
bool isEmpty() const const
bool isNull() const const
qsizetype length() const const
QByteArray number(double n, char format, int precision)
iterator insert(const Key &key, const T &value)
QList< T > toList() const const
iterator begin()
iterator end()
qsizetype size() const const
QList< Key > keys() const const
bool hasNext() const const
const Key & key() const const
QList< T > values() const const
QString fromUtf8(QByteArrayView str)
This file is part of the IMAP support library and defines the RfcCodecs class.
KIMAP_EXPORT QByteArray encodeImapFolderName(const QByteArray &src)
Converts an Unicode IMAP mailbox to a QByteArray which can be used in IMAP communication.
Q_D(Todo)
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Tue Mar 26 2024 11:14:37 by doxygen 1.10.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.