[haiku-commits] BRANCH axeld-github.imap - in src: add-ons/mail_daemon/inbound_protocols/imap/imap_lib add-ons/mail_daemon/inbound_protocols/imap tests/add-ons/mail/imap

  • From: axeld-github.imap <community@xxxxxxxxxxxx>
  • To: haiku-commits@xxxxxxxxxxxxx
  • Date: Fri, 19 Apr 2013 23:45:49 +0200 (CEST)

added 1 changeset to branch 'refs/remotes/axeld-github/imap'
old head: f79e74cddf027a87ca86cede7974e54ccc73d3d1
new head: d10b838e460a596c57968f5fd12ee5d9818e84aa
overview: https://github.com/axeld/haiku/compare/f79e74c...d10b838

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

d10b838: imap: WIP of getting fetching headers to work.
  
  * Changed the FetchListener mechanism quite a bit.
  * Doesn't seem to work correctly yet, although most pieces are in
    place now.

                                   [ Axel Dörfler <axeld@xxxxxxxxxxxxxxxx> ]

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

Commit:      d10b838e460a596c57968f5fd12ee5d9818e84aa
Author:      Axel Dörfler <axeld@xxxxxxxxxxxxxxxx>
Date:        Fri Apr 19 21:29:34 2013 UTC

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

9 files changed, 170 insertions(+), 50 deletions(-)
.../imap/IMAPConnectionWorker.cpp                | 21 ++++++--
.../inbound_protocols/imap/IMAPFolder.cpp        | 52 +++++++++++++++++++-
.../inbound_protocols/imap/IMAPFolder.h          |  8 ++-
.../inbound_protocols/imap/imap_lib/Commands.cpp | 46 ++++++++---------
.../inbound_protocols/imap/imap_lib/Commands.h   | 21 ++++----
.../inbound_protocols/imap/imap_lib/Protocol.cpp | 28 +++++++++++
.../inbound_protocols/imap/imap_lib/Response.cpp |  6 ++-
.../inbound_protocols/imap/imap_lib/Response.h   |  3 +-
src/tests/add-ons/mail/imap/imap_tester.cpp      | 35 ++++++++-----

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

diff --git 
a/src/add-ons/mail_daemon/inbound_protocols/imap/IMAPConnectionWorker.cpp 
b/src/add-ons/mail_daemon/inbound_protocols/imap/IMAPConnectionWorker.cpp
index eea0214..746226f 100644
--- a/src/add-ons/mail_daemon/inbound_protocols/imap/IMAPConnectionWorker.cpp
+++ b/src/add-ons/mail_daemon/inbound_protocols/imap/IMAPConnectionWorker.cpp
@@ -112,7 +112,7 @@ public:
 };
 
 
-class FetchHeadersCommand : public WorkerCommand {
+class FetchHeadersCommand : public WorkerCommand, public IMAP::FetchListener {
 public:
        FetchHeadersCommand(IMAPFolder& folder, IMAPMailbox& mailbox,
                uint32 from, uint32 to)
@@ -133,11 +133,11 @@ public:
                if (status != B_OK)
                        return status;
 
-               // TODO: create messages!
                // TODO: trigger download of mails for all messages below the
                // body fetch limit
-               // TODO: we would really like to have the message flags at this 
point
                IMAP::FetchCommand fetch(fFrom, fTo, IMAP::kFetchHeader);
+               fetch.SetListener(this);
+
                status = protocol.ProcessCommand(fetch);
                if (status != B_OK)
                        return status;
@@ -145,11 +145,26 @@ public:
                return B_OK;
        }
 
+       virtual bool FetchData(uint32 fetchFlags, BDataIO& stream, size_t 
length)
+       {
+               fFetchStatus = fFolder.StoreTemporaryMessage(fetchFlags, stream,
+                       length, fRef);
+               return true;
+       }
+
+       virtual void FetchedData(uint32 fetchFlags, uint32 uid, uint32 flags)
+       {
+               if (fFetchStatus == B_OK)
+                       fFolder.StoreMessage(fetchFlags, uid, flags, fRef);
+       }
+
 private:
        IMAPFolder&                             fFolder;
        IMAPMailbox&                    fMailbox;
        uint32                                  fFrom;
        uint32                                  fTo;
+       entry_ref                               fRef;
+       status_t                                fFetchStatus;
 };
 
 
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 4c3d40a..3b7cda6 100644
--- a/src/add-ons/mail_daemon/inbound_protocols/imap/IMAPFolder.cpp
+++ b/src/add-ons/mail_daemon/inbound_protocols/imap/IMAPFolder.cpp
@@ -11,8 +11,10 @@
 #include <ByteOrder.h>
 #include <Debug.h>
 #include <Directory.h>
