added 2 changesets to branch 'refs/remotes/axeld-github/imap' old head: 3f2007abb0fb6bf20163d2a464de5d9f611c82e9 new head: 7a4ef93c415a7727f645db790f2f2bfb3c827ff2 overview: https://github.com/axeld/haiku/compare/3f2007a...7a4ef93 ---------------------------------------------------------------------------- b39861a: IMAP: Use useful default without destination. * We now use the account name as destination directory. * Turns out that an empty string is written as destination which worked around the GetString() solution. 7a4ef93: IMAP: IMAPFolder now stores the last UID. * So mails are no longer downloaded every time. [ Axel Dörfler <axeld@xxxxxxxxxxxxxxxx> ] ---------------------------------------------------------------------------- 7 files changed, 76 insertions(+), 24 deletions(-) .../imap/FolderConfigWindow.cpp | 2 +- .../imap/IMAPConnectionWorker.cpp | 3 +- .../inbound_protocols/imap/IMAPFolder.cpp | 67 +++++++++++++++----- .../inbound_protocols/imap/IMAPFolder.h | 7 ++ .../inbound_protocols/imap/IMAPProtocol.cpp | 4 +- .../inbound_protocols/imap/Settings.cpp | 13 +++- .../inbound_protocols/imap/Settings.h | 4 +- ############################################################################ Commit: b39861a027dc4b9cf4fedbee3ec889d06c72dd75 Author: Axel Dörfler <axeld@xxxxxxxxxxxxxxxx> Date: Thu Apr 25 18:56:11 2013 UTC IMAP: Use useful default without destination. * We now use the account name as destination directory. * Turns out that an empty string is written as destination which worked around the GetString() solution. ---------------------------------------------------------------------------- diff --git a/src/add-ons/mail_daemon/inbound_protocols/imap/FolderConfigWindow.cpp b/src/add-ons/mail_daemon/inbound_protocols/imap/FolderConfigWindow.cpp index b16bc18..3147fb5 100644 --- a/src/add-ons/mail_daemon/inbound_protocols/imap/FolderConfigWindow.cpp +++ b/src/add-ons/mail_daemon/inbound_protocols/imap/FolderConfigWindow.cpp @@ -256,7 +256,7 @@ FolderConfigWindow::FolderConfigWindow(BRect parent, const BMessage& settings) BWindow(BRect(0, 0, 350, 350), B_TRANSLATE("IMAP Folders"), B_TITLED_WINDOW_LOOK, B_MODAL_APP_WINDOW_FEEL, B_NOT_ZOOMABLE | B_ASYNCHRONOUS_CONTROLS | B_AUTO_UPDATE_SIZE_LIMITS), - fSettings(settings) + fSettings("in", settings) { fQuotaView = new BStringView("quota view", B_TRANSLATE("Failed to fetch available storage.")); diff --git a/src/add-ons/mail_daemon/inbound_protocols/imap/IMAPProtocol.cpp b/src/add-ons/mail_daemon/inbound_protocols/imap/IMAPProtocol.cpp index e6da5f3..d6c98c4 100644 --- a/src/add-ons/mail_daemon/inbound_protocols/imap/IMAPProtocol.cpp +++ b/src/add-ons/mail_daemon/inbound_protocols/imap/IMAPProtocol.cpp @@ -16,14 +16,14 @@ IMAPProtocol::IMAPProtocol(const BMailAccountSettings& settings) : BInboundMailProtocol(settings), - fSettings(settings.InboundSettings()), + fSettings(settings.Name(), settings.InboundSettings()), fWorkers(5, false) { BPath destination = fSettings.Destination(); status_t status = create_directory(destination.Path(), 0755); if (status != B_OK) { - fprintf(stderr, "imap: Could not create destination directory %s: %s\n", + fprintf(stderr, "IMAP: Could not create destination directory %s: %s\n", destination.Path(), strerror(status)); } diff --git a/src/add-ons/mail_daemon/inbound_protocols/imap/Settings.cpp b/src/add-ons/mail_daemon/inbound_protocols/imap/Settings.cpp index 5c44c72..a5673ea 100644 --- a/src/add-ons/mail_daemon/inbound_protocols/imap/Settings.cpp +++ b/src/add-ons/mail_daemon/inbound_protocols/imap/Settings.cpp @@ -9,9 +9,10 @@ #include <crypt.h> -Settings::Settings(const BMessage& archive) +Settings::Settings(const char* accountName, const BMessage& archive) : - fMessage(archive) + fMessage(archive), + fAccountName(accountName) { } @@ -78,7 +79,13 @@ Settings::Password() const BPath Settings::Destination() const { - return BPath(fMessage.GetString("destination", "/boot/home/mail/in")); + BPath path(fMessage.FindString("destination")); + if (path.Path() == NULL) { + // Use default directory + path = "/boot/home/mail"; + path.Append(fAccountName.String()); + } + return path; } diff --git a/src/add-ons/mail_daemon/inbound_protocols/imap/Settings.h b/src/add-ons/mail_daemon/inbound_protocols/imap/Settings.h index cb3f2cc..3555e00 100644 --- a/src/add-ons/mail_daemon/inbound_protocols/imap/Settings.h +++ b/src/add-ons/mail_daemon/inbound_protocols/imap/Settings.h @@ -13,7 +13,8 @@ class Settings { public: - Settings(const BMessage& archive); + Settings(const char* accountName, + const BMessage& archive); ~Settings(); BNetworkAddress ServerAddress() const; @@ -32,6 +33,7 @@ public: private: const BMessage fMessage; + BString fAccountName; }; ############################################################################ Commit: 7a4ef93c415a7727f645db790f2f2bfb3c827ff2 Author: Axel Dörfler <axeld@xxxxxxxxxxxxxxxx> Date: Thu Apr 25 18:56:49 2013 UTC IMAP: IMAPFolder now stores the last UID. * So mails are no longer downloaded every time. ---------------------------------------------------------------------------- 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 fd61d58..011d4c0 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 0739f20..e7a0f4b 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; - - uint32 uidValidity; - if (node.ReadAttr(kUIDValidityAttribute, B_UINT32_TYPE, 0, &uidValidity, - sizeof(uint32)) != sizeof(uint32)) - return; + BString originalMailboxName; + if (node.ReadAttrString(kMailboxNameAttribute, &originalMailboxName) == B_OK + && originalMailboxName != mailboxName) { + // TODO: mailbox name has changed + } - 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 1da9e82..6c9100e 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<uint32, uint32> UIDToFlagsMap; typedef std::hash_map<uint32, entry_ref> UIDToRefMap; @@ -77,6 +83,7 @@ private: const entry_ref fRef; BString fMailboxName; uint32 fUIDValidity; + uint32 fLastUID; FolderListener* fListener; UIDToRefMap fRefMap; UIDToFlagsMap fUIDMap;