summaryrefslogtreecommitdiffstats
path: root/examples/maildirresource/maildirresource.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'examples/maildirresource/maildirresource.cpp')
-rw-r--r--examples/maildirresource/maildirresource.cpp105
1 files changed, 72 insertions, 33 deletions
diff --git a/examples/maildirresource/maildirresource.cpp b/examples/maildirresource/maildirresource.cpp
index 42da667..6dc9990 100644
--- a/examples/maildirresource/maildirresource.cpp
+++ b/examples/maildirresource/maildirresource.cpp
@@ -49,6 +49,22 @@
49#undef DEBUG_AREA 49#undef DEBUG_AREA
50#define DEBUG_AREA "resource.maildir" 50#define DEBUG_AREA "resource.maildir"
51 51
52static QString getFilePathFromMimeMessagePath(const QString &mimeMessagePath)
53{
54 auto parts = mimeMessagePath.split('/');
55 const auto key = parts.takeLast();
56 const auto path = parts.join("/") + "/cur/";
57
58 QDir dir(path);
59 const QFileInfoList list = dir.entryInfoList(QStringList() << (key+"*"), QDir::Files);
60 if (list.size() != 1) {
61 Warning() << "Failed to find message " << mimeMessagePath;
62 Warning() << "Failed to find message " << path;
63 return QString();
64 }
65 return list.first().filePath();
66}
67
52class FolderUpdater : public Sink::Preprocessor 68class FolderUpdater : public Sink::Preprocessor
53{ 69{
54public: 70public:
@@ -76,7 +92,7 @@ public:
76 }); 92 });
77 return folderPath; 93 return folderPath;
78 } 94 }
79 95
80 QString moveMessage(const QString &oldPath, const QByteArray &folder, Sink::Storage::Transaction &transaction) 96 QString moveMessage(const QString &oldPath, const QByteArray &folder, Sink::Storage::Transaction &transaction)
81 { 97 {
82 if (oldPath.startsWith(Sink::temporaryFileLocation())) { 98 if (oldPath.startsWith(Sink::temporaryFileLocation())) {
@@ -90,22 +106,13 @@ public:
90 } 106 }
91 return oldPath; 107 return oldPath;
92 } 108 }
109
93 void updatedIndexedProperties(Sink::ApplicationDomain::BufferAdaptor &newEntity) 110 void updatedIndexedProperties(Sink::ApplicationDomain::BufferAdaptor &newEntity)
94 { 111 {
95 const auto mimeMessagePath = newEntity.getProperty("mimeMessage").toString(); 112 const auto filePath = getFilePathFromMimeMessagePath(newEntity.getProperty("mimeMessage").toString());
96 auto parts = mimeMessagePath.split('/');
97 const auto key = parts.takeLast();
98 const auto path = parts.join("/") + "/cur/";
99
100 QDir dir(path);
101 const QFileInfoList list = dir.entryInfoList(QStringList() << (key+"*"), QDir::Files);
102 if (list.size() != 1) {
103 Warning() << "Failed to find message " << path << key << list.size();
104 return;
105 }
106 113
107 KMime::Message *msg = new KMime::Message; 114 KMime::Message *msg = new KMime::Message;
108 msg->setHead(KMime::CRLFtoLF(KPIM::Maildir::readEntryHeadersFromFile(list.first().filePath()))); 115 msg->setHead(KMime::CRLFtoLF(KPIM::Maildir::readEntryHeadersFromFile(filePath)));
109 msg->parse(); 116 msg->parse();
110 117
111 newEntity.setProperty("subject", msg->subject(true)->asUnicodeString()); 118 newEntity.setProperty("subject", msg->subject(true)->asUnicodeString());
@@ -408,15 +415,7 @@ KAsync::Job<void> MaildirResource::replay(Sink::Storage &synchronizationStore, c
408 } else if (type == ENTITY_TYPE_MAIL) { 415 } else if (type == ENTITY_TYPE_MAIL) {
409 if (operation == Sink::Operation_Creation) { 416 if (operation == Sink::Operation_Creation) {
410 const Sink::ApplicationDomain::Mail mail(mResourceInstanceIdentifier, Sink::Storage::uidFromKey(key), revision, mMailAdaptorFactory->createAdaptor(entity)); 417 const Sink::ApplicationDomain::Mail mail(mResourceInstanceIdentifier, Sink::Storage::uidFromKey(key), revision, mMailAdaptorFactory->createAdaptor(entity));
411 auto parentFolder = mail.getProperty("folder").toByteArray(); 418 const auto remoteId = getFilePathFromMimeMessagePath(mail.getMimeMessagePath());
412 QByteArray parentFolderRemoteId;
413 if (!parentFolder.isEmpty()) {
414 parentFolderRemoteId = resolveLocalId(ENTITY_TYPE_FOLDER, parentFolder, synchronizationTransaction);
415 } else {
416 parentFolderRemoteId = mMaildirPath.toUtf8();
417 }
418 const auto parentFolderPath = parentFolderRemoteId;
419 const auto remoteId = mail.getProperty("mimeMessage").toString().split('/').last();
420 Trace() << "Creating a new mail." << remoteId; 419 Trace() << "Creating a new mail." << remoteId;
421 if (remoteId.isEmpty()) { 420 if (remoteId.isEmpty()) {
422 Warning() << "Failed to create mail: " << remoteId; 421 Warning() << "Failed to create mail: " << remoteId;
@@ -436,11 +435,18 @@ KAsync::Job<void> MaildirResource::replay(Sink::Storage &synchronizationStore, c
436 const auto remoteId = resolveLocalId(ENTITY_TYPE_MAIL, uid, synchronizationTransaction); 435 const auto remoteId = resolveLocalId(ENTITY_TYPE_MAIL, uid, synchronizationTransaction);
437 Trace() << "Modifying a mail: " << remoteId; 436 Trace() << "Modifying a mail: " << remoteId;
438 437
439 const auto maildirPath = KPIM::Maildir::getDirectoryFromFile(remoteId); 438 const Sink::ApplicationDomain::Mail mail(mResourceInstanceIdentifier, Sink::Storage::uidFromKey(key), revision, mMailAdaptorFactory->createAdaptor(entity));
439
440 const auto filePath = getFilePathFromMimeMessagePath(mail.getMimeMessagePath());
441 const auto maildirPath = KPIM::Maildir::getDirectoryFromFile(filePath);
440 KPIM::Maildir maildir(maildirPath, false); 442 KPIM::Maildir maildir(maildirPath, false);
441 443
442 const Sink::ApplicationDomain::Mail mail(mResourceInstanceIdentifier, Sink::Storage::uidFromKey(key), revision, mMailAdaptorFactory->createAdaptor(entity)); 444 const auto messagePathParts = filePath.split("/");
443 auto newIdentifier = mail.getMimeMessagePath().split("/").last(); 445 if (messagePathParts.isEmpty()) {
446 Warning() << "No message path available: " << remoteId;
447 return KAsync::error<void>(1, "No message path available.");
448 }
449 const auto newIdentifier = messagePathParts.last();
444 QString identifier; 450 QString identifier;
445 if (newIdentifier != KPIM::Maildir::getKeyFromFile(remoteId)) { 451 if (newIdentifier != KPIM::Maildir::getKeyFromFile(remoteId)) {
446 //Remove the old mime message if it changed 452 //Remove the old mime message if it changed
@@ -449,6 +455,7 @@ KAsync::Job<void> MaildirResource::replay(Sink::Storage &synchronizationStore, c
449 identifier = newIdentifier; 455 identifier = newIdentifier;
450 } else { 456 } else {
451 //The identifier needs to contain the flags for changeEntryFlags to work 457 //The identifier needs to contain the flags for changeEntryFlags to work
458 Q_ASSERT(!remoteId.split('/').isEmpty());
452 identifier = remoteId.split('/').last(); 459 identifier = remoteId.split('/').last();
453 } 460 }
454 461
@@ -480,12 +487,23 @@ KAsync::Job<void> MaildirResource::inspect(int inspectionType, const QByteArray
480{ 487{
481 auto synchronizationStore = QSharedPointer<Sink::Storage>::create(Sink::storageLocation(), mResourceInstanceIdentifier + ".synchronization", Sink::Storage::ReadOnly); 488 auto synchronizationStore = QSharedPointer<Sink::Storage>::create(Sink::storageLocation(), mResourceInstanceIdentifier + ".synchronization", Sink::Storage::ReadOnly);
482 auto synchronizationTransaction = synchronizationStore->createTransaction(Sink::Storage::ReadOnly); 489 auto synchronizationTransaction = synchronizationStore->createTransaction(Sink::Storage::ReadOnly);
490
491 auto mainStore = QSharedPointer<Sink::Storage>::create(Sink::storageLocation(), mResourceInstanceIdentifier, Sink::Storage::ReadOnly);
492 auto transaction = mainStore->createTransaction(Sink::Storage::ReadOnly);
493
483 Trace() << "Inspecting " << inspectionType << domainType << entityId << property << expectedValue; 494 Trace() << "Inspecting " << inspectionType << domainType << entityId << property << expectedValue;
495
484 if (domainType == ENTITY_TYPE_MAIL) { 496 if (domainType == ENTITY_TYPE_MAIL) {
497 auto mainDatabase = Sink::Storage::mainDatabase(transaction, ENTITY_TYPE_MAIL);
498 auto bufferAdaptor = getLatest(mainDatabase, entityId, *mMailAdaptorFactory);
499 Q_ASSERT(bufferAdaptor);
500
501 const Sink::ApplicationDomain::Mail mail(mResourceInstanceIdentifier, entityId, 0, bufferAdaptor);
502 const auto filePath = getFilePathFromMimeMessagePath(mail.getMimeMessagePath());
503
485 if (inspectionType == Sink::ResourceControl::Inspection::PropertyInspectionType) { 504 if (inspectionType == Sink::ResourceControl::Inspection::PropertyInspectionType) {
486 if (property == "unread") { 505 if (property == "unread") {
487 const auto remoteId = resolveLocalId(ENTITY_TYPE_MAIL, entityId, synchronizationTransaction); 506 const auto flags = KPIM::Maildir::readEntryFlags(filePath.split('/').last());
488 const auto flags = KPIM::Maildir::readEntryFlags(remoteId.split('/').last());
489 if (expectedValue.toBool() && (flags & KPIM::Maildir::Seen)) { 507 if (expectedValue.toBool() && (flags & KPIM::Maildir::Seen)) {
490 return KAsync::error<void>(1, "Expected unread but couldn't find it."); 508 return KAsync::error<void>(1, "Expected unread but couldn't find it.");
491 } 509 }
@@ -495,10 +513,8 @@ KAsync::Job<void> MaildirResource::inspect(int inspectionType, const QByteArray
495 return KAsync::null<void>(); 513 return KAsync::null<void>();
496 } 514 }
497 if (property == "subject") { 515 if (property == "subject") {
498 const auto remoteId = resolveLocalId(ENTITY_TYPE_MAIL, entityId, synchronizationTransaction);
499
500 KMime::Message *msg = new KMime::Message; 516 KMime::Message *msg = new KMime::Message;
501 msg->setHead(KMime::CRLFtoLF(KPIM::Maildir::readEntryHeadersFromFile(remoteId))); 517 msg->setHead(KMime::CRLFtoLF(KPIM::Maildir::readEntryHeadersFromFile(filePath)));
502 msg->parse(); 518 msg->parse();
503 519
504 if (msg->subject(true)->asUnicodeString() != expectedValue.toString()) { 520 if (msg->subject(true)->asUnicodeString() != expectedValue.toString()) {
@@ -508,9 +524,32 @@ KAsync::Job<void> MaildirResource::inspect(int inspectionType, const QByteArray
508 } 524 }
509 } 525 }
510 if (inspectionType == Sink::ResourceControl::Inspection::ExistenceInspectionType) { 526 if (inspectionType == Sink::ResourceControl::Inspection::ExistenceInspectionType) {
511 const auto remoteId = resolveLocalId(ENTITY_TYPE_MAIL, entityId, synchronizationTransaction); 527 if (QFileInfo(filePath).exists() != expectedValue.toBool()) {
512 if (QFileInfo(remoteId).exists() != expectedValue.toBool()) { 528 return KAsync::error<void>(1, "Wrong file existence: " + filePath);
513 return KAsync::error<void>(1, "Wrong file existence: " + remoteId); 529 }
530 }
531 }
532 if (domainType == ENTITY_TYPE_FOLDER) {
533 const auto remoteId = resolveLocalId(ENTITY_TYPE_FOLDER, entityId, synchronizationTransaction);
534
535 if (inspectionType == Sink::ResourceControl::Inspection::CacheIntegrityInspectionType) {
536 if (!QDir(remoteId).exists()) {
537 return KAsync::error<void>(1, "The directory is not existing: " + remoteId);
538 }
539
540 int expectedCount = 0;
541 Index index("mail.index.folder", transaction);
542 index.lookup(entityId, [&](const QByteArray &sinkId) {
543 expectedCount++;
544 },
545 [&](const Index::Error &error) {
546 Warning() << "Error in index: " << error.message << property;
547 });
548
549 QDir dir(remoteId + "/cur");
550 const QFileInfoList list = dir.entryInfoList(QDir::Files);
551 if (list.size() != expectedCount) {
552 return KAsync::error<void>(1, QString("Wrong number of files; found %1 instead of %2.").arg(list.size()).arg(expectedCount));
514 } 553 }
515 } 554 }
516 } 555 }