+#include <File.h>
 #include <fs_attr.h>
 #include <Node.h>
+#include <Path.h>
 
 
 static const char* kMailboxNameAttribute = "IMAP:mailbox";
@@ -95,9 +97,57 @@ IMAPFolder::SetUIDValidity(uint32 uidValidity)
 }
 
 
+status_t
+IMAPFolder::StoreTemporaryMessage(uint32 fetchFlags, BDataIO& stream,
+       size_t length, entry_ref& ref)
+{
+       BPath path;
+       status_t status = path.SetTo(&fRef);
+       if (status != B_OK)
+               return status;
+
+       path.Append("tmp1234");
+
+       BFile file;
+       status = (path.Path(), B_CREATE_FILE);
+       if (status != B_OK)
+               return status;
+
+       get_ref_for_path(path.Path(), &ref);
+
+       char buffer[65535];
+       while (length > 0) {
+               ssize_t bytesRead = stream.Read(buffer,
+                       min_c(sizeof(buffer), length));
+               if (bytesRead <= 0)
+                       break;
+
+               file.Write(buffer, bytesRead);
+               length -= bytesRead;
+       }
+
+       return B_OK;
+}
+
+
 void
-IMAPFolder::StoreMessage(uint32 uid, ...)
+IMAPFolder::StoreMessage(uint32 fetchFlags, uint32 uid, uint32 flags,
+       entry_ref& ref)
+{
+       BString name = "mail-";
+       name << uid;
+
+       // TODO: remove renaming as its superfluous here
+       BEntry entry(&ref);
+       entry.Rename(name.String());
+}
+
+
+status_t
+IMAPFolder::StoreMessage(uint32 fetchFlags, uint32 uid, BDataIO& stream,
+       size_t length)
 {
+       return B_ERROR;
 }
 
 
diff --git a/src/add-ons/mail_daemon/inbound_protocols/imap/IMAPFolder.h 
b/src/add-ons/mail_daemon/inbound_protocols/imap/IMAPFolder.h
index 11a69aa..1b8b2e5 100644
--- a/src/add-ons/mail_daemon/inbound_protocols/imap/IMAPFolder.h
+++ b/src/add-ons/mail_daemon/inbound_protocols/imap/IMAPFolder.h
@@ -45,7 +45,13 @@ public:
                        void                            
SetListener(FolderListener* listener);
                        void                            SetUIDValidity(uint32 
uidValidity);
 
-                       void                            StoreMessage(uint32 
uid, ...);
+                       status_t                        
StoreTemporaryMessage(uint32 fetchFlags,
+                                                                       
BDataIO& stream, size_t length,
+                                                                       
entry_ref& ref);
+                       void                            StoreMessage(uint32 
fetchFlags, uint32 uid,
+                                                                       uint32 
flags, entry_ref& ref);
+                       status_t                        StoreMessage(uint32 
fetchFlags, uint32 uid,
+                                                                       
BDataIO& stream, size_t length);
                        void                            DeleteMessage(uint32 
uid);
                        void                            SetMessageFlags(uint32 
uid, uint32 flags);
 
