File indexing completed on 2024-05-12 05:17:25

0001 /*
0002     Copyright (c) 2009 Andras Mantia <amantia@kde.org>
0003 
0004     This library is free software; you can redistribute it and/or modify it
0005     under the terms of the GNU Library General Public License as published by
0006     the Free Software Foundation; either version 2 of the License, or (at your
0007     option) any later version.
0008 
0009     This library is distributed in the hope that it will be useful, but WITHOUT
0010     ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
0011     FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Library General Public
0012     License for more details.
0013 
0014     You should have received a copy of the GNU Library General Public License
0015     along with this library; see the file COPYING.LIB.  If not, write to the
0016     Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
0017     02110-1301, USA.
0018 */
0019 
0020 #include "setmetadatajob.h"
0021 
0022 #include "kimap_debug.h"
0023 
0024 #include "metadatajobbase_p.h"
0025 #include "message_p.h"
0026 #include "session_p.h"
0027 #include "rfccodecs.h"
0028 
0029 namespace KIMAP2
0030 {
0031 class SetMetaDataJobPrivate : public MetaDataJobBasePrivate
0032 {
0033 public:
0034     SetMetaDataJobPrivate(Session *session, const QString &name) : MetaDataJobBasePrivate(session, name), metaDataErrors(Q_NULLPTR), maxAcceptedSize(-1) { }
0035     ~SetMetaDataJobPrivate() { }
0036 
0037     QMap<QByteArray, QByteArray> entries;
0038     QMap<QByteArray, QByteArray>::ConstIterator entriesIt;
0039     QByteArray entryName;
0040     SetMetaDataJob::MetaDataErrors metaDataErrors;
0041     qint64 maxAcceptedSize;
0042 };
0043 }
0044 
0045 using namespace KIMAP2;
0046 
0047 SetMetaDataJob::SetMetaDataJob(Session *session)
0048     : MetaDataJobBase(*new SetMetaDataJobPrivate(session, "SetMetaData"))
0049 {
0050 }
0051 
0052 SetMetaDataJob::~SetMetaDataJob()
0053 {
0054 }
0055 
0056 void SetMetaDataJob::doStart()
0057 {
0058     Q_D(SetMetaDataJob);
0059     QByteArray parameters;
0060     parameters = '\"' + KIMAP2::encodeImapFolderName(d->mailBox.toUtf8()) + "\" ";
0061     d->entriesIt = d->entries.constBegin();
0062 
0063     QByteArray command = "SETMETADATA";
0064     bool bSimpleData = true;
0065 
0066     if (d->serverCapability == Annotatemore) {
0067         command = "SETANNOTATION";
0068         parameters += '\"' + d->entryName + "\" ";
0069     } else {
0070         for (; d->entriesIt != d->entries.constEnd(); ++d->entriesIt) {
0071             if (d->entriesIt.value().contains('\r') || d->entriesIt.value().contains('\n')) {
0072                 bSimpleData = false;
0073                 break;
0074             }
0075         }
0076         d->entriesIt = d->entries.constBegin();
0077     }
0078 
0079     parameters += '(';
0080     if (bSimpleData == true) {
0081         for ( ; d->entriesIt != d->entries.constEnd(); ++d->entriesIt ) {
0082             parameters += '\"' + d->entriesIt.key() + "\" ";
0083             if (d->entriesIt.value().isEmpty()) {
0084                 parameters += "NIL";
0085             } else {
0086                 parameters +=  "\"" + d->entriesIt.value() + "\"";
0087             }
0088             parameters += " ";
0089 
0090         }
0091         parameters[parameters.length() - 1] = ')';
0092     } else {
0093         if (!d->entries.isEmpty()) {
0094             parameters += '\"' + d->entriesIt.key() + "\"";
0095             int size = d->entriesIt.value().size();
0096             parameters += " {" + QByteArray::number( size==0 ? 3 : size ) + '}';
0097         }
0098     }
0099 
0100     if (d->entries.isEmpty()) {
0101         parameters += ')';
0102     }
0103 
0104     d->sendCommand(command, parameters);
0105 //   qCDebug(KIMAP2_LOG) << "SENT: " << command << " " << parameters;
0106 }
0107 
0108 void SetMetaDataJob::handleResponse(const Message &response)
0109 {
0110     Q_D(SetMetaDataJob);
0111 
0112     //TODO: Test if a server can really return more then one untagged NO response. If not, no need to OR the error codes
0113     if (!response.content.isEmpty() &&
0114         d->tags.contains(response.content.first().toString())) {
0115         if (response.content[1].toString() == "NO") {
0116             setError(UserDefinedError);
0117             setErrorText(QString("%1 failed, server replied: %2").arg(d->m_name).arg(QLatin1String(response.toString().constData())));
0118             if (response.content[2].toString() == "[ANNOTATEMORE TOOMANY]" ||
0119                     response.content[2].toString() == "[METADATA TOOMANY]") {
0120                 d->metaDataErrors |= TooMany;
0121             } else if (response.content[2].toString() == "[ANNOTATEMORE TOOBIG]" ||
0122                        response.content[2].toString().startsWith("[METADATA MAXSIZE")) {    //krazy:exclude=strings
0123                 d->metaDataErrors |= TooBig;
0124                 d->maxAcceptedSize = -1;
0125                 if (response.content[2].toString().startsWith("[METADATA MAXSIZE")) {     //krazy:exclude=strings
0126                     QByteArray max = response.content[2].toString();
0127                     max.replace("[METADATA MAXSIZE", "");   //krazy:exclude=doublequote_chars
0128                     max.replace("]", "");                   //krazy:exclude=doublequote_chars
0129                     d->maxAcceptedSize = max.toLongLong();
0130                 }
0131             } else if (response.content[2].toString() == "[METADATA NOPRIVATE]") {
0132                 d->metaDataErrors |= NoPrivate;
0133             }
0134         } else if (response.content.size() < 2) {
0135             setErrorText(QString("%1 failed, malformed reply from the server.").arg(d->m_name));
0136         } else if (response.content[1].toString() != "OK") {
0137             setError(UserDefinedError);
0138             setErrorText(QString("%1 failed, server replied: %2").arg(d->m_name).arg(QLatin1String(response.toString().constData())));
0139         }
0140         emitResult();
0141     } else if (d->serverCapability == Metadata && response.content[0].toString() == "+") {
0142         QByteArray content = "";
0143         if (d->entriesIt.value().isEmpty()) {
0144             content += "NIL";
0145         } else {
0146             content +=  d->entriesIt.value();
0147         }
0148         ++d->entriesIt;
0149         if (d->entriesIt == d->entries.constEnd()) {
0150             content += ')';
0151         } else {
0152             content += " \"" + d->entriesIt.key() + '\"';
0153             int size = d->entriesIt.value().size();
0154             content += " {" + QByteArray::number( size==0 ? 3 : size ) + '}';
0155         }
0156 //      qCDebug(KIMAP2_LOG) << "SENT: " << content;
0157         d->sessionInternal()->sendData(content);
0158     }
0159 }
0160 
0161 void SetMetaDataJob::addMetaData(const QByteArray &name, const QByteArray &value)
0162 {
0163     Q_D(SetMetaDataJob);
0164     if (d->serverCapability == Annotatemore && (name.startsWith("/shared") || name.startsWith("/private"))) {
0165         const QByteArray &attribute = d->getAttribute(name);
0166         d->entries[attribute] = value;
0167         d->entryName = d->removePrefix(name);
0168     } else {
0169         d->entries[name] = value;
0170     }
0171 }
0172 
0173 void SetMetaDataJob::setEntry(const QByteArray &entry)
0174 {
0175     Q_D(SetMetaDataJob);
0176     d->entryName = entry;
0177 }
0178 
0179 SetMetaDataJob::MetaDataErrors SetMetaDataJob::metaDataErrors() const
0180 {
0181     Q_D(const SetMetaDataJob);
0182     return d->metaDataErrors;
0183 }