[haiku-commits] BRANCH axeld-github.imap [fcab7c5] src/kits/mail src/add-ons/mail_daemon/inbound_filters/spam_filter src/add-ons/mail_daemon/inbound_filters/match_header headers/os/add-ons/mail_daemon src/add-ons/mail_daemon

  • From: axeld-github.imap <community@xxxxxxxxxxxx>
  • To: haiku-commits@xxxxxxxxxxxxx
  • Date: Thu, 27 Jun 2013 00:45:31 +0200 (CEST)

added 1 changeset to branch 'refs/remotes/axeld-github/imap'
old head: 22074d6029b2eab8027e00c2fb013e096306fe03
new head: fcab7c5e00eb195fb42177209b2f7985560db84b
overview: https://github.com/axeld/haiku/compare/22074d6...fcab7c5

----------------------------------------------------------------------------

fcab7c5: Mail Kit: Changed how filter changes work.
  
  * BMailFilter::HeaderFetched() now only alters the entry_ref, and returns
    B_MOVE_MAIL_ACTION to move a mail.
  * Instead of potentially moving the file around several times, the
    BMailProtocol now takes care of carrying out the filter action just once,
    including trying to make the file name unique.
  * This also allows the IMAP add-on to know the final location of the mail,
    and thus downloading a message actually works.
  * However, with my test inbox, it currently hangs, and a current Debugger does
    not work on my older system -- I guess I need to update.
  * Replaced the duplicated space mechanism within the "HaikuMailFormatFilter"
    that is substantially faster, and handles all whitespace, not just spaces.
    It will also replace tabs with spaces.

                                   [ Axel Dörfler <axeld@xxxxxxxxxxxxxxxx> ]

----------------------------------------------------------------------------

Commit:      fcab7c5e00eb195fb42177209b2f7985560db84b
Author:      Axel Dörfler <axeld@xxxxxxxxxxxxxxxx>
Date:        Wed Jun 26 22:30:14 2013 UTC

----------------------------------------------------------------------------

14 files changed, 215 insertions(+), 198 deletions(-)
headers/os/add-ons/mail_daemon/MailFilter.h      |  12 +-
headers/os/add-ons/mail_daemon/MailProtocol.h    |  23 ++--
.../inbound_filters/match_header/RuleFilter.cpp  |  41 +++---
.../inbound_filters/match_header/RuleFilter.h    |   5 +-
.../inbound_filters/spam_filter/SpamFilter.cpp   |  33 ++---
.../inbound_filters/spam_filter/SpamFilter.h     |  11 +-
.../inbound_protocols/imap/IMAPFolder.cpp        |   2 -
.../inbound_protocols/imap/IMAPProtocol.cpp      |   9 +-
.../mail_daemon/inbound_protocols/pop3/POP3.cpp  |   8 +-
.../mail_daemon/outbound_protocols/smtp/SMTP.cpp |   6 +-
src/kits/mail/HaikuMailFormatFilter.cpp          | 110 +++++++++-------
src/kits/mail/HaikuMailFormatFilter.h            |  13 +-
src/kits/mail/MailFilter.cpp                     |  14 ++-
src/kits/mail/MailProtocol.cpp                   | 126 +++++++++----------

----------------------------------------------------------------------------

diff --git a/headers/os/add-ons/mail_daemon/MailFilter.h 
b/headers/os/add-ons/mail_daemon/MailFilter.h
index c16f269..b071c70 100644
--- a/headers/os/add-ons/mail_daemon/MailFilter.h
+++ b/headers/os/add-ons/mail_daemon/MailFilter.h
@@ -1,5 +1,5 @@
 /*
- * Copyright 2011-2012, Haiku, Inc. All Rights Reserved.
+ * Copyright 2011-2013, Haiku, Inc. All Rights Reserved.
  * Distributed under the terms of the MIT License.
  */
 #ifndef _MAIL_FILTER_H
@@ -21,16 +21,14 @@ public:
        virtual                                         ~BMailFilter();
 
        // Message hooks if filter is installed to an inbound protocol
-       virtual void                            HeaderFetched(const entry_ref& 
ref,
-                                                                       BFile* 
file);
-       virtual void                            BodyFetched(const entry_ref& 
ref, BFile* file);
+       virtual BMailFilterAction       HeaderFetched(entry_ref& ref, BFile& 
file);
+       virtual void                            BodyFetched(const entry_ref& 
ref, BFile& file);
        virtual void                            MailboxSynchronized(status_t 
status);
 
        // Message hooks if filter is installed to an outbound protocol
        virtual void                            MessageReadyToSend(const 
entry_ref& ref,
-                                                                       BFile* 
file);
-       virtual void                            MessageSent(const entry_ref& 
ref,
-                                                                       BFile* 
file);
+                                                                       BFile& 
file);
+       virtual void                            MessageSent(const entry_ref& 
ref, BFile& file);
 
 protected:
                        BMailProtocol&          fMailProtocol;
