/* SPDX-FileCopyrightText: 2008 Ingo Klöcker SPDX-FileCopyrightText: 2009 Constantin Berzan SPDX-License-Identifier: LGPL-2.0-or-later */ #include "pepagent.h" #include "pepagent_debug.h" #include "pep-introspectadaptor.h" using namespace Akonadi; PEP_STATUS pEpAgent::messageToSend(::message* msg) { qDebug() << "pEp wants to send a message"; return PEP_STATUS_OK; } pEpAgent::pEpAgent(const QString &id) : ResourceBase(id) { Q_D(pEpAgent); PEP_STATUS status; QDBusConnection dbus = QDBusConnection::sessionBus(); const QString service = Akonadi::ServerManager::self()->agentServiceName(Akonadi::ServerManager::Agent, QStringLiteral("pEpAgent")); /* -------------- Starting the pEp Engine ------------------- */ status = ::init(&m_session, NULL, NULL, NULL); /* --------------------- Done ------------------------------- */ /* ------------- Extending DBus functions ------------------- */ m_pEpadaptor = new PepAdaptor(this); dbus.registerObject(QStringLiteral("/security/pep"), QStringLiteral("security.pep"), this); dbus.registerService(service); /* --------------------- Done ------------------------------- */ // pEp management m_syncThread = new pEpSyncThread(this); // This here is just bureaucracy: auto *collectionMonitor = new Akonadi::Monitor(this); collectionMonitor->setObjectName(QStringLiteral("pEpCollectionMonitor")); collectionMonitor->fetchCollection(true); collectionMonitor->ignoreSession(Akonadi::Session::defaultSession()); collectionMonitor->collectionFetchScope().setAncestorRetrieval(Akonadi::CollectionFetchScope::All); collectionMonitor->setMimeTypeMonitored(KMime::Message::mimeType()); connect(collectionMonitor, &Akonadi::Monitor::collectionAdded, this, &pEpAgent::mailCollectionAdded); connect(collectionMonitor, qOverload(&Akonadi::Monitor::collectionChanged), this, &pEpAgent::mailCollectionChanged); connect(collectionMonitor, &Akonadi::Monitor::collectionRemoved, this, &pEpAgent::mailCollectionRemoved); connect(Akonadi::AgentManager::self(), &Akonadi::AgentManager::instanceRemoved, this, &pEpAgent::slotInstanceRemoved); QTimer::singleShot(0, this, &pEpAgent::initializeCollections); mProgressCounter = 0; mProgressTimer = new QTimer(this); itemMonitor = new Akonadi::Monitor(this); itemMonitor->setObjectName(QStringLiteral("pEpItemMonitor")); itemMonitor->itemFetchScope().setFetchRemoteIdentification(true); itemMonitor->itemFetchScope().setAncestorRetrieval(Akonadi::ItemFetchScope::Parent); connect(itemMonitor, &Akonadi::Monitor::itemChanged, this, &pEpAgent::slotItemChanged); } void pEpAgent::initializeCollections() { qCDebug(PEPAGENT_LOG) << __FUNCTION__ << " Test"; qDebug() << __FUNCTION__ << " Test"; Akonadi::CollectionFetchJob *job = new Akonadi::CollectionFetchJob(Akonadi::Collection::root(), Akonadi::CollectionFetchJob::Recursive, this); job->fetchScope(); //.setContentMimeTypes({ QStringLiteral("multipart/encrypted") }); connect(job, &Akonadi::CollectionFetchJob::result, this, &pEpAgent::initialCollectionFetchingDone); } void pEpAgent::emitProgress(int p) { qCDebug(PEPAGENT_LOG) << __FUNCTION__ << " Test"; qDebug() << __FUNCTION__ << " Test"; if (p == 0) { mProgressTimer->stop(); Q_EMIT status(AgentBase::Idle, QString()); } mProgressCounter = p; Q_EMIT percent(p); } void pEpAgent::emitProgressMessage(const QString &message) { qCDebug(PEPAGENT_LOG) << __FUNCTION__ << " Test"; Q_EMIT status(AgentBase::Running, message); if (status() == AgentBase::Idle) { // If still idle after aborting, clear 'aborted' status. Q_EMIT status(AgentBase::Idle, i18n("Ready to dispatch messages.")); } } void pEpAgent::itemsReceiviedForFiltering(const Akonadi::Item::List &items) { qDebug() << __FUNCTION__ << " Test"; if (items.isEmpty()) { qCDebug(PEPAGENT_LOG) << "pEpAgent::itemsReceiviedForFiltering items is empty!"; return; } Akonadi::Item item = items.first(); if (!item.hasPayload()) { qCDebug(PEPAGENT_LOG) << "pEpAgent::itemsReceiviedForFiltering item has no payload!"; return; } QString resource = sender()->property("resource").toString(); const Akonadi::Pop3ResourceAttribute *pop3ResourceAttribute = item.attribute(); if (pop3ResourceAttribute) { resource = pop3ResourceAttribute->pop3AccountName(); } emitProgressMessage(i18n("Filtering in %1", Akonadi::AgentManager::self()->instance(resource).name())); emitProgress(++mProgressCounter); mProgressTimer->start(1000); } void pEpAgent::clearMessage() { } void pEpAgent::emitStatusReady() { if (status() == AgentBase::Idle) { // If still idle after aborting, clear 'aborted' status. Q_EMIT status(AgentBase::Idle, i18n("p≡p engine ready")); } } bool pEpAgent::isFilterableCollection(const Akonadi::Collection &collection) const { // TODO: Do this smarter if(QStringLiteral( "INBOX" ) == collection.name()) { qDebug() << __FUNCTION__ << "Found an INBOX folder"; return true; } if( QStringLiteral("inbox") == collection.name() ) { qDebug() << __FUNCTION__ << "Found an INBOX folder"; return true; } qDebug() << __FUNCTION__ << "Not yet supported folder name: " << collection.name(); return false; } void pEpAgent::scanCollection(const Akonadi::Collection &collection) { } void pEpAgent::initialCollectionFetchingDone(KJob *job) { qDebug() << __FUNCTION__ << " Test"; if (job->error()) { qDebug() << job->errorString(); return; } const auto fetchJob = qobject_cast(job); const auto pop3ResourceMap = MailCommon::Kernel::pop3ResourceTargetCollection(); const auto lstCols = fetchJob->collections(); for (const Akonadi::Collection &collection : lstCols) { // All the folders of all the accounts if(isFilterableCollection(collection)) { qDebug() << "Checking for keys in collection: " << collection.name(); changeRecorder()->setCollectionMonitored(collection, true); } } Q_EMIT status(AgentBase::Idle, i18n("Ready")); Q_EMIT percent(100); QTimer::singleShot(2000, this, &pEpAgent::clearMessage); } void pEpAgent::slotItemChanged(const Akonadi::Item &item) { qDebug() << __FUNCTION__ << " Test"; if (item.remoteId().isEmpty()) { return; } // now we have the remoteId itemMonitor->setItemMonitored(item, false); filterItem(item, item.parentCollection()); } void pEpAgent::filterItem(const Akonadi::Item &item, const Akonadi::Collection &collection) { qDebug() << __FUNCTION__; auto job = new Akonadi::ItemFetchJob(item); connect(job, &Akonadi::ItemFetchJob::itemsReceived, this, &pEpAgent::itemsReceiviedForFiltering); job->fetchScope().fetchFullPayload(); job->fetchScope().setAncestorRetrieval(Akonadi::ItemFetchScope::Parent); job->fetchScope().fetchAttribute(); job->setProperty("resource", collection.resource()); // TODO: Error handling? } void pEpAgent::mailCollectionRemoved(const Akonadi::Collection &collection) { qDebug() << __FUNCTION__; changeRecorder()->setCollectionMonitored(collection, false); } void pEpAgent::mailCollectionChanged(const Akonadi::Collection &collection) { qDebug() << __FUNCTION__; changeRecorder()->setCollectionMonitored(collection, isFilterableCollection(collection)); } void pEpAgent::mailCollectionAdded(const Akonadi::Collection &collection, const Akonadi::Collection &) { qDebug() << __FUNCTION__; if (isFilterableCollection(collection)) { changeRecorder()->setCollectionMonitored(collection, true); } } void pEpAgent::slotInstanceRemoved(const Akonadi::AgentInstance &instance) { qDebug() << __FUNCTION__; //m_filterManager->agentRemoved(instance.identifier()); } void pEpAgent::itemAdded(const Akonadi::Item &item, const Akonadi::Collection &collection) { qDebug() << __FUNCTION__; /* The monitor mimetype filter would override the collection filter, therefor we have to check * for the mimetype of the item here. */ if (item.mimeType() != KMime::Message::mimeType()) { return; } if (item.remoteId().isEmpty()) { itemMonitor->setItemMonitored(item); } else { qDebug() << __FUNCTION__ << ": Filter this\n"; filterItem(item, collection); } } void pEpAgent::configure(WId windowId) { qDebug() << __FUNCTION__ << "Test"; } void pEpAgent::retrieveCollections() { // TODO: Put information here, like person table content and so: Akonadi::Collection::List collections; Akonadi::Collection topLevel; topLevel.setName(identifier()); topLevel.setRemoteId(identifier()); topLevel.setParentCollection(Akonadi::Collection::root()); topLevel.setContentMimeTypes({Akonadi::Collection::mimeType()}); topLevel.setRights(Akonadi::Collection::ReadOnly); auto topLevelDisplayAttr = topLevel.attribute(Akonadi::Collection::AddIfMissing); topLevelDisplayAttr->setDisplayName(i18n("p≡p Engine")); topLevelDisplayAttr->setActiveIconName(QStringLiteral("akonadi-pep")); collections.push_back(topLevel); collectionsRetrieved(std::move(collections)); } int pEpAgent::decrypt_message(const QString &src, QString &dst, QStringList &keylist, int &flags) { qDebug() << "pEpAgent: Decrypting"; char *ms = src.toLatin1().data(); ::message *m = NULL; ::message *md = new_message(PEP_dir_incoming); stringlist_t *kl = new_stringlist(""); PEP_decrypt_flags_t fl = 0; bool might_be_pep = true; ::mime_decode_message( ms, src.toLatin1().size(), &m, &might_be_pep ); ::decrypt_message(m_session, m, &md, &kl, &fl); if(md) { ::mime_encode_message(md, true, &ms, true); } flags = fl; dst = QLatin1String(ms); keylist.clear(); while(kl) { keylist << QLatin1String(kl->value); kl = kl->next; } return 0; } AKONADI_RESOURCE_MAIN(pEpAgent) #include "moc_pepagent.cpp"