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 fd61d58ab8..011d4c0e2a 100644 --- a/src/add-ons/mail_daemon/inbound_protocols/imap/IMAPConnectionWorker.cpp +++ b/src/add-ons/mail_daemon/inbound_protocols/imap/IMAPConnectionWorker.cpp @@ -215,8 +215,7 @@ public: return status; fState = FETCH_ENTRIES; -// fFirstUID = fLastUID = fFolder->LastUID(); - fFirstUID = fLastUID = 0; + fFirstUID = fLastUID = fFolder->LastUID() + 1; fMailboxEntries = 0; } 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 0739f20ea6..e7a0f4b766 100644 --- a/src/add-ons/mail_daemon/inbound_protocols/imap/IMAPFolder.cpp +++ b/src/add-ons/mail_daemon/inbound_protocols/imap/IMAPFolder.cpp @@ -23,6 +23,7 @@ static const char* kMailboxNameAttribute = "IMAP:mailbox"; static const char* kUIDValidityAttribute = "IMAP:uidvalidity"; +static const char* kLastUIDAttribute = "IMAP:lastuid"; static const char* kStateAttribute = "IMAP:state"; static const char* kFlagsAttribute = "IMAP:flags"; static const char* kUIDAttribute = "MAIL:unique_id"; @@ -88,22 +89,23 @@ IMAPFolder::IMAPFolder(IMAPProtocol& protocol, const BString& mailboxName, fProtocol(protocol), fRef(ref), fMailboxName(mailboxName), - fUIDValidity(UINT32_MAX) + fUIDValidity(UINT32_MAX), + fLastUID(0) { // Initialize from folder attributes BNode node(&ref); if (node.InitCheck() != B_OK) return; - if (node.ReadAttrString(kMailboxNameAttribute, &fMailboxName) != B_OK) - return; + BString originalMailboxName; + if (node.ReadAttrString(kMailboxNameAttribute, &originalMailboxName) == B_OK + && originalMailboxName != mailboxName) { + // TODO: mailbox name has changed + } - uint32 uidValidity; - if (node.ReadAttr(kUIDValidityAttribute, B_UINT32_TYPE, 0, &uidValidity, - sizeof(uint32)) != sizeof(uint32)) - return; - - fUIDValidity = B_BENDIAN_TO_HOST_INT32(uidValidity); + fUIDValidity = _ReadUInt32(node, kUIDValidityAttribute); + fLastUID = _ReadUInt32(node, kLastUIDAttribute); + printf("IMAP: %s, last UID %lu\n", fMailboxName.String(), fLastUID); attr_info info; status_t status = node.GetAttrInfo(kStateAttribute, &info); @@ -135,7 +137,7 @@ IMAPFolder::IMAPFolder(IMAPProtocol& protocol, const BString& mailboxName, // Initialize current state from actual folder // TODO: this should be done in another thread - _InitializeFolderState(); + //_InitializeFolderState(); } @@ -154,7 +156,13 @@ IMAPFolder::SetListener(FolderListener* listener) void IMAPFolder::SetUIDValidity(uint32 uidValidity) { + if (fUIDValidity == uidValidity) + return; + fUIDValidity = uidValidity; + + BNode node(&fRef); + _WriteUInt32(node, kUIDValidityAttribute, uidValidity); } @@ -216,8 +224,18 @@ IMAPFolder::MessageStored(entry_ref& ref, BFile& file, uint32 fetchFlags, // TODO: the call below may move/rename the file fProtocol.MessageStored(ref, file, fetchFlags); - file.Unset(); + + if (uid > fLastUID) { + // Update last known UID + fLastUID = uid; + + BNode directory(&fRef); + status_t status = _WriteUInt32(directory, kLastUIDAttribute, uid); + if (status != B_OK) + fprintf(stderr, "IMAP: Could not write last UID for mailbox " + "%s: %s\n", fMailboxName.String(), strerror(status)); + } } @@ -323,16 +341,35 @@ IMAPFolder::_WriteUniqueID(BNode& node, uint32 uid) uint32 IMAPFolder::_ReadFlags(BNode& node) { - // TODO! - return 0; + return _ReadUInt32(node, kFlagsAttribute); } status_t IMAPFolder::_WriteFlags(BNode& node, uint32 flags) { - ssize_t bytesWritten = node.WriteAttr(kFlagsAttribute, B_UINT32_TYPE, 0, - &flags, sizeof(uint32)); + return _WriteUInt32(node, kFlagsAttribute, flags); +} + + +uint32 +IMAPFolder::_ReadUInt32(BNode& node, const char* attribute) +{ + uint32 value; + ssize_t bytesRead = node.ReadAttr(attribute, B_UINT32_TYPE, 0, + &value, sizeof(uint32)); + if (bytesRead == (ssize_t)sizeof(uint32)) + return value; + + return 0; +} + + +status_t +IMAPFolder::_WriteUInt32(BNode& node, const char* attribute, uint32 value) +{ + ssize_t bytesWritten = node.WriteAttr(attribute, B_UINT32_TYPE, 0, + &value, sizeof(uint32)); if (bytesWritten == (ssize_t)sizeof(uint32)) return B_OK; 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 1da9e82292..6c9100e127 100644 --- a/src/add-ons/mail_daemon/inbound_protocols/imap/IMAPFolder.h +++ b/src/add-ons/mail_daemon/inbound_protocols/imap/IMAPFolder.h @@ -49,6 +49,8 @@ public: void SetListener(FolderListener* listener); void SetUIDValidity(uint32 uidValidity); + uint32 LastUID() const { return fLastUID; } + status_t StoreMessage(BFile& file, uint32 fetchFlags, BDataIO& stream, size_t& length, entry_ref& ref); @@ -69,6 +71,10 @@ private: uint32 _ReadFlags(BNode& node); status_t _WriteFlags(BNode& node, uint32 flags); + uint32 _ReadUInt32(BNode& node, const char* attribute); + status_t _WriteUInt32(BNode& node, + const char* attribute, uint32 value); + private: typedef std::hash_map UIDToFlagsMap; typedef std::hash_map UIDToRefMap; @@ -77,6 +83,7 @@ private: const entry_ref fRef; BString fMailboxName; uint32 fUIDValidity; + uint32 fLastUID; FolderListener* fListener; UIDToRefMap fRefMap; UIDToFlagsMap fUIDMap;