diff --git 
a/src/add-ons/mail_daemon/inbound_protocols/imap/imap_lib/Commands.cpp 
b/src/add-ons/mail_daemon/inbound_protocols/imap/imap_lib/Commands.cpp
index e7adfab..0a60206 100644
--- a/src/add-ons/mail_daemon/inbound_protocols/imap/imap_lib/Commands.cpp
+++ b/src/add-ons/mail_daemon/inbound_protocols/imap/imap_lib/Commands.cpp
@@ -330,11 +330,11 @@ FetchMessageEntriesCommand::HandleUntagged(Response& 
response)
 // #pragma mark -
 
 
-FetchCommand::FetchCommand(uint32 from, uint32 to, FetchMode mode)
+FetchCommand::FetchCommand(uint32 from, uint32 to, uint32 flags)
        :
        fFrom(from),
        fTo(to),
-       fMode(mode)
+       fFlags(flags)
 {
 }
 
@@ -355,7 +355,9 @@ FetchCommand::CommandString()
                command << ":" << fTo;
 
        command += " (UID ";
-       switch (fMode) {
+       if ((fFlags & kFetchFlags) != 0)
+               command += "FLAGS ";
+       switch (fFlags & kFetchAll) {
                case kFetchHeader:
                        command += "RFC822.HEADER";
                        break;
@@ -378,35 +380,35 @@ FetchCommand::HandleUntagged(Response& response)
        if (!response.EqualsAt(1, "FETCH") || !response.IsListAt(2))
                return false;
 
-       // We don't need to parse anything here - all the data is processed via
-       // HandleLiteral().
+       ArgumentList& list = response.ListAt(2);
+       uint32 uid = 0;
+       uint32 flags = 0;
+
+       for (int32 i = 0; i < list.CountItems(); i += 2) {
+               if (list.EqualsAt(i, "UID") && list.IsNumberAt(i + 1))
+                       uid = list.NumberAt(i + 1);
+               else if (list.EqualsAt(i, "FLAGS") && list.IsListAt(i + 1)) {
+                       // Parse flags
+                       ArgumentList& flagList = list.ListAt(i + 1);
+                       flags = ParseFlags(flagList);
+               }
+       }
+
+       if (fListener != NULL)
+               fListener->FetchedData(fFlags, uid, flags);
        return true;
 }
 
 
 bool
-FetchCommand::HandleLiteral(Response& response, BDataIO& stream,
-       size_t length)
+FetchCommand::HandleLiteral(Response& response, ArgumentList& arguments,
+       BDataIO& stream, size_t length)
 {
        if (fListener == NULL || !response.EqualsAt(1, "FETCH")
                || !response.IsListAt(2))
                return false;
 
-       uint32 uid = 0;
-
-       // Get current UID
-       ArgumentList& list = response.ListAt(2);
-       for (int32 i = 0; i < list.CountItems(); i += 2) {
-               if (list.EqualsAt(i, "UID") && list.IsNumberAt(i + 1)) {
-                       uid = list.NumberAt(i + 1);
-                       break;
-               }
-       }
-
-       if (uid == 0)
-               return false;
-
-       return fListener->FetchData(response, uid, fMode, stream, length);
+       return fListener->FetchData(fFlags, stream, length);
 }
 
 
diff --git a/src/add-ons/mail_daemon/inbound_protocols/imap/imap_lib/Commands.h 
b/src/add-ons/mail_daemon/inbound_protocols/imap/imap_lib/Commands.h
index 8a547bc..4284409 100644
--- a/src/add-ons/mail_daemon/inbound_protocols/imap/imap_lib/Commands.h
+++ b/src/add-ons/mail_daemon/inbound_protocols/imap/imap_lib/Commands.h
@@ -136,18 +136,20 @@ private:
 };
 
 
