From d33e4744df1542a1350f55c25ce7b691560d7345 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Axel=20D=C3=B6rfler?= Date: Wed, 3 Jul 2013 22:52:22 +0200 Subject: [PATCH] IMAP: downloading mails is now working. * Changed the way the attributes are written to make sure that everything that can be written once is in fact written just once. * The rename code in BMailProtocol::_ProcessFetchedHeader() was broken, and caused the hang of the last commit. --- headers/os/add-ons/mail_daemon/MailFilter.h | 6 +- headers/os/add-ons/mail_daemon/MailProtocol.h | 10 +- headers/os/app/Message.h | 3 +- .../match_header/RuleFilter.cpp | 14 +- .../inbound_filters/match_header/RuleFilter.h | 3 +- .../spam_filter/SpamFilter.cpp | 6 +- .../inbound_filters/spam_filter/SpamFilter.h | 6 +- .../inbound_protocols/imap/IMAPFolder.cpp | 12 +- .../inbound_protocols/imap/IMAPProtocol.cpp | 15 +- .../inbound_protocols/imap/IMAPProtocol.h | 2 +- .../inbound_protocols/pop3/POP3.cpp | 13 +- src/kits/app/Message.cpp | 9 +- src/kits/mail/HaikuMailFormatFilter.cpp | 26 +-- src/kits/mail/HaikuMailFormatFilter.h | 8 +- src/kits/mail/MailFilter.cpp | 5 +- src/kits/mail/MailProtocol.cpp | 156 +++++++++++------- 16 files changed, 178 insertions(+), 116 deletions(-) diff --git a/headers/os/add-ons/mail_daemon/MailFilter.h b/headers/os/add-ons/mail_daemon/MailFilter.h index b071c703be..5721d6f0e1 100644 --- a/headers/os/add-ons/mail_daemon/MailFilter.h +++ b/headers/os/add-ons/mail_daemon/MailFilter.h @@ -21,8 +21,10 @@ public: virtual ~BMailFilter(); // Message hooks if filter is installed to an inbound protocol - virtual BMailFilterAction HeaderFetched(entry_ref& ref, BFile& file); - virtual void BodyFetched(const entry_ref& ref, BFile& file); + virtual BMailFilterAction HeaderFetched(entry_ref& ref, BFile& file, + BMessage& attributes); + virtual void BodyFetched(const entry_ref& ref, BFile& file, + BMessage& attributes); virtual void MailboxSynchronized(status_t status); // Message hooks if filter is installed to an outbound protocol diff --git a/headers/os/add-ons/mail_daemon/MailProtocol.h b/headers/os/add-ons/mail_daemon/MailProtocol.h index f263fc043e..d4c3b2ca4e 100644 --- a/headers/os/add-ons/mail_daemon/MailProtocol.h +++ b/headers/os/add-ons/mail_daemon/MailProtocol.h @@ -95,9 +95,11 @@ protected: // Filter notifications BMailFilterAction ProcessHeaderFetched(entry_ref& ref, - BFile& mail); + BFile& mail, BMessage& attributes); void NotifyBodyFetched(const entry_ref& ref, - BFile& mail); + BFile& mail, BMessage& attributes); + BMailFilterAction ProcessMessageFetched(entry_ref& ref, + BFile& mail, BMessage& attributes); void NotifyMessageReadyToSend(const entry_ref& ref, BFile& mail); void NotifyMessageSent(const entry_ref& ref, @@ -108,6 +110,10 @@ protected: private: BMailFilter* _LoadFilter(const BMailAddOnSettings& settings); + BMailFilterAction _ProcessHeaderFetched(entry_ref& ref, + BFile& mail, BMessage& attributes); + void _NotifyBodyFetched(const entry_ref& ref, + BFile& mail, BMessage& attributes); protected: const BMailAccountSettings fAccountSettings; diff --git a/headers/os/app/Message.h b/headers/os/app/Message.h index b0957e279d..0f7e585c02 100644 --- a/headers/os/app/Message.h +++ b/headers/os/app/Message.h @@ -489,7 +489,8 @@ public: status_t SetRect(const char* name, const BRect& value); status_t SetSize(const char* name, const BSize& value); status_t SetData(const char* name, type_code type, - const void* data, ssize_t numBytes); + const void* data, ssize_t numBytes, + bool fixedSize = true, int count = 1); class Private; struct message_header; diff --git a/src/add-ons/mail_daemon/inbound_filters/match_header/RuleFilter.cpp b/src/add-ons/mail_daemon/inbound_filters/match_header/RuleFilter.cpp index 75bc5ddcf3..c01f46e3b9 100644 --- a/src/add-ons/mail_daemon/inbound_filters/match_header/RuleFilter.cpp +++ b/src/add-ons/mail_daemon/inbound_filters/match_header/RuleFilter.cpp @@ -57,7 +57,7 @@ RuleFilter::RuleFilter(BMailProtocol& protocol, BMailFilterAction -RuleFilter::HeaderFetched(entry_ref& ref, BFile& file) +RuleFilter::HeaderFetched(entry_ref& ref, BFile& file, BMessage& attributes) { // That field doesn't exist? NO match if (fAttribute == "") @@ -68,16 +68,8 @@ RuleFilter::HeaderFetched(entry_ref& ref, BFile& file) || info.type != B_STRING_TYPE) return B_NO_MAIL_ACTION; - char* buffer = new char[info.size]; - if (file.ReadAttr(fAttribute, B_STRING_TYPE, 0, buffer, info.size) < 0) { - delete[] buffer; - return B_NO_MAIL_ACTION; - } - - BString data = buffer; - delete[] buffer; - - if (!fMatcher.Match(data)) { + BString data = attributes.GetString(fAttribute.String(), NULL); + if (data.IsEmpty() || !fMatcher.Match(data)) { // We're not supposed to do anything return B_NO_MAIL_ACTION; } diff --git a/src/add-ons/mail_daemon/inbound_filters/match_header/RuleFilter.h b/src/add-ons/mail_daemon/inbound_filters/match_header/RuleFilter.h index ef24e80b3d..e7a48f30e6 100644 --- a/src/add-ons/mail_daemon/inbound_filters/match_header/RuleFilter.h +++ b/src/add-ons/mail_daemon/inbound_filters/match_header/RuleFilter.h @@ -21,7 +21,8 @@ public: RuleFilter(BMailProtocol& protocol, const BMailAddOnSettings& settings); - virtual BMailFilterAction HeaderFetched(entry_ref& ref, BFile& file); + virtual BMailFilterAction HeaderFetched(entry_ref& ref, BFile& file, + BMessage& attributes); private: BString fAttribute; diff --git a/src/add-ons/mail_daemon/inbound_filters/spam_filter/SpamFilter.cpp b/src/add-ons/mail_daemon/inbound_filters/spam_filter/SpamFilter.cpp index d034f7caa4..f638628628 100644 --- a/src/add-ons/mail_daemon/inbound_filters/spam_filter/SpamFilter.cpp +++ b/src/add-ons/mail_daemon/inbound_filters/spam_filter/SpamFilter.cpp @@ -67,7 +67,7 @@ SpamFilter::~SpamFilter() BMailFilterAction -SpamFilter::HeaderFetched(entry_ref& ref, BFile& file) +SpamFilter::HeaderFetched(entry_ref& ref, BFile& file, BMessage& attributes) { _CheckForSpam(file); return B_NO_MAIL_ACTION; @@ -75,7 +75,7 @@ SpamFilter::HeaderFetched(entry_ref& ref, BFile& file) void -SpamFilter::BodyFetched(const entry_ref& ref, BFile& file) +SpamFilter::BodyFetched(const entry_ref& ref, BFile& file, BMessage& attributes) { if (fHeaderOnly) return; @@ -85,7 +85,7 @@ SpamFilter::BodyFetched(const entry_ref& ref, BFile& file) // untrain the partial part before training on the complete message, but we // don't know how big it was, so instead just ignore the message. attr_info attributeInfo; - if (file.GetAttrInfo ("MAIL:classification", &attributeInfo) == B_OK) + if (file.GetAttrInfo("MAIL:classification", &attributeInfo) == B_OK) return; _CheckForSpam(file); diff --git a/src/add-ons/mail_daemon/inbound_filters/spam_filter/SpamFilter.h b/src/add-ons/mail_daemon/inbound_filters/spam_filter/SpamFilter.h index 15368c5a36..f255a395fb 100644 --- a/src/add-ons/mail_daemon/inbound_filters/spam_filter/SpamFilter.h +++ b/src/add-ons/mail_daemon/inbound_filters/spam_filter/SpamFilter.h @@ -18,8 +18,10 @@ public: const BMailAddOnSettings& settings); virtual ~SpamFilter(); - virtual BMailFilterAction HeaderFetched(entry_ref& ref, BFile& file); - virtual void BodyFetched(const entry_ref& ref, BFile& file); + virtual BMailFilterAction HeaderFetched(entry_ref& ref, BFile& file, + BMessage& attributes); + virtual void BodyFetched(const entry_ref& ref, BFile& file, + BMessage& attributes); private: status_t _CheckForSpam(BFile& file); 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 7a026afa3e..cb58d82a5b 100644 --- a/src/add-ons/mail_daemon/inbound_protocols/imap/IMAPFolder.cpp +++ b/src/add-ons/mail_daemon/inbound_protocols/imap/IMAPFolder.cpp @@ -231,7 +231,14 @@ IMAPFolder::MessageStored(entry_ref& ref, BFile& file, uint32 fetchFlags, if ((fetchFlags & IMAP::kFetchFlags) != 0) _WriteFlags(file, flags); - fProtocol.MessageStored(*this, ref, file, fetchFlags); + // TODO: add some utility function for this in libmail.so + BMessage attributes; + if ((flags & IMAP::kAnswered) != 0) + attributes.AddString(B_MAIL_ATTR_STATUS, "Answered"); + else if ((flags & IMAP::kSeen) != 0) + attributes.AddString(B_MAIL_ATTR_STATUS, "Read"); + + fProtocol.MessageStored(*this, ref, file, fetchFlags, attributes); file.Unset(); fRefMap.insert(std::make_pair(uid, ref)); @@ -282,7 +289,8 @@ IMAPFolder::StoreBody(uint32 uid, BDataIO& stream, size_t& length, void IMAPFolder::BodyStored(entry_ref& ref, BFile& file, uint32 uid) { - fProtocol.MessageStored(*this, ref, file, IMAP::kFetchBody); + BMessage attributes; + fProtocol.MessageStored(*this, ref, file, IMAP::kFetchBody, attributes); file.Unset(); } 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 b9605b1213..17ccf2226c 100644 --- a/src/add-ons/mail_daemon/inbound_protocols/imap/IMAPProtocol.cpp +++ b/src/add-ons/mail_daemon/inbound_protocols/imap/IMAPProtocol.cpp @@ -124,15 +124,16 @@ IMAPProtocol::WorkerQuit(IMAPConnectionWorker* worker) void IMAPProtocol::MessageStored(IMAPFolder& folder, entry_ref& ref, BFile& stream, - uint32 fetchFlags) + uint32 fetchFlags, BMessage& attributes) { - if ((fetchFlags & IMAP::kFetchHeader) != 0) { - BMailFilterAction action = ProcessHeaderFetched(ref, stream); - if (action < B_OK || action == B_DELETE_MAIL_ACTION) - return; + if ((fetchFlags & (IMAP::kFetchHeader | IMAP::kFetchBody)) + == IMAP::kFetchHeader | IMAP::kFetchBody) { + ProcessMessageFetched(ref, stream, attributes); + } else if ((fetchFlags & IMAP::kFetchHeader) != 0) { + ProcessHeaderFetched(ref, stream, attributes); + } else if ((fetchFlags & IMAP::kFetchBody) != 0) { + NotifyBodyFetched(ref, stream, attributes); } - if ((fetchFlags & IMAP::kFetchBody) != 0) - NotifyBodyFetched(ref, stream); } diff --git a/src/add-ons/mail_daemon/inbound_protocols/imap/IMAPProtocol.h b/src/add-ons/mail_daemon/inbound_protocols/imap/IMAPProtocol.h index 531b5c9b17..fb3d1441aa 100644 --- a/src/add-ons/mail_daemon/inbound_protocols/imap/IMAPProtocol.h +++ b/src/add-ons/mail_daemon/inbound_protocols/imap/IMAPProtocol.h @@ -36,7 +36,7 @@ public: void MessageStored(IMAPFolder& folder, entry_ref& ref, BFile& stream, - uint32 fetchFlags); + uint32 fetchFlags, BMessage& attributes); virtual status_t SyncMessages(); virtual status_t FetchBody(const entry_ref& ref); diff --git a/src/add-ons/mail_daemon/inbound_protocols/pop3/POP3.cpp b/src/add-ons/mail_daemon/inbound_protocols/pop3/POP3.cpp index 4929d7402d..954ef7a3c5 100644 --- a/src/add-ons/mail_daemon/inbound_protocols/pop3/POP3.cpp +++ b/src/add-ons/mail_daemon/inbound_protocols/pop3/POP3.cpp @@ -203,14 +203,11 @@ POP3Protocol::SyncMessages() break; } BMailMessageIO mailIO(this, &file, toRetrieve); + BMessage attributes; entry_ref ref; entry.GetRef(&ref); - // the ref becomes invalid after renaming the file thus we already - // write the status here - MarkMessageAsRead(ref, B_UNREAD); - int32 size = MessageSize(toRetrieve); if (fFetchBodyLimit < 0 || size <= fFetchBodyLimit) { error = mailIO.Seek(0, SEEK_END); @@ -218,8 +215,7 @@ POP3Protocol::SyncMessages() printf("POP3: Failed to download body %s\n ", uid); break; } - ProcessHeaderFetched(ref, file); - NotifyBodyFetched(ref, file); + ProcessMessageFetched(ref, file, attributes); if (!leaveOnServer) Delete(toRetrieve); @@ -230,7 +226,7 @@ POP3Protocol::SyncMessages() printf("POP3: Failed to download header %s\n ", uid); break; } - ProcessHeaderFetched(ref, file); + ProcessHeaderFetched(ref, file, attributes); } ReportProgress(1, 0); @@ -302,7 +298,8 @@ POP3Protocol::FetchBody(const entry_ref& ref) return status; } - NotifyBodyFetched(ref, file); + BMessage attributes; + NotifyBodyFetched(ref, file, attributes); if (!leaveOnServer) Delete(toRetrieve); diff --git a/src/kits/app/Message.cpp b/src/kits/app/Message.cpp index bd5e592cc9..c6992cdcca 100644 --- a/src/kits/app/Message.cpp +++ b/src/kits/app/Message.cpp @@ -3194,20 +3194,21 @@ BMessage::GetString(const char* name, int32 index, status_t BMessage::SetString(const char* name, const BString& value) { - return SetData(name, B_STRING_TYPE, value.String(), value.Length() + 1); + return SetData(name, B_STRING_TYPE, value.String(), value.Length() + 1, + false); } status_t BMessage::SetString(const char* name, const char* value) { - return SetData(name, B_STRING_TYPE, value, strlen(value) + 1); + return SetData(name, B_STRING_TYPE, value, strlen(value) + 1, false); } status_t BMessage::SetData(const char* name, type_code type, const void* data, - ssize_t numBytes) + ssize_t numBytes, bool fixedSize, int count) { if (numBytes <= 0 || data == NULL) return B_BAD_VALUE; @@ -3215,5 +3216,5 @@ BMessage::SetData(const char* name, type_code type, const void* data, if (ReplaceData(name, type, data, numBytes) == B_OK) return B_OK; - return AddData(name, type, data, numBytes); + return AddData(name, type, data, numBytes, fixedSize, count); } diff --git a/src/kits/mail/HaikuMailFormatFilter.cpp b/src/kits/mail/HaikuMailFormatFilter.cpp index 96a28fa35b..8c4b4d8c68 100644 --- a/src/kits/mail/HaikuMailFormatFilter.cpp +++ b/src/kits/mail/HaikuMailFormatFilter.cpp @@ -16,7 +16,6 @@ #include #include -#include struct mail_header_field { @@ -98,11 +97,11 @@ HaikuMailFormatFilter::DescriptiveName() const BMailFilterAction -HaikuMailFormatFilter::HeaderFetched(entry_ref& ref, BFile& file) +HaikuMailFormatFilter::HeaderFetched(entry_ref& ref, BFile& file, + BMessage& attributes) { file.Seek(0, SEEK_SET); - BMessage attributes; // TODO: attributes.AddInt32(B_MAIL_ATTR_CONTENT, length); attributes.AddInt32(B_MAIL_ATTR_ACCOUNT_ID, fAccountID); attributes.AddString(B_MAIL_ATTR_ACCOUNT, fAccountName); @@ -196,11 +195,10 @@ HaikuMailFormatFilter::HeaderFetched(entry_ref& ref, BFile& file) _RemoveLeadingDots(name); // Avoid files starting with a dot. - file << attributes; + if (!attributes.HasString(B_MAIL_ATTR_STATUS)) + attributes.AddString(B_MAIL_ATTR_STATUS, "New"); - // TODO: find a way to not set that twice for each complete mail - BNodeInfo info(&file); - info.SetType(B_PARTIAL_MAIL_TYPE); + _SetType(attributes, B_PARTIAL_MAIL_TYPE); ref.set_name(name.String()); @@ -209,10 +207,10 @@ HaikuMailFormatFilter::HeaderFetched(entry_ref& ref, BFile& file) void -HaikuMailFormatFilter::BodyFetched(const entry_ref& ref, BFile& file) +HaikuMailFormatFilter::BodyFetched(const entry_ref& ref, BFile& file, + BMessage& attributes) { - BNodeInfo info(&file); - info.SetType(B_MAIL_TYPE); + _SetType(attributes, B_MAIL_TYPE); } @@ -307,3 +305,11 @@ HaikuMailFormatFilter::_ExtractName(const BString& from) name.Trim(); return name; } + + +status_t +HaikuMailFormatFilter::_SetType(BMessage& attributes, const char* mimeType) +{ + return attributes.SetData("BEOS:TYPE", B_MIME_STRING_TYPE, mimeType, + strlen(mimeType) + 1, false); +} diff --git a/src/kits/mail/HaikuMailFormatFilter.h b/src/kits/mail/HaikuMailFormatFilter.h index 2eebb6087a..b8c1ef1c3e 100644 --- a/src/kits/mail/HaikuMailFormatFilter.h +++ b/src/kits/mail/HaikuMailFormatFilter.h @@ -18,8 +18,10 @@ public: virtual BString DescriptiveName() const; - BMailFilterAction HeaderFetched(entry_ref& ref, BFile& file); - void BodyFetched(const entry_ref& ref, BFile& file); + BMailFilterAction HeaderFetched(entry_ref& ref, BFile& file, + BMessage& attributes); + void BodyFetched(const entry_ref& ref, BFile& file, + BMessage& attributes); void MessageSent(const entry_ref& ref, BFile& file); @@ -27,6 +29,8 @@ private: void _RemoveExtraWhitespace(BString& name); void _RemoveLeadingDots(BString& name); BString _ExtractName(const BString& from); + status_t _SetType(BMessage& attributes, + const char* mimeType); private: int32 fAccountID; diff --git a/src/kits/mail/MailFilter.cpp b/src/kits/mail/MailFilter.cpp index 7c7d626c17..faf93ea99f 100644 --- a/src/kits/mail/MailFilter.cpp +++ b/src/kits/mail/MailFilter.cpp @@ -22,14 +22,15 @@ BMailFilter::~BMailFilter() BMailFilterAction -BMailFilter::HeaderFetched(entry_ref& ref, BFile& file) +BMailFilter::HeaderFetched(entry_ref& ref, BFile& file, BMessage& attributes) { return B_NO_MAIL_ACTION; } void -BMailFilter::BodyFetched(const entry_ref& ref, BFile& file) +BMailFilter::BodyFetched(const entry_ref& ref, BFile& file, + BMessage& attributes) { } diff --git a/src/kits/mail/MailProtocol.cpp b/src/kits/mail/MailProtocol.cpp index b39185cd4b..446e142fb6 100644 --- a/src/kits/mail/MailProtocol.cpp +++ b/src/kits/mail/MailProtocol.cpp @@ -32,6 +32,7 @@ #include #include +#include #include "HaikuMailFormatFilter.h" @@ -210,83 +211,53 @@ BMailProtocol::NotifyNewMessagesToFetch(int32 count) BMailFilterAction -BMailProtocol::ProcessHeaderFetched(entry_ref& ref, BFile& data) +BMailProtocol::ProcessHeaderFetched(entry_ref& ref, BFile& file, + BMessage& attributes) { - entry_ref outRef = ref; + BMailFilterAction action = _ProcessHeaderFetched(ref, file, attributes); + if (action >= B_OK && action != B_DELETE_MAIL_ACTION) + file << attributes; - for (int i = 0; i < fFilterList.CountItems(); i++) { - BMailFilterAction action = fFilterList.ItemAt(i)->HeaderFetched(outRef, - data); - if (action == B_DELETE_MAIL_ACTION) { - // We have to delete the message - BEntry entry(&ref); - status_t status = entry.Remove(); - if (status != B_OK) { - fprintf(stderr, "BMailProtocol::NotifyHeaderFetched(): could " - "not delete mail: %s\n", strerror(status)); - } - return B_DELETE_MAIL_ACTION; - } - } - - if (ref == outRef) - return B_NO_MAIL_ACTION; - - // We have to rename the file - node_ref newParentRef; - newParentRef.device = outRef.device; - newParentRef.node = outRef.directory; - - BDirectory newParent(&newParentRef); - status_t status = newParent.InitCheck(); - BString workerName; - if (status == B_OK) { - int32 uniqueNumber = 1; - do { - workerName = outRef.name; - if (uniqueNumber > 1) - workerName << "_" << ++uniqueNumber; - - // TODO: support copying to another device! - BEntry entry(&ref); - status = entry.Rename(workerName); - } while (status == B_FILE_EXISTS); - } - - if (status != B_OK) { - fprintf(stderr, "BMailProtocol::NotifyHeaderFetched(): could not " - "rename mail (%s)! (should be: %s)\n", strerror(status), - workerName.String()); - } - - ref = outRef; - ref.set_name(workerName.String()); - - return B_MOVE_MAIL_ACTION; + return action; } void -BMailProtocol::NotifyBodyFetched(const entry_ref& ref, BFile& data) +BMailProtocol::NotifyBodyFetched(const entry_ref& ref, BFile& file, + BMessage& attributes) { - for (int i = 0; i < fFilterList.CountItems(); i++) - fFilterList.ItemAt(i)->BodyFetched(ref, data); + _NotifyBodyFetched(ref, file, attributes); + file << attributes; +} + + +BMailFilterAction +BMailProtocol::ProcessMessageFetched(entry_ref& ref, BFile& file, + BMessage& attributes) +{ + BMailFilterAction action = _ProcessHeaderFetched(ref, file, attributes); + if (action >= B_OK && action != B_DELETE_MAIL_ACTION) { + _NotifyBodyFetched(ref, file, attributes); + file << attributes; + } + + return action; } void -BMailProtocol::NotifyMessageReadyToSend(const entry_ref& ref, BFile& data) +BMailProtocol::NotifyMessageReadyToSend(const entry_ref& ref, BFile& file) { for (int i = 0; i < fFilterList.CountItems(); i++) - fFilterList.ItemAt(i)->MessageReadyToSend(ref, data); + fFilterList.ItemAt(i)->MessageReadyToSend(ref, file); } void -BMailProtocol::NotifyMessageSent(const entry_ref& ref, BFile& data) +BMailProtocol::NotifyMessageSent(const entry_ref& ref, BFile& file) { for (int i = 0; i < fFilterList.CountItems(); i++) - fFilterList.ItemAt(i)->MessageSent(ref, data); + fFilterList.ItemAt(i)->MessageSent(ref, file); } @@ -331,6 +302,75 @@ BMailProtocol::_LoadFilter(const BMailAddOnSettings& settings) } +BMailFilterAction +BMailProtocol::_ProcessHeaderFetched(entry_ref& ref, BFile& file, + BMessage& attributes) +{ + entry_ref outRef = ref; + + for (int i = 0; i < fFilterList.CountItems(); i++) { + BMailFilterAction action = fFilterList.ItemAt(i)->HeaderFetched(outRef, + file, attributes); + if (action == B_DELETE_MAIL_ACTION) { + // We have to delete the message + BEntry entry(&ref); + status_t status = entry.Remove(); + if (status != B_OK) { + fprintf(stderr, "BMailProtocol::NotifyHeaderFetched(): could " + "not delete mail: %s\n", strerror(status)); + } + return B_DELETE_MAIL_ACTION; + } + } + + if (ref == outRef) + return B_NO_MAIL_ACTION; + + // We have to rename the file + node_ref newParentRef; + newParentRef.device = outRef.device; + newParentRef.node = outRef.directory; + + BDirectory newParent(&newParentRef); + status_t status = newParent.InitCheck(); + BString workerName; + if (status == B_OK) { + int32 uniqueNumber = 1; + do { + workerName = outRef.name; + if (uniqueNumber > 1) + workerName << "_" << uniqueNumber; + + // TODO: support copying to another device! + BEntry entry(&ref); + status = entry.Rename(workerName); + + uniqueNumber++; + } while (status == B_FILE_EXISTS); + } + + if (status != B_OK) { + fprintf(stderr, "BMailProtocol::NotifyHeaderFetched(): could not " + "rename mail (%s)! (should be: %s)\n", strerror(status), + workerName.String()); + } + + ref = outRef; + ref.set_name(workerName.String()); + + return B_MOVE_MAIL_ACTION; +} + + +void +BMailProtocol::_NotifyBodyFetched(const entry_ref& ref, BFile& file, + BMessage& attributes) +{ + for (int i = 0; i < fFilterList.CountItems(); i++) + fFilterList.ItemAt(i)->BodyFetched(ref, file, attributes); +} + + // #pragma mark -