KIMAP

setmetadatajob.cpp
1 /*
2  SPDX-FileCopyrightText: 2009 Andras Mantia <[email protected]>
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 
17 namespace KIMAP
18 {
19 class SetMetaDataJobPrivate : public MetaDataJobBasePrivate
20 {
21 public:
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 
40 using namespace KIMAP;
41 
42 SetMetaDataJob::SetMetaDataJob(Session *session)
43  : MetaDataJobBase(*new SetMetaDataJobPrivate(session, i18n("SetMetaData")))
44 {
45 }
46 
47 SetMetaDataJob::~SetMetaDataJob()
48 {
49 }
50 
51 void 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 
101 void 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, QLatin1String(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, QLatin1String(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 
152 void 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"
KIMAP_EXPORT QString encodeImapFolderName(const QString &src)
Converts an Unicode IMAP mailbox to a QString which can be used in IMAP communication.
Definition: rfccodecs.cpp:180
void setErrorText(const QString &errorText)
QByteArray::const_iterator constBegin() const const
QByteArray number(int n, int base)
@ TooBig
A metadata value was too big (see maxAcceptedSize())
void addMetaData(const QByteArray &name, const QByteArray &value)
Adds a metadata entry or attribute to the list of modifications to make.
qlonglong toLongLong(bool *ok, int base) const const
QString::const_iterator constBegin() const const
QString i18n(const char *text, const TYPE &arg...)
@ NoPrivate
The server does not support private metadata entries.
Sets mailbox metadata.
bool startsWith(const QByteArray &ba) const const
@ Metadata
Used to indicate that the server supports the RFC 5464 version of the extension.
QByteArray & replace(int pos, int len, const char *after)
MetaDataErrors metaDataErrors() const
The metadata errors received from the server.
KIMAP_DEPRECATED void setEntry(const QByteArray &entry)
Sets the metadata entry name to operate on (in Annotatemore mode)
@ TooMany
Cannot add a new metadata item, because the limit has already been reached.
const char * name(StandardAction id)
@ Annotatemore
Used to indicate that the server supports the draft-daboo-imap-annotatemore-07 version of the extensi...
int size() const const
void emitResult()
int length() const const
Provides handlers for various RFC/MIME encodings.
void setError(int errorCode)
Q_D(Todo)
Base class for jobs that operate on mailbox metadata.
This file is part of the KDE documentation.
Documentation copyright © 1996-2023 The KDE developers.
Generated on Sun Dec 3 2023 03:51:44 by doxygen 1.8.17 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.