-enum FetchMode {
-       kFetchHeader,
-       kFetchBody,
-       kFetchAll
+enum FetchFlags {
+       kFetchHeader    = 0x01,
+       kFetchBody              = 0x02,
+       kFetchAll               = kFetchHeader | kFetchBody,
+       kFetchFlags             = 0x04,
 };
 
 
 class FetchListener {
 public:
-       virtual bool                            FetchData(Response& reponse, 
uint32 uid,
-                                                                       
FetchMode mode, BDataIO& stream,
+       virtual bool                            FetchData(uint32 fetchFlags, 
BDataIO& stream,
                                                                        size_t 
length) = 0;
+       virtual void                            FetchedData(uint32 fetchFlags, 
uint32 uid,
+                                                                       uint32 
flags) = 0;
 };
 
 
@@ -155,7 +157,7 @@ class FetchCommand : public Command, public Handler,
        public LiteralHandler {
 public:
                                                                
FetchCommand(uint32 from, uint32 to,
-                                                                       
FetchMode mode);
+                                                                       uint32 
fetchFlags);
 
                        void                            
SetListener(FetchListener* listener);
                        FetchListener*          Listener() const { return 
fListener; }
@@ -163,12 +165,13 @@ public:
        virtual BString                         CommandString();
        virtual bool                            HandleUntagged(Response& 
response);
        virtual bool                            HandleLiteral(Response& 
response,
-                                                                       
BDataIO& stream, size_t length);
+                                                                       
ArgumentList& arguments, BDataIO& stream,
+                                                                       size_t 
length);
 
 private:
                        uint32                          fFrom;
                        uint32                          fTo;
-                       FetchMode                       fMode;
+                       uint32                          fFlags;
                        FetchListener*          fListener;
 };
 
diff --git 
a/src/add-ons/mail_daemon/inbound_protocols/imap/imap_lib/Protocol.cpp 
b/src/add-ons/mail_daemon/inbound_protocols/imap/imap_lib/Protocol.cpp
index 88adcad..9a50cf1 100644
--- a/src/add-ons/mail_daemon/inbound_protocols/imap/imap_lib/Protocol.cpp
+++ b/src/add-ons/mail_daemon/inbound_protocols/imap/imap_lib/Protocol.cpp
@@ -85,6 +85,34 @@ Protocol::Connect(const BNetworkAddress& address, const 
char* username,
                _ParseCapabilities(capabilityHandler.Capabilities());
        }
 
+       if (Capabilities().Contains("ID")) {
+               // Get the server's ID into our log
+               class IDCommand : public IMAP::Command, public IMAP::Handler {
+               public:
+                       BString CommandString()
+                       {
+                               return "ID NIL";
+                       }
+
+                       bool HandleUntagged(IMAP::Response& response)
+                       {
+                               if (response.IsCommand("ID") && 
response.IsListAt(1)) {
+                                       puts("Server:");
+                                       ArgumentList& list = response.ListAt(1);
+                                       for (int32 i = 0; i < 
list.CountItems(); i += 2) {
+                                               printf("  %s: %s\n",
+                                                       
list.ItemAt(i)->ToString().String(),
+                                                       list.ItemAt(i + 
1)->ToString().String());
+                                       }
+                                       return true;
+                               }
+
+                               return false;
+                       }
+               };
+               IDCommand idCommand;
+               ProcessCommand(idCommand);
+       }
        return B_OK;
 }
 
diff --git 
a/src/add-ons/mail_daemon/inbound_protocols/imap/imap_lib/Response.cpp 
b/src/add-ons/mail_daemon/inbound_protocols/imap/imap_lib/Response.cpp
index d27b4c4..446d2c1 100644
--- a/src/add-ons/mail_daemon/inbound_protocols/imap/imap_lib/Response.cpp
+++ b/src/add-ons/mail_daemon/inbound_protocols/imap/imap_lib/Response.cpp
@@ -583,8 +583,10 @@ Response::ParseLiteral(ArgumentList& arguments, BDataIO& 
stream)
        Consume(stream, '\n');
 
        bool handled = false;
