KIMAP

setmetadatajob.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 "setmetadatajob.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 SetMetaDataJobPrivate : public MetaDataJobBasePrivate
20{
21public:
22 SetMetaDataJobPrivate(Session *session, const QString &name)
23 : MetaDataJobBasePrivate(session, name)
24 , metaDataErrors({})
25 , maxAcceptedSize(-1)
26 {
27 }
28 ~SetMetaDataJobPrivate()
29 {
30 }
31
32 QMap<QByteArray, QByteArray> entries;
34 QByteArray entryName;
35 SetMetaDataJob::MetaDataErrors metaDataErrors;
36 qint64 maxAcceptedSize;
37};
38}
39
40using namespace KIMAP;
41
42SetMetaDataJob::SetMetaDataJob(Session *session)
43 : MetaDataJobBase(*new SetMetaDataJobPrivate(session, i18n("SetMetaData")))
44{
45}
46
47SetMetaDataJob::~SetMetaDataJob()
48{
49}
50
51void SetMetaDataJob::doStart()
52{
53 Q_D(SetMetaDataJob);
54 QByteArray parameters = '\"' + KIMAP::encodeImapFolderName(d->mailBox.toUtf8()) + "\" ";
55 d->entriesIt = d->entries.constBegin();
56
57 QByteArray command = "SETMETADATA";
58 bool bSimpleData = true;
59
60 if (d->serverCapability == Annotatemore) {
61 command = "SETANNOTATION";
62 parameters += '\"' + d->entryName + "\" ";
63 } else {
64 for (; d->entriesIt != d->entries.constEnd(); ++d->entriesIt) {
65 if (d->entriesIt.value().contains('\r') || d->entriesIt.value().contains('\n')) {
66 bSimpleData = false;
67 break;
68 }
69 }
70 d->entriesIt = d->entries.constBegin();
71 }
72
73 parameters += '(';
74 if (bSimpleData == true) {
75 for (; d->entriesIt != d->entries.constEnd(); ++d->entriesIt) {
76 parameters += '\"' + d->entriesIt.key() + "\" ";
77 if (d->entriesIt.value().isEmpty()) {
78 parameters += "NIL";
79 } else {
80 parameters += "\"" + d->entriesIt.value() + "\"";
81 }
82 parameters += " ";
83 }
84 parameters[parameters.length() - 1] = ')';
85 } else {
86 if (!d->entries.isEmpty()) {
87 parameters += '\"' + d->entriesIt.key() + "\"";
88 int size = d->entriesIt.value().size();
89 parameters += " {" + QByteArray::number(size == 0 ? 3 : size) + '}';
90 }
91 }
92
93 if (d->entries.isEmpty()) {
94 parameters += ')';
95 }
96
97 d->tags << d->sessionInternal()->sendCommand(command, parameters);
98 // qCDebug(KIMAP_LOG) << "SENT: " << command << " " << parameters;
99}
100
101void SetMetaDataJob::handleResponse(const Response &response)
102{
103 Q_D(SetMetaDataJob);
104
105 // TODO: Test if a server can really return more then one untagged NO response. If not, no need to OR the error codes
106 if (!response.content.isEmpty() && d->tags.contains(response.content.first().toString())) {
107 if (response.content[1].toString() == "NO") {
108 setError(UserDefinedError);
109 setErrorText(i18n("%1 failed, server replied: %2", d->m_name, QLatin1StringView(response.toString().constData())));
110 const QByteArray responseBa = response.content[2].toString();
111 if (responseBa == "[ANNOTATEMORE TOOMANY]" || responseBa == "[METADATA TOOMANY]") {
112 d->metaDataErrors |= TooMany;
113 } else if (responseBa == "[ANNOTATEMORE TOOBIG]" || responseBa.startsWith("[METADATA MAXSIZE")) { // krazy:exclude=strings
114 d->metaDataErrors |= TooBig;
115 d->maxAcceptedSize = -1;
116 if (responseBa.startsWith("[METADATA MAXSIZE")) { // krazy:exclude=strings
117 QByteArray max = responseBa;
118 max.replace("[METADATA MAXSIZE", ""); // krazy:exclude=doublequote_chars
119 max.replace("]", ""); // krazy:exclude=doublequote_chars
120 d->maxAcceptedSize = max.toLongLong();
121 }
122 } else if (responseBa == "[METADATA NOPRIVATE]") {
123 d->metaDataErrors |= NoPrivate;
124 }
125 } else if (response.content.size() < 2) {
126 setErrorText(i18n("%1 failed, malformed reply from the server.", d->m_name));
127 } else if (response.content[1].toString() != "OK") {
128 setError(UserDefinedError);
129 setErrorText(i18n("%1 failed, server replied: %2", d->m_name, QLatin1StringView(response.toString().constData())));
130 }
131 emitResult();
132 } else if (d->serverCapability == Metadata && response.content[0].toString() == "+") {
133 QByteArray content = "";
134 if (d->entriesIt.value().isEmpty()) {
135 content += "NIL";
136 } else {
137 content += d->entriesIt.value();
138 }
139 ++d->entriesIt;
140 if (d->entriesIt == d->entries.constEnd()) {
141 content += ')';
142 } else {
143 content += " \"" + d->entriesIt.key() + '\"';
144 int size = d->entriesIt.value().size();
145 content += " {" + QByteArray::number(size == 0 ? 3 : size) + '}';
146 }
147 // qCDebug(KIMAP_LOG) << "SENT: " << content;
148 d->sessionInternal()->sendData(content);
149 }
150}
151
152void SetMetaDataJob::addMetaData(const QByteArray &name, const QByteArray &value)
153{
154 Q_D(SetMetaDataJob);
155 if (d->serverCapability == Annotatemore && (name.startsWith("/shared") || name.startsWith("/private"))) {
156 const QByteArray &attribute = d->getAttribute(name);
157 d->entries[attribute] = value;
158 d->entryName = d->removePrefix(name);
159 } else {
160 d->entries[name] = value;
161 }
162}
163
165{
166 Q_D(SetMetaDataJob);
167 d->entryName = entry;
168}
169
170SetMetaDataJob::MetaDataErrors SetMetaDataJob::metaDataErrors() const
171{
172 Q_D(const SetMetaDataJob);
173 return d->metaDataErrors;
174}
175
176#include "moc_setmetadatajob.cpp"
Base class for jobs that operate on mailbox metadata.
@ 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.
MetaDataErrors metaDataErrors() const
The metadata errors received from the server.
void addMetaData(const QByteArray &name, const QByteArray &value)
Adds a metadata entry or attribute to the list of modifications to make.
KIMAP_DEPRECATED void setEntry(const QByteArray &entry)
Sets the metadata entry name to operate on (in Annotatemore mode)
@ NoPrivate
The server does not support private metadata entries.
@ TooBig
A metadata value was too big (see maxAcceptedSize())
@ TooMany
Cannot add a new metadata item, because the limit has already been reached.
void setErrorText(const QString &errorText)
void emitResult()
void setError(int errorCode)
QString i18n(const char *text, const TYPE &arg...)
QString name(StandardAction id)
const_iterator constBegin() const const
qsizetype length() const const
QByteArray number(double n, char format, int precision)
QByteArray & replace(QByteArrayView before, QByteArrayView after)
qsizetype size() const const
bool startsWith(QByteArrayView bv) const const
qlonglong toLongLong(bool *ok, int base) const const
typedef ConstIterator
bool startsWith(QChar c, Qt::CaseSensitivity cs) const const
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-2025 The KDE developers.
Generated on Fri Jan 31 2025 12:04:47 by doxygen 1.13.2 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.