From e13a9d19bcf57da2e07c2604338af820b5f73fb8 Mon Sep 17 00:00:00 2001 From: Vincent Richard Date: Tue, 31 Dec 2013 11:35:29 +0100 Subject: [PATCH] Added support for RFC-3348 (Child Mailbox extension for IMAP). Renamed FLAG_CHILDREN to FLAG_HAS_CHILDREN. --- src/vmime/net/folder.hpp | 4 ++-- src/vmime/net/imap/IMAPConnection.cpp | 14 ++++++++++++++ src/vmime/net/imap/IMAPConnection.hpp | 1 + src/vmime/net/imap/IMAPFolder.cpp | 8 ++++---- src/vmime/net/imap/IMAPParser.hpp | 9 +++++++++ src/vmime/net/imap/IMAPUtils.cpp | 18 ++++++++++++++---- src/vmime/net/imap/IMAPUtils.hpp | 4 +++- src/vmime/net/maildir/maildirFolder.cpp | 2 +- 8 files changed, 48 insertions(+), 12 deletions(-) diff --git a/src/vmime/net/folder.hpp b/src/vmime/net/folder.hpp index 98c88169..3a0781f5 100644 --- a/src/vmime/net/folder.hpp +++ b/src/vmime/net/folder.hpp @@ -97,8 +97,8 @@ public: */ enum Flags { - FLAG_CHILDREN = (1 << 0), /**< Folder contains subfolders. */ - FLAG_NO_OPEN = (1 << 1), /**< Folder cannot be open. */ + FLAG_HAS_CHILDREN = (1 << 0), /**< Folder contains subfolders. */ + FLAG_NO_OPEN = (1 << 1), /**< Folder cannot be open. */ FLAG_UNDEFINED = 9999 /**< Used internally (this should not be returned by the type() function). */ diff --git a/src/vmime/net/imap/IMAPConnection.cpp b/src/vmime/net/imap/IMAPConnection.cpp index 234c2b6a..bab4e58b 100644 --- a/src/vmime/net/imap/IMAPConnection.cpp +++ b/src/vmime/net/imap/IMAPConnection.cpp @@ -540,6 +540,20 @@ bool IMAPConnection::hasCapability(const string& capa) } +bool IMAPConnection::hasCapability(const string& capa) const +{ + const string normCapa = utility::stringUtils::toUpper(capa); + + for (size_t i = 0, n = m_capabilities.size() ; i < n ; ++i) + { + if (m_capabilities[i] == normCapa) + return true; + } + + return false; +} + + void IMAPConnection::invalidateCapabilities() { m_capabilities.clear(); diff --git a/src/vmime/net/imap/IMAPConnection.hpp b/src/vmime/net/imap/IMAPConnection.hpp index b38d0c27..a3156f25 100644 --- a/src/vmime/net/imap/IMAPConnection.hpp +++ b/src/vmime/net/imap/IMAPConnection.hpp @@ -94,6 +94,7 @@ public: void invalidateCapabilities(); const std::vector getCapabilities(); bool hasCapability(const string& capa); + bool hasCapability(const string& capa) const; shared_ptr getAuthenticator(); diff --git a/src/vmime/net/imap/IMAPFolder.cpp b/src/vmime/net/imap/IMAPFolder.cpp index f7de6bfe..83d3e924 100644 --- a/src/vmime/net/imap/IMAPFolder.cpp +++ b/src/vmime/net/imap/IMAPFolder.cpp @@ -118,7 +118,7 @@ int IMAPFolder::getFlags() // Root folder if (m_path.isEmpty()) { - return (FLAG_CHILDREN | FLAG_NO_OPEN); + return (FLAG_HAS_CHILDREN | FLAG_NO_OPEN); } else { @@ -249,7 +249,7 @@ void IMAPFolder::open(const int mode, bool failIfModeIsNotAvailable) (responseData->mailbox_data()->mailbox_flag_list()); m_flags = IMAPUtils::folderFlagsFromFlags - (responseData->mailbox_data()->mailbox_flag_list()); + (connection, responseData->mailbox_data()->mailbox_flag_list()); break; } @@ -502,7 +502,7 @@ int IMAPFolder::testExistAndGetType() (mailboxData->mailbox_list()->mailbox_flag_list()); m_flags = IMAPUtils::folderFlagsFromFlags - (mailboxData->mailbox_list()->mailbox_flag_list()); + (m_connection, mailboxData->mailbox_list()->mailbox_flag_list()); } } @@ -742,7 +742,7 @@ std::vector > IMAPFolder::getFolders(const bool recursive) v.push_back(make_shared (path, store, IMAPUtils::folderTypeFromFlags(mailbox_flag_list), - IMAPUtils::folderFlagsFromFlags(mailbox_flag_list))); + IMAPUtils::folderFlagsFromFlags(m_connection, mailbox_flag_list))); } } diff --git a/src/vmime/net/imap/IMAPParser.hpp b/src/vmime/net/imap/IMAPParser.hpp index ad5d57a2..53e9a3c0 100644 --- a/src/vmime/net/imap/IMAPParser.hpp +++ b/src/vmime/net/imap/IMAPParser.hpp @@ -1811,6 +1811,10 @@ public: m_type = NOSELECT; else if (name == "unmarked") m_type = UNMARKED; + else if (name == "haschildren") + m_type = HASCHILDREN; + else if (name == "hasnochildren") + m_type = HASNOCHILDREN; else { m_type = UNKNOWN; @@ -1833,6 +1837,11 @@ public: enum Type { + // RFC-3348 - Child Mailbox Extension + HASCHILDREN, + HASNOCHILDREN, + + // Standard mailbox flags UNKNOWN, MARKED, NOINFERIORS, diff --git a/src/vmime/net/imap/IMAPUtils.cpp b/src/vmime/net/imap/IMAPUtils.cpp index 00f84d44..a58035cb 100644 --- a/src/vmime/net/imap/IMAPUtils.cpp +++ b/src/vmime/net/imap/IMAPUtils.cpp @@ -386,10 +386,16 @@ int IMAPUtils::folderTypeFromFlags(const IMAPParser::mailbox_flag_list* list) } -int IMAPUtils::folderFlagsFromFlags(const IMAPParser::mailbox_flag_list* list) +int IMAPUtils::folderFlagsFromFlags + (shared_ptr cnt, const IMAPParser::mailbox_flag_list* list) { - // Get folder flags - int folderFlags = folder::FLAG_CHILDREN; + int folderFlags = 0; + + // If CHILDREN extension (RFC-3348) is not supported, assume folder has children + // as we have no hint about it + if (!cnt->hasCapability("CHILDREN")) + folderFlags |= folder::FLAG_HAS_CHILDREN; + const std::vector & flags = list->flags(); for (std::vector ::const_iterator it = flags.begin() ; @@ -398,7 +404,11 @@ int IMAPUtils::folderFlagsFromFlags(const IMAPParser::mailbox_flag_list* list) if ((*it)->type() == IMAPParser::mailbox_flag::NOSELECT) folderFlags |= folder::FLAG_NO_OPEN; else if ((*it)->type() == IMAPParser::mailbox_flag::NOINFERIORS) - folderFlags &= ~folder::FLAG_CHILDREN; + folderFlags &= ~folder::FLAG_HAS_CHILDREN; + else if ((*it)->type() == IMAPParser::mailbox_flag::HASNOCHILDREN) + folderFlags &= ~folder::FLAG_HAS_CHILDREN; + else if ((*it)->type() == IMAPParser::mailbox_flag::HASCHILDREN) + folderFlags |= folder::FLAG_HAS_CHILDREN; } return (folderFlags); diff --git a/src/vmime/net/imap/IMAPUtils.hpp b/src/vmime/net/imap/IMAPUtils.hpp index afca98d6..55443cfc 100644 --- a/src/vmime/net/imap/IMAPUtils.hpp +++ b/src/vmime/net/imap/IMAPUtils.hpp @@ -67,7 +67,9 @@ public: static const string quoteString(const string& text); static int folderTypeFromFlags(const IMAPParser::mailbox_flag_list* list); - static int folderFlagsFromFlags(const IMAPParser::mailbox_flag_list* list); + static int folderFlagsFromFlags + (shared_ptr cnt, + const IMAPParser::mailbox_flag_list* list); static int messageFlagsFromFlags(const IMAPParser::flag_list* list); diff --git a/src/vmime/net/maildir/maildirFolder.cpp b/src/vmime/net/maildir/maildirFolder.cpp index 7280f639..7bcbc04f 100644 --- a/src/vmime/net/maildir/maildirFolder.cpp +++ b/src/vmime/net/maildir/maildirFolder.cpp @@ -105,7 +105,7 @@ int maildirFolder::getFlags() int flags = 0; if (m_store.lock()->getFormat()->folderHasSubfolders(m_path)) - flags |= FLAG_CHILDREN; // Contains at least one sub-folder + flags |= FLAG_HAS_CHILDREN; // Contains at least one sub-folder return (flags); }