-       if (fLiteralHandler != NULL)
-               handled = fLiteralHandler->HandleLiteral(*this, stream, size);
+       if (fLiteralHandler != NULL) {
+               handled = fLiteralHandler->HandleLiteral(*this, arguments, 
stream,
+                       size);
+       }
 
        if (!handled) {
                // The default implementation just adds the data as a string
diff --git a/src/add-ons/mail_daemon/inbound_protocols/imap/imap_lib/Response.h 
b/src/add-ons/mail_daemon/inbound_protocols/imap/imap_lib/Response.h
index 7460cf4..584ce6c 100644
--- a/src/add-ons/mail_daemon/inbound_protocols/imap/imap_lib/Response.h
+++ b/src/add-ons/mail_daemon/inbound_protocols/imap/imap_lib/Response.h
@@ -129,7 +129,8 @@ public:
        virtual                                         ~LiteralHandler();
 
        virtual bool                            HandleLiteral(Response& 
response,
-                                                                       
BDataIO& stream, size_t length) = 0;
+                                                                       
ArgumentList& arguments, BDataIO& stream,
+                                                                       size_t 
length) = 0;
 };
 
 
diff --git a/src/tests/add-ons/mail/imap/imap_tester.cpp 
b/src/tests/add-ons/mail/imap/imap_tester.cpp
index c77c912..95ddc86 100644
--- a/src/tests/add-ons/mail/imap/imap_tester.cpp
+++ b/src/tests/add-ons/mail/imap/imap_tester.cpp
@@ -87,17 +87,17 @@ do_fetch(int argc, char** argv)
 {
        uint32 from = 1;
        uint32 to;
-       IMAP::FetchMode mode = IMAP::kFetchAll;
+       uint32 flags = IMAP::kFetchAll;
        if (argc < 2) {
                printf("usage: %s [<from>] [<to>] [header|body]\n", argv[0]);
                return;
        }
        if (argc > 2) {
                if (!strcasecmp(argv[argc - 1], "header")) {
-                       mode = IMAP::kFetchHeader;
+                       flags = IMAP::kFetchHeader;
                        argc--;
                } else if (!strcasecmp(argv[argc - 1], "body")) {
-                       mode = IMAP::kFetchBody;
+                       flags = IMAP::kFetchBody;
                        argc--;
                }
        }
@@ -107,15 +107,20 @@ do_fetch(int argc, char** argv)
        } else
                from = to = atoul(argv[1]);
 
-       IMAP::FetchCommand command(from, to, mode);
+       IMAP::FetchCommand command(from, to, flags | IMAP::kFetchFlags);
 
        // A fetch listener that dumps everything to stdout
        class Listener : public IMAP::FetchListener {
        public:
-               virtual bool FetchData(IMAP::Response& reponse, uint32 uid,
-                       IMAP::FetchMode mode, BDataIO& stream, size_t length)
+               virtual ~Listener()
                {
-                       BMallocIO copy;
+               }
+
+               virtual bool FetchData(uint32 fetchFlags, BDataIO& stream,
+                       size_t length)
+               {
+                       fBuffer.SetSize(0);
+
                        char buffer[65535];
                        while (length > 0) {
                                ssize_t bytesRead = stream.Read(buffer,
@@ -123,18 +128,26 @@ do_fetch(int argc, char** argv)
                                if (bytesRead <= 0)
                                        break;
 
-                               copy.Write(buffer, bytesRead);
+                               fBuffer.Write(buffer, bytesRead);
                                length -= bytesRead;
                        }
 
                        // Null terminate the buffer
                        char null = '\0';
-                       copy.Write(&null, 1);
+                       fBuffer.Write(&null, 1);
 
-                       printf("================= UID %ld =================\n", 
uid);
-                       puts((const char*)copy.Buffer());
                        return true;
                }
+
+               virtual void FetchedData(uint32 fetchFlags, uint32 uid, uint32 
flags)
+               {
+                       printf("================= UID %ld, flags %lx 
=================\n",
+                               uid, flags);
+                       puts((const char*)fBuffer.Buffer());
+               }
+
+       private:
+               BMallocIO       fBuffer;
        } listener;
 
        command.SetListener(&listener);


Other related posts: