File indexing completed on 2024-11-24 04:44:17

0001 /*
0002     SPDX-FileCopyrightText: 2014 Klarälvdalens Datakonsult AB, a KDAB Group company <info@kdab.com>
0003     SPDX-FileContributor: Kevin Krammer <kevin.krammer@kdab.com>
0004 
0005     SPDX-License-Identifier: LGPL-2.0-or-later
0006 */
0007 
0008 #include "kolabaddtagtask.h"
0009 #include "../imap/uidnextattribute.h"
0010 #include "kolabresource_debug.h"
0011 
0012 #include "pimkolab/kolabformat/kolabobject.h"
0013 
0014 #include <KIMAP/AppendJob>
0015 #include <KIMAP/ImapSet>
0016 #include <KIMAP/SearchJob>
0017 #include <KIMAP/SelectJob>
0018 #include <KIMAP/Session>
0019 
0020 #include <KLocalizedString>
0021 
0022 KolabAddTagTask::KolabAddTagTask(const ResourceStateInterface::Ptr &resource, QObject *parent)
0023     : KolabRelationResourceTask(resource, parent)
0024 {
0025 }
0026 
0027 void KolabAddTagTask::startRelationTask(KIMAP::Session *session)
0028 {
0029     qCDebug(KOLABRESOURCE_LOG) << "converted tag";
0030 
0031     const QLatin1StringView productId("Akonadi-Kolab-Resource");
0032     const KMime::Message::Ptr message = Kolab::KolabObjectWriter::writeTag(resourceState()->tag(), QStringList(), Kolab::KolabV3, productId);
0033     mMessageId = message->messageID()->asUnicodeString().toUtf8();
0034 
0035     auto job = new KIMAP::AppendJob(session);
0036     job->setMailBox(mailBoxForCollection(relationCollection()));
0037     job->setContent(message->encodedContent(true));
0038     job->setInternalDate(message->date()->dateTime());
0039     connect(job, &KJob::result, this, &KolabAddTagTask::onAppendMessageDone);
0040     job->start();
0041 }
0042 
0043 void KolabAddTagTask::applyFoundUid(qint64 uid)
0044 {
0045     Akonadi::Tag tag = resourceState()->tag();
0046 
0047     // If we failed to get the remoteid the tag remains local only
0048     if (uid > 0) {
0049         tag.setRemoteId(QByteArray::number(uid));
0050     }
0051 
0052     qCDebug(KOLABRESOURCE_LOG) << "committing new tag";
0053     changeCommitted(tag);
0054 
0055     Akonadi::Collection c = relationCollection();
0056 
0057     // Get the current uid next value and store it
0058     UidNextAttribute *uidAttr = nullptr;
0059     int oldNextUid = 0;
0060     if (c.hasAttribute("uidnext")) {
0061         uidAttr = static_cast<UidNextAttribute *>(c.attribute("uidnext"));
0062         oldNextUid = uidAttr->uidNext();
0063     }
0064 
0065     // If the uid we just got back is the expected next one of the box
0066     // then update the property to the probable next uid to keep the cache in sync.
0067     // If not something happened in our back, so we don't update and a refetch will
0068     // happen at some point.
0069     if (uid == oldNextUid) {
0070         if (uidAttr == nullptr) {
0071             uidAttr = new UidNextAttribute(uid + 1);
0072             c.addAttribute(uidAttr);
0073         } else {
0074             uidAttr->setUidNext(uid + 1);
0075         }
0076 
0077         applyCollectionChanges(c);
0078     }
0079 }
0080 
0081 void KolabAddTagTask::triggerSearchJob(KIMAP::Session *session)
0082 {
0083     auto search = new KIMAP::SearchJob(session);
0084 
0085     search->setUidBased(true);
0086 
0087     if (!mMessageId.isEmpty()) {
0088         search->setTerm(KIMAP::Term(QStringLiteral("Message-ID"), QString::fromLatin1(mMessageId)));
0089     } else {
0090         auto uidNext = relationCollection().attribute<UidNextAttribute>();
0091         if (!uidNext) {
0092             cancelTask(i18n("Could not determine the UID for the newly created message on the server"));
0093             search->deleteLater();
0094             return;
0095         }
0096         KIMAP::ImapInterval interval(uidNext->uidNext());
0097 
0098         search->setTerm(KIMAP::Term(KIMAP::Term::And, {KIMAP::Term(KIMAP::Term::New), KIMAP::Term(KIMAP::Term::Uid, KIMAP::ImapSet(uidNext->uidNext(), 0))}));
0099     }
0100 
0101     connect(search, &KJob::result, this, &KolabAddTagTask::onSearchDone);
0102 
0103     search->start();
0104 }
0105 
0106 void KolabAddTagTask::onAppendMessageDone(KJob *job)
0107 {
0108     auto append = qobject_cast<KIMAP::AppendJob *>(job);
0109 
0110     if (append->error()) {
0111         qCWarning(KOLABRESOURCE_LOG) << append->errorString();
0112         cancelTask(append->errorString());
0113         return;
0114     }
0115 
0116     qint64 uid = append->uid();
0117     qCDebug(KOLABRESOURCE_LOG) << "appended message with uid: " << uid;
0118 
0119     if (uid > 0) {
0120         // We got it directly if UIDPLUS is supported...
0121         applyFoundUid(uid);
0122     } else {
0123         // ... otherwise prepare searching for the message
0124         KIMAP::Session *session = append->session();
0125         const QString mailBox = append->mailBox();
0126 
0127         if (session->selectedMailBox() != mailBox) {
0128             auto select = new KIMAP::SelectJob(session);
0129             select->setMailBox(mailBox);
0130 
0131             connect(select, &KJob::result, this, &KolabAddTagTask::onPreSearchSelectDone);
0132 
0133             select->start();
0134         } else {
0135             triggerSearchJob(session);
0136         }
0137     }
0138 }
0139 
0140 void KolabAddTagTask::onPreSearchSelectDone(KJob *job)
0141 {
0142     if (job->error()) {
0143         qCWarning(KOLABRESOURCE_LOG) << job->errorString();
0144         cancelTask(job->errorString());
0145     } else {
0146         auto select = static_cast<KIMAP::SelectJob *>(job);
0147         triggerSearchJob(select->session());
0148     }
0149 }
0150 
0151 void KolabAddTagTask::onSearchDone(KJob *job)
0152 {
0153     if (job->error()) {
0154         qCWarning(KOLABRESOURCE_LOG) << job->errorString();
0155         cancelTask(job->errorString());
0156         return;
0157     }
0158 
0159     auto search = static_cast<KIMAP::SearchJob *>(job);
0160 
0161     qint64 uid = 0;
0162     if (search->results().count() == 1) {
0163         uid = search->results().at(0);
0164     }
0165 
0166     applyFoundUid(uid);
0167 }
0168 
0169 #include "moc_kolabaddtagtask.cpp"