diff --git a/headers/os/add-ons/mail_daemon/MailProtocol.h 
b/headers/os/add-ons/mail_daemon/MailProtocol.h
index bb90719..f263fc0 100644
--- a/headers/os/add-ons/mail_daemon/MailProtocol.h
+++ b/headers/os/add-ons/mail_daemon/MailProtocol.h
@@ -43,6 +43,13 @@ public:
 };
 
 
+typedef status_t BMailFilterAction;
+
+#define B_NO_MAIL_ACTION               0
+#define B_MOVE_MAIL_ACTION             1
+#define B_DELETE_MAIL_ACTION   2
+
+
 class BMailProtocol : public BLooper {
 public:
                                                                BMailProtocol(
@@ -68,10 +75,6 @@ public:
                                                                        
BDirectory& dir);
        virtual status_t                        DeleteMessage(const entry_ref& 
ref);
 
-       virtual void                            FileRenamed(const entry_ref& 
from,
-                                                                       const 
entry_ref& to);
-       virtual void                            FileDeleted(const node_ref& 
node);
-
                        // Convenience methods that call the BMailNotifier
                        void                            ShowError(const char* 
error);
                        void                            ShowMessage(const char* 
message);
@@ -88,17 +91,17 @@ protected:
                        void                            ReportProgress(uint32 
items, uint64 bytes,
                                                                        const 
char* message = NULL);
                        void                            ResetProgress(const 
char* message = NULL);
+                       void                            
NotifyNewMessagesToFetch(int32 nMessages);
 
                        // Filter notifications
-                       void                            
NotifyNewMessagesToFetch(int32 nMessages);
-                       void                            
NotifyHeaderFetched(const entry_ref& ref,
-                                                                       BFile* 
mail);
+                       BMailFilterAction       ProcessHeaderFetched(entry_ref& 
ref,
+                                                                       BFile& 
mail);
                        void                            NotifyBodyFetched(const 
entry_ref& ref,
-                                                                       BFile* 
mail);
+                                                                       BFile& 
mail);
                        void                            
