File indexing completed on 2024-05-12 05:17:17
0001 /* 0002 SPDX-FileCopyrightText: 2009 Andras Mantia <amantia@kde.org> 0003 0004 SPDX-License-Identifier: LGPL-2.0-or-later 0005 */ 0006 0007 #include "setmetadatajob.h" 0008 0009 #include "kimap_debug.h" 0010 #include <KLocalizedString> 0011 0012 #include "metadatajobbase_p.h" 0013 #include "response_p.h" 0014 #include "rfccodecs.h" 0015 #include "session_p.h" 0016 0017 namespace KIMAP 0018 { 0019 class SetMetaDataJobPrivate : public MetaDataJobBasePrivate 0020 { 0021 public: 0022 SetMetaDataJobPrivate(Session *session, const QString &name) 0023 : MetaDataJobBasePrivate(session, name) 0024 , metaDataErrors({}) 0025 , maxAcceptedSize(-1) 0026 { 0027 } 0028 ~SetMetaDataJobPrivate() 0029 { 0030 } 0031 0032 QMap<QByteArray, QByteArray> entries; 0033 QMap<QByteArray, QByteArray>::ConstIterator entriesIt; 0034 QByteArray entryName; 0035 SetMetaDataJob::MetaDataErrors metaDataErrors; 0036 qint64 maxAcceptedSize; 0037 }; 0038 } 0039 0040 using namespace KIMAP; 0041 0042 SetMetaDataJob::SetMetaDataJob(Session *session) 0043 : MetaDataJobBase(*new SetMetaDataJobPrivate(session, i18n("SetMetaData"))) 0044 { 0045 } 0046 0047 SetMetaDataJob::~SetMetaDataJob() 0048 { 0049 } 0050 0051 void SetMetaDataJob::doStart() 0052 { 0053 Q_D(SetMetaDataJob); 0054 QByteArray parameters = '\"' + KIMAP::encodeImapFolderName(d->mailBox.toUtf8()) + "\" "; 0055 d->entriesIt = d->entries.constBegin(); 0056 0057 QByteArray command = "SETMETADATA"; 0058 bool bSimpleData = true; 0059 0060 if (d->serverCapability == Annotatemore) { 0061 command = "SETANNOTATION"; 0062 parameters += '\"' + d->entryName + "\" "; 0063 } else { 0064 for (; d->entriesIt != d->entries.constEnd(); ++d->entriesIt) { 0065 if (d->entriesIt.value().contains('\r') || d->entriesIt.value().contains('\n')) { 0066 bSimpleData = false; 0067 break; 0068 } 0069 } 0070 d->entriesIt = d->entries.constBegin(); 0071 } 0072 0073 parameters += '('; 0074 if (bSimpleData == true) { 0075 for (; d->entriesIt != d->entries.constEnd(); ++d->entriesIt) { 0076 parameters += '\"' + d->entriesIt.key() + "\" "; 0077 if (d->entriesIt.value().isEmpty()) { 0078 parameters += "NIL"; 0079 } else { 0080 parameters += "\"" + d->entriesIt.value() + "\""; 0081 } 0082 parameters += " "; 0083 } 0084 parameters[parameters.length() - 1] = ')'; 0085 } else { 0086 if (!d->entries.isEmpty()) { 0087 parameters += '\"' + d->entriesIt.key() + "\""; 0088 int size = d->entriesIt.value().size(); 0089 parameters += " {" + QByteArray::number(size == 0 ? 3 : size) + '}'; 0090 } 0091 } 0092 0093 if (d->entries.isEmpty()) { 0094 parameters += ')'; 0095 } 0096 0097 d->tags << d->sessionInternal()->sendCommand(command, parameters); 0098 // qCDebug(KIMAP_LOG) << "SENT: " << command << " " << parameters; 0099 } 0100 0101 void SetMetaDataJob::handleResponse(const Response &response) 0102 { 0103 Q_D(SetMetaDataJob); 0104 0105 // TODO: Test if a server can really return more then one untagged NO response. If not, no need to OR the error codes 0106 if (!response.content.isEmpty() && d->tags.contains(response.content.first().toString())) { 0107 if (response.content[1].toString() == "NO") { 0108 setError(UserDefinedError); 0109 setErrorText(i18n("%1 failed, server replied: %2", d->m_name, QLatin1StringView(response.toString().constData()))); 0110 const QByteArray responseBa = response.content[2].toString(); 0111 if (responseBa == "[ANNOTATEMORE TOOMANY]" || responseBa == "[METADATA TOOMANY]") { 0112 d->metaDataErrors |= TooMany; 0113 } else if (responseBa == "[ANNOTATEMORE TOOBIG]" || responseBa.startsWith("[METADATA MAXSIZE")) { // krazy:exclude=strings 0114 d->metaDataErrors |= TooBig; 0115 d->maxAcceptedSize = -1; 0116 if (responseBa.startsWith("[METADATA MAXSIZE")) { // krazy:exclude=strings 0117 QByteArray max = responseBa; 0118 max.replace("[METADATA MAXSIZE", ""); // krazy:exclude=doublequote_chars 0119 max.replace("]", ""); // krazy:exclude=doublequote_chars 0120 d->maxAcceptedSize = max.toLongLong(); 0121 } 0122 } else if (responseBa == "[METADATA NOPRIVATE]") { 0123 d->metaDataErrors |= NoPrivate; 0124 } 0125 } else if (response.content.size() < 2) { 0126 setErrorText(i18n("%1 failed, malformed reply from the server.", d->m_name)); 0127 } else if (response.content[1].toString() != "OK") { 0128 setError(UserDefinedError); 0129 setErrorText(i18n("%1 failed, server replied: %2", d->m_name, QLatin1StringView(response.toString().constData()))); 0130 } 0131 emitResult(); 0132 } else if (d->serverCapability == Metadata && response.content[0].toString() == "+") { 0133 QByteArray content = ""; 0134 if (d->entriesIt.value().isEmpty()) { 0135 content += "NIL"; 0136 } else { 0137 content += d->entriesIt.value(); 0138 } 0139 ++d->entriesIt; 0140 if (d->entriesIt == d->entries.constEnd()) { 0141 content += ')'; 0142 } else { 0143 content += " \"" + d->entriesIt.key() + '\"'; 0144 int size = d->entriesIt.value().size(); 0145 content += " {" + QByteArray::number(size == 0 ? 3 : size) + '}'; 0146 } 0147 // qCDebug(KIMAP_LOG) << "SENT: " << content; 0148 d->sessionInternal()->sendData(content); 0149 } 0150 } 0151 0152 void SetMetaDataJob::addMetaData(const QByteArray &name, const QByteArray &value) 0153 { 0154 Q_D(SetMetaDataJob); 0155 if (d->serverCapability == Annotatemore && (name.startsWith("/shared") || name.startsWith("/private"))) { 0156 const QByteArray &attribute = d->getAttribute(name); 0157 d->entries[attribute] = value; 0158 d->entryName = d->removePrefix(name); 0159 } else { 0160 d->entries[name] = value; 0161 } 0162 } 0163 0164 void SetMetaDataJob::setEntry(const QByteArray &entry) 0165 { 0166 Q_D(SetMetaDataJob); 0167 d->entryName = entry; 0168 } 0169 0170 SetMetaDataJob::MetaDataErrors SetMetaDataJob::metaDataErrors() const 0171 { 0172 Q_D(const SetMetaDataJob); 0173 return d->metaDataErrors; 0174 } 0175 0176 #include "moc_setmetadatajob.cpp"