summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChristian Mollekopf <chrigi_1@fastmail.fm>2016-06-02 14:39:51 +0200
committerChristian Mollekopf <chrigi_1@fastmail.fm>2016-06-02 14:39:51 +0200
commitfb5b40088817d420532f7330864e0570278f112e (patch)
treeed6c23eb14a0b93813737ef73ca1991cb4188590
parent4eb8b954655a4c6d89f8d9b2a558a50d0d7a6f67 (diff)
downloadsink-fb5b40088817d420532f7330864e0570278f112e.tar.gz
sink-fb5b40088817d420532f7330864e0570278f112e.zip
IMAP folder writeback
-rw-r--r--examples/imapresource/imapresource.cpp213
1 files changed, 125 insertions, 88 deletions
diff --git a/examples/imapresource/imapresource.cpp b/examples/imapresource/imapresource.cpp
index 2bb28e7..4122a69 100644
--- a/examples/imapresource/imapresource.cpp
+++ b/examples/imapresource/imapresource.cpp
@@ -320,6 +320,73 @@ public:
320 QByteArray mResourceInstanceIdentifier; 320 QByteArray mResourceInstanceIdentifier;
321}; 321};
322 322
323class ImapWriteback : public Sink::SourceWriteBack
324{
325public:
326 ImapWriteback(const QByteArray &resourceType, const QByteArray &resourceInstanceIdentifier) : Sink::SourceWriteBack(resourceType, resourceInstanceIdentifier)
327 {
328
329 }
330
331 KAsync::Job<QByteArray> replay(const ApplicationDomain::Mail &mail, Sink::Operation operation, const QByteArray &oldRemoteId)
332 {
333 return KAsync::null<QByteArray>();
334 }
335
336 QString buildPath(const ApplicationDomain::Folder &folder)
337 {
338 //Don't use entityStore in here, it can produce wrong results we're replaying an older revision than the latest one
339 QChar separator = '/';
340 QString path;
341 auto parent = folder.getParent();
342 if (!parent.isEmpty()) {
343 auto parentRemoteId = syncStore().resolveLocalId("folder", parent);
344 return parentRemoteId + separator.toLatin1() + folder.getName().toUtf8();
345 }
346 return separator + folder.getName();
347 }
348
349 KAsync::Job<QByteArray> replay(const ApplicationDomain::Folder &folder, Sink::Operation operation, const QByteArray &oldRemoteId)
350 {
351 auto imap = QSharedPointer<ImapServerProxy>::create(mServer, mPort);
352 auto login = imap->login(mUser, mPassword);
353 if (operation == Sink::Operation_Creation) {
354 auto folderPath = buildPath(folder);
355 auto imapPath = "INBOX" + folderPath.replace('/', '.');
356 Trace() << "Creating a new folder: " << imapPath;
357 return login.then<void>(imap->create(imapPath))
358 .then<QByteArray>([imapPath, imap]() {
359 Trace() << "Finished creating a new folder: " << imapPath;
360 return imapPath.toUtf8();
361 });
362 } else if (operation == Sink::Operation_Removal) {
363 Trace() << "Removing a folder: " << oldRemoteId;
364 return login.then<void>(imap->remove(oldRemoteId))
365 .then<QByteArray>([oldRemoteId, imap]() {
366 Trace() << "Finished removing a folder: " << oldRemoteId;
367 return QByteArray();
368 });
369 } else if (operation == Sink::Operation_Modification) {
370 auto newFolderPath = buildPath(folder);
371 auto newImapPath = "INBOX" + newFolderPath.replace('/', '.');
372 Trace() << "Renaming a folder: " << oldRemoteId << newImapPath;
373 return login.then<void>(imap->rename(oldRemoteId, newImapPath))
374 .then<QByteArray>([newImapPath, imap]() {
375 Trace() << "Finished renaming a folder: " << newImapPath;
376 return newImapPath.toUtf8();
377 });
378 }
379 return KAsync::null<QByteArray>();
380 }
381
382public:
383 QString mServer;
384 int mPort;
385 QString mUser;
386 QString mPassword;
387 QByteArray mResourceInstanceIdentifier;
388};
389
323ImapResource::ImapResource(const QByteArray &instanceIdentifier, const QSharedPointer<Sink::Pipeline> &pipeline) 390ImapResource::ImapResource(const QByteArray &instanceIdentifier, const QSharedPointer<Sink::Pipeline> &pipeline)
324 : Sink::GenericResource(PLUGIN_NAME, instanceIdentifier, pipeline) 391 : Sink::GenericResource(PLUGIN_NAME, instanceIdentifier, pipeline)
325{ 392{
@@ -336,12 +403,11 @@ ImapResource::ImapResource(const QByteArray &instanceIdentifier, const QSharedPo
336 synchronizer->mPassword = mPassword; 403 synchronizer->mPassword = mPassword;
337 synchronizer->mResourceInstanceIdentifier = instanceIdentifier; 404 synchronizer->mResourceInstanceIdentifier = instanceIdentifier;
338 setupSynchronizer(synchronizer); 405 setupSynchronizer(synchronizer);
339 auto changereplay = QSharedPointer<Sink::NullChangeReplay>::create(instanceIdentifier); 406 auto changereplay = QSharedPointer<ImapWriteback>::create(PLUGIN_NAME, instanceIdentifier);
340 // auto changereplay = QSharedPointer<ImapWriteback>::create(PLUGIN_NAME, instanceIdentifier); 407 changereplay->mServer = mServer;
341 // changereplay->mServer = mServer; 408 changereplay->mPort = mPort;
342 // changereplay->mPort = mPort; 409 changereplay->mUser = mUser;
343 // changereplay->mUser = mUser; 410 changereplay->mPassword = mPassword;
344 // changereplay->mPassword = mPassword;
345 setupChangereplay(changereplay); 411 setupChangereplay(changereplay);
346 412
347 setupPreprocessors(ENTITY_TYPE_MAIL, QVector<Sink::Preprocessor*>() << new MailPropertyExtractor << new DefaultIndexUpdater<Sink::ApplicationDomain::Mail>); 413 setupPreprocessors(ENTITY_TYPE_MAIL, QVector<Sink::Preprocessor*>() << new MailPropertyExtractor << new DefaultIndexUpdater<Sink::ApplicationDomain::Mail>);
@@ -356,7 +422,7 @@ void ImapResource::removeFromDisk(const QByteArray &instanceIdentifier)
356 422
357KAsync::Job<void> ImapResource::inspect(int inspectionType, const QByteArray &inspectionId, const QByteArray &domainType, const QByteArray &entityId, const QByteArray &property, const QVariant &expectedValue) 423KAsync::Job<void> ImapResource::inspect(int inspectionType, const QByteArray &inspectionId, const QByteArray &domainType, const QByteArray &entityId, const QByteArray &property, const QVariant &expectedValue)
358{ 424{
359 auto synchronizationStore = QSharedPointer<Sink::Storage>::create(Sink::storageLocation(), mResourceInstanceIdentifier + ".synchronization", Sink::Storage::ReadOnly); 425 auto synchronizationStore = QSharedPointer<Sink::Storage>::create(Sink::storageLocation(), mResourceInstanceIdentifier + ".synchronization", Sink::Storage::ReadOnly);
360 auto synchronizationTransaction = synchronizationStore->createTransaction(Sink::Storage::ReadOnly); 426 auto synchronizationTransaction = synchronizationStore->createTransaction(Sink::Storage::ReadOnly);
361 427
362 auto mainStore = QSharedPointer<Sink::Storage>::create(Sink::storageLocation(), mResourceInstanceIdentifier, Sink::Storage::ReadOnly); 428 auto mainStore = QSharedPointer<Sink::Storage>::create(Sink::storageLocation(), mResourceInstanceIdentifier, Sink::Storage::ReadOnly);
@@ -367,87 +433,58 @@ KAsync::Job<void> ImapResource::inspect(int inspectionType, const QByteArray &in
367 433
368 Trace() << "Inspecting " << inspectionType << domainType << entityId << property << expectedValue; 434 Trace() << "Inspecting " << inspectionType << domainType << entityId << property << expectedValue;
369 435
370 // if (domainType == ENTITY_TYPE_MAIL) { 436 if (domainType == ENTITY_TYPE_MAIL) {
371 // const auto mail = entityStore->read<Sink::ApplicationDomain::Mail>(entityId); 437 const auto mail = entityStore->read<Sink::ApplicationDomain::Mail>(entityId);
372 // const auto folder = entityStore->read<Sink::ApplicationDomain::Folder>(mail.getFolder()); 438 const auto folder = entityStore->read<Sink::ApplicationDomain::Folder>(mail.getFolder());
373 // const auto folderRemoteId = syncStore->resolveLocalId(ENTITY_TYPE_FOLDER, mail.getFolder()); 439 const auto folderRemoteId = syncStore->resolveLocalId(ENTITY_TYPE_FOLDER, mail.getFolder());
374 // const auto mailRemoteId = syncStore->resolveLocalId(ENTITY_TYPE_MAIL, mail.identifier()); 440 const auto mailRemoteId = syncStore->resolveLocalId(ENTITY_TYPE_MAIL, mail.identifier());
375 // // const auto filePath = getFilePathFromMimeMessagePath(mail.getMimeMessagePath()); 441 if (mailRemoteId.isEmpty() || folderRemoteId.isEmpty()) {
376 // ImapServerProxy imap(mServer, mPort); 442 KAsync::error<void>();
377 // imap.login(mUser, mPassword).exec().waitForFinished(); 443 }
378 // imap.select(folderRemoteId).exec().waitForFinished(); 444 Trace() << "Mail remote id: " << folderRemoteId << mailRemoteId << mail.identifier() << folder.identifier();
379 // KIMAP::ImapSet set; 445
380 // set.add(mailRemoteId.toLongLong()); 446 if (inspectionType == Sink::ResourceControl::Inspection::PropertyInspectionType) {
381 // KIMAP::FetchJob::FetchScope scope; 447 if (property == "unread") {
382 // scope.mode = KIMAP::FetchJob::FetchScope::Full; 448 return KAsync::null<void>();
383 // imap.fetch(set, scope, [](const QVector<Imap::Message> &messages) { 449 }
384 // 450 if (property == "subject") {
385 // }).exec().waitForFinished(); 451 return KAsync::null<void>();
386 // 452 }
387 // if (inspectionType == Sink::ResourceControl::Inspection::PropertyInspectionType) { 453 }
388 // if (property == "unread") { 454 if (inspectionType == Sink::ResourceControl::Inspection::ExistenceInspectionType) {
389 // // const auto flags = KPIM::Maildir::readEntryFlags(filePath.split('/').last()); 455 }
390 // // if (expectedValue.toBool() && (flags & KPIM::Maildir::Seen)) { 456 }
391 // // return KAsync::error<void>(1, "Expected unread but couldn't find it."); 457 if (domainType == ENTITY_TYPE_FOLDER) {
392 // // } 458 const auto remoteId = syncStore->resolveLocalId(ENTITY_TYPE_FOLDER, entityId);
393 // // if (!expectedValue.toBool() && !(flags & KPIM::Maildir::Seen)) { 459 const auto folder = entityStore->read<Sink::ApplicationDomain::Folder>(entityId);
394 // // return KAsync::error<void>(1, "Expected read but couldn't find it."); 460
395 // // } 461 if (inspectionType == Sink::ResourceControl::Inspection::CacheIntegrityInspectionType) {
396 // return KAsync::null<void>(); 462 }
397 // } 463 if (inspectionType == Sink::ResourceControl::Inspection::ExistenceInspectionType) {
398 // if (property == "subject") { 464 auto folderByPath = QSharedPointer<QSet<QString>>::create();
399 // // KMime::Message *msg = new KMime::Message; 465 auto folderByName = QSharedPointer<QSet<QString>>::create();
400 // // msg->setHead(KMime::CRLFtoLF(KPIM::Maildir::readEntryHeadersFromFile(filePath))); 466
401 // // msg->parse(); 467 auto imap = QSharedPointer<ImapServerProxy>::create(mServer, mPort);
402 // // 468 auto inspectionJob = imap->login(mUser, mPassword)
403 // // if (msg->subject(true)->asUnicodeString() != expectedValue.toString()) { 469 .then<void>(imap->fetchFolders([=](const QVector<Imap::Folder> &folders) {
404 // // return KAsync::error<void>(1, "Subject not as expected: " + msg->subject(true)->asUnicodeString()); 470 for (const auto &f : folders) {
405 // // } 471 *folderByPath << f.normalizedPath();
406 // return KAsync::null<void>(); 472 *folderByName << f.pathParts.last();
407 // } 473 }
408 // } 474 }))
409 // if (inspectionType == Sink::ResourceControl::Inspection::ExistenceInspectionType) { 475 .then<void, KAsync::Job<void>>([folderByName, folderByPath, folder, remoteId, imap]() {
410 // // if (QFileInfo(filePath).exists() != expectedValue.toBool()) { 476 if (!folderByName->contains(folder.getName())) {
411 // // return KAsync::error<void>(1, "Wrong file existence: " + filePath); 477 Warning() << "Existing folders are: " << *folderByPath;
412 // // } 478 Warning() << "We're looking for: " << folder.getName();
413 // } 479 return KAsync::error<void>(1, "Wrong folder name: " + remoteId);
414 // } 480 }
415 // if (domainType == ENTITY_TYPE_FOLDER) { 481 return KAsync::null<void>();
416 // const auto remoteId = syncStore->resolveLocalId(ENTITY_TYPE_FOLDER, entityId); 482 });
417 // const auto folder = entityStore->read<Sink::ApplicationDomain::Folder>(entityId); 483
418 // 484 return inspectionJob;
419 // if (inspectionType == Sink::ResourceControl::Inspection::CacheIntegrityInspectionType) { 485 }
420 // // Warning() << "Inspecting cache integrity" << remoteId; 486
421 // // if (!QDir(remoteId).exists()) { 487 }
422 // // return KAsync::error<void>(1, "The directory is not existing: " + remoteId);
423 // // }
424 // //
425 // // int expectedCount = 0;
426 // // Index index("mail.index.folder", transaction);
427 // // index.lookup(entityId, [&](const QByteArray &sinkId) {
428 // // expectedCount++;
429 // // },
430 // // [&](const Index::Error &error) {
431 // // Warning() << "Error in index: " << error.message << property;
432 // // });
433 // //
434 // // QDir dir(remoteId + "/cur");
435 // // const QFileInfoList list = dir.entryInfoList(QDir::Files);
436 // // if (list.size() != expectedCount) {
437 // // return KAsync::error<void>(1, QString("Wrong number of files; found %1 instead of %2.").arg(list.size()).arg(expectedCount));
438 // // }
439 // // if (inspectionType == Sink::ResourceControl::Inspection::ExistenceInspectionType) {
440 // // if (!remoteId.endsWith(folder.getName().toUtf8())) {
441 // // return KAsync::error<void>(1, "Wrong folder name: " + remoteId);
442 // // }
443 // // //TODO we shouldn't use the remoteId here to figure out the path, it could be gone/changed already
444 // // if (QDir(remoteId).exists() != expectedValue.toBool()) {
445 // // return KAsync::error<void>(1, "Wrong folder existence: " + remoteId);
446 // // }
447 // // }
448 // }
449 //
450 // }
451 return KAsync::null<void>(); 488 return KAsync::null<void>();
452} 489}
453 490