IMAP: IMAPFolder now stores the last UID.

* So mails are no longer downloaded every time.
This commit is contained in:
Axel Dörfler
2015-01-06 15:25:56 +01:00
parent 28ee6c2839
commit 47b68f5806
3 changed files with 60 additions and 17 deletions
@@ -215,8 +215,7 @@ public:
return status; return status;
fState = FETCH_ENTRIES; fState = FETCH_ENTRIES;
// fFirstUID = fLastUID = fFolder->LastUID(); fFirstUID = fLastUID = fFolder->LastUID() + 1;
fFirstUID = fLastUID = 0;
fMailboxEntries = 0; fMailboxEntries = 0;
} }
@@ -23,6 +23,7 @@
static const char* kMailboxNameAttribute = "IMAP:mailbox"; static const char* kMailboxNameAttribute = "IMAP:mailbox";
static const char* kUIDValidityAttribute = "IMAP:uidvalidity"; static const char* kUIDValidityAttribute = "IMAP:uidvalidity";
static const char* kLastUIDAttribute = "IMAP:lastuid";
static const char* kStateAttribute = "IMAP:state"; static const char* kStateAttribute = "IMAP:state";
static const char* kFlagsAttribute = "IMAP:flags"; static const char* kFlagsAttribute = "IMAP:flags";
static const char* kUIDAttribute = "MAIL:unique_id"; static const char* kUIDAttribute = "MAIL:unique_id";
@@ -88,22 +89,23 @@ IMAPFolder::IMAPFolder(IMAPProtocol& protocol, const BString& mailboxName,
fProtocol(protocol), fProtocol(protocol),
fRef(ref), fRef(ref),
fMailboxName(mailboxName), fMailboxName(mailboxName),
fUIDValidity(UINT32_MAX) fUIDValidity(UINT32_MAX),
fLastUID(0)
{ {
// Initialize from folder attributes // Initialize from folder attributes
BNode node(&ref); BNode node(&ref);
if (node.InitCheck() != B_OK) if (node.InitCheck() != B_OK)
return; return;
if (node.ReadAttrString(kMailboxNameAttribute, &fMailboxName) != B_OK) BString originalMailboxName;
return; if (node.ReadAttrString(kMailboxNameAttribute, &originalMailboxName) == B_OK
&& originalMailboxName != mailboxName) {
// TODO: mailbox name has changed
}
uint32 uidValidity; fUIDValidity = _ReadUInt32(node, kUIDValidityAttribute);
if (node.ReadAttr(kUIDValidityAttribute, B_UINT32_TYPE, 0, &uidValidity, fLastUID = _ReadUInt32(node, kLastUIDAttribute);
sizeof(uint32)) != sizeof(uint32)) printf("IMAP: %s, last UID %lu\n", fMailboxName.String(), fLastUID);
return;
fUIDValidity = B_BENDIAN_TO_HOST_INT32(uidValidity);
attr_info info; attr_info info;
status_t status = node.GetAttrInfo(kStateAttribute, &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 // Initialize current state from actual folder
// TODO: this should be done in another thread // TODO: this should be done in another thread
_InitializeFolderState(); //_InitializeFolderState();
} }
@@ -154,7 +156,13 @@ IMAPFolder::SetListener(FolderListener* listener)
void void
IMAPFolder::SetUIDValidity(uint32 uidValidity) IMAPFolder::SetUIDValidity(uint32 uidValidity)
{ {
if (fUIDValidity == uidValidity)
return;
fUIDValidity = uidValidity; 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 // TODO: the call below may move/rename the file
fProtocol.MessageStored(ref, file, fetchFlags); fProtocol.MessageStored(ref, file, fetchFlags);
file.Unset(); 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 uint32
IMAPFolder::_ReadFlags(BNode& node) IMAPFolder::_ReadFlags(BNode& node)
{ {
// TODO! return _ReadUInt32(node, kFlagsAttribute);
return 0;
} }
status_t status_t
IMAPFolder::_WriteFlags(BNode& node, uint32 flags) IMAPFolder::_WriteFlags(BNode& node, uint32 flags)
{ {
ssize_t bytesWritten = node.WriteAttr(kFlagsAttribute, B_UINT32_TYPE, 0, return _WriteUInt32(node, kFlagsAttribute, flags);
&flags, sizeof(uint32)); }
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)) if (bytesWritten == (ssize_t)sizeof(uint32))
return B_OK; return B_OK;
@@ -49,6 +49,8 @@ public:
void SetListener(FolderListener* listener); void SetListener(FolderListener* listener);
void SetUIDValidity(uint32 uidValidity); void SetUIDValidity(uint32 uidValidity);
uint32 LastUID() const { return fLastUID; }
status_t StoreMessage(BFile& file, uint32 fetchFlags, status_t StoreMessage(BFile& file, uint32 fetchFlags,
BDataIO& stream, size_t& length, BDataIO& stream, size_t& length,
entry_ref& ref); entry_ref& ref);
@@ -69,6 +71,10 @@ private:
uint32 _ReadFlags(BNode& node); uint32 _ReadFlags(BNode& node);
status_t _WriteFlags(BNode& node, uint32 flags); 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: private:
typedef std::hash_map<uint32, uint32> UIDToFlagsMap; typedef std::hash_map<uint32, uint32> UIDToFlagsMap;
typedef std::hash_map<uint32, entry_ref> UIDToRefMap; typedef std::hash_map<uint32, entry_ref> UIDToRefMap;
@@ -77,6 +83,7 @@ private:
const entry_ref fRef; const entry_ref fRef;
BString fMailboxName; BString fMailboxName;
uint32 fUIDValidity; uint32 fUIDValidity;
uint32 fLastUID;
FolderListener* fListener; FolderListener* fListener;
UIDToRefMap fRefMap; UIDToRefMap fRefMap;
UIDToFlagsMap fUIDMap; UIDToFlagsMap fUIDMap;