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

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