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

0001 /*
0002     SPDX-FileCopyrightText: 2009 Kevin Ottens <ervin@kde.org>
0003 
0004     SPDX-License-Identifier: LGPL-2.0-or-later
0005 */
0006 
0007 #include "storejob.h"
0008 
0009 #include "kimap_debug.h"
0010 #include <KLocalizedString>
0011 
0012 #include "job_p.h"
0013 #include "response_p.h"
0014 #include "session_p.h"
0015 
0016 namespace KIMAP
0017 {
0018 class StoreJobPrivate : public JobPrivate
0019 {
0020 public:
0021     StoreJobPrivate(Session *session, const QString &name)
0022         : JobPrivate(session, name)
0023         , uidBased(false)
0024     {
0025     }
0026     ~StoreJobPrivate()
0027     {
0028     }
0029 
0030     QByteArray addFlags(const QByteArray &param, const MessageFlags &flags)
0031     {
0032         QByteArray parameters;
0033         switch (mode) {
0034         case StoreJob::SetFlags:
0035             parameters += param;
0036             break;
0037         case StoreJob::AppendFlags:
0038             parameters += "+" + param;
0039             break;
0040         case StoreJob::RemoveFlags:
0041             parameters += "-" + param;
0042             break;
0043         }
0044 
0045         parameters += " (";
0046         for (const QByteArray &flag : flags) {
0047             parameters += flag + ' ';
0048         }
0049         if (!flags.isEmpty()) {
0050             parameters.chop(1);
0051         }
0052         parameters += ')';
0053 
0054         return parameters;
0055     }
0056 
0057     ImapSet set;
0058     bool uidBased;
0059     StoreJob::StoreMode mode;
0060     MessageFlags flags;
0061     MessageFlags gmLabels;
0062 
0063     QMap<int, MessageFlags> resultingFlags;
0064 };
0065 }
0066 
0067 using namespace KIMAP;
0068 
0069 StoreJob::StoreJob(Session *session)
0070     : Job(*new StoreJobPrivate(session, i18n("Store")))
0071 {
0072     Q_D(StoreJob);
0073     d->uidBased = false;
0074     d->mode = SetFlags;
0075 }
0076 
0077 StoreJob::~StoreJob()
0078 {
0079 }
0080 
0081 void StoreJob::setSequenceSet(const ImapSet &set)
0082 {
0083     Q_D(StoreJob);
0084     d->set = set;
0085 }
0086 
0087 ImapSet StoreJob::sequenceSet() const
0088 {
0089     Q_D(const StoreJob);
0090     return d->set;
0091 }
0092 
0093 void StoreJob::setUidBased(bool uidBased)
0094 {
0095     Q_D(StoreJob);
0096     d->uidBased = uidBased;
0097 }
0098 
0099 bool StoreJob::isUidBased() const
0100 {
0101     Q_D(const StoreJob);
0102     return d->uidBased;
0103 }
0104 
0105 void StoreJob::setFlags(const MessageFlags &flags)
0106 {
0107     Q_D(StoreJob);
0108     d->flags = flags;
0109 }
0110 
0111 MessageFlags StoreJob::flags() const
0112 {
0113     Q_D(const StoreJob);
0114     return d->flags;
0115 }
0116 
0117 void StoreJob::setGMLabels(const MessageFlags &gmLabels)
0118 {
0119     Q_D(StoreJob);
0120     d->gmLabels = gmLabels;
0121 }
0122 
0123 MessageFlags StoreJob::gmLabels() const
0124 {
0125     Q_D(const StoreJob);
0126     return d->gmLabels;
0127 }
0128 
0129 void StoreJob::setMode(StoreMode mode)
0130 {
0131     Q_D(StoreJob);
0132     d->mode = mode;
0133 }
0134 
0135 StoreJob::StoreMode StoreJob::mode() const
0136 {
0137     Q_D(const StoreJob);
0138     return d->mode;
0139 }
0140 
0141 QMap<int, MessageFlags> StoreJob::resultingFlags() const
0142 {
0143     Q_D(const StoreJob);
0144     return d->resultingFlags;
0145 }
0146 
0147 void StoreJob::doStart()
0148 {
0149     Q_D(StoreJob);
0150 
0151     if (d->set.isEmpty()) {
0152         qCWarning(KIMAP_LOG) << "Empty uid set passed to store job";
0153         setError(KJob::UserDefinedError);
0154         setErrorText(QStringLiteral("Empty uid set passed to store job"));
0155         emitResult();
0156         return;
0157     }
0158 
0159     d->set.optimize();
0160     QByteArray parameters = d->set.toImapSequenceSet() + ' ';
0161 
0162     if (!d->flags.isEmpty()) {
0163         parameters += d->addFlags("FLAGS", d->flags);
0164     }
0165     if (!d->gmLabels.isEmpty()) {
0166         if (!d->flags.isEmpty()) {
0167             parameters += ' ';
0168         }
0169         parameters += d->addFlags("X-GM-LABELS", d->gmLabels);
0170     }
0171 
0172     qCDebug(KIMAP_LOG) << parameters;
0173 
0174     QByteArray command = "STORE";
0175     if (d->uidBased) {
0176         command = "UID " + command;
0177     }
0178 
0179     d->tags << d->sessionInternal()->sendCommand(command, parameters);
0180 }
0181 
0182 void StoreJob::handleResponse(const Response &response)
0183 {
0184     Q_D(StoreJob);
0185 
0186     if (handleErrorReplies(response) == NotHandled) {
0187         if (response.content.size() == 4 && response.content[2].toString() == "FETCH" && response.content[3].type() == Response::Part::List) {
0188             int id = response.content[1].toString().toInt();
0189             qint64 uid = 0;
0190             bool uidFound = false;
0191             QList<QByteArray> resultingFlags;
0192 
0193             QList<QByteArray> content = response.content[3].toList();
0194 
0195             for (QList<QByteArray>::ConstIterator it = content.constBegin(); it != content.constEnd(); ++it) {
0196                 QByteArray str = *it;
0197                 ++it;
0198 
0199                 if (str == "FLAGS") {
0200                     if ((*it).startsWith('(') && (*it).endsWith(')')) {
0201                         QByteArray str = *it;
0202                         str.chop(1);
0203                         str.remove(0, 1);
0204                         resultingFlags = str.split(' ');
0205                     } else {
0206                         resultingFlags << *it;
0207                     }
0208                 } else if (str == "UID") {
0209                     uid = it->toLongLong(&uidFound);
0210                 }
0211             }
0212 
0213             if (!d->uidBased) {
0214                 d->resultingFlags[id] = resultingFlags;
0215             } else if (uidFound) {
0216                 d->resultingFlags[uid] = resultingFlags;
0217             } else {
0218                 qCWarning(KIMAP_LOG) << "We asked for UID but the server didn't give it back, resultingFlags not stored.";
0219             }
0220         }
0221     }
0222 }
0223 
0224 #include "moc_storejob.cpp"