IMAP: work in progress of downloading the mail body.
* Most things are in place now, we just try to download the body to the wrong file, as the final location is currently unknown. * Added local only kPartialMessage flag for mails, but it's not being used yet.
This commit is contained in:
@@ -59,6 +59,11 @@ public:
|
|||||||
return fWorker._MailboxFor(folder);
|
return fWorker._MailboxFor(folder);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int32 BodyFetchLimit()
|
||||||
|
{
|
||||||
|
return fWorker.fSettings.BodyFetchLimit();
|
||||||
|
}
|
||||||
|
|
||||||
status_t EnqueueCommand(WorkerCommand* command)
|
status_t EnqueueCommand(WorkerCommand* command)
|
||||||
{
|
{
|
||||||
return fWorker._EnqueueCommand(command);
|
return fWorker._EnqueueCommand(command);
|
||||||
@@ -125,15 +130,78 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class FetchBodiesCommand : public SyncCommand, public IMAP::FetchListener {
|
||||||
|
public:
|
||||||
|
FetchBodiesCommand(IMAPFolder& folder, IMAPMailbox& mailbox,
|
||||||
|
std::vector<uint32>& entries)
|
||||||
|
:
|
||||||
|
fFolder(folder),
|
||||||
|
fMailbox(mailbox),
|
||||||
|
fEntries(entries)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual status_t Process(IMAPConnectionWorker& worker)
|
||||||
|
{
|
||||||
|
IMAP::Protocol& protocol = WorkerPrivate(worker).Protocol();
|
||||||
|
|
||||||
|
if (fEntries.empty())
|
||||||
|
return B_OK;
|
||||||
|
|
||||||
|
fUID = *fEntries.begin();
|
||||||
|
fEntries.erase(fEntries.begin());
|
||||||
|
|
||||||
|
// TODO: check nextUID if we get one
|
||||||
|
status_t status = WorkerPrivate(worker).SelectMailbox(fFolder);
|
||||||
|
if (status != B_OK)
|
||||||
|
return status;
|
||||||
|
|
||||||
|
printf("IMAP: fetch body for %lu\n", fUID);
|
||||||
|
// TODO: combine smaller messages together for faster retrieval
|
||||||
|
IMAP::FetchCommand fetch(fUID, fUID, IMAP::kFetchBody);
|
||||||
|
fetch.SetListener(this);
|
||||||
|
|
||||||
|
return protocol.ProcessCommand(fetch);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual bool IsDone() const
|
||||||
|
{
|
||||||
|
return fEntries.empty();
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual bool FetchData(uint32 fetchFlags, BDataIO& stream, size_t& length)
|
||||||
|
{
|
||||||
|
fFetchStatus = fFolder.StoreBody(fUID, stream, length, fRef, fFile);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void FetchedData(uint32 fetchFlags, uint32 uid, uint32 flags)
|
||||||
|
{
|
||||||
|
if (fFetchStatus == B_OK)
|
||||||
|
fFolder.BodyStored(fRef, fFile, uid);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
IMAPFolder& fFolder;
|
||||||
|
IMAPMailbox& fMailbox;
|
||||||
|
std::vector<uint32> fEntries;
|
||||||
|
uint32 fUID;
|
||||||
|
entry_ref fRef;
|
||||||
|
BFile fFile;
|
||||||
|
status_t fFetchStatus;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
class FetchHeadersCommand : public SyncCommand, public IMAP::FetchListener {
|
class FetchHeadersCommand : public SyncCommand, public IMAP::FetchListener {
|
||||||
public:
|
public:
|
||||||
FetchHeadersCommand(IMAPFolder& folder, IMAPMailbox& mailbox,
|
FetchHeadersCommand(IMAPFolder& folder, IMAPMailbox& mailbox,
|
||||||
uint32 from, uint32 to)
|
uint32 from, uint32 to, int32 bodyFetchLimit)
|
||||||
:
|
:
|
||||||
fFolder(folder),
|
fFolder(folder),
|
||||||
fMailbox(mailbox),
|
fMailbox(mailbox),
|
||||||
fFrom(from),
|
fFrom(from),
|
||||||
fTo(to)
|
fTo(to),
|
||||||
|
fBodyFetchLimit(bodyFetchLimit)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -152,8 +220,6 @@ public:
|
|||||||
if (to - fFrom >= kMaxFetchEntries)
|
if (to - fFrom >= kMaxFetchEntries)
|
||||||
to = fFrom + kMaxFetchEntries - 1;
|
to = fFrom + kMaxFetchEntries - 1;
|
||||||
|
|
||||||
// TODO: trigger download of mails for all messages below the
|
|
||||||
// body fetch limit
|
|
||||||
printf("IMAP: fetch headers from %lu to %lu\n", fFrom, to);
|
printf("IMAP: fetch headers from %lu to %lu\n", fFrom, to);
|
||||||
IMAP::FetchCommand fetch(fFrom, to,
|
IMAP::FetchCommand fetch(fFrom, to,
|
||||||
IMAP::kFetchHeader | IMAP::kFetchFlags);
|
IMAP::kFetchHeader | IMAP::kFetchFlags);
|
||||||
@@ -164,6 +230,13 @@ public:
|
|||||||
return status;
|
return status;
|
||||||
|
|
||||||
fFrom = to + 1;
|
fFrom = to + 1;
|
||||||
|
|
||||||
|
if (IsDone() && !fFetchBodies.empty()) {
|
||||||
|
// Enqueue command to fetch the message bodies
|
||||||
|
WorkerPrivate(worker).EnqueueCommand(new FetchBodiesCommand(fFolder,
|
||||||
|
fMailbox, fFetchBodies));
|
||||||
|
}
|
||||||
|
|
||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -174,15 +247,20 @@ public:
|
|||||||
|
|
||||||
virtual bool FetchData(uint32 fetchFlags, BDataIO& stream, size_t& length)
|
virtual bool FetchData(uint32 fetchFlags, BDataIO& stream, size_t& length)
|
||||||
{
|
{
|
||||||
fFetchStatus = fFolder.StoreMessage(fFile, fetchFlags, stream,
|
fFetchStatus = fFolder.StoreMessage(fetchFlags, stream, length,
|
||||||
length, fRef);
|
fRef, fFile);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void FetchedData(uint32 fetchFlags, uint32 uid, uint32 flags)
|
virtual void FetchedData(uint32 fetchFlags, uint32 uid, uint32 flags)
|
||||||
{
|
{
|
||||||
if (fFetchStatus == B_OK)
|
if (fFetchStatus == B_OK) {
|
||||||
fFolder.MessageStored(fRef, fFile, fetchFlags, uid, flags);
|
fFolder.MessageStored(fRef, fFile, fetchFlags, uid, flags);
|
||||||
|
|
||||||
|
uint32 size = fMailbox.MessageSize(uid);
|
||||||
|
if (fBodyFetchLimit < 0 || size < fBodyFetchLimit)
|
||||||
|
fFetchBodies.push_back(uid);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@@ -190,6 +268,8 @@ private:
|
|||||||
IMAPMailbox& fMailbox;
|
IMAPMailbox& fMailbox;
|
||||||
uint32 fFrom;
|
uint32 fFrom;
|
||||||
uint32 fTo;
|
uint32 fTo;
|
||||||
|
uint32 fBodyFetchLimit;
|
||||||
|
std::vector<uint32> fFetchBodies;
|
||||||
entry_ref fRef;
|
entry_ref fRef;
|
||||||
BFile fFile;
|
BFile fFile;
|
||||||
status_t fFetchStatus;
|
status_t fFetchStatus;
|
||||||
@@ -269,9 +349,13 @@ public:
|
|||||||
return status;
|
return status;
|
||||||
|
|
||||||
// Determine how much we need to download
|
// Determine how much we need to download
|
||||||
|
// TODO: also retrieve the header size, and only take the body
|
||||||
|
// size into account if it's below the limit
|
||||||
for (size_t i = 0; i < entries.size(); i++) {
|
for (size_t i = 0; i < entries.size(); i++) {
|
||||||
printf("%10lu %8lu bytes, flags: %#lx\n", entries[i].uid,
|
printf("%10lu %8lu bytes, flags: %#lx\n", entries[i].uid,
|
||||||
entries[i].size, entries[i].flags);
|
entries[i].size, entries[i].flags);
|
||||||
|
fMailbox->AddMessageEntry(entries[i].uid, entries[i].flags,
|
||||||
|
entries[i].size);
|
||||||
fTotalBytes += entries[i].size;
|
fTotalBytes += entries[i].size;
|
||||||
}
|
}
|
||||||
fTotalEntries += entries.size();
|
fTotalEntries += entries.size();
|
||||||
@@ -283,7 +367,8 @@ public:
|
|||||||
if (fMailboxEntries > 0) {
|
if (fMailboxEntries > 0) {
|
||||||
// Add pending command to fetch the message headers
|
// Add pending command to fetch the message headers
|
||||||
WorkerCommand* command = new FetchHeadersCommand(*fFolder,
|
WorkerCommand* command = new FetchHeadersCommand(*fFolder,
|
||||||
*fMailbox, fFirstUID, fNextUID);
|
*fMailbox, fFirstUID, fNextUID,
|
||||||
|
WorkerPrivate(worker).BodyFetchLimit());
|
||||||
if (!fFetchCommands.AddItem(command))
|
if (!fFetchCommands.AddItem(command))
|
||||||
delete command;
|
delete command;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -132,7 +132,7 @@ IMAPFolder::IMAPFolder(IMAPProtocol& protocol, const BString& mailboxName,
|
|||||||
uint32 uid = B_BENDIAN_TO_HOST_INT32(entries[i].uid);
|
uint32 uid = B_BENDIAN_TO_HOST_INT32(entries[i].uid);
|
||||||
uint32 flags = B_BENDIAN_TO_HOST_INT32(entries[i].flags);
|
uint32 flags = B_BENDIAN_TO_HOST_INT32(entries[i].flags);
|
||||||
|
|
||||||
fUIDMap.insert(std::make_pair(uid, flags));
|
fFlagsMap.insert(std::make_pair(uid, flags));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -167,6 +167,29 @@ IMAPFolder::SetUIDValidity(uint32 uidValidity)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
IMAPFolder::GetMessageEntryRef(uint32 uid, entry_ref& ref) const
|
||||||
|
{
|
||||||
|
UIDToRefMap::const_iterator found = fRefMap.find(uid);
|
||||||
|
if (found == fRefMap.end())
|
||||||
|
return B_ENTRY_NOT_FOUND;
|
||||||
|
|
||||||
|
ref = found->second;
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
uint32
|
||||||
|
IMAPFolder::MessageFlags(uint32 uid) const
|
||||||
|
{
|
||||||
|
UIDToFlagsMap::const_iterator found = fFlagsMap.find(uid);
|
||||||
|
if (found == fFlagsMap.end())
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return found->second;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*! Stores the given \a stream into a temporary file using the provided
|
/*! 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
|
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
|
point to it. The file will remain open when this method exits without
|
||||||
@@ -176,8 +199,8 @@ IMAPFolder::SetUIDValidity(uint32 uidValidity)
|
|||||||
were an error.
|
were an error.
|
||||||
*/
|
*/
|
||||||
status_t
|
status_t
|
||||||
IMAPFolder::StoreMessage(BFile& file, uint32 fetchFlags, BDataIO& stream,
|
IMAPFolder::StoreMessage(uint32 fetchFlags, BDataIO& stream,
|
||||||
size_t& length, entry_ref& ref)
|
size_t& length, entry_ref& ref, BFile& file)
|
||||||
{
|
{
|
||||||
BPath path;
|
BPath path;
|
||||||
status_t status = path.SetTo(&fRef);
|
status_t status = path.SetTo(&fRef);
|
||||||
@@ -189,26 +212,11 @@ IMAPFolder::StoreMessage(BFile& file, uint32 fetchFlags, BDataIO& stream,
|
|||||||
if (status != B_OK)
|
if (status != B_OK)
|
||||||
return status;
|
return status;
|
||||||
|
|
||||||
char buffer[65535];
|
status = _WriteStream(file, stream, length);
|
||||||
while (length > 0) {
|
if (status == B_OK)
|
||||||
ssize_t bytesRead = stream.Read(buffer,
|
temporaryFile.KeepFile();
|
||||||
std::min(sizeof(buffer), length));
|
|
||||||
if (bytesRead < 0)
|
|
||||||
return bytesRead;
|
|
||||||
if (bytesRead <= 0)
|
|
||||||
break;
|
|
||||||
|
|
||||||
length -= bytesRead;
|
return status;
|
||||||
|
|
||||||
ssize_t bytesWritten = file.Write(buffer, bytesRead);
|
|
||||||
if (bytesWritten < 0)
|
|
||||||
return bytesWritten;
|
|
||||||
if (bytesWritten != bytesRead)
|
|
||||||
return B_IO_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
temporaryFile.KeepFile();
|
|
||||||
return B_OK;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -223,29 +231,73 @@ IMAPFolder::MessageStored(entry_ref& ref, BFile& file, uint32 fetchFlags,
|
|||||||
if ((fetchFlags & IMAP::kFetchFlags) != 0)
|
if ((fetchFlags & IMAP::kFetchFlags) != 0)
|
||||||
_WriteFlags(file, flags);
|
_WriteFlags(file, flags);
|
||||||
|
|
||||||
// TODO: the call below may move/rename the file
|
// TODO: the call below may move/rename the file - this prevents downloading
|
||||||
fProtocol.MessageStored(ref, file, fetchFlags);
|
// the body to the correct file!
|
||||||
|
fProtocol.MessageStored(*this, ref, file, fetchFlags);
|
||||||
file.Unset();
|
file.Unset();
|
||||||
|
|
||||||
|
fRefMap.insert(std::make_pair(uid, ref));
|
||||||
|
|
||||||
if (uid > fLastUID) {
|
if (uid > fLastUID) {
|
||||||
// Update last known UID
|
// Update last known UID
|
||||||
fLastUID = uid;
|
fLastUID = uid;
|
||||||
|
|
||||||
BNode directory(&fRef);
|
BNode directory(&fRef);
|
||||||
status_t status = _WriteUInt32(directory, kLastUIDAttribute, uid);
|
status_t status = _WriteUInt32(directory, kLastUIDAttribute, uid);
|
||||||
if (status != B_OK)
|
if (status != B_OK) {
|
||||||
fprintf(stderr, "IMAP: Could not write last UID for mailbox "
|
fprintf(stderr, "IMAP: Could not write last UID for mailbox "
|
||||||
"%s: %s\n", fMailboxName.String(), strerror(status));
|
"%s: %s\n", fMailboxName.String(), strerror(status));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*! Appends the given \a stream as body to the message file for the
|
||||||
|
specified unique ID. The file will remain open when this method exits
|
||||||
|
without an error.
|
||||||
|
|
||||||
|
\a length will reflect how many bytes are left to read in case there
|
||||||
|
were an error.
|
||||||
|
*/
|
||||||
|
status_t
|
||||||
|
IMAPFolder::StoreBody(uint32 uid, BDataIO& stream, size_t& length,
|
||||||
|
entry_ref& ref, BFile& file)
|
||||||
|
{
|
||||||
|
status_t status = GetMessageEntryRef(uid, ref);
|
||||||
|
if (status != B_OK)
|
||||||
|
return status;
|
||||||
|
|
||||||
|
status = file.SetTo(&ref, B_OPEN_AT_END | B_WRITE_ONLY);
|
||||||
|
if (status != B_OK)
|
||||||
|
return status;
|
||||||
|
|
||||||
|
BPath path(&ref);
|
||||||
|
printf("IMAP: write body to %s\n", path.Path());
|
||||||
|
|
||||||
|
return _WriteStream(file, stream, length);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*! Notifies the protocol that a body has been fetched.
|
||||||
|
This method also closes the \a file passed in.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
IMAPFolder::BodyStored(entry_ref& ref, BFile& file, uint32 uid)
|
||||||
|
{
|
||||||
|
fProtocol.MessageStored(*this, ref, file, IMAP::kFetchBody);
|
||||||
|
file.Unset();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
IMAPFolder::DeleteMessage(uint32 uid)
|
IMAPFolder::DeleteMessage(uint32 uid)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*! Called when the flags of a message changed on the server. This will update
|
||||||
|
the flags for the local file.
|
||||||
|
*/
|
||||||
void
|
void
|
||||||
IMAPFolder::SetMessageFlags(uint32 uid, uint32 flags)
|
IMAPFolder::SetMessageFlags(uint32 uid, uint32 flags)
|
||||||
{
|
{
|
||||||
@@ -264,8 +316,8 @@ IMAPFolder::_InitializeFolderState()
|
|||||||
// Create set of the last known UID state - if an entry is found, it
|
// Create set of the last known UID state - if an entry is found, it
|
||||||
// is being removed from the list. The remaining entries were deleted.
|
// is being removed from the list. The remaining entries were deleted.
|
||||||
std::set<uint32> lastUIDs;
|
std::set<uint32> lastUIDs;
|
||||||
UIDToFlagsMap::iterator iterator = fUIDMap.begin();
|
UIDToFlagsMap::iterator iterator = fFlagsMap.begin();
|
||||||
for (; iterator != fUIDMap.end(); iterator++)
|
for (; iterator != fFlagsMap.end(); iterator++)
|
||||||
lastUIDs.insert(iterator->first);
|
lastUIDs.insert(iterator->first);
|
||||||
|
|
||||||
BDirectory directory(&fRef);
|
BDirectory directory(&fRef);
|
||||||
@@ -286,12 +338,11 @@ IMAPFolder::_InitializeFolderState()
|
|||||||
// The message is still around
|
// The message is still around
|
||||||
lastUIDs.erase(found);
|
lastUIDs.erase(found);
|
||||||
|
|
||||||
UIDToFlagsMap::iterator flagsFound = fUIDMap.find(uid);
|
uint32 flagsFound = MessageFlags(uid);
|
||||||
ASSERT(flagsFound != fUIDMap.end());
|
if (flagsFound != flags) {
|
||||||
if (flagsFound->second != flags) {
|
|
||||||
// Its flags have changed locally, and need to be updated
|
// Its flags have changed locally, and need to be updated
|
||||||
fListener->MessageFlagsChanged(_Token(uid), ref,
|
fListener->MessageFlagsChanged(_Token(uid), ref,
|
||||||
flagsFound->second, flags);
|
flagsFound, flags);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// This is a new message
|
// This is a new message
|
||||||
@@ -376,3 +427,28 @@ IMAPFolder::_WriteUInt32(BNode& node, const char* attribute, uint32 value)
|
|||||||
|
|
||||||
return bytesWritten < 0 ? bytesWritten : B_IO_ERROR;
|
return bytesWritten < 0 ? bytesWritten : B_IO_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
IMAPFolder::_WriteStream(BFile& file, BDataIO& stream, size_t& length)
|
||||||
|
{
|
||||||
|
char buffer[65535];
|
||||||
|
while (length > 0) {
|
||||||
|
ssize_t bytesRead = stream.Read(buffer,
|
||||||
|
std::min(sizeof(buffer), length));
|
||||||
|
if (bytesRead < 0)
|
||||||
|
return bytesRead;
|
||||||
|
if (bytesRead <= 0)
|
||||||
|
break;
|
||||||
|
|
||||||
|
length -= bytesRead;
|
||||||
|
|
||||||
|
ssize_t bytesWritten = file.Write(buffer, bytesRead);
|
||||||
|
if (bytesWritten < 0)
|
||||||
|
return bytesWritten;
|
||||||
|
if (bytesWritten != bytesRead)
|
||||||
|
return B_IO_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|||||||
@@ -24,6 +24,11 @@ struct MessageToken {
|
|||||||
uint32 uid;
|
uint32 uid;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Additional local only message flags
|
||||||
|
enum FolderMessageFlags {
|
||||||
|
kPartialMessage = 0x00010000,
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
class FolderListener {
|
class FolderListener {
|
||||||
public:
|
public:
|
||||||
@@ -51,13 +56,23 @@ public:
|
|||||||
|
|
||||||
uint32 LastUID() const { return fLastUID; }
|
uint32 LastUID() const { return fLastUID; }
|
||||||
|
|
||||||
status_t StoreMessage(BFile& file, uint32 fetchFlags,
|
status_t GetMessageEntryRef(uint32 uid,
|
||||||
BDataIO& stream, size_t& length,
|
entry_ref& ref) const;
|
||||||
entry_ref& ref);
|
uint32 MessageFlags(uint32 uid) const;
|
||||||
|
|
||||||
|
status_t StoreMessage(uint32 fetchFlags, BDataIO& stream,
|
||||||
|
size_t& length, entry_ref& ref,
|
||||||
|
BFile& file);
|
||||||
void MessageStored(entry_ref& ref, BFile& file,
|
void MessageStored(entry_ref& ref, BFile& file,
|
||||||
uint32 fetchFlags, uint32 uid,
|
uint32 fetchFlags, uint32 uid,
|
||||||
uint32 flags);
|
uint32 flags);
|
||||||
|
|
||||||
|
status_t StoreBody(uint32 uid, BDataIO& stream,
|
||||||
|
size_t& length, entry_ref& ref,
|
||||||
|
BFile& file);
|
||||||
|
void BodyStored(entry_ref& ref, BFile& file,
|
||||||
|
uint32 uid);
|
||||||
|
|
||||||
void DeleteMessage(uint32 uid);
|
void DeleteMessage(uint32 uid);
|
||||||
void SetMessageFlags(uint32 uid, uint32 flags);
|
void SetMessageFlags(uint32 uid, uint32 flags);
|
||||||
|
|
||||||
@@ -75,6 +90,9 @@ private:
|
|||||||
status_t _WriteUInt32(BNode& node,
|
status_t _WriteUInt32(BNode& node,
|
||||||
const char* attribute, uint32 value);
|
const char* attribute, uint32 value);
|
||||||
|
|
||||||
|
status_t _WriteStream(BFile& file, BDataIO& stream,
|
||||||
|
size_t& length);
|
||||||
|
|
||||||
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;
|
||||||
@@ -86,7 +104,7 @@ private:
|
|||||||
uint32 fLastUID;
|
uint32 fLastUID;
|
||||||
FolderListener* fListener;
|
FolderListener* fListener;
|
||||||
UIDToRefMap fRefMap;
|
UIDToRefMap fRefMap;
|
||||||
UIDToFlagsMap fUIDMap;
|
UIDToFlagsMap fFlagsMap;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -24,6 +24,36 @@ IMAPMailbox::~IMAPMailbox()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
IMAPMailbox::AddMessageEntry(uint32 uid, uint32 flags, uint32 size)
|
||||||
|
{
|
||||||
|
fMessageEntries.insert(
|
||||||
|
std::make_pair(uid, MessageFlagsAndSize(flags, size)));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
uint32
|
||||||
|
IMAPMailbox::MessageFlags(uint32 uid) const
|
||||||
|
{
|
||||||
|
MessageEntryMap::const_iterator found = fMessageEntries.find(uid);
|
||||||
|
if (found == fMessageEntries.end())
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return found->second.flags;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
uint32
|
||||||
|
IMAPMailbox::MessageSize(uint32 uid) const
|
||||||
|
{
|
||||||
|
MessageEntryMap::const_iterator found = fMessageEntries.find(uid);
|
||||||
|
if (found == fMessageEntries.end())
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return found->second.size;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
uint32
|
uint32
|
||||||
IMAPMailbox::MessageAdded(const MessageToken& fromToken, const entry_ref& ref)
|
IMAPMailbox::MessageAdded(const MessageToken& fromToken, const entry_ref& ref)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -22,6 +22,11 @@ public:
|
|||||||
|
|
||||||
const BString& MailboxName() const { return fMailboxName; }
|
const BString& MailboxName() const { return fMailboxName; }
|
||||||
|
|
||||||
|
void AddMessageEntry(uint32 uid, uint32 flags,
|
||||||
|
uint32 size);
|
||||||
|
uint32 MessageFlags(uint32 uid) const;
|
||||||
|
uint32 MessageSize(uint32 uid) const;
|
||||||
|
|
||||||
// FolderListener interface
|
// FolderListener interface
|
||||||
virtual uint32 MessageAdded(const MessageToken& fromToken,
|
virtual uint32 MessageAdded(const MessageToken& fromToken,
|
||||||
const entry_ref& ref);
|
const entry_ref& ref);
|
||||||
@@ -32,8 +37,22 @@ public:
|
|||||||
uint32 newFlags);
|
uint32 newFlags);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
struct MessageFlagsAndSize {
|
||||||
|
MessageFlagsAndSize(uint32 _flags, uint32 _size)
|
||||||
|
:
|
||||||
|
flags(_flags),
|
||||||
|
size(_size)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32 flags;
|
||||||
|
uint32 size;
|
||||||
|
};
|
||||||
|
typedef std::hash_map<uint32, MessageFlagsAndSize> MessageEntryMap;
|
||||||
|
|
||||||
IMAP::Protocol& fProtocol;
|
IMAP::Protocol& fProtocol;
|
||||||
BString fMailboxName;
|
BString fMailboxName;
|
||||||
|
MessageEntryMap fMessageEntries;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -123,7 +123,8 @@ IMAPProtocol::WorkerQuit(IMAPConnectionWorker* worker)
|
|||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
IMAPProtocol::MessageStored(entry_ref& ref, BFile& stream, uint32 fetchFlags)
|
IMAPProtocol::MessageStored(IMAPFolder& folder, entry_ref& ref, BFile& stream,
|
||||||
|
uint32 fetchFlags)
|
||||||
{
|
{
|
||||||
if ((fetchFlags & IMAP::kFetchHeader) != 0)
|
if ((fetchFlags & IMAP::kFetchHeader) != 0)
|
||||||
NotifyHeaderFetched(ref, &stream);
|
NotifyHeaderFetched(ref, &stream);
|
||||||
|
|||||||
@@ -34,7 +34,8 @@ public:
|
|||||||
IMAP::Protocol& protocol, bool idle);
|
IMAP::Protocol& protocol, bool idle);
|
||||||
void WorkerQuit(IMAPConnectionWorker* worker);
|
void WorkerQuit(IMAPConnectionWorker* worker);
|
||||||
|
|
||||||
void MessageStored(entry_ref& ref, BFile& stream,
|
void MessageStored(IMAPFolder& folder,
|
||||||
|
entry_ref& ref, BFile& stream,
|
||||||
uint32 fetchFlags);
|
uint32 fetchFlags);
|
||||||
|
|
||||||
virtual status_t SyncMessages();
|
virtual status_t SyncMessages();
|
||||||
|
|||||||
@@ -34,12 +34,14 @@ struct MessageEntry {
|
|||||||
typedef std::vector<MessageEntry> MessageEntryList;
|
typedef std::vector<MessageEntry> MessageEntryList;
|
||||||
|
|
||||||
enum MessageFlags {
|
enum MessageFlags {
|
||||||
kSeen = 0x01,
|
kSeen = 0x01,
|
||||||
kAnswered = 0x02,
|
kAnswered = 0x02,
|
||||||
kFlagged = 0x04,
|
kFlagged = 0x04,
|
||||||
kDeleted = 0x08,
|
kDeleted = 0x08,
|
||||||
kDraft = 0x10
|
kDraft = 0x10,
|
||||||
// \Recent doesn't really have any useful meaning, so we just ignore it
|
// \Recent doesn't really have any useful meaning, so we just ignore it
|
||||||
|
|
||||||
|
kServerFlagsMask = 0x0000ffff
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user