diff --git a/src/add-ons/mail_daemon/inbound_protocols/imap/IMAPConnectionWorker.cpp b/src/add-ons/mail_daemon/inbound_protocols/imap/IMAPConnectionWorker.cpp index 76869ac1d2..5f986a84ea 100644 --- a/src/add-ons/mail_daemon/inbound_protocols/imap/IMAPConnectionWorker.cpp +++ b/src/add-ons/mail_daemon/inbound_protocols/imap/IMAPConnectionWorker.cpp @@ -370,8 +370,7 @@ public: fTotalBytes += entries[i].size; fUIDsToFetch.push_back(entries[i].uid); } else { - fFolder->UpdateMessageFlags(entries[i].uid, - entries[i].flags); + fFolder->SyncMessageFlags(entries[i].uid, entries[i].flags); } } @@ -379,6 +378,8 @@ public: fLastIndex = from - 1; if (from == 1) { + fFolder->MessageEntriesFetched(); + if (fUIDsToFetch.size() > 0) { // Add pending command to fetch the message headers WorkerCommand* command = new FetchHeadersCommand(*fFolder, diff --git a/src/add-ons/mail_daemon/inbound_protocols/imap/IMAPFolder.cpp b/src/add-ons/mail_daemon/inbound_protocols/imap/IMAPFolder.cpp index 0ae442d9a7..6d45284304 100644 --- a/src/add-ons/mail_daemon/inbound_protocols/imap/IMAPFolder.cpp +++ b/src/add-ons/mail_daemon/inbound_protocols/imap/IMAPFolder.cpp @@ -178,6 +178,7 @@ IMAPFolder::SetUIDValidity(uint32 uidValidity) if (fUIDValidity == uidValidity) return; + // TODO: delete all mails that have the same UID validity value we had fUIDValidity = uidValidity; BNode node(&fRef); @@ -221,8 +222,11 @@ IMAPFolder::MessageFlags(uint32 uid) } +/*! Synchronizes the message flags/state from the server with the local + one. +*/ void -IMAPFolder::UpdateMessageFlags(uint32 uid, uint32 mailboxFlags) +IMAPFolder::SyncMessageFlags(uint32 uid, uint32 mailboxFlags) { if (uid > LastUID()) return; @@ -233,7 +237,8 @@ IMAPFolder::UpdateMessageFlags(uint32 uid, uint32 mailboxFlags) while (true) { status_t status = GetMessageEntryRef(uid, ref); if (status == B_ENTRY_NOT_FOUND) { - // The message does not exist anymore locally, delete it on the server + // The message does not exist anymore locally, delete it on the + // server // TODO: copy it to the trash directory first! fProtocol.UpdateMessageFlags(*this, uid, IMAP::kDeleted); return; @@ -247,6 +252,7 @@ IMAPFolder::UpdateMessageFlags(uint32 uid, uint32 mailboxFlags) break; } + fSynchronizedUIDsSet.insert(uid); uint32 previousFlags = MessageFlags(uid); uint32 currentFlags = previousFlags; @@ -279,6 +285,21 @@ IMAPFolder::UpdateMessageFlags(uint32 uid, uint32 mailboxFlags) } +void +IMAPFolder::MessageEntriesFetched() +{ + // Delete all local messages that weren't synchronized with the server + UIDToRefMap::const_iterator iterator = fRefMap.begin(); + for (; iterator != fRefMap.end(); iterator++) { + uint32 uid = iterator->first; + if (fSynchronizedUIDsSet.find(uid) == fSynchronizedUIDsSet.end()) + _DeleteLocalMessage(uid); + } + + fSynchronizedUIDsSet.clear(); +} + + /*! Stores the given \a stream into a temporary file using the provided BFile object. A new file will be created, and the \a ref object will point to it. The file will remain open when this method exits without @@ -416,6 +437,9 @@ IMAPFolder::StoringBodyFailed(const entry_ref& ref, uint32 uid, status_t error) void IMAPFolder::DeleteMessage(uint32 uid) { + // TODO: move message to trash (server side) + + _DeleteLocalMessage(uid); } @@ -471,7 +495,6 @@ IMAPFolder::_InitializeFolderState() // _WriteUniqueID(node, uid); // } // - fRefMap.insert(std::make_pair(uid, ref)); } fInitializing = false; @@ -519,6 +542,22 @@ IMAPFolder::_GetMessageEntryRef(uint32 uid, entry_ref& ref) const } +status_t +IMAPFolder::_DeleteLocalMessage(uint32 uid) +{ + entry_ref ref; + status_t status = GetMessageEntryRef(uid, ref); + if (status != B_OK) + return status; + + fRefMap.erase(uid); + fFlagsMap.erase(uid); + + BEntry entry(&ref); + return entry.Remove(); +} + + void IMAPFolder::_IMAPToMailFlags(uint32 flags, BMessage& attributes) { diff --git a/src/add-ons/mail_daemon/inbound_protocols/imap/IMAPFolder.h b/src/add-ons/mail_daemon/inbound_protocols/imap/IMAPFolder.h index 3ffa96e079..f976ca694d 100644 --- a/src/add-ons/mail_daemon/inbound_protocols/imap/IMAPFolder.h +++ b/src/add-ons/mail_daemon/inbound_protocols/imap/IMAPFolder.h @@ -7,6 +7,8 @@ #include +#include + #include #include @@ -69,8 +71,9 @@ public: uint32& uid) const; uint32 MessageFlags(uint32 uid); - void UpdateMessageFlags(uint32 uid, + void SyncMessageFlags(uint32 uid, uint32 mailboxFlags); + void MessageEntriesFetched(); status_t StoreMessage(uint32 fetchFlags, BDataIO& stream, size_t& length, entry_ref& ref, @@ -101,6 +104,7 @@ private: uint32 uid, status_t status); status_t _GetMessageEntryRef(uint32 uid, entry_ref& ref) const; + status_t _DeleteLocalMessage(uint32 uid); void _IMAPToMailFlags(uint32 flags, BMessage& attributes); @@ -130,10 +134,12 @@ private: typedef __gnu_cxx::hash_map UIDToFlagsMap; typedef __gnu_cxx::hash_map UIDToRefMap; typedef __gnu_cxx::hash_map MessengerMap; + typedef __gnu_cxx::hash_set UIDSet; #else typedef std::hash_map UIDToFlagsMap; typedef std::hash_map UIDToRefMap; typedef std::hash_map MessengerMap; + typedef std::hash_set UIDSet; #endif IMAPProtocol& fProtocol; @@ -147,6 +153,7 @@ private: bool fInitializing; UIDToRefMap fRefMap; UIDToFlagsMap fFlagsMap; + UIDSet fSynchronizedUIDsSet; MessengerMap fPendingBodies; };