NotifyMessageReadyToSend(const entry_ref& ref,
-                                                                       BFile* 
mail);
+                                                                       BFile& 
mail);
                        void                            NotifyMessageSent(const 
entry_ref& ref,
-                                                                       BFile* 
mail);
+                                                                       BFile& 
mail);
 
                        void                            LoadFilters(
                                                                        const 
BMailProtocolSettings& settings);
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 023840e..75bc5dd 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
@@ -1,5 +1,5 @@
 /*
- * Copyright 2004-2012, Haiku, Inc. All rights reserved.
+ * Copyright 2004-2013, Haiku, Inc. All rights reserved.
  * Copyright 2001 Dr. Zoidberg Enterprises. All rights reserved.
  *
  * Distributed under the terms of the MIT License.
@@ -56,50 +56,55 @@ RuleFilter::RuleFilter(BMailProtocol& protocol,
 }
 
 
-void
-RuleFilter::HeaderFetched(const entry_ref& ref, BFile* file)
+BMailFilterAction
+RuleFilter::HeaderFetched(entry_ref& ref, BFile& file)
 {
        // That field doesn't exist? NO match
        if (fAttribute == "")
-               return;
+               return B_NO_MAIL_ACTION;
 
        attr_info info;
-       if (file->GetAttrInfo("Subject", &info) != B_OK
+       if (file.GetAttrInfo("Subject", &info) != B_OK
                || info.type != B_STRING_TYPE)
-               return;
+               return B_NO_MAIL_ACTION;
 
        char* buffer = new char[info.size];
-       if (file->ReadAttr(fAttribute, B_STRING_TYPE, 0, buffer, info.size) < 
0) {
+       if (file.ReadAttr(fAttribute, B_STRING_TYPE, 0, buffer, info.size) < 0) 
{
                delete[] buffer;
-               return;
+               return B_NO_MAIL_ACTION;
        }
+
        BString data = buffer;
        delete[] buffer;
 
        if (!fMatcher.Match(data)) {
                // We're not supposed to do anything
-               return;
+               return B_NO_MAIL_ACTION;
        }
 
        switch (fAction) {
                case ACTION_MOVE_TO:
                {
                        BDirectory dir(fMoveTarget);
-                       // TODO: move is currently broken!
-//                     fMailProtocol.Looper()->TriggerFileMove(ref, dir);
-                       break;
+                       node_ref nodeRef;
+                       status_t status = dir.GetNodeRef(&nodeRef);
+                       if (status != B_OK)
+                               return status;
+
+                       ref.device = nodeRef.device;
+                       ref.directory = nodeRef.node;
+                       return B_MOVE_MAIL_ACTION;
                }
+
                case ACTION_DELETE_MESSAGE:
-                       // TODO trash!?
-//                     fMailProtocol.Looper()->TriggerFileDeletion(ref);
-                       break;
+                       return B_DELETE_MAIL_ACTION;
 
                case ACTION_SET_FLAGS_TO:
-                       file->WriteAttrString("MAIL:filter_flags", &fSetFlags);
+                       file.WriteAttrString("MAIL:filter_flags", &fSetFlags);
                        break;
 
                case ACTION_REPLY_WITH:
-                       file->WriteAttr("MAIL:reply_with", B_INT32_TYPE, 0, 
&fReplyAccount,
+                       file.WriteAttr("MAIL:reply_with", B_INT32_TYPE, 0, 
&fReplyAccount,
                                sizeof(int32));
                        break;
                case ACTION_SET_AS_READ:
@@ -113,7 +118,7 @@ RuleFilter::HeaderFetched(const entry_ref& ref, BFile* file)
                        fprintf(stderr,"Unknown do_what: 0x%04x!\n", fAction);
        }
 
-       return;
+       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 b262407..ef24e80 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
@@ -1,5 +1,5 @@
 /*
- * Copyright 2004-2012, Haiku, Inc. All rights reserved.
+ * Copyright 2004-2013, Haiku, Inc. All rights reserved.
  * Copyright 2001 Dr. Zoidberg Enterprises. All rights reserved.
  *
  * Distributed under the terms of the MIT License.
@@ -21,8 +21,7 @@ public:
                                                                
RuleFilter(BMailProtocol& protocol,
                                                                        const 
BMailAddOnSettings& settings);
 
-       virtual void                            HeaderFetched(const entry_ref& 
ref,
-                                                                       BFile* 
file);
+       virtual BMailFilterAction       HeaderFetched(entry_ref& ref, BFile& 
file);
 
 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 cfb3587..5544c83 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
@@ -1,5 +1,5 @@
 /*
- * Copyright 2002-2012, Haiku, Inc. All rights reserved.
+ * Copyright 2002-2013, Haiku, Inc. All rights reserved.
  * Copyright 2002 Alexander G. M. Smith.
  * Copyright 2011, Clemens Zeidler <haiku@xxxxxxxxxxxxxxxxxx>
  * Distributed under the terms of the MIT License.
@@ -66,15 +66,16 @@ SpamFilter::~SpamFilter()
 }
 
 
-void
-SpamFilter::HeaderFetched(const entry_ref& ref, BFile* file)
+BMailFilterAction
+SpamFilter::HeaderFetched(entry_ref& ref, BFile& file)
 {
        _CheckForSpam(file);
+       return B_NO_MAIL_ACTION;
 }
 
 
 void
-SpamFilter::BodyFetched(const entry_ref& ref, BFile* file)
+SpamFilter::BodyFetched(const entry_ref& ref, BFile& file)
 {
        if (fHeaderOnly)
                return;
@@ -84,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);
@@ -92,22 +93,22 @@ SpamFilter::BodyFetched(const entry_ref& ref, BFile* file)
 
 
 status_t
-SpamFilter::_CheckForSpam(BFile* file)
+SpamFilter::_CheckForSpam(BFile& file)
 {
        // Get a connection to the spam database server.  Launch if needed, 
should
        // only need it once, unless another e-mail thread shuts down the server
        // inbetween messages.  This code used to be in InitCheck, but 
apparently
        // that isn't called.
        printf("Checking for Spam Server.\n");
-       if (fLaunchAttemptCount == 0 || !fMessengerToServer.IsValid ()) {
+       if (fLaunchAttemptCount == 0 || !fMessengerToServer.IsValid()) {
                if (_GetTokenizeMode() != B_OK)
                        return B_ERROR;
        }
 
        off_t dataSize;
-       file->GetSize(&dataSize);
+       file.GetSize(&dataSize);
        char* stringBuffer = new char[dataSize + 1];
-       file->Read(stringBuffer, dataSize);
+       file.Read(stringBuffer, dataSize);
        stringBuffer[dataSize] = 0; // Add an end of string NUL, just in case.
 
        float spamRatio;
@@ -118,7 +119,7 @@ SpamFilter::_CheckForSpam(BFile* file)
        // training example (don't train if it is uncertain).
        if (fAutoTraining && (spamRatio >= fSpamCutoffRatio
                || spamRatio < fGenuineCutoffRatio)) {
-                       _TrainServer(stringBuffer, dataSize, spamRatio);
+               _TrainServer(stringBuffer, dataSize, spamRatio);
        }
 
        delete[] stringBuffer;
@@ -127,12 +128,12 @@ SpamFilter::_CheckForSpam(BFile* file)
        const char *classificationString;
        classificationString = spamRatio >= fSpamCutoffRatio ? "Spam"
                : spamRatio < fGenuineCutoffRatio ? "Genuine" : "Uncertain";
-       file->WriteAttr("MAIL:classification", B_STRING_TYPE, 0 /* offset */,
+       file.WriteAttr("MAIL:classification", B_STRING_TYPE, 0 /* offset */,
                classificationString, strlen(classificationString) + 1);
 
        // Store the spam ratio in an attribute called MAIL:ratio_spam,
        // attached to the eventual output file.
