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
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{
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{
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{
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{
167 d->entryName = entry;
168}
169
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.
Sets mailbox metadata.
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(StandardShortcut 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
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-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.