diff --git a/resources/imap/retrievecollectionmetadatatask.cpp b/resources/imap/retrievecollectionmetadatatask.cpp index 33b6536a6..e32ead158 100644 --- a/resources/imap/retrievecollectionmetadatatask.cpp +++ b/resources/imap/retrievecollectionmetadatatask.cpp @@ -1,293 +1,293 @@ /* Copyright (c) 2010 Klarälvdalens Datakonsult AB, a KDAB Group company Author: Kevin Ottens This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "retrievecollectionmetadatatask.h" #include #include #include #include #include #include #include #include #include "imapresource_debug.h" #include #include #include "collectionannotationsattribute.h" #include "imapaclattribute.h" #include "imapquotaattribute.h" #include "noselectattribute.h" #include "collectionmetadatahelper.h" #include "helper_p.h" RetrieveCollectionMetadataTask::RetrieveCollectionMetadataTask(const ResourceStateInterface::Ptr &resource, QObject *parent) : ResourceTask(CancelIfNoSession, resource, parent), m_pendingMetaDataJobs(0), m_session(nullptr) { } RetrieveCollectionMetadataTask::~RetrieveCollectionMetadataTask() { } void RetrieveCollectionMetadataTask::doStart(KIMAP::Session *session) { qCDebug(IMAPRESOURCE_LOG) << collection().remoteId(); // Prevent fetching metadata from noselect folders. if (collection().hasAttribute("noselect")) { NoSelectAttribute *noselect = static_cast(collection().attribute("noselect")); if (noselect->noSelect()) { qCDebug(IMAPRESOURCE_LOG) << "No Select folder"; endTaskIfNeeded(); return; } } m_session = session; m_collection = collection(); const QString mailBox = mailBoxForCollection(m_collection); const QStringList capabilities = serverCapabilities(); m_pendingMetaDataJobs = 0; // First get the annotations from the mailbox if it's supported if (capabilities.contains(QStringLiteral("METADATA")) || capabilities.contains(QStringLiteral("ANNOTATEMORE"))) { KIMAP::GetMetaDataJob *meta = new KIMAP::GetMetaDataJob(session); meta->setMailBox(mailBox); if (capabilities.contains(QStringLiteral("METADATA"))) { meta->setServerCapability(KIMAP::MetaDataJobBase::Metadata); meta->addRequestedEntry("/shared"); meta->setDepth(KIMAP::GetMetaDataJob::AllLevels); } else { meta->setServerCapability(KIMAP::MetaDataJobBase::Annotatemore); meta->addEntry("*", "value.shared"); } connect(meta, &KJob::result, this, &RetrieveCollectionMetadataTask::onGetMetaDataDone); m_pendingMetaDataJobs++; meta->start(); } // Get the ACLs from the mailbox if it's supported if (capabilities.contains(QStringLiteral("ACL"))) { KIMAP::MyRightsJob *rights = new KIMAP::MyRightsJob(session); rights->setMailBox(mailBox); connect(rights, &KJob::result, this, &RetrieveCollectionMetadataTask::onRightsReceived); m_pendingMetaDataJobs++; rights->start(); } // Get the QUOTA info from the mailbox if it's supported if (capabilities.contains(QStringLiteral("QUOTA"))) { KIMAP::GetQuotaRootJob *quota = new KIMAP::GetQuotaRootJob(session); quota->setMailBox(mailBox); connect(quota, &KJob::result, this, &RetrieveCollectionMetadataTask::onQuotasReceived); m_pendingMetaDataJobs++; quota->start(); } // the server does not have any of the capabilities needed to get extra info, so this // step is done here if (m_pendingMetaDataJobs == 0) { endTaskIfNeeded(); } } void RetrieveCollectionMetadataTask::onGetMetaDataDone(KJob *job) { m_pendingMetaDataJobs--; if (job->error()) { qCWarning(IMAPRESOURCE_LOG) << "Get metadata failed: " << job->errorString(); endTaskIfNeeded(); return; // Well, no metadata for us then... } KIMAP::GetMetaDataJob *meta = qobject_cast(job); QMap rawAnnotations = meta->allMetaData(); // filter out unused and annoying Cyrus annotation /vendor/cmu/cyrus-imapd/lastupdate // which contains the current date and time and thus constantly changes for no good // reason which triggers a change notification and thus a bunch of Akonadi operations rawAnnotations.remove("/shared/vendor/cmu/cyrus-imapd/lastupdate"); rawAnnotations.remove("/private/vendor/cmu/cyrus-imapd/lastupdate"); // Store the mailbox metadata Akonadi::CollectionAnnotationsAttribute *annotationsAttribute = m_collection.attribute(Akonadi::Collection::AddIfMissing); const QMap oldAnnotations = annotationsAttribute->annotations(); if (oldAnnotations != rawAnnotations) { annotationsAttribute->setAnnotations(rawAnnotations); } endTaskIfNeeded(); } void RetrieveCollectionMetadataTask::onGetAclDone(KJob *job) { m_pendingMetaDataJobs--; if (job->error()) { qCWarning(IMAPRESOURCE_LOG) << "GetACL failed: " << job->errorString(); endTaskIfNeeded(); return; // Well, no metadata for us then... } KIMAP::GetAclJob *acl = qobject_cast(job); // Store the mailbox ACLs Akonadi::ImapAclAttribute *const aclAttribute = m_collection.attribute(Akonadi::Collection::AddIfMissing); const QMap oldRights = aclAttribute->rights(); if (oldRights != acl->allRights()) { aclAttribute->setRights(acl->allRights()); } endTaskIfNeeded(); } void RetrieveCollectionMetadataTask::onRightsReceived(KJob *job) { m_pendingMetaDataJobs--; if (job->error()) { qCWarning(IMAPRESOURCE_LOG) << "MyRights failed: " << job->errorString(); endTaskIfNeeded(); return; // Well, no metadata for us then... } KIMAP::MyRightsJob *rightsJob = qobject_cast(job); const KIMAP::Acl::Rights imapRights = rightsJob->rights(); //Default value in case we have nothing better available KIMAP::Acl::Rights parentRights = KIMAP::Acl::CreateMailbox | KIMAP::Acl::Create; //FIXME I don't think we have the parent's acl's available if (collection().parentCollection().attribute()) { parentRights = myRights(collection().parentCollection()); } // qCDebug(IMAPRESOURCE_LOG) << collection.remoteId() // << "imapRights:" << imapRights // << "newRights:" << newRights // << "oldRights:" << collection.rights(); const bool isNewCollection = !m_collection.hasAttribute(); const bool accessRevoked = CollectionMetadataHelper::applyRights(m_collection, imapRights, parentRights); if (accessRevoked && !isNewCollection) { // write access revoked const QString collectionName = m_collection.displayName(); showInformationDialog(i18n("

Your access rights to folder %1 have been restricted, " "it will no longer be possible to add messages to this folder.

", collectionName), i18n("Access rights revoked"), QStringLiteral("ShowRightsRevokedWarning")); } // Store the mailbox ACLs Akonadi::ImapAclAttribute *aclAttribute = m_collection.attribute(Akonadi::Collection::AddIfMissing); const KIMAP::Acl::Rights oldRights = aclAttribute->myRights(); if (oldRights != imapRights) { aclAttribute->setMyRights(imapRights); } //The a right is required to list acl's if (imapRights & KIMAP::Acl::Admin) { KIMAP::GetAclJob *acl = new KIMAP::GetAclJob(m_session); acl->setMailBox(mailBoxForCollection(m_collection)); connect(acl, &KJob::result, this, &RetrieveCollectionMetadataTask::onGetAclDone); m_pendingMetaDataJobs++; acl->start(); } endTaskIfNeeded(); } void RetrieveCollectionMetadataTask::onQuotasReceived(KJob *job) { m_pendingMetaDataJobs--; + const QString &mailBox = mailBoxForCollection(m_collection); if (job->error()) { - qCWarning(IMAPRESOURCE_LOG) << "Quota retrieval failed: " << job->errorString(); + qCWarning(IMAPRESOURCE_LOG) << "Quota retrieval for mailbox " << mailBox << " failed: " << job->errorString(); endTaskIfNeeded(); return; // Well, no metadata for us then... } KIMAP::GetQuotaRootJob *quotaJob = qobject_cast(job); - const QString &mailBox = mailBoxForCollection(m_collection); QList newRoots = quotaJob->roots(); QList< QMap > newLimits; QList< QMap > newUsages; qint64 newCurrent = -1; qint64 newMax = -1; newLimits.reserve(newRoots.count()); newUsages.reserve(newRoots.count()); for (const QByteArray &root : qAsConst(newRoots)) { newLimits << quotaJob->allLimits(root); newUsages << quotaJob->allUsages(root); const QString &decodedRoot = QString::fromUtf8(KIMAP::decodeImapFolderName(root)); if (newRoots.size() == 1 || decodedRoot == mailBox) { newCurrent = newUsages.last()["STORAGE"] * 1024; newMax = newLimits.last()["STORAGE"] * 1024; } } // Store the mailbox IMAP Quotas Akonadi::ImapQuotaAttribute *imapQuotaAttribute = m_collection.attribute(Akonadi::Collection::AddIfMissing); const QList oldRoots = imapQuotaAttribute->roots(); const QList< QMap > oldLimits = imapQuotaAttribute->limits(); const QList< QMap > oldUsages = imapQuotaAttribute->usages(); if (oldRoots != newRoots || oldLimits != newLimits || oldUsages != newUsages) { imapQuotaAttribute->setQuotas(newRoots, newLimits, newUsages); } // Store the collection Quota Akonadi::CollectionQuotaAttribute *quotaAttribute = m_collection.attribute(Akonadi::Collection::AddIfMissing); qint64 oldCurrent = quotaAttribute->currentValue(); qint64 oldMax = quotaAttribute->maximumValue(); if (oldCurrent != newCurrent || oldMax != newMax) { quotaAttribute->setCurrentValue(newCurrent); quotaAttribute->setMaximumValue(newMax); } endTaskIfNeeded(); } void RetrieveCollectionMetadataTask::endTaskIfNeeded() { if (m_pendingMetaDataJobs <= 0) { collectionAttributesRetrieved(m_collection); } }