-       file->WriteAttr("MAIL:ratio_spam", B_FLOAT_TYPE, 0 /* offset */, 
&spamRatio,
+       file.WriteAttr("MAIL:ratio_spam", B_FLOAT_TYPE, 0 /* offset */, 
&spamRatio,
                sizeof(spamRatio));
 
        // Also add it to the subject, if requested.
@@ -279,16 +280,16 @@ SpamFilter::_TrainServer(const char* stringBuffer, off_t 
dataSize,
 
 
 status_t
-SpamFilter::_AddSpamToSubject(BNode* file, float spamRatio)
+SpamFilter::_AddSpamToSubject(BNode& file, float spamRatio)
 {
        attr_info info;
-       if (file->GetAttrInfo("Subject", &info) != B_OK)
+       if (file.GetAttrInfo("Subject", &info) != B_OK)
                return B_ERROR;
        if (info.type != B_STRING_TYPE)
                return B_ERROR;
 
        char* buffer = new char[info.size];
-       if (file->ReadAttr("Subject", B_STRING_TYPE, 0, buffer, info.size) < 0) 
{
+       if (file.ReadAttr("Subject", B_STRING_TYPE, 0, buffer, info.size) < 0) {
                delete[] buffer;
                return B_ERROR;
        }
@@ -301,7 +302,7 @@ SpamFilter::_AddSpamToSubject(BNode* file, float spamRatio)
        newSubjectString << buffer;
        delete[] buffer;
 
-       if (file->WriteAttr("Subject", B_STRING_TYPE, 0, 
newSubjectString.String(),
+       if (file.WriteAttr("Subject", B_STRING_TYPE, 0, 
newSubjectString.String(),
                newSubjectString.Length()) < 0)
                return B_ERROR;
 
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 9650007..15368c5 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
@@ -1,5 +1,5 @@
 /*
- * Copyright 2002-2011, Haiku, Inc. All rights reserved.
+ * Copyright 2002-2013, Haiku, Inc. All rights reserved.
  * Copyright 2002 Alexander G. M. Smith.
  * Copyright 2011, Clemens Zeidler <haiku@xxxxxxxxxxxxxxxxxx>
  * Distributed under the terms of the MIT License.
@@ -18,12 +18,11 @@ public:
                                                                        const 
BMailAddOnSettings& settings);
        virtual                                         ~SpamFilter();
 
-       virtual void                            HeaderFetched(const entry_ref& 
ref,
-                                                                       BFile* 
file);
-       virtual void                            BodyFetched(const entry_ref& 
ref, BFile* file);
+       virtual BMailFilterAction       HeaderFetched(entry_ref& ref, BFile& 
file);
+       virtual void                            BodyFetched(const entry_ref& 
ref, BFile& file);
 
 private:
-                       status_t                        _CheckForSpam(BFile* 
file);
+                       status_t                        _CheckForSpam(BFile& 
file);
                        //! If the server is not running start it
                        status_t                        _CheckForSpamServer();
                        status_t                        _GetTokenizeMode();
@@ -31,7 +30,7 @@ private:
                                                                        float& 
ratio);
                        status_t                        _TrainServer(const 
char* data, off_t dataSize,
                                                                        float 
spamRatio);
-                       status_t                        
_AddSpamToSubject(BNode* file, float spamRatio);
+                       status_t                        
_AddSpamToSubject(BNode& file, float spamRatio);
 
 private:
                        bool                            fAddSpamToSubject;
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 a7abf30..7a026af 100644
--- a/src/add-ons/mail_daemon/inbound_protocols/imap/IMAPFolder.cpp
+++ b/src/add-ons/mail_daemon/inbound_protocols/imap/IMAPFolder.cpp
@@ -231,8 +231,6 @@ IMAPFolder::MessageStored(entry_ref& ref, BFile& file, 
uint32 fetchFlags,
        if ((fetchFlags & IMAP::kFetchFlags) != 0)
                _WriteFlags(file, flags);
 
-       // TODO: the call below may move/rename the file - this prevents 
downloading
-       // the body to the correct file!
        fProtocol.MessageStored(*this, ref, file, fetchFlags);
        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 5499c06..b9605b1 100644
--- a/src/add-ons/mail_daemon/inbound_protocols/imap/IMAPProtocol.cpp
+++ b/src/add-ons/mail_daemon/inbound_protocols/imap/IMAPProtocol.cpp
@@ -126,10 +126,13 @@ void
 IMAPProtocol::MessageStored(IMAPFolder& folder, entry_ref& ref, BFile& stream,
        uint32 fetchFlags)
 {
-       if ((fetchFlags & IMAP::kFetchHeader) != 0)
-               NotifyHeaderFetched(ref, &stream);
+       if ((fetchFlags & IMAP::kFetchHeader) != 0) {
+               BMailFilterAction action = ProcessHeaderFetched(ref, stream);
+               if (action < B_OK || action == B_DELETE_MAIL_ACTION)
+                       return;
+       }
        if ((fetchFlags & IMAP::kFetchBody) != 0)
-               NotifyBodyFetched(ref, &stream);
+               NotifyBodyFetched(ref, stream);
 }
 
 
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 8573b27..9a1f3cd 100644
--- a/src/add-ons/mail_daemon/inbound_protocols/pop3/POP3.cpp
+++ b/src/add-ons/mail_daemon/inbound_protocols/pop3/POP3.cpp
@@ -218,8 +218,8 @@ POP3Protocol::SyncMessages()
                                printf("POP3: Failed to download body %s\n ", 
uid);
                                break;
                        }
-                       NotifyHeaderFetched(ref, &file);
-                       NotifyBodyFetched(ref, &file);
+                       ProcessHeaderFetched(ref, file);
+                       NotifyBodyFetched(ref, file);
 
                        if (!leaveOnServer)
                                Delete(toRetrieve);
@@ -230,7 +230,7 @@ POP3Protocol::SyncMessages()
                                printf("POP3: Failed to download header %s\n ", 
uid);
                                break;
                        }
-                       NotifyHeaderFetched(ref, &file);
+                       ProcessHeaderFetched(ref, file);
                }
                ReportProgress(1, 0);
 
@@ -302,7 +302,7 @@ POP3Protocol::FetchBody(const entry_ref& ref)
                return status;
        }
 
-       NotifyBodyFetched(ref, &file);
+       NotifyBodyFetched(ref, file);
 
        if (!leaveOnServer)
                Delete(toRetrieve);
diff --git a/src/add-ons/mail_daemon/outbound_protocols/smtp/SMTP.cpp 
b/src/add-ons/mail_daemon/outbound_protocols/smtp/SMTP.cpp
index 0d98809..e9adae1 100644
--- a/src/add-ons/mail_daemon/outbound_protocols/smtp/SMTP.cpp
+++ b/src/add-ons/mail_daemon/outbound_protocols/smtp/SMTP.cpp
@@ -1,5 +1,5 @@
 /*
- * Copyright 2007-2012, Haiku, Inc. All rights reserved.
+ * Copyright 2007-2013, Haiku, Inc. All rights reserved.
  * Copyright 2001-2002 Dr. Zoidberg Enterprises. All rights reserved.
  * Copyright 2011, Clemens Zeidler <haiku@xxxxxxxxxxxxxxxxxx>
  *
@@ -546,11 +546,11 @@ SMTPProtocol::_SendMessage(const entry_ref& ref)
                return B_ERROR;
        }
 
-       NotifyMessageReadyToSend(ref, &file);
+       NotifyMessageReadyToSend(ref, file);
        status = Send(to, from, &file);
        if (status != B_OK)
                return status;
-       NotifyMessageSent(ref, &file);
+       NotifyMessageSent(ref, file);
 
        off_t size = 0;
        file.GetSize(&size);
diff --git a/src/kits/mail/HaikuMailFormatFilter.cpp 
b/src/kits/mail/HaikuMailFormatFilter.cpp
index f0db565..96a28fa 100644
--- a/src/kits/mail/HaikuMailFormatFilter.cpp
+++ b/src/kits/mail/HaikuMailFormatFilter.cpp
@@ -1,5 +1,5 @@
 /*
- * Copyright 2011-2012, Haiku, Inc. All rights reserved.
+ * Copyright 2011-2013, Haiku, Inc. All rights reserved.
  * Copyright 2011, Clemens Zeidler <haiku@xxxxxxxxxxxxxxxxxx>
  * Copyright 2001-2003 Dr. Zoidberg Enterprises. All rights reserved.
  *
@@ -97,10 +97,10 @@ HaikuMailFormatFilter::DescriptiveName() const
 }
 
 
-void
-HaikuMailFormatFilter::HeaderFetched(const entry_ref& ref, BFile* file)
+BMailFilterAction
+HaikuMailFormatFilter::HeaderFetched(entry_ref& ref, BFile& file)
 {
-       file->Seek(0, SEEK_SET);
+       file.Seek(0, SEEK_SET);
 
        BMessage attributes;
        // TODO: attributes.AddInt32(B_MAIL_ATTR_CONTENT, length);
@@ -109,9 +109,17 @@ HaikuMailFormatFilter::HeaderFetched(const entry_ref& ref, 
BFile* file)
 
        BString header;
        off_t size;
-       if (file->GetSize(&size) == B_OK) {
+       if (file.GetSize(&size) == B_OK) {
                char* buffer = header.LockBuffer(size);
-               file->Read(buffer, size);
+               if (buffer == NULL)
+                       return B_NO_MEMORY;
+
+               ssize_t bytesRead = file.Read(buffer, size);
+               if (bytesRead < 0)
+                       return bytesRead;
+               if (bytesRead != size)
+                       return B_IO_ERROR;
+
                header.UnlockBuffer(size);
        }
 
@@ -151,9 +159,6 @@ HaikuMailFormatFilter::HeaderFetched(const entry_ref& ref, 
BFile* file)
        if (name.Length() <= 0)
                name = "No Subject";
        attributes.AddString(B_MAIL_ATTR_THREAD, name);
-       // Avoid hidden files, starting with a dot.
-       if (name[0] == '.')
-               name.Prepend ("_");
 
        // Convert the date into a year-month-day fixed digit width format, so 
that
        // sorting by file name will give all the messages with the same 
subject in
@@ -174,11 +179,11 @@ HaikuMailFormatFilter::HeaderFetched(const entry_ref& 
ref, BFile* file)
                timeFields.tm_hour, timeFields.tm_min, timeFields.tm_sec);
        name << " " << numericDateString;
 
-       BString worker = attributes.FindString(B_MAIL_ATTR_FROM);
-       extract_address_name(worker);
-       name << " " << worker;
+       BString workerName = attributes.FindString(B_MAIL_ATTR_FROM);
+       extract_address_name(workerName);
+       name << " " << workerName;
 
-       name.Truncate(222);     // reserve space for the uniquer
+       name.Truncate(222);     // reserve space for the unique number
 
        // Get rid of annoying characters which are hard to use in the shell.
        name.ReplaceAll('/', '_');
@@ -187,49 +192,36 @@ HaikuMailFormatFilter::HeaderFetched(const entry_ref& 
ref, BFile* file)
        name.ReplaceAll('!', '_');
        name.ReplaceAll('<', '_');
        name.ReplaceAll('>', '_');
-       // Remove multiple spaces.
-       while (name.FindFirst("  ") >= 0)
-               name.Replace("  ", " ", 1024);
-
-       worker = name;
-       int32 identicalNumber = 1;
-       status_t status = _SetFileName(ref, worker);
-       while (status == B_FILE_EXISTS) {
-               identicalNumber++;
-
-               worker = name;
-               worker << "_" << identicalNumber;
-               status = _SetFileName(ref, worker);
-       }
-       if (status < B_OK) {
-               printf("FolderFilter::ProcessMailMessage: could not rename mail 
(%s)! "
-                       "(should be: %s)\n",strerror(status), worker.String());
-       } else {
-               entry_ref to(ref.device, ref.directory, worker);
-               fMailProtocol.FileRenamed(ref, to);
-       }
+       _RemoveExtraWhitespace(name);
+       _RemoveLeadingDots(name);
+               // Avoid files starting with a dot.
 
-       (*file) << attributes;
+       file << attributes;
 
-       BNodeInfo info(file);
+       // TODO: find a way to not set that twice for each complete mail
+       BNodeInfo info(&file);
        info.SetType(B_PARTIAL_MAIL_TYPE);
+
+       ref.set_name(name.String());
+
+       return B_MOVE_MAIL_ACTION;
 }
 
 
 void
-HaikuMailFormatFilter::BodyFetched(const entry_ref& ref, BFile* file)
+HaikuMailFormatFilter::BodyFetched(const entry_ref& ref, BFile& file)
 {
-       BNodeInfo info(file);
+       BNodeInfo info(&file);
        info.SetType(B_MAIL_TYPE);
 }
 
 
 void
-HaikuMailFormatFilter::MessageSent(const entry_ref& ref, BFile* file)
+HaikuMailFormatFilter::MessageSent(const entry_ref& ref, BFile& file)
 {
        mail_flags flags = B_MAIL_SENT;
-       file->WriteAttr(B_MAIL_ATTR_FLAGS, B_INT32_TYPE, 0, &flags, 
sizeof(int32));
-       file->WriteAttr(B_MAIL_ATTR_STATUS, B_STRING_TYPE, 0, "Sent", 5);
+       file.WriteAttr(B_MAIL_ATTR_FLAGS, B_INT32_TYPE, 0, &flags, 
sizeof(int32));
+       file.WriteAttr(B_MAIL_ATTR_STATUS, B_STRING_TYPE, 0, "Sent", 5);
 
        if (!fOutboundDirectory.IsEmpty()) {
                create_directory(fOutboundDirectory, 755);
@@ -243,11 +235,39 @@ HaikuMailFormatFilter::MessageSent(const entry_ref& ref, 
BFile* file)
 }
 
 
-status_t
-HaikuMailFormatFilter::_SetFileName(const entry_ref& ref, const BString& name)
+void
+HaikuMailFormatFilter::_RemoveExtraWhitespace(BString& name)
 {
-       BEntry entry(&ref);
-       return entry.Rename(name);
+       int spaces = 0;
+       for (int i = 0; i <= name.Length();) {
+               if (i < name.Length() && isspace(name.ByteAt(i))) {
+                       spaces++;
+                       i++;
+               } else if (spaces > 0) {
+                       int remove = spaces - 1;
+                       // Also remove leading and trailing spaces
+                       if (i == remove + 1 || i == name.Length())
+                               remove++;
+                       else
+                               name[i - spaces] = ' ';
+                       name.Remove(i - remove, remove);
+                       i -= remove;
+                       spaces = 0;
+               } else
+                       i++;
+       }
+}
+
+
+void
+HaikuMailFormatFilter::_RemoveLeadingDots(BString& name)
+{
+       int dots = 0;
+       while (dots < name.Length() && name.ByteAt(dots) == '.')
+               dots++;
+
+       if (dots > 0)
+               name.Remove(0, dots);
 }
 
 
diff --git a/src/kits/mail/HaikuMailFormatFilter.h 
b/src/kits/mail/HaikuMailFormatFilter.h
index bf16c64..2eebb60 100644
--- a/src/kits/mail/HaikuMailFormatFilter.h
+++ b/src/kits/mail/HaikuMailFormatFilter.h
@@ -1,5 +1,5 @@
 /*
- * Copyright 2011-2012, Haiku, Inc. All rights reserved.
+ * Copyright 2011-2013, Haiku, Inc. All rights reserved.
  * Copyright 2011, Clemens Zeidler <haiku@xxxxxxxxxxxxxxxxxx>
  * Distributed under the terms of the MIT License.
  */
@@ -18,15 +18,14 @@ public:
 
        virtual BString                         DescriptiveName() const;
 
-                       void                            HeaderFetched(const 
entry_ref& ref,
-                                                                       BFile* 
file);
-                       void                            BodyFetched(const 
entry_ref& ref, BFile* file);
+                       BMailFilterAction       HeaderFetched(entry_ref& ref, 
BFile& file);
+                       void                            BodyFetched(const 
entry_ref& ref, BFile& file);
 
-                       void                            MessageSent(const 
entry_ref& ref, BFile* file);
+                       void                            MessageSent(const 
entry_ref& ref, BFile& file);
 
 private:
-                       status_t                        _SetFileName(const 
entry_ref& ref,
-                                                                       const 
BString& name);
+                       void                            
_RemoveExtraWhitespace(BString& name);
+                       void                            
_RemoveLeadingDots(BString& name);
                        BString                         _ExtractName(const 
BString& from);
 
 private:
diff --git a/src/kits/mail/MailFilter.cpp b/src/kits/mail/MailFilter.cpp
index 5ef9115..7c7d626 100644
--- a/src/kits/mail/MailFilter.cpp
+++ b/src/kits/mail/MailFilter.cpp
@@ -1,5 +1,6 @@
 /*
- * Copyright 2011-2012, Haiku, Inc. All rights reserved.
+ * Copyright 2011-2013, Haiku, Inc. All rights reserved.
+ * Distributed under the terms of the MIT License.
  */
 
 
@@ -20,14 +21,15 @@ BMailFilter::~BMailFilter()
 }
 
 
-void
-BMailFilter::HeaderFetched(const entry_ref& ref, BFile* file)
+BMailFilterAction
+BMailFilter::HeaderFetched(entry_ref& ref, BFile& file)
 {
+       return B_NO_MAIL_ACTION;
 }
 
 
 void
-BMailFilter::BodyFetched(const entry_ref& ref, BFile* file)
+BMailFilter::BodyFetched(const entry_ref& ref, BFile& file)
 {
 }
 
@@ -39,12 +41,12 @@ BMailFilter::MailboxSynchronized(status_t status)
 
 
 void
-BMailFilter::MessageReadyToSend(const entry_ref& ref, BFile* file)
+BMailFilter::MessageReadyToSend(const entry_ref& ref, BFile& file)
 {
 }
 
 
 void
-BMailFilter::MessageSent(const entry_ref& ref, BFile* file)
+BMailFilter::MessageSent(const entry_ref& ref, BFile& file)
 {
 }
diff --git a/src/kits/mail/MailProtocol.cpp b/src/kits/mail/MailProtocol.cpp
index 4111315..b39185c 100644
--- a/src/kits/mail/MailProtocol.cpp
+++ b/src/kits/mail/MailProtocol.cpp
@@ -1,5 +1,5 @@
 /*
- * Copyright 2011-2012, Haiku, Inc. All rights reserved.
+ * Copyright 2011-2013, Haiku, Inc. All rights reserved.
  * Copyright 2001-2003 Dr. Zoidberg Enterprises. All rights reserved.
  */
 
@@ -42,12 +42,6 @@ using namespace BPrivate;
 const uint32 kMsgDeleteMessage = '&DeM';
 const uint32 kMsgAppendMessage = '&ApM';
 
-const uint32 kMsgMoveFile = '&MoF';
-const uint32 kMsgDeleteFile = '&DeF';
-const uint32 kMsgFileRenamed = '&FiR';
-const uint32 kMsgFileDeleted = '&FDe';
-const uint32 kMsgInit = '&Ini';
-
 const uint32 kMsgSendMessage = '&SeM';
 
 
@@ -138,48 +132,7 @@ BMailProtocol::RemoveFilter(BMailFilter* filter)
 void
 BMailProtocol::MessageReceived(BMessage* message)
 {
-       switch (message->what) {
-               case kMsgMoveFile:
-               {
-                       entry_ref file;
-                       message->FindRef("file", &file);
-                       entry_ref dir;
-                       message->FindRef("directory", &dir);
-                       BDirectory directory(&dir);
-                       MoveMessage(file, directory);
-                       break;
-               }
-
-               case kMsgDeleteFile:
-               {
-                       entry_ref file;
-                       message->FindRef("file", &file);
-                       DeleteMessage(file);
-                       break;
-               }
-
-               case kMsgFileRenamed:
-               {
-                       entry_ref from;
-                       message->FindRef("from", &from);
-                       entry_ref to;
-                       message->FindRef("to", &to);
-                       FileRenamed(from, to);
-                       break;
-               }
-
-               case kMsgFileDeleted:
-               {
-                       node_ref node;
-                       message->FindInt32("device",&node.device);
-                       message->FindInt64("node", &node.node);
-                       FileDeleted(node);
-                       break;
-               }
-
-               default:
-                       BLooper::MessageReceived(message);
-       }
+       BLooper::MessageReceived(message);
 }
 
 
@@ -200,18 +153,6 @@ BMailProtocol::DeleteMessage(const entry_ref& ref)
 
 
 void
-BMailProtocol::FileRenamed(const entry_ref& from, const entry_ref& to)
-{
-}
-
-
-void
-BMailProtocol::FileDeleted(const node_ref& node)
-{
-}
-
-
-void
 BMailProtocol::ShowError(const char* error)
 {
        if (MailNotifier() != NULL)
@@ -268,16 +209,65 @@ BMailProtocol::NotifyNewMessagesToFetch(int32 count)
 }
 
 
-void
-BMailProtocol::NotifyHeaderFetched(const entry_ref& ref, BFile* data)
+BMailFilterAction
+BMailProtocol::ProcessHeaderFetched(entry_ref& ref, BFile& data)
 {
-       for (int i = 0; i < fFilterList.CountItems(); i++)
-               fFilterList.ItemAt(i)->HeaderFetched(ref, data);
+       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;
+
+                       // 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;
 }
 
 
 void
-BMailProtocol::NotifyBodyFetched(const entry_ref& ref, BFile* data)
+BMailProtocol::NotifyBodyFetched(const entry_ref& ref, BFile& data)
 {
        for (int i = 0; i < fFilterList.CountItems(); i++)
                fFilterList.ItemAt(i)->BodyFetched(ref, data);
@@ -285,7 +275,7 @@ BMailProtocol::NotifyBodyFetched(const entry_ref& ref, 
BFile* data)
 
 
 void
-BMailProtocol::NotifyMessageReadyToSend(const entry_ref& ref, BFile* data)
+BMailProtocol::NotifyMessageReadyToSend(const entry_ref& ref, BFile& data)
 {
        for (int i = 0; i < fFilterList.CountItems(); i++)
                fFilterList.ItemAt(i)->MessageReadyToSend(ref, data);
@@ -293,7 +283,7 @@ BMailProtocol::NotifyMessageReadyToSend(const entry_ref& 
ref, BFile* data)
 
 
 void
-BMailProtocol::NotifyMessageSent(const entry_ref& ref, BFile* data)
+BMailProtocol::NotifyMessageSent(const entry_ref& ref, BFile& data)
 {
        for (int i = 0; i < fFilterList.CountItems(); i++)
                fFilterList.ItemAt(i)->MessageSent(ref, data);


Other related posts:

  • » [haiku-commits] BRANCH axeld-github.imap [fcab7c5] src/kits/mail src/add-ons/mail_daemon/inbound_filters/spam_filter src/add-ons/mail_daemon/inbound_filters/match_header headers/os/add-ons/mail_daemon src/add-ons/mail_daemon - axeld-github . imap