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"