added 1 changeset to branch 'refs/remotes/axeld-github/imap' old head: d3ede35cf2c614eafe7cc08e9143c22fc74cb815 new head: 002f09437f5f468e0c52c884aa7fcdf9e37251d3 overview: https://github.com/axeld/haiku/compare/d3ede35...002f094 ---------------------------------------------------------------------------- 002f094: 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. [ Axel Dörfler <axeld@xxxxxxxxxxxxxxxx> ] ---------------------------------------------------------------------------- Commit: 002f09437f5f468e0c52c884aa7fcdf9e37251d3 Author: Axel Dörfler <axeld@xxxxxxxxxxxxxxxx> Date: Wed Jul 3 20:52:22 2013 UTC ---------------------------------------------------------------------------- 16 files changed, 181 insertions(+), 119 deletions(-) headers/os/add-ons/mail_daemon/MailFilter.h | 6 +- headers/os/add-ons/mail_daemon/MailProtocol.h | 10 +- headers/os/app/Message.h | 5 +- .../inbound_filters/match_header/RuleFilter.cpp | 14 +- .../inbound_filters/match_header/RuleFilter.h | 3 +- .../inbound_filters/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 +- .../mail_daemon/inbound_protocols/pop3/POP3.cpp | 13 +- src/kits/app/Message.cpp | 15 +- src/kits/mail/HaikuMailFormatFilter.cpp | 26 ++-- src/kits/mail/HaikuMailFormatFilter.h | 8 +- src/kits/mail/MailFilter.cpp | 5 +- src/kits/mail/MailProtocol.cpp | 154 ++++++++++++------- ---------------------------------------------------------------------------- diff --git a/headers/os/add-ons/mail_daemon/MailFilter.h b/headers/os/add-ons/mail_daemon/MailFilter.h index b071c70..5721d6f 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 f263fc0..d4c3b2c 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 bb3a74d..104ebf2 100644 --- a/headers/os/app/Message.h +++ b/headers/os/app/Message.h @@ -1,5 +1,5 @@ /* - * Copyright 2005-2012, Haiku Inc. All Rights Reserved. + * Copyright 2005-2013, Haiku Inc. All Rights Reserved. * Distributed under the terms of the MIT License. * * Authors: @@ -486,7 +486,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 75bc5dd..c01f46e 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 ef24e80..e7a48f3 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 5544c83..9ca3a6c 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 15368c5..f255a39 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 7a026af..cb58d82 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 b9605b1..17ccf22 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 531b5c9..fb3d144 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 9a1f3cd..db2e893 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 3c0dbe6..fe4f18f 100644 --- a/src/kits/app/Message.cpp +++ b/src/kits/app/Message.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2005-2012, Haiku Inc. All rights reserved. + * Copyright 2005-2013, Haiku Inc. All rights reserved. * Distributed under the terms of the MIT License. * * Authors: @@ -3128,8 +3128,8 @@ BMessage::HasFlat(const char *name, const BFlattenable *object) const bool -BMessage::HasFlat(const char *name, int32 index, const BFlattenable *object) - const +BMessage::HasFlat(const char *name, int32 index, + const BFlattenable *object) const { return HasData(name, object->TypeCode(), index); } @@ -3157,20 +3157,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; @@ -3178,5 +3179,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 96a28fa..8c4b4d8 100644 --- a/src/kits/mail/HaikuMailFormatFilter.cpp +++ b/src/kits/mail/HaikuMailFormatFilter.cpp @@ -16,7 +16,6 @@ #include <NodeInfo.h> #include <mail_util.h> -#include <NodeMessage.h> 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 2eebb60..b8c1ef1 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 7c7d626..faf93ea 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 b39185c..446e142 100644 --- a/src/kits/mail/MailProtocol.cpp +++ b/src/kits/mail/MailProtocol.cpp @@ -32,6 +32,7 @@ #include <mail_util.h> #include <MailPrivate.h> +#include <NodeMessage.h> #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; - - 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; + BMailFilterAction action = _ProcessHeaderFetched(ref, file, attributes); + if (action >= B_OK && action != B_DELETE_MAIL_ACTION) + file << attributes; - // TODO: support copying to another device! - BEntry entry(&ref); - status = entry.Rename(workerName); - } while (status == B_FILE_EXISTS); - } + return action; +} - 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) +{ + _NotifyBodyFetched(ref, file, attributes); + file << attributes; } -void -BMailProtocol::NotifyBodyFetched(const entry_ref& ref, BFile& data) +BMailFilterAction +BMailProtocol::ProcessMessageFetched(entry_ref& ref, BFile& file, + BMessage& attributes) { - for (int i = 0; i < fFilterList.CountItems(); i++) - fFilterList.ItemAt(i)->BodyFetched(ref, data); + 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 -