diff options
Diffstat (limited to 'src/vmime/net')
155 files changed, 9306 insertions, 7834 deletions
diff --git a/src/vmime/net/builtinServices.inl b/src/vmime/net/builtinServices.inl index fa2f3fe3..2f67d2e0 100644 --- a/src/vmime/net/builtinServices.inl +++ b/src/vmime/net/builtinServices.inl @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard <[email protected]> +// Copyright (C) 2002 Vincent Richard <[email protected]> // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License as diff --git a/src/vmime/net/connectionInfos.hpp b/src/vmime/net/connectionInfos.hpp index 6c86eeab..0e519c7e 100644 --- a/src/vmime/net/connectionInfos.hpp +++ b/src/vmime/net/connectionInfos.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard <[email protected]> +// Copyright (C) 2002 Vincent Richard <[email protected]> // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License as @@ -40,8 +40,8 @@ namespace net { /** Information about the connection used by a service. */ -class VMIME_EXPORT connectionInfos : public object -{ +class VMIME_EXPORT connectionInfos : public object { + public: /** Return the host to which the service is connected. diff --git a/src/vmime/net/defaultConnectionInfos.cpp b/src/vmime/net/defaultConnectionInfos.cpp index 335e8f6f..889f214a 100644 --- a/src/vmime/net/defaultConnectionInfos.cpp +++ b/src/vmime/net/defaultConnectionInfos.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard <[email protected]> +// Copyright (C) 2002 Vincent Richard <[email protected]> // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License as @@ -35,19 +35,19 @@ namespace net { defaultConnectionInfos::defaultConnectionInfos(const string& host, const port_t port) - : m_host(host), m_port(port) -{ + : m_host(host), m_port(port) { + } -const string defaultConnectionInfos::getHost() const -{ +const string defaultConnectionInfos::getHost() const { + return m_host; } -port_t defaultConnectionInfos::getPort() const -{ +port_t defaultConnectionInfos::getPort() const { + return m_port; } diff --git a/src/vmime/net/defaultConnectionInfos.hpp b/src/vmime/net/defaultConnectionInfos.hpp index 50673bbc..f3488595 100644 --- a/src/vmime/net/defaultConnectionInfos.hpp +++ b/src/vmime/net/defaultConnectionInfos.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard <[email protected]> +// Copyright (C) 2002 Vincent Richard <[email protected]> // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License as @@ -40,8 +40,8 @@ namespace net { /** Information about the connection used by a service. */ -class VMIME_EXPORT defaultConnectionInfos : public connectionInfos -{ +class VMIME_EXPORT defaultConnectionInfos : public connectionInfos { + public: defaultConnectionInfos(const string& host, const port_t port); diff --git a/src/vmime/net/defaultTimeoutHandler.cpp b/src/vmime/net/defaultTimeoutHandler.cpp index 306289c0..f5dcc7d6 100644 --- a/src/vmime/net/defaultTimeoutHandler.cpp +++ b/src/vmime/net/defaultTimeoutHandler.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2014 Vincent Richard <[email protected]> +// Copyright (C) 2002 Vincent Richard <[email protected]> // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License as @@ -34,39 +34,39 @@ namespace vmime { namespace net { -defaultTimeoutHandler::defaultTimeoutHandler() -{ +defaultTimeoutHandler::defaultTimeoutHandler() { + m_startTime = time(NULL); } -defaultTimeoutHandler::~defaultTimeoutHandler() -{ +defaultTimeoutHandler::~defaultTimeoutHandler() { + } -bool defaultTimeoutHandler::isTimeOut() -{ +bool defaultTimeoutHandler::isTimeOut() { + return time(NULL) - m_startTime >= 30; } -void defaultTimeoutHandler::resetTimeOut() -{ +void defaultTimeoutHandler::resetTimeOut() { + m_startTime = time(NULL); } -bool defaultTimeoutHandler::handleTimeOut() -{ +bool defaultTimeoutHandler::handleTimeOut() { + return false; } -shared_ptr <timeoutHandler> defaultTimeoutHandlerFactory::create() -{ +shared_ptr <timeoutHandler> defaultTimeoutHandlerFactory::create() { + return make_shared <defaultTimeoutHandler>(); } diff --git a/src/vmime/net/defaultTimeoutHandler.hpp b/src/vmime/net/defaultTimeoutHandler.hpp index a45b9739..545c6550 100644 --- a/src/vmime/net/defaultTimeoutHandler.hpp +++ b/src/vmime/net/defaultTimeoutHandler.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2014 Vincent Richard <[email protected]> +// Copyright (C) 2002 Vincent Richard <[email protected]> // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License as @@ -44,9 +44,8 @@ namespace net { * is to throw a exceptions::operation_timed_out exception when an * operation is blocked for more than 30 seconds. */ +class VMIME_EXPORT defaultTimeoutHandler : public timeoutHandler { -class VMIME_EXPORT defaultTimeoutHandler : public timeoutHandler -{ public: defaultTimeoutHandler(); @@ -64,9 +63,8 @@ private: /** A class that creates default timeout handlers. */ +class defaultTimeoutHandlerFactory : public timeoutHandlerFactory { -class defaultTimeoutHandlerFactory : public timeoutHandlerFactory -{ public: shared_ptr <timeoutHandler> create(); diff --git a/src/vmime/net/events.cpp b/src/vmime/net/events.cpp index 45f7f98e..86608127 100644 --- a/src/vmime/net/events.cpp +++ b/src/vmime/net/events.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard <[email protected]> +// Copyright (C) 2002 Vincent Richard <[email protected]> // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License as @@ -42,13 +42,13 @@ namespace events { // event // -event::event() -{ +event::event() { + } -event::~event() -{ +event::~event() { + } @@ -59,10 +59,14 @@ event::~event() const char* messageCountEvent::EVENT_CLASS = "messageCountEvent"; -messageCountEvent::messageCountEvent - (shared_ptr <folder> folder, const Types type, const std::vector <size_t>& nums) - : m_folder(folder), m_type(type) -{ +messageCountEvent::messageCountEvent( + const shared_ptr <folder>& folder, + const Types type, + const std::vector <size_t>& nums +) + : m_folder(folder), + m_type(type) { + m_nums.resize(nums.size()); std::copy(nums.begin(), nums.end(), m_nums.begin()); } @@ -73,17 +77,18 @@ messageCountEvent::Types messageCountEvent::getType() const { return (m_type); } const std::vector <size_t>& messageCountEvent::getNumbers() const { return (m_nums); } -void messageCountEvent::dispatch(messageCountListener* listener) -{ - if (m_type == TYPE_ADDED) +void messageCountEvent::dispatch(messageCountListener* listener) { + + if (m_type == TYPE_ADDED) { listener->messagesAdded(dynamicCast <messageCountEvent>(shared_from_this())); - else + } else { listener->messagesRemoved(dynamicCast <messageCountEvent>(shared_from_this())); + } } -const char* messageCountEvent::getClass() const -{ +const char* messageCountEvent::getClass() const { + return EVENT_CLASS; } @@ -95,10 +100,14 @@ const char* messageCountEvent::getClass() const const char* messageChangedEvent::EVENT_CLASS = "messageChangedEvent"; -messageChangedEvent::messageChangedEvent - (shared_ptr <folder> folder, const Types type, const std::vector <size_t>& nums) - : m_folder(folder), m_type(type) -{ +messageChangedEvent::messageChangedEvent( + const shared_ptr <folder>& folder, + const Types type, + const std::vector <size_t>& nums +) + : m_folder(folder), + m_type(type) { + m_nums.resize(nums.size()); std::copy(nums.begin(), nums.end(), m_nums.begin()); } @@ -109,14 +118,14 @@ messageChangedEvent::Types messageChangedEvent::getType() const { return (m_type const std::vector <size_t>& messageChangedEvent::getNumbers() const { return (m_nums); } -void messageChangedEvent::dispatch(messageChangedListener* listener) -{ +void messageChangedEvent::dispatch(messageChangedListener* listener) { + listener->messageChanged(dynamicCast <messageChangedEvent>(shared_from_this())); } -const char* messageChangedEvent::getClass() const -{ +const char* messageChangedEvent::getClass() const { + return EVENT_CLASS; } @@ -128,11 +137,17 @@ const char* messageChangedEvent::getClass() const const char* folderEvent::EVENT_CLASS = "folderEvent"; -folderEvent::folderEvent - (shared_ptr <folder> folder, const Types type, - const utility::path& oldPath, const utility::path& newPath) - : m_folder(folder), m_type(type), m_oldPath(oldPath), m_newPath(newPath) -{ +folderEvent::folderEvent( + const shared_ptr <folder>& folder, + const Types type, + const utility::path& oldPath, + const utility::path& newPath +) + : m_folder(folder), + m_type(type), + m_oldPath(oldPath), + m_newPath(newPath) { + } @@ -140,19 +155,18 @@ shared_ptr <folder> folderEvent::getFolder() const { return (m_folder); } folderEvent::Types folderEvent::getType() const { return (m_type); } -void folderEvent::dispatch(folderListener* listener) -{ - switch (m_type) - { - case TYPE_CREATED: listener->folderCreated(dynamicCast <folderEvent>(shared_from_this())); break; - case TYPE_RENAMED: listener->folderRenamed(dynamicCast <folderEvent>(shared_from_this())); break; - case TYPE_DELETED: listener->folderDeleted(dynamicCast <folderEvent>(shared_from_this())); break; +void folderEvent::dispatch(folderListener* listener) { + + switch (m_type) { + case TYPE_CREATED: listener->folderCreated(dynamicCast <folderEvent>(shared_from_this())); break; + case TYPE_RENAMED: listener->folderRenamed(dynamicCast <folderEvent>(shared_from_this())); break; + case TYPE_DELETED: listener->folderDeleted(dynamicCast <folderEvent>(shared_from_this())); break; } } -const char* folderEvent::getClass() const -{ +const char* folderEvent::getClass() const { + return EVENT_CLASS; } diff --git a/src/vmime/net/events.hpp b/src/vmime/net/events.hpp index 60d15bd9..2ad64e79 100644 --- a/src/vmime/net/events.hpp +++ b/src/vmime/net/events.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard <[email protected]> +// Copyright (C) 2002 Vincent Richard <[email protected]> // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License as @@ -46,9 +46,8 @@ namespace events { /** Event occurring on folders or messages. */ +class VMIME_EXPORT event : public object, public enable_shared_from_this <event> { -class VMIME_EXPORT event : public object, public enable_shared_from_this <event> -{ public: event(); @@ -60,22 +59,24 @@ public: /** Event about the message count in a folder. */ +class VMIME_EXPORT messageCountEvent : public event { -class VMIME_EXPORT messageCountEvent : public event -{ public: static const char* EVENT_CLASS; - enum Types - { + enum Types { TYPE_ADDED, /**< New messages have been added. */ TYPE_REMOVED /**< Messages have been expunged (renumbering). */ }; - messageCountEvent(shared_ptr <folder> folder, const Types type, const std::vector <size_t>& nums); + messageCountEvent( + const shared_ptr <folder>& folder, + const Types type, + const std::vector <size_t>& nums + ); /** Return the folder in which messages have been added/removed. * @@ -114,37 +115,38 @@ private: /** Listener for events about the message count in a folder. */ +class VMIME_EXPORT messageCountListener { -class VMIME_EXPORT messageCountListener -{ protected: virtual ~messageCountListener() { } public: - virtual void messagesAdded(shared_ptr <messageCountEvent> event) = 0; - virtual void messagesRemoved(shared_ptr <messageCountEvent> event) = 0; + virtual void messagesAdded(const shared_ptr <messageCountEvent>& event) = 0; + virtual void messagesRemoved(const shared_ptr <messageCountEvent>& event) = 0; }; /** Event occuring on a message. */ +class VMIME_EXPORT messageChangedEvent : public event { -class VMIME_EXPORT messageChangedEvent : public event -{ public: static const char* EVENT_CLASS; - enum Types - { + enum Types { TYPE_FLAGS // flags changed }; - messageChangedEvent(shared_ptr <folder> folder, const Types type, const std::vector <size_t>& nums); + messageChangedEvent( + const shared_ptr <folder>& folder, + const Types type, + const std::vector <size_t>& nums + ); /** Return the folder in which messages have changed. * @@ -183,38 +185,40 @@ private: /** Listener for events occuring on a message. */ +class VMIME_EXPORT messageChangedListener { -class VMIME_EXPORT messageChangedListener -{ protected: virtual ~messageChangedListener() { } public: - virtual void messageChanged(shared_ptr <messageChangedEvent> event) = 0; + virtual void messageChanged(const shared_ptr <messageChangedEvent>& event) = 0; }; /** Event occuring on a folder. */ +class VMIME_EXPORT folderEvent : public event { -class VMIME_EXPORT folderEvent : public event -{ public: static const char* EVENT_CLASS; - enum Types - { + enum Types { TYPE_CREATED, /**< A folder was created. */ TYPE_DELETED, /**< A folder was deleted. */ TYPE_RENAMED /**< A folder was renamed. */ }; - folderEvent(shared_ptr <folder> folder, const Types type, const utility::path& oldPath, const utility::path& newPath); + folderEvent( + const shared_ptr <folder>& folder, + const Types type, + const utility::path& oldPath, + const utility::path& newPath + ); /** Return the folder on which the event occurred. * @@ -248,18 +252,17 @@ private: /** Listener for events occuring on a folder. */ +class VMIME_EXPORT folderListener { -class VMIME_EXPORT folderListener -{ protected: virtual ~folderListener() { } public: - virtual void folderCreated(shared_ptr <folderEvent> event) = 0; - virtual void folderRenamed(shared_ptr <folderEvent> event) = 0; - virtual void folderDeleted(shared_ptr <folderEvent> event) = 0; + virtual void folderCreated(const shared_ptr <folderEvent>& event) = 0; + virtual void folderRenamed(const shared_ptr <folderEvent>& event) = 0; + virtual void folderDeleted(const shared_ptr <folderEvent>& event) = 0; }; diff --git a/src/vmime/net/fetchAttributes.cpp b/src/vmime/net/fetchAttributes.cpp index d499674c..d9b54b83 100644 --- a/src/vmime/net/fetchAttributes.cpp +++ b/src/vmime/net/fetchAttributes.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard <[email protected]> +// Copyright (C) 2002 Vincent Richard <[email protected]> // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License as @@ -39,51 +39,54 @@ namespace net { fetchAttributes::fetchAttributes() - : m_predefinedAttribs(0) -{ + : m_predefinedAttribs(0) { + } fetchAttributes::fetchAttributes(const int attribs) - : m_predefinedAttribs(attribs) -{ + : m_predefinedAttribs(attribs) { + } fetchAttributes::fetchAttributes(const fetchAttributes& attribs) - : object() -{ + : object() { + m_predefinedAttribs = attribs.m_predefinedAttribs; m_headers = attribs.m_headers; } -void fetchAttributes::add(const int attribs) -{ +void fetchAttributes::add(const int attribs) { + m_predefinedAttribs |= attribs; } -void fetchAttributes::add(const string& header) -{ +void fetchAttributes::add(const string& header) { + m_headers.push_back(utility::stringUtils::toLower(header)); } -bool fetchAttributes::has(const int attribs) const -{ +bool fetchAttributes::has(const int attribs) const { + return (m_predefinedAttribs & attribs) != 0; } -bool fetchAttributes::has(const string& header) const -{ - return std::find(m_headers.begin(), m_headers.end(), utility::stringUtils::toLower(header)) != m_headers.end(); +bool fetchAttributes::has(const string& header) const { + + return std::find( + m_headers.begin(), m_headers.end(), + utility::stringUtils::toLower(header) + ) != m_headers.end(); } -const std::vector <string> fetchAttributes::getHeaderFields() const -{ +const std::vector <string> fetchAttributes::getHeaderFields() const { + return m_headers; } diff --git a/src/vmime/net/fetchAttributes.hpp b/src/vmime/net/fetchAttributes.hpp index d01e9f50..19d92627 100644 --- a/src/vmime/net/fetchAttributes.hpp +++ b/src/vmime/net/fetchAttributes.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard <[email protected]> +// Copyright (C) 2002 Vincent Richard <[email protected]> // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License as @@ -42,14 +42,13 @@ namespace net { /** Holds a set of attributes to fetch for a message. */ -class VMIME_EXPORT fetchAttributes : public object -{ +class VMIME_EXPORT fetchAttributes : public object { + public: /** Predefined attributes that can be fetched. */ - enum PredefinedFetchAttributes - { + enum PredefinedFetchAttributes { ENVELOPE = (1 << 0), /**< Sender, recipients, date, subject. */ STRUCTURE = (1 << 1), /**< MIME structure (body parts). */ CONTENT_INFO = (1 << 2), /**< Top-level content type. */ @@ -114,8 +113,7 @@ public: * @param attribs one or more OR-ed values of the PredefinedFetchAttributes enum * @return true if the specified attributes are to be fetched */ - VMIME_DEPRECATED inline bool operator&(const int attribs) const - { + VMIME_DEPRECATED inline bool operator&(const int attribs) const { return has(attribs); } diff --git a/src/vmime/net/folder.cpp b/src/vmime/net/folder.cpp index 78ed5131..6e01b602 100644 --- a/src/vmime/net/folder.cpp +++ b/src/vmime/net/folder.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard <[email protected]> +// Copyright (C) 2002 Vincent Richard <[email protected]> // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License as @@ -36,96 +36,91 @@ namespace vmime { namespace net { -int folder::getType() -{ +int folder::getType() { + return getAttributes().getType(); } -int folder::getFlags() -{ +int folder::getFlags() { + return getAttributes().getFlags(); } -void folder::addMessageChangedListener(events::messageChangedListener* l) -{ +void folder::addMessageChangedListener(events::messageChangedListener* l) { + m_messageChangedListeners.push_back(l); } -void folder::removeMessageChangedListener(events::messageChangedListener* l) -{ +void folder::removeMessageChangedListener(events::messageChangedListener* l) { + std::remove(m_messageChangedListeners.begin(), m_messageChangedListeners.end(), l); } -void folder::notifyMessageChanged(shared_ptr <events::messageChangedEvent> event) -{ +void folder::notifyMessageChanged(const shared_ptr <events::messageChangedEvent>& event) { + for (std::list <events::messageChangedListener*>::iterator - it = m_messageChangedListeners.begin() ; it != m_messageChangedListeners.end() ; ++it) - { + it = m_messageChangedListeners.begin() ; it != m_messageChangedListeners.end() ; ++it) { + event->dispatch(*it); } } -void folder::addMessageCountListener(events::messageCountListener* l) -{ +void folder::addMessageCountListener(events::messageCountListener* l) { + m_messageCountListeners.push_back(l); } -void folder::removeMessageCountListener(events::messageCountListener* l) -{ +void folder::removeMessageCountListener(events::messageCountListener* l) { + std::remove(m_messageCountListeners.begin(), m_messageCountListeners.end(), l); } -void folder::notifyMessageCount(shared_ptr <events::messageCountEvent> event) -{ +void folder::notifyMessageCount(const shared_ptr <events::messageCountEvent>& event) { + for (std::list <events::messageCountListener*>::iterator - it = m_messageCountListeners.begin() ; it != m_messageCountListeners.end() ; ++it) - { + it = m_messageCountListeners.begin() ; it != m_messageCountListeners.end() ; ++it) { + event->dispatch(*it); } } -void folder::addFolderListener(events::folderListener* l) -{ +void folder::addFolderListener(events::folderListener* l) { + m_folderListeners.push_back(l); } -void folder::removeFolderListener(events::folderListener* l) -{ +void folder::removeFolderListener(events::folderListener* l) { + std::remove(m_folderListeners.begin(), m_folderListeners.end(), l); } -void folder::notifyFolder(shared_ptr <events::folderEvent> event) -{ +void folder::notifyFolder(const shared_ptr <events::folderEvent>& event) { + for (std::list <events::folderListener*>::iterator - it = m_folderListeners.begin() ; it != m_folderListeners.end() ; ++it) - { + it = m_folderListeners.begin() ; it != m_folderListeners.end() ; ++it) { + event->dispatch(*it); } } -void folder::notifyEvent(shared_ptr <events::event> event) -{ - if (event->getClass() == events::messageCountEvent::EVENT_CLASS) - { +void folder::notifyEvent(const shared_ptr <events::event>& event) { + + if (event->getClass() == events::messageCountEvent::EVENT_CLASS) { notifyMessageCount(dynamicCast <events::messageCountEvent>(event)); - } - else if (event->getClass() == events::messageChangedEvent::EVENT_CLASS) - { + } else if (event->getClass() == events::messageChangedEvent::EVENT_CLASS) { notifyMessageChanged(dynamicCast <events::messageChangedEvent>(event)); - } - else if (event->getClass() == events::folderEvent::EVENT_CLASS) - { + } else if (event->getClass() == events::folderEvent::EVENT_CLASS) { notifyFolder(dynamicCast <events::folderEvent>(event)); } } diff --git a/src/vmime/net/folder.hpp b/src/vmime/net/folder.hpp index 5186bae0..4d5cf6ef 100644 --- a/src/vmime/net/folder.hpp +++ b/src/vmime/net/folder.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard <[email protected]> +// Copyright (C) 2002 Vincent Richard <[email protected]> // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License as @@ -58,17 +58,15 @@ class store; /** Abstract representation of a folder in a message store. */ +class VMIME_EXPORT folder : public object, public enable_shared_from_this <folder> { -class VMIME_EXPORT folder : public object, public enable_shared_from_this <folder> -{ protected: folder(const folder&) : object(), enable_shared_from_this <folder>() { } folder() { } - enum PrivateConstants - { + enum PrivateConstants { TYPE_UNDEFINED = 9999, /**< Used internally to indicate type has not been initialized yet. */ FLAG_UNDEFINED = 9999 /**< Used internally to indicate flags have not @@ -86,8 +84,7 @@ public: /** Open mode. */ - enum Modes - { + enum Modes { MODE_READ_ONLY, /**< Read-only mode (no modification to folder or messages is possible). */ MODE_READ_WRITE /**< Full access mode (read and write). */ }; @@ -273,11 +270,12 @@ public: * support returning the number or UID of an added message) * @throw exceptions::net_exception if an error occurs */ - virtual messageSet addMessage - (shared_ptr <vmime::message> msg, - const int flags = -1, - vmime::datetime* date = NULL, - utility::progressListener* progress = NULL) = 0; + virtual messageSet addMessage( + const shared_ptr <vmime::message>& msg, + const int flags = -1, + vmime::datetime* date = NULL, + utility::progressListener* progress = NULL + ) = 0; /** Add a message to this folder. * @@ -291,12 +289,13 @@ public: * support returning the number or UID of an added message) * @throw exceptions::net_exception if an error occurs */ - virtual messageSet addMessage - (utility::inputStream& is, - const size_t size, - const int flags = -1, - vmime::datetime* date = NULL, - utility::progressListener* progress = NULL) = 0; + virtual messageSet addMessage( + utility::inputStream& is, + const size_t size, + const int flags = -1, + vmime::datetime* date = NULL, + utility::progressListener* progress = NULL + ) = 0; /** Copy messages from this folder to another folder. * @@ -307,8 +306,10 @@ public: * support returning the number or UID of a copied message) * @throw exceptions::net_exception if an error occurs */ - virtual messageSet copyMessages - (const folder::path& dest, const messageSet& msgs) = 0; + virtual messageSet copyMessages( + const folder::path& dest, + const messageSet& msgs + ) = 0; /** Request folder status without opening it. * @@ -358,7 +359,11 @@ public: * @param progress progress listener, or NULL if not used * @throw exceptions::net_exception if an error occurs */ - virtual void fetchMessages(std::vector <shared_ptr <message> >& msg, const fetchAttributes& attribs, utility::progressListener* progress = NULL) = 0; + virtual void fetchMessages( + std::vector <shared_ptr <message> >& msg, + const fetchAttributes& attribs, + utility::progressListener* progress = NULL + ) = 0; /** Fetch objects for the specified message. * @@ -366,7 +371,10 @@ public: * @param attribs set of attributes to fetch * @throw exceptions::net_exception if an error occurs */ - virtual void fetchMessage(shared_ptr <message> msg, const fetchAttributes& attribs) = 0; + virtual void fetchMessage( + const shared_ptr <message>& msg, + const fetchAttributes& attribs + ) = 0; /** Get new references to messages in this folder, given either their * sequence numbers or UIDs, and fetch objects for them at the same time. @@ -378,8 +386,10 @@ public: * @see folder::getMessages() * @see folder::fetchMessages() */ - virtual std::vector <shared_ptr <message> > getAndFetchMessages - (const messageSet& msgs, const fetchAttributes& attribs) = 0; + virtual std::vector <shared_ptr <message> > getAndFetchMessages( + const messageSet& msgs, + const fetchAttributes& attribs + ) = 0; /** Return the list of fetchable objects supported by * the underlying protocol (see folder::fetchAttributes). @@ -408,10 +418,10 @@ public: protected: - void notifyMessageChanged(shared_ptr <events::messageChangedEvent> event); - void notifyMessageCount(shared_ptr <events::messageCountEvent> event); - void notifyFolder(shared_ptr <events::folderEvent> event); - void notifyEvent(shared_ptr <events::event> event); + void notifyMessageChanged(const shared_ptr <events::messageChangedEvent>& event); + void notifyMessageCount(const shared_ptr <events::messageCountEvent>& event); + void notifyFolder(const shared_ptr <events::folderEvent>& event); + void notifyEvent(const shared_ptr <events::event>& event); private: diff --git a/src/vmime/net/folderAttributes.cpp b/src/vmime/net/folderAttributes.cpp index 1a283764..107007cf 100644 --- a/src/vmime/net/folderAttributes.cpp +++ b/src/vmime/net/folderAttributes.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2014 Vincent Richard <[email protected]> +// Copyright (C) 2002 Vincent Richard <[email protected]> // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License as @@ -39,8 +39,8 @@ namespace net { folderAttributes::folderAttributes() : m_type(TYPE_CONTAINS_FOLDERS | TYPE_CONTAINS_MESSAGES), m_flags(0), - m_specialUse(SPECIALUSE_NONE) -{ + m_specialUse(SPECIALUSE_NONE) { + } @@ -49,67 +49,67 @@ folderAttributes::folderAttributes(const folderAttributes& attribs) m_type(attribs.m_type), m_flags(attribs.m_flags), m_userFlags(attribs.m_userFlags), - m_specialUse(attribs.m_specialUse) -{ + m_specialUse(attribs.m_specialUse) { + } -int folderAttributes::getType() const -{ +int folderAttributes::getType() const { + return m_type; } -void folderAttributes::setType(const int type) -{ +void folderAttributes::setType(const int type) { + m_type = type; } -int folderAttributes::getSpecialUse() const -{ +int folderAttributes::getSpecialUse() const { + return m_specialUse; } -void folderAttributes::setSpecialUse(const int use) -{ +void folderAttributes::setSpecialUse(const int use) { + m_specialUse = use; } -int folderAttributes::getFlags() const -{ +int folderAttributes::getFlags() const { + return m_flags; } -void folderAttributes::setFlags(const int flags) -{ +void folderAttributes::setFlags(const int flags) { + m_flags = flags; } -bool folderAttributes::hasFlag(const int flag) -{ +bool folderAttributes::hasFlag(const int flag) { + return (m_flags & flag) != 0; } -const std::vector <string> folderAttributes::getUserFlags() const -{ +const std::vector <string> folderAttributes::getUserFlags() const { + return m_userFlags; } -void folderAttributes::setUserFlags(const std::vector <string>& flags) -{ +void folderAttributes::setUserFlags(const std::vector <string>& flags) { + m_userFlags = flags; } -bool folderAttributes::hasUserFlag(const string& flag) -{ +bool folderAttributes::hasUserFlag(const string& flag) { + return std::find(m_userFlags.begin(), m_userFlags.end(), flag) != m_userFlags.end(); } diff --git a/src/vmime/net/folderAttributes.hpp b/src/vmime/net/folderAttributes.hpp index d6c51926..b91347b5 100644 --- a/src/vmime/net/folderAttributes.hpp +++ b/src/vmime/net/folderAttributes.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2014 Vincent Richard <[email protected]> +// Copyright (C) 2002 Vincent Richard <[email protected]> // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License as @@ -42,22 +42,20 @@ namespace net { /** Holds a set of attributes for a folder. */ -class VMIME_EXPORT folderAttributes : public object -{ +class VMIME_EXPORT folderAttributes : public object { + public: /** Folder types. */ - enum Types - { + enum Types { TYPE_CONTAINS_FOLDERS = (1 << 0), /**< Folder can contain folders. */ TYPE_CONTAINS_MESSAGES = (1 << 1) /**< Folder can contain messages. */ }; /** Folder flags. */ - enum Flags - { + enum Flags { FLAG_HAS_CHILDREN = (1 << 0), /**< Folder contains subfolders. */ FLAG_NO_OPEN = (1 << 1) /**< Folder cannot be open. */ }; @@ -66,8 +64,7 @@ public: * Not all protocols support this. At the current time, only IMAP supports this, * if the server has the SPECIAL-USE capability. */ - enum SpecialUses - { + enum SpecialUses { SPECIALUSE_NONE, /**< User folder, no special use (or unknown). */ SPECIALUSE_ALL, /**< Virtual folder containing all messages. */ SPECIALUSE_ARCHIVE, /**< Folder is used to archives messages (server-dependent). */ @@ -139,7 +136,7 @@ public: * * @param flag combination of one ore more folder flags (see folderAttributes::Flags enum) * @return true if the specified flags are all set, or false otherwise - */ + */ bool hasFlag(const int flag); /** Set the user-defined flags of the folder. diff --git a/src/vmime/net/folderStatus.hpp b/src/vmime/net/folderStatus.hpp index e80b5a9f..fcc4afc0 100644 --- a/src/vmime/net/folderStatus.hpp +++ b/src/vmime/net/folderStatus.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard <[email protected]> +// Copyright (C) 2002 Vincent Richard <[email protected]> // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License as @@ -40,9 +40,8 @@ namespace net { /** Holds the status of a mail store folder. */ +class VMIME_EXPORT folderStatus : public object { -class VMIME_EXPORT folderStatus : public object -{ public: /** Returns the total number of messages in the folder. diff --git a/src/vmime/net/imap/IMAPCommand.cpp b/src/vmime/net/imap/IMAPCommand.cpp index b1840d8d..8911ed02 100644 --- a/src/vmime/net/imap/IMAPCommand.cpp +++ b/src/vmime/net/imap/IMAPCommand.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2014 Vincent Richard <[email protected]> +// Copyright (C) 2002 Vincent Richard <[email protected]> // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License as @@ -41,14 +41,15 @@ namespace imap { IMAPCommand::IMAPCommand(const string& text, const string& traceText) - : m_text(text), m_traceText(traceText) -{ + : m_text(text), + m_traceText(traceText) { + } // static -shared_ptr <IMAPCommand> IMAPCommand::LOGIN(const string& username, const string& password) -{ +shared_ptr <IMAPCommand> IMAPCommand::LOGIN(const string& username, const string& password) { + std::ostringstream cmd; cmd.imbue(std::locale::classic()); cmd << "LOGIN " << IMAPUtils::quoteString(username) @@ -63,8 +64,8 @@ shared_ptr <IMAPCommand> IMAPCommand::LOGIN(const string& username, const string // static -shared_ptr <IMAPCommand> IMAPCommand::AUTHENTICATE(const string& mechName) -{ +shared_ptr <IMAPCommand> IMAPCommand::AUTHENTICATE(const string& mechName) { + std::ostringstream cmd; cmd.imbue(std::locale::classic()); cmd << "AUTHENTICATE " << mechName; @@ -74,8 +75,8 @@ shared_ptr <IMAPCommand> IMAPCommand::AUTHENTICATE(const string& mechName) // static -shared_ptr <IMAPCommand> IMAPCommand::AUTHENTICATE(const string& mechName, const string& initialResponse) -{ +shared_ptr <IMAPCommand> IMAPCommand::AUTHENTICATE(const string& mechName, const string& initialResponse) { + std::ostringstream cmd; cmd.imbue(std::locale::classic()); cmd << "AUTHENTICATE " << mechName << " " << initialResponse; @@ -85,8 +86,8 @@ shared_ptr <IMAPCommand> IMAPCommand::AUTHENTICATE(const string& mechName, const // static -shared_ptr <IMAPCommand> IMAPCommand::LIST(const string& refName, const string& mailboxName) -{ +shared_ptr <IMAPCommand> IMAPCommand::LIST(const string& refName, const string& mailboxName) { + std::ostringstream cmd; cmd.imbue(std::locale::classic()); cmd << "LIST " << IMAPUtils::quoteString(refName) @@ -97,25 +98,28 @@ shared_ptr <IMAPCommand> IMAPCommand::LIST(const string& refName, const string& // static -shared_ptr <IMAPCommand> IMAPCommand::SELECT - (const bool readOnly, const string& mailboxName, const std::vector <string>& params) -{ +shared_ptr <IMAPCommand> IMAPCommand::SELECT( + const bool readOnly, + const string& mailboxName, + const std::vector <string>& params +) { + std::ostringstream cmd; cmd.imbue(std::locale::classic()); - if (readOnly) + if (readOnly) { cmd << "EXAMINE "; - else + } else { cmd << "SELECT "; + } cmd << IMAPUtils::quoteString(mailboxName); - if (!params.empty()) - { + if (!params.empty()) { + cmd << " ("; - for (size_t i = 0, n = params.size() ; i < n ; ++i) - { + for (size_t i = 0, n = params.size() ; i < n ; ++i) { if (i != 0) cmd << " "; cmd << params[i]; } @@ -128,17 +132,18 @@ shared_ptr <IMAPCommand> IMAPCommand::SELECT // static -shared_ptr <IMAPCommand> IMAPCommand::STATUS - (const string& mailboxName, const std::vector <string>& attribs) -{ +shared_ptr <IMAPCommand> IMAPCommand::STATUS( + const string& mailboxName, + const std::vector <string>& attribs +) { + std::ostringstream cmd; cmd.imbue(std::locale::classic()); cmd << "STATUS " << IMAPUtils::quoteString(mailboxName); cmd << " ("; - for (size_t i = 0, n = attribs.size() ; i < n ; ++i) - { + for (size_t i = 0, n = attribs.size() ; i < n ; ++i) { if (i != 0) cmd << " "; cmd << attribs[i]; } @@ -150,19 +155,20 @@ shared_ptr <IMAPCommand> IMAPCommand::STATUS // static -shared_ptr <IMAPCommand> IMAPCommand::CREATE - (const string& mailboxName, const std::vector <string>& params) -{ +shared_ptr <IMAPCommand> IMAPCommand::CREATE( + const string& mailboxName, + const std::vector <string>& params +) { + std::ostringstream cmd; cmd.imbue(std::locale::classic()); cmd << "CREATE " << IMAPUtils::quoteString(mailboxName); - if (!params.empty()) - { + if (!params.empty()) { + cmd << " ("; - for (size_t i = 0, n = params.size() ; i < n ; ++i) - { + for (size_t i = 0, n = params.size() ; i < n ; ++i) { if (i != 0) cmd << " "; cmd << params[i]; } @@ -175,8 +181,8 @@ shared_ptr <IMAPCommand> IMAPCommand::CREATE // static -shared_ptr <IMAPCommand> IMAPCommand::DELETE(const string& mailboxName) -{ +shared_ptr <IMAPCommand> IMAPCommand::DELETE(const string& mailboxName) { + std::ostringstream cmd; cmd.imbue(std::locale::classic()); cmd << "DELETE " << IMAPUtils::quoteString(mailboxName); @@ -186,9 +192,11 @@ shared_ptr <IMAPCommand> IMAPCommand::DELETE(const string& mailboxName) // static -shared_ptr <IMAPCommand> IMAPCommand::RENAME - (const string& mailboxName, const string& newMailboxName) -{ +shared_ptr <IMAPCommand> IMAPCommand::RENAME( + const string& mailboxName, + const string& newMailboxName +) { + std::ostringstream cmd; cmd.imbue(std::locale::classic()); cmd << "RENAME " << IMAPUtils::quoteString(mailboxName) @@ -199,27 +207,29 @@ shared_ptr <IMAPCommand> IMAPCommand::RENAME // static -shared_ptr <IMAPCommand> IMAPCommand::FETCH - (const messageSet& msgs, const std::vector <string>& params) -{ +shared_ptr <IMAPCommand> IMAPCommand::FETCH( + const messageSet& msgs, + const std::vector <string>& params +) { + std::ostringstream cmd; cmd.imbue(std::locale::classic()); - if (msgs.isUIDSet()) + if (msgs.isUIDSet()) { cmd << "UID FETCH " << IMAPUtils::messageSetToSequenceSet(msgs); - else + } else { cmd << "FETCH " << IMAPUtils::messageSetToSequenceSet(msgs); + } + + if (params.size() == 1) { - if (params.size() == 1) - { cmd << " " << params[0]; - } - else - { + + } else { + cmd << " ("; - for (size_t i = 0, n = params.size() ; i < n ; ++i) - { + for (size_t i = 0, n = params.size() ; i < n ; ++i) { if (i != 0) cmd << " "; cmd << params[i]; } @@ -232,28 +242,32 @@ shared_ptr <IMAPCommand> IMAPCommand::FETCH // static -shared_ptr <IMAPCommand> IMAPCommand::STORE - (const messageSet& msgs, const int mode, const std::vector <string>& flags) -{ +shared_ptr <IMAPCommand> IMAPCommand::STORE( + const messageSet& msgs, + const int mode, + const std::vector <string>& flags +) { + std::ostringstream cmd; cmd.imbue(std::locale::classic()); - if (msgs.isUIDSet()) + if (msgs.isUIDSet()) { cmd << "UID STORE " << IMAPUtils::messageSetToSequenceSet(msgs); - else + } else { cmd << "STORE " << IMAPUtils::messageSetToSequenceSet(msgs); + } - if (mode == message::FLAG_MODE_ADD) + if (mode == message::FLAG_MODE_ADD) { cmd << " +FLAGS "; - else if (mode == message::FLAG_MODE_REMOVE) + } else if (mode == message::FLAG_MODE_REMOVE) { cmd << " -FLAGS "; - else // if (mode == message::FLAG_MODE_SET) + } else { // if (mode == message::FLAG_MODE_SET) cmd << " FLAGS "; + } cmd << "("; - for (size_t i = 0, n = flags.size() ; i < n ; ++i) - { + for (size_t i = 0, n = flags.size() ; i < n ; ++i) { if (i != 0) cmd << " "; cmd << flags[i]; } @@ -265,20 +279,22 @@ shared_ptr <IMAPCommand> IMAPCommand::STORE // static -shared_ptr <IMAPCommand> IMAPCommand::APPEND - (const string& mailboxName, const std::vector <string>& flags, - vmime::datetime* date, const size_t size) -{ +shared_ptr <IMAPCommand> IMAPCommand::APPEND( + const string& mailboxName, + const std::vector <string>& flags, + vmime::datetime* date, + const size_t size +) { + std::ostringstream cmd; cmd.imbue(std::locale::classic()); cmd << "APPEND " << IMAPUtils::quoteString(mailboxName); - if (!flags.empty()) - { + if (!flags.empty()) { + cmd << " ("; - for (size_t i = 0, n = flags.size() ; i < n ; ++i) - { + for (size_t i = 0, n = flags.size() ; i < n ; ++i) { if (i != 0) cmd << " "; cmd << flags[i]; } @@ -286,8 +302,9 @@ shared_ptr <IMAPCommand> IMAPCommand::APPEND cmd << ")"; } - if (date != NULL) + if (date != NULL) { cmd << " " << IMAPUtils::dateTime(*date); + } cmd << " {" << size << "}"; @@ -296,16 +313,19 @@ shared_ptr <IMAPCommand> IMAPCommand::APPEND // static -shared_ptr <IMAPCommand> IMAPCommand::COPY - (const messageSet& msgs, const string& mailboxName) -{ +shared_ptr <IMAPCommand> IMAPCommand::COPY( + const messageSet& msgs, + const string& mailboxName +) { + std::ostringstream cmd; cmd.imbue(std::locale::classic()); - if (msgs.isUIDSet()) + if (msgs.isUIDSet()) { cmd << "UID COPY " << IMAPUtils::messageSetToSequenceSet(msgs); - else + } else { cmd << "COPY " << IMAPUtils::messageSetToSequenceSet(msgs); + } cmd << " " << IMAPUtils::quoteString(mailboxName); @@ -314,90 +334,97 @@ shared_ptr <IMAPCommand> IMAPCommand::COPY // static -shared_ptr <IMAPCommand> IMAPCommand::SEARCH - (const std::vector <string>& keys, const vmime::charset* charset) -{ +shared_ptr <IMAPCommand> IMAPCommand::SEARCH( + const std::vector <string>& keys, + const vmime::charset* charset +) { + std::ostringstream cmd; cmd.imbue(std::locale::classic()); cmd << "SEARCH"; - if (charset) + if (charset) { cmd << " CHARSET " << charset->getName(); + } - for (size_t i = 0, n = keys.size() ; i < n ; ++i) + for (size_t i = 0, n = keys.size() ; i < n ; ++i) { cmd << " " << keys[i]; + } return createCommand(cmd.str()); } // static -shared_ptr <IMAPCommand> IMAPCommand::STARTTLS() -{ +shared_ptr <IMAPCommand> IMAPCommand::STARTTLS() { + return createCommand("STARTTLS"); } // static -shared_ptr <IMAPCommand> IMAPCommand::CAPABILITY() -{ +shared_ptr <IMAPCommand> IMAPCommand::CAPABILITY() { + return createCommand("CAPABILITY"); } // static -shared_ptr <IMAPCommand> IMAPCommand::NOOP() -{ +shared_ptr <IMAPCommand> IMAPCommand::NOOP() { + return createCommand("NOOP"); } // static -shared_ptr <IMAPCommand> IMAPCommand::EXPUNGE() -{ +shared_ptr <IMAPCommand> IMAPCommand::EXPUNGE() { + return createCommand("EXPUNGE"); } // static -shared_ptr <IMAPCommand> IMAPCommand::CLOSE() -{ +shared_ptr <IMAPCommand> IMAPCommand::CLOSE() { + return createCommand("CLOSE"); } // static -shared_ptr <IMAPCommand> IMAPCommand::LOGOUT() -{ +shared_ptr <IMAPCommand> IMAPCommand::LOGOUT() { + return createCommand("LOGOUT"); } // static -shared_ptr <IMAPCommand> IMAPCommand::createCommand - (const string& text, const string& traceText) -{ - if (traceText.empty()) +shared_ptr <IMAPCommand> IMAPCommand::createCommand( + const string& text, + const string& traceText +) { + + if (traceText.empty()) { return shared_ptr <IMAPCommand>(new IMAPCommand(text, text)); - else + } else { return shared_ptr <IMAPCommand>(new IMAPCommand(text, traceText)); + } } -const string IMAPCommand::getText() const -{ +const string IMAPCommand::getText() const { + return m_text; } -const string IMAPCommand::getTraceText() const -{ +const string IMAPCommand::getTraceText() const { + return m_traceText; } -void IMAPCommand::send(shared_ptr <IMAPConnection> conn) -{ +void IMAPCommand::send(const shared_ptr <IMAPConnection>& conn) { + conn->sendCommand(dynamicCast <IMAPCommand>(shared_from_this())); } diff --git a/src/vmime/net/imap/IMAPCommand.hpp b/src/vmime/net/imap/IMAPCommand.hpp index dd499859..4915a577 100644 --- a/src/vmime/net/imap/IMAPCommand.hpp +++ b/src/vmime/net/imap/IMAPCommand.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2014 Vincent Richard <[email protected]> +// Copyright (C) 2002 Vincent Richard <[email protected]> // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License as @@ -48,8 +48,8 @@ class IMAPConnection; /** An IMAP command that will be sent to the server. */ -class VMIME_EXPORT IMAPCommand : public object, public enable_shared_from_this <IMAPCommand> -{ +class VMIME_EXPORT IMAPCommand : public object, public enable_shared_from_this <IMAPCommand> { + public: static shared_ptr <IMAPCommand> LOGIN(const string& username, const string& password); @@ -85,7 +85,7 @@ public: * * @param conn connection onto which the command will be sent */ - virtual void send(shared_ptr <IMAPConnection> conn); + virtual void send(const shared_ptr <IMAPConnection>& conn); /** Returns the full text of the command, including command name * and parameters (if any). This is the text that will be sent diff --git a/src/vmime/net/imap/IMAPConnection.cpp b/src/vmime/net/imap/IMAPConnection.cpp index 0cc08178..0e593829 100644 --- a/src/vmime/net/imap/IMAPConnection.cpp +++ b/src/vmime/net/imap/IMAPConnection.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard <[email protected]> +// Copyright (C) 2002 Vincent Richard <[email protected]> // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License as @@ -66,17 +66,30 @@ namespace net { namespace imap { -IMAPConnection::IMAPConnection(shared_ptr <IMAPStore> store, shared_ptr <security::authenticator> auth) - : m_store(store), m_auth(auth), m_socket(null), m_parser(null), m_tag(null), - m_hierarchySeparator('\0'), m_state(STATE_NONE), m_timeoutHandler(null), - m_secured(false), m_firstTag(true), m_capabilitiesFetched(false), m_noModSeq(false) -{ +IMAPConnection::IMAPConnection( + const shared_ptr <IMAPStore>& store, + const shared_ptr <security::authenticator>& auth +) + : m_store(store), + m_auth(auth), + m_socket(null), + m_parser(null), + m_tag(null), + m_hierarchySeparator('\0'), + m_state(STATE_NONE), + m_timeoutHandler(null), + m_secured(false), + m_firstTag(true), + m_capabilitiesFetched(false), + m_noModSeq(false) { + static int connectionId = 0; m_tag = make_shared <IMAPTag>(); - if (store->getTracerFactory()) + if (store->getTracerFactory()) { m_tracer = store->getTracerFactory()->create(store, ++connectionId); + } m_parser = make_shared <IMAPParser>(); m_parser->setTag(m_tag); @@ -84,26 +97,28 @@ IMAPConnection::IMAPConnection(shared_ptr <IMAPStore> store, shared_ptr <securit } -IMAPConnection::~IMAPConnection() -{ - try - { - if (isConnected()) +IMAPConnection::~IMAPConnection() { + + try { + + if (isConnected()) { disconnect(); - else if (m_socket) + } else if (m_socket) { internalDisconnect(); - } - catch (...) - { + } + + } catch (...) { + // Don't throw in destructor } } -void IMAPConnection::connect() -{ - if (isConnected()) +void IMAPConnection::connect() { + + if (isConnected()) { throw exceptions::already_connected(); + } m_state = STATE_NONE; m_hierarchySeparator = '\0'; @@ -114,16 +129,17 @@ void IMAPConnection::connect() shared_ptr <IMAPStore> store = m_store.lock(); // Create the time-out handler - if (store->getTimeoutHandlerFactory()) + if (store->getTimeoutHandlerFactory()) { m_timeoutHandler = store->getTimeoutHandlerFactory()->create(); + } // Create and connect the socket m_socket = store->getSocketFactory()->create(m_timeoutHandler); m_socket->setTracer(m_tracer); #if VMIME_HAVE_TLS_SUPPORT - if (store->isIMAPS()) // dedicated port/IMAPS - { + if (store->isIMAPS()) { // dedicated port/IMAPS + shared_ptr <tls::TLSSession> tlsSession = tls::TLSSession::create (store->getCertificateVerifier(), store->getSession()->getTLSProperties()); @@ -135,8 +151,8 @@ void IMAPConnection::connect() m_secured = true; m_cntInfos = make_shared <tls::TLSSecuredConnectionInfos>(address, port, tlsSession, tlsSocket); - } - else + + } else #endif // VMIME_HAVE_TLS_SUPPORT { m_cntInfos = make_shared <defaultConnectionInfos>(address, port); @@ -160,19 +176,19 @@ void IMAPConnection::connect() scoped_ptr <IMAPParser::greeting> greet(m_parser->readGreeting()); bool needAuth = false; - if (greet->resp_cond_bye()) - { + if (greet->resp_cond_bye()) { + internalDisconnect(); throw exceptions::connection_greeting_error(greet->getErrorLog()); - } - else if (greet->resp_cond_auth()->condition() != IMAPParser::resp_cond_auth::PREAUTH) - { + + } else if (greet->resp_cond_auth()->condition() != IMAPParser::resp_cond_auth::PREAUTH) { + needAuth = true; } if (greet->resp_cond_auth()->resp_text()->resp_text_code() && - greet->resp_cond_auth()->resp_text()->resp_text_code()->capability_data()) - { + greet->resp_cond_auth()->resp_text()->resp_text_code()->capability_data()) { + processCapabilityResponseData(greet->resp_cond_auth()->resp_text()->resp_text_code()->capability_data()); } @@ -183,28 +199,25 @@ void IMAPConnection::connect() const bool tlsRequired = HAS_PROPERTY(PROPERTY_CONNECTION_TLS_REQUIRED) && GET_PROPERTY(bool, PROPERTY_CONNECTION_TLS_REQUIRED); - if (!store->isIMAPS() && tls) // only if not IMAPS - { - try - { + if (!store->isIMAPS() && tls) { // only if not IMAPS + + try { + startTLS(); - } + // Non-fatal error - catch (exceptions::command_error&) - { - if (tlsRequired) - { + } catch (exceptions::command_error&) { + + if (tlsRequired) { m_state = STATE_NONE; throw; - } - else - { + } else { // TLS is not required, so don't bother } - } + // Fatal error - catch (...) - { + } catch (...) { + m_state = STATE_NONE; throw; } @@ -212,14 +225,14 @@ void IMAPConnection::connect() #endif // VMIME_HAVE_TLS_SUPPORT // Authentication - if (needAuth) - { - try - { + if (needAuth) { + + try { + authenticate(); - } - catch (...) - { + + } catch (...) { + m_state = STATE_NONE; throw; } @@ -233,34 +246,34 @@ void IMAPConnection::connect() } -void IMAPConnection::authenticate() -{ +void IMAPConnection::authenticate() { + getAuthenticator()->setService(m_store.lock()); #if VMIME_HAVE_SASL_SUPPORT // First, try SASL authentication - if (GET_PROPERTY(bool, PROPERTY_OPTIONS_SASL)) - { - try - { + if (GET_PROPERTY(bool, PROPERTY_OPTIONS_SASL)) { + + try { + authenticateSASL(); return; - } - catch (exceptions::authentication_error&) - { - if (!GET_PROPERTY(bool, PROPERTY_OPTIONS_SASL_FALLBACK)) - { + + } catch (exceptions::authentication_error&) { + + if (!GET_PROPERTY(bool, PROPERTY_OPTIONS_SASL_FALLBACK)) { + // Can't fallback on normal authentication internalDisconnect(); throw; - } - else - { + + } else { + // Ignore, will try normal authentication } - } - catch (exception&) - { + + } catch (exception&) { + internalDisconnect(); throw; } @@ -276,36 +289,38 @@ void IMAPConnection::authenticate() scoped_ptr <IMAPParser::response> resp(m_parser->readResponse()); - if (resp->isBad()) - { + if (resp->isBad()) { + internalDisconnect(); throw exceptions::command_error("LOGIN", resp->getErrorLog()); - } - else if (resp->response_done()->response_tagged()-> - resp_cond_state()->status() != IMAPParser::resp_cond_state::OK) - { + + } else if (resp->response_done()->response_tagged()-> + resp_cond_state()->status() != IMAPParser::resp_cond_state::OK) { + internalDisconnect(); throw exceptions::authentication_error(resp->getErrorLog()); } // Server capabilities may change when logged in - if (!processCapabilityResponseData(resp.get())) + if (!processCapabilityResponseData(resp.get())) { invalidateCapabilities(); + } } #if VMIME_HAVE_SASL_SUPPORT -void IMAPConnection::authenticateSASL() -{ - if (!dynamicCast <security::sasl::SASLAuthenticator>(getAuthenticator())) +void IMAPConnection::authenticateSASL() { + + if (!dynamicCast <security::sasl::SASLAuthenticator>(getAuthenticator())) { throw exceptions::authentication_error("No SASL authenticator available."); + } const std::vector <string> capa = getCapabilities(); std::vector <string> saslMechs; - for (unsigned int i = 0 ; i < capa.size() ; ++i) - { + for (unsigned int i = 0 ; i < capa.size() ; ++i) { + const string& x = capa[i]; if (x.length() > 5 && @@ -313,53 +328,53 @@ void IMAPConnection::authenticateSASL() (x[1] == 'U' || x[1] == 'u') && (x[2] == 'T' || x[2] == 't') && (x[3] == 'H' || x[3] == 'h') && - x[4] == '=') - { + x[4] == '=') { + saslMechs.push_back(string(x.begin() + 5, x.end())); } } - if (saslMechs.empty()) + if (saslMechs.empty()) { throw exceptions::authentication_error("No SASL mechanism available."); + } std::vector <shared_ptr <security::sasl::SASLMechanism> > mechList; shared_ptr <security::sasl::SASLContext> saslContext = security::sasl::SASLContext::create(); - for (unsigned int i = 0 ; i < saslMechs.size() ; ++i) - { - try - { - mechList.push_back - (saslContext->createMechanism(saslMechs[i])); - } - catch (exceptions::no_such_mechanism&) - { + for (unsigned int i = 0 ; i < saslMechs.size() ; ++i) { + + try { + mechList.push_back(saslContext->createMechanism(saslMechs[i])); + } catch (exceptions::no_such_mechanism&) { // Ignore mechanism } } - if (mechList.empty()) + if (mechList.empty()) { throw exceptions::authentication_error("No SASL mechanism available."); + } // Try to suggest a mechanism among all those supported shared_ptr <security::sasl::SASLMechanism> suggestedMech = saslContext->suggestMechanism(mechList); - if (!suggestedMech) + if (!suggestedMech) { throw exceptions::authentication_error("Unable to suggest SASL mechanism."); + } // Allow application to choose which mechanisms to use mechList = dynamicCast <security::sasl::SASLAuthenticator>(getAuthenticator())-> getAcceptableMechanisms(mechList, suggestedMech); - if (mechList.empty()) + if (mechList.empty()) { throw exceptions::authentication_error("No SASL mechanism available."); + } // Try each mechanism in the list in turn - for (unsigned int i = 0 ; i < mechList.size() ; ++i) - { + for (unsigned int i = 0 ; i < mechList.size() ; ++i) { + shared_ptr <security::sasl::SASLMechanism> mech = mechList[i]; shared_ptr <security::sasl::SASLSession> saslSession = @@ -369,8 +384,8 @@ void IMAPConnection::authenticateSASL() shared_ptr <IMAPCommand> authCmd; - if (saslSession->getMechanism()->hasInitialResponse()) - { + if (saslSession->getMechanism()->hasInitialResponse()) { + byte_t* initialResp = 0; size_t initialRespLen = 0; @@ -379,50 +394,50 @@ void IMAPConnection::authenticateSASL() string encodedInitialResp(saslContext->encodeB64(initialResp, initialRespLen)); delete [] initialResp; - if (encodedInitialResp.empty()) + if (encodedInitialResp.empty()) { authCmd = IMAPCommand::AUTHENTICATE(mech->getName(), "="); - else + } else { authCmd = IMAPCommand::AUTHENTICATE(mech->getName(), encodedInitialResp); - } - else - { + } + + } else { + authCmd = IMAPCommand::AUTHENTICATE(mech->getName()); } authCmd->send(dynamicCast <IMAPConnection>(shared_from_this())); - for (bool cont = true ; cont ; ) - { + for (bool cont = true ; cont ; ) { + scoped_ptr <IMAPParser::response> resp(m_parser->readResponse()); if (resp->response_done() && resp->response_done()->response_tagged() && resp->response_done()->response_tagged()->resp_cond_state()-> - status() == IMAPParser::resp_cond_state::OK) - { + status() == IMAPParser::resp_cond_state::OK) { + m_socket = saslSession->getSecuredSocket(m_socket); return; - } - else - { + + } else { + std::vector <IMAPParser::continue_req_or_response_data*> respDataList = resp->continue_req_or_response_data(); string response; bool hasResponse = false; - for (unsigned int i = 0 ; i < respDataList.size() ; ++i) - { - if (respDataList[i]->continue_req()) - { + for (unsigned int i = 0 ; i < respDataList.size() ; ++i) { + + if (respDataList[i]->continue_req()) { + response = respDataList[i]->continue_req()->resp_text()->text(); hasResponse = true; break; } } - if (!hasResponse) - { + if (!hasResponse) { cont = false; continue; } @@ -433,8 +448,8 @@ void IMAPConnection::authenticateSASL() byte_t* resp = 0; size_t respLen = 0; - try - { + try { + // Extract challenge saslContext->decodeB64(response, &challenge, &challengeLen); @@ -446,22 +461,21 @@ void IMAPConnection::authenticateSASL() const string respB64 = saslContext->encodeB64(resp, respLen) + "\r\n"; sendRaw(utility::stringUtils::bytesFromString(respB64), respB64.length()); - if (m_tracer) + if (m_tracer) { m_tracer->traceSendBytes(respB64.length() - 2, "SASL exchange"); + } // Server capabilities may change when logged in invalidateCapabilities(); - } - catch (exceptions::sasl_exception& e) - { - if (challenge) - { + + } catch (exceptions::sasl_exception& e) { + + if (challenge) { delete [] challenge; challenge = NULL; } - if (resp) - { + if (resp) { delete [] resp; resp = NULL; } @@ -469,31 +483,35 @@ void IMAPConnection::authenticateSASL() // Cancel SASL exchange sendRaw(utility::stringUtils::bytesFromString("*\r\n"), 3); - if (m_tracer) + if (m_tracer) { m_tracer->traceSend("*"); - } - catch (...) - { - if (challenge) + } + + } catch (...) { + + if (challenge) { delete [] challenge; + } - if (resp) + if (resp) { delete [] resp; + } throw; } - if (challenge) + if (challenge) { delete [] challenge; + } - if (resp) + if (resp) { delete [] resp; + } } } } - throw exceptions::authentication_error - ("Could not authenticate using SASL: all mechanisms failed."); + throw exceptions::authentication_error("Could not authenticate using SASL: all mechanisms failed."); } #endif // VMIME_HAVE_SASL_SUPPORT @@ -501,27 +519,26 @@ void IMAPConnection::authenticateSASL() #if VMIME_HAVE_TLS_SUPPORT -void IMAPConnection::startTLS() -{ - try - { +void IMAPConnection::startTLS() { + + try { + IMAPCommand::STARTTLS()->send(dynamicCast <IMAPConnection>(shared_from_this())); scoped_ptr <IMAPParser::response> resp(m_parser->readResponse()); if (resp->isBad() || resp->response_done()->response_tagged()-> - resp_cond_state()->status() != IMAPParser::resp_cond_state::OK) - { - throw exceptions::command_error - ("STARTTLS", resp->getErrorLog(), "bad response"); + resp_cond_state()->status() != IMAPParser::resp_cond_state::OK) { + + throw exceptions::command_error("STARTTLS", resp->getErrorLog(), "bad response"); } - shared_ptr <tls::TLSSession> tlsSession = tls::TLSSession::create - (m_store.lock()->getCertificateVerifier(), - m_store.lock()->getSession()->getTLSProperties()); + shared_ptr <tls::TLSSession> tlsSession = tls::TLSSession::create( + m_store.lock()->getCertificateVerifier(), + m_store.lock()->getSession()->getTLSProperties() + ); - shared_ptr <tls::TLSSocket> tlsSocket = - tlsSession->getSocket(m_socket); + shared_ptr <tls::TLSSocket> tlsSocket = tlsSession->getSocket(m_socket); tlsSocket->handshake(); @@ -529,8 +546,9 @@ void IMAPConnection::startTLS() m_parser->setSocket(m_socket); m_secured = true; - m_cntInfos = make_shared <tls::TLSSecuredConnectionInfos> - (m_cntInfos->getHost(), m_cntInfos->getPort(), tlsSession, tlsSocket); + m_cntInfos = make_shared <tls::TLSSecuredConnectionInfos>( + m_cntInfos->getHost(), m_cntInfos->getPort(), tlsSession, tlsSocket + ); // " Once TLS has been started, the client MUST discard cached // information about server capabilities and SHOULD re-issue the @@ -538,14 +556,14 @@ void IMAPConnection::startTLS() // man-in-the-middle attacks which alter the capabilities list prior // to STARTTLS. " (RFC-2595) invalidateCapabilities(); - } - catch (exceptions::command_error&) - { + + } catch (exceptions::command_error&) { + // Non-fatal error throw; - } - catch (exception&) - { + + } catch (exception&) { + // Fatal error internalDisconnect(); throw; @@ -555,38 +573,41 @@ void IMAPConnection::startTLS() #endif // VMIME_HAVE_TLS_SUPPORT -const std::vector <string> IMAPConnection::getCapabilities() -{ - if (!m_capabilitiesFetched) +const std::vector <string> IMAPConnection::getCapabilities() { + + if (!m_capabilitiesFetched) { fetchCapabilities(); + } return m_capabilities; } -bool IMAPConnection::hasCapability(const string& capa) -{ - if (!m_capabilitiesFetched) +bool IMAPConnection::hasCapability(const string& capa) { + + if (!m_capabilitiesFetched) { fetchCapabilities(); + } const string normCapa = utility::stringUtils::toUpper(capa); - for (size_t i = 0, n = m_capabilities.size() ; i < n ; ++i) - { - if (m_capabilities[i] == normCapa) + for (size_t i = 0, n = m_capabilities.size() ; i < n ; ++i) { + + if (m_capabilities[i] == normCapa) { return true; + } } return false; } -bool IMAPConnection::hasCapability(const string& capa) const -{ +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) - { + for (size_t i = 0, n = m_capabilities.size() ; i < n ; ++i) { + if (m_capabilities[i] == normCapa) return true; } @@ -595,42 +616,44 @@ bool IMAPConnection::hasCapability(const string& capa) const } -void IMAPConnection::invalidateCapabilities() -{ +void IMAPConnection::invalidateCapabilities() { + m_capabilities.clear(); m_capabilitiesFetched = false; } -void IMAPConnection::fetchCapabilities() -{ +void IMAPConnection::fetchCapabilities() { + IMAPCommand::CAPABILITY()->send(dynamicCast <IMAPConnection>(shared_from_this())); scoped_ptr <IMAPParser::response> resp(m_parser->readResponse()); if (resp->response_done()->response_tagged()-> - resp_cond_state()->status() == IMAPParser::resp_cond_state::OK) - { + resp_cond_state()->status() == IMAPParser::resp_cond_state::OK) { + processCapabilityResponseData(resp.get()); } } -bool IMAPConnection::processCapabilityResponseData(const IMAPParser::response* resp) -{ +bool IMAPConnection::processCapabilityResponseData(const IMAPParser::response* resp) { + const std::vector <IMAPParser::continue_req_or_response_data*>& respDataList = resp->continue_req_or_response_data(); - for (size_t i = 0 ; i < respDataList.size() ; ++i) - { - if (respDataList[i]->response_data() == NULL) + for (size_t i = 0 ; i < respDataList.size() ; ++i) { + + if (respDataList[i]->response_data() == NULL) { continue; + } const IMAPParser::capability_data* capaData = respDataList[i]->response_data()->capability_data(); - if (capaData == NULL) + if (capaData == NULL) { continue; + } processCapabilityResponseData(capaData); return true; @@ -640,18 +663,19 @@ bool IMAPConnection::processCapabilityResponseData(const IMAPParser::response* r } -void IMAPConnection::processCapabilityResponseData(const IMAPParser::capability_data* capaData) -{ +void IMAPConnection::processCapabilityResponseData(const IMAPParser::capability_data* capaData) { + std::vector <string> res; std::vector <IMAPParser::capability*> caps = capaData->capabilities(); - for (unsigned int j = 0 ; j < caps.size() ; ++j) - { - if (caps[j]->auth_type()) + for (unsigned int j = 0 ; j < caps.size() ; ++j) { + + if (caps[j]->auth_type()) { res.push_back("AUTH=" + caps[j]->auth_type()->name()); - else + } else { res.push_back(utility::stringUtils::toUpper(caps[j]->atom()->value())); + } } m_capabilities = res; @@ -659,44 +683,46 @@ void IMAPConnection::processCapabilityResponseData(const IMAPParser::capability_ } -shared_ptr <security::authenticator> IMAPConnection::getAuthenticator() -{ +shared_ptr <security::authenticator> IMAPConnection::getAuthenticator() { + return m_auth; } -bool IMAPConnection::isConnected() const -{ - return (m_socket && m_socket->isConnected() && - (m_state == STATE_AUTHENTICATED || m_state == STATE_SELECTED)); +bool IMAPConnection::isConnected() const { + + return m_socket + && m_socket->isConnected() + && (m_state == STATE_AUTHENTICATED || m_state == STATE_SELECTED); } -bool IMAPConnection::isSecuredConnection() const -{ +bool IMAPConnection::isSecuredConnection() const { + return m_secured; } -shared_ptr <connectionInfos> IMAPConnection::getConnectionInfos() const -{ +shared_ptr <connectionInfos> IMAPConnection::getConnectionInfos() const { + return m_cntInfos; } -void IMAPConnection::disconnect() -{ - if (!isConnected()) +void IMAPConnection::disconnect() { + + if (!isConnected()) { throw exceptions::not_connected(); + } internalDisconnect(); } -void IMAPConnection::internalDisconnect() -{ - if (isConnected()) - { +void IMAPConnection::internalDisconnect() { + + if (isConnected()) { + IMAPCommand::LOGOUT()->send(dynamicCast <IMAPConnection>(shared_from_this())); m_socket->disconnect(); @@ -712,15 +738,15 @@ void IMAPConnection::internalDisconnect() } -void IMAPConnection::initHierarchySeparator() -{ +void IMAPConnection::initHierarchySeparator() { + IMAPCommand::LIST("", "")->send(dynamicCast <IMAPConnection>(shared_from_this())); scoped_ptr <IMAPParser::response> resp(m_parser->readResponse()); if (resp->isBad() || resp->response_done()->response_tagged()-> - resp_cond_state()->status() != IMAPParser::resp_cond_state::OK) - { + resp_cond_state()->status() != IMAPParser::resp_cond_state::OK) { + internalDisconnect(); throw exceptions::command_error("LIST", resp->getErrorLog(), "bad response"); } @@ -730,34 +756,37 @@ void IMAPConnection::initHierarchySeparator() bool found = false; - for (unsigned int i = 0 ; !found && i < respDataList.size() ; ++i) - { - if (respDataList[i]->response_data() == NULL) + for (unsigned int i = 0 ; !found && i < respDataList.size() ; ++i) { + + if (respDataList[i]->response_data() == NULL) { continue; + } const IMAPParser::mailbox_data* mailboxData = static_cast <const IMAPParser::response_data*> (respDataList[i]->response_data())->mailbox_data(); - if (mailboxData == NULL || mailboxData->type() != IMAPParser::mailbox_data::LIST) + if (mailboxData == NULL || mailboxData->type() != IMAPParser::mailbox_data::LIST) { continue; + } - if (mailboxData->mailbox_list()->quoted_char() != '\0') - { + if (mailboxData->mailbox_list()->quoted_char() != '\0') { m_hierarchySeparator = mailboxData->mailbox_list()->quoted_char(); found = true; } } - if (!found) // default + if (!found) { // default m_hierarchySeparator = '/'; + } } -void IMAPConnection::sendCommand(shared_ptr <IMAPCommand> cmd) -{ - if (!m_firstTag) +void IMAPConnection::sendCommand(const shared_ptr <IMAPCommand>& cmd) { + + if (!m_firstTag) { ++(*m_tag); + } m_socket->send(*m_tag); m_socket->send(" "); @@ -766,8 +795,8 @@ void IMAPConnection::sendCommand(shared_ptr <IMAPCommand> cmd) m_firstTag = false; - if (m_tracer) - { + if (m_tracer) { + std::ostringstream oss; oss << string(*m_tag) << " " << cmd->getText(); @@ -776,87 +805,87 @@ void IMAPConnection::sendCommand(shared_ptr <IMAPCommand> cmd) } -void IMAPConnection::sendRaw(const byte_t* buffer, const size_t count) -{ +void IMAPConnection::sendRaw(const byte_t* buffer, const size_t count) { + m_socket->sendRaw(buffer, count); } -IMAPParser::response* IMAPConnection::readResponse(IMAPParser::literalHandler* lh) -{ - return (m_parser->readResponse(lh)); +IMAPParser::response* IMAPConnection::readResponse(IMAPParser::literalHandler* lh) { + + return m_parser->readResponse(lh); } -IMAPConnection::ProtocolStates IMAPConnection::state() const -{ - return (m_state); +IMAPConnection::ProtocolStates IMAPConnection::state() const { + + return m_state; } -void IMAPConnection::setState(const ProtocolStates state) -{ +void IMAPConnection::setState(const ProtocolStates state) { + m_state = state; } -char IMAPConnection::hierarchySeparator() const -{ - return (m_hierarchySeparator); +char IMAPConnection::hierarchySeparator() const { + + return m_hierarchySeparator; } -shared_ptr <const IMAPStore> IMAPConnection::getStore() const -{ +shared_ptr <const IMAPStore> IMAPConnection::getStore() const { + return m_store.lock(); } -shared_ptr <IMAPStore> IMAPConnection::getStore() -{ +shared_ptr <IMAPStore> IMAPConnection::getStore() { + return m_store.lock(); } -shared_ptr <session> IMAPConnection::getSession() -{ +shared_ptr <session> IMAPConnection::getSession() { + return m_store.lock()->getSession(); } -shared_ptr <const socket> IMAPConnection::getSocket() const -{ +shared_ptr <const socket> IMAPConnection::getSocket() const { + return m_socket; } -void IMAPConnection::setSocket(shared_ptr <socket> sok) -{ +void IMAPConnection::setSocket(const shared_ptr <socket>& sok) { + m_socket = sok; m_parser->setSocket(sok); } -shared_ptr <tracer> IMAPConnection::getTracer() -{ +shared_ptr <tracer> IMAPConnection::getTracer() { + return m_tracer; } -shared_ptr <IMAPTag> IMAPConnection::getTag() -{ +shared_ptr <IMAPTag> IMAPConnection::getTag() { + return m_tag; } -bool IMAPConnection::isMODSEQDisabled() const -{ +bool IMAPConnection::isMODSEQDisabled() const { + return m_noModSeq; } -void IMAPConnection::disableMODSEQ() -{ +void IMAPConnection::disableMODSEQ() { + m_noModSeq = true; } diff --git a/src/vmime/net/imap/IMAPConnection.hpp b/src/vmime/net/imap/IMAPConnection.hpp index 0ce9092d..99750d49 100644 --- a/src/vmime/net/imap/IMAPConnection.hpp +++ b/src/vmime/net/imap/IMAPConnection.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard <[email protected]> +// Copyright (C) 2002 Vincent Richard <[email protected]> // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License as @@ -52,11 +52,11 @@ class IMAPStore; class IMAPCommand; -class VMIME_EXPORT IMAPConnection : public object, public enable_shared_from_this <IMAPConnection> -{ +class VMIME_EXPORT IMAPConnection : public object, public enable_shared_from_this <IMAPConnection> { + public: - IMAPConnection(shared_ptr <IMAPStore> store, shared_ptr <security::authenticator> auth); + IMAPConnection(const shared_ptr <IMAPStore>& store, const shared_ptr <security::authenticator>& auth); ~IMAPConnection(); @@ -65,8 +65,7 @@ public: void disconnect(); - enum ProtocolStates - { + enum ProtocolStates { STATE_NONE, STATE_NON_AUTHENTICATED, STATE_AUTHENTICATED, @@ -81,7 +80,7 @@ public: char hierarchySeparator() const; - void sendCommand(shared_ptr <IMAPCommand> cmd); + void sendCommand(const shared_ptr <IMAPCommand>& cmd); void sendRaw(const byte_t* buffer, const size_t count); IMAPParser::response* readResponse(IMAPParser::literalHandler* lh = NULL); @@ -104,7 +103,7 @@ public: shared_ptr <connectionInfos> getConnectionInfos() const; shared_ptr <const socket> getSocket() const; - void setSocket(shared_ptr <socket> sok); + void setSocket(const shared_ptr <socket>& sok); shared_ptr <tracer> getTracer(); diff --git a/src/vmime/net/imap/IMAPFolder.cpp b/src/vmime/net/imap/IMAPFolder.cpp index 1fbe1331..ec39fe3e 100644 --- a/src/vmime/net/imap/IMAPFolder.cpp +++ b/src/vmime/net/imap/IMAPFolder.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard <[email protected]> +// Copyright (C) 2002 Vincent Richard <[email protected]> // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License as @@ -52,106 +52,119 @@ namespace net { namespace imap { -IMAPFolder::IMAPFolder(const folder::path& path, shared_ptr <IMAPStore> store, shared_ptr <folderAttributes> attribs) - : m_store(store), m_connection(store->connection()), m_path(path), - m_name(path.isEmpty() ? folder::path::component("") : path.getLastComponent()), m_mode(-1), - m_open(false), m_attribs(attribs) -{ +IMAPFolder::IMAPFolder( + const folder::path& path, + const shared_ptr <IMAPStore>& store, + const shared_ptr <folderAttributes>& attribs +) + : m_store(store), + m_connection(store->connection()), + m_path(path), + m_name(path.isEmpty() ? folder::path::component("") : path.getLastComponent()), + m_mode(-1), + m_open(false), + m_attribs(attribs) { + store->registerFolder(this); m_status = make_shared <IMAPFolderStatus>(); } -IMAPFolder::~IMAPFolder() -{ - try - { +IMAPFolder::~IMAPFolder() { + + try { + shared_ptr <IMAPStore> store = m_store.lock(); - if (store) - { - if (m_open) + if (store) { + + if (m_open) { close(false); + } store->unregisterFolder(this); - } - else if (m_open) - { + + } else if (m_open) { + m_connection = null; onClose(); } - } - catch (...) - { + + } catch (...) { + // Don't throw in destructor } } -int IMAPFolder::getMode() const -{ - if (!isOpen()) +int IMAPFolder::getMode() const { + + if (!isOpen()) { throw exceptions::illegal_state("Folder not open"); + } - return (m_mode); + return m_mode; } -const folderAttributes IMAPFolder::getAttributes() -{ +const folderAttributes IMAPFolder::getAttributes() { + // Root folder - if (m_path.isEmpty()) - { + if (m_path.isEmpty()) { + folderAttributes attribs; attribs.setType(folderAttributes::TYPE_CONTAINS_FOLDERS); attribs.setFlags(folderAttributes::FLAG_HAS_CHILDREN | folderAttributes::FLAG_NO_OPEN); return attribs; - } - else - { - if (!m_attribs) + + } else { + + if (!m_attribs) { testExistAndGetType(); + } return *m_attribs; } } -const folder::path::component IMAPFolder::getName() const -{ - return (m_name); +const folder::path::component IMAPFolder::getName() const { + + return m_name; } -const folder::path IMAPFolder::getFullPath() const -{ - return (m_path); +const folder::path IMAPFolder::getFullPath() const { + + return m_path; } -void IMAPFolder::open(const int mode, bool failIfModeIsNotAvailable) -{ +void IMAPFolder::open(const int mode, bool failIfModeIsNotAvailable) { + shared_ptr <IMAPStore> store = m_store.lock(); - if (!store) + if (!store) { throw exceptions::illegal_state("Store disconnected"); + } // Ensure this folder is not already open in the same session for (std::list <IMAPFolder*>::iterator it = store->m_folders.begin() ; - it != store->m_folders.end() ; ++it) - { - if ((*it) != this && (*it)->getFullPath() == m_path) + it != store->m_folders.end() ; ++it) { + + if ((*it) != this && (*it)->getFullPath() == m_path) { throw exceptions::folder_already_open(); + } } // Open a connection for this folder shared_ptr <IMAPConnection> connection = make_shared <IMAPConnection>(store, store->getAuthenticator()); - try - { + try { + connection->connect(); // Emit the "SELECT" command @@ -167,8 +180,9 @@ void IMAPFolder::open(const int mode, bool failIfModeIsNotAvailable) std::vector <string> selectParams; - if (m_connection->hasCapability("CONDSTORE")) + if (m_connection->hasCapability("CONDSTORE")) { selectParams.push_back("CONDSTORE"); + } IMAPCommand::SELECT( mode == MODE_READ_ONLY, @@ -180,65 +194,66 @@ void IMAPFolder::open(const int mode, bool failIfModeIsNotAvailable) scoped_ptr <IMAPParser::response> resp(connection->readResponse()); if (resp->isBad() || resp->response_done()->response_tagged()-> - resp_cond_state()->status() != IMAPParser::resp_cond_state::OK) - { - throw exceptions::command_error("SELECT", - resp->getErrorLog(), "bad response"); + resp_cond_state()->status() != IMAPParser::resp_cond_state::OK) { + + throw exceptions::command_error("SELECT", resp->getErrorLog(), "bad response"); } const std::vector <IMAPParser::continue_req_or_response_data*>& respDataList = resp->continue_req_or_response_data(); for (std::vector <IMAPParser::continue_req_or_response_data*>::const_iterator - it = respDataList.begin() ; it != respDataList.end() ; ++it) - { - if ((*it)->response_data() == NULL) - { - throw exceptions::command_error("SELECT", - resp->getErrorLog(), "invalid response"); + it = respDataList.begin() ; it != respDataList.end() ; ++it) { + + if ((*it)->response_data() == NULL) { + + throw exceptions::command_error("SELECT", resp->getErrorLog(), "invalid response"); } const IMAPParser::response_data* responseData = (*it)->response_data(); // OK Untagged responses: UNSEEN, PERMANENTFLAGS, UIDVALIDITY (optional) - if (responseData->resp_cond_state()) - { + if (responseData->resp_cond_state()) { + const IMAPParser::resp_text_code* code = responseData->resp_cond_state()->resp_text()->resp_text_code(); - if (code != NULL) - { - switch (code->type()) - { - case IMAPParser::resp_text_code::NOMODSEQ: + if (code != NULL) { - connection->disableMODSEQ(); - break; + switch (code->type()) { - default: + case IMAPParser::resp_text_code::NOMODSEQ: - break; + connection->disableMODSEQ(); + break; + + default: + + break; } } - } + // Untagged responses: FLAGS, EXISTS, RECENT (required) - else if (responseData->mailbox_data()) - { - switch (responseData->mailbox_data()->type()) - { - default: break; + } else if (responseData->mailbox_data()) { - case IMAPParser::mailbox_data::FLAGS: - { - if (!m_attribs) - m_attribs = make_shared <folderAttributes>(); + switch (responseData->mailbox_data()->type()) { - IMAPUtils::mailboxFlagsToFolderAttributes - (connection, responseData->mailbox_data()->mailbox_flag_list(), *m_attribs); + default: break; - break; - } + case IMAPParser::mailbox_data::FLAGS: { + + if (!m_attribs) { + m_attribs = make_shared <folderAttributes>(); + } + IMAPUtils::mailboxFlagsToFolderAttributes( + connection, + responseData->mailbox_data()->mailbox_flag_list(), + *m_attribs + ); + + break; + } } } } @@ -249,49 +264,52 @@ void IMAPFolder::open(const int mode, bool failIfModeIsNotAvailable) const IMAPParser::resp_text_code* respTextCode = resp->response_done()-> response_tagged()->resp_cond_state()->resp_text()->resp_text_code(); - if (respTextCode) - { + if (respTextCode) { + const int openMode = (respTextCode->type() == IMAPParser::resp_text_code::READ_WRITE) - ? MODE_READ_WRITE : MODE_READ_ONLY; + ? MODE_READ_WRITE + : MODE_READ_ONLY; if (failIfModeIsNotAvailable && - mode == MODE_READ_WRITE && openMode == MODE_READ_ONLY) - { + mode == MODE_READ_WRITE && openMode == MODE_READ_ONLY) { + throw exceptions::operation_not_supported(); } } - m_connection = connection; m_open = true; m_mode = mode; - } - catch (std::exception&) - { + + } catch (std::exception&) { + throw; } } -void IMAPFolder::close(const bool expunge) -{ +void IMAPFolder::close(const bool expunge) { + shared_ptr <IMAPStore> store = m_store.lock(); - if (!store) + if (!store) { throw exceptions::illegal_state("Store disconnected"); + } - if (!isOpen()) + if (!isOpen()) { throw exceptions::illegal_state("Folder not open"); + } shared_ptr <IMAPConnection> oldConnection = m_connection; // Emit the "CLOSE" command to expunge messages marked // as deleted (this is fastest than "EXPUNGE") - if (expunge) - { - if (m_mode == MODE_READ_ONLY) + if (expunge) { + + if (m_mode == MODE_READ_ONLY) { throw exceptions::operation_not_supported(); + } IMAPCommand::CLOSE()->send(oldConnection); } @@ -311,11 +329,11 @@ void IMAPFolder::close(const bool expunge) } -void IMAPFolder::onClose() -{ +void IMAPFolder::onClose() { + for (std::vector <IMAPMessage*>::iterator it = m_messages.begin() ; - it != m_messages.end() ; ++it) - { + it != m_messages.end() ; ++it) { + (*it)->onFolderClosed(); } @@ -323,18 +341,19 @@ void IMAPFolder::onClose() } -void IMAPFolder::create(const folderAttributes& attribs) -{ +void IMAPFolder::create(const folderAttributes& attribs) { + shared_ptr <IMAPStore> store = m_store.lock(); - if (!store) + if (!store) { throw exceptions::illegal_state("Store disconnected"); - else if (isOpen()) + } else if (isOpen()) { throw exceptions::illegal_state("Folder is open"); - else if (exists()) + } else if (exists()) { throw exceptions::illegal_state("Folder already exists"); - else if (!store->isValidFolderName(m_name)) + } else if (!store->isValidFolderName(m_name)) { throw exceptions::invalid_folder_name(); + } // Emit the "CREATE" command // @@ -346,31 +365,33 @@ void IMAPFolder::create(const folderAttributes& attribs) string mailbox = IMAPUtils::pathToString (m_connection->hierarchySeparator(), getFullPath()); - if (attribs.getType() & folderAttributes::TYPE_CONTAINS_FOLDERS) + if (attribs.getType() & folderAttributes::TYPE_CONTAINS_FOLDERS) { mailbox += m_connection->hierarchySeparator(); + } std::vector <string> createParams; - if (attribs.getSpecialUse() != folderAttributes::SPECIALUSE_NONE) - { - if (!m_connection->hasCapability("CREATE-SPECIAL-USE")) + if (attribs.getSpecialUse() != folderAttributes::SPECIALUSE_NONE) { + + if (!m_connection->hasCapability("CREATE-SPECIAL-USE")) { throw exceptions::operation_not_supported(); + } // C: t2 CREATE MySpecial (USE (\Drafts \Sent)) std::ostringstream oss; oss << "USE ("; - switch (attribs.getSpecialUse()) - { - case folderAttributes::SPECIALUSE_NONE: // should not happen - case folderAttributes::SPECIALUSE_ALL: oss << "\\All"; break; - case folderAttributes::SPECIALUSE_ARCHIVE: oss << "\\Archive"; break; - case folderAttributes::SPECIALUSE_DRAFTS: oss << "\\Drafts"; break; - case folderAttributes::SPECIALUSE_FLAGGED: oss << "\\Flagged"; break; - case folderAttributes::SPECIALUSE_JUNK: oss << "\\Junk"; break; - case folderAttributes::SPECIALUSE_SENT: oss << "\\Sent"; break; - case folderAttributes::SPECIALUSE_TRASH: oss << "\\Trash"; break; - case folderAttributes::SPECIALUSE_IMPORTANT: oss << "\\Important"; break; + switch (attribs.getSpecialUse()) { + + case folderAttributes::SPECIALUSE_NONE: // should not happen + case folderAttributes::SPECIALUSE_ALL: oss << "\\All"; break; + case folderAttributes::SPECIALUSE_ARCHIVE: oss << "\\Archive"; break; + case folderAttributes::SPECIALUSE_DRAFTS: oss << "\\Drafts"; break; + case folderAttributes::SPECIALUSE_FLAGGED: oss << "\\Flagged"; break; + case folderAttributes::SPECIALUSE_JUNK: oss << "\\Junk"; break; + case folderAttributes::SPECIALUSE_SENT: oss << "\\Sent"; break; + case folderAttributes::SPECIALUSE_TRASH: oss << "\\Trash"; break; + case folderAttributes::SPECIALUSE_IMPORTANT: oss << "\\Important"; break; } oss << ")"; @@ -384,34 +405,38 @@ void IMAPFolder::create(const folderAttributes& attribs) scoped_ptr <IMAPParser::response> resp(m_connection->readResponse()); if (resp->isBad() || resp->response_done()->response_tagged()-> - resp_cond_state()->status() != IMAPParser::resp_cond_state::OK) - { - throw exceptions::command_error("CREATE", - resp->getErrorLog(), "bad response"); + resp_cond_state()->status() != IMAPParser::resp_cond_state::OK) { + + throw exceptions::command_error("CREATE", resp->getErrorLog(), "bad response"); } // Notify folder created shared_ptr <events::folderEvent> event = - make_shared <events::folderEvent> - (dynamicCast <folder>(shared_from_this()), - events::folderEvent::TYPE_CREATED, m_path, m_path); + make_shared <events::folderEvent>( + dynamicCast <folder>(shared_from_this()), + events::folderEvent::TYPE_CREATED, + m_path, m_path + ); notifyFolder(event); } -void IMAPFolder::destroy() -{ +void IMAPFolder::destroy() { + shared_ptr <IMAPStore> store = m_store.lock(); - if (!store) + if (!store) { throw exceptions::illegal_state("Store disconnected"); + } - if (isOpen()) + if (isOpen()) { throw exceptions::illegal_state("Folder is open"); + } - const string mailbox = IMAPUtils::pathToString - (m_connection->hierarchySeparator(), getFullPath()); + const string mailbox = IMAPUtils::pathToString( + m_connection->hierarchySeparator(), getFullPath() + ); IMAPCommand::DELETE(mailbox)->send(m_connection); @@ -419,35 +444,37 @@ void IMAPFolder::destroy() scoped_ptr <IMAPParser::response> resp(m_connection->readResponse()); if (resp->isBad() || resp->response_done()->response_tagged()-> - resp_cond_state()->status() != IMAPParser::resp_cond_state::OK) - { - throw exceptions::command_error("DELETE", - resp->getErrorLog(), "bad response"); + resp_cond_state()->status() != IMAPParser::resp_cond_state::OK) { + + throw exceptions::command_error("DELETE", resp->getErrorLog(), "bad response"); } // Notify folder deleted shared_ptr <events::folderEvent> event = - make_shared <events::folderEvent> - (dynamicCast <folder>(shared_from_this()), - events::folderEvent::TYPE_DELETED, m_path, m_path); + make_shared <events::folderEvent>( + dynamicCast <folder>(shared_from_this()), + events::folderEvent::TYPE_DELETED, + m_path, m_path + ); notifyFolder(event); } -bool IMAPFolder::exists() -{ +bool IMAPFolder::exists() { + shared_ptr <IMAPStore> store = m_store.lock(); - if (!isOpen() && !store) + if (!isOpen() && !store) { throw exceptions::illegal_state("Store disconnected"); + } return testExistAndGetType() != -1; } -int IMAPFolder::testExistAndGetType() -{ +int IMAPFolder::testExistAndGetType() { + // To test whether a folder exists, we simple list it using // the "LIST" command, and there should be one unique mailbox // with this name... @@ -467,17 +494,21 @@ int IMAPFolder::testExistAndGetType() // // ==> NO, does not exist - IMAPCommand::LIST("", IMAPUtils::pathToString - (m_connection->hierarchySeparator(), getFullPath()))->send(m_connection); + IMAPCommand::LIST( + "", + IMAPUtils::pathToString( + m_connection->hierarchySeparator(), + getFullPath() + ) + )->send(m_connection); scoped_ptr <IMAPParser::response> resp(m_connection->readResponse()); if (resp->isBad() || resp->response_done()->response_tagged()-> - resp_cond_state()->status() != IMAPParser::resp_cond_state::OK) - { - throw exceptions::command_error("LIST", - resp->getErrorLog(), "bad response"); + resp_cond_state()->status() != IMAPParser::resp_cond_state::OK) { + + throw exceptions::command_error("LIST", resp->getErrorLog(), "bad response"); } // Check whether the result mailbox list contains this folder @@ -488,23 +519,26 @@ int IMAPFolder::testExistAndGetType() attribs.setType(-1); for (std::vector <IMAPParser::continue_req_or_response_data*>::const_iterator - it = respDataList.begin() ; it != respDataList.end() ; ++it) - { - if ((*it)->response_data() == NULL) - { - throw exceptions::command_error("LIST", - resp->getErrorLog(), "invalid response"); + it = respDataList.begin() ; it != respDataList.end() ; ++it) { + + if ((*it)->response_data() == NULL) { + + throw exceptions::command_error("LIST", resp->getErrorLog(), "invalid response"); } const IMAPParser::mailbox_data* mailboxData = (*it)->response_data()->mailbox_data(); // We are only interested in responses of type "LIST" - if (mailboxData != NULL && mailboxData->type() == IMAPParser::mailbox_data::LIST) - { + if (mailboxData != NULL && + mailboxData->type() == IMAPParser::mailbox_data::LIST) { + // Get the folder type/flags at the same time - IMAPUtils::mailboxFlagsToFolderAttributes - (m_connection, mailboxData->mailbox_list()->mailbox_flag_list(), attribs); + IMAPUtils::mailboxFlagsToFolderAttributes( + m_connection, + mailboxData->mailbox_list()->mailbox_flag_list(), + attribs + ); } } @@ -514,31 +548,35 @@ int IMAPFolder::testExistAndGetType() } -bool IMAPFolder::isOpen() const -{ - return (m_open); +bool IMAPFolder::isOpen() const { + + return m_open; } -shared_ptr <message> IMAPFolder::getMessage(const size_t num) -{ - if (!isOpen()) +shared_ptr <message> IMAPFolder::getMessage(const size_t num) { + + if (!isOpen()) { throw exceptions::illegal_state("Folder not open"); + } - if (num < 1 || num > m_status->getMessageCount()) + if (num < 1 || num > m_status->getMessageCount()) { throw exceptions::message_not_found(); + } return make_shared <IMAPMessage>(dynamicCast <IMAPFolder>(shared_from_this()), num); } -std::vector <shared_ptr <message> > IMAPFolder::getMessages(const messageSet& msgs) -{ - if (!isOpen()) +std::vector <shared_ptr <message> > IMAPFolder::getMessages(const messageSet& msgs) { + + if (!isOpen()) { throw exceptions::illegal_state("Folder not open"); + } - if (msgs.isEmpty()) + if (msgs.isEmpty()) { return std::vector <shared_ptr <message> >(); + } std::vector <shared_ptr <message> > messages; @@ -565,8 +603,8 @@ std::vector <shared_ptr <message> > IMAPFolder::getMessages(const messageSet& ms scoped_ptr <IMAPParser::response> resp(m_connection->readResponse()); if (resp->isBad() || resp->response_done()->response_tagged()-> - resp_cond_state()->status() != IMAPParser::resp_cond_state::OK) - { + resp_cond_state()->status() != IMAPParser::resp_cond_state::OK) { + throw exceptions::command_error("UID FETCH ... UID", resp->getErrorLog(), "bad response"); } @@ -575,20 +613,20 @@ std::vector <shared_ptr <message> > IMAPFolder::getMessages(const messageSet& ms resp->continue_req_or_response_data(); for (std::vector <IMAPParser::continue_req_or_response_data*>::const_iterator - it = respDataList.begin() ; it != respDataList.end() ; ++it) - { - if ((*it)->response_data() == NULL) - { - throw exceptions::command_error("UID FETCH ... UID", - resp->getErrorLog(), "invalid response"); + it = respDataList.begin() ; it != respDataList.end() ; ++it) { + + if ((*it)->response_data() == NULL) { + + throw exceptions::command_error("UID FETCH ... UID", resp->getErrorLog(), "invalid response"); } const IMAPParser::message_data* messageData = (*it)->response_data()->message_data(); // We are only interested in responses of type "FETCH" - if (messageData == NULL || messageData->type() != IMAPParser::message_data::FETCH) + if (messageData == NULL || messageData->type() != IMAPParser::message_data::FETCH) { continue; + } // Get Process fetch response for this message const size_t msgNum = messageData->number(); @@ -598,17 +636,15 @@ std::vector <shared_ptr <message> > IMAPFolder::getMessages(const messageSet& ms const std::vector <IMAPParser::msg_att_item*> atts = messageData->msg_att()->items(); for (std::vector <IMAPParser::msg_att_item*>::const_iterator - it = atts.begin() ; it != atts.end() ; ++it) - { - if ((*it)->type() == IMAPParser::msg_att_item::UID) - { + it = atts.begin() ; it != atts.end() ; ++it) { + + if ((*it)->type() == IMAPParser::msg_att_item::UID) { msgUID = (*it)->unique_id()->value(); break; } } - if (!msgUID.empty()) - { + if (!msgUID.empty()) { shared_ptr <IMAPFolder> thisFolder = dynamicCast <IMAPFolder>(shared_from_this()); messages.push_back(make_shared <IMAPMessage>(thisFolder, msgNum, msgUID)); } @@ -618,50 +654,55 @@ std::vector <shared_ptr <message> > IMAPFolder::getMessages(const messageSet& ms } -size_t IMAPFolder::getMessageCount() -{ - if (!isOpen()) +size_t IMAPFolder::getMessageCount() { + + if (!isOpen()) { throw exceptions::illegal_state("Folder not open"); + } return m_status->getMessageCount(); } -vmime_uint32 IMAPFolder::getUIDValidity() const -{ - if (!isOpen()) +vmime_uint32 IMAPFolder::getUIDValidity() const { + + if (!isOpen()) { throw exceptions::illegal_state("Folder not open"); + } return m_status->getUIDValidity(); } -vmime_uint64 IMAPFolder::getHighestModSequence() const -{ - if (!isOpen()) +vmime_uint64 IMAPFolder::getHighestModSequence() const { + + if (!isOpen()) { throw exceptions::illegal_state("Folder not open"); + } return m_status->getHighestModSeq(); } -shared_ptr <folder> IMAPFolder::getFolder(const folder::path::component& name) -{ +shared_ptr <folder> IMAPFolder::getFolder(const folder::path::component& name) { + shared_ptr <IMAPStore> store = m_store.lock(); - if (!store) + if (!store) { throw exceptions::illegal_state("Store disconnected"); + } - return shared_ptr <IMAPFolder>(new IMAPFolder(m_path / name, store, shared_ptr <folderAttributes>())); + return make_shared <IMAPFolder>(m_path / name, store, shared_ptr <folderAttributes>()); } -std::vector <shared_ptr <folder> > IMAPFolder::getFolders(const bool recursive) -{ +std::vector <shared_ptr <folder> > IMAPFolder::getFolders(const bool recursive) { + shared_ptr <IMAPStore> store = m_store.lock(); - if (!isOpen() && !store) + if (!isOpen() && !store) { throw exceptions::illegal_state("Store disconnected"); + } // Eg. List folders in '/foo/bar' // @@ -672,17 +713,22 @@ std::vector <shared_ptr <folder> > IMAPFolder::getFolders(const bool recursive) shared_ptr <IMAPCommand> cmd; - const string pathString = IMAPUtils::pathToString - (m_connection->hierarchySeparator(), getFullPath()); + const string pathString = IMAPUtils::pathToString( + m_connection->hierarchySeparator(), getFullPath() + ); + + if (recursive) { - if (recursive) - { cmd = IMAPCommand::LIST(pathString, "*"); - } - else - { - cmd = IMAPCommand::LIST - (pathString.empty() ? "" : (pathString + m_connection->hierarchySeparator()), "%"); + + } else { + + cmd = IMAPCommand::LIST( + pathString.empty() + ? "" + : (pathString + m_connection->hierarchySeparator()), + "%" + ); } cmd->send(m_connection); @@ -691,8 +737,8 @@ std::vector <shared_ptr <folder> > IMAPFolder::getFolders(const bool recursive) scoped_ptr <IMAPParser::response> resp(m_connection->readResponse()); if (resp->isBad() || resp->response_done()->response_tagged()-> - resp_cond_state()->status() != IMAPParser::resp_cond_state::OK) - { + resp_cond_state()->status() != IMAPParser::resp_cond_state::OK) { + throw exceptions::command_error("LIST", resp->getErrorLog(), "bad response"); } @@ -703,57 +749,62 @@ std::vector <shared_ptr <folder> > IMAPFolder::getFolders(const bool recursive) std::vector <shared_ptr <folder> > v; for (std::vector <IMAPParser::continue_req_or_response_data*>::const_iterator - it = respDataList.begin() ; it != respDataList.end() ; ++it) - { - if ((*it)->response_data() == NULL) - { - throw exceptions::command_error("LIST", - resp->getErrorLog(), "invalid response"); + it = respDataList.begin() ; it != respDataList.end() ; ++it) { + + if ((*it)->response_data() == NULL) { + + throw exceptions::command_error("LIST", resp->getErrorLog(), "invalid response"); } const IMAPParser::mailbox_data* mailboxData = (*it)->response_data()->mailbox_data(); - if (mailboxData == NULL || mailboxData->type() != IMAPParser::mailbox_data::LIST) + if (mailboxData == NULL || mailboxData->type() != IMAPParser::mailbox_data::LIST) { continue; + } // Get folder path const class IMAPParser::mailbox* mailbox = mailboxData->mailbox_list()->mailbox(); - folder::path path = IMAPUtils::stringToPath - (mailboxData->mailbox_list()->quoted_char(), mailbox->name()); + folder::path path = IMAPUtils::stringToPath( + mailboxData->mailbox_list()->quoted_char(), mailbox->name() + ); + + if (recursive || m_path.isDirectParentOf(path)) { - if (recursive || m_path.isDirectParentOf(path)) - { // Append folder to list const class IMAPParser::mailbox_flag_list* mailbox_flag_list = mailboxData->mailbox_list()->mailbox_flag_list(); shared_ptr <folderAttributes> attribs = make_shared <folderAttributes>(); - IMAPUtils::mailboxFlagsToFolderAttributes - (m_connection, mailbox_flag_list, *attribs); + IMAPUtils::mailboxFlagsToFolderAttributes(m_connection, mailbox_flag_list, *attribs); - v.push_back(shared_ptr <IMAPFolder>(new IMAPFolder(path, store, attribs))); + v.push_back(make_shared <IMAPFolder>(path, store, attribs)); } } - return (v); + return v; } -void IMAPFolder::fetchMessages(std::vector <shared_ptr <message> >& msg, const fetchAttributes& options, - utility::progressListener* progress) -{ +void IMAPFolder::fetchMessages( + std::vector <shared_ptr <message> >& msg, + const fetchAttributes& options, + utility::progressListener* progress +) { + shared_ptr <IMAPStore> store = m_store.lock(); - if (!store) + if (!store) { throw exceptions::illegal_state("Store disconnected"); - else if (!isOpen()) + } else if (!isOpen()) { throw exceptions::illegal_state("Folder not open"); + } - if (msg.empty()) + if (msg.empty()) { return; + } // Build message numbers list std::vector <size_t> list; @@ -761,24 +812,24 @@ void IMAPFolder::fetchMessages(std::vector <shared_ptr <message> >& msg, const f std::map <size_t, shared_ptr <IMAPMessage> > numberToMsg; - for (std::vector <shared_ptr <message> >::iterator it = msg.begin() ; it != msg.end() ; ++it) - { + for (std::vector <shared_ptr <message> >::iterator it = msg.begin() ; it != msg.end() ; ++it) { + list.push_back((*it)->getNumber()); numberToMsg[(*it)->getNumber()] = dynamicCast <IMAPMessage>(*it); } // Send the request - IMAPUtils::buildFetchCommand - (m_connection, messageSet::byNumber(list), options)->send(m_connection); + IMAPUtils::buildFetchCommand( + m_connection, messageSet::byNumber(list), options + )->send(m_connection); // Get the response scoped_ptr <IMAPParser::response> resp(m_connection->readResponse()); if (resp->isBad() || resp->response_done()->response_tagged()-> - resp_cond_state()->status() != IMAPParser::resp_cond_state::OK) - { - throw exceptions::command_error("FETCH", - resp->getErrorLog(), "bad response"); + resp_cond_state()->status() != IMAPParser::resp_cond_state::OK) { + + throw exceptions::command_error("FETCH", resp->getErrorLog(), "bad response"); } const std::vector <IMAPParser::continue_req_or_response_data*>& respDataList = @@ -787,58 +838,62 @@ void IMAPFolder::fetchMessages(std::vector <shared_ptr <message> >& msg, const f const size_t total = msg.size(); size_t current = 0; - if (progress) + if (progress) { progress->start(total); + } + + try { - try - { for (std::vector <IMAPParser::continue_req_or_response_data*>::const_iterator - it = respDataList.begin() ; it != respDataList.end() ; ++it) - { - if ((*it)->response_data() == NULL) - { - throw exceptions::command_error("FETCH", - resp->getErrorLog(), "invalid response"); + it = respDataList.begin() ; it != respDataList.end() ; ++it) { + + if ((*it)->response_data() == NULL) { + + throw exceptions::command_error("FETCH", resp->getErrorLog(), "invalid response"); } const IMAPParser::message_data* messageData = (*it)->response_data()->message_data(); // We are only interested in responses of type "FETCH" - if (messageData == NULL || messageData->type() != IMAPParser::message_data::FETCH) + if (messageData == NULL || messageData->type() != IMAPParser::message_data::FETCH) { continue; + } // Process fetch response for this message const size_t num = messageData->number(); std::map <size_t, shared_ptr <IMAPMessage> >::iterator msg = numberToMsg.find(num); - if (msg != numberToMsg.end()) - { + if (msg != numberToMsg.end()) { + (*msg).second->processFetchResponse(options, messageData); - if (progress) + if (progress) { progress->progress(++current, total); + } } } - } - catch (...) - { - if (progress) + + } catch (...) { + + if (progress) { progress->stop(total); + } throw; } - if (progress) + if (progress) { progress->stop(total); + } processStatusUpdate(resp.get()); } -void IMAPFolder::fetchMessage(shared_ptr <message> msg, const fetchAttributes& options) -{ +void IMAPFolder::fetchMessage(const shared_ptr <message>& msg, const fetchAttributes& options) { + std::vector <shared_ptr <message> > msgs; msgs.push_back(msg); @@ -846,35 +901,37 @@ void IMAPFolder::fetchMessage(shared_ptr <message> msg, const fetchAttributes& o } -std::vector <shared_ptr <message> > IMAPFolder::getAndFetchMessages - (const messageSet& msgs, const fetchAttributes& attribs) -{ +std::vector <shared_ptr <message> > IMAPFolder::getAndFetchMessages( + const messageSet& msgs, + const fetchAttributes& attribs +) { + shared_ptr <IMAPStore> store = m_store.lock(); - if (!store) + if (!store) { throw exceptions::illegal_state("Store disconnected"); - else if (!isOpen()) + } else if (!isOpen()) { throw exceptions::illegal_state("Folder not open"); + } - if (msgs.isEmpty()) + if (msgs.isEmpty()) { return std::vector <shared_ptr <message> >(); + } // Ensure we also get the UID for each message fetchAttributes attribsWithUID(attribs); attribsWithUID.add(fetchAttributes::UID); // Send the request - IMAPUtils::buildFetchCommand - (m_connection, msgs, attribsWithUID)->send(m_connection); + IMAPUtils::buildFetchCommand(m_connection, msgs, attribsWithUID)->send(m_connection); // Get the response scoped_ptr <IMAPParser::response> resp(m_connection->readResponse()); if (resp->isBad() || resp->response_done()->response_tagged()-> - resp_cond_state()->status() != IMAPParser::resp_cond_state::OK) - { - throw exceptions::command_error("FETCH", - resp->getErrorLog(), "bad response"); + resp_cond_state()->status() != IMAPParser::resp_cond_state::OK) { + + throw exceptions::command_error("FETCH", resp->getErrorLog(), "bad response"); } const std::vector <IMAPParser::continue_req_or_response_data*>& respDataList = @@ -883,20 +940,20 @@ std::vector <shared_ptr <message> > IMAPFolder::getAndFetchMessages std::vector <shared_ptr <message> > messages; for (std::vector <IMAPParser::continue_req_or_response_data*>::const_iterator - it = respDataList.begin() ; it != respDataList.end() ; ++it) - { - if ((*it)->response_data() == NULL) - { - throw exceptions::command_error("FETCH", - resp->getErrorLog(), "invalid response"); + it = respDataList.begin() ; it != respDataList.end() ; ++it) { + + if ((*it)->response_data() == NULL) { + + throw exceptions::command_error("FETCH", resp->getErrorLog(), "invalid response"); } const IMAPParser::message_data* messageData = (*it)->response_data()->message_data(); // We are only interested in responses of type "FETCH" - if (messageData == NULL || messageData->type() != IMAPParser::message_data::FETCH) + if (messageData == NULL || messageData->type() != IMAPParser::message_data::FETCH) { continue; + } // Get message number const size_t msgNum = messageData->number(); @@ -906,10 +963,9 @@ std::vector <shared_ptr <message> > IMAPFolder::getAndFetchMessages message::uid msgUID; for (std::vector <IMAPParser::msg_att_item*>::const_iterator - it = atts.begin() ; it != atts.end() ; ++it) - { - if ((*it)->type() == IMAPParser::msg_att_item::UID) - { + it = atts.begin() ; it != atts.end() ; ++it) { + + if ((*it)->type() == IMAPParser::msg_att_item::UID) { msgUID = (*it)->unique_id()->value(); break; } @@ -931,8 +987,8 @@ std::vector <shared_ptr <message> > IMAPFolder::getAndFetchMessages } -int IMAPFolder::getFetchCapabilities() const -{ +int IMAPFolder::getFetchCapabilities() const { + return fetchAttributes::ENVELOPE | fetchAttributes::CONTENT_INFO | fetchAttributes::STRUCTURE | fetchAttributes::FLAGS | fetchAttributes::SIZE | fetchAttributes::FULL_HEADER | @@ -940,64 +996,71 @@ int IMAPFolder::getFetchCapabilities() const } -shared_ptr <folder> IMAPFolder::getParent() -{ - if (m_path.isEmpty()) +shared_ptr <folder> IMAPFolder::getParent() { + + if (m_path.isEmpty()) { + return null; - else - return shared_ptr <IMAPFolder>( - new IMAPFolder(m_path.getParent(), m_store.lock(), shared_ptr <folderAttributes>()) + + } else { + + return make_shared <IMAPFolder>( + m_path.getParent(), m_store.lock(), shared_ptr <folderAttributes>() ); + } } -shared_ptr <const store> IMAPFolder::getStore() const -{ +shared_ptr <const store> IMAPFolder::getStore() const { + return m_store.lock(); } -shared_ptr <store> IMAPFolder::getStore() -{ +shared_ptr <store> IMAPFolder::getStore() { + return m_store.lock(); } -void IMAPFolder::registerMessage(IMAPMessage* msg) -{ +void IMAPFolder::registerMessage(IMAPMessage* msg) { + m_messages.push_back(msg); } -void IMAPFolder::unregisterMessage(IMAPMessage* msg) -{ +void IMAPFolder::unregisterMessage(IMAPMessage* msg) { + std::vector <IMAPMessage*>::iterator it = std::find(m_messages.begin(), m_messages.end(), msg); - if (it != m_messages.end()) + if (it != m_messages.end()) { m_messages.erase(it); + } } -void IMAPFolder::onStoreDisconnected() -{ +void IMAPFolder::onStoreDisconnected() { + m_store.reset(); } -void IMAPFolder::deleteMessages(const messageSet& msgs) -{ +void IMAPFolder::deleteMessages(const messageSet& msgs) { + shared_ptr <IMAPStore> store = m_store.lock(); - if (msgs.isEmpty()) + if (msgs.isEmpty()) { throw exceptions::invalid_argument(); + } - if (!store) + if (!store) { throw exceptions::illegal_state("Store disconnected"); - else if (!isOpen()) + } else if (!isOpen()) { throw exceptions::illegal_state("Folder not open"); - else if (m_mode == MODE_READ_ONLY) + } else if (m_mode == MODE_READ_ONLY) { throw exceptions::illegal_state("Folder is read-only"); + } // Send the request IMAPCommand::STORE( @@ -1009,22 +1072,25 @@ void IMAPFolder::deleteMessages(const messageSet& msgs) scoped_ptr <IMAPParser::response> resp(m_connection->readResponse()); if (resp->isBad() || resp->response_done()->response_tagged()-> - resp_cond_state()->status() != IMAPParser::resp_cond_state::OK) - { - throw exceptions::command_error("STORE", - resp->getErrorLog(), "bad response"); + resp_cond_state()->status() != IMAPParser::resp_cond_state::OK) { + + throw exceptions::command_error("STORE", resp->getErrorLog(), "bad response"); } processStatusUpdate(resp.get()); } -void IMAPFolder::setMessageFlags(const messageSet& msgs, const int flags, const int mode) -{ +void IMAPFolder::setMessageFlags( + const messageSet& msgs, + const int flags, + const int mode +) { + const std::vector <string> flagList = IMAPUtils::messageFlagList(flags); - if (!flagList.empty()) - { + if (!flagList.empty()) { + // Send the request IMAPCommand::STORE(msgs, mode, flagList)->send(m_connection); @@ -1032,10 +1098,9 @@ void IMAPFolder::setMessageFlags(const messageSet& msgs, const int flags, const scoped_ptr <IMAPParser::response> resp(m_connection->readResponse()); if (resp->isBad() || resp->response_done()->response_tagged()-> - resp_cond_state()->status() != IMAPParser::resp_cond_state::OK) - { - throw exceptions::command_error("STORE", - resp->getErrorLog(), "bad response"); + resp_cond_state()->status() != IMAPParser::resp_cond_state::OK) { + + throw exceptions::command_error("STORE", resp->getErrorLog(), "bad response"); } processStatusUpdate(resp.get()); @@ -1043,10 +1108,13 @@ void IMAPFolder::setMessageFlags(const messageSet& msgs, const int flags, const } -messageSet IMAPFolder::addMessage - (shared_ptr <vmime::message> msg, const int flags, - vmime::datetime* date, utility::progressListener* progress) -{ +messageSet IMAPFolder::addMessage( + const shared_ptr <vmime::message>& msg, + const int flags, + vmime::datetime* date, + utility::progressListener* progress +) { + std::ostringstream oss; utility::outputStreamAdapter ossAdapter(oss); @@ -1059,18 +1127,23 @@ messageSet IMAPFolder::addMessage } -messageSet IMAPFolder::addMessage - (utility::inputStream& is, const size_t size, const int flags, - vmime::datetime* date, utility::progressListener* progress) -{ +messageSet IMAPFolder::addMessage( + utility::inputStream& is, + const size_t size, + const int flags, + vmime::datetime* date, + utility::progressListener* progress +) { + shared_ptr <IMAPStore> store = m_store.lock(); - if (!store) + if (!store) { throw exceptions::illegal_state("Store disconnected"); - else if (!isOpen()) + } else if (!isOpen()) { throw exceptions::illegal_state("Folder not open"); - else if (m_mode == MODE_READ_ONLY) + } else if (m_mode == MODE_READ_ONLY) { throw exceptions::illegal_state("Folder is read-only"); + } // Send the request IMAPCommand::APPEND( @@ -1086,16 +1159,15 @@ messageSet IMAPFolder::addMessage = resp->continue_req_or_response_data(); for (std::vector <IMAPParser::continue_req_or_response_data*>::const_iterator - it = respList.begin() ; !ok && (it != respList.end()) ; ++it) - { - if ((*it)->continue_req()) + it = respList.begin() ; !ok && (it != respList.end()) ; ++it) { + + if ((*it)->continue_req()) { ok = true; + } } - if (!ok) - { - throw exceptions::command_error("APPEND", - resp->getErrorLog(), "bad response"); + if (!ok) { + throw exceptions::command_error("APPEND", resp->getErrorLog(), "bad response"); } processStatusUpdate(resp.get()); @@ -1104,17 +1176,20 @@ messageSet IMAPFolder::addMessage const size_t total = size; size_t current = 0; - if (progress) + if (progress) { progress->start(total); + } - const size_t blockSize = std::min(is.getBlockSize(), - static_cast <size_t>(m_connection->getSocket()->getBlockSize())); + const size_t blockSize = std::min( + is.getBlockSize(), + static_cast <size_t>(m_connection->getSocket()->getBlockSize()) + ); std::vector <byte_t> vbuffer(blockSize); byte_t* buffer = &vbuffer.front(); - while (!is.eof()) - { + while (!is.eof()) { + // Read some data from the input stream const size_t read = is.read(buffer, blockSize); current += read; @@ -1123,26 +1198,28 @@ messageSet IMAPFolder::addMessage m_connection->sendRaw(buffer, read); // Notify progress - if (progress) + if (progress) { progress->progress(current, total); + } } m_connection->sendRaw(utility::stringUtils::bytesFromString("\r\n"), 2); - if (m_connection->getTracer()) + if (m_connection->getTracer()) { m_connection->getTracer()->traceSendBytes(current); + } - if (progress) + if (progress) { progress->stop(total); + } // Get the response scoped_ptr <IMAPParser::response> finalResp(m_connection->readResponse()); if (finalResp->isBad() || finalResp->response_done()->response_tagged()-> - resp_cond_state()->status() != IMAPParser::resp_cond_state::OK) - { - throw exceptions::command_error("APPEND", - resp->getErrorLog(), "bad response"); + resp_cond_state()->status() != IMAPParser::resp_cond_state::OK) { + + throw exceptions::command_error("APPEND", resp->getErrorLog(), "bad response"); } processStatusUpdate(finalResp.get()); @@ -1150,23 +1227,25 @@ messageSet IMAPFolder::addMessage const IMAPParser::resp_text_code* respTextCode = finalResp->response_done()->response_tagged()->resp_cond_state()->resp_text()->resp_text_code(); - if (respTextCode && respTextCode->type() == IMAPParser::resp_text_code::APPENDUID) + if (respTextCode && respTextCode->type() == IMAPParser::resp_text_code::APPENDUID) { return IMAPUtils::buildMessageSet(respTextCode->uid_set()); + } return messageSet::empty(); } -void IMAPFolder::expunge() -{ +void IMAPFolder::expunge() { + shared_ptr <IMAPStore> store = m_store.lock(); - if (!store) + if (!store) { throw exceptions::illegal_state("Store disconnected"); - else if (!isOpen()) + } else if (!isOpen()) { throw exceptions::illegal_state("Folder not open"); - else if (m_mode == MODE_READ_ONLY) + } else if (m_mode == MODE_READ_ONLY) { throw exceptions::illegal_state("Folder is read-only"); + } // Send the request IMAPCommand::EXPUNGE()->send(m_connection); @@ -1175,28 +1254,28 @@ void IMAPFolder::expunge() scoped_ptr <IMAPParser::response> resp(m_connection->readResponse()); if (resp->isBad() || resp->response_done()->response_tagged()-> - resp_cond_state()->status() != IMAPParser::resp_cond_state::OK) - { - throw exceptions::command_error("EXPUNGE", - resp->getErrorLog(), "bad response"); + resp_cond_state()->status() != IMAPParser::resp_cond_state::OK) { + + throw exceptions::command_error("EXPUNGE", resp->getErrorLog(), "bad response"); } processStatusUpdate(resp.get()); } -void IMAPFolder::rename(const folder::path& newPath) -{ +void IMAPFolder::rename(const folder::path& newPath) { + shared_ptr <IMAPStore> store = m_store.lock(); - if (!store) + if (!store) { throw exceptions::illegal_state("Store disconnected"); - else if (m_path.isEmpty() || newPath.isEmpty()) + } else if (m_path.isEmpty() || newPath.isEmpty()) { throw exceptions::illegal_operation("Cannot rename root folder"); - else if (m_path.getSize() == 1 && m_name.getBuffer() == "INBOX") + } else if (m_path.getSize() == 1 && m_name.getBuffer() == "INBOX") { throw exceptions::illegal_operation("Cannot rename 'INBOX' folder"); - else if (!store->isValidFolderName(newPath.getLastComponent())) + } else if (!store->isValidFolderName(newPath.getLastComponent())) { throw exceptions::invalid_folder_name(); + } // Send the request IMAPCommand::RENAME( @@ -1208,10 +1287,9 @@ void IMAPFolder::rename(const folder::path& newPath) scoped_ptr <IMAPParser::response> resp(m_connection->readResponse()); if (resp->isBad() || resp->response_done()->response_tagged()-> - resp_cond_state()->status() != IMAPParser::resp_cond_state::OK) - { - throw exceptions::command_error("RENAME", - resp->getErrorLog(), "bad response"); + resp_cond_state()->status() != IMAPParser::resp_cond_state::OK) { + + throw exceptions::command_error("RENAME", resp->getErrorLog(), "bad response"); } // Notify folder renamed @@ -1221,26 +1299,31 @@ void IMAPFolder::rename(const folder::path& newPath) m_name = newPath.getLastComponent(); shared_ptr <events::folderEvent> event = - make_shared <events::folderEvent> - (dynamicCast <folder>(shared_from_this()), - events::folderEvent::TYPE_RENAMED, oldPath, newPath); + make_shared <events::folderEvent>( + dynamicCast <folder>(shared_from_this()), + events::folderEvent::TYPE_RENAMED, + oldPath, + newPath + ); notifyFolder(event); // Notify sub-folders for (std::list <IMAPFolder*>::iterator it = store->m_folders.begin() ; - it != store->m_folders.end() ; ++it) - { - if ((*it) != this && oldPath.isParentOf((*it)->getFullPath())) - { + it != store->m_folders.end() ; ++it) { + + if ((*it) != this && oldPath.isParentOf((*it)->getFullPath())) { + folder::path oldPath((*it)->m_path); (*it)->m_path.renameParent(oldPath, newPath); shared_ptr <events::folderEvent> event = - make_shared <events::folderEvent> - (dynamicCast <folder>((*it)->shared_from_this()), - events::folderEvent::TYPE_RENAMED, oldPath, (*it)->m_path); + make_shared <events::folderEvent>( + dynamicCast <folder>((*it)->shared_from_this()), + events::folderEvent::TYPE_RENAMED, + oldPath, (*it)->m_path + ); (*it)->notifyFolder(event); } @@ -1250,14 +1333,15 @@ void IMAPFolder::rename(const folder::path& newPath) } -messageSet IMAPFolder::copyMessages(const folder::path& dest, const messageSet& set) -{ +messageSet IMAPFolder::copyMessages(const folder::path& dest, const messageSet& set) { + shared_ptr <IMAPStore> store = m_store.lock(); - if (!store) + if (!store) { throw exceptions::illegal_state("Store disconnected"); - else if (!isOpen()) + } else if (!isOpen()) { throw exceptions::illegal_state("Folder not open"); + } // Send the request IMAPCommand::COPY( @@ -1269,10 +1353,9 @@ messageSet IMAPFolder::copyMessages(const folder::path& dest, const messageSet& scoped_ptr <IMAPParser::response> resp(m_connection->readResponse()); if (resp->isBad() || resp->response_done()->response_tagged()-> - resp_cond_state()->status() != IMAPParser::resp_cond_state::OK) - { - throw exceptions::command_error("COPY", - resp->getErrorLog(), "bad response"); + resp_cond_state()->status() != IMAPParser::resp_cond_state::OK) { + + throw exceptions::command_error("COPY", resp->getErrorLog(), "bad response"); } processStatusUpdate(resp.get()); @@ -1280,15 +1363,16 @@ messageSet IMAPFolder::copyMessages(const folder::path& dest, const messageSet& const IMAPParser::resp_text_code* respTextCode = resp->response_done()->response_tagged()->resp_cond_state()->resp_text()->resp_text_code(); - if (respTextCode && respTextCode->type() == IMAPParser::resp_text_code::COPYUID) + if (respTextCode && respTextCode->type() == IMAPParser::resp_text_code::COPYUID) { return IMAPUtils::buildMessageSet(respTextCode->uid_set2()); + } return messageSet::empty(); } -void IMAPFolder::status(size_t& count, size_t& unseen) -{ +void IMAPFolder::status(size_t& count, size_t& unseen) { + count = 0; unseen = 0; @@ -1299,12 +1383,13 @@ void IMAPFolder::status(size_t& count, size_t& unseen) } -shared_ptr <folderStatus> IMAPFolder::getStatus() -{ +shared_ptr <folderStatus> IMAPFolder::getStatus() { + shared_ptr <IMAPStore> store = m_store.lock(); - if (!store) + if (!store) { throw exceptions::illegal_state("Store disconnected"); + } // Build the attributes list std::vector <string> attribs; @@ -1314,8 +1399,9 @@ shared_ptr <folderStatus> IMAPFolder::getStatus() attribs.push_back("UIDNEXT"); attribs.push_back("UIDVALIDITY"); - if (m_connection->hasCapability("CONDSTORE")) + if (m_connection->hasCapability("CONDSTORE")) { attribs.push_back("HIGHESTMODSEQ"); + } // Send the request IMAPCommand::STATUS( @@ -1327,25 +1413,24 @@ shared_ptr <folderStatus> IMAPFolder::getStatus() scoped_ptr <IMAPParser::response> resp(m_connection->readResponse()); if (resp->isBad() || resp->response_done()->response_tagged()-> - resp_cond_state()->status() != IMAPParser::resp_cond_state::OK) - { - throw exceptions::command_error("STATUS", - resp->getErrorLog(), "bad response"); + resp_cond_state()->status() != IMAPParser::resp_cond_state::OK) { + + throw exceptions::command_error("STATUS", resp->getErrorLog(), "bad response"); } const std::vector <IMAPParser::continue_req_or_response_data*>& respDataList = resp->continue_req_or_response_data(); for (std::vector <IMAPParser::continue_req_or_response_data*>::const_iterator - it = respDataList.begin() ; it != respDataList.end() ; ++it) - { - if ((*it)->response_data() != NULL) - { + it = respDataList.begin() ; it != respDataList.end() ; ++it) { + + if ((*it)->response_data() != NULL) { + const IMAPParser::response_data* responseData = (*it)->response_data(); if (responseData->mailbox_data() && - responseData->mailbox_data()->type() == IMAPParser::mailbox_data::STATUS) - { + responseData->mailbox_data()->type() == IMAPParser::mailbox_data::STATUS) { + shared_ptr <IMAPFolderStatus> status = make_shared <IMAPFolderStatus>(); status->updateFromResponse(responseData->mailbox_data()); @@ -1356,25 +1441,25 @@ shared_ptr <folderStatus> IMAPFolder::getStatus() } } - throw exceptions::command_error("STATUS", - resp->getErrorLog(), "invalid response"); + throw exceptions::command_error("STATUS", resp->getErrorLog(), "invalid response"); } -void IMAPFolder::noop() -{ +void IMAPFolder::noop() { + shared_ptr <IMAPStore> store = m_store.lock(); - if (!store) + if (!store) { throw exceptions::illegal_state("Store disconnected"); + } IMAPCommand::NOOP()->send(m_connection); scoped_ptr <IMAPParser::response> resp(m_connection->readResponse()); if (resp->isBad() || resp->response_done()->response_tagged()-> - resp_cond_state()->status() != IMAPParser::resp_cond_state::OK) - { + resp_cond_state()->status() != IMAPParser::resp_cond_state::OK) { + throw exceptions::command_error("NOOP", resp->getErrorLog()); } @@ -1382,8 +1467,8 @@ void IMAPFolder::noop() } -std::vector <size_t> IMAPFolder::getMessageNumbersStartingOnUID(const message::uid& uid) -{ +std::vector <size_t> IMAPFolder::getMessageNumbersStartingOnUID(const message::uid& uid) { + // Send the request std::ostringstream uidSearchKey; uidSearchKey.imbue(std::locale::classic()); @@ -1398,22 +1483,20 @@ std::vector <size_t> IMAPFolder::getMessageNumbersStartingOnUID(const message::u scoped_ptr <IMAPParser::response> resp(m_connection->readResponse()); if (resp->isBad() || - resp->response_done()->response_tagged()->resp_cond_state()->status() != IMAPParser::resp_cond_state::OK) - { - throw exceptions::command_error("SEARCH", - resp->getErrorLog(), "bad response"); + resp->response_done()->response_tagged()->resp_cond_state()->status() != IMAPParser::resp_cond_state::OK) { + + throw exceptions::command_error("SEARCH", resp->getErrorLog(), "bad response"); } const std::vector <IMAPParser::continue_req_or_response_data*>& respDataList = resp->continue_req_or_response_data(); + std::vector <size_t> seqNumbers; for (std::vector <IMAPParser::continue_req_or_response_data*>::const_iterator - it = respDataList.begin() ; it != respDataList.end() ; ++it) - { - if ((*it)->response_data() == NULL) - { - throw exceptions::command_error("SEARCH", - resp->getErrorLog(), "invalid response"); + it = respDataList.begin() ; it != respDataList.end() ; ++it) { + + if ((*it)->response_data() == NULL) { + throw exceptions::command_error("SEARCH", resp->getErrorLog(), "invalid response"); } const IMAPParser::mailbox_data* mailboxData = @@ -1421,16 +1504,16 @@ std::vector <size_t> IMAPFolder::getMessageNumbersStartingOnUID(const message::u // We are only interested in responses of type "SEARCH" if (mailboxData == NULL || - mailboxData->type() != IMAPParser::mailbox_data::SEARCH) - { + mailboxData->type() != IMAPParser::mailbox_data::SEARCH) { + continue; } for (std::vector <IMAPParser::nz_number*>::const_iterator it = mailboxData->search_nz_number_list().begin() ; it != mailboxData->search_nz_number_list().end(); - ++it) - { + ++it) { + seqNumbers.push_back((*it)->value()); } } @@ -1441,8 +1524,8 @@ std::vector <size_t> IMAPFolder::getMessageNumbersStartingOnUID(const message::u } -void IMAPFolder::processStatusUpdate(const IMAPParser::response* resp) -{ +void IMAPFolder::processStatusUpdate(const IMAPParser::response* resp) { + std::vector <shared_ptr <events::event> > events; shared_ptr <IMAPFolderStatus> oldStatus = vmime::clone(m_status); @@ -1451,8 +1534,8 @@ void IMAPFolder::processStatusUpdate(const IMAPParser::response* resp) // Process tagged response if (resp->response_done() && resp->response_done()->response_tagged() && resp->response_done()->response_tagged() - ->resp_cond_state()->resp_text()->resp_text_code()) - { + ->resp_cond_state()->resp_text()->resp_text_code()) { + const IMAPParser::resp_text_code* code = resp->response_done()->response_tagged() ->resp_cond_state()->resp_text()->resp_text_code(); @@ -1463,66 +1546,77 @@ void IMAPFolder::processStatusUpdate(const IMAPParser::response* resp) // Process untagged responses for (std::vector <IMAPParser::continue_req_or_response_data*>::const_iterator it = resp->continue_req_or_response_data().begin() ; - it != resp->continue_req_or_response_data().end() ; ++it) - { + it != resp->continue_req_or_response_data().end() ; ++it) { + if ((*it)->response_data() && (*it)->response_data()->resp_cond_state() && - (*it)->response_data()->resp_cond_state()->resp_text()->resp_text_code()) - { + (*it)->response_data()->resp_cond_state()->resp_text()->resp_text_code()) { + const IMAPParser::resp_text_code* code = (*it)->response_data()->resp_cond_state()->resp_text()->resp_text_code(); m_status->updateFromResponse(code); - } - else if ((*it)->response_data() && (*it)->response_data()->mailbox_data()) - { + + } else if ((*it)->response_data() && (*it)->response_data()->mailbox_data()) { + m_status->updateFromResponse((*it)->response_data()->mailbox_data()); // Update folder attributes, if available - if ((*it)->response_data()->mailbox_data()->type() == IMAPParser::mailbox_data::LIST) - { + if ((*it)->response_data()->mailbox_data()->type() == IMAPParser::mailbox_data::LIST) { + folderAttributes attribs; - IMAPUtils::mailboxFlagsToFolderAttributes - (m_connection, (*it)->response_data()->mailbox_data()->mailbox_list()->mailbox_flag_list(), attribs); + IMAPUtils::mailboxFlagsToFolderAttributes( + m_connection, + (*it)->response_data()->mailbox_data()->mailbox_list()->mailbox_flag_list(), + attribs + ); m_attribs = make_shared <folderAttributes>(attribs); } - } - else if ((*it)->response_data() && (*it)->response_data()->message_data()) - { + + } else if ((*it)->response_data() && (*it)->response_data()->message_data()) { + const IMAPParser::message_data* msgData = (*it)->response_data()->message_data(); const size_t msgNumber = msgData->number(); - if ((*it)->response_data()->message_data()->type() == IMAPParser::message_data::FETCH) - { + if ((*it)->response_data()->message_data()->type() == IMAPParser::message_data::FETCH) { + // Message changed for (std::vector <IMAPMessage*>::iterator mit = - m_messages.begin() ; mit != m_messages.end() ; ++mit) - { - if ((*mit)->getNumber() == msgNumber) + m_messages.begin() ; mit != m_messages.end() ; ++mit) { + + if ((*mit)->getNumber() == msgNumber) { (*mit)->processFetchResponse(/* options */ 0, msgData); + } } - events.push_back(make_shared <events::messageChangedEvent> - (dynamicCast <folder>(shared_from_this()), - events::messageChangedEvent::TYPE_FLAGS, - std::vector <size_t>(1, msgNumber))); - } - else if ((*it)->response_data()->message_data()->type() == IMAPParser::message_data::EXPUNGE) - { + events.push_back( + make_shared <events::messageChangedEvent>( + dynamicCast <folder>(shared_from_this()), + events::messageChangedEvent::TYPE_FLAGS, + std::vector <size_t>(1, msgNumber) + ) + ); + + } else if ((*it)->response_data()->message_data()->type() == IMAPParser::message_data::EXPUNGE) { + // A message has been expunged, renumber messages for (std::vector <IMAPMessage*>::iterator jt = - m_messages.begin() ; jt != m_messages.end() ; ++jt) - { - if ((*jt)->getNumber() == msgNumber) + m_messages.begin() ; jt != m_messages.end() ; ++jt) { + + if ((*jt)->getNumber() == msgNumber) { (*jt)->setExpunged(); - else if ((*jt)->getNumber() > msgNumber) + } else if ((*jt)->getNumber() > msgNumber) { (*jt)->renumber((*jt)->getNumber() - 1); + } } - events.push_back(make_shared <events::messageCountEvent> - (dynamicCast <folder>(shared_from_this()), - events::messageCountEvent::TYPE_REMOVED, - std::vector <size_t>(1, msgNumber))); + events.push_back( + make_shared <events::messageCountEvent>( + dynamicCast <folder>(shared_from_this()), + events::messageCountEvent::TYPE_REMOVED, + std::vector <size_t>(1, msgNumber) + ) + ); expungedMessageCount++; } @@ -1530,26 +1624,29 @@ void IMAPFolder::processStatusUpdate(const IMAPParser::response* resp) } // New messages arrived - if (m_status->getMessageCount() > oldStatus->getMessageCount() - expungedMessageCount) - { + if (m_status->getMessageCount() > oldStatus->getMessageCount() - expungedMessageCount) { + std::vector <size_t> newMessageNumbers; for (size_t msgNumber = oldStatus->getMessageCount() - expungedMessageCount ; - msgNumber <= m_status->getMessageCount() ; ++msgNumber) - { + msgNumber <= m_status->getMessageCount() ; ++msgNumber) { + newMessageNumbers.push_back(msgNumber); } - events.push_back(make_shared <events::messageCountEvent> - (dynamicCast <folder>(shared_from_this()), - events::messageCountEvent::TYPE_ADDED, - newMessageNumbers)); + events.push_back( + make_shared <events::messageCountEvent>( + dynamicCast <folder>(shared_from_this()), + events::messageCountEvent::TYPE_ADDED, + newMessageNumbers + ) + ); } // Dispatch notifications for (std::vector <shared_ptr <events::event> >::iterator evit = - events.begin() ; evit != events.end() ; ++evit) - { + events.begin() ; evit != events.end() ; ++evit) { + notifyEvent(*evit); } } diff --git a/src/vmime/net/imap/IMAPFolder.hpp b/src/vmime/net/imap/IMAPFolder.hpp index d4e1c34a..3e6b04b5 100644 --- a/src/vmime/net/imap/IMAPFolder.hpp +++ b/src/vmime/net/imap/IMAPFolder.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard <[email protected]> +// Copyright (C) 2002 Vincent Richard <[email protected]> // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License as @@ -54,19 +54,23 @@ class IMAPFolderStatus; /** IMAP folder implementation. */ +class VMIME_EXPORT IMAPFolder : public folder { -class VMIME_EXPORT IMAPFolder : public folder -{ private: friend class IMAPStore; friend class IMAPMessage; IMAPFolder(const IMAPFolder&); - IMAPFolder(const folder::path& path, shared_ptr <IMAPStore> store, shared_ptr <folderAttributes> attribs); public: + IMAPFolder( + const folder::path& path, + const shared_ptr <IMAPStore>& store, + const shared_ptr <folderAttributes>& attribs + ); + ~IMAPFolder(); int getMode() const; @@ -100,20 +104,26 @@ public: void deleteMessages(const messageSet& msgs); - void setMessageFlags(const messageSet& msgs, const int flags, const int mode = message::FLAG_MODE_SET); - - messageSet addMessage - (shared_ptr <vmime::message> msg, - const int flags = -1, - vmime::datetime* date = NULL, - utility::progressListener* progress = NULL); - - messageSet addMessage - (utility::inputStream& is, - const size_t size, - const int flags = -1, - vmime::datetime* date = NULL, - utility::progressListener* progress = NULL); + void setMessageFlags( + const messageSet& msgs, + const int flags, + const int mode = message::FLAG_MODE_SET + ); + + messageSet addMessage( + const shared_ptr <vmime::message>& msg, + const int flags = -1, + vmime::datetime* date = NULL, + utility::progressListener* progress = NULL + ); + + messageSet addMessage( + utility::inputStream& is, + const size_t size, + const int flags = -1, + vmime::datetime* date = NULL, + utility::progressListener* progress = NULL + ); messageSet copyMessages(const folder::path& dest, const messageSet& msgs); @@ -130,11 +140,18 @@ public: shared_ptr <store> getStore(); - void fetchMessages(std::vector <shared_ptr <message> >& msg, const fetchAttributes& options, utility::progressListener* progress = NULL); - void fetchMessage(shared_ptr <message> msg, const fetchAttributes& options); + void fetchMessages( + std::vector <shared_ptr <message> >& msg, + const fetchAttributes& options, + utility::progressListener* progress = NULL + ); + + void fetchMessage(const shared_ptr <message>& msg, const fetchAttributes& options); - std::vector <shared_ptr <message> > getAndFetchMessages - (const messageSet& msgs, const fetchAttributes& attribs); + std::vector <shared_ptr <message> > getAndFetchMessages( + const messageSet& msgs, + const fetchAttributes& attribs + ); int getFetchCapabilities() const; diff --git a/src/vmime/net/imap/IMAPFolderStatus.cpp b/src/vmime/net/imap/IMAPFolderStatus.cpp index 73e1dfed..1962c1ca 100644 --- a/src/vmime/net/imap/IMAPFolderStatus.cpp +++ b/src/vmime/net/imap/IMAPFolderStatus.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard <[email protected]> +// Copyright (C) 2002 Vincent Richard <[email protected]> // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License as @@ -41,8 +41,8 @@ IMAPFolderStatus::IMAPFolderStatus() m_recent(0), m_uidValidity(0), m_uidNext(0), - m_highestModSeq(0) -{ + m_highestModSeq(0) { + } @@ -53,166 +53,158 @@ IMAPFolderStatus::IMAPFolderStatus(const IMAPFolderStatus& other) m_recent(other.m_recent), m_uidValidity(other.m_uidValidity), m_uidNext(other.m_uidNext), - m_highestModSeq(other.m_highestModSeq) -{ + m_highestModSeq(other.m_highestModSeq) { + } -size_t IMAPFolderStatus::getMessageCount() const -{ +size_t IMAPFolderStatus::getMessageCount() const { + return m_count; } -size_t IMAPFolderStatus::getUnseenCount() const -{ +size_t IMAPFolderStatus::getUnseenCount() const { + return m_unseen; } -size_t IMAPFolderStatus::getRecentCount() const -{ +size_t IMAPFolderStatus::getRecentCount() const { + return m_recent; } -vmime_uint32 IMAPFolderStatus::getUIDValidity() const -{ +vmime_uint32 IMAPFolderStatus::getUIDValidity() const { + return m_uidValidity; } -vmime_uint32 IMAPFolderStatus::getUIDNext() const -{ +vmime_uint32 IMAPFolderStatus::getUIDNext() const { + return m_uidNext; } -vmime_uint64 IMAPFolderStatus::getHighestModSeq() const -{ +vmime_uint64 IMAPFolderStatus::getHighestModSeq() const { + return m_highestModSeq; } -shared_ptr <folderStatus> IMAPFolderStatus::clone() const -{ +shared_ptr <folderStatus> IMAPFolderStatus::clone() const { + return make_shared <IMAPFolderStatus>(*this); } -bool IMAPFolderStatus::updateFromResponse(const IMAPParser::mailbox_data* resp) -{ +bool IMAPFolderStatus::updateFromResponse(const IMAPParser::mailbox_data* resp) { + bool changed = false; - if (resp->type() == IMAPParser::mailbox_data::STATUS) - { + if (resp->type() == IMAPParser::mailbox_data::STATUS) { + const IMAPParser::status_att_list* statusAttList = resp->status_att_list(); for (std::vector <IMAPParser::status_att_val*>::const_iterator - jt = statusAttList->values().begin() ; jt != statusAttList->values().end() ; ++jt) - { - switch ((*jt)->type()) - { - case IMAPParser::status_att_val::MESSAGES: - { - const size_t count = - static_cast <size_t>((*jt)->value_as_number()->value()); + jt = statusAttList->values().begin() ; jt != statusAttList->values().end() ; ++jt) { - if (m_count != count) - { - m_count = count; - changed = true; - } + switch ((*jt)->type()) { - break; - } - case IMAPParser::status_att_val::UNSEEN: - { - const size_t unseen = - static_cast <size_t>((*jt)->value_as_number()->value()); + case IMAPParser::status_att_val::MESSAGES: { + + const size_t count = + static_cast <size_t>((*jt)->value_as_number()->value()); - if (m_unseen != unseen) - { - m_unseen = unseen; - changed = true; + if (m_count != count) { + m_count = count; + changed = true; + } + + break; } + case IMAPParser::status_att_val::UNSEEN: { - break; - } - case IMAPParser::status_att_val::RECENT: - { - const size_t recent = - static_cast <size_t>((*jt)->value_as_number()->value()); + const size_t unseen = + static_cast <size_t>((*jt)->value_as_number()->value()); - if (m_recent != recent) - { - m_recent = recent; - changed = true; + if (m_unseen != unseen) { + m_unseen = unseen; + changed = true; + } + + break; } + case IMAPParser::status_att_val::RECENT: { - break; - } - case IMAPParser::status_att_val::UIDNEXT: - { - const vmime_uint32 uidNext = - static_cast <vmime_uint32>((*jt)->value_as_number()->value()); + const size_t recent = + static_cast <size_t>((*jt)->value_as_number()->value()); + + if (m_recent != recent) { + m_recent = recent; + changed = true; + } - if (m_uidNext != uidNext) - { - m_uidNext = uidNext; - changed = true; + break; } + case IMAPParser::status_att_val::UIDNEXT: { - break; - } - case IMAPParser::status_att_val::UIDVALIDITY: - { - const vmime_uint32 uidValidity = - static_cast <vmime_uint32>((*jt)->value_as_number()->value()); + const vmime_uint32 uidNext = + static_cast <vmime_uint32>((*jt)->value_as_number()->value()); - if (m_uidValidity != uidValidity) - { - m_uidValidity = uidValidity; - changed = true; + if (m_uidNext != uidNext) { + m_uidNext = uidNext; + changed = true; + } + + break; } + case IMAPParser::status_att_val::UIDVALIDITY: { - break; - } - case IMAPParser::status_att_val::HIGHESTMODSEQ: - { - const vmime_uint64 highestModSeq = - static_cast <vmime_uint64>((*jt)->value_as_mod_sequence_value()->value()); + const vmime_uint32 uidValidity = + static_cast <vmime_uint32>((*jt)->value_as_number()->value()); + + if (m_uidValidity != uidValidity) { + m_uidValidity = uidValidity; + changed = true; + } - if (m_highestModSeq != highestModSeq) - { - m_highestModSeq = highestModSeq; - changed = true; + break; } + case IMAPParser::status_att_val::HIGHESTMODSEQ: { - break; - } + const vmime_uint64 highestModSeq = + static_cast <vmime_uint64>((*jt)->value_as_mod_sequence_value()->value()); + + if (m_highestModSeq != highestModSeq) { + m_highestModSeq = highestModSeq; + changed = true; + } + + break; + } } } - } - else if (resp->type() == IMAPParser::mailbox_data::EXISTS) - { + + } else if (resp->type() == IMAPParser::mailbox_data::EXISTS) { + const size_t count = static_cast <size_t>(resp->number()->value()); - if (m_count != count) - { + if (m_count != count) { m_count = count; changed = true; } - } - else if (resp->type() == IMAPParser::mailbox_data::RECENT) - { + + } else if (resp->type() == IMAPParser::mailbox_data::RECENT) { + const size_t recent = static_cast <size_t>(resp->number()->value()); - if (m_recent != recent) - { + if (m_recent != recent) { m_recent = recent; changed = true; } @@ -222,77 +214,73 @@ bool IMAPFolderStatus::updateFromResponse(const IMAPParser::mailbox_data* resp) } -bool IMAPFolderStatus::updateFromResponse(const IMAPParser::resp_text_code* resp) -{ +bool IMAPFolderStatus::updateFromResponse(const IMAPParser::resp_text_code* resp) { + bool changed = false; - switch (resp->type()) - { - case IMAPParser::resp_text_code::UIDVALIDITY: - { - const vmime_uint32 uidValidity = - static_cast <vmime_uint32>(resp->nz_number()->value()); + switch (resp->type()) { - if (m_uidValidity != uidValidity) - { - m_uidValidity = uidValidity; - changed = true; - } + case IMAPParser::resp_text_code::UIDVALIDITY: { - break; - } - case IMAPParser::resp_text_code::UIDNEXT: - { - const vmime_uint32 uidNext = - static_cast <vmime_uint32>(resp->nz_number()->value()); - - if (m_uidNext != uidNext) - { - m_uidNext = uidNext; - changed = true; + const vmime_uint32 uidValidity = + static_cast <vmime_uint32>(resp->nz_number()->value()); + + if (m_uidValidity != uidValidity) { + m_uidValidity = uidValidity; + changed = true; + } + + break; } + case IMAPParser::resp_text_code::UIDNEXT: { - break; - } - case IMAPParser::resp_text_code::UNSEEN: - { - const size_t unseen = - static_cast <size_t>(resp->nz_number()->value()); - - if (m_unseen != unseen) - { - m_unseen = unseen; - changed = true; + const vmime_uint32 uidNext = + static_cast <vmime_uint32>(resp->nz_number()->value()); + + if (m_uidNext != uidNext) { + m_uidNext = uidNext; + changed = true; + } + + break; } + case IMAPParser::resp_text_code::UNSEEN: { - break; - } - case IMAPParser::resp_text_code::HIGHESTMODSEQ: - { - const vmime_uint64 highestModSeq = - static_cast <vmime_uint64>(resp->mod_sequence_value()->value()); - - if (m_highestModSeq != highestModSeq) - { - m_highestModSeq = highestModSeq; - changed = true; + const size_t unseen = + static_cast <size_t>(resp->nz_number()->value()); + + if (m_unseen != unseen) + { + m_unseen = unseen; + changed = true; + } + + break; } + case IMAPParser::resp_text_code::HIGHESTMODSEQ: { - break; - } - case IMAPParser::resp_text_code::NOMODSEQ: - { - if (m_highestModSeq != 0) - { - m_highestModSeq = 0; - changed = true; + const vmime_uint64 highestModSeq = + static_cast <vmime_uint64>(resp->mod_sequence_value()->value()); + + if (m_highestModSeq != highestModSeq) { + m_highestModSeq = highestModSeq; + changed = true; + } + + break; } + case IMAPParser::resp_text_code::NOMODSEQ: { - break; - } - default: + if (m_highestModSeq != 0) { + m_highestModSeq = 0; + changed = true; + } + + break; + } + default: - break; + break; } return changed; diff --git a/src/vmime/net/imap/IMAPFolderStatus.hpp b/src/vmime/net/imap/IMAPFolderStatus.hpp index 63143548..846ad771 100644 --- a/src/vmime/net/imap/IMAPFolderStatus.hpp +++ b/src/vmime/net/imap/IMAPFolderStatus.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard <[email protected]> +// Copyright (C) 2002 Vincent Richard <[email protected]> // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License as @@ -43,9 +43,8 @@ namespace imap { /** Holds the status of an IMAP folder. */ +class VMIME_EXPORT IMAPFolderStatus : public folderStatus { -class VMIME_EXPORT IMAPFolderStatus : public folderStatus -{ public: IMAPFolderStatus(); diff --git a/src/vmime/net/imap/IMAPMessage.cpp b/src/vmime/net/imap/IMAPMessage.cpp index 123a94a9..b09c9c19 100644 --- a/src/vmime/net/imap/IMAPMessage.cpp +++ b/src/vmime/net/imap/IMAPMessage.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard <[email protected]> +// Copyright (C) 2002 Vincent Richard <[email protected]> // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License as @@ -56,25 +56,25 @@ namespace imap { // IMAPMessage_literalHandler // -class IMAPMessage_literalHandler : public IMAPParser::literalHandler -{ +class IMAPMessage_literalHandler : public IMAPParser::literalHandler { + public: - IMAPMessage_literalHandler(utility::outputStream& os, utility::progressListener* progress) - { + IMAPMessage_literalHandler(utility::outputStream& os, utility::progressListener* progress) { + m_target = shared_ptr <target>(new targetStream(progress, os)); } - shared_ptr <target> targetFor(const IMAPParser::component& comp, const int /* data */) - { - if (typeid(comp) == typeid(IMAPParser::msg_att_item)) - { + shared_ptr <target> targetFor(const IMAPParser::component& comp, const int /* data */) { + + if (typeid(comp) == typeid(IMAPParser::msg_att_item)) { + const int type = static_cast <const IMAPParser::msg_att_item&>(comp).type(); if (type == IMAPParser::msg_att_item::BODY_SECTION || - type == IMAPParser::msg_att_item::RFC822_TEXT) - { + type == IMAPParser::msg_att_item::RFC822_TEXT) { + return m_target; } } @@ -82,8 +82,8 @@ public: return shared_ptr <target>(); } - shared_ptr <target> getTarget() - { + shared_ptr <target> getTarget() { + return m_target; } @@ -101,152 +101,187 @@ private: // -IMAPMessage::IMAPMessage(shared_ptr <IMAPFolder> folder, const size_t num) - : m_folder(folder), m_num(num), m_size(-1U), m_flags(FLAG_UNDEFINED), - m_expunged(false), m_modseq(0), m_structure(null) -{ +IMAPMessage::IMAPMessage( + const shared_ptr <IMAPFolder>& folder, + const size_t num +) + : m_folder(folder), + m_num(num), + m_size(-1U), + m_flags(FLAG_UNDEFINED), + m_expunged(false), + m_modseq(0), + m_structure(null) { + folder->registerMessage(this); } -IMAPMessage::IMAPMessage(shared_ptr <IMAPFolder> folder, const size_t num, const uid& uid) - : m_folder(folder), m_num(num), m_size(-1), m_flags(FLAG_UNDEFINED), - m_expunged(false), m_uid(uid), m_modseq(0), m_structure(null) -{ +IMAPMessage::IMAPMessage( + const shared_ptr <IMAPFolder>& folder, + const size_t num, + const uid& uid +) + : m_folder(folder), + m_num(num), + m_size(-1), + m_flags(FLAG_UNDEFINED), + m_expunged(false), + m_uid(uid), + m_modseq(0), + m_structure(null) { + folder->registerMessage(this); } -IMAPMessage::~IMAPMessage() -{ - try - { +IMAPMessage::~IMAPMessage() { + + try { + shared_ptr <IMAPFolder> folder = m_folder.lock(); - if (folder) + if (folder) { folder->unregisterMessage(this); - } - catch (...) - { + } + + } catch (...) { + // Don't throw in destructor } } -void IMAPMessage::onFolderClosed() -{ +void IMAPMessage::onFolderClosed() { + m_folder.reset(); } -size_t IMAPMessage::getNumber() const -{ - return (m_num); +size_t IMAPMessage::getNumber() const { + + return m_num; } -const message::uid IMAPMessage::getUID() const -{ +const message::uid IMAPMessage::getUID() const { + return m_uid; } -vmime_uint64 IMAPMessage::getModSequence() const -{ +vmime_uint64 IMAPMessage::getModSequence() const { + return m_modseq; } -size_t IMAPMessage::getSize() const -{ - if (m_size == -1U) +size_t IMAPMessage::getSize() const { + + if (m_size == -1U) { throw exceptions::unfetched_object(); + } - return (m_size); + return m_size; } -bool IMAPMessage::isExpunged() const -{ - return (m_expunged); +bool IMAPMessage::isExpunged() const { + + return m_expunged; } -int IMAPMessage::getFlags() const -{ - if (m_flags == FLAG_UNDEFINED) +int IMAPMessage::getFlags() const { + + if (m_flags == FLAG_UNDEFINED) { throw exceptions::unfetched_object(); + } - return (m_flags); + return m_flags; } -shared_ptr <const messageStructure> IMAPMessage::getStructure() const -{ - if (m_structure == NULL) +shared_ptr <const messageStructure> IMAPMessage::getStructure() const { + + if (m_structure == NULL) { throw exceptions::unfetched_object(); + } return m_structure; } -shared_ptr <messageStructure> IMAPMessage::getStructure() -{ - if (m_structure == NULL) +shared_ptr <messageStructure> IMAPMessage::getStructure() { + + if (m_structure == NULL) { throw exceptions::unfetched_object(); + } return m_structure; } -shared_ptr <const header> IMAPMessage::getHeader() const -{ - if (m_header == NULL) +shared_ptr <const header> IMAPMessage::getHeader() const { + + if (m_header == NULL) { throw exceptions::unfetched_object(); + } - return (m_header); + return m_header; } -void IMAPMessage::extract - (utility::outputStream& os, - utility::progressListener* progress, - const size_t start, const size_t length, - const bool peek) const -{ +void IMAPMessage::extract( + utility::outputStream& os, + utility::progressListener* progress, + const size_t start, + const size_t length, + const bool peek +) const { + shared_ptr <const IMAPFolder> folder = m_folder.lock(); - if (!folder) + if (!folder) { throw exceptions::folder_not_found(); + } - extractImpl(null, os, progress, start, length, - EXTRACT_HEADER | EXTRACT_BODY | (peek ? EXTRACT_PEEK : 0)); + extractImpl( + null, os, progress, start, length, + EXTRACT_HEADER | EXTRACT_BODY | (peek ? EXTRACT_PEEK : 0) + ); } -void IMAPMessage::extractPart - (shared_ptr <const messagePart> p, - utility::outputStream& os, - utility::progressListener* progress, - const size_t start, const size_t length, - const bool peek) const -{ +void IMAPMessage::extractPart( + const shared_ptr <const messagePart>& p, + utility::outputStream& os, + utility::progressListener* progress, + const size_t start, + const size_t length, + const bool peek +) const { + shared_ptr <const IMAPFolder> folder = m_folder.lock(); - if (!folder) + if (!folder) { throw exceptions::folder_not_found(); + } - extractImpl(p, os, progress, start, length, - EXTRACT_HEADER | EXTRACT_BODY | (peek ? EXTRACT_PEEK : 0)); + extractImpl( + p, os, progress, start, length, + EXTRACT_HEADER | EXTRACT_BODY | (peek ? EXTRACT_PEEK : 0) + ); } -void IMAPMessage::fetchPartHeader(shared_ptr <messagePart> p) -{ +void IMAPMessage::fetchPartHeader(const shared_ptr <messagePart>& p) { + shared_ptr <IMAPFolder> folder = m_folder.lock(); - if (!folder) + if (!folder) { throw exceptions::folder_not_found(); + } std::ostringstream oss; utility::outputStreamAdapter ossAdapter(oss); @@ -257,10 +292,10 @@ void IMAPMessage::fetchPartHeader(shared_ptr <messagePart> p) } -void IMAPMessage::fetchPartHeaderForStructure(shared_ptr <messageStructure> str) -{ - for (size_t i = 0, n = str->getPartCount() ; i < n ; ++i) - { +void IMAPMessage::fetchPartHeaderForStructure(const shared_ptr <messageStructure>& str) { + + for (size_t i = 0, n = str->getPartCount() ; i < n ; ++i) { + shared_ptr <messagePart> part = str->getPartAt(i); // Fetch header of current part @@ -272,42 +307,43 @@ void IMAPMessage::fetchPartHeaderForStructure(shared_ptr <messageStructure> str) } -size_t IMAPMessage::extractImpl - (shared_ptr <const messagePart> p, - utility::outputStream& os, - utility::progressListener* progress, - const size_t start, const size_t length, - const int extractFlags) const -{ +size_t IMAPMessage::extractImpl( + const shared_ptr <const messagePart>& p, + utility::outputStream& os, + utility::progressListener* progress, + const size_t start, + const size_t length, + const int extractFlags +) const { + shared_ptr <const IMAPFolder> folder = m_folder.lock(); IMAPMessage_literalHandler literalHandler(os, progress); - if (length == 0) + if (length == 0) { return 0; + } // Construct section identifier std::ostringstream section; section.imbue(std::locale::classic()); - if (p != NULL) - { + if (p != NULL) { + shared_ptr <const IMAPMessagePart> currentPart = dynamicCast <const IMAPMessagePart>(p); std::vector <size_t> numbers; numbers.push_back(currentPart->getNumber()); currentPart = currentPart->getParent(); - while (currentPart != NULL) - { + while (currentPart != NULL) { numbers.push_back(currentPart->getNumber()); currentPart = currentPart->getParent(); } numbers.erase(numbers.end() - 1); - for (std::vector <size_t>::reverse_iterator it = numbers.rbegin() ; it != numbers.rend() ; ++it) - { + for (std::vector <size_t>::reverse_iterator it = numbers.rbegin() ; it != numbers.rend() ; ++it) { if (it != numbers.rbegin()) section << "."; section << (*it + 1); } @@ -327,53 +363,57 @@ size_t IMAPMessage::extractImpl bodyDesc << "BODY"; - if (extractFlags & EXTRACT_PEEK) + if (extractFlags & EXTRACT_PEEK) { bodyDesc << ".PEEK"; + } bodyDesc << "["; - if (section.str().empty()) - { + if (section.str().empty()) { + // header + body - if ((extractFlags & EXTRACT_HEADER) && (extractFlags & EXTRACT_BODY)) + if ((extractFlags & EXTRACT_HEADER) && (extractFlags & EXTRACT_BODY)) { bodyDesc << ""; // body only - else if (extractFlags & EXTRACT_BODY) + } else if (extractFlags & EXTRACT_BODY) { bodyDesc << "TEXT"; // header only - else if (extractFlags & EXTRACT_HEADER) + } else if (extractFlags & EXTRACT_HEADER) { bodyDesc << "HEADER"; - } - else - { + } + + } else { + bodyDesc << section.str(); // header + body - if ((extractFlags & EXTRACT_HEADER) && (extractFlags & EXTRACT_BODY)) - { + if ((extractFlags & EXTRACT_HEADER) && (extractFlags & EXTRACT_BODY)) { + // First, extract header std::ostringstream header; utility::outputStreamAdapter headerStream(header); - const size_t headerLength = extractImpl - (p, headerStream, /* progress */ NULL, - /* start */ 0, /* length */ -1, extractFlags & ~EXTRACT_BODY); + const size_t headerLength = extractImpl( + p, headerStream, /* progress */ NULL, + /* start */ 0, /* length */ -1, extractFlags & ~EXTRACT_BODY + ); size_t s = start; size_t l = length; - if (s < headerLength) - { - if (l == static_cast <size_t>(-1)) - { + if (s < headerLength) { + + if (l == static_cast <size_t>(-1)) { + os.write(header.str().data() + s, headerLength - s); - } - else - { + + } else { + size_t headerCopyLength = l; - if (start + headerCopyLength > headerLength) + if (start + headerCopyLength > headerLength) { headerCopyLength = headerLength - start; + } os.write(header.str().data() + s, headerCopyLength); @@ -381,30 +421,31 @@ size_t IMAPMessage::extractImpl } s = 0; - } - else - { + + } else { + s -= headerLength; } // Then, extract body return extractImpl(p, os, progress, s, l, extractFlags & ~EXTRACT_HEADER); - } + // header only - else if (extractFlags & EXTRACT_HEADER) - { + } else if (extractFlags & EXTRACT_HEADER) { + bodyDesc << ".MIME"; // "MIME" not "HEADER" for parts } } bodyDesc << "]"; - if (start != 0 || length != static_cast <size_t>(-1)) - { - if (length == static_cast <size_t>(-1)) + if (start != 0 || length != static_cast <size_t>(-1)) { + + if (length == static_cast <size_t>(-1)) { bodyDesc << "<" << start << "." << static_cast <unsigned int>(-1) << ">"; - else + } else { bodyDesc << "<" << start << "." << length << ">"; + } } std::vector <std::string> fetchParams; @@ -414,22 +455,19 @@ size_t IMAPMessage::extractImpl IMAPCommand::FETCH( m_uid.empty() ? messageSet::byNumber(m_num) : messageSet::byUID(m_uid), fetchParams - )->send(constCast <IMAPFolder>(folder)->m_connection); + )->send(folder->m_connection); // Get the response - scoped_ptr <IMAPParser::response> resp - (constCast <IMAPFolder>(folder)->m_connection->readResponse(&literalHandler)); + scoped_ptr <IMAPParser::response> resp(folder->m_connection->readResponse(&literalHandler)); if (resp->isBad() || resp->response_done()->response_tagged()-> - resp_cond_state()->status() != IMAPParser::resp_cond_state::OK) - { - throw exceptions::command_error("FETCH", - resp->getErrorLog(), "bad response"); + resp_cond_state()->status() != IMAPParser::resp_cond_state::OK) { + + throw exceptions::command_error("FETCH", resp->getErrorLog(), "bad response"); } - if (extractFlags & EXTRACT_BODY) - { + if (extractFlags & EXTRACT_BODY) { // TODO: update the flags (eg. flag "\Seen" may have been set) } @@ -437,9 +475,11 @@ size_t IMAPMessage::extractImpl } -int IMAPMessage::processFetchResponse - (const fetchAttributes& options, const IMAPParser::message_data* msgData) -{ +int IMAPMessage::processFetchResponse( + const fetchAttributes& options, + const IMAPParser::message_data* msgData +) { + shared_ptr <IMAPFolder> folder = m_folder.lock(); // Get message attributes @@ -447,138 +487,142 @@ int IMAPMessage::processFetchResponse int changes = 0; for (std::vector <IMAPParser::msg_att_item*>::const_iterator - it = atts.begin() ; it != atts.end() ; ++it) - { - switch ((*it)->type()) - { - case IMAPParser::msg_att_item::FLAGS: - { - int flags = IMAPUtils::messageFlagsFromFlags((*it)->flag_list()); - - if (m_flags != flags) - { - m_flags = flags; - changes |= events::messageChangedEvent::TYPE_FLAGS; + it = atts.begin() ; it != atts.end() ; ++it) { + + switch ((*it)->type()) { + + case IMAPParser::msg_att_item::FLAGS: { + + int flags = IMAPUtils::messageFlagsFromFlags((*it)->flag_list()); + + if (m_flags != flags) { + m_flags = flags; + changes |= events::messageChangedEvent::TYPE_FLAGS; + } + + break; } + case IMAPParser::msg_att_item::UID: { - break; - } - case IMAPParser::msg_att_item::UID: - { - m_uid = (*it)->unique_id()->value(); - break; - } - case IMAPParser::msg_att_item::MODSEQ: - { - m_modseq = (*it)->mod_sequence_value()->value(); - break; - } - case IMAPParser::msg_att_item::ENVELOPE: - { - if (!options.has(fetchAttributes::FULL_HEADER)) - { - const IMAPParser::envelope* env = (*it)->envelope(); - shared_ptr <vmime::header> hdr = getOrCreateHeader(); + m_uid = (*it)->unique_id()->value(); + break; + } + case IMAPParser::msg_att_item::MODSEQ: { + + m_modseq = (*it)->mod_sequence_value()->value(); + break; + } + case IMAPParser::msg_att_item::ENVELOPE: { + + if (!options.has(fetchAttributes::FULL_HEADER)) { - // Date - hdr->Date()->setValue(env->env_date()->value()); + const IMAPParser::envelope* env = (*it)->envelope(); + shared_ptr <vmime::header> hdr = getOrCreateHeader(); - // Subject - text subject; - text::decodeAndUnfold(env->env_subject()->value(), &subject); + // Date + hdr->Date()->setValue(env->env_date()->value()); - hdr->Subject()->setValue(subject); + // Subject + text subject; + text::decodeAndUnfold(env->env_subject()->value(), &subject); - // From - mailboxList from; - IMAPUtils::convertAddressList(*(env->env_from()), from); + hdr->Subject()->setValue(subject); - if (!from.isEmpty()) - hdr->From()->setValue(*(from.getMailboxAt(0))); + // From + mailboxList from; + IMAPUtils::convertAddressList(*(env->env_from()), from); - // To - mailboxList to; - IMAPUtils::convertAddressList(*(env->env_to()), to); + if (!from.isEmpty()) { + hdr->From()->setValue(*(from.getMailboxAt(0))); + } + + // To + mailboxList to; + IMAPUtils::convertAddressList(*(env->env_to()), to); - hdr->To()->setValue(to.toAddressList()); + hdr->To()->setValue(to.toAddressList()); - // Sender - mailboxList sender; - IMAPUtils::convertAddressList(*(env->env_sender()), sender); + // Sender + mailboxList sender; + IMAPUtils::convertAddressList(*(env->env_sender()), sender); + + if (!sender.isEmpty()) { + hdr->Sender()->setValue(*(sender.getMailboxAt(0))); + } - if (!sender.isEmpty()) - hdr->Sender()->setValue(*(sender.getMailboxAt(0))); + // Reply-to + mailboxList replyTo; + IMAPUtils::convertAddressList(*(env->env_reply_to()), replyTo); - // Reply-to - mailboxList replyTo; - IMAPUtils::convertAddressList(*(env->env_reply_to()), replyTo); + if (!replyTo.isEmpty()) { + hdr->ReplyTo()->setValue(*(replyTo.getMailboxAt(0))); + } - if (!replyTo.isEmpty()) - hdr->ReplyTo()->setValue(*(replyTo.getMailboxAt(0))); + // Cc + mailboxList cc; + IMAPUtils::convertAddressList(*(env->env_cc()), cc); - // Cc - mailboxList cc; - IMAPUtils::convertAddressList(*(env->env_cc()), cc); + if (!cc.isEmpty()) { + hdr->Cc()->setValue(cc.toAddressList()); + } - if (!cc.isEmpty()) - hdr->Cc()->setValue(cc.toAddressList()); + // Bcc + mailboxList bcc; + IMAPUtils::convertAddressList(*(env->env_bcc()), bcc); - // Bcc - mailboxList bcc; - IMAPUtils::convertAddressList(*(env->env_bcc()), bcc); + if (!bcc.isEmpty()) { + hdr->Bcc()->setValue(bcc.toAddressList()); + } + } - if (!bcc.isEmpty()) - hdr->Bcc()->setValue(bcc.toAddressList()); + break; } + case IMAPParser::msg_att_item::BODY_STRUCTURE: { - break; - } - case IMAPParser::msg_att_item::BODY_STRUCTURE: - { - m_structure = make_shared <IMAPMessageStructure>((*it)->body()); - break; - } - case IMAPParser::msg_att_item::RFC822_HEADER: - { - getOrCreateHeader()->parse((*it)->nstring()->value()); - break; - } - case IMAPParser::msg_att_item::RFC822_SIZE: - { - m_size = static_cast <size_t>((*it)->number()->value()); - break; - } - case IMAPParser::msg_att_item::BODY_SECTION: - { - if (!options.has(fetchAttributes::FULL_HEADER)) - { - if ((*it)->section()->section_text1() && - (*it)->section()->section_text1()->type() - == IMAPParser::section_text::HEADER_FIELDS) - { - header tempHeader; - tempHeader.parse((*it)->nstring()->value()); - - vmime::header& hdr = *getOrCreateHeader(); - std::vector <shared_ptr <headerField> > fields = tempHeader.getFieldList(); - - for (std::vector <shared_ptr <headerField> >::const_iterator jt = fields.begin() ; - jt != fields.end() ; ++jt) - { - hdr.appendField(vmime::clone(*jt)); + m_structure = make_shared <IMAPMessageStructure>((*it)->body()); + break; + } + case IMAPParser::msg_att_item::RFC822_HEADER: { + + getOrCreateHeader()->parse((*it)->nstring()->value()); + break; + } + case IMAPParser::msg_att_item::RFC822_SIZE: { + + m_size = static_cast <size_t>((*it)->number()->value()); + break; + } + case IMAPParser::msg_att_item::BODY_SECTION: { + + if (!options.has(fetchAttributes::FULL_HEADER)) { + + if ((*it)->section()->section_text1() && + (*it)->section()->section_text1()->type() + == IMAPParser::section_text::HEADER_FIELDS) { + + header tempHeader; + tempHeader.parse((*it)->nstring()->value()); + + vmime::header& hdr = *getOrCreateHeader(); + std::vector <shared_ptr <headerField> > fields = tempHeader.getFieldList(); + + for (std::vector <shared_ptr <headerField> >::const_iterator jt = fields.begin() ; + jt != fields.end() ; ++jt) { + + hdr.appendField(vmime::clone(*jt)); + } } } + + break; } + case IMAPParser::msg_att_item::INTERNALDATE: + case IMAPParser::msg_att_item::RFC822: + case IMAPParser::msg_att_item::RFC822_TEXT: + case IMAPParser::msg_att_item::BODY: { - break; - } - case IMAPParser::msg_att_item::INTERNALDATE: - case IMAPParser::msg_att_item::RFC822: - case IMAPParser::msg_att_item::RFC822_TEXT: - case IMAPParser::msg_att_item::BODY: - { - break; - } + break; + } } } @@ -587,34 +631,40 @@ int IMAPMessage::processFetchResponse } -shared_ptr <header> IMAPMessage::getOrCreateHeader() -{ - if (m_header != NULL) - return (m_header); - else - return (m_header = make_shared <header>()); +shared_ptr <header> IMAPMessage::getOrCreateHeader() { + + if (m_header != NULL) { + return m_header; + } else { + return m_header = make_shared <header>(); + } } -void IMAPMessage::setFlags(const int flags, const int mode) -{ +void IMAPMessage::setFlags(const int flags, const int mode) { + shared_ptr <IMAPFolder> folder = m_folder.lock(); - if (!folder) + if (!folder) { throw exceptions::folder_not_found(); + } - if (!m_uid.empty()) + if (!m_uid.empty()) { folder->setMessageFlags(messageSet::byUID(m_uid), flags, mode); - else + } else { folder->setMessageFlags(messageSet::byNumber(m_num), flags, mode); + } } -void IMAPMessage::constructParsedMessage - (shared_ptr <bodyPart> parentPart, shared_ptr <messageStructure> str, int level) -{ - if (level == 0) - { +void IMAPMessage::constructParsedMessage( + const shared_ptr <bodyPart>& parentPart, + const shared_ptr <messageStructure>& str, + int level +) { + + if (level == 0) { + shared_ptr <messagePart> part = str->getPartAt(0); // Copy header @@ -622,17 +672,19 @@ void IMAPMessage::constructParsedMessage parentPart->getHeader()->copyFrom(*hdr); // Initialize body - parentPart->getBody()->setContents - (make_shared <IMAPMessagePartContentHandler> - (dynamicCast <IMAPMessage>(shared_from_this()), - part, parentPart->getBody()->getEncoding())); + parentPart->getBody()->setContents( + make_shared <IMAPMessagePartContentHandler>( + dynamicCast <IMAPMessage>(shared_from_this()), + part, parentPart->getBody()->getEncoding() + ) + ); constructParsedMessage(parentPart, part->getStructure(), 1); - } - else - { - for (size_t i = 0, n = str->getPartCount() ; i < n ; ++i) - { + + } else { + + for (size_t i = 0, n = str->getPartCount() ; i < n ; ++i) { + shared_ptr <messagePart> part = str->getPartAt(i); shared_ptr <bodyPart> childPart = make_shared <bodyPart>(); @@ -642,10 +694,12 @@ void IMAPMessage::constructParsedMessage childPart->getHeader()->copyFrom(*hdr); // Initialize body - childPart->getBody()->setContents - (make_shared <IMAPMessagePartContentHandler> - (dynamicCast <IMAPMessage>(shared_from_this()), - part, childPart->getBody()->getEncoding())); + childPart->getBody()->setContents( + make_shared <IMAPMessagePartContentHandler>( + dynamicCast <IMAPMessage>(shared_from_this()), + part, childPart->getBody()->getEncoding() + ) + ); // Add child part parentPart->getBody()->appendPart(childPart); @@ -657,22 +711,23 @@ void IMAPMessage::constructParsedMessage } -shared_ptr <vmime::message> IMAPMessage::getParsedMessage() -{ +shared_ptr <vmime::message> IMAPMessage::getParsedMessage() { + // Fetch structure shared_ptr <messageStructure> structure; - try - { + try { + structure = getStructure(); - } - catch (exceptions::unfetched_object&) - { + + } catch (exceptions::unfetched_object&) { + std::vector <shared_ptr <message> > msgs; msgs.push_back(dynamicCast <IMAPMessage>(shared_from_this())); - m_folder.lock()->fetchMessages - (msgs, fetchAttributes(fetchAttributes::STRUCTURE), /* progress */ NULL); + m_folder.lock()->fetchMessages( + msgs, fetchAttributes(fetchAttributes::STRUCTURE), /* progress */ NULL + ); structure = getStructure(); } @@ -689,14 +744,14 @@ shared_ptr <vmime::message> IMAPMessage::getParsedMessage() } -void IMAPMessage::renumber(const size_t number) -{ +void IMAPMessage::renumber(const size_t number) { + m_num = number; } -void IMAPMessage::setExpunged() -{ +void IMAPMessage::setExpunged() { + m_expunged = true; } diff --git a/src/vmime/net/imap/IMAPMessage.hpp b/src/vmime/net/imap/IMAPMessage.hpp index 93545f22..60875e8c 100644 --- a/src/vmime/net/imap/IMAPMessage.hpp +++ b/src/vmime/net/imap/IMAPMessage.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard <[email protected]> +// Copyright (C) 2002 Vincent Richard <[email protected]> // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License as @@ -47,9 +47,8 @@ class IMAPFolder; /** IMAP message implementation. */ +class VMIME_EXPORT IMAPMessage : public message { -class VMIME_EXPORT IMAPMessage : public message -{ private: friend class IMAPFolder; @@ -59,8 +58,8 @@ private: public: - IMAPMessage(shared_ptr <IMAPFolder> folder, const size_t num); - IMAPMessage(shared_ptr <IMAPFolder> folder, const size_t num, const uid& uid); + IMAPMessage(const shared_ptr <IMAPFolder>& folder, const size_t num); + IMAPMessage(const shared_ptr <IMAPFolder>& folder, const size_t num, const uid& uid); ~IMAPMessage(); @@ -92,20 +91,24 @@ public: int getFlags() const; void setFlags(const int flags, const int mode = FLAG_MODE_SET); - void extract - (utility::outputStream& os, - utility::progressListener* progress = NULL, - const size_t start = 0, const size_t length = -1, - const bool peek = false) const; - - void extractPart - (shared_ptr <const messagePart> p, - utility::outputStream& os, - utility::progressListener* progress = NULL, - const size_t start = 0, const size_t length = -1, - const bool peek = false) const; - - void fetchPartHeader(shared_ptr <messagePart> p); + void extract( + utility::outputStream& os, + utility::progressListener* progress = NULL, + const size_t start = 0, + const size_t length = -1, + const bool peek = false + ) const; + + void extractPart( + const shared_ptr <const messagePart>& p, + utility::outputStream& os, + utility::progressListener* progress = NULL, + const size_t start = 0, + const size_t length = -1, + const bool peek = false + ) const; + + void fetchPartHeader(const shared_ptr <messagePart>& p); shared_ptr <vmime::message> getParsedMessage(); @@ -135,7 +138,7 @@ private: * * @param str structure for which to fetch parts headers */ - void fetchPartHeaderForStructure(shared_ptr <messageStructure> str); + void fetchPartHeaderForStructure(const shared_ptr <messageStructure>& str); /** Recursively contruct parsed message from structure. * Called by getParsedMessage(). @@ -144,7 +147,11 @@ private: * @param str structure for which to construct part * @param level current nesting level (0 is root) */ - void constructParsedMessage(shared_ptr <bodyPart> parentPart, shared_ptr <messageStructure> str, int level = 0); + void constructParsedMessage( + const shared_ptr <bodyPart>& parentPart, + const shared_ptr <messageStructure>& str, + int level = 0 + ); enum ExtractFlags @@ -154,12 +161,14 @@ private: EXTRACT_PEEK = 0x10 }; - size_t extractImpl - (shared_ptr <const messagePart> p, - utility::outputStream& os, - utility::progressListener* progress, - const size_t start, const size_t length, - const int extractFlags) const; + size_t extractImpl( + const shared_ptr <const messagePart>& p, + utility::outputStream& os, + utility::progressListener* progress, + const size_t start, + const size_t length, + const int extractFlags + ) const; shared_ptr <header> getOrCreateHeader(); diff --git a/src/vmime/net/imap/IMAPMessagePart.cpp b/src/vmime/net/imap/IMAPMessagePart.cpp index 1539f2ca..b76457fb 100644 --- a/src/vmime/net/imap/IMAPMessagePart.cpp +++ b/src/vmime/net/imap/IMAPMessagePart.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard <[email protected]> +// Copyright (C) 2002 Vincent Richard <[email protected]> // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License as @@ -36,119 +36,159 @@ namespace net { namespace imap { -IMAPMessagePart::IMAPMessagePart(shared_ptr <IMAPMessagePart> parent, const size_t number, const IMAPParser::body_type_mpart* mpart) - : m_parent(parent), m_header(null), m_number(number), m_size(0) -{ - m_mediaType = vmime::mediaType - ("multipart", mpart->media_subtype()->value()); +IMAPMessagePart::IMAPMessagePart( + const shared_ptr <IMAPMessagePart>& parent, + const size_t number, + const IMAPParser::body_type_mpart* mpart +) + : m_parent(parent), + m_header(null), + m_number(number), + m_size(0) { + + m_mediaType = vmime::mediaType( + "multipart", + mpart->media_subtype()->value() + ); } -IMAPMessagePart::IMAPMessagePart(shared_ptr <IMAPMessagePart> parent, const size_t number, const IMAPParser::body_type_1part* part) - : m_parent(parent), m_header(null), m_number(number), m_size(0) -{ - if (part->body_type_text()) - { - m_mediaType = vmime::mediaType - ("text", part->body_type_text()-> - media_text()->media_subtype()->value()); +IMAPMessagePart::IMAPMessagePart( + const shared_ptr <IMAPMessagePart>& parent, + const size_t number, + const IMAPParser::body_type_1part* part +) + : m_parent(parent), + m_header(null), + m_number(number), + m_size(0) { + + if (part->body_type_text()) { + + m_mediaType = vmime::mediaType( + "text", + part->body_type_text()->media_text()->media_subtype()->value() + ); m_size = part->body_type_text()->body_fields()->body_fld_octets()->value(); - } - else if (part->body_type_msg()) - { - m_mediaType = vmime::mediaType - ("message", part->body_type_msg()-> - media_message()->media_subtype()->value()); - } - else - { - m_mediaType = vmime::mediaType - (part->body_type_basic()->media_basic()->media_type()->value(), - part->body_type_basic()->media_basic()->media_subtype()->value()); + + } else if (part->body_type_msg()) { + + m_mediaType = vmime::mediaType( + "message", + part->body_type_msg()->media_message()->media_subtype()->value() + ); + + } else { + + m_mediaType = vmime::mediaType( + part->body_type_basic()->media_basic()->media_type()->value(), + part->body_type_basic()->media_basic()->media_subtype()->value() + ); m_size = part->body_type_basic()->body_fields()->body_fld_octets()->value(); + + if (const auto pparam = part->body_type_basic()->body_fields()->body_fld_param()) { + for (const auto& param : pparam->items()) { + if (param->string1()->value() == "NAME") { + m_name = param->string2()->value(); + } + } + } } m_structure = null; } -shared_ptr <const messageStructure> IMAPMessagePart::getStructure() const -{ - if (m_structure != NULL) +shared_ptr <const messageStructure> IMAPMessagePart::getStructure() const { + + if (m_structure) { return m_structure; - else + } else { return IMAPMessageStructure::emptyStructure(); + } } -shared_ptr <messageStructure> IMAPMessagePart::getStructure() -{ - if (m_structure != NULL) +shared_ptr <messageStructure> IMAPMessagePart::getStructure() { + + if (m_structure) { return m_structure; - else + } else { return IMAPMessageStructure::emptyStructure(); + } } -shared_ptr <const IMAPMessagePart> IMAPMessagePart::getParent() const -{ +shared_ptr <const IMAPMessagePart> IMAPMessagePart::getParent() const { + return m_parent.lock(); } -const mediaType& IMAPMessagePart::getType() const -{ +const mediaType& IMAPMessagePart::getType() const { + return m_mediaType; } -size_t IMAPMessagePart::getSize() const -{ +size_t IMAPMessagePart::getSize() const { + return m_size; } -size_t IMAPMessagePart::getNumber() const -{ +size_t IMAPMessagePart::getNumber() const { + return m_number; } -shared_ptr <const header> IMAPMessagePart::getHeader() const -{ - if (m_header == NULL) +string IMAPMessagePart::getName() const { + + return m_name; +} + + +shared_ptr <const header> IMAPMessagePart::getHeader() const { + + if (!m_header) { throw exceptions::unfetched_object(); - else + } else { return m_header; + } } // static -shared_ptr <IMAPMessagePart> IMAPMessagePart::create - (shared_ptr <IMAPMessagePart> parent, const size_t number, const IMAPParser::body* body) -{ - if (body->body_type_mpart()) - { +shared_ptr <IMAPMessagePart> IMAPMessagePart::create( + const shared_ptr <IMAPMessagePart>& parent, + const size_t number, + const IMAPParser::body* body +) { + + if (body->body_type_mpart()) { + shared_ptr <IMAPMessagePart> part = make_shared <IMAPMessagePart>(parent, number, body->body_type_mpart()); part->m_structure = make_shared <IMAPMessageStructure>(part, body->body_type_mpart()->list()); return part; - } - else - { + + } else { + return make_shared <IMAPMessagePart>(parent, number, body->body_type_1part()); } } -header& IMAPMessagePart::getOrCreateHeader() -{ - if (m_header != NULL) +header& IMAPMessagePart::getOrCreateHeader() { + + if (m_header) { return *m_header; - else + } else { return *(m_header = make_shared <header>()); + } } diff --git a/src/vmime/net/imap/IMAPMessagePart.hpp b/src/vmime/net/imap/IMAPMessagePart.hpp index 3b00887b..4a636dd8 100644 --- a/src/vmime/net/imap/IMAPMessagePart.hpp +++ b/src/vmime/net/imap/IMAPMessagePart.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard <[email protected]> +// Copyright (C) 2002 Vincent Richard <[email protected]> // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License as @@ -44,12 +44,21 @@ namespace imap { class IMAPMessageStructure; -class VMIME_EXPORT IMAPMessagePart : public messagePart -{ +class VMIME_EXPORT IMAPMessagePart : public messagePart { + public: - IMAPMessagePart(shared_ptr <IMAPMessagePart> parent, const size_t number, const IMAPParser::body_type_mpart* mpart); - IMAPMessagePart(shared_ptr <IMAPMessagePart> parent, const size_t number, const IMAPParser::body_type_1part* part); + IMAPMessagePart( + const shared_ptr <IMAPMessagePart>& parent, + const size_t number, + const IMAPParser::body_type_mpart* mpart + ); + + IMAPMessagePart( + const shared_ptr <IMAPMessagePart>& parent, + const size_t number, + const IMAPParser::body_type_1part* part + ); shared_ptr <const messageStructure> getStructure() const; shared_ptr <messageStructure> getStructure(); @@ -59,12 +68,16 @@ public: const mediaType& getType() const; size_t getSize() const; size_t getNumber() const; + string getName() const; shared_ptr <const header> getHeader() const; - static shared_ptr <IMAPMessagePart> create - (shared_ptr <IMAPMessagePart> parent, const size_t number, const IMAPParser::body* body); + static shared_ptr <IMAPMessagePart> create( + const shared_ptr <IMAPMessagePart>& parent, + const size_t number, + const IMAPParser::body* body + ); header& getOrCreateHeader(); @@ -77,6 +90,7 @@ private: size_t m_number; size_t m_size; + string m_name; mediaType m_mediaType; }; diff --git a/src/vmime/net/imap/IMAPMessagePartContentHandler.cpp b/src/vmime/net/imap/IMAPMessagePartContentHandler.cpp index 1f53f082..d9cc07d9 100644 --- a/src/vmime/net/imap/IMAPMessagePartContentHandler.cpp +++ b/src/vmime/net/imap/IMAPMessagePartContentHandler.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard <[email protected]> +// Copyright (C) 2002 Vincent Richard <[email protected]> // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License as @@ -42,37 +42,44 @@ namespace net { namespace imap { -IMAPMessagePartContentHandler::IMAPMessagePartContentHandler - (shared_ptr <IMAPMessage> msg, shared_ptr <messagePart> part, const vmime::encoding& encoding) - : m_message(msg), m_part(part), m_encoding(encoding) -{ +IMAPMessagePartContentHandler::IMAPMessagePartContentHandler( + const shared_ptr <IMAPMessage>& msg, + const shared_ptr <messagePart>& part, + const vmime::encoding& encoding +) + : m_message(msg), + m_part(part), + m_encoding(encoding) { + } -shared_ptr <contentHandler> IMAPMessagePartContentHandler::clone() const -{ - return make_shared <IMAPMessagePartContentHandler> - (constCast <IMAPMessage>(m_message.lock()), - constCast <messagePart>(m_part.lock()), - m_encoding); +shared_ptr <contentHandler> IMAPMessagePartContentHandler::clone() const { + + return make_shared <IMAPMessagePartContentHandler>( + m_message.lock(), m_part.lock(), m_encoding + ); } -void IMAPMessagePartContentHandler::generate - (utility::outputStream& os, const vmime::encoding& enc, const size_t maxLineLength) const -{ - shared_ptr <IMAPMessage> msg = constCast <IMAPMessage>(m_message.lock()); - shared_ptr <messagePart> part = constCast <messagePart>(m_part.lock()); +void IMAPMessagePartContentHandler::generate( + utility::outputStream& os, + const vmime::encoding& enc, + const size_t maxLineLength +) const { + + shared_ptr <IMAPMessage> msg = m_message.lock(); + shared_ptr <messagePart> part = m_part.lock(); // Data is already encoded - if (isEncoded()) - { + if (isEncoded()) { + // The data is already encoded but the encoding specified for // the generation is different from the current one. We need // to re-encode data: decode from input buffer to temporary // buffer, and then re-encode to output stream... - if (m_encoding != enc) - { + if (m_encoding != enc) { + // Extract part contents to temporary buffer std::ostringstream oss; utility::outputStreamAdapter tmp(oss); @@ -97,16 +104,16 @@ void IMAPMessagePartContentHandler::generate theEncoder->getProperties()["text"] = (m_contentType.getType() == mediaTypes::TEXT); theEncoder->encode(tempIn, os); - } + // No encoding to perform - else - { + } else { + msg->extractPart(part, os); } - } + // Need to encode data before - else - { + } else { + // Extract part contents to temporary buffer std::ostringstream oss; utility::outputStreamAdapter tmp(oss); @@ -125,20 +132,22 @@ void IMAPMessagePartContentHandler::generate } -void IMAPMessagePartContentHandler::extract - (utility::outputStream& os, utility::progressListener* progress) const -{ - shared_ptr <IMAPMessage> msg = constCast <IMAPMessage>(m_message.lock()); - shared_ptr <messagePart> part = constCast <messagePart>(m_part.lock()); +void IMAPMessagePartContentHandler::extract( + utility::outputStream& os, + utility::progressListener* progress +) const { + + shared_ptr <IMAPMessage> msg = m_message.lock(); + shared_ptr <messagePart> part = m_part.lock(); // No decoding to perform - if (!isEncoded()) - { + if (!isEncoded()) { + msg->extractImpl(part, os, progress, 0, -1, IMAPMessage::EXTRACT_BODY); - } + // Need to decode data - else - { + } else { + // Extract part contents to temporary buffer std::ostringstream oss; utility::outputStreamAdapter tmp(oss); @@ -155,54 +164,56 @@ void IMAPMessagePartContentHandler::extract } -void IMAPMessagePartContentHandler::extractRaw - (utility::outputStream& os, utility::progressListener* progress) const -{ - shared_ptr <IMAPMessage> msg = constCast <IMAPMessage>(m_message.lock()); - shared_ptr <messagePart> part = constCast <messagePart>(m_part.lock()); +void IMAPMessagePartContentHandler::extractRaw( + utility::outputStream& os, + utility::progressListener* progress +) const { + + shared_ptr <IMAPMessage> msg = m_message.lock(); + shared_ptr <messagePart> part = m_part.lock(); msg->extractPart(part, os, progress); } -size_t IMAPMessagePartContentHandler::getLength() const -{ +size_t IMAPMessagePartContentHandler::getLength() const { + return m_part.lock()->getSize(); } -bool IMAPMessagePartContentHandler::isEncoded() const -{ +bool IMAPMessagePartContentHandler::isEncoded() const { + return m_encoding != NO_ENCODING; } -const vmime::encoding& IMAPMessagePartContentHandler::getEncoding() const -{ +const vmime::encoding& IMAPMessagePartContentHandler::getEncoding() const { + return m_encoding; } -bool IMAPMessagePartContentHandler::isEmpty() const -{ +bool IMAPMessagePartContentHandler::isEmpty() const { + return getLength() == 0; } -bool IMAPMessagePartContentHandler::isBuffered() const -{ +bool IMAPMessagePartContentHandler::isBuffered() const { + return true; } -void IMAPMessagePartContentHandler::setContentTypeHint(const mediaType& type) -{ +void IMAPMessagePartContentHandler::setContentTypeHint(const mediaType& type) { + m_contentType = type; } -const mediaType IMAPMessagePartContentHandler::getContentTypeHint() const -{ +const mediaType IMAPMessagePartContentHandler::getContentTypeHint() const { + return m_contentType; } diff --git a/src/vmime/net/imap/IMAPMessagePartContentHandler.hpp b/src/vmime/net/imap/IMAPMessagePartContentHandler.hpp index cb52b2e3..17f53e34 100644 --- a/src/vmime/net/imap/IMAPMessagePartContentHandler.hpp +++ b/src/vmime/net/imap/IMAPMessagePartContentHandler.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard <[email protected]> +// Copyright (C) 2002 Vincent Richard <[email protected]> // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License as @@ -40,15 +40,23 @@ namespace net { namespace imap { -class VMIME_EXPORT IMAPMessagePartContentHandler : public contentHandler -{ +class VMIME_EXPORT IMAPMessagePartContentHandler : public contentHandler { + public: - IMAPMessagePartContentHandler(shared_ptr <IMAPMessage> msg, shared_ptr <messagePart> part, const vmime::encoding& encoding); + IMAPMessagePartContentHandler( + const shared_ptr <IMAPMessage>& msg, + const shared_ptr <messagePart>& part, + const vmime::encoding& encoding + ); shared_ptr <contentHandler> clone() const; - void generate(utility::outputStream& os, const vmime::encoding& enc, const size_t maxLineLength = lineLengthLimits::infinite) const; + void generate( + utility::outputStream& os, + const vmime::encoding& enc, + const size_t maxLineLength = lineLengthLimits::infinite + ) const; void extract(utility::outputStream& os, utility::progressListener* progress = NULL) const; void extractRaw(utility::outputStream& os, utility::progressListener* progress = NULL) const; diff --git a/src/vmime/net/imap/IMAPMessageStructure.cpp b/src/vmime/net/imap/IMAPMessageStructure.cpp index 689c495d..0bc7e909 100644 --- a/src/vmime/net/imap/IMAPMessageStructure.cpp +++ b/src/vmime/net/imap/IMAPMessageStructure.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard <[email protected]> +// Copyright (C) 2002 Vincent Richard <[email protected]> // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License as @@ -36,50 +36,52 @@ namespace net { namespace imap { -IMAPMessageStructure::IMAPMessageStructure() -{ +IMAPMessageStructure::IMAPMessageStructure() { } -IMAPMessageStructure::IMAPMessageStructure(const IMAPParser::body* body) -{ +IMAPMessageStructure::IMAPMessageStructure(const IMAPParser::body* body) { + m_parts.push_back(IMAPMessagePart::create(null, 0, body)); } -IMAPMessageStructure::IMAPMessageStructure(shared_ptr <IMAPMessagePart> parent, const std::vector <IMAPParser::body*>& list) -{ +IMAPMessageStructure::IMAPMessageStructure( + const shared_ptr <IMAPMessagePart>& parent, + const std::vector <IMAPParser::body*>& list +) { + size_t number = 0; for (std::vector <IMAPParser::body*>::const_iterator - it = list.begin() ; it != list.end() ; ++it, ++number) - { + it = list.begin() ; it != list.end() ; ++it, ++number) { + m_parts.push_back(IMAPMessagePart::create(parent, number, *it)); } } -shared_ptr <const messagePart> IMAPMessageStructure::getPartAt(const size_t x) const -{ +shared_ptr <const messagePart> IMAPMessageStructure::getPartAt(const size_t x) const { + return m_parts[x]; } -shared_ptr <messagePart> IMAPMessageStructure::getPartAt(const size_t x) -{ +shared_ptr <messagePart> IMAPMessageStructure::getPartAt(const size_t x) { + return m_parts[x]; } -size_t IMAPMessageStructure::getPartCount() const -{ +size_t IMAPMessageStructure::getPartCount() const { + return m_parts.size(); } // static -shared_ptr <IMAPMessageStructure> IMAPMessageStructure::emptyStructure() -{ +shared_ptr <IMAPMessageStructure> IMAPMessageStructure::emptyStructure() { + static shared_ptr <IMAPMessageStructure> emptyStructure = make_shared <IMAPMessageStructure>(); return emptyStructure; } diff --git a/src/vmime/net/imap/IMAPMessageStructure.hpp b/src/vmime/net/imap/IMAPMessageStructure.hpp index 44b6d6f0..5eafb04f 100644 --- a/src/vmime/net/imap/IMAPMessageStructure.hpp +++ b/src/vmime/net/imap/IMAPMessageStructure.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard <[email protected]> +// Copyright (C) 2002 Vincent Richard <[email protected]> // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License as @@ -44,13 +44,13 @@ namespace imap { class IMAPMessagePart; -class VMIME_EXPORT IMAPMessageStructure : public messageStructure -{ +class VMIME_EXPORT IMAPMessageStructure : public messageStructure { + public: IMAPMessageStructure(); IMAPMessageStructure(const IMAPParser::body* body); - IMAPMessageStructure(shared_ptr <IMAPMessagePart> parent, const std::vector <IMAPParser::body*>& list); + IMAPMessageStructure(const shared_ptr <IMAPMessagePart>& parent, const std::vector <IMAPParser::body*>& list); shared_ptr <const messagePart> getPartAt(const size_t x) const; shared_ptr <messagePart> getPartAt(const size_t x); diff --git a/src/vmime/net/imap/IMAPParser.hpp b/src/vmime/net/imap/IMAPParser.hpp index 8b24c9ca..74b5145f 100644 --- a/src/vmime/net/imap/IMAPParser.hpp +++ b/src/vmime/net/imap/IMAPParser.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard <[email protected]> +// Copyright (C) 2002 Vincent Richard <[email protected]> // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License as @@ -193,25 +193,34 @@ namespace imap { static int IMAPParserDebugResponse_level = 0; static std::vector <string> IMAPParserDebugResponse_stack; - class IMAPParserDebugResponse - { + class IMAPParserDebugResponse { + public: - IMAPParserDebugResponse(const string& name, string& line, const size_t currentPos, const bool &result) - : m_name(name), m_line(line), m_pos(currentPos), m_result(result) - { + IMAPParserDebugResponse( + const string& name, + string& line, + const size_t currentPos, + const bool &result + ) + : m_name(name), + m_line(line), + m_pos(currentPos), + m_result(result) { + ++IMAPParserDebugResponse_level; IMAPParserDebugResponse_stack.push_back(name); - for (int i = 0 ; i < IMAPParserDebugResponse_level ; ++i) + for (int i = 0 ; i < IMAPParserDebugResponse_level ; ++i) { std::cout << " "; + } std::cout << "ENTER(" << m_name << "), pos=" << m_pos; std::cout << std::endl; for (std::vector <string>::iterator it = IMAPParserDebugResponse_stack.begin() ; - it != IMAPParserDebugResponse_stack.end() ; ++it) - { + it != IMAPParserDebugResponse_stack.end() ; ++it) { + std::cout << "> " << *it << " "; } @@ -219,16 +228,18 @@ namespace imap { std::cout << string(m_line.begin() + (m_pos < 30 ? 0U : m_pos - 30), m_line.begin() + std::min(m_line.length(), m_pos + 30)) << std::endl; - for (size_t i = (m_pos < 30 ? m_pos : (m_pos - (m_pos - 30))) ; i != 0 ; --i) + for (size_t i = (m_pos < 30 ? m_pos : (m_pos - (m_pos - 30))) ; i != 0 ; --i) { std::cout << " "; + } std::cout << "^" << std::endl; } - ~IMAPParserDebugResponse() - { - for (int i = 0 ; i < IMAPParserDebugResponse_level ; ++i) + ~IMAPParserDebugResponse() { + + for (int i = 0 ; i < IMAPParserDebugResponse_level ; ++i) { std::cout << " "; + } std::cout << "LEAVE(" << m_name << "), result="; std::cout << (m_result ? "TRUE" : "FALSE") << ", pos=" << m_pos; @@ -258,14 +269,18 @@ namespace imap { #endif -class VMIME_EXPORT IMAPParser : public object -{ +class VMIME_EXPORT IMAPParser : public object { + public: IMAPParser() - : m_tag(), m_socket(), m_progress(NULL), m_strict(false), - m_literalHandler(NULL), m_timeoutHandler() - { + : m_tag(), + m_socket(), + m_progress(NULL), + m_strict(false), + m_literalHandler(NULL), + m_timeoutHandler() { + } @@ -273,8 +288,8 @@ public: * * @param tag IMAP command tag */ - void setTag(shared_ptr <IMAPTag> tag) - { + void setTag(const shared_ptr <IMAPTag>& tag) { + m_tag = tag; } @@ -282,8 +297,8 @@ public: * * @return IMAP command tag */ - shared_ptr <const IMAPTag> getTag() const - { + shared_ptr <const IMAPTag> getTag() const { + return m_tag.lock(); } @@ -292,8 +307,8 @@ public: * * @param sok socket */ - void setSocket(shared_ptr <socket> sok) - { + void setSocket(const shared_ptr <socket>& sok) { + m_socket = sok; } @@ -301,8 +316,8 @@ public: * * @param toh timeout handler */ - void setTimeoutHandler(shared_ptr <timeoutHandler> toh) - { + void setTimeoutHandler(const shared_ptr <timeoutHandler>& toh) { + m_timeoutHandler = toh; } @@ -310,8 +325,8 @@ public: * * @param tr tracer */ - void setTracer(shared_ptr <tracer> tr) - { + void setTracer(const shared_ptr <tracer>& tr) { + m_tracer = tr; } @@ -321,8 +336,8 @@ public: * @param strict true to operate in strict mode, or false * to operate in default, relaxed mode */ - void setStrict(const bool strict) - { + void setStrict(const bool strict) { + m_strict = strict; } @@ -331,8 +346,8 @@ public: * * @return true if we are in strict mode, false otherwise */ - bool isStrict() const - { + bool isStrict() const { + return m_strict; } @@ -344,16 +359,16 @@ public: class component; - class literalHandler - { + class literalHandler { + public: virtual ~literalHandler() { } // Abstract target class - class target - { + class target { + protected: target(utility::progressListener* progress) : m_progress(progress) {} @@ -377,8 +392,8 @@ public: // Target: put in a string - class targetString : public target - { + class targetString : public target { + public: targetString(utility::progressListener* progress, vmime::string& str) @@ -388,14 +403,14 @@ public: vmime::string& string() { return (m_string); } - void putData(const vmime::string& chunk) - { + void putData(const vmime::string& chunk) { + m_string += chunk; m_bytesWritten += chunk.length(); } - size_t getBytesWritten() const - { + size_t getBytesWritten() const { + return m_bytesWritten; } @@ -407,25 +422,32 @@ public: // Target: redirect to an output stream - class targetStream : public target - { + class targetStream : public target { + public: - targetStream(utility::progressListener* progress, utility::outputStream& stream) - : target(progress), m_stream(stream), m_bytesWritten(0) { } + targetStream( + utility::progressListener* progress, + utility::outputStream& stream + ) + : target(progress), + m_stream(stream), + m_bytesWritten(0) { + + } const utility::outputStream& stream() const { return (m_stream); } utility::outputStream& stream() { return (m_stream); } - void putData(const string& chunk) - { + void putData(const string& chunk) { + m_stream.write(chunk.data(), chunk.length()); m_bytesWritten += chunk.length(); } - size_t getBytesWritten() const - { + size_t getBytesWritten() const { + return m_bytesWritten; } @@ -452,8 +474,8 @@ public: // Base class for a terminal or a non-terminal // - class component - { + class component { + public: component() { } @@ -461,8 +483,8 @@ public: virtual const string getComponentName() const = 0; - bool parse(IMAPParser& parser, string& line, size_t* currentPos) - { + bool parse(IMAPParser& parser, string& line, size_t* currentPos) { + bool res = false; DEBUG_ENTER_COMPONENT(getComponentName(), res); res = parseImpl(parser, line, currentPos); @@ -472,12 +494,16 @@ public: virtual bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) = 0; - const string makeResponseLine(const string& comp, const string& line, - const size_t pos) - { + const string makeResponseLine( + const string& comp, + const string& line, + const size_t pos + ) { + #if DEBUG_RESPONSE - if (pos > line.length()) + if (pos > line.length()) { std::cout << "WARNING: component::makeResponseLine(): pos > line.length()" << std::endl; + } #endif string result(line.substr(0, pos)); @@ -491,19 +517,16 @@ public: #define COMPONENT_ALIAS(parent, name) \ - class name : public parent \ - { \ + class name : public parent { \ virtual const string getComponentName() const { return #name; } \ public: \ - bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) \ - { \ + bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) { \ return parent::parseImpl(parser, line, currentPos); \ } \ } #define DECLARE_COMPONENT(name) \ - class name : public component \ - { \ + class name : public component { \ virtual const string getComponentName() const { return #name; } \ public: @@ -513,26 +536,23 @@ public: // template <char C> - class one_char : public component - { + class one_char : public component { + public: - const string getComponentName() const - { + const string getComponentName() const { + return string("one_char <") + C + ">"; } - bool parseImpl(IMAPParser& /* parser */, string& line, size_t* currentPos) - { + bool parseImpl(IMAPParser& /* parser */, string& line, size_t* currentPos) { + const size_t pos = *currentPos; - if (pos < line.length() && line[pos] == C) - { + if (pos < line.length() && line[pos] == C) { *currentPos = pos + 1; return true; - } - else - { + } else { return false; } } @@ -545,20 +565,18 @@ public: DECLARE_COMPONENT(SPACE) - bool parseImpl(IMAPParser& /* parser */, string& line, size_t* currentPos) - { + bool parseImpl(IMAPParser& /* parser */, string& line, size_t* currentPos) { + size_t pos = *currentPos; - while (pos < line.length() && (line[pos] == ' ' || line[pos] == '\t')) + while (pos < line.length() && (line[pos] == ' ' || line[pos] == '\t')) { ++pos; + } - if (pos > *currentPos) - { + if (pos > *currentPos) { *currentPos = pos; return true; - } - else - { + } else { return false; } } @@ -573,20 +591,20 @@ public: DECLARE_COMPONENT(CRLF) - bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) - { + bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) { + size_t pos = *currentPos; VIMAP_PARSER_TRY_CHECK(SPACE); if (pos + 1 < line.length() && - line[pos] == 0x0d && line[pos + 1] == 0x0a) - { + line[pos] == 0x0d && line[pos + 1] == 0x0a) { + *currentPos = pos + 2; return true; - } - else - { + + } else { + return false; } } @@ -607,8 +625,8 @@ public: DECLARE_COMPONENT(xtag) - bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) - { + bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) { + size_t pos = *currentPos; bool end = false; @@ -616,46 +634,42 @@ public: string tagString; tagString.reserve(10); - while (!end && pos < line.length()) - { + while (!end && pos < line.length()) { + const unsigned char c = line[pos]; - switch (c) - { - case '+': - case '(': - case ')': - case '{': - case 0x20: // SPACE - case '%': // list_wildcards - case '*': // list_wildcards - case '"': // quoted_specials - case '\\': // quoted_specials - - end = true; - break; + switch (c) { - default: + case '+': + case '(': + case ')': + case '{': + case 0x20: // SPACE + case '%': // list_wildcards + case '*': // list_wildcards + case '"': // quoted_specials + case '\\': // quoted_specials - if (c <= 0x1f || c >= 0x7f) end = true; - else - { - tagString += c; - ++pos; - } + break; - break; + default: + + if (c <= 0x1f || c >= 0x7f) { + end = true; + } else { + tagString += c; + ++pos; + } + + break; } } - if (tagString == string(*parser.getTag())) - { + if (tagString == string(*parser.getTag())) { *currentPos = pos; return true; - } - else - { + } else { // Invalid tag return false; } @@ -675,41 +689,36 @@ public: DECLARE_COMPONENT(number) number(const bool nonZero = false) - : m_nonZero(nonZero), m_value(0) - { + : m_nonZero(nonZero), + m_value(0) { + } - bool parseImpl(IMAPParser& /* parser */, string& line, size_t* currentPos) - { + bool parseImpl(IMAPParser& /* parser */, string& line, size_t* currentPos) { + size_t pos = *currentPos; bool valid = true; unsigned int val = 0; - while (valid && pos < line.length()) - { + while (valid && pos < line.length()) { + const char c = line[pos]; - if (c >= '0' && c <= '9') - { + if (c >= '0' && c <= '9') { val = (val * 10) + (c - '0'); ++pos; - } - else - { + } else { valid = false; } } // Check for non-null length (and for non-zero number) - if (!(m_nonZero && val == 0) && pos != *currentPos) - { + if (!(m_nonZero && val == 0) && pos != *currentPos) { m_value = val; *currentPos = pos; return true; - } - else - { + } else { return false; } } @@ -730,12 +739,13 @@ public: // ;; (0 < n < 4,294,967,296) // - class nz_number : public number - { + class nz_number : public number { + public: - nz_number() : number(true) - { + nz_number() + : number(true) { + } }; @@ -745,12 +755,13 @@ public: // ;; Strictly ascending // - class uniqueid : public nz_number - { + class uniqueid : public nz_number { + public: - uniqueid() : nz_number() - { + uniqueid() + : nz_number() { + } }; @@ -763,18 +774,19 @@ public: DECLARE_COMPONENT(uid_range) uid_range() - : m_uniqueid1(NULL), m_uniqueid2(NULL) - { + : m_uniqueid1(NULL), + m_uniqueid2(NULL) { + } - ~uid_range() - { + ~uid_range() { + delete m_uniqueid1; delete m_uniqueid2; } - bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) - { + bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) { + size_t pos = *currentPos; VIMAP_PARSER_GET(uniqueid, m_uniqueid1); @@ -805,28 +817,32 @@ public: DECLARE_COMPONENT(uid_set) uid_set() - : m_uniqueid(NULL), m_uid_range(NULL), m_next_uid_set(NULL) - { + : m_uniqueid(NULL), + m_uid_range(NULL), + m_next_uid_set(NULL) { + } - ~uid_set() - { + ~uid_set() { + delete m_uniqueid; delete m_uid_range; delete m_next_uid_set; } - bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) - { + bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) { + size_t pos = *currentPos; // We have either a 'uid_range' or a 'uniqueid' - if (!VIMAP_PARSER_TRY_GET(IMAPParser::uid_range, m_uid_range)) + if (!VIMAP_PARSER_TRY_GET(IMAPParser::uid_range, m_uid_range)) { VIMAP_PARSER_GET(IMAPParser::uniqueid, m_uniqueid); + } // And maybe another 'uid-set' following - if (VIMAP_PARSER_TRY_CHECK(one_char <','>)) + if (VIMAP_PARSER_TRY_CHECK(one_char <','>)) { VIMAP_PARSER_GET(IMAPParser::uid_set, m_next_uid_set); + } *currentPos = pos; @@ -859,56 +875,50 @@ public: DECLARE_COMPONENT(text) text(bool allow8bits = false, const char except = 0) - : m_allow8bits(allow8bits), m_except(except) - { + : m_allow8bits(allow8bits), m_except(except) { } - bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) - { + bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) { + size_t pos = *currentPos; size_t len = 0; - if (m_allow8bits || !parser.isStrict()) - { + if (m_allow8bits || !parser.isStrict()) { + const unsigned char except = m_except; - for (bool end = false ; !end && pos < line.length() ; ) - { + for (bool end = false ; !end && pos < line.length() ; ) { + const unsigned char c = line[pos]; - if (c == 0x00 || c == 0x0d || c == 0x0a || c == except) - { + if (c == 0x00 || c == 0x0d || c == 0x0a || c == except) { end = true; - } - else - { + } else { ++pos; ++len; } } - } - else - { + + } else { + const unsigned char except = m_except; - for (bool end = false ; !end && pos < line.length() ; ) - { + for (bool end = false ; !end && pos < line.length() ; ) { + const unsigned char c = line[pos]; - if (c < 0x01 || c > 0x7f || c == 0x0d || c == 0x0a || c == except) - { + if (c < 0x01 || c > 0x7f || c == 0x0d || c == 0x0a || c == except) { end = true; - } - else - { + } else { ++pos; ++len; } } } - if (len == 0) + if (len == 0) { VIMAP_PARSER_FAIL(); + } m_value.resize(len); std::copy(line.begin() + *currentPos, line.begin() + pos, m_value.begin()); @@ -930,34 +940,34 @@ public: }; - class text8 : public text - { + class text8 : public text { + public: - text8() : text(true) - { + text8() : text(true) { + } }; template <char C> - class text_except : public text - { + class text_except : public text { + public: - text_except() : text(false, C) - { + text_except() : text(false, C) { + } }; template <char C> - class text8_except : public text - { + class text8_except : public text { + public: - text8_except() : text(true, C) - { + text8_except() : text(true, C) { + } }; @@ -971,27 +981,27 @@ public: DECLARE_COMPONENT(QUOTED_CHAR) - bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) - { + bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) { + size_t pos = *currentPos; const unsigned char c = static_cast <unsigned char>(pos < line.length() ? line[pos] : 0); if (c >= 0x01 && c <= 0x7f && // 0x01 - 0x7f c != '"' && c != '\\' && // quoted_specials - c != '\r' && c != '\n') // CR and LF - { + c != '\r' && c != '\n') { // CR and LF + m_value = c; *currentPos = pos + 1; - } - else if (c == '\\' && pos + 1 < line.length() && - (line[pos + 1] == '"' || line[pos + 1] == '\\')) - { + + } else if (c == '\\' && pos + 1 < line.length() && + (line[pos + 1] == '"' || line[pos + 1] == '\\')) { + m_value = line[pos + 1]; *currentPos = pos + 2; - } - else - { + + } else { + VIMAP_PARSER_FAIL(); } @@ -1018,24 +1028,23 @@ public: DECLARE_COMPONENT(quoted_text) - bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) - { + bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) { + size_t pos = *currentPos; size_t len = 0; bool valid = false; m_value.reserve(line.length() - pos); - for (bool end = false, quoted = false ; !end && pos < line.length() ; ) - { + for (bool end = false, quoted = false ; !end && pos < line.length() ; ) { + const unsigned char c = line[pos]; - if (quoted) - { - if (c == '"' || c == '\\') + if (quoted) { + + if (c == '"' || c == '\\') { m_value += c; - else - { + } else { m_value += '\\'; m_value += c; } @@ -1044,39 +1053,40 @@ public: ++pos; ++len; - } - else - { - if (c == '\\') - { + + } else { + + if (c == '\\') { + quoted = true; ++pos; ++len; - } - else if (c == '"') - { + + } else if (c == '"') { + valid = true; end = true; - } - else if (c >= 0x01 && c <= 0x7f && // CHAR - c != 0x0a && c != 0x0d) // CR and LF - { + + } else if (c >= 0x01 && c <= 0x7f && // CHAR + c != 0x0a && c != 0x0d) { // CR and LF + m_value += c; ++pos; ++len; - } - else - { + + } else { + valid = false; end = true; } } } - if (!valid) + if (!valid) { VIMAP_PARSER_FAIL(); + } *currentPos = pos; @@ -1099,8 +1109,8 @@ public: DECLARE_COMPONENT(NIL) - bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) - { + bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) { + size_t pos = *currentPos; VIMAP_PARSER_CHECK_WITHARG(special_atom, "nil"); @@ -1128,74 +1138,79 @@ public: DECLARE_COMPONENT(xstring) - xstring(const bool canBeNIL = false, component* comp = NULL, const int data = 0) - : m_canBeNIL(canBeNIL), m_isNIL(true), m_component(comp), m_data(data) - { + xstring( + const bool canBeNIL = false, + component* comp = NULL, + const int data = 0 + ) + : m_canBeNIL(canBeNIL), + m_isNIL(true), + m_component(comp), + m_data(data) { + } - bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) - { + bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) { + size_t pos = *currentPos; if (m_canBeNIL && - VIMAP_PARSER_TRY_CHECK_WITHARG(special_atom, "nil")) - { + VIMAP_PARSER_TRY_CHECK_WITHARG(special_atom, "nil")) { + // NIL m_isNIL = true; - } - else - { + + } else { + pos = *currentPos; m_isNIL = false; // quoted ::= <"> *QUOTED_CHAR <"> - if (VIMAP_PARSER_TRY_CHECK(one_char <'"'>)) - { + if (VIMAP_PARSER_TRY_CHECK(one_char <'"'>)) { + shared_ptr <quoted_text> text; VIMAP_PARSER_GET_PTR(quoted_text, text); VIMAP_PARSER_CHECK(one_char <'"'>); - if (parser.m_literalHandler != NULL) - { + if (parser.m_literalHandler != NULL) { + shared_ptr <literalHandler::target> target = parser.m_literalHandler->targetFor(*m_component, m_data); - if (target != NULL) - { + if (target != NULL) { + m_value = "[literal-handler]"; const size_t length = text->value().length(); utility::progressListener* progress = target->progressListener(); - if (progress) - { + if (progress) { progress->start(length); } target->putData(text->value()); - if (progress) - { + if (progress) { progress->progress(length, length); progress->stop(length); } - } - else - { + + } else { + m_value = text->value(); } - } - else - { + + } else { + m_value = text->value(); } DEBUG_FOUND("string[quoted]", "<length=" << m_value.length() << ", value='" << m_value << "'>"); - } + // literal ::= "{" number "}" CRLF *CHAR8 - else - { + } else { + VIMAP_PARSER_CHECK(one_char <'{'>); shared_ptr <number> num; @@ -1208,27 +1223,27 @@ public: VIMAP_PARSER_CHECK(CRLF); - if (parser.m_literalHandler != NULL) - { + if (parser.m_literalHandler != NULL) { + shared_ptr <literalHandler::target> target = parser.m_literalHandler->targetFor(*m_component, m_data); - if (target != NULL) - { + if (target != NULL) { + m_value = "[literal-handler]"; parser.m_progress = target->progressListener(); parser.readLiteral(*target, length); parser.m_progress = NULL; - } - else - { + + } else { + literalHandler::targetString target(NULL, m_value); parser.readLiteral(target, length); } - } - else - { + + } else { + literalHandler::targetString target(NULL, m_value); parser.readLiteral(target, length); } @@ -1266,18 +1281,18 @@ public: // nstring ::= string / nil // - class nstring : public xstring - { + class nstring : public xstring { + public: - const string getComponentName() const - { + const string getComponentName() const { + return "nstring"; } nstring(component* comp = NULL, const int data = 0) - : xstring(true, comp, data) - { + : xstring(true, comp, data) { + } }; @@ -1288,19 +1303,16 @@ public: DECLARE_COMPONENT(astring) - bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) - { + bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) { + size_t pos = *currentPos; shared_ptr <xstring> str; VIMAP_PARSER_TRY_GET_PTR(xstring, str); - if (str) - { + if (str) { m_value = str->value(); - } - else - { + } else { shared_ptr <atom> at; VIMAP_PARSER_GET_PTR(atom, at); m_value = at->value(); @@ -1335,53 +1347,52 @@ public: DECLARE_COMPONENT(atom) - bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) - { + bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) { + size_t pos = *currentPos; size_t len = 0; - for (bool end = false ; !end && pos < line.length() ; ) - { + for (bool end = false ; !end && pos < line.length() ; ) { + const unsigned char c = line[pos]; - switch (c) - { - case '(': - case ')': - case '{': - case 0x20: // SPACE - case '%': // list_wildcards - case '*': // list_wildcards - case '"': // quoted_specials - case '\\': // quoted_specials - - case '[': - case ']': // for "special_atom" - - end = true; - break; + switch (c) { - default: + case '(': + case ')': + case '{': + case 0x20: // SPACE + case '%': // list_wildcards + case '*': // list_wildcards + case '"': // quoted_specials + case '\\': // quoted_specials + + case '[': + case ']': // for "special_atom" - if (c <= 0x1f || c >= 0x7f) end = true; - else - { - ++pos; - ++len; + break; + + default: + + if (c <= 0x1f || c >= 0x7f) { + end = true; + } else { + ++pos; + ++len; + } } - } } - if (len != 0) - { + if (len != 0) { + m_value.resize(len); std::copy(line.begin() + *currentPos, line.begin() + pos, m_value.begin()); *currentPos = pos; - } - else - { + + } else { + VIMAP_PARSER_FAIL(); } @@ -1407,42 +1418,44 @@ public: // accept these strings in a case-insensitive fashion. " // - class special_atom : public atom - { + class special_atom : public atom { + public: - const std::string getComponentName() const - { + const std::string getComponentName() const { + return string("special_atom <") + m_string + ">"; } special_atom(const char* str) - : m_string(str) // 'string' must be in lower-case - { + : m_string(str) { // 'string' must be in lower-case + } - bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) - { + bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) { + size_t pos = *currentPos; - if (!atom::parseImpl(parser, line, &pos)) + if (!atom::parseImpl(parser, line, &pos)) { return false; + } const char* cmp = value().c_str(); const char* with = m_string; bool ok = true; - while (ok && *cmp && *with) - { + while (ok && *cmp && *with) { + ok = (std::tolower(*cmp, std::locale()) == *with); ++cmp; ++with; } - if (!ok || *cmp || *with) + if (!ok || *cmp || *with) { VIMAP_PARSER_FAIL(); + } *currentPos = pos; @@ -1462,8 +1475,8 @@ public: DECLARE_COMPONENT(text_mime2) - bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) - { + bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) { + size_t pos = *currentPos; shared_ptr <atom> theCharset, theEncoding; @@ -1490,28 +1503,28 @@ public: // Decode text scoped_ptr <utility::encoder::encoder> theEncoder; - if (theEncoding->value()[0] == 'q' || theEncoding->value()[0] == 'Q') - { + if (theEncoding->value()[0] == 'q' || theEncoding->value()[0] == 'Q') { + // Quoted-printable theEncoder.reset(new utility::encoder::qpEncoder()); theEncoder->getProperties()["rfc2047"] = true; - } - else if (theEncoding->value()[0] == 'b' || theEncoding->value()[0] == 'B') - { + + } else if (theEncoding->value()[0] == 'b' || theEncoding->value()[0] == 'B') { + // Base64 theEncoder.reset(new utility::encoder::b64Encoder()); } - if (theEncoder.get()) - { + if (theEncoder.get()) { + utility::inputStreamStringAdapter in(theText->value()); utility::outputStreamStringAdapter out(m_value); theEncoder->decode(in, out); - } + // No decoder available - else - { + } else { + m_value = theText->value(); } @@ -1540,26 +1553,27 @@ public: DECLARE_COMPONENT(seq_number) seq_number() - : m_number(NULL), m_star(false) - { + : m_number(NULL), + m_star(false) { + } - ~seq_number() - { + ~seq_number() { + delete m_number; } - bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) - { + bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) { + size_t pos = *currentPos; - if (VIMAP_PARSER_TRY_CHECK(one_char <'*'> )) - { + if (VIMAP_PARSER_TRY_CHECK(one_char <'*'> )) { + m_star = true; m_number = NULL; - } - else - { + + } else { + m_star = false; VIMAP_PARSER_GET(IMAPParser::number, m_number); } @@ -1590,18 +1604,19 @@ public: DECLARE_COMPONENT(seq_range) seq_range() - : m_first(NULL), m_last(NULL) - { + : m_first(NULL), + m_last(NULL) { + } - ~seq_range() - { + ~seq_range() { + delete m_first; delete m_last; } - bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) - { + bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) { + size_t pos = *currentPos; VIMAP_PARSER_GET(seq_number, m_first); @@ -1638,26 +1653,30 @@ public: DECLARE_COMPONENT(sequence_set) sequence_set() - : m_number(NULL), m_range(NULL), m_nextSet(NULL) - { + : m_number(NULL), + m_range(NULL), + m_nextSet(NULL) { + } - ~sequence_set() - { + ~sequence_set() { + delete m_number; delete m_range; delete m_nextSet; } - bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) - { + bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) { + size_t pos = *currentPos; - if (!VIMAP_PARSER_TRY_GET(IMAPParser::seq_range, m_range)) + if (!VIMAP_PARSER_TRY_GET(IMAPParser::seq_range, m_range)) { VIMAP_PARSER_GET(IMAPParser::seq_number, m_number); + } - if (VIMAP_PARSER_TRY_CHECK(one_char <','> )) + if (VIMAP_PARSER_TRY_CHECK(one_char <','> )) { VIMAP_PARSER_GET(sequence_set, m_nextSet); + } *currentPos = pos; @@ -1686,28 +1705,25 @@ public: DECLARE_COMPONENT(mod_sequence_value) mod_sequence_value() - : m_value(0) - { + : m_value(0) { + } - bool parseImpl(IMAPParser& /* parser */, string& line, size_t* currentPos) - { + bool parseImpl(IMAPParser& /* parser */, string& line, size_t* currentPos) { + size_t pos = *currentPos; bool valid = true; vmime_uint64 val = 0; - while (valid && pos < line.length()) - { + while (valid && pos < line.length()) { + const char c = line[pos]; - if (c >= '0' && c <= '9') - { + if (c >= '0' && c <= '9') { val = (val * 10) + (c - '0'); ++pos; - } - else - { + } else { valid = false; } } @@ -1747,51 +1763,51 @@ public: DECLARE_COMPONENT(flag) flag() - : m_type(UNKNOWN), m_flag_keyword(NULL) - { + : m_type(UNKNOWN), + m_flag_keyword(NULL) { + } - ~flag() - { - delete (m_flag_keyword); + ~flag() { + + delete m_flag_keyword; } - bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) - { + bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) { + size_t pos = *currentPos; - if (VIMAP_PARSER_TRY_CHECK(one_char <'\\'> )) - { - if (VIMAP_PARSER_TRY_CHECK(one_char <'*'> )) - { + if (VIMAP_PARSER_TRY_CHECK(one_char <'\\'> )) { + + if (VIMAP_PARSER_TRY_CHECK(one_char <'*'> )) { + m_type = STAR; - } - else - { + + } else { + shared_ptr <atom> at; VIMAP_PARSER_GET_PTR(atom, at); const string name = utility::stringUtils::toLower(at->value()); - if (name == "answered") + if (name == "answered") { m_type = ANSWERED; - else if (name == "flagged") + } else if (name == "flagged") { m_type = FLAGGED; - else if (name == "deleted") + } else if (name == "deleted") { m_type = DELETED; - else if (name == "seen") + } else if (name == "seen") { m_type = SEEN; - else if (name == "draft") + } else if (name == "draft") { m_type = DRAFT; - else - { + } else { m_type = UNKNOWN; m_name = name; } } - } - else - { + + } else { + m_type = KEYWORD_OR_EXTENSION; VIMAP_PARSER_GET(atom, m_flag_keyword); } @@ -1802,8 +1818,7 @@ public: } - enum Type - { + enum Type { UNKNOWN, ANSWERED, FLAGGED, @@ -1836,23 +1851,22 @@ public: DECLARE_COMPONENT(flag_list) - ~flag_list() - { + ~flag_list() { + for (std::vector <flag*>::iterator it = m_flags.begin() ; - it != m_flags.end() ; ++it) - { - delete (*it); + it != m_flags.end() ; ++it) { + + delete *it; } } - bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) - { + bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) { + size_t pos = *currentPos; VIMAP_PARSER_CHECK(one_char <'('> ); - while (!VIMAP_PARSER_TRY_CHECK(one_char <')'> )) - { + while (!VIMAP_PARSER_TRY_CHECK(one_char <')'> )) { VIMAP_PARSER_GET_PUSHBACK(flag, m_flags); VIMAP_PARSER_TRY_CHECK(SPACE); } @@ -1882,17 +1896,17 @@ public: DECLARE_COMPONENT(mailbox) - bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) - { + bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) { + size_t pos = *currentPos; - if (VIMAP_PARSER_TRY_CHECK_WITHARG(special_atom, "inbox")) - { + if (VIMAP_PARSER_TRY_CHECK_WITHARG(special_atom, "inbox")) { + m_type = INBOX; m_name = "INBOX"; - } - else - { + + } else { + m_type = OTHER; shared_ptr <astring> astr; @@ -1906,8 +1920,7 @@ public: } - enum Type - { + enum Type { INBOX, OTHER }; @@ -1931,105 +1944,121 @@ public: DECLARE_COMPONENT(mailbox_flag) - bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) - { + bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) { + size_t pos = *currentPos; - if (VIMAP_PARSER_TRY_CHECK(one_char <'\\'> )) - { + if (VIMAP_PARSER_TRY_CHECK(one_char <'\\'> )) { + shared_ptr <atom> at; VIMAP_PARSER_GET_PTR(atom, at); const string name = utility::stringUtils::toLower(at->value()); m_type = UNKNOWN; // default - switch (name[0]) - { - case 'a': + switch (name[0]) { - if (name == "all") - m_type = SPECIALUSE_ALL; - else if (name == "archive") - m_type = SPECIALUSE_ARCHIVE; + case 'a': - break; + if (name == "all") { + m_type = SPECIALUSE_ALL; + } else if (name == "archive") { + m_type = SPECIALUSE_ARCHIVE; + } - case 'd': + break; - if (name == "drafts") - m_type = SPECIALUSE_DRAFTS; + case 'd': - break; + if (name == "drafts") { + m_type = SPECIALUSE_DRAFTS; + } - case 'f': + break; - if (name == "flagged") - m_type = SPECIALUSE_FLAGGED; + case 'f': - break; + if (name == "flagged") { + m_type = SPECIALUSE_FLAGGED; + } - case 'h': + break; - if (name == "haschildren") - m_type = HASCHILDREN; - else if (name == "hasnochildren") - m_type = HASNOCHILDREN; + case 'h': - break; + if (name == "haschildren") { + m_type = HASCHILDREN; + } else if (name == "hasnochildren") { + m_type = HASNOCHILDREN; + } - case 'i': + break; - if (name == "important") - m_type = SPECIALUSE_IMPORTANT; + case 'i': - break; + if (name == "important") { + m_type = SPECIALUSE_IMPORTANT; + } - case 'j': + break; - if (name == "junk") - m_type = SPECIALUSE_JUNK; + case 'j': - break; + if (name == "junk") { + m_type = SPECIALUSE_JUNK; + } - case 'm': + break; - if (name == "marked") - m_type = MARKED; + case 'm': - case 'n': + if (name == "marked") { + m_type = MARKED; + } - if (name == "noinferiors") - m_type = NOINFERIORS; - else if (name == "noselect") - m_type = NOSELECT; + break; - case 's': + case 'n': - if (name == "sent") - m_type = SPECIALUSE_SENT; + if (name == "noinferiors") { + m_type = NOINFERIORS; + } else if (name == "noselect") { + m_type = NOSELECT; + } - break; + break; - case 't': + case 's': - if (name == "trash") - m_type = SPECIALUSE_TRASH; + if (name == "sent") { + m_type = SPECIALUSE_SENT; + } - break; + break; - case 'u': + case 't': - if (name == "unmarked") - m_type = UNMARKED; + if (name == "trash") { + m_type = SPECIALUSE_TRASH; + } - break; + break; + + case 'u': + + if (name == "unmarked") { + m_type = UNMARKED; + } + + break; } - if (m_type == UNKNOWN) + if (m_type == UNKNOWN) { m_name = "\\" + name; - } - else - { + } + + } else { + shared_ptr <atom> at; VIMAP_PARSER_GET_PTR(atom, at); const string name = utility::stringUtils::toLower(at->value()); @@ -2044,8 +2073,7 @@ public: } - enum Type - { + enum Type { // RFC-3348 - Child Mailbox Extension HASCHILDREN, HASNOCHILDREN, @@ -2086,23 +2114,22 @@ public: DECLARE_COMPONENT(mailbox_flag_list) - ~mailbox_flag_list() - { + ~mailbox_flag_list() { + for (std::vector <mailbox_flag*>::iterator it = m_flags.begin() ; - it != m_flags.end() ; ++it) - { - delete (*it); + it != m_flags.end() ; ++it) { + + delete *it; } } - bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) - { + bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) { + size_t pos = *currentPos; VIMAP_PARSER_CHECK(one_char <'('> ); - while (!VIMAP_PARSER_TRY_CHECK(one_char <')'> )) - { + while (!VIMAP_PARSER_TRY_CHECK(one_char <')'> )) { VIMAP_PARSER_GET_PUSHBACK(mailbox_flag, m_flags); VIMAP_PARSER_TRY_CHECK(SPACE); } @@ -2131,26 +2158,26 @@ public: mailbox_list() : m_mailbox_flag_list(NULL), - m_mailbox(NULL), m_quoted_char('\0') - { + m_mailbox(NULL), m_quoted_char('\0') { + } - ~mailbox_list() - { - delete (m_mailbox_flag_list); - delete (m_mailbox); + ~mailbox_list() { + + delete m_mailbox_flag_list; + delete m_mailbox; } - bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) - { + bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) { + size_t pos = *currentPos; VIMAP_PARSER_GET(IMAPParser::mailbox_flag_list, m_mailbox_flag_list); VIMAP_PARSER_CHECK(SPACE); - if (!VIMAP_PARSER_TRY_CHECK(NIL)) - { + if (!VIMAP_PARSER_TRY_CHECK(NIL)) { + VIMAP_PARSER_CHECK(one_char <'"'> ); shared_ptr <QUOTED_CHAR> qc; @@ -2190,29 +2217,29 @@ public: DECLARE_COMPONENT(auth_type) - bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) - { + bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) { + size_t pos = *currentPos; shared_ptr <atom> at; VIMAP_PARSER_GET_PTR(atom, at); m_name = utility::stringUtils::toLower(at->value()); - if (m_name == "kerberos_v4") + if (m_name == "kerberos_v4") { m_type = KERBEROS_V4; - else if (m_name == "gssapi") + } else if (m_name == "gssapi") { m_type = GSSAPI; - else if (m_name == "skey") + } else if (m_name == "skey") { m_type = SKEY; - else + } else { m_type = UNKNOWN; + } return true; } - enum Type - { + enum Type { UNKNOWN, // RFC 1731 - IMAP4 Authentication Mechanisms @@ -2251,47 +2278,38 @@ public: DECLARE_COMPONENT(status_att_val) status_att_val() - : m_value(NULL) - { + : m_value(NULL) { + } - ~status_att_val() - { + ~status_att_val() { + delete m_value; } - bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) - { + bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) { + size_t pos = *currentPos; // "HIGHESTMODSEQ" SP mod-sequence-valzer - if (VIMAP_PARSER_TRY_CHECK_WITHARG(special_atom, "highestmodseq")) - { + if (VIMAP_PARSER_TRY_CHECK_WITHARG(special_atom, "highestmodseq")) { + m_type = HIGHESTMODSEQ; VIMAP_PARSER_CHECK(SPACE); VIMAP_PARSER_GET(IMAPParser::mod_sequence_value, m_value); - } - else - { - if (VIMAP_PARSER_TRY_CHECK_WITHARG(special_atom, "messages")) - { + + } else { + + if (VIMAP_PARSER_TRY_CHECK_WITHARG(special_atom, "messages")) { m_type = MESSAGES; - } - else if (VIMAP_PARSER_TRY_CHECK_WITHARG(special_atom, "recent")) - { + } else if (VIMAP_PARSER_TRY_CHECK_WITHARG(special_atom, "recent")) { m_type = RECENT; - } - else if (VIMAP_PARSER_TRY_CHECK_WITHARG(special_atom, "uidnext")) - { + } else if (VIMAP_PARSER_TRY_CHECK_WITHARG(special_atom, "uidnext")) { m_type = UIDNEXT; - } - else if (VIMAP_PARSER_TRY_CHECK_WITHARG(special_atom, "uidvalidity")) - { + } else if (VIMAP_PARSER_TRY_CHECK_WITHARG(special_atom, "uidvalidity")) { m_type = UIDVALIDITY; - } - else - { + } else { VIMAP_PARSER_CHECK_WITHARG(special_atom, "unseen"); m_type = UNSEEN; } @@ -2306,8 +2324,7 @@ public: } - enum Type - { + enum Type { // Extensions HIGHESTMODSEQ, @@ -2328,13 +2345,11 @@ public: Type type() const { return (m_type); } - const IMAPParser::number* value_as_number() const - { + const IMAPParser::number* value_as_number() const { return dynamic_cast <IMAPParser::number *>(m_value); } - const IMAPParser::mod_sequence_value* value_as_mod_sequence_value() const - { + const IMAPParser::mod_sequence_value* value_as_mod_sequence_value() const { return dynamic_cast <IMAPParser::mod_sequence_value *>(m_value); } }; @@ -2344,23 +2359,24 @@ public: DECLARE_COMPONENT(status_att_list) - ~status_att_list() - { + ~status_att_list() { + for (std::vector <status_att_val*>::iterator it = m_values.begin() ; - it != m_values.end() ; ++it) - { + it != m_values.end() ; ++it) { + delete *it; } } - bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) - { + bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) { + size_t pos = *currentPos; VIMAP_PARSER_GET_PUSHBACK(IMAPParser::status_att_val, m_values); - while (VIMAP_PARSER_TRY_CHECK(SPACE)) + while (VIMAP_PARSER_TRY_CHECK(SPACE)) { VIMAP_PARSER_GET_PUSHBACK(IMAPParser::status_att_val, m_values); + } *currentPos = pos; @@ -2386,18 +2402,19 @@ public: DECLARE_COMPONENT(capability) capability() - : m_auth_type(NULL), m_atom(NULL) - { + : m_auth_type(NULL), + m_atom(NULL) { + } - ~capability() - { - delete (m_auth_type); - delete (m_atom); + ~capability() { + + delete m_auth_type; + delete m_atom; } - bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) - { + bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) { + size_t pos = *currentPos; VIMAP_PARSER_GET(IMAPParser::atom, m_atom); @@ -2409,8 +2426,8 @@ public: (str[1] == 'u' || str[1] == 'U') && (str[2] == 't' || str[2] == 'T') && (str[3] == 'h' || str[3] == 'H') && - (str[4] == '=')) - { + (str[4] == '=')) { + size_t pos = 5; m_auth_type = parser.get <IMAPParser::auth_type>(value, &pos); @@ -2445,36 +2462,34 @@ public: DECLARE_COMPONENT(capability_data) - ~capability_data() - { + ~capability_data() { + for (std::vector <capability*>::iterator it = m_capabilities.begin() ; - it != m_capabilities.end() ; ++it) - { - delete (*it); + it != m_capabilities.end() ; ++it) { + + delete *it; } } - bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) - { + bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) { + size_t pos = *currentPos; VIMAP_PARSER_CHECK_WITHARG(special_atom, "capability"); - while (VIMAP_PARSER_TRY_CHECK(SPACE)) - { + while (VIMAP_PARSER_TRY_CHECK(SPACE)) { + capability* cap; - if (parser.isStrict() || m_capabilities.empty()) - { + if (parser.isStrict() || m_capabilities.empty()) { VIMAP_PARSER_GET(capability, cap); - } - else - { + } else { VIMAP_PARSER_TRY_GET(capability, cap); // allow SPACE at end of line (Apple iCloud IMAP server) } - if (!cap) + if (!cap) { break; + } m_capabilities.push_back(cap); } @@ -2520,8 +2535,8 @@ public: DECLARE_COMPONENT(date_time) - bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) - { + bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) { + size_t pos = *currentPos; // <"> date_day_fixed "-" date_month "-" date_year @@ -2562,8 +2577,9 @@ public: // ("+" / "-") 4digit int sign = 1; - if (!(VIMAP_PARSER_TRY_CHECK(one_char <'+'> ))) + if (!(VIMAP_PARSER_TRY_CHECK(one_char <'+'> ))) { VIMAP_PARSER_CHECK(one_char <'-'> ); + } shared_ptr <number> nz; VIMAP_PARSER_GET_PTR(number, nz); @@ -2587,55 +2603,53 @@ public: const string month(utility::stringUtils::toLower(amo->value())); int mon = vmime::datetime::JANUARY; - if (month.length() >= 3) - { - switch (month[0]) - { - case 'j': - { - switch (month[1]) - { - case 'a': mon = vmime::datetime::JANUARY; break; - case 'u': - { - switch (month[2]) - { - case 'n': mon = vmime::datetime::JUNE; break; - default: mon = vmime::datetime::JULY; break; + if (month.length() >= 3) { + + switch (month[0]) { + + case 'j': { + + switch (month[1]) { + + case 'a': mon = vmime::datetime::JANUARY; break; + case 'u': { + + switch (month[2]) { + + case 'n': mon = vmime::datetime::JUNE; break; + default: mon = vmime::datetime::JULY; break; + } + + break; + } + } break; } + case 'f': mon = vmime::datetime::FEBRUARY; break; + case 'm': { - } + switch (month[2]) { + case 'r': mon = vmime::datetime::MARCH; break; + default: mon = vmime::datetime::MAY; break; + } - break; - } - case 'f': mon = vmime::datetime::FEBRUARY; break; - case 'm': - { - switch (month[2]) - { - case 'r': mon = vmime::datetime::MARCH; break; - default: mon = vmime::datetime::MAY; break; + break; } - - break; - } - case 'a': - { - switch (month[1]) + case 'a': { - case 'p': mon = vmime::datetime::APRIL; break; - default: mon = vmime::datetime::AUGUST; break; - } + switch (month[1]) { + case 'p': mon = vmime::datetime::APRIL; break; + default: mon = vmime::datetime::AUGUST; break; + } - break; - } - case 's': mon = vmime::datetime::SEPTEMBER; break; - case 'o': mon = vmime::datetime::OCTOBER; break; - case 'n': mon = vmime::datetime::NOVEMBER; break; - case 'd': mon = vmime::datetime::DECEMBER; break; + break; + } + case 's': mon = vmime::datetime::SEPTEMBER; break; + case 'o': mon = vmime::datetime::OCTOBER; break; + case 'n': mon = vmime::datetime::NOVEMBER; break; + case 'd': mon = vmime::datetime::DECEMBER; break; } } @@ -2665,23 +2679,22 @@ public: DECLARE_COMPONENT(header_list) - ~header_list() - { + ~header_list() { + for (std::vector <header_fld_name*>::iterator it = m_fld_names.begin() ; - it != m_fld_names.end() ; ++it) - { - delete (*it); + it != m_fld_names.end() ; ++it) { + + delete *it; } } - bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) - { + bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) { + size_t pos = *currentPos; VIMAP_PARSER_CHECK(one_char <'('> ); - while (!VIMAP_PARSER_TRY_CHECK(one_char <')'> )) - { + while (!VIMAP_PARSER_TRY_CHECK(one_char <')'> )) { VIMAP_PARSER_GET_PUSHBACK(header_fld_name, m_fld_names); VIMAP_PARSER_TRY_CHECK(SPACE); } @@ -2714,40 +2727,41 @@ public: DECLARE_COMPONENT(body_extension) body_extension() - : m_nstring(NULL), m_number(NULL) - { + : m_nstring(NULL), + m_number(NULL) { + } - ~body_extension() - { - delete (m_nstring); - delete (m_number); + ~body_extension() { + + delete m_nstring; + delete m_number; for (std::vector <body_extension*>::iterator it = m_body_extensions.begin() ; - it != m_body_extensions.end() ; ++it) - { - delete (*it); + it != m_body_extensions.end() ; ++it) { + + delete *it; } } - bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) - { + bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) { + size_t pos = *currentPos; - if (VIMAP_PARSER_TRY_CHECK(one_char <'('> )) - { + if (VIMAP_PARSER_TRY_CHECK(one_char <'('> )) { + VIMAP_PARSER_GET_PUSHBACK(body_extension, m_body_extensions); - while (!VIMAP_PARSER_TRY_CHECK(one_char <')'> )) - { + while (!VIMAP_PARSER_TRY_CHECK(one_char <')'> )) { VIMAP_PARSER_GET_PUSHBACK(body_extension, m_body_extensions); VIMAP_PARSER_TRY_CHECK(SPACE); } - } - else - { - if (!VIMAP_PARSER_TRY_GET(IMAPParser::nstring, m_nstring)) + + } else { + + if (!VIMAP_PARSER_TRY_GET(IMAPParser::nstring, m_nstring)) { VIMAP_PARSER_GET(IMAPParser::number, m_number); + } } *currentPos = pos; @@ -2779,43 +2793,43 @@ public: DECLARE_COMPONENT(section_text) section_text() - : m_header_list(NULL) - { + : m_header_list(NULL) { + } - ~section_text() - { - delete (m_header_list); + ~section_text() { + + delete m_header_list; } - bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) - { + bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) { + size_t pos = *currentPos; // "HEADER.FIELDS" [".NOT"] SPACE header_list const bool b1 = VIMAP_PARSER_TRY_CHECK_WITHARG(special_atom, "header.fields.not"); const bool b2 = (b1 ? false : VIMAP_PARSER_TRY_CHECK_WITHARG(special_atom, "header.fields")); - if (b1 || b2) - { + if (b1 || b2) { + m_type = b1 ? HEADER_FIELDS_NOT : HEADER_FIELDS; VIMAP_PARSER_CHECK(SPACE); VIMAP_PARSER_GET(IMAPParser::header_list, m_header_list); - } + // "HEADER" - else if (VIMAP_PARSER_TRY_CHECK_WITHARG(special_atom, "header")) - { + } else if (VIMAP_PARSER_TRY_CHECK_WITHARG(special_atom, "header")) { + m_type = HEADER; - } + // "MIME" - else if (VIMAP_PARSER_TRY_CHECK_WITHARG(special_atom, "mime")) - { + } else if (VIMAP_PARSER_TRY_CHECK_WITHARG(special_atom, "mime")) { + m_type = MIME; - } + // "TEXT" - else - { + } else { + m_type = TEXT; VIMAP_PARSER_CHECK_WITHARG(special_atom, "text"); @@ -2827,8 +2841,7 @@ public: } - enum Type - { + enum Type { HEADER, HEADER_FIELDS, HEADER_FIELDS_NOT, @@ -2856,38 +2869,36 @@ public: DECLARE_COMPONENT(section) section() - : m_section_text1(NULL), m_section_text2(NULL) - { + : m_section_text1(NULL), + m_section_text2(NULL) { + } - ~section() - { - delete (m_section_text1); - delete (m_section_text2); + ~section() { + + delete m_section_text1; + delete m_section_text2; } - bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) - { + bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) { + size_t pos = *currentPos; VIMAP_PARSER_CHECK(one_char <'['> ); - if (!VIMAP_PARSER_TRY_CHECK(one_char <']'> )) - { - if (!VIMAP_PARSER_TRY_GET(section_text, m_section_text1)) - { + if (!VIMAP_PARSER_TRY_CHECK(one_char <']'> )) { + + if (!VIMAP_PARSER_TRY_GET(section_text, m_section_text1)) { + shared_ptr <nz_number> num; VIMAP_PARSER_GET_PTR(nz_number, num); m_nz_numbers.push_back(static_cast <unsigned int>(num->value())); - while (VIMAP_PARSER_TRY_CHECK(one_char <'.'> )) - { - if (VIMAP_PARSER_TRY_GET_PTR(nz_number, num)) - { + while (VIMAP_PARSER_TRY_CHECK(one_char <'.'> )) { + + if (VIMAP_PARSER_TRY_GET_PTR(nz_number, num)) { m_nz_numbers.push_back(static_cast <unsigned int>(num->value())); - } - else - { + } else { VIMAP_PARSER_GET(section_text, m_section_text2); break; } @@ -2942,21 +2953,23 @@ public: DECLARE_COMPONENT(address) address() - : m_addr_name(NULL), m_addr_adl(NULL), - m_addr_mailbox(NULL), m_addr_host(NULL) - { + : m_addr_name(NULL), + m_addr_adl(NULL), + m_addr_mailbox(NULL), + m_addr_host(NULL) { + } - ~address() - { - delete (m_addr_name); - delete (m_addr_adl); - delete (m_addr_mailbox); - delete (m_addr_host); + ~address() { + + delete m_addr_name; + delete m_addr_adl; + delete m_addr_mailbox; + delete m_addr_host; } - bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) - { + bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) { + size_t pos = *currentPos; VIMAP_PARSER_CHECK(one_char <'('> ); @@ -2996,25 +3009,24 @@ public: DECLARE_COMPONENT(address_list) - ~address_list() - { + ~address_list() { + for (std::vector <address*>::iterator it = m_addresses.begin() ; - it != m_addresses.end() ; ++it) - { + it != m_addresses.end() ; ++it) { + delete (*it); } } - bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) - { + bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) { + size_t pos = *currentPos; - if (!VIMAP_PARSER_TRY_CHECK(NIL)) - { + if (!VIMAP_PARSER_TRY_CHECK(NIL)) { + VIMAP_PARSER_CHECK(one_char <'('> ); - while (!VIMAP_PARSER_TRY_CHECK(one_char <')'> )) - { + while (!VIMAP_PARSER_TRY_CHECK(one_char <')'> )) { VIMAP_PARSER_GET_PUSHBACK(address, m_addresses); VIMAP_PARSER_TRY_CHECK(SPACE); } @@ -3115,29 +3127,35 @@ public: DECLARE_COMPONENT(envelope) envelope() - : m_env_date(NULL), m_env_subject(NULL), - m_env_from(NULL), m_env_sender(NULL), m_env_reply_to(NULL), - m_env_to(NULL), m_env_cc(NULL), m_env_bcc(NULL), - m_env_in_reply_to(NULL), m_env_message_id(NULL) - { + : m_env_date(NULL), + m_env_subject(NULL), + m_env_from(NULL), + m_env_sender(NULL), + m_env_reply_to(NULL), + m_env_to(NULL), + m_env_cc(NULL), + m_env_bcc(NULL), + m_env_in_reply_to(NULL), + m_env_message_id(NULL) { + } - ~envelope() - { - delete (m_env_date); - delete (m_env_subject); - delete (m_env_from); - delete (m_env_sender); - delete (m_env_reply_to); - delete (m_env_to); - delete (m_env_cc); - delete (m_env_bcc); - delete (m_env_in_reply_to); - delete (m_env_message_id); + ~envelope() { + + delete m_env_date; + delete m_env_subject; + delete m_env_from; + delete m_env_sender; + delete m_env_reply_to; + delete m_env_to; + delete m_env_cc; + delete m_env_bcc; + delete m_env_in_reply_to; + delete m_env_message_id; } - bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) - { + bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) { + size_t pos = *currentPos; VIMAP_PARSER_CHECK(one_char <'('> ); @@ -3246,25 +3264,26 @@ public: // "QUOTED-PRINTABLE") <">) / string // - class body_fld_enc : public nstring - { + class body_fld_enc : public nstring { + public: - const string getComponentName() const - { + const string getComponentName() const { + return "body_fld_enc"; } - body_fld_enc() - { + body_fld_enc() { + } - bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) - { + bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) { + size_t pos = *currentPos; - if (!xstring::parseImpl(parser, line, &pos)) + if (!xstring::parseImpl(parser, line, &pos)) { return false; + } // " When an IMAP4 client sends a FETCH (bodystructure) request // to a server that is running the Exchange Server 2007 IMAP4 @@ -3272,8 +3291,7 @@ public: // (see http://support.microsoft.com/kb/975918/en-us) // // Fail in strict mode - if (isNIL() && parser.isStrict()) - { + if (isNIL() && parser.isStrict()) { VIMAP_PARSER_FAIL(); } @@ -3291,51 +3309,52 @@ public: DECLARE_COMPONENT(body_fld_param_item) body_fld_param_item() - : m_string1(NULL), m_string2(NULL) - { + : m_string1(NULL), + m_string2(NULL) { + } - ~body_fld_param_item() - { - delete (m_string1); - delete (m_string2); + ~body_fld_param_item() { + + delete m_string1; + delete m_string2; } - bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) - { + bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) { + size_t pos = *currentPos; - if (!parser.isStrict()) - { + if (!parser.isStrict()) { + // Some servers send an <atom> instead of a <string> here: // eg. ... (CHARSET "X-UNKNOWN") ... - if (!VIMAP_PARSER_TRY_GET(xstring, m_string1)) - { + if (!VIMAP_PARSER_TRY_GET(xstring, m_string1)) { + shared_ptr <atom> at; VIMAP_PARSER_GET_PTR(atom, at); m_string1 = new xstring(); m_string1->setValue(at->value()); } - } - else - { + + } else { + VIMAP_PARSER_GET(xstring, m_string1); } VIMAP_PARSER_CHECK(SPACE); - if (!parser.isStrict()) - { + if (!parser.isStrict()) { + // In non-strict mode, allow NIL in value shared_ptr <nstring> nstr; VIMAP_PARSER_GET_PTR(nstring, nstr); m_string2 = new xstring(); m_string2->setValue(nstr->value()); - } - else - { + + } else { + VIMAP_PARSER_GET(xstring, m_string2); } @@ -3364,31 +3383,30 @@ public: DECLARE_COMPONENT(body_fld_param) - ~body_fld_param() - { + ~body_fld_param() { + for (std::vector <body_fld_param_item*>::iterator it = m_items.begin() ; - it != m_items.end() ; ++it) - { - delete (*it); + it != m_items.end() ; ++it) { + + delete *it; } } - bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) - { + bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) { + size_t pos = *currentPos; - if (VIMAP_PARSER_TRY_CHECK(one_char <'('> )) - { + if (VIMAP_PARSER_TRY_CHECK(one_char <'('> )) { + VIMAP_PARSER_GET_PUSHBACK(body_fld_param_item, m_items); - while (!VIMAP_PARSER_TRY_CHECK(one_char <')'> )) - { + while (!VIMAP_PARSER_TRY_CHECK(one_char <')'> )) { VIMAP_PARSER_CHECK(SPACE); VIMAP_PARSER_GET_PUSHBACK(body_fld_param_item, m_items); } - } - else - { + + } else { + VIMAP_PARSER_CHECK(NIL); } @@ -3414,29 +3432,30 @@ public: DECLARE_COMPONENT(body_fld_dsp) body_fld_dsp() - : m_string(NULL), m_body_fld_param(NULL) - { + : m_string(NULL), + m_body_fld_param(NULL) { + } - ~body_fld_dsp() - { - delete (m_string); - delete (m_body_fld_param); + ~body_fld_dsp() { + + delete m_string; + delete m_body_fld_param; } - bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) - { + bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) { + size_t pos = *currentPos; - if (VIMAP_PARSER_TRY_CHECK(one_char <'('> )) - { + if (VIMAP_PARSER_TRY_CHECK(one_char <'('> )) { + VIMAP_PARSER_GET(xstring, m_string); VIMAP_PARSER_CHECK(SPACE); VIMAP_PARSER_GET(class body_fld_param, m_body_fld_param); VIMAP_PARSER_CHECK(one_char <')'> ); - } - else - { + + } else { + VIMAP_PARSER_CHECK(NIL); } @@ -3463,31 +3482,30 @@ public: DECLARE_COMPONENT(body_fld_lang) - ~body_fld_lang() - { + ~body_fld_lang() { + for (std::vector <xstring*>::iterator it = m_strings.begin() ; - it != m_strings.end() ; ++it) - { - delete (*it); + it != m_strings.end() ; ++it) { + + delete *it; } } - bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) - { + bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) { + size_t pos = *currentPos; - if (VIMAP_PARSER_TRY_CHECK(one_char <'('> )) - { + if (VIMAP_PARSER_TRY_CHECK(one_char <'('> )) { + VIMAP_PARSER_GET_PUSHBACK(xstring, m_strings); - while (!VIMAP_PARSER_TRY_CHECK(one_char <')'> )) - { + while (!VIMAP_PARSER_TRY_CHECK(one_char <')'> )) { VIMAP_PARSER_CHECK(SPACE); VIMAP_PARSER_GET_PUSHBACK(xstring, m_strings); } - } - else - { + + } else { + VIMAP_PARSER_GET_PUSHBACK(nstring, m_strings); } @@ -3515,22 +3533,25 @@ public: DECLARE_COMPONENT(body_fields) body_fields() - : m_body_fld_param(NULL), m_body_fld_id(NULL), - m_body_fld_desc(NULL), m_body_fld_enc(NULL), m_body_fld_octets(NULL) - { + : m_body_fld_param(NULL), + m_body_fld_id(NULL), + m_body_fld_desc(NULL), + m_body_fld_enc(NULL), + m_body_fld_octets(NULL) { + } - ~body_fields() - { - delete (m_body_fld_param); - delete (m_body_fld_id); - delete (m_body_fld_desc); - delete (m_body_fld_enc); - delete (m_body_fld_octets); + ~body_fields() { + + delete m_body_fld_param; + delete m_body_fld_id; + delete m_body_fld_desc; + delete m_body_fld_enc; + delete m_body_fld_octets; } - bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) - { + bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) { + size_t pos = *currentPos; VIMAP_PARSER_GET(IMAPParser::body_fld_param, m_body_fld_param); @@ -3582,17 +3603,17 @@ public: DECLARE_COMPONENT(media_text) media_text() - : m_media_subtype(NULL) - { + : m_media_subtype(NULL) { + } - ~media_text() - { - delete (m_media_subtype); + ~media_text() { + + delete m_media_subtype; } - bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) - { + bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) { + size_t pos = *currentPos; VIMAP_PARSER_CHECK(one_char <'"'> ); @@ -3625,17 +3646,17 @@ public: DECLARE_COMPONENT(media_message) media_message() - : m_media_subtype(NULL) - { + : m_media_subtype(NULL) { + } - ~media_message() - { + ~media_message() { + delete m_media_subtype; } - bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) - { + bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) { + size_t pos = *currentPos; VIMAP_PARSER_CHECK(one_char <'"'> ); @@ -3673,18 +3694,19 @@ public: DECLARE_COMPONENT(media_basic) media_basic() - : m_media_type(NULL), m_media_subtype(NULL) - { + : m_media_type(NULL), + m_media_subtype(NULL) { + } - ~media_basic() - { - delete (m_media_type); - delete (m_media_subtype); + ~media_basic() { + + delete m_media_type; + delete m_media_subtype; } - bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) - { + bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) { + size_t pos = *currentPos; VIMAP_PARSER_GET(xstring, m_media_type); @@ -3721,20 +3743,22 @@ public: DECLARE_COMPONENT(body_ext_1part) body_ext_1part() - : m_body_fld_md5(NULL), m_body_fld_dsp(NULL), m_body_fld_lang(NULL) - { + : m_body_fld_md5(NULL), + m_body_fld_dsp(NULL), + m_body_fld_lang(NULL) { + } - ~body_ext_1part() - { - delete (m_body_fld_md5); - delete (m_body_fld_dsp); - delete (m_body_fld_lang); + ~body_ext_1part() { + + delete m_body_fld_md5; + delete m_body_fld_dsp; + delete m_body_fld_lang; for (std::vector <body_extension*>::iterator it = m_body_extensions.begin() ; - it != m_body_extensions.end() ; ++it) - { - delete (*it); + it != m_body_extensions.end() ; ++it) { + + delete *it; } } @@ -3745,22 +3769,23 @@ public: VIMAP_PARSER_GET(IMAPParser::body_fld_md5, m_body_fld_md5); // [SPACE body_fld_dsp - if (VIMAP_PARSER_TRY_CHECK(SPACE)) - { + if (VIMAP_PARSER_TRY_CHECK(SPACE)) { + VIMAP_PARSER_GET(IMAPParser::body_fld_dsp, m_body_fld_dsp); // [SPACE body_fld_lang - if (VIMAP_PARSER_TRY_CHECK(SPACE)) - { + if (VIMAP_PARSER_TRY_CHECK(SPACE)) { + VIMAP_PARSER_GET(IMAPParser::body_fld_lang, m_body_fld_lang); // [SPACE 1#body_extension] - if (VIMAP_PARSER_TRY_CHECK(SPACE)) - { + if (VIMAP_PARSER_TRY_CHECK(SPACE)) { + VIMAP_PARSER_GET_PUSHBACK(body_extension, m_body_extensions); - while (VIMAP_PARSER_TRY_CHECK(SPACE)) + while (VIMAP_PARSER_TRY_CHECK(SPACE)) { VIMAP_PARSER_GET_PUSHBACK(body_extension, m_body_extensions); + } } } } @@ -3798,45 +3823,48 @@ public: DECLARE_COMPONENT(body_ext_mpart) body_ext_mpart() - : m_body_fld_param(NULL), m_body_fld_dsp(NULL), m_body_fld_lang(NULL) - { + : m_body_fld_param(NULL), + m_body_fld_dsp(NULL), + m_body_fld_lang(NULL) { + } - ~body_ext_mpart() - { - delete (m_body_fld_param); - delete (m_body_fld_dsp); - delete (m_body_fld_lang); + ~body_ext_mpart() { + + delete m_body_fld_param; + delete m_body_fld_dsp; + delete m_body_fld_lang; for (std::vector <body_extension*>::iterator it = m_body_extensions.begin() ; - it != m_body_extensions.end() ; ++it) - { - delete (*it); + it != m_body_extensions.end() ; ++it) { + + delete *it; } } - bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) - { + bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) { + size_t pos = *currentPos; VIMAP_PARSER_GET(IMAPParser::body_fld_param, m_body_fld_param); // [SPACE body_fld_dsp [SPACE body_fld_lang [SPACE 1#body_extension]]] - if (VIMAP_PARSER_TRY_CHECK(SPACE)) - { + if (VIMAP_PARSER_TRY_CHECK(SPACE)) { + VIMAP_PARSER_GET(IMAPParser::body_fld_dsp, m_body_fld_dsp); - if (VIMAP_PARSER_TRY_CHECK(SPACE)) - { + if (VIMAP_PARSER_TRY_CHECK(SPACE)) { + VIMAP_PARSER_GET(IMAPParser::body_fld_lang, m_body_fld_lang); // [SPACE 1#body_extension] - if (VIMAP_PARSER_TRY_CHECK(SPACE)) - { + if (VIMAP_PARSER_TRY_CHECK(SPACE)) { + VIMAP_PARSER_GET_PUSHBACK(body_extension, m_body_extensions); - while (VIMAP_PARSER_TRY_CHECK(SPACE)) + while (VIMAP_PARSER_TRY_CHECK(SPACE)) { VIMAP_PARSER_GET_PUSHBACK(body_extension, m_body_extensions); + } } } } @@ -3872,18 +3900,19 @@ public: DECLARE_COMPONENT(body_type_basic) body_type_basic() - : m_media_basic(NULL), m_body_fields(NULL) - { + : m_media_basic(NULL), + m_body_fields(NULL) { + } - ~body_type_basic() - { - delete (m_media_basic); - delete (m_body_fields); + ~body_type_basic() { + + delete m_media_basic; + delete m_body_fields; } - bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) - { + bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) { + size_t pos = *currentPos; VIMAP_PARSER_GET(IMAPParser::media_basic, m_media_basic); @@ -3918,22 +3947,25 @@ public: DECLARE_COMPONENT(body_type_msg) body_type_msg() - : m_media_message(NULL), m_body_fields(NULL), - m_envelope(NULL), m_body(NULL), m_body_fld_lines(NULL) - { + : m_media_message(NULL), + m_body_fields(NULL), + m_envelope(NULL), + m_body(NULL), + m_body_fld_lines(NULL) { + } - ~body_type_msg() - { - delete (m_media_message); - delete (m_body_fields); - delete (m_envelope); - delete (m_body); - delete (m_body_fld_lines); + ~body_type_msg() { + + delete m_media_message; + delete m_body_fields; + delete m_envelope; + delete m_body; + delete m_body_fld_lines; } - bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) - { + bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) { + size_t pos = *currentPos; VIMAP_PARSER_GET(IMAPParser::media_message, m_media_message); @@ -3980,19 +4012,20 @@ public: body_type_text() : m_media_text(NULL), - m_body_fields(NULL), m_body_fld_lines(NULL) - { + m_body_fields(NULL), + m_body_fld_lines(NULL) { + } - ~body_type_text() - { - delete (m_media_text); - delete (m_body_fields); - delete (m_body_fld_lines); + ~body_type_text() { + + delete m_media_text; + delete m_body_fields; + delete m_body_fld_lines; } - bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) - { + bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) { + size_t pos = *currentPos; VIMAP_PARSER_GET(IMAPParser::media_text, m_media_text); @@ -4028,32 +4061,35 @@ public: DECLARE_COMPONENT(body_type_1part) body_type_1part() - : m_body_type_basic(NULL), m_body_type_msg(NULL), - m_body_type_text(NULL), m_body_ext_1part(NULL) - { + : m_body_type_basic(NULL), + m_body_type_msg(NULL), + m_body_type_text(NULL), + m_body_ext_1part(NULL) { + } - ~body_type_1part() - { - delete (m_body_type_basic); - delete (m_body_type_msg); - delete (m_body_type_text); + ~body_type_1part() { - delete (m_body_ext_1part); + delete m_body_type_basic; + delete m_body_type_msg; + delete m_body_type_text; + delete m_body_ext_1part; } - bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) - { + bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) { + size_t pos = *currentPos; - if (!VIMAP_PARSER_TRY_GET(IMAPParser::body_type_text, m_body_type_text)) - if (!VIMAP_PARSER_TRY_GET(IMAPParser::body_type_msg, m_body_type_msg)) + if (!VIMAP_PARSER_TRY_GET(IMAPParser::body_type_text, m_body_type_text)) { + if (!VIMAP_PARSER_TRY_GET(IMAPParser::body_type_msg, m_body_type_msg)) { VIMAP_PARSER_GET(IMAPParser::body_type_basic, m_body_type_basic); + } + } - if (VIMAP_PARSER_TRY_CHECK(SPACE)) - { - if (!VIMAP_PARSER_TRY_GET(IMAPParser::body_ext_1part, m_body_ext_1part)) + if (VIMAP_PARSER_TRY_CHECK(SPACE)) { + if (!VIMAP_PARSER_TRY_GET(IMAPParser::body_ext_1part, m_body_ext_1part)) { --pos; + } } *currentPos = pos; @@ -4087,30 +4123,30 @@ public: DECLARE_COMPONENT(body_type_mpart) body_type_mpart() - : m_media_subtype(NULL), m_body_ext_mpart(NULL) - { + : m_media_subtype(NULL), + m_body_ext_mpart(NULL) { + } - ~body_type_mpart() - { - delete (m_media_subtype); - delete (m_body_ext_mpart); + ~body_type_mpart() { + + delete m_media_subtype; + delete m_body_ext_mpart; for (std::vector <xbody*>::iterator it = m_list.begin() ; - it != m_list.end() ; ++it) - { - delete (*it); + it != m_list.end() ; ++it) { + + delete *it; } } - bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) - { + bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) { + size_t pos = *currentPos; VIMAP_PARSER_GET_PUSHBACK(xbody, m_list); - while (true) - { + while (true) { VIMAP_PARSER_TRY_GET_PUSHBACK_OR_ELSE(xbody, m_list, break); } @@ -4118,8 +4154,9 @@ public: VIMAP_PARSER_GET(IMAPParser::media_subtype, m_media_subtype); - if (VIMAP_PARSER_TRY_CHECK(SPACE)) + if (VIMAP_PARSER_TRY_CHECK(SPACE)) { VIMAP_PARSER_GET(IMAPParser::body_ext_mpart, m_body_ext_mpart); + } *currentPos = pos; @@ -4149,24 +4186,26 @@ public: DECLARE_COMPONENT(xbody) xbody() - : m_body_type_1part(NULL), m_body_type_mpart(NULL) - { + : m_body_type_1part(NULL), + m_body_type_mpart(NULL) { + } - ~xbody() - { - delete (m_body_type_1part); - delete (m_body_type_mpart); + ~xbody() { + + delete m_body_type_1part; + delete m_body_type_mpart; } - bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) - { + bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) { + size_t pos = *currentPos; VIMAP_PARSER_CHECK(one_char <'('> ); - if (!VIMAP_PARSER_TRY_GET(IMAPParser::body_type_mpart, m_body_type_mpart)) + if (!VIMAP_PARSER_TRY_GET(IMAPParser::body_type_mpart, m_body_type_mpart)) { VIMAP_PARSER_GET(IMAPParser::body_type_1part, m_body_type_1part); + } VIMAP_PARSER_CHECK(one_char <')'> ); @@ -4203,139 +4242,141 @@ public: DECLARE_COMPONENT(msg_att_item) msg_att_item() - : m_date_time(NULL), m_number(NULL), m_envelope(NULL), - m_uniqueid(NULL), m_nstring(NULL), m_body(NULL), m_flag_list(NULL), - m_section(NULL), m_mod_sequence_value(NULL) + : m_date_time(NULL), + m_number(NULL), + m_envelope(NULL), + m_uniqueid(NULL), + m_nstring(NULL), + m_body(NULL), + m_flag_list(NULL), + m_section(NULL), + m_mod_sequence_value(NULL) { - { } - ~msg_att_item() - { - delete (m_date_time); - delete (m_number); - delete (m_envelope); - delete (m_uniqueid); - delete (m_nstring); - delete (m_body); - delete (m_flag_list); - delete (m_section); + ~msg_att_item() { + + delete m_date_time; + delete m_number; + delete m_envelope; + delete m_uniqueid; + delete m_nstring; + delete m_body; + delete m_flag_list; + delete m_section; delete m_mod_sequence_value; } - bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) - { + bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) { + size_t pos = *currentPos; // "ENVELOPE" SPACE envelope - if (VIMAP_PARSER_TRY_CHECK_WITHARG(special_atom, "envelope")) - { + if (VIMAP_PARSER_TRY_CHECK_WITHARG(special_atom, "envelope")) { + m_type = ENVELOPE; VIMAP_PARSER_CHECK(SPACE); VIMAP_PARSER_GET(IMAPParser::envelope, m_envelope); - } + // "FLAGS" SPACE "(" #(flag / "\Recent") ")" - else if (VIMAP_PARSER_TRY_CHECK_WITHARG(special_atom, "flags")) - { + } else if (VIMAP_PARSER_TRY_CHECK_WITHARG(special_atom, "flags")) { + m_type = FLAGS; VIMAP_PARSER_CHECK(SPACE); VIMAP_PARSER_GET(IMAPParser::flag_list, m_flag_list); - } + // "INTERNALDATE" SPACE date_time - else if (VIMAP_PARSER_TRY_CHECK_WITHARG(special_atom, "internaldate")) - { + } else if (VIMAP_PARSER_TRY_CHECK_WITHARG(special_atom, "internaldate")) { + m_type = INTERNALDATE; VIMAP_PARSER_CHECK(SPACE); VIMAP_PARSER_GET(IMAPParser::date_time, m_date_time); - } + // "RFC822" ".HEADER" SPACE nstring - else if (VIMAP_PARSER_TRY_CHECK_WITHARG(special_atom, "rfc822.header")) - { + } else if (VIMAP_PARSER_TRY_CHECK_WITHARG(special_atom, "rfc822.header")) { + m_type = RFC822_HEADER; VIMAP_PARSER_CHECK(SPACE); VIMAP_PARSER_GET(IMAPParser::nstring, m_nstring); - } + // "RFC822" ".TEXT" SPACE nstring - else if (VIMAP_PARSER_TRY_CHECK_WITHARG(special_atom, "rfc822.text")) - { + } else if (VIMAP_PARSER_TRY_CHECK_WITHARG(special_atom, "rfc822.text")) { + m_type = RFC822_TEXT; VIMAP_PARSER_CHECK(SPACE); - m_nstring = parser.getWithArgs <IMAPParser::nstring> - (line, &pos, this, RFC822_TEXT); + m_nstring = parser.getWithArgs <IMAPParser::nstring>(line, &pos, this, RFC822_TEXT); VIMAP_PARSER_FAIL_UNLESS(m_nstring); - } + // "RFC822.SIZE" SPACE number - else if (VIMAP_PARSER_TRY_CHECK_WITHARG(special_atom, "rfc822.size")) - { + } else if (VIMAP_PARSER_TRY_CHECK_WITHARG(special_atom, "rfc822.size")) { + m_type = RFC822_SIZE; VIMAP_PARSER_CHECK(SPACE); VIMAP_PARSER_GET(IMAPParser::number, m_number); - } + // "RFC822" SPACE nstring - else if (VIMAP_PARSER_TRY_CHECK_WITHARG(special_atom, "rfc822")) - { + } else if (VIMAP_PARSER_TRY_CHECK_WITHARG(special_atom, "rfc822")) { + m_type = RFC822; VIMAP_PARSER_CHECK(SPACE); VIMAP_PARSER_GET(IMAPParser::nstring, m_nstring); - } + // "BODY" "STRUCTURE" SPACE body - else if (VIMAP_PARSER_TRY_CHECK_WITHARG(special_atom, "bodystructure")) - { + } else if (VIMAP_PARSER_TRY_CHECK_WITHARG(special_atom, "bodystructure")) { + m_type = BODY_STRUCTURE; VIMAP_PARSER_CHECK(SPACE); VIMAP_PARSER_GET(IMAPParser::body, m_body); - } + // "BODY" section ["<" number ">"] SPACE nstring // "BODY" SPACE body - else if (VIMAP_PARSER_TRY_CHECK_WITHARG(special_atom, "body")) - { + } else if (VIMAP_PARSER_TRY_CHECK_WITHARG(special_atom, "body")) { + VIMAP_PARSER_TRY_GET(IMAPParser::section, m_section); // "BODY" section ["<" number ">"] SPACE nstring - if (m_section != NULL) - { + if (m_section != NULL) { + m_type = BODY_SECTION; - if (VIMAP_PARSER_TRY_CHECK(one_char <'<'> )) - { + if (VIMAP_PARSER_TRY_CHECK(one_char <'<'> )) { VIMAP_PARSER_GET(IMAPParser::number, m_number); VIMAP_PARSER_CHECK(one_char <'>'> ); } VIMAP_PARSER_CHECK(SPACE); - m_nstring = parser.getWithArgs <IMAPParser::nstring> - (line, &pos, this, BODY_SECTION); + m_nstring = parser.getWithArgs <IMAPParser::nstring>(line, &pos, this, BODY_SECTION); VIMAP_PARSER_FAIL_UNLESS(m_nstring); - } + // "BODY" SPACE body - else - { + } else { + m_type = BODY; VIMAP_PARSER_CHECK(SPACE); VIMAP_PARSER_GET(IMAPParser::body, m_body); } - } + // "MODSEQ" SP "(" mod_sequence_value ")" - else if (VIMAP_PARSER_TRY_CHECK_WITHARG(special_atom, "modseq")) - { + } else if (VIMAP_PARSER_TRY_CHECK_WITHARG(special_atom, "modseq")) { + m_type = MODSEQ; VIMAP_PARSER_CHECK(SPACE); @@ -4344,10 +4385,10 @@ public: VIMAP_PARSER_GET(IMAPParser::mod_sequence_value, m_mod_sequence_value); VIMAP_PARSER_CHECK(one_char <')'> ); - } + // "UID" SPACE uniqueid - else - { + } else { + m_type = UID; VIMAP_PARSER_CHECK_WITHARG(special_atom, "uid"); @@ -4362,8 +4403,7 @@ public: } - enum Type - { + enum Type { ENVELOPE, FLAGS, INTERNALDATE, @@ -4414,25 +4454,24 @@ public: DECLARE_COMPONENT(msg_att) - ~msg_att() - { + ~msg_att() { + for (std::vector <msg_att_item*>::iterator it = m_items.begin() ; - it != m_items.end() ; ++it) - { - delete (*it); + it != m_items.end() ; ++it) { + + delete *it; } } - bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) - { + bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) { + size_t pos = *currentPos; VIMAP_PARSER_CHECK(one_char <'('> ); m_items.push_back(parser.get <msg_att_item>(line, &pos)); - while (!VIMAP_PARSER_TRY_CHECK(one_char <')'> )) - { + while (!VIMAP_PARSER_TRY_CHECK(one_char <')'> )) { VIMAP_PARSER_CHECK(SPACE); VIMAP_PARSER_GET_PUSHBACK(msg_att_item, m_items); } @@ -4460,17 +4499,18 @@ public: DECLARE_COMPONENT(message_data) message_data() - : m_number(0), m_msg_att(NULL) - { + : m_number(0), + m_msg_att(NULL) { + } - ~message_data() - { - delete (m_msg_att); + ~message_data() { + + delete m_msg_att; } - bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) - { + bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) { + size_t pos = *currentPos; scoped_ptr <nz_number> num; @@ -4479,12 +4519,12 @@ public: VIMAP_PARSER_CHECK(SPACE); - if (VIMAP_PARSER_TRY_CHECK_WITHARG(special_atom, "expunge")) - { + if (VIMAP_PARSER_TRY_CHECK_WITHARG(special_atom, "expunge")) { + m_type = EXPUNGE; - } - else - { + + } else { + m_type = FETCH; VIMAP_PARSER_CHECK_WITHARG(special_atom, "fetch"); @@ -4498,8 +4538,7 @@ public: } - enum Type - { + enum Type { EXPUNGE, FETCH }; @@ -4543,122 +4582,125 @@ public: DECLARE_COMPONENT(resp_text_code) resp_text_code() - : m_nz_number(NULL), m_atom(NULL), m_flag_list(NULL), - m_text(NULL), m_capability_data(NULL) - { + : m_nz_number(NULL), + m_atom(NULL), + m_flag_list(NULL), + m_text(NULL), + m_capability_data(NULL) { + } - ~resp_text_code() - { - delete (m_nz_number); - delete (m_atom); - delete (m_flag_list); - delete (m_text); + ~resp_text_code() { + + delete m_nz_number; + delete m_atom; + delete m_flag_list; + delete m_text; delete m_capability_data; } - bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) - { + bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) { + size_t pos = *currentPos; // "ALERT" - if (VIMAP_PARSER_TRY_CHECK_WITHARG(special_atom, "alert")) - { + if (VIMAP_PARSER_TRY_CHECK_WITHARG(special_atom, "alert")) { + m_type = ALERT; - } + // "PARSE" - else if (VIMAP_PARSER_TRY_CHECK_WITHARG(special_atom, "parse")) - { + } else if (VIMAP_PARSER_TRY_CHECK_WITHARG(special_atom, "parse")) { + m_type = PARSE; - } + // capability_data - else if (VIMAP_PARSER_TRY_GET(IMAPParser::capability_data, m_capability_data)) - { + } else if (VIMAP_PARSER_TRY_GET(IMAPParser::capability_data, m_capability_data)) { + m_type = CAPABILITY; - } + // "PERMANENTFLAGS" SPACE flag_list - else if (VIMAP_PARSER_TRY_CHECK_WITHARG(special_atom, "permanentflags")) - { + } else if (VIMAP_PARSER_TRY_CHECK_WITHARG(special_atom, "permanentflags")) { + m_type = PERMANENTFLAGS; VIMAP_PARSER_CHECK(SPACE); VIMAP_PARSER_GET(IMAPParser::flag_list, m_flag_list); - } + // "READ-ONLY" - else if (VIMAP_PARSER_TRY_CHECK_WITHARG(special_atom, "read-only")) - { + } else if (VIMAP_PARSER_TRY_CHECK_WITHARG(special_atom, "read-only")) { + m_type = READ_ONLY; - } + // "READ-WRITE" - else if (VIMAP_PARSER_TRY_CHECK_WITHARG(special_atom, "read-write")) - { + } else if (VIMAP_PARSER_TRY_CHECK_WITHARG(special_atom, "read-write")) { + m_type = READ_WRITE; - } + // "TRYCREATE" - else if (VIMAP_PARSER_TRY_CHECK_WITHARG(special_atom, "trycreate")) - { + } else if (VIMAP_PARSER_TRY_CHECK_WITHARG(special_atom, "trycreate")) { + m_type = TRYCREATE; - } + // "UIDVALIDITY" SPACE nz_number - else if (VIMAP_PARSER_TRY_CHECK_WITHARG(special_atom, "uidvalidity")) - { + } else if (VIMAP_PARSER_TRY_CHECK_WITHARG(special_atom, "uidvalidity")) { + m_type = UIDVALIDITY; VIMAP_PARSER_CHECK(SPACE); VIMAP_PARSER_GET(IMAPParser::nz_number, m_nz_number); - } + // "UIDNEXT" SPACE nz_number - else if (VIMAP_PARSER_TRY_CHECK_WITHARG(special_atom, "uidnext")) - { + } else if (VIMAP_PARSER_TRY_CHECK_WITHARG(special_atom, "uidnext")) { + m_type = UIDNEXT; VIMAP_PARSER_CHECK(SPACE); VIMAP_PARSER_GET(IMAPParser::nz_number, m_nz_number); - } + // "UNSEEN" SPACE nz_number - else if (VIMAP_PARSER_TRY_CHECK_WITHARG(special_atom, "unseen")) - { + } else if (VIMAP_PARSER_TRY_CHECK_WITHARG(special_atom, "unseen")) { + m_type = UNSEEN; VIMAP_PARSER_CHECK(SPACE); VIMAP_PARSER_GET(IMAPParser::nz_number, m_nz_number); - } + // "HIGHESTMODSEQ" SP mod-sequence-value - else if (VIMAP_PARSER_TRY_CHECK_WITHARG(special_atom, "highestmodseq")) - { + } else if (VIMAP_PARSER_TRY_CHECK_WITHARG(special_atom, "highestmodseq")) { + m_type = HIGHESTMODSEQ; VIMAP_PARSER_CHECK(SPACE); VIMAP_PARSER_GET(IMAPParser::mod_sequence_value, m_mod_sequence_value); - } + // "NOMODSEQ" - else if (VIMAP_PARSER_TRY_CHECK_WITHARG(special_atom, "nomodseq")) - { + } else if (VIMAP_PARSER_TRY_CHECK_WITHARG(special_atom, "nomodseq")) { + m_type = NOMODSEQ; - } + // "MODIFIED" SP sequence-set - else if (VIMAP_PARSER_TRY_CHECK_WITHARG(special_atom, "modified")) - { + } else if (VIMAP_PARSER_TRY_CHECK_WITHARG(special_atom, "modified")) { + m_type = MODIFIED; VIMAP_PARSER_CHECK(SPACE); VIMAP_PARSER_GET(IMAPParser::sequence_set, m_sequence_set); - } + // "APPENDUID" SP nz-number SP append-uid - else if (VIMAP_PARSER_TRY_CHECK_WITHARG(special_atom, "appenduid")) - { + } else if (VIMAP_PARSER_TRY_CHECK_WITHARG(special_atom, "appenduid")) { + m_type = APPENDUID; VIMAP_PARSER_CHECK(SPACE); VIMAP_PARSER_GET(IMAPParser::nz_number, m_nz_number); VIMAP_PARSER_CHECK(SPACE); VIMAP_PARSER_GET(IMAPParser::uid_set, m_uid_set); - } + // "COPYUID" SP nz-number SP uid-set SP uid-set - else if (VIMAP_PARSER_TRY_CHECK_WITHARG(special_atom, "copyuid")) - { + } else if (VIMAP_PARSER_TRY_CHECK_WITHARG(special_atom, "copyuid")) { + m_type = COPYUID; VIMAP_PARSER_CHECK(SPACE); @@ -4667,21 +4709,22 @@ public: VIMAP_PARSER_GET(IMAPParser::uid_set, m_uid_set); VIMAP_PARSER_CHECK(SPACE); VIMAP_PARSER_GET(IMAPParser::uid_set, m_uid_set2); - } + // "UIDNOTSTICKY" - else if (VIMAP_PARSER_TRY_CHECK_WITHARG(special_atom, "uidnotsticky")) - { + } else if (VIMAP_PARSER_TRY_CHECK_WITHARG(special_atom, "uidnotsticky")) { + m_type = UIDNOTSTICKY; - } + // atom [SPACE 1*<any TEXT_CHAR except "]">] - else - { + } else { + m_type = OTHER; VIMAP_PARSER_GET(IMAPParser::atom, m_atom); - if (VIMAP_PARSER_TRY_CHECK(SPACE)) + if (VIMAP_PARSER_TRY_CHECK(SPACE)) { VIMAP_PARSER_GET(text_except <']'> , m_text); + } } *currentPos = pos; @@ -4690,8 +4733,7 @@ public: } - enum Type - { + enum Type { // Extensions HIGHESTMODSEQ, NOMODSEQ, @@ -4751,21 +4793,21 @@ public: DECLARE_COMPONENT(resp_text) resp_text() - : m_resp_text_code(NULL) - { + : m_resp_text_code(NULL) { + } - ~resp_text() - { - delete (m_resp_text_code); + ~resp_text() { + + delete m_resp_text_code; } - bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) - { + bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) { + size_t pos = *currentPos; - if (VIMAP_PARSER_TRY_CHECK(one_char <'['> )) - { + if (VIMAP_PARSER_TRY_CHECK(one_char <'['> )) { + VIMAP_PARSER_GET(IMAPParser::resp_text_code, m_resp_text_code); VIMAP_PARSER_CHECK(one_char <']'> ); @@ -4775,21 +4817,18 @@ public: scoped_ptr <text_mime2> text1; VIMAP_PARSER_TRY_GET_PTR(text_mime2, text1); - if (text1.get()) - { + if (text1.get()) { + m_text = text1->value(); - } - else - { + + } else { + scoped_ptr <IMAPParser::text> text2; VIMAP_PARSER_TRY_GET_PTR(IMAPParser::text, text2); - if (text2.get()) - { + if (text2.get()) { m_text = text2->value(); - } - else - { + } else { // Empty response text } } @@ -4818,35 +4857,32 @@ public: DECLARE_COMPONENT(continue_req) continue_req() - : m_resp_text(NULL) - { + : m_resp_text(NULL) { + } - ~continue_req() - { - delete (m_resp_text); + ~continue_req() { + + delete m_resp_text; } - bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) - { + bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) { + size_t pos = *currentPos; VIMAP_PARSER_CHECK(one_char <'+'> ); - if (!parser.isStrict()) - { + if (!parser.isStrict()) { + // Some servers do not send SPACE when response text is empty - if (VIMAP_PARSER_TRY_CHECK(SPACE)) - { + if (VIMAP_PARSER_TRY_CHECK(SPACE)) { VIMAP_PARSER_GET(IMAPParser::resp_text, m_resp_text); - } - else - { + } else { m_resp_text = new IMAPParser::resp_text(); // empty } - } - else - { + + } else { + VIMAP_PARSER_CHECK(SPACE); VIMAP_PARSER_GET(IMAPParser::resp_text, m_resp_text); @@ -4877,29 +4913,25 @@ public: DECLARE_COMPONENT(resp_cond_state) resp_cond_state() - : m_resp_text(NULL), m_status(BAD) - { + : m_resp_text(NULL), + m_status(BAD) { + } - ~resp_cond_state() - { - delete (m_resp_text); + ~resp_cond_state() { + + delete m_resp_text; } - bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) - { + bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) { + size_t pos = *currentPos; - if (VIMAP_PARSER_TRY_CHECK_WITHARG(special_atom, "ok")) - { + if (VIMAP_PARSER_TRY_CHECK_WITHARG(special_atom, "ok")) { m_status = OK; - } - else if (VIMAP_PARSER_TRY_CHECK_WITHARG(special_atom, "no")) - { + } else if (VIMAP_PARSER_TRY_CHECK_WITHARG(special_atom, "no")) { m_status = NO; - } - else - { + } else { VIMAP_PARSER_CHECK_WITHARG(special_atom, "bad"); m_status = BAD; } @@ -4914,8 +4946,7 @@ public: } - enum Status - { + enum Status { OK, NO, BAD @@ -4940,17 +4971,17 @@ public: DECLARE_COMPONENT(resp_cond_bye) resp_cond_bye() - : m_resp_text(NULL) - { + : m_resp_text(NULL) { + } - ~resp_cond_bye() - { - delete (m_resp_text); + ~resp_cond_bye() { + + delete m_resp_text; } - bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) - { + bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) { + size_t pos = *currentPos; VIMAP_PARSER_CHECK_WITHARG(special_atom, "bye"); @@ -4982,27 +5013,23 @@ public: DECLARE_COMPONENT(resp_cond_auth) resp_cond_auth() - : m_resp_text(NULL) - { + : m_resp_text(NULL) { + } - ~resp_cond_auth() - { - delete (m_resp_text); + ~resp_cond_auth() { + + delete m_resp_text; } - bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) - { + bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) { + size_t pos = *currentPos; - if (VIMAP_PARSER_TRY_CHECK_WITHARG(special_atom, "ok")) - { + if (VIMAP_PARSER_TRY_CHECK_WITHARG(special_atom, "ok")) { m_cond = OK; - } - else - { + } else { VIMAP_PARSER_CHECK_WITHARG(special_atom, "preauth"); - m_cond = PREAUTH; } @@ -5016,8 +5043,7 @@ public: } - enum Condition - { + enum Condition { OK, PREAUTH }; @@ -5049,102 +5075,103 @@ public: DECLARE_COMPONENT(mailbox_data) mailbox_data() - : m_number(NULL), m_mailbox_flag_list(NULL), m_mailbox_list(NULL), - m_mailbox(NULL), m_text(NULL), m_status_att_list(NULL) - { + : m_number(NULL), + m_mailbox_flag_list(NULL), + m_mailbox_list(NULL), + m_mailbox(NULL), + m_text(NULL), + m_status_att_list(NULL) { + } - ~mailbox_data() - { - delete (m_number); - delete (m_mailbox_flag_list); - delete (m_mailbox_list); - delete (m_mailbox); - delete (m_text); + ~mailbox_data() { + + delete m_number; + delete m_mailbox_flag_list; + delete m_mailbox_list; + delete m_mailbox; + delete m_text; for (std::vector <nz_number*>::iterator it = m_search_nz_number_list.begin() ; - it != m_search_nz_number_list.end() ; ++it) - { - delete (*it); + it != m_search_nz_number_list.end() ; ++it) { + + delete *it; } delete m_status_att_list; } - bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) - { + bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) { + size_t pos = *currentPos; - if (VIMAP_PARSER_TRY_GET(IMAPParser::number, m_number)) - { + if (VIMAP_PARSER_TRY_GET(IMAPParser::number, m_number)) { + VIMAP_PARSER_CHECK(SPACE); - if (VIMAP_PARSER_TRY_CHECK_WITHARG(special_atom, "exists")) - { + if (VIMAP_PARSER_TRY_CHECK_WITHARG(special_atom, "exists")) { m_type = EXISTS; - } - else - { + } else { VIMAP_PARSER_CHECK_WITHARG(special_atom, "recent"); - m_type = RECENT; } - } - else - { + + } else { + // "FLAGS" SPACE mailbox_flag_list - if (VIMAP_PARSER_TRY_CHECK_WITHARG(special_atom, "flags")) - { + if (VIMAP_PARSER_TRY_CHECK_WITHARG(special_atom, "flags")) { + VIMAP_PARSER_CHECK(SPACE); VIMAP_PARSER_GET(IMAPParser::mailbox_flag_list, m_mailbox_flag_list); m_type = FLAGS; - } + // "LIST" SPACE mailbox_list - else if (VIMAP_PARSER_TRY_CHECK_WITHARG(special_atom, "list")) - { + } else if (VIMAP_PARSER_TRY_CHECK_WITHARG(special_atom, "list")) { + VIMAP_PARSER_CHECK(SPACE); VIMAP_PARSER_GET(IMAPParser::mailbox_list, m_mailbox_list); m_type = LIST; - } + // "LSUB" SPACE mailbox_list - else if (VIMAP_PARSER_TRY_CHECK_WITHARG(special_atom, "lsub")) - { + } else if (VIMAP_PARSER_TRY_CHECK_WITHARG(special_atom, "lsub")) { + VIMAP_PARSER_CHECK(SPACE); VIMAP_PARSER_GET(IMAPParser::mailbox_list, m_mailbox_list); m_type = LSUB; - } + // "MAILBOX" SPACE text - else if (VIMAP_PARSER_TRY_CHECK_WITHARG(special_atom, "mailbox")) - { + } else if (VIMAP_PARSER_TRY_CHECK_WITHARG(special_atom, "mailbox")) { + VIMAP_PARSER_CHECK(SPACE); VIMAP_PARSER_GET(IMAPParser::text, m_text); m_type = MAILBOX; - } + // "SEARCH" [SPACE 1#nz_number] - else if (VIMAP_PARSER_TRY_CHECK_WITHARG(special_atom, "search")) - { - if (VIMAP_PARSER_TRY_CHECK(SPACE)) - { + } else if (VIMAP_PARSER_TRY_CHECK_WITHARG(special_atom, "search")) { + + if (VIMAP_PARSER_TRY_CHECK(SPACE)) { + VIMAP_PARSER_GET_PUSHBACK(nz_number, m_search_nz_number_list); - while (VIMAP_PARSER_TRY_CHECK(SPACE)) + while (VIMAP_PARSER_TRY_CHECK(SPACE)) { VIMAP_PARSER_GET_PUSHBACK(nz_number, m_search_nz_number_list); + } } m_type = SEARCH; - } + // "STATUS" SPACE mailbox SPACE // "(" [status_att_list] ")" - else - { + } else { + VIMAP_PARSER_CHECK_WITHARG(special_atom, "status"); VIMAP_PARSER_CHECK(SPACE); @@ -5166,8 +5193,8 @@ public: } - enum Type - { + enum Type { + FLAGS, LIST, LSUB, @@ -5212,38 +5239,46 @@ public: DECLARE_COMPONENT(response_data) response_data() - : m_resp_cond_state(NULL), m_resp_cond_bye(NULL), - m_mailbox_data(NULL), m_message_data(NULL), m_capability_data(NULL) - { + : m_resp_cond_state(NULL), + m_resp_cond_bye(NULL), + m_mailbox_data(NULL), + m_message_data(NULL), + m_capability_data(NULL) { + } - ~response_data() - { - delete (m_resp_cond_state); - delete (m_resp_cond_bye); - delete (m_mailbox_data); - delete (m_message_data); - delete (m_capability_data); + ~response_data() { + + delete m_resp_cond_state; + delete m_resp_cond_bye; + delete m_mailbox_data; + delete m_message_data; + delete m_capability_data; } - bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) - { + bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) { + size_t pos = *currentPos; VIMAP_PARSER_CHECK(one_char <'*'> ); VIMAP_PARSER_CHECK(SPACE); - if (!VIMAP_PARSER_TRY_GET(IMAPParser::resp_cond_state, m_resp_cond_state)) - if (!VIMAP_PARSER_TRY_GET(IMAPParser::resp_cond_bye, m_resp_cond_bye)) - if (!VIMAP_PARSER_TRY_GET(IMAPParser::mailbox_data, m_mailbox_data)) - if (!VIMAP_PARSER_TRY_GET(IMAPParser::message_data, m_message_data)) + if (!VIMAP_PARSER_TRY_GET(IMAPParser::resp_cond_state, m_resp_cond_state)) { + if (!VIMAP_PARSER_TRY_GET(IMAPParser::resp_cond_bye, m_resp_cond_bye)) { + if (!VIMAP_PARSER_TRY_GET(IMAPParser::mailbox_data, m_mailbox_data)) { + if (!VIMAP_PARSER_TRY_GET(IMAPParser::message_data, m_message_data)) { VIMAP_PARSER_GET(IMAPParser::capability_data, m_capability_data); + } + } + } + } + + if (!parser.isStrict()) { - if (!parser.isStrict()) - { // Allow SPACEs at end of line - while (VIMAP_PARSER_TRY_CHECK(SPACE)) + while (VIMAP_PARSER_TRY_CHECK(SPACE)) { ; + } } VIMAP_PARSER_CHECK(CRLF); @@ -5274,22 +5309,24 @@ public: DECLARE_COMPONENT(continue_req_or_response_data) continue_req_or_response_data() - : m_continue_req(NULL), m_response_data(NULL) - { + : m_continue_req(NULL), + m_response_data(NULL) { + } - ~continue_req_or_response_data() - { - delete (m_continue_req); - delete (m_response_data); + ~continue_req_or_response_data() { + + delete m_continue_req; + delete m_response_data; } - bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) - { + bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) { + size_t pos = *currentPos; - if (!VIMAP_PARSER_TRY_GET(IMAPParser::continue_req, m_continue_req)) + if (!VIMAP_PARSER_TRY_GET(IMAPParser::continue_req, m_continue_req)) { VIMAP_PARSER_GET(IMAPParser::response_data, m_response_data); + } *currentPos = pos; @@ -5316,17 +5353,17 @@ public: DECLARE_COMPONENT(response_fatal) response_fatal() - : m_resp_cond_bye(NULL) - { + : m_resp_cond_bye(NULL) { + } - ~response_fatal() - { - delete (m_resp_cond_bye); + ~response_fatal() { + + delete m_resp_cond_bye; } - bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) - { + bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) { + size_t pos = *currentPos; VIMAP_PARSER_CHECK(one_char <'*'> ); @@ -5334,11 +5371,12 @@ public: VIMAP_PARSER_GET(IMAPParser::resp_cond_bye, m_resp_cond_bye); - if (!parser.isStrict()) - { + if (!parser.isStrict()) { + // Allow SPACEs at end of line - while (VIMAP_PARSER_TRY_CHECK(SPACE)) + while (VIMAP_PARSER_TRY_CHECK(SPACE)) { ; + } } VIMAP_PARSER_CHECK(CRLF); @@ -5365,28 +5403,29 @@ public: DECLARE_COMPONENT(response_tagged) response_tagged() - : m_resp_cond_state(NULL) - { + : m_resp_cond_state(NULL) { + } - ~response_tagged() - { - delete (m_resp_cond_state); + ~response_tagged() { + + delete m_resp_cond_state; } - bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) - { + bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) { + size_t pos = *currentPos; VIMAP_PARSER_CHECK(IMAPParser::xtag); VIMAP_PARSER_CHECK(SPACE); VIMAP_PARSER_GET(IMAPParser::resp_cond_state, m_resp_cond_state); - if (!parser.isStrict()) - { + if (!parser.isStrict()) { + // Allow SPACEs at end of line - while (VIMAP_PARSER_TRY_CHECK(SPACE)) + while (VIMAP_PARSER_TRY_CHECK(SPACE)) { ; + } } VIMAP_PARSER_CHECK(CRLF); @@ -5413,22 +5452,24 @@ public: DECLARE_COMPONENT(response_done) response_done() - : m_response_tagged(NULL), m_response_fatal(NULL) - { + : m_response_tagged(NULL), + m_response_fatal(NULL) { + } - ~response_done() - { - delete (m_response_tagged); - delete (m_response_fatal); + ~response_done() { + + delete m_response_tagged; + delete m_response_fatal; } - bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) - { + bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) { + size_t pos = *currentPos; - if (!VIMAP_PARSER_TRY_GET(IMAPParser::response_tagged, m_response_tagged)) + if (!VIMAP_PARSER_TRY_GET(IMAPParser::response_tagged, m_response_tagged)) { VIMAP_PARSER_GET(IMAPParser::response_fatal, m_response_fatal); + } *currentPos = pos; @@ -5454,37 +5495,36 @@ public: DECLARE_COMPONENT(response) response() - : m_response_done(NULL) - { + : m_response_done(NULL) { + } - ~response() - { + ~response() { + for (std::vector <IMAPParser::continue_req_or_response_data*>::iterator it = m_continue_req_or_response_data.begin() ; - it != m_continue_req_or_response_data.end() ; ++it) - { - delete (*it); + it != m_continue_req_or_response_data.end() ; ++it) { + + delete *it; } - delete (m_response_done); + delete m_response_done; } - bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) - { + bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) { + size_t pos = *currentPos; string curLine = line; bool partial = false; // partial response IMAPParser::continue_req_or_response_data* resp = NULL; - while ((resp = parser.get <IMAPParser::continue_req_or_response_data>(curLine, &pos))) - { + while ((resp = parser.get <IMAPParser::continue_req_or_response_data>(curLine, &pos))) { + m_continue_req_or_response_data.push_back(resp); // Partial response (continue_req) - if (resp->continue_req()) - { + if (resp->continue_req()) { partial = true; break; } @@ -5494,8 +5534,7 @@ public: pos = 0; } - if (!partial) - { + if (!partial) { m_response_done = parser.get <IMAPParser::response_done>(curLine, &pos); VIMAP_PARSER_FAIL_UNLESS(m_response_done); } @@ -5506,30 +5545,32 @@ public: } - bool isBad() const - { - if (!response_done()) // incomplete (partial) response - return (true); + bool isBad() const { + + if (!response_done()) { // incomplete (partial) response + return true; + } - if (response_done()->response_fatal()) - return (true); + if (response_done()->response_fatal()) { + return true; + } if (response_done()->response_tagged()->resp_cond_state()-> - status() == IMAPParser::resp_cond_state::BAD) - { - return (true); + status() == IMAPParser::resp_cond_state::BAD) { + + return true; } - return (false); + return false; } - void setErrorLog(const string& errorLog) - { + void setErrorLog(const string& errorLog) { + m_errorLog = errorLog; } - const string& getErrorLog() const - { + const string& getErrorLog() const { + return m_errorLog; } @@ -5554,25 +5595,27 @@ public: DECLARE_COMPONENT(greeting) greeting() - : m_resp_cond_auth(NULL), m_resp_cond_bye(NULL) - { + : m_resp_cond_auth(NULL), + m_resp_cond_bye(NULL) { + } - ~greeting() - { - delete (m_resp_cond_auth); - delete (m_resp_cond_bye); + ~greeting() { + + delete m_resp_cond_auth; + delete m_resp_cond_bye; } - bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) - { + bool parseImpl(IMAPParser& parser, string& line, size_t* currentPos) { + size_t pos = *currentPos; VIMAP_PARSER_CHECK(one_char <'*'> ); VIMAP_PARSER_CHECK(SPACE); - if (!VIMAP_PARSER_TRY_GET(IMAPParser::resp_cond_auth, m_resp_cond_auth)) + if (!VIMAP_PARSER_TRY_GET(IMAPParser::resp_cond_auth, m_resp_cond_auth)) { VIMAP_PARSER_GET(IMAPParser::resp_cond_bye, m_resp_cond_bye); + } VIMAP_PARSER_CHECK(CRLF); @@ -5581,13 +5624,13 @@ public: return true; } - void setErrorLog(const string& errorLog) - { + void setErrorLog(const string& errorLog) { + m_errorLog = errorLog; } - const string& getErrorLog() const - { + const string& getErrorLog() const { + return m_errorLog; } @@ -5610,8 +5653,8 @@ public: // The main functions used to parse a response // - response* readResponse(literalHandler* lh = NULL) - { + response* readResponse(literalHandler* lh = NULL) { + size_t pos = 0; string line = readLine(); @@ -5619,8 +5662,9 @@ public: response* resp = get <response>(line, &pos); m_literalHandler = NULL; - if (!resp) + if (!resp) { throw exceptions::invalid_response("", m_errorResponseLine); + } resp->setErrorLog(lastLine()); @@ -5628,15 +5672,16 @@ public: } - greeting* readGreeting() - { + greeting* readGreeting() { + size_t pos = 0; string line = readLine(); greeting* greet = get <greeting>(line, &pos); - if (!greet) + if (!greet) { throw exceptions::invalid_response("", m_errorResponseLine); + } greet->setErrorLog(lastLine()); @@ -5655,8 +5700,8 @@ public: * @return a raw pointer to the parsed token, or NULL otherwise */ template <class TYPE> - TYPE* get(string& line, size_t* currentPos) - { + TYPE* get(string& line, size_t* currentPos) { + component* resp = new TYPE; return internalGet <TYPE>(resp, line, currentPos); } @@ -5676,9 +5721,8 @@ public: * @return a raw pointer to the parsed token, or NULL otherwise */ template <class TYPE, class ARG1_TYPE, class ARG2_TYPE> - TYPE* getWithArgs(string& line, size_t* currentPos, - ARG1_TYPE arg1, ARG2_TYPE arg2) - { + TYPE* getWithArgs(string& line, size_t* currentPos, ARG1_TYPE arg1, ARG2_TYPE arg2) { + component* resp = new TYPE(arg1, arg2); return internalGet <TYPE>(resp, line, currentPos); } @@ -5686,15 +5730,15 @@ public: private: template <class TYPE> - TYPE* internalGet(component* resp, string& line, size_t* currentPos) - { + TYPE* internalGet(component* resp, string& line, size_t* currentPos) { + const size_t oldPos = *currentPos; - if (!resp->parse(*this, line, currentPos)) - { + if (!resp->parse(*this, line, currentPos)) { + *currentPos = oldPos; - delete (resp); + delete resp; return NULL; } @@ -5702,20 +5746,21 @@ private: return static_cast <TYPE*>(resp); } - const string lastLine() const - { + const string lastLine() const { + // Remove blanks and new lines at the end of the line. string line(m_lastLine); string::const_iterator it = line.end(); int count = 0; - while (it != line.begin()) - { + while (it != line.begin()) { + const unsigned char c = *(it - 1); - if (!(c == ' ' || c == '\t' || c == '\n' || c == '\r')) + if (!(c == ' ' || c == '\t' || c == '\n' || c == '\r')) { break; + } ++count; --it; @@ -5737,19 +5782,16 @@ public: * @return true if the token has been parsed, or false otherwise */ template <class TYPE> - bool check(string& line, size_t* currentPos) - { + bool check(string& line, size_t* currentPos) { + const size_t oldPos = *currentPos; TYPE term; - if (!term.parse(*this, line, currentPos)) - { + if (!term.parse(*this, line, currentPos)) { *currentPos = oldPos; return false; - } - else - { + } else { return true; } } @@ -5765,19 +5807,16 @@ public: * @return true if the token has been parsed, or false otherwise */ template <class TYPE, class ARG_TYPE> - bool checkWithArg(string& line, size_t* currentPos, const ARG_TYPE arg) - { + bool checkWithArg(string& line, size_t* currentPos, const ARG_TYPE arg) { + const size_t oldPos = *currentPos; TYPE term(arg); - if (!term.parse(*this, line, currentPos)) - { + if (!term.parse(*this, line, currentPos)) { *currentPos = oldPos; return false; - } - else - { + } else { return true; } } @@ -5811,12 +5850,11 @@ public: * * @return next line */ - const string readLine() - { + const string readLine() { + size_t pos; - while ((pos = m_buffer.find('\n')) == string::npos) - { + while ((pos = m_buffer.find('\n')) == string::npos) { read(); } @@ -5832,8 +5870,7 @@ public: std::cout << std::endl << "Read line:" << std::endl << line << std::endl; #endif - if (m_tracer) - { + if (m_tracer) { string::size_type len = line.length(); while (len != 0 && (line[len - 1] == '\r' || line[len - 1] == '\n')) --len; m_tracer->traceReceive(line.substr(0, len)); @@ -5845,84 +5882,90 @@ public: /** Fill in the input buffer with data available from the socket stream. * The function blocks until some data is available. */ - void read() - { + void read() { + string receiveBuffer; shared_ptr <timeoutHandler> toh = m_timeoutHandler.lock(); shared_ptr <socket> sok = m_socket.lock(); - if (toh) + if (toh) { toh->resetTimeOut(); + } + + while (receiveBuffer.empty()) { - while (receiveBuffer.empty()) - { // Check whether the time-out delay is elapsed - if (toh && toh->isTimeOut()) - { - if (!toh->handleTimeOut()) + if (toh && toh->isTimeOut()) { + if (!toh->handleTimeOut()) { throw exceptions::operation_timed_out(); + } } // We have received data: reset the time-out counter sok->receive(receiveBuffer); - if (receiveBuffer.empty()) // buffer is empty - { - if (sok->getStatus() & socket::STATUS_WANT_WRITE) + if (receiveBuffer.empty()) { // buffer is empty + + if (sok->getStatus() & socket::STATUS_WANT_WRITE) { sok->waitForWrite(); - else + } else { sok->waitForRead(); + } continue; } // We have received data ... - if (toh) + if (toh) { toh->resetTimeOut(); + } } m_buffer += receiveBuffer; } - void readLiteral(literalHandler::target& buffer, size_t count) - { + void readLiteral(literalHandler::target& buffer, size_t count) { + size_t len = 0; string receiveBuffer; shared_ptr <timeoutHandler> toh = m_timeoutHandler.lock(); shared_ptr <socket> sok = m_socket.lock(); - if (m_progress) + if (m_progress) { m_progress->start(count); + } - if (toh) + if (toh) { toh->resetTimeOut(); + } + + if (!m_buffer.empty()) { + + if (m_buffer.length() > count) { - if (!m_buffer.empty()) - { - if (m_buffer.length() > count) - { buffer.putData(string(m_buffer.begin(), m_buffer.begin() + count)); m_buffer.erase(m_buffer.begin(), m_buffer.begin() + count); len = count; - } - else - { + + } else { + len += m_buffer.length(); buffer.putData(m_buffer); m_buffer.clear(); } } - while (len < count) - { + while (len < count) { + // Check whether the time-out delay is elapsed - if (toh && toh->isTimeOut()) - { - if (!toh->handleTimeOut()) + if (toh && toh->isTimeOut()) { + + if (!toh->handleTimeOut()) { throw exceptions::operation_timed_out(); + } toh->resetTimeOut(); } @@ -5930,22 +5973,24 @@ public: // Receive data from the socket sok->receive(receiveBuffer); - if (receiveBuffer.empty()) // buffer is empty - { - if (sok->getStatus() & socket::STATUS_WANT_WRITE) + if (receiveBuffer.empty()) { // buffer is empty + + if (sok->getStatus() & socket::STATUS_WANT_WRITE) { sok->waitForWrite(); - else + } else { sok->waitForRead(); + } continue; } // We have received data: reset the time-out counter - if (toh) + if (toh) { toh->resetTimeOut(); + } + + if (len + receiveBuffer.length() > count) { - if (len + receiveBuffer.length() > count) - { const size_t remaining = count - len; // Get the needed amount of data @@ -5956,23 +6001,26 @@ public: m_buffer += receiveBuffer; len = count; - } - else - { + + } else { + buffer.putData(receiveBuffer); len += receiveBuffer.length(); } // Notify progress - if (m_progress) + if (m_progress) { m_progress->progress(len, count); + } } - if (m_tracer) + if (m_tracer) { m_tracer->traceReceiveBytes(count); + } - if (m_progress) + if (m_progress) { m_progress->stop(count); + } } }; diff --git a/src/vmime/net/imap/IMAPSStore.cpp b/src/vmime/net/imap/IMAPSStore.cpp index c9e64f5b..dd9c318a 100644 --- a/src/vmime/net/imap/IMAPSStore.cpp +++ b/src/vmime/net/imap/IMAPSStore.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard <[email protected]> +// Copyright (C) 2002 Vincent Richard <[email protected]> // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License as @@ -35,19 +35,22 @@ namespace net { namespace imap { -IMAPSStore::IMAPSStore(shared_ptr <session> sess, shared_ptr <security::authenticator> auth) - : IMAPStore(sess, auth, true) -{ +IMAPSStore::IMAPSStore( + const shared_ptr <session>& sess, + const shared_ptr <security::authenticator>& auth +) + : IMAPStore(sess, auth, true) { + } -IMAPSStore::~IMAPSStore() -{ +IMAPSStore::~IMAPSStore() { + } -const string IMAPSStore::getProtocolName() const -{ +const string IMAPSStore::getProtocolName() const { + return "imaps"; } @@ -58,14 +61,14 @@ const string IMAPSStore::getProtocolName() const IMAPServiceInfos IMAPSStore::sm_infos(true); -const serviceInfos& IMAPSStore::getInfosInstance() -{ +const serviceInfos& IMAPSStore::getInfosInstance() { + return sm_infos; } -const serviceInfos& IMAPSStore::getInfos() const -{ +const serviceInfos& IMAPSStore::getInfos() const { + return sm_infos; } diff --git a/src/vmime/net/imap/IMAPSStore.hpp b/src/vmime/net/imap/IMAPSStore.hpp index 9d27bdd0..e18a067f 100644 --- a/src/vmime/net/imap/IMAPSStore.hpp +++ b/src/vmime/net/imap/IMAPSStore.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard <[email protected]> +// Copyright (C) 2002 Vincent Richard <[email protected]> // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License as @@ -41,12 +41,11 @@ namespace imap { /** IMAPS store service. */ +class VMIME_EXPORT IMAPSStore : public IMAPStore { -class VMIME_EXPORT IMAPSStore : public IMAPStore -{ public: - IMAPSStore(shared_ptr <session> sess, shared_ptr <security::authenticator> auth); + IMAPSStore(const shared_ptr <session>& sess, const shared_ptr <security::authenticator>& auth); ~IMAPSStore(); const string getProtocolName() const; diff --git a/src/vmime/net/imap/IMAPServiceInfos.cpp b/src/vmime/net/imap/IMAPServiceInfos.cpp index 46dbc2e1..baed6ba2 100644 --- a/src/vmime/net/imap/IMAPServiceInfos.cpp +++ b/src/vmime/net/imap/IMAPServiceInfos.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard <[email protected]> +// Copyright (C) 2002 Vincent Richard <[email protected]> // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License as @@ -36,24 +36,24 @@ namespace imap { IMAPServiceInfos::IMAPServiceInfos(const bool imaps) - : m_imaps(imaps) -{ + : m_imaps(imaps) { + } -const string IMAPServiceInfos::getPropertyPrefix() const -{ - if (m_imaps) +const string IMAPServiceInfos::getPropertyPrefix() const { + + if (m_imaps) { return "store.imaps."; - else + } else { return "store.imap."; + } } -const IMAPServiceInfos::props& IMAPServiceInfos::getProperties() const -{ - static props imapProps = - { +const IMAPServiceInfos::props& IMAPServiceInfos::getProperties() const { + + static props imapProps = { // IMAP-specific options #if VMIME_HAVE_SASL_SUPPORT property("options.sasl", serviceInfos::property::TYPE_BOOLEAN, "true"), @@ -73,8 +73,7 @@ const IMAPServiceInfos::props& IMAPServiceInfos::getProperties() const property(serviceInfos::property::SERVER_PORT, "143"), }; - static props imapsProps = - { + static props imapsProps = { // IMAP-specific options #if VMIME_HAVE_SASL_SUPPORT property("options.sasl", serviceInfos::property::TYPE_BOOLEAN, "true"), @@ -98,8 +97,8 @@ const IMAPServiceInfos::props& IMAPServiceInfos::getProperties() const } -const std::vector <serviceInfos::property> IMAPServiceInfos::getAvailableProperties() const -{ +const std::vector <serviceInfos::property> IMAPServiceInfos::getAvailableProperties() const { + std::vector <property> list; const props& p = getProperties(); @@ -114,8 +113,7 @@ const std::vector <serviceInfos::property> IMAPServiceInfos::getAvailablePropert list.push_back(p.PROPERTY_AUTH_PASSWORD); #if VMIME_HAVE_TLS_SUPPORT - if (!m_imaps) - { + if (!m_imaps) { list.push_back(p.PROPERTY_CONNECTION_TLS); list.push_back(p.PROPERTY_CONNECTION_TLS_REQUIRED); } diff --git a/src/vmime/net/imap/IMAPServiceInfos.hpp b/src/vmime/net/imap/IMAPServiceInfos.hpp index 376f4476..73fca7a0 100644 --- a/src/vmime/net/imap/IMAPServiceInfos.hpp +++ b/src/vmime/net/imap/IMAPServiceInfos.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard <[email protected]> +// Copyright (C) 2002 Vincent Richard <[email protected]> // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License as @@ -41,15 +41,13 @@ namespace imap { /** Information about IMAP service. */ +class VMIME_EXPORT IMAPServiceInfos : public serviceInfos { -class VMIME_EXPORT IMAPServiceInfos : public serviceInfos -{ public: IMAPServiceInfos(const bool imaps); - struct props - { + struct props { // IMAP-specific options #if VMIME_HAVE_SASL_SUPPORT serviceInfos::property PROPERTY_OPTIONS_SASL; diff --git a/src/vmime/net/imap/IMAPStore.cpp b/src/vmime/net/imap/IMAPStore.cpp index bf93f284..c10e158d 100644 --- a/src/vmime/net/imap/IMAPStore.cpp +++ b/src/vmime/net/imap/IMAPStore.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard <[email protected]> +// Copyright (C) 2002 Vincent Richard <[email protected]> // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License as @@ -44,130 +44,148 @@ namespace net { namespace imap { -IMAPStore::IMAPStore(shared_ptr <session> sess, shared_ptr <security::authenticator> auth, const bool secured) - : store(sess, getInfosInstance(), auth), m_connection(null), m_isIMAPS(secured) -{ +IMAPStore::IMAPStore( + const shared_ptr <session>& sess, + const shared_ptr <security::authenticator>& auth, + const bool secured +) + : store(sess, getInfosInstance(), auth), + m_connection(null), + m_isIMAPS(secured) { + } -IMAPStore::~IMAPStore() -{ - try - { - if (isConnected()) +IMAPStore::~IMAPStore() { + + try { + + if (isConnected()) { disconnect(); - } - catch (...) - { + } + + } catch (...) { + // Don't throw in destructor } } -const string IMAPStore::getProtocolName() const -{ +const string IMAPStore::getProtocolName() const { + return "imap"; } -shared_ptr <folder> IMAPStore::getRootFolder() -{ - if (!isConnected()) +shared_ptr <folder> IMAPStore::getRootFolder() { + + if (!isConnected()) { throw exceptions::illegal_state("Not connected"); + } - return shared_ptr <IMAPFolder> - (new IMAPFolder(folder::path(), - dynamicCast <IMAPStore>(shared_from_this()), - shared_ptr <folderAttributes>())); + return make_shared <IMAPFolder>( + folder::path(), + dynamicCast <IMAPStore>(shared_from_this()), + shared_ptr <folderAttributes>() + ); } -shared_ptr <folder> IMAPStore::getDefaultFolder() -{ - if (!isConnected()) +shared_ptr <folder> IMAPStore::getDefaultFolder() { + + if (!isConnected()) { throw exceptions::illegal_state("Not connected"); + } - return shared_ptr <IMAPFolder> - (new IMAPFolder(folder::path::component("INBOX"), - dynamicCast <IMAPStore>(shared_from_this()), - shared_ptr <folderAttributes>())); + return make_shared <IMAPFolder>( + folder::path::component("INBOX"), + dynamicCast <IMAPStore>(shared_from_this()), + shared_ptr <folderAttributes>() + ); } -shared_ptr <folder> IMAPStore::getFolder(const folder::path& path) -{ - if (!isConnected()) +shared_ptr <folder> IMAPStore::getFolder(const folder::path& path) { + + if (!isConnected()) { throw exceptions::illegal_state("Not connected"); + } - return shared_ptr <IMAPFolder> - (new IMAPFolder(path, - dynamicCast <IMAPStore>(shared_from_this()), - shared_ptr <folderAttributes>())); + return make_shared <IMAPFolder>( + path, + dynamicCast <IMAPStore>(shared_from_this()), + shared_ptr <folderAttributes>() + ); } -bool IMAPStore::isValidFolderName(const folder::path::component& /* name */) const -{ +bool IMAPStore::isValidFolderName(const folder::path::component& /* name */) const { + return true; } -void IMAPStore::connect() -{ - if (isConnected()) +void IMAPStore::connect() { + + if (isConnected()) { throw exceptions::already_connected(); + } - m_connection = make_shared <IMAPConnection> - (dynamicCast <IMAPStore>(shared_from_this()), getAuthenticator()); + m_connection = make_shared <IMAPConnection>( + dynamicCast <IMAPStore>(shared_from_this()), getAuthenticator() + ); m_connection->connect(); } -bool IMAPStore::isConnected() const -{ - return (m_connection && m_connection->isConnected()); +bool IMAPStore::isConnected() const { + + return m_connection && m_connection->isConnected(); } -bool IMAPStore::isIMAPS() const -{ +bool IMAPStore::isIMAPS() const { + return m_isIMAPS; } -bool IMAPStore::isSecuredConnection() const -{ - if (m_connection == NULL) +bool IMAPStore::isSecuredConnection() const { + + if (!m_connection) { return false; + } return m_connection->isSecuredConnection(); } -shared_ptr <connectionInfos> IMAPStore::getConnectionInfos() const -{ - if (m_connection == NULL) +shared_ptr <connectionInfos> IMAPStore::getConnectionInfos() const { + + if (!m_connection) { return null; + } return m_connection->getConnectionInfos(); } -shared_ptr <IMAPConnection> IMAPStore::getConnection() -{ +shared_ptr <IMAPConnection> IMAPStore::getConnection() { + return m_connection; } -void IMAPStore::disconnect() -{ - if (!isConnected()) +void IMAPStore::disconnect() { + + if (!isConnected()) { throw exceptions::not_connected(); + } for (std::list <IMAPFolder*>::iterator it = m_folders.begin() ; - it != m_folders.end() ; ++it) - { + it != m_folders.end() ; ++it) { + (*it)->onStoreDisconnected(); } @@ -180,60 +198,65 @@ void IMAPStore::disconnect() } -void IMAPStore::noop() -{ - if (!isConnected()) +void IMAPStore::noop() { + + if (!isConnected()) { throw exceptions::not_connected(); + } IMAPCommand::NOOP()->send(m_connection); scoped_ptr <IMAPParser::response> resp(m_connection->readResponse()); if (resp->isBad() || resp->response_done()->response_tagged()-> - resp_cond_state()->status() != IMAPParser::resp_cond_state::OK) - { + resp_cond_state()->status() != IMAPParser::resp_cond_state::OK) { + throw exceptions::command_error("NOOP", resp->getErrorLog()); } for (std::list <IMAPFolder*>::iterator it = m_folders.begin() ; - it != m_folders.end() ; ++it) - { - if ((*it)->isOpen()) + it != m_folders.end() ; ++it) { + + if ((*it)->isOpen()) { (*it)->noop(); + } } } -shared_ptr <IMAPConnection> IMAPStore::connection() -{ - return (m_connection); +shared_ptr <IMAPConnection> IMAPStore::connection() { + + return m_connection; } -void IMAPStore::registerFolder(IMAPFolder* folder) -{ +void IMAPStore::registerFolder(IMAPFolder* folder) { + m_folders.push_back(folder); } -void IMAPStore::unregisterFolder(IMAPFolder* folder) -{ +void IMAPStore::unregisterFolder(IMAPFolder* folder) { + std::list <IMAPFolder*>::iterator it = std::find(m_folders.begin(), m_folders.end(), folder); - if (it != m_folders.end()) m_folders.erase(it); + + if (it != m_folders.end()) { + m_folders.erase(it); + } } -int IMAPStore::getCapabilities() const -{ - return (CAPABILITY_CREATE_FOLDER | - CAPABILITY_RENAME_FOLDER | - CAPABILITY_ADD_MESSAGE | - CAPABILITY_COPY_MESSAGE | - CAPABILITY_DELETE_MESSAGE | - CAPABILITY_PARTIAL_FETCH | - CAPABILITY_MESSAGE_FLAGS | - CAPABILITY_EXTRACT_PART); +int IMAPStore::getCapabilities() const { + + return CAPABILITY_CREATE_FOLDER | + CAPABILITY_RENAME_FOLDER | + CAPABILITY_ADD_MESSAGE | + CAPABILITY_COPY_MESSAGE | + CAPABILITY_DELETE_MESSAGE | + CAPABILITY_PARTIAL_FETCH | + CAPABILITY_MESSAGE_FLAGS | + CAPABILITY_EXTRACT_PART; } @@ -243,14 +266,14 @@ int IMAPStore::getCapabilities() const IMAPServiceInfos IMAPStore::sm_infos(false); -const serviceInfos& IMAPStore::getInfosInstance() -{ +const serviceInfos& IMAPStore::getInfosInstance() { + return sm_infos; } -const serviceInfos& IMAPStore::getInfos() const -{ +const serviceInfos& IMAPStore::getInfos() const { + return sm_infos; } diff --git a/src/vmime/net/imap/IMAPStore.hpp b/src/vmime/net/imap/IMAPStore.hpp index f854fadf..018c195e 100644 --- a/src/vmime/net/imap/IMAPStore.hpp +++ b/src/vmime/net/imap/IMAPStore.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard <[email protected]> +// Copyright (C) 2002 Vincent Richard <[email protected]> // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License as @@ -51,16 +51,20 @@ class IMAPFolder; /** IMAP store service. */ +class VMIME_EXPORT IMAPStore : public store { -class VMIME_EXPORT IMAPStore : public store -{ friend class IMAPFolder; friend class IMAPMessage; friend class IMAPConnection; public: - IMAPStore(shared_ptr <session> sess, shared_ptr <security::authenticator> auth, const bool secured = false); + IMAPStore( + const shared_ptr <session>& sess, + const shared_ptr <security::authenticator>& auth, + const bool secured = false + ); + ~IMAPStore(); const string getProtocolName() const; diff --git a/src/vmime/net/imap/IMAPTag.cpp b/src/vmime/net/imap/IMAPTag.cpp index 14d12788..69f48477 100644 --- a/src/vmime/net/imap/IMAPTag.cpp +++ b/src/vmime/net/imap/IMAPTag.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard <[email protected]> +// Copyright (C) 2002 Vincent Richard <[email protected]> // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License as @@ -39,70 +39,72 @@ const int IMAPTag::sm_maxNumber = 52 * 10 * 10 * 10; IMAPTag::IMAPTag(const int number) - : m_number(number) -{ + : m_number(number) { + m_tag.resize(4); generate(); } IMAPTag::IMAPTag(const IMAPTag& tag) - : object(), m_number(tag.m_number) -{ + : object(), + m_number(tag.m_number) { + m_tag.resize(4); generate(); } IMAPTag::IMAPTag() - : m_number(1) -{ + : m_number(1) { + m_tag.resize(4); generate(); } -IMAPTag& IMAPTag::operator++() -{ +IMAPTag& IMAPTag::operator++() { + ++m_number; - if (m_number >= sm_maxNumber) + if (m_number >= sm_maxNumber) { m_number = 1; + } generate(); - return (*this); + return *this; } -const IMAPTag IMAPTag::operator++(int) -{ +const IMAPTag IMAPTag::operator++(int) { + IMAPTag old(*this); operator++(); - return (old); + return old; } -int IMAPTag::maximumNumber() const -{ +int IMAPTag::maximumNumber() const { + return sm_maxNumber - 1; } -int IMAPTag::number() const -{ - return (m_number); +int IMAPTag::number() const { + + return m_number; } IMAPTag::operator string() const { - return (m_tag); + return m_tag; } -void IMAPTag::generate() -{ +void IMAPTag::generate() { + static const char prefixChars[53] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"; diff --git a/src/vmime/net/imap/IMAPTag.hpp b/src/vmime/net/imap/IMAPTag.hpp index 430a3b10..d4292fde 100644 --- a/src/vmime/net/imap/IMAPTag.hpp +++ b/src/vmime/net/imap/IMAPTag.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard <[email protected]> +// Copyright (C) 2002 Vincent Richard <[email protected]> // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License as @@ -39,8 +39,8 @@ namespace net { namespace imap { -class VMIME_EXPORT IMAPTag : public object -{ +class VMIME_EXPORT IMAPTag : public object { + private: IMAPTag(const int number); diff --git a/src/vmime/net/imap/IMAPUtils.cpp b/src/vmime/net/imap/IMAPUtils.cpp index 6124edcf..353fc2da 100644 --- a/src/vmime/net/imap/IMAPUtils.cpp +++ b/src/vmime/net/imap/IMAPUtils.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard <[email protected]> +// Copyright (C) 2002 Vincent Richard <[email protected]> // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License as @@ -44,8 +44,8 @@ namespace imap { // static -const string IMAPUtils::quoteString(const string& text) -{ +const string IMAPUtils::quoteString(const string& text) { + // // ATOM_CHAR ::= <any CHAR except atom_specials> // @@ -66,66 +66,70 @@ const string IMAPUtils::quoteString(const string& text) bool needQuoting = text.empty(); for (string::const_iterator it = text.begin() ; - !needQuoting && it != text.end() ; ++it) - { - const unsigned char c = *it; + !needQuoting && it != text.end() ; ++it) { - switch (c) - { - case '(': - case ')': - case '{': - case 0x20: // SPACE - case '%': - case '*': - case '"': - case '\\': + const unsigned char c = *it; - needQuoting = true; - break; + switch (c) { - default: + case '(': + case ')': + case '{': + case 0x20: // SPACE + case '%': + case '*': + case '"': + case '\\': - if (c <= 0x1f || c >= 0x7f) needQuoting = true; - } + break; + + default: + + if (c <= 0x1f || c >= 0x7f) { + needQuoting = true; + } + } } - if (needQuoting) - { + if (needQuoting) { + string quoted; quoted.reserve((text.length() * 3) / 2 + 2); quoted += '"'; - for (string::const_iterator it = text.begin() ; it != text.end() ; ++it) - { + for (string::const_iterator it = text.begin() ; it != text.end() ; ++it) { + const unsigned char c = *it; - if (c == '\\' || c == '"') + if (c == '\\' || c == '"') { quoted += '\\'; + } quoted += c; } quoted += '"'; - return (quoted); - } - else - { - return (text); + return quoted; + + } else { + + return text; } } -const string IMAPUtils::pathToString - (const char hierarchySeparator, const folder::path& path) -{ +const string IMAPUtils::pathToString( + const char hierarchySeparator, + const folder::path& path +) { + string result; - for (size_t i = 0 ; i < path.getSize() ; ++i) - { + for (size_t i = 0 ; i < path.getSize() ; ++i) { + if (i > 0) result += hierarchySeparator; result += toModifiedUTF7(hierarchySeparator, path[i]); } @@ -134,33 +138,35 @@ const string IMAPUtils::pathToString } -const folder::path IMAPUtils::stringToPath - (const char hierarchySeparator, const string& str) -{ +const folder::path IMAPUtils::stringToPath( + const char hierarchySeparator, + const string& str +) { + folder::path result; string::const_iterator begin = str.begin(); - for (string::const_iterator it = str.begin() ; it != str.end() ; ++it) - { - if (*it == hierarchySeparator) - { + for (string::const_iterator it = str.begin() ; it != str.end() ; ++it) { + + if (*it == hierarchySeparator) { result /= fromModifiedUTF7(string(begin, it)); begin = it + 1; } } - if (begin != str.end()) - { + if (begin != str.end()) { result /= fromModifiedUTF7(string(begin, str.end())); } - return (result); + return result; } -const string IMAPUtils::toModifiedUTF7 - (const char hierarchySeparator, const folder::path::component& text) -{ +const string IMAPUtils::toModifiedUTF7( + const char hierarchySeparator, + const folder::path::component& text +) { + // We will replace the hierarchy separator with an equivalent // UTF-7 sequence, so we compute it here... const char base64alphabet[] = @@ -192,13 +198,13 @@ const string IMAPUtils::toModifiedUTF7 size_t remaining = cvt.length(); - for (size_t i = 0, len = cvt.length() ; i < len ; ) - { + for (size_t i = 0, len = cvt.length() ; i < len ; ) { + const unsigned char c = cvt[i]; // Replace hierarchy separator with an equivalent UTF-7 Base64 sequence - if (!base64 && c == hierarchySeparator) - { + if (!base64 && c == hierarchySeparator) { + out += "&" + hsUTF7 + "-"; ++i; @@ -209,72 +215,78 @@ const string IMAPUtils::toModifiedUTF7 size_t n = 0; int ch = 0; - if (c < 0x80) + if (c < 0x80) { ch = c, n = 0; - else if (c < 0xc2) + } else if (c < 0xc2) { return ""; - else if (c < 0xe0) + } else if (c < 0xe0) { ch = c & 0x1f, n = 1; - else if (c < 0xf0) + } else if (c < 0xf0) { ch = c & 0x0f, n = 2; - else if (c < 0xf8) + } else if (c < 0xf8) { ch = c & 0x07, n = 3; - else if (c < 0xfc) + } else if (c < 0xfc) { ch = c & 0x03, n = 4; - else if (c < 0xfe) + } else if (c < 0xfe) { ch = c & 0x01, n = 5; - else + } else { return ""; + } - if (n > remaining) + if (n > remaining) { return ""; // error + } ++i; --remaining; - for (size_t j = 0 ; j < n ; j++) - { - if ((cvt[i + j] & 0xc0) != 0x80) + for (size_t j = 0 ; j < n ; j++) { + + if ((cvt[i + j] & 0xc0) != 0x80) { return ""; // error + } ch = (ch << 6) | (cvt[i + j] & 0x3f); } - if (n > 1 && !(ch >> (n * 5 + 1))) + if (n > 1 && !(ch >> (n * 5 + 1))) { return ""; // error + } i += n; remaining -= n; - if (ch < 0x20 || ch >= 0x7f) - { - if (!base64) - { + if (ch < 0x20 || ch >= 0x7f) { + + if (!base64) { out += '&'; base64 = true; b = 0; k = 10; } - if (ch & ~0xffff) + if (ch & ~0xffff) { ch = 0xfffe; + } out += base64alphabet[b | ch >> k]; k -= 6; - for ( ; k >= 0 ; k -= 6) + for ( ; k >= 0 ; k -= 6) { out += base64alphabet[(ch >> k) & 0x3f]; + } b = (ch << (-k)) & 0x3f; k += 16; - } - else - { - if (base64) - { - if (k > 10) + + } else { + + if (base64) { + + if (k > 10) { out += base64alphabet[b]; + } out += '-'; base64 = false; @@ -282,15 +294,17 @@ const string IMAPUtils::toModifiedUTF7 out += static_cast <char>(ch); - if (ch == '&') + if (ch == '&') { out += '-'; + } } } - if (base64) - { - if (k > 10) + if (base64) { + + if (k > 10) { out += base64alphabet[b]; + } out += '-'; } @@ -299,8 +313,8 @@ const string IMAPUtils::toModifiedUTF7 } -const folder::path::component IMAPUtils::fromModifiedUTF7(const string& text) -{ +const folder::path::component IMAPUtils::fromModifiedUTF7(const string& text) { + // Transcode from modified UTF-7 (RFC-2060). string out; out.reserve(text.length()); @@ -309,62 +323,57 @@ const folder::path::component IMAPUtils::fromModifiedUTF7(const string& text) bool plusOutput = false; unsigned char prev = 0; - for (string::const_iterator it = text.begin() ; it != text.end() ; ++it) - { + for (string::const_iterator it = text.begin() ; it != text.end() ; ++it) { + const unsigned char c = *it; - switch (c) - { - // Start of Base64 sequence - case '&': - { - if (!inB64sequence) - { - inB64sequence = true; - plusOutput = false; - } - else - { - out += '&'; + switch (c) { + + // Start of Base64 sequence + case '&': { + + if (!inB64sequence) { + inB64sequence = true; + plusOutput = false; + } else { + out += '&'; + } + + break; } + // End of Base64 sequence (or "&-" --> "&") + case '-': { - break; - } - // End of Base64 sequence (or "&-" --> "&") - case '-': - { - if (inB64sequence && prev == '&') // special case "&-" --> "&" - out += '&'; - else - out += '-'; + if (inB64sequence && prev == '&') { // special case "&-" --> "&" + out += '&'; + } else { + out += '-'; + } - inB64sequence = false; - break; - } - // ',' is used instead of '/' in modified Base64 - case ',': - { - if (inB64sequence && !plusOutput) - { - out += '+'; - plusOutput = true; + inB64sequence = false; + break; } + // ',' is used instead of '/' in modified Base64 + case ',': { - out += (inB64sequence ? '/' : ','); - break; - } - default: - { - if (inB64sequence && !plusOutput) - { - out += '+'; - plusOutput = true; + if (inB64sequence && !plusOutput) { + out += '+'; + plusOutput = true; + } + + out += (inB64sequence ? '/' : ','); + break; } + default: { - out += c; - break; - } + if (inB64sequence && !plusOutput) { + out += '+'; + plusOutput = true; + } + out += c; + break; + } } prev = c; @@ -372,94 +381,96 @@ const folder::path::component IMAPUtils::fromModifiedUTF7(const string& text) // Store it as UTF-8 by default string cvt; - charset::convert(out, cvt, - charset(charsets::UTF_7), charset(charsets::UTF_8)); + charset::convert(out, cvt, charset(charsets::UTF_7), charset(charsets::UTF_8)); - return (folder::path::component(cvt, charset(charsets::UTF_8))); + return folder::path::component(cvt, charset(charsets::UTF_8)); } // static -void IMAPUtils::mailboxFlagsToFolderAttributes - (shared_ptr <const IMAPConnection> cnt, const IMAPParser::mailbox_flag_list* list, - folderAttributes& attribs) -{ +void IMAPUtils::mailboxFlagsToFolderAttributes( + const shared_ptr <const IMAPConnection>& cnt, + const IMAPParser::mailbox_flag_list* list, + folderAttributes& attribs +) { + int specialUse = folderAttributes::SPECIALUSE_NONE; int type = folderAttributes::TYPE_CONTAINS_MESSAGES | folderAttributes::TYPE_CONTAINS_FOLDERS; int flags = 0; // If CHILDREN extension (RFC-3348) is not supported, assume folder has children // as we have no hint about it - if (!cnt->hasCapability("CHILDREN")) + if (!cnt->hasCapability("CHILDREN")) { flags |= folderAttributes::FLAG_HAS_CHILDREN; + } const std::vector <IMAPParser::mailbox_flag*>& mailboxFlags = list->flags(); for (std::vector <IMAPParser::mailbox_flag*>::const_iterator it = mailboxFlags.begin() ; - it != mailboxFlags.end() ; ++it) - { - switch ((*it)->type()) - { - case IMAPParser::mailbox_flag::NOSELECT: + it != mailboxFlags.end() ; ++it) { + + switch ((*it)->type()) { + + case IMAPParser::mailbox_flag::NOSELECT: - type &= ~folderAttributes::TYPE_CONTAINS_MESSAGES; - flags |= folderAttributes::FLAG_NO_OPEN; - break; + type &= ~folderAttributes::TYPE_CONTAINS_MESSAGES; + flags |= folderAttributes::FLAG_NO_OPEN; + break; - case IMAPParser::mailbox_flag::NOINFERIORS: - case IMAPParser::mailbox_flag::HASNOCHILDREN: + case IMAPParser::mailbox_flag::NOINFERIORS: + case IMAPParser::mailbox_flag::HASNOCHILDREN: - flags &= ~folderAttributes::FLAG_HAS_CHILDREN; - break; + flags &= ~folderAttributes::FLAG_HAS_CHILDREN; + break; - case IMAPParser::mailbox_flag::HASCHILDREN: + case IMAPParser::mailbox_flag::HASCHILDREN: - flags |= folderAttributes::FLAG_HAS_CHILDREN; - break; + flags |= folderAttributes::FLAG_HAS_CHILDREN; + break; - case IMAPParser::mailbox_flag::SPECIALUSE_ALL: + case IMAPParser::mailbox_flag::SPECIALUSE_ALL: - specialUse = folderAttributes::SPECIALUSE_ALL; - break; + specialUse = folderAttributes::SPECIALUSE_ALL; + break; - case IMAPParser::mailbox_flag::SPECIALUSE_ARCHIVE: + case IMAPParser::mailbox_flag::SPECIALUSE_ARCHIVE: - specialUse = folderAttributes::SPECIALUSE_ARCHIVE; - break; + specialUse = folderAttributes::SPECIALUSE_ARCHIVE; + break; - case IMAPParser::mailbox_flag::SPECIALUSE_DRAFTS: + case IMAPParser::mailbox_flag::SPECIALUSE_DRAFTS: - specialUse = folderAttributes::SPECIALUSE_DRAFTS; - break; + specialUse = folderAttributes::SPECIALUSE_DRAFTS; + break; - case IMAPParser::mailbox_flag::SPECIALUSE_FLAGGED: + case IMAPParser::mailbox_flag::SPECIALUSE_FLAGGED: - specialUse = folderAttributes::SPECIALUSE_FLAGGED; - break; + specialUse = folderAttributes::SPECIALUSE_FLAGGED; + break; - case IMAPParser::mailbox_flag::SPECIALUSE_JUNK: + case IMAPParser::mailbox_flag::SPECIALUSE_JUNK: - specialUse = folderAttributes::SPECIALUSE_JUNK; - break; + specialUse = folderAttributes::SPECIALUSE_JUNK; + break; - case IMAPParser::mailbox_flag::SPECIALUSE_SENT: + case IMAPParser::mailbox_flag::SPECIALUSE_SENT: - specialUse = folderAttributes::SPECIALUSE_SENT; - break; + specialUse = folderAttributes::SPECIALUSE_SENT; + break; - case IMAPParser::mailbox_flag::SPECIALUSE_TRASH: + case IMAPParser::mailbox_flag::SPECIALUSE_TRASH: - specialUse = folderAttributes::SPECIALUSE_TRASH; - break; + specialUse = folderAttributes::SPECIALUSE_TRASH; + break; - case IMAPParser::mailbox_flag::SPECIALUSE_IMPORTANT: + case IMAPParser::mailbox_flag::SPECIALUSE_IMPORTANT: - specialUse = folderAttributes::SPECIALUSE_IMPORTANT; - break; + specialUse = folderAttributes::SPECIALUSE_IMPORTANT; + break; - default: + default: - break; + break; } } @@ -469,49 +480,60 @@ void IMAPUtils::mailboxFlagsToFolderAttributes } -int IMAPUtils::messageFlagsFromFlags(const IMAPParser::flag_list* list) -{ +int IMAPUtils::messageFlagsFromFlags(const IMAPParser::flag_list* list) { + const std::vector <IMAPParser::flag*>& flagList = list->flags(); int flags = 0; for (std::vector <IMAPParser::flag*>::const_iterator - it = flagList.begin() ; it != flagList.end() ; ++it) - { - switch ((*it)->type()) - { - case IMAPParser::flag::ANSWERED: - flags |= message::FLAG_REPLIED; - break; - case IMAPParser::flag::FLAGGED: - flags |= message::FLAG_MARKED; - break; - case IMAPParser::flag::DELETED: - flags |= message::FLAG_DELETED; - break; - case IMAPParser::flag::SEEN: - flags |= message::FLAG_SEEN; - break; - case IMAPParser::flag::DRAFT: - flags |= message::FLAG_DRAFT; - break; - - default: - //case IMAPParser::flag::UNKNOWN: - break; + it = flagList.begin() ; it != flagList.end() ; ++it) { + + switch ((*it)->type()) { + + case IMAPParser::flag::ANSWERED: + + flags |= message::FLAG_REPLIED; + break; + + case IMAPParser::flag::FLAGGED: + + flags |= message::FLAG_MARKED; + break; + + case IMAPParser::flag::DELETED: + + flags |= message::FLAG_DELETED; + break; + + case IMAPParser::flag::SEEN: + + flags |= message::FLAG_SEEN; + break; + + case IMAPParser::flag::DRAFT: + + flags |= message::FLAG_DRAFT; + break; + + default: + //case IMAPParser::flag::UNKNOWN: + + break; } } - return (flags); + return flags; } // static -const std::vector <string> IMAPUtils::messageFlagList(const int flags) -{ +const std::vector <string> IMAPUtils::messageFlagList(const int flags) { + std::vector <string> flagList; - if (flags == -1) + if (flags == -1) { return flagList; // default flags + } if (flags & message::FLAG_REPLIED) flagList.push_back("\\Answered"); if (flags & message::FLAG_MARKED) flagList.push_back("\\Flagged"); @@ -524,8 +546,8 @@ const std::vector <string> IMAPUtils::messageFlagList(const int flags) // static -const string IMAPUtils::dateTime(const vmime::datetime& date) -{ +const string IMAPUtils::dateTime(const vmime::datetime& date) { + std::ostringstream res; res.imbue(std::locale::classic()); @@ -545,9 +567,10 @@ const string IMAPUtils::dateTime(const vmime::datetime& date) res << '-'; - static const char* monthNames[12] = - { "Jan", "Feb", "Mar", "Apr", "May", "Jun", - "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" }; + static const char* monthNames[12] = { + "Jan", "Feb", "Mar", "Apr", "May", "Jun", + "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" + }; res << monthNames[std::min(std::max(date.getMonth() - 1, 0), 11)]; @@ -587,15 +610,17 @@ const string IMAPUtils::dateTime(const vmime::datetime& date) res << '"'; - - return (res.str()); + return res.str(); } // static -shared_ptr <IMAPCommand> IMAPUtils::buildFetchCommand - (shared_ptr <IMAPConnection> cnt, const messageSet& msgs, const fetchAttributes& options) -{ +shared_ptr <IMAPCommand> IMAPUtils::buildFetchCommand( + const shared_ptr <IMAPConnection>& cnt, + const messageSet& msgs, + const fetchAttributes& options +) { + // Example: // C: A654 FETCH 2:4 (FLAGS BODY[HEADER.FIELDS (DATE FROM)]) // S: * 2 FETCH .... @@ -605,38 +630,45 @@ shared_ptr <IMAPCommand> IMAPUtils::buildFetchCommand std::vector <string> items; - if (options.has(fetchAttributes::SIZE)) + if (options.has(fetchAttributes::SIZE)) { items.push_back("RFC822.SIZE"); + } - if (options.has(fetchAttributes::FLAGS)) + if (options.has(fetchAttributes::FLAGS)) { items.push_back("FLAGS"); + } - if (options.has(fetchAttributes::STRUCTURE)) + if (options.has(fetchAttributes::STRUCTURE)) { items.push_back("BODYSTRUCTURE"); + } + + if (options.has(fetchAttributes::UID)) { - if (options.has(fetchAttributes::UID)) - { items.push_back("UID"); // Also fetch MODSEQ if CONDSTORE is supported - if (cnt && cnt->hasCapability("CONDSTORE") && !cnt->isMODSEQDisabled()) + if (cnt && cnt->hasCapability("CONDSTORE") && !cnt->isMODSEQDisabled()) { items.push_back("MODSEQ"); + } } - if (options.has(fetchAttributes::FULL_HEADER)) + if (options.has(fetchAttributes::FULL_HEADER)) { + items.push_back("RFC822.HEADER"); - else - { - if (options.has(fetchAttributes::ENVELOPE)) + + } else { + + if (options.has(fetchAttributes::ENVELOPE)) { items.push_back("ENVELOPE"); + } std::vector <string> headerFields; - if (options.has(fetchAttributes::CONTENT_INFO)) + if (options.has(fetchAttributes::CONTENT_INFO)) { headerFields.push_back("CONTENT_TYPE"); + } - if (options.has(fetchAttributes::IMPORTANCE)) - { + if (options.has(fetchAttributes::IMPORTANCE)) { headerFields.push_back("IMPORTANCE"); headerFields.push_back("X-PRIORITY"); } @@ -645,15 +677,16 @@ shared_ptr <IMAPCommand> IMAPUtils::buildFetchCommand const std::vector <string> customHeaderFields = options.getHeaderFields(); std::copy(customHeaderFields.begin(), customHeaderFields.end(), std::back_inserter(headerFields)); - if (!headerFields.empty()) - { + if (!headerFields.empty()) { + string list; for (std::vector <string>::iterator it = headerFields.begin() ; - it != headerFields.end() ; ++it) - { - if (it != headerFields.begin()) + it != headerFields.end() ; ++it) { + + if (it != headerFields.begin()) { list += " "; + } list += *it; } @@ -667,12 +700,14 @@ shared_ptr <IMAPCommand> IMAPUtils::buildFetchCommand // static -void IMAPUtils::convertAddressList - (const IMAPParser::address_list& src, mailboxList& dest) -{ +void IMAPUtils::convertAddressList( + const IMAPParser::address_list& src, + mailboxList& dest +) { + for (std::vector <IMAPParser::address*>::const_iterator - it = src.addresses().begin() ; it != src.addresses().end() ; ++it) - { + it = src.addresses().begin() ; it != src.addresses().end() ; ++it) { + const IMAPParser::address& addr = **it; text name; @@ -687,47 +722,52 @@ void IMAPUtils::convertAddressList -class IMAPUIDMessageSetEnumerator : public messageSetEnumerator -{ +class IMAPUIDMessageSetEnumerator : public messageSetEnumerator { + public: IMAPUIDMessageSetEnumerator() - : m_first(true) - { + : m_first(true) { + + m_oss.imbue(std::locale::classic()); } - void enumerateNumberMessageRange(const vmime::net::numberMessageRange& range) - { - if (!m_first) + void enumerateNumberMessageRange(const vmime::net::numberMessageRange& range) { + + if (!m_first) { m_oss << ","; + } - if (range.getFirst() == range.getLast()) + if (range.getFirst() == range.getLast()) { m_oss << range.getFirst(); - else if (range.getLast() == size_t(-1)) + } else if (range.getLast() == size_t(-1)) { m_oss << range.getFirst() << ":*"; - else + } else { m_oss << range.getFirst() << ":" << range.getLast(); + } m_first = false; } - void enumerateUIDMessageRange(const vmime::net::UIDMessageRange& range) - { - if (!m_first) + void enumerateUIDMessageRange(const vmime::net::UIDMessageRange& range) { + + if (!m_first) { m_oss << ","; + } - if (range.getFirst() == range.getLast()) + if (range.getFirst() == range.getLast()) { m_oss << range.getFirst(); - else if (range.getLast() == size_t(-1)) + } else if (range.getLast() == size_t(-1)) { m_oss << range.getFirst() << ":*"; - else + } else { m_oss << range.getFirst() << ":" << range.getLast(); + } m_first = false; } - const std::string str() const - { + const std::string str() const { + return m_oss.str(); } @@ -738,23 +778,24 @@ private: }; -class IMAPMessageSetEnumerator : public messageSetEnumerator -{ +class IMAPMessageSetEnumerator : public messageSetEnumerator { + public: - void enumerateNumberMessageRange(const vmime::net::numberMessageRange& range) - { - for (size_t i = range.getFirst(), last = range.getLast() ; i <= last ; ++i) + void enumerateNumberMessageRange(const vmime::net::numberMessageRange& range) { + + for (size_t i = range.getFirst(), last = range.getLast() ; i <= last ; ++i) { m_list.push_back(i); + } } - void enumerateUIDMessageRange(const vmime::net::UIDMessageRange& /* range */) - { + void enumerateUIDMessageRange(const vmime::net::UIDMessageRange& /* range */) { + // Not used } - const std::vector <size_t>& list() const - { + const std::vector <size_t>& list() const { + return m_list; } @@ -766,8 +807,8 @@ public: // static -const string IMAPUtils::messageSetToSequenceSet(const messageSet& msgs) -{ +const string IMAPUtils::messageSetToSequenceSet(const messageSet& msgs) { + IMAPUIDMessageSetEnumerator en; msgs.enumerate(en); @@ -776,22 +817,28 @@ const string IMAPUtils::messageSetToSequenceSet(const messageSet& msgs) // static -messageSet IMAPUtils::buildMessageSet(const IMAPParser::uid_set* uidSet) -{ +messageSet IMAPUtils::buildMessageSet(const IMAPParser::uid_set* uidSet) { + messageSet set = messageSet::empty(); - for ( ; uidSet ; uidSet = uidSet->next_uid_set()) - { - if (uidSet->uid_range()) - { - set.addRange(UIDMessageRange - (message::uid(uidSet->uid_range()->uniqueid1()->value()), - message::uid(uidSet->uid_range()->uniqueid2()->value()))); - } - else - { - set.addRange(UIDMessageRange - (message::uid(uidSet->uniqueid()->value()))); + for ( ; uidSet ; uidSet = uidSet->next_uid_set()) { + + if (uidSet->uid_range()) { + + set.addRange( + UIDMessageRange( + message::uid(uidSet->uid_range()->uniqueid1()->value()), + message::uid(uidSet->uid_range()->uniqueid2()->value()) + ) + ); + + } else { + + set.addRange( + UIDMessageRange( + message::uid(uidSet->uniqueid()->value()) + ) + ); } } diff --git a/src/vmime/net/imap/IMAPUtils.hpp b/src/vmime/net/imap/IMAPUtils.hpp index 6140855d..957ff846 100644 --- a/src/vmime/net/imap/IMAPUtils.hpp +++ b/src/vmime/net/imap/IMAPUtils.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard <[email protected]> +// Copyright (C) 2002 Vincent Richard <[email protected]> // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License as @@ -74,7 +74,7 @@ public: * @param attribs reference to an object holding folder attributes */ static void mailboxFlagsToFolderAttributes - (shared_ptr <const IMAPConnection> cnt, + (const shared_ptr <const IMAPConnection>& cnt, const IMAPParser::mailbox_flag_list* list, folderAttributes& attribs); @@ -98,7 +98,7 @@ public: * @return fetch request */ static shared_ptr <IMAPCommand> buildFetchCommand - (shared_ptr <IMAPConnection> cnt, const messageSet& msgs, const fetchAttributes& options); + (const shared_ptr <IMAPConnection>& cnt, const messageSet& msgs, const fetchAttributes& options); /** Convert a parser-style address list to a mailbox list. * @@ -124,7 +124,7 @@ public: private: static const string buildFetchRequestImpl - (shared_ptr <IMAPConnection> cnt, const string& mode, const string& set, const int options); + (const shared_ptr <IMAPConnection>& cnt, const string& mode, const string& set, const int options); }; diff --git a/src/vmime/net/imap/imap.hpp b/src/vmime/net/imap/imap.hpp index 5e10619a..f25baa4b 100644 --- a/src/vmime/net/imap/imap.hpp +++ b/src/vmime/net/imap/imap.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard <[email protected]> +// Copyright (C) 2002 Vincent Richard <[email protected]> // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License as diff --git a/src/vmime/net/maildir/format/courierMaildirFormat.cpp b/src/vmime/net/maildir/format/courierMaildirFormat.cpp index 6d460d5e..e6119490 100644 --- a/src/vmime/net/maildir/format/courierMaildirFormat.cpp +++ b/src/vmime/net/maildir/format/courierMaildirFormat.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard <[email protected]> +// Copyright (C) 2002 Vincent Richard <[email protected]> // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License as @@ -41,34 +41,39 @@ namespace maildir { namespace format { -courierMaildirFormat::courierMaildirFormat(shared_ptr <context> ctx) - : maildirFormat(ctx) -{ +courierMaildirFormat::courierMaildirFormat(const shared_ptr <context>& ctx) + : maildirFormat(ctx) { + } -const string courierMaildirFormat::getName() const -{ +const string courierMaildirFormat::getName() const { + return "courier"; } -void courierMaildirFormat::createFolder(const folder::path& path) -{ +void courierMaildirFormat::createFolder(const folder::path& path) { + shared_ptr <utility::fileSystemFactory> fsf = platform::getHandler()->getFileSystemFactory(); - if (!fsf->isValidPath(folderPathToFileSystemPath(path, ROOT_DIRECTORY))) + if (!fsf->isValidPath(folderPathToFileSystemPath(path, ROOT_DIRECTORY))) { throw exceptions::invalid_folder_name(); + } - shared_ptr <utility::file> rootDir = fsf->create - (folderPathToFileSystemPath(path, ROOT_DIRECTORY)); + shared_ptr <utility::file> rootDir = fsf->create( + folderPathToFileSystemPath(path, ROOT_DIRECTORY) + ); - shared_ptr <utility::file> newDir = fsf->create - (folderPathToFileSystemPath(path, NEW_DIRECTORY)); - shared_ptr <utility::file> tmpDir = fsf->create - (folderPathToFileSystemPath(path, TMP_DIRECTORY)); - shared_ptr <utility::file> curDir = fsf->create - (folderPathToFileSystemPath(path, CUR_DIRECTORY)); + shared_ptr <utility::file> newDir = fsf->create( + folderPathToFileSystemPath(path, NEW_DIRECTORY) + ); + shared_ptr <utility::file> tmpDir = fsf->create( + folderPathToFileSystemPath(path, TMP_DIRECTORY) + ); + shared_ptr <utility::file> curDir = fsf->create( + folderPathToFileSystemPath(path, CUR_DIRECTORY) + ); rootDir->createDirectory(true); @@ -76,40 +81,45 @@ void courierMaildirFormat::createFolder(const folder::path& path) tmpDir->createDirectory(false); curDir->createDirectory(false); - shared_ptr <utility::file> maildirFile = fsf->create - (folderPathToFileSystemPath(path, ROOT_DIRECTORY) - / utility::file::path::component("maildirfolder")); + shared_ptr <utility::file> maildirFile = fsf->create( + folderPathToFileSystemPath(path, ROOT_DIRECTORY) + / utility::file::path::component("maildirfolder") + ); maildirFile->createFile(); } -void courierMaildirFormat::destroyFolder(const folder::path& path) -{ +void courierMaildirFormat::destroyFolder(const folder::path& path) { + shared_ptr <utility::fileSystemFactory> fsf = platform::getHandler()->getFileSystemFactory(); // Recursively delete directories of subfolders const std::vector <folder::path> folders = listFolders(path, true); - for (std::vector <folder::path>::size_type i = 0, n = folders.size() ; i < n ; ++i) - { - maildirUtils::recursiveFSDelete(fsf->create - (folderPathToFileSystemPath(folders[i], ROOT_DIRECTORY))); + for (std::vector <folder::path>::size_type i = 0, n = folders.size() ; i < n ; ++i) { + + maildirUtils::recursiveFSDelete( + fsf->create(folderPathToFileSystemPath(folders[i], ROOT_DIRECTORY)) + ); } // Recursively delete the directory of this folder - maildirUtils::recursiveFSDelete(fsf->create - (folderPathToFileSystemPath(path, ROOT_DIRECTORY))); + maildirUtils::recursiveFSDelete( + fsf->create(folderPathToFileSystemPath(path, ROOT_DIRECTORY)) + ); } -void courierMaildirFormat::renameFolder - (const folder::path& oldPath, const folder::path& newPath) -{ +void courierMaildirFormat::renameFolder( + const folder::path& oldPath, + const folder::path& newPath +) { + const std::vector <folder::path> folders = listFolders(oldPath, true); - for (std::vector <folder::path>::size_type i = 0, n = folders.size() ; i < n ; ++i) - { + for (std::vector <folder::path>::size_type i = 0, n = folders.size() ; i < n ; ++i) { + const folder::path folderOldPath = folders[i]; folder::path folderNewPath = folderOldPath; @@ -122,9 +132,11 @@ void courierMaildirFormat::renameFolder } -void courierMaildirFormat::renameFolderImpl - (const folder::path& oldPath, const folder::path& newPath) -{ +void courierMaildirFormat::renameFolderImpl( + const folder::path& oldPath, + const folder::path& newPath +) { + shared_ptr <utility::fileSystemFactory> fsf = platform::getHandler()->getFileSystemFactory(); const utility::file::path oldFSPath = @@ -138,98 +150,109 @@ void courierMaildirFormat::renameFolderImpl } -bool courierMaildirFormat::folderExists(const folder::path& path) const -{ - shared_ptr <utility::fileSystemFactory> fsf = platform::getHandler()->getFileSystemFactory(); - - shared_ptr <utility::file> rootDir = fsf->create - (folderPathToFileSystemPath(path, ROOT_DIRECTORY)); +bool courierMaildirFormat::folderExists(const folder::path& path) const { - shared_ptr <utility::file> newDir = fsf->create - (folderPathToFileSystemPath(path, NEW_DIRECTORY)); - shared_ptr <utility::file> tmpDir = fsf->create - (folderPathToFileSystemPath(path, TMP_DIRECTORY)); - shared_ptr <utility::file> curDir = fsf->create - (folderPathToFileSystemPath(path, CUR_DIRECTORY)); + shared_ptr <utility::fileSystemFactory> fsf = platform::getHandler()->getFileSystemFactory(); - shared_ptr <utility::file> maildirFile = fsf->create - (folderPathToFileSystemPath(path, ROOT_DIRECTORY) - / utility::file::path::component("maildirfolder")); + shared_ptr <utility::file> rootDir = fsf->create( + folderPathToFileSystemPath(path, ROOT_DIRECTORY) + ); + + shared_ptr <utility::file> newDir = fsf->create( + folderPathToFileSystemPath(path, NEW_DIRECTORY) + ); + shared_ptr <utility::file> tmpDir = fsf->create( + folderPathToFileSystemPath(path, TMP_DIRECTORY) + ); + shared_ptr <utility::file> curDir = fsf->create( + folderPathToFileSystemPath(path, CUR_DIRECTORY) + ); + + shared_ptr <utility::file> maildirFile = fsf->create( + folderPathToFileSystemPath(path, ROOT_DIRECTORY) + / utility::file::path::component("maildirfolder") + ); bool exists = rootDir->exists() && rootDir->isDirectory() && - newDir->exists() && newDir->isDirectory() && - tmpDir->exists() && tmpDir->isDirectory() && - curDir->exists() && curDir->isDirectory(); + newDir->exists() && newDir->isDirectory() && + tmpDir->exists() && tmpDir->isDirectory() && + curDir->exists() && curDir->isDirectory(); // If this is not the root folder, then a file named "maildirfolder" // must also be present in the directory - if (!path.isRoot()) + if (!path.isRoot()) { exists = exists && maildirFile->exists() && maildirFile->isFile(); + } return exists; } -bool courierMaildirFormat::folderHasSubfolders(const folder::path& path) const -{ +bool courierMaildirFormat::folderHasSubfolders(const folder::path& path) const { + std::vector <string> dirs; return listDirectories(path, dirs, true); } -const utility::file::path courierMaildirFormat::folderPathToFileSystemPath - (const folder::path& path, const DirectoryType type) const -{ +const utility::file::path courierMaildirFormat::folderPathToFileSystemPath( + const folder::path& path, + const DirectoryType type +) const { + // Virtual folder "/MyFolder/SubFolder" corresponds to physical // directory "[store root]/.MyFolder.SubFolder" utility::file::path fsPath = getContext()->getStore()->getFileSystemPath(); - if (!path.isRoot()) - { + if (!path.isRoot()) { + string folderComp; - for (size_t i = 0, n = path.getSize() ; i < n ; ++i) + for (size_t i = 0, n = path.getSize() ; i < n ; ++i) { folderComp += "." + toModifiedUTF7(path[i]); + } fsPath /= utility::file::path::component(folderComp); } // Last component - switch (type) - { - case ROOT_DIRECTORY: + switch (type) { - // Nothing to add - break; + case ROOT_DIRECTORY: - case NEW_DIRECTORY: + // Nothing to add + break; - fsPath /= NEW_DIR; - break; + case NEW_DIRECTORY: - case CUR_DIRECTORY: + fsPath /= NEW_DIR; + break; - fsPath /= CUR_DIR; - break; + case CUR_DIRECTORY: - case TMP_DIRECTORY: + fsPath /= CUR_DIR; + break; - fsPath /= TMP_DIR; - break; + case TMP_DIRECTORY: - case CONTAINER_DIRECTORY: + fsPath /= TMP_DIR; + break; - // Not used - break; + case CONTAINER_DIRECTORY: + + // Not used + break; } return fsPath; } -const std::vector <folder::path> courierMaildirFormat::listFolders - (const folder::path& root, const bool recursive) const -{ +const std::vector <folder::path> courierMaildirFormat::listFolders( + const folder::path& root, + const bool recursive +) const { + // First, list directories std::vector <string> dirs; listDirectories(root, dirs, false); @@ -237,69 +260,75 @@ const std::vector <folder::path> courierMaildirFormat::listFolders // Then, map directories to folders std::vector <folder::path> folders; - for (std::vector <string>::size_type i = 0, n = dirs.size() ; i < n ; ++i) - { + for (std::vector <string>::size_type i = 0, n = dirs.size() ; i < n ; ++i) { + const string dir = dirs[i].substr(1) + "."; folder::path path; for (size_t pos = dir.find("."), prev = 0 ; - pos != string::npos ; prev = pos + 1, pos = dir.find(".", pos + 1)) - { + pos != string::npos ; prev = pos + 1, pos = dir.find(".", pos + 1)) { + const string comp = dir.substr(prev, pos - prev); path /= fromModifiedUTF7(comp); } - if (recursive || path.getSize() == root.getSize() + 1) + if (recursive || path.getSize() == root.getSize() + 1) { folders.push_back(path); + } } return folders; } -bool courierMaildirFormat::listDirectories(const folder::path& root, - std::vector <string>& dirs, const bool onlyTestForExistence) const -{ +bool courierMaildirFormat::listDirectories( + const folder::path& root, + std::vector <string>& dirs, + const bool onlyTestForExistence +) const { + shared_ptr <utility::fileSystemFactory> fsf = platform::getHandler()->getFileSystemFactory(); - shared_ptr <utility::file> rootDir = fsf->create - (getContext()->getStore()->getFileSystemPath()); + shared_ptr <utility::file> rootDir = fsf->create( + getContext()->getStore()->getFileSystemPath() + ); + + if (rootDir->exists()) { - if (rootDir->exists()) - { // To speed up things, and if we are not searching in root folder, // search for directories with a common prefix string base; - if (!root.isRoot()) - { - for (size_t i = 0, n = root.getSize() ; i < n ; ++i) + if (!root.isRoot()) { + for (size_t i = 0, n = root.getSize() ; i < n ; ++i) { base += "." + toModifiedUTF7(root[i]); + } } // Enumerate directories shared_ptr <utility::fileIterator> it = rootDir->getFiles(); - while (it->hasMoreElements()) - { + while (it->hasMoreElements()) { + shared_ptr <utility::file> file = it->nextElement(); - if (isSubfolderDirectory(*file)) - { + if (isSubfolderDirectory(*file)) { + const string dir = file->getFullPath().getLastComponent().getBuffer(); - if (base.empty() || (dir.length() > base.length() && dir.substr(0, base.length()) == base)) - { + if (base.empty() || (dir.length() > base.length() && dir.substr(0, base.length()) == base)) { + dirs.push_back(dir); - if (onlyTestForExistence) + if (onlyTestForExistence) { return true; + } } } } - } - else - { + + } else { + // No sub-folder } @@ -310,13 +339,13 @@ bool courierMaildirFormat::listDirectories(const folder::path& root, // static -bool courierMaildirFormat::isSubfolderDirectory(const utility::file& file) -{ +bool courierMaildirFormat::isSubfolderDirectory(const utility::file& file) { + // A directory which names starts with '.' may be a subfolder if (file.isDirectory() && file.getFullPath().getLastComponent().getBuffer().length() >= 1 && - file.getFullPath().getLastComponent().getBuffer()[0] == '.') - { + file.getFullPath().getLastComponent().getBuffer()[0] == '.') { + return true; } @@ -325,8 +354,8 @@ bool courierMaildirFormat::isSubfolderDirectory(const utility::file& file) // static -const string courierMaildirFormat::toModifiedUTF7(const folder::path::component& text) -{ +const string courierMaildirFormat::toModifiedUTF7(const folder::path::component& text) { + // From http://www.courier-mta.org/?maildir.html: // // Folder names can contain any Unicode character, except for control @@ -364,67 +393,65 @@ const string courierMaildirFormat::toModifiedUTF7(const folder::path::component& bool inB64sequence = false; - for (string::const_iterator it = cvt.begin() ; it != cvt.end() ; ++it) - { + for (string::const_iterator it = cvt.begin() ; it != cvt.end() ; ++it) { + const unsigned char c = *it; - switch (c) - { - // Beginning of Base64 sequence: replace '+' with '&' - case '+': - { - if (!inB64sequence) - { - inB64sequence = true; - out += '&'; + switch (c) { + + // Beginning of Base64 sequence: replace '+' with '&' + case '+': { + + if (!inB64sequence) { + inB64sequence = true; + out += '&'; + } else { + out += '+'; + } + + break; + } + // End of Base64 sequence + case '-': { + + inB64sequence = false; + out += '-'; + break; } - else - { - out += '+'; + // ',' is used instead of '/' in modified Base64, + // and simply UTF7-encoded out of a Base64 sequence + case '/': { + + if (inB64sequence) { + out += ','; + } else { + out += "&Lw-"; + } + + break; } + // Encode period (should not happen in a Base64 sequence) + case '.': { - break; - } - // End of Base64 sequence - case '-': - { - inB64sequence = false; - out += '-'; - break; - } - // ',' is used instead of '/' in modified Base64, - // and simply UTF7-encoded out of a Base64 sequence - case '/': - { - if (inB64sequence) - out += ','; - else - out += "&Lw-"; + out += "&Lg-"; + break; + } + // '&' (0x26) is represented by the two-octet sequence "&-" + case '&': { - break; - } - // Encode period (should not happen in a Base64 sequence) - case '.': - { - out += "&Lg-"; - break; - } - // '&' (0x26) is represented by the two-octet sequence "&-" - case '&': - { - if (!inB64sequence) - out += "&-"; - else - out += '&'; + if (!inB64sequence) { + out += "&-"; + } else { + out += '&'; + } - break; - } - default: - { - out += c; - break; - } + break; + } + default: { + out += c; + break; + } } } @@ -433,8 +460,8 @@ const string courierMaildirFormat::toModifiedUTF7(const folder::path::component& // static -const folder::path::component courierMaildirFormat::fromModifiedUTF7(const string& text) -{ +const folder::path::component courierMaildirFormat::fromModifiedUTF7(const string& text) { + // Transcode from modified UTF-7 string out; out.reserve(text.length()); @@ -442,49 +469,47 @@ const folder::path::component courierMaildirFormat::fromModifiedUTF7(const strin bool inB64sequence = false; unsigned char prev = 0; - for (string::const_iterator it = text.begin() ; it != text.end() ; ++it) - { + for (string::const_iterator it = text.begin() ; it != text.end() ; ++it) { + const unsigned char c = *it; - switch (c) - { - // Start of Base64 sequence - case '&': - { - if (!inB64sequence) - { - inB64sequence = true; - out += '+'; + switch (c) { + + // Start of Base64 sequence + case '&': { + + if (!inB64sequence) { + inB64sequence = true; + out += '+'; + } else { + out += '&'; + } + + break; } - else - { - out += '&'; + // End of Base64 sequence (or "&-" --> "&") + case '-': { + + if (inB64sequence && prev == '&') { + out += '&'; + } else { + out += '-'; + } + + inB64sequence = false; + break; } + // ',' is used instead of '/' in modified Base64 + case ',': { - break; - } - // End of Base64 sequence (or "&-" --> "&") - case '-': - { - if (inB64sequence && prev == '&') - out += '&'; - else - out += '-'; + out += (inB64sequence ? '/' : ','); + break; + } + default: { - inB64sequence = false; - break; - } - // ',' is used instead of '/' in modified Base64 - case ',': - { - out += (inB64sequence ? '/' : ','); - break; - } - default: - { - out += c; - break; - } + out += c; + break; + } } @@ -493,37 +518,39 @@ const folder::path::component courierMaildirFormat::fromModifiedUTF7(const strin // Store it as UTF-8 by default string cvt; - charset::convert(out, cvt, - charset(charsets::UTF_7), charset(charsets::UTF_8)); + charset::convert(out, cvt, charset(charsets::UTF_7), charset(charsets::UTF_8)); - return (folder::path::component(cvt, charset(charsets::UTF_8))); + return folder::path::component(cvt, charset(charsets::UTF_8)); } -bool courierMaildirFormat::supports() const -{ +bool courierMaildirFormat::supports() const { + shared_ptr <utility::fileSystemFactory> fsf = platform::getHandler()->getFileSystemFactory(); - shared_ptr <utility::file> rootDir = fsf->create - (getContext()->getStore()->getFileSystemPath()); + shared_ptr <utility::file> rootDir = fsf->create( + getContext()->getStore()->getFileSystemPath() + ); + + if (rootDir->exists()) { - if (rootDir->exists()) - { // Try to find a file named "maildirfolder", which indicates // the Maildir is in Courier format shared_ptr <utility::fileIterator> it = rootDir->getFiles(); - while (it->hasMoreElements()) - { + while (it->hasMoreElements()) { + shared_ptr <utility::file> file = it->nextElement(); - if (isSubfolderDirectory(*file)) - { - shared_ptr <utility::file> folderFile = fsf->create - (file->getFullPath() / utility::file::path::component("maildirfolder")); + if (isSubfolderDirectory(*file)) { - if (folderFile->exists() && folderFile->isFile()) + shared_ptr <utility::file> folderFile = fsf->create( + file->getFullPath() / utility::file::path::component("maildirfolder") + ); + + if (folderFile->exists() && folderFile->isFile()) { return true; + } } } } diff --git a/src/vmime/net/maildir/format/courierMaildirFormat.hpp b/src/vmime/net/maildir/format/courierMaildirFormat.hpp index b8443426..7db1a834 100644 --- a/src/vmime/net/maildir/format/courierMaildirFormat.hpp +++ b/src/vmime/net/maildir/format/courierMaildirFormat.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard <[email protected]> +// Copyright (C) 2002 Vincent Richard <[email protected]> // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License as @@ -42,12 +42,11 @@ namespace format { /** Reads Courier/QMail Maildir format. */ +class VMIME_EXPORT courierMaildirFormat : public maildirFormat { -class VMIME_EXPORT courierMaildirFormat : public maildirFormat -{ public: - courierMaildirFormat(shared_ptr <context> ctx); + courierMaildirFormat(const shared_ptr <context>& ctx); /* Folder types: @@ -68,11 +67,15 @@ public: bool folderExists(const folder::path& path) const; bool folderHasSubfolders(const folder::path& path) const; - const utility::file::path folderPathToFileSystemPath - (const folder::path& path, const DirectoryType type) const; + const utility::file::path folderPathToFileSystemPath( + const folder::path& path, + const DirectoryType type + ) const; - const std::vector <folder::path> listFolders - (const folder::path& root, const bool recursive) const; + const std::vector <folder::path> listFolders( + const folder::path& root, + const bool recursive + ) const; protected: @@ -104,8 +107,11 @@ protected: * @return true if at least one directory has been found, * false otherwise */ - bool listDirectories(const folder::path& root, - std::vector <string>& dirs, const bool onlyTestForExistence) const; + bool listDirectories( + const folder::path& root, + std::vector <string>& dirs, + const bool onlyTestForExistence + ) const; }; diff --git a/src/vmime/net/maildir/format/kmailMaildirFormat.cpp b/src/vmime/net/maildir/format/kmailMaildirFormat.cpp index 975752a5..4eb89e8b 100644 --- a/src/vmime/net/maildir/format/kmailMaildirFormat.cpp +++ b/src/vmime/net/maildir/format/kmailMaildirFormat.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard <[email protected]> +// Copyright (C) 2002 Vincent Richard <[email protected]> // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License as @@ -41,34 +41,39 @@ namespace maildir { namespace format { -kmailMaildirFormat::kmailMaildirFormat(shared_ptr <context> ctx) - : maildirFormat(ctx) -{ +kmailMaildirFormat::kmailMaildirFormat(const shared_ptr <context>& ctx) + : maildirFormat(ctx) { + } -const string kmailMaildirFormat::getName() const -{ +const string kmailMaildirFormat::getName() const { + return "kmail"; } -void kmailMaildirFormat::createFolder(const folder::path& path) -{ +void kmailMaildirFormat::createFolder(const folder::path& path) { + shared_ptr <utility::fileSystemFactory> fsf = platform::getHandler()->getFileSystemFactory(); - if (!fsf->isValidPath(folderPathToFileSystemPath(path, ROOT_DIRECTORY))) + if (!fsf->isValidPath(folderPathToFileSystemPath(path, ROOT_DIRECTORY))) { throw exceptions::invalid_folder_name(); + } - shared_ptr <utility::file> rootDir = fsf->create - (folderPathToFileSystemPath(path, ROOT_DIRECTORY)); + shared_ptr <utility::file> rootDir = fsf->create( + folderPathToFileSystemPath(path, ROOT_DIRECTORY) + ); - shared_ptr <utility::file> newDir = fsf->create - (folderPathToFileSystemPath(path, NEW_DIRECTORY)); - shared_ptr <utility::file> tmpDir = fsf->create - (folderPathToFileSystemPath(path, TMP_DIRECTORY)); - shared_ptr <utility::file> curDir = fsf->create - (folderPathToFileSystemPath(path, CUR_DIRECTORY)); + shared_ptr <utility::file> newDir = fsf->create( + folderPathToFileSystemPath(path, NEW_DIRECTORY) + ); + shared_ptr <utility::file> tmpDir = fsf->create( + folderPathToFileSystemPath(path, TMP_DIRECTORY) + ); + shared_ptr <utility::file> curDir = fsf->create( + folderPathToFileSystemPath(path, CUR_DIRECTORY) + ); rootDir->createDirectory(true); @@ -78,32 +83,38 @@ void kmailMaildirFormat::createFolder(const folder::path& path) } -void kmailMaildirFormat::destroyFolder(const folder::path& path) -{ +void kmailMaildirFormat::destroyFolder(const folder::path& path) { + // Delete 'folder' and '.folder.directory' directories shared_ptr <utility::fileSystemFactory> fsf = platform::getHandler()->getFileSystemFactory(); - maildirUtils::recursiveFSDelete(fsf->create - (folderPathToFileSystemPath(path, ROOT_DIRECTORY))); // root + maildirUtils::recursiveFSDelete( + fsf->create(folderPathToFileSystemPath(path, ROOT_DIRECTORY)) // root + ); - maildirUtils::recursiveFSDelete(fsf->create - (folderPathToFileSystemPath(path, CONTAINER_DIRECTORY))); // container + maildirUtils::recursiveFSDelete( + fsf->create(folderPathToFileSystemPath(path, CONTAINER_DIRECTORY)) // container + ); } -bool kmailMaildirFormat::folderExists(const folder::path& path) const -{ +bool kmailMaildirFormat::folderExists(const folder::path& path) const { + shared_ptr <utility::fileSystemFactory> fsf = platform::getHandler()->getFileSystemFactory(); - shared_ptr <utility::file> rootDir = fsf->create - (folderPathToFileSystemPath(path, ROOT_DIRECTORY)); + shared_ptr <utility::file> rootDir = fsf->create( + folderPathToFileSystemPath(path, ROOT_DIRECTORY) + ); - shared_ptr <utility::file> newDir = fsf->create - (folderPathToFileSystemPath(path, NEW_DIRECTORY)); - shared_ptr <utility::file> tmpDir = fsf->create - (folderPathToFileSystemPath(path, TMP_DIRECTORY)); - shared_ptr <utility::file> curDir = fsf->create - (folderPathToFileSystemPath(path, CUR_DIRECTORY)); + shared_ptr <utility::file> newDir = fsf->create( + folderPathToFileSystemPath(path, NEW_DIRECTORY) + ); + shared_ptr <utility::file> tmpDir = fsf->create( + folderPathToFileSystemPath(path, TMP_DIRECTORY) + ); + shared_ptr <utility::file> curDir = fsf->create( + folderPathToFileSystemPath(path, CUR_DIRECTORY) + ); return rootDir->exists() && rootDir->isDirectory() && newDir->exists() && newDir->isDirectory() && @@ -112,9 +123,11 @@ bool kmailMaildirFormat::folderExists(const folder::path& path) const } -const utility::file::path kmailMaildirFormat::folderPathToFileSystemPath - (const folder::path& path, const DirectoryType type) const -{ +const utility::file::path kmailMaildirFormat::folderPathToFileSystemPath( + const folder::path& path, + const DirectoryType type +) const { + // Root path utility::file::path fsPath = getContext()->getStore()->getFileSystemPath(); @@ -123,8 +136,8 @@ const utility::file::path kmailMaildirFormat::folderPathToFileSystemPath ? pathSize : (pathSize >= 1 ? pathSize - 1 : 0)); // Parent folders - for (size_t i = 0 ; i < count ; ++i) - { + for (size_t i = 0 ; i < count ; ++i) { + utility::file::path::component comp(path[i]); // TODO: may not work with all encodings... @@ -134,36 +147,36 @@ const utility::file::path kmailMaildirFormat::folderPathToFileSystemPath } // Last component - if (path.getSize() != 0 && type != CONTAINER_DIRECTORY) - { + if (path.getSize() != 0 && type != CONTAINER_DIRECTORY) { + fsPath /= path.getLastComponent(); - switch (type) - { - case ROOT_DIRECTORY: + switch (type) { + + case ROOT_DIRECTORY: - // Nothing to add - break; + // Nothing to add + break; - case NEW_DIRECTORY: + case NEW_DIRECTORY: - fsPath /= NEW_DIR; - break; + fsPath /= NEW_DIR; + break; - case CUR_DIRECTORY: + case CUR_DIRECTORY: - fsPath /= CUR_DIR; - break; + fsPath /= CUR_DIR; + break; - case TMP_DIRECTORY: + case TMP_DIRECTORY: - fsPath /= TMP_DIR; - break; + fsPath /= TMP_DIR; + break; - case CONTAINER_DIRECTORY: + case CONTAINER_DIRECTORY: - // Can't happen... - break; + // Can't happen... + break; } } @@ -171,9 +184,11 @@ const utility::file::path kmailMaildirFormat::folderPathToFileSystemPath } -const std::vector <folder::path> kmailMaildirFormat::listFolders - (const folder::path& root, const bool recursive) const -{ +const std::vector <folder::path> kmailMaildirFormat::listFolders( + const folder::path& root, + const bool recursive +) const { + std::vector <folder::path> list; listFoldersImpl(list, root, recursive); @@ -181,49 +196,53 @@ const std::vector <folder::path> kmailMaildirFormat::listFolders } -void kmailMaildirFormat::listFoldersImpl - (std::vector <folder::path>& list, const folder::path& root, const bool recursive) const -{ +void kmailMaildirFormat::listFoldersImpl( + std::vector <folder::path>& list, + const folder::path& root, + const bool recursive +) const { + shared_ptr <utility::fileSystemFactory> fsf = platform::getHandler()->getFileSystemFactory(); - shared_ptr <utility::file> rootDir = fsf->create(folderPathToFileSystemPath(root, - root.isEmpty() ? ROOT_DIRECTORY : CONTAINER_DIRECTORY)); + shared_ptr <utility::file> rootDir = fsf->create( + folderPathToFileSystemPath(root, root.isEmpty() ? ROOT_DIRECTORY : CONTAINER_DIRECTORY) + ); + + if (rootDir->exists()) { - if (rootDir->exists()) - { shared_ptr <utility::fileIterator> it = rootDir->getFiles(); - while (it->hasMoreElements()) - { + while (it->hasMoreElements()) { + shared_ptr <utility::file> file = it->nextElement(); - if (isSubfolderDirectory(*file)) - { - const utility::path subPath = - root / file->getFullPath().getLastComponent(); + if (isSubfolderDirectory(*file)) { + + const utility::path subPath = root / file->getFullPath().getLastComponent(); list.push_back(subPath); - if (recursive) + if (recursive) { listFoldersImpl(list, subPath, true); + } } } - } - else - { + + } else { + // No sub-folder } } // static -bool kmailMaildirFormat::isSubfolderDirectory(const utility::file& file) -{ +bool kmailMaildirFormat::isSubfolderDirectory(const utility::file& file) { + // A directory which name does not start with '.' is listed as a sub-folder if (file.isDirectory() && file.getFullPath().getLastComponent().getBuffer().length() >= 1 && - file.getFullPath().getLastComponent().getBuffer()[0] != '.') - { + file.getFullPath().getLastComponent().getBuffer()[0] != '.') { + return true; } @@ -231,17 +250,19 @@ bool kmailMaildirFormat::isSubfolderDirectory(const utility::file& file) } -void kmailMaildirFormat::renameFolder(const folder::path& oldPath, const folder::path& newPath) -{ +void kmailMaildirFormat::renameFolder(const folder::path& oldPath, const folder::path& newPath) { + shared_ptr <utility::fileSystemFactory> fsf = platform::getHandler()->getFileSystemFactory(); - shared_ptr <utility::file> rootDir = fsf->create - (folderPathToFileSystemPath(oldPath, ROOT_DIRECTORY)); - shared_ptr <utility::file> contDir = fsf->create - (folderPathToFileSystemPath(oldPath, CONTAINER_DIRECTORY)); + shared_ptr <utility::file> rootDir = fsf->create( + folderPathToFileSystemPath(oldPath, ROOT_DIRECTORY) + ); + shared_ptr <utility::file> contDir = fsf->create( + folderPathToFileSystemPath(oldPath, CONTAINER_DIRECTORY) + ); + + try { - try - { const utility::file::path newRootPath = folderPathToFileSystemPath(newPath, ROOT_DIRECTORY); const utility::file::path newContPath = @@ -250,30 +271,24 @@ void kmailMaildirFormat::renameFolder(const folder::path& oldPath, const folder: rootDir->rename(newRootPath); // Container directory may not exist, so ignore error when trying to rename it - try - { + try { contDir->rename(newContPath); - } - catch (exceptions::filesystem_exception& e) - { + } catch (exceptions::filesystem_exception& e) { // Ignore } - } - catch (exceptions::filesystem_exception& e) - { + + } catch (exceptions::filesystem_exception& e) { + // Revert to old location const utility::file::path rootPath = folderPathToFileSystemPath(oldPath, ROOT_DIRECTORY); const utility::file::path contPath = folderPathToFileSystemPath(oldPath, CONTAINER_DIRECTORY); - try - { + try { rootDir->rename(rootPath); contDir->rename(contPath); - } - catch (exceptions::filesystem_exception& e) - { + } catch (exceptions::filesystem_exception& e) { // Ignore (not recoverable) } @@ -282,29 +297,31 @@ void kmailMaildirFormat::renameFolder(const folder::path& oldPath, const folder: } -bool kmailMaildirFormat::folderHasSubfolders(const folder::path& path) const -{ +bool kmailMaildirFormat::folderHasSubfolders(const folder::path& path) const { + shared_ptr <utility::fileSystemFactory> fsf = platform::getHandler()->getFileSystemFactory(); - shared_ptr <utility::file> rootDir = fsf->create - (folderPathToFileSystemPath(path, CONTAINER_DIRECTORY)); + shared_ptr <utility::file> rootDir = fsf->create( + folderPathToFileSystemPath(path, CONTAINER_DIRECTORY) + ); shared_ptr <utility::fileIterator> it = rootDir->getFiles(); - while (it->hasMoreElements()) - { + while (it->hasMoreElements()) { + shared_ptr <utility::file> file = it->nextElement(); - if (isSubfolderDirectory(*file)) + if (isSubfolderDirectory(*file)) { return true; + } } return false; } -bool kmailMaildirFormat::supports() const -{ +bool kmailMaildirFormat::supports() const { + // This is the default return true; } diff --git a/src/vmime/net/maildir/format/kmailMaildirFormat.hpp b/src/vmime/net/maildir/format/kmailMaildirFormat.hpp index 98ca212e..26b557a3 100644 --- a/src/vmime/net/maildir/format/kmailMaildirFormat.hpp +++ b/src/vmime/net/maildir/format/kmailMaildirFormat.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard <[email protected]> +// Copyright (C) 2002 Vincent Richard <[email protected]> // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License as @@ -42,12 +42,11 @@ namespace format { /** Reads KMail Maildir format. */ +class VMIME_EXPORT kmailMaildirFormat : public maildirFormat { -class VMIME_EXPORT kmailMaildirFormat : public maildirFormat -{ public: - kmailMaildirFormat(shared_ptr <context> ctx); + kmailMaildirFormat(const shared_ptr <context>& ctx); /* Folder types: @@ -68,11 +67,15 @@ public: bool folderExists(const folder::path& path) const; bool folderHasSubfolders(const folder::path& path) const; - const utility::file::path folderPathToFileSystemPath - (const folder::path& path, const DirectoryType type) const; + const utility::file::path folderPathToFileSystemPath( + const folder::path& path, + const DirectoryType type + ) const; - const std::vector <folder::path> listFolders - (const folder::path& root, const bool recursive) const; + const std::vector <folder::path> listFolders( + const folder::path& root, + const bool recursive + ) const; protected: @@ -81,8 +84,11 @@ protected: /** Recursive implementation of listFolders(). */ - void listFoldersImpl(std::vector <folder::path>& list, - const folder::path& root, const bool recursive) const; + void listFoldersImpl( + std::vector <folder::path>& list, + const folder::path& root, + const bool recursive + ) const; /** Test whether the specified file system directory corresponds to * a maildir subfolder. The name of the directory should not start diff --git a/src/vmime/net/maildir/maildir.hpp b/src/vmime/net/maildir/maildir.hpp index 42bbbea4..8835bf4c 100644 --- a/src/vmime/net/maildir/maildir.hpp +++ b/src/vmime/net/maildir/maildir.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard <[email protected]> +// Copyright (C) 2002 Vincent Richard <[email protected]> // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License as diff --git a/src/vmime/net/maildir/maildirFolder.cpp b/src/vmime/net/maildir/maildirFolder.cpp index 8951cb1c..8c02025b 100644 --- a/src/vmime/net/maildir/maildirFolder.cpp +++ b/src/vmime/net/maildir/maildirFolder.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard <[email protected]> +// Copyright (C) 2002 Vincent Richard <[email protected]> // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License as @@ -49,93 +49,105 @@ namespace net { namespace maildir { -maildirFolder::maildirFolder(const folder::path& path, shared_ptr <maildirStore> store) - : m_store(store), m_path(path), +maildirFolder::maildirFolder( + const folder::path& path, + const shared_ptr <maildirStore>& store +) + : m_store(store), + m_path(path), m_name(path.isEmpty() ? folder::path::component("") : path.getLastComponent()), - m_mode(-1), m_open(false), m_unreadMessageCount(0), m_messageCount(0) -{ + m_mode(-1), + m_open(false), + m_unreadMessageCount(0), + m_messageCount(0) { + store->registerFolder(this); } -maildirFolder::~maildirFolder() -{ - try - { +maildirFolder::~maildirFolder() { + + try { + shared_ptr <maildirStore> store = m_store.lock(); - if (store) - { - if (m_open) + if (store) { + + if (m_open) { close(false); + } store->unregisterFolder(this); - } - else if (m_open) - { + + } else if (m_open) { + close(false); } - } - catch (...) - { + + } catch (...) { + // Don't throw in destructor } } -void maildirFolder::onStoreDisconnected() -{ +void maildirFolder::onStoreDisconnected() { + m_store.reset(); } -int maildirFolder::getMode() const -{ - if (!isOpen()) +int maildirFolder::getMode() const { + + if (!isOpen()) { throw exceptions::illegal_state("Folder not open"); + } - return (m_mode); + return m_mode; } -const folderAttributes maildirFolder::getAttributes() -{ +const folderAttributes maildirFolder::getAttributes() { + folderAttributes attribs; - if (m_path.isEmpty()) + if (m_path.isEmpty()) { attribs.setType(folderAttributes::TYPE_CONTAINS_FOLDERS); - else + } else { attribs.setType(folderAttributes::TYPE_CONTAINS_FOLDERS | folderAttributes::TYPE_CONTAINS_MESSAGES); + } - if (m_store.lock()->getFormat()->folderHasSubfolders(m_path)) + if (m_store.lock()->getFormat()->folderHasSubfolders(m_path)) { attribs.setFlags(folderAttributes::FLAG_HAS_CHILDREN); // contains at least one sub-folder + } return attribs; } -const folder::path::component maildirFolder::getName() const -{ - return (m_name); +const folder::path::component maildirFolder::getName() const { + + return m_name; } -const folder::path maildirFolder::getFullPath() const -{ - return (m_path); +const folder::path maildirFolder::getFullPath() const { + + return m_path; } -void maildirFolder::open(const int mode, bool /* failIfModeIsNotAvailable */) -{ +void maildirFolder::open(const int mode, bool /* failIfModeIsNotAvailable */) { + shared_ptr <maildirStore> store = m_store.lock(); - if (!store) + if (!store) { throw exceptions::illegal_state("Store disconnected"); - else if (isOpen()) + } else if (isOpen()) { throw exceptions::illegal_state("Folder is already open"); - else if (!exists()) + } else if (!exists()) { throw exceptions::illegal_state("Folder does not exist"); + } scanFolder(); @@ -144,18 +156,21 @@ void maildirFolder::open(const int mode, bool /* failIfModeIsNotAvailable */) } -void maildirFolder::close(const bool expunge) -{ +void maildirFolder::close(const bool expunge) { + shared_ptr <maildirStore> store = m_store.lock(); - if (!store) + if (!store) { throw exceptions::illegal_state("Store disconnected"); + } - if (!isOpen()) + if (!isOpen()) { throw exceptions::illegal_state("Folder not open"); + } - if (expunge) + if (expunge) { this->expunge(); + } m_open = false; m_mode = -1; @@ -164,11 +179,11 @@ void maildirFolder::close(const bool expunge) } -void maildirFolder::onClose() -{ +void maildirFolder::onClose() { + for (std::vector <maildirMessage*>::iterator it = m_messages.begin() ; - it != m_messages.end() ; ++it) - { + it != m_messages.end() ; ++it) { + (*it)->onFolderClosed(); } @@ -176,144 +191,147 @@ void maildirFolder::onClose() } -void maildirFolder::registerMessage(maildirMessage* msg) -{ +void maildirFolder::registerMessage(maildirMessage* msg) { + m_messages.push_back(msg); } -void maildirFolder::unregisterMessage(maildirMessage* msg) -{ +void maildirFolder::unregisterMessage(maildirMessage* msg) { + std::vector <maildirMessage*>::iterator it = std::find(m_messages.begin(), m_messages.end(), msg); - if (it != m_messages.end()) + if (it != m_messages.end()) { m_messages.erase(it); + } } -void maildirFolder::create(const folderAttributes& /* attribs */) -{ +void maildirFolder::create(const folderAttributes& /* attribs */) { + shared_ptr <maildirStore> store = m_store.lock(); - if (!store) + if (!store) { throw exceptions::illegal_state("Store disconnected"); - else if (isOpen()) + } else if (isOpen()) { throw exceptions::illegal_state("Folder is open"); - else if (exists()) + } else if (exists()) { throw exceptions::illegal_state("Folder already exists"); - else if (!store->isValidFolderName(m_name)) + } else if (!store->isValidFolderName(m_name)) { throw exceptions::invalid_folder_name(); + } // Create directory on file system - try - { + try { store->getFormat()->createFolder(m_path); - } - catch (exceptions::filesystem_exception& e) - { + } catch (exceptions::filesystem_exception& e) { throw exceptions::command_error("CREATE", "", "File system exception", e); } // Notify folder created shared_ptr <events::folderEvent> event = - make_shared <events::folderEvent> - (dynamicCast <folder>(shared_from_this()), - events::folderEvent::TYPE_CREATED, m_path, m_path); + make_shared <events::folderEvent>( + dynamicCast <folder>(shared_from_this()), + events::folderEvent::TYPE_CREATED, + m_path, m_path + ); notifyFolder(event); } -void maildirFolder::destroy() -{ +void maildirFolder::destroy() { + shared_ptr <maildirStore> store = m_store.lock(); - if (!store) + if (!store) { throw exceptions::illegal_state("Store disconnected"); - else if (isOpen()) + } else if (isOpen()) { throw exceptions::illegal_state("Folder is open"); + } // Delete folder - try - { + try { store->getFormat()->destroyFolder(m_path); - } - catch (std::exception&) - { + } catch (std::exception&) { // Ignore exception: anyway, we can't recover from this... } // Notify folder deleted shared_ptr <events::folderEvent> event = - make_shared <events::folderEvent> - (dynamicCast <folder>(shared_from_this()), - events::folderEvent::TYPE_DELETED, m_path, m_path); + make_shared <events::folderEvent>( + dynamicCast <folder>(shared_from_this()), + events::folderEvent::TYPE_DELETED, + m_path, m_path + ); notifyFolder(event); } -bool maildirFolder::exists() -{ +bool maildirFolder::exists() { + shared_ptr <maildirStore> store = m_store.lock(); return store->getFormat()->folderExists(m_path); } -bool maildirFolder::isOpen() const -{ - return (m_open); +bool maildirFolder::isOpen() const { + + return m_open; } -void maildirFolder::scanFolder() -{ +void maildirFolder::scanFolder() { + shared_ptr <maildirStore> store = m_store.lock(); - try - { + try { + m_messageCount = 0; m_unreadMessageCount = 0; shared_ptr <utility::fileSystemFactory> fsf = platform::getHandler()->getFileSystemFactory(); - utility::file::path newDirPath = store->getFormat()->folderPathToFileSystemPath - (m_path, maildirFormat::NEW_DIRECTORY); + utility::file::path newDirPath = + store->getFormat()->folderPathToFileSystemPath(m_path, maildirFormat::NEW_DIRECTORY); shared_ptr <utility::file> newDir = fsf->create(newDirPath); - utility::file::path curDirPath = store->getFormat()->folderPathToFileSystemPath - (m_path, maildirFormat::CUR_DIRECTORY); + utility::file::path curDirPath = + store->getFormat()->folderPathToFileSystemPath(m_path, maildirFormat::CUR_DIRECTORY); shared_ptr <utility::file> curDir = fsf->create(curDirPath); // New received messages (new/) shared_ptr <utility::fileIterator> nit = newDir->getFiles(); std::vector <utility::file::path::component> newMessageFilenames; - while (nit->hasMoreElements()) - { + while (nit->hasMoreElements()) { + shared_ptr <utility::file> file = nit->nextElement(); - if (maildirUtils::isMessageFile(*file)) + if (maildirUtils::isMessageFile(*file)) { newMessageFilenames.push_back(file->getFullPath().getLastComponent()); + } } // Current messages (cur/) shared_ptr <utility::fileIterator> cit = curDir->getFiles(); std::vector <utility::file::path::component> curMessageFilenames; - while (cit->hasMoreElements()) - { + while (cit->hasMoreElements()) { + shared_ptr <utility::file> file = cit->nextElement(); - if (maildirUtils::isMessageFile(*file)) + if (maildirUtils::isMessageFile(*file)) { curMessageFilenames.push_back(file->getFullPath().getLastComponent()); + } } // Update/delete existing messages (found in previous scan) - for (size_t i = 0 ; i < m_messageInfos.size() ; ++i) - { + for (size_t i = 0 ; i < m_messageInfos.size() ; ++i) { + messageInfos& msgInfos = m_messageInfos[i]; // NOTE: the flags may have changed (eg. moving from 'new' to 'cur' @@ -321,21 +339,24 @@ void maildirFolder::scanFolder() // "maildirUtils::messageIdComparator" to compare only the 'unique' // portion of the filename... - if (msgInfos.type == messageInfos::TYPE_CUR) - { + if (msgInfos.type == messageInfos::TYPE_CUR) { + const std::vector <utility::file::path::component>::iterator pos = - std::find_if(curMessageFilenames.begin(), curMessageFilenames.end(), - maildirUtils::messageIdComparator(msgInfos.path)); + std::find_if( + curMessageFilenames.begin(), + curMessageFilenames.end(), + maildirUtils::messageIdComparator(msgInfos.path) + ); // If we cannot find this message in the 'cur' directory, // it means it has been deleted (and expunged). - if (pos == curMessageFilenames.end()) - { + if (pos == curMessageFilenames.end()) { + msgInfos.type = messageInfos::TYPE_DELETED; - } + // Otherwise, update its information. - else - { + } else { + msgInfos.path = *pos; curMessageFilenames.erase(pos); } @@ -349,8 +370,8 @@ void maildirFolder::scanFolder() // from the 'new' directory to the 'cur' directory, and append them // to our message list. for (std::vector <utility::file::path::component>::const_iterator - it = newMessageFilenames.begin() ; it != newMessageFilenames.end() ; ++it) - { + it = newMessageFilenames.begin() ; it != newMessageFilenames.end() ; ++it) { + const utility::file::path::component newFilename = maildirUtils::buildFilename(maildirUtils::extractId(*it), 0); @@ -362,10 +383,11 @@ void maildirFolder::scanFolder() messageInfos msgInfos; msgInfos.path = newFilename; - if (maildirUtils::extractFlags(msgInfos.path) & message::FLAG_DELETED) + if (maildirUtils::extractFlags(msgInfos.path) & message::FLAG_DELETED) { msgInfos.type = messageInfos::TYPE_DELETED; - else + } else { msgInfos.type = messageInfos::TYPE_CUR; + } m_messageInfos.push_back(msgInfos); } @@ -373,16 +395,17 @@ void maildirFolder::scanFolder() // Add new messages from 'cur': the files have already been moved // from 'new' to 'cur'. Just append them to our message list. for (std::vector <utility::file::path::component>::const_iterator - it = curMessageFilenames.begin() ; it != curMessageFilenames.end() ; ++it) - { + it = curMessageFilenames.begin() ; it != curMessageFilenames.end() ; ++it) { + // Append to message list messageInfos msgInfos; msgInfos.path = *it; - if (maildirUtils::extractFlags(msgInfos.path) & message::FLAG_DELETED) + if (maildirUtils::extractFlags(msgInfos.path) & message::FLAG_DELETED) { msgInfos.type = messageInfos::TYPE_DELETED; - else + } else { msgInfos.type = messageInfos::TYPE_CUR; + } m_messageInfos.push_back(msgInfos); } @@ -391,140 +414,145 @@ void maildirFolder::scanFolder() size_t unreadMessageCount = 0; for (std::vector <messageInfos>::const_iterator - it = m_messageInfos.begin() ; it != m_messageInfos.end() ; ++it) - { - if ((maildirUtils::extractFlags((*it).path) & message::FLAG_SEEN) == 0) + it = m_messageInfos.begin() ; it != m_messageInfos.end() ; ++it) { + + if ((maildirUtils::extractFlags((*it).path) & message::FLAG_SEEN) == 0) { ++unreadMessageCount; + } } m_unreadMessageCount = unreadMessageCount; m_messageCount = static_cast <size_t>(m_messageInfos.size()); - } - catch (exceptions::filesystem_exception&) - { + + } catch (exceptions::filesystem_exception&) { + // Should not happen... } } -shared_ptr <message> maildirFolder::getMessage(const size_t num) -{ - if (!isOpen()) +shared_ptr <message> maildirFolder::getMessage(const size_t num) { + + if (!isOpen()) { throw exceptions::illegal_state("Folder not open"); + } - if (num < 1 || num > m_messageCount) + if (num < 1 || num > m_messageCount) { throw exceptions::message_not_found(); + } - return make_shared <maildirMessage> - (dynamicCast <maildirFolder>(shared_from_this()), num); + return make_shared <maildirMessage>(dynamicCast <maildirFolder>(shared_from_this()), num); } -std::vector <shared_ptr <message> > maildirFolder::getMessages(const messageSet& msgs) -{ - if (!isOpen()) +std::vector <shared_ptr <message> > maildirFolder::getMessages(const messageSet& msgs) { + + if (!isOpen()) { throw exceptions::illegal_state("Folder not open"); + } + + if (msgs.isNumberSet()) { - if (msgs.isNumberSet()) - { const std::vector <size_t> numbers = maildirUtils::messageSetToNumberList(msgs, m_messageCount); std::vector <shared_ptr <message> > messages; shared_ptr <maildirFolder> thisFolder = dynamicCast <maildirFolder>(shared_from_this()); - for (std::vector <size_t>::const_iterator it = numbers.begin() ; it != numbers.end() ; ++it) - { - if (*it < 1|| *it > m_messageCount) + for (std::vector <size_t>::const_iterator it = numbers.begin() ; it != numbers.end() ; ++it) { + + if (*it < 1|| *it > m_messageCount) { throw exceptions::message_not_found(); + } messages.push_back(make_shared <maildirMessage>(thisFolder, *it)); } return messages; - } - else - { + + } else { + throw exceptions::operation_not_supported(); } } -size_t maildirFolder::getMessageCount() -{ - return (m_messageCount); +size_t maildirFolder::getMessageCount() { + + return m_messageCount; } -shared_ptr <folder> maildirFolder::getFolder(const folder::path::component& name) -{ +shared_ptr <folder> maildirFolder::getFolder(const folder::path::component& name) { + shared_ptr <maildirStore> store = m_store.lock(); - if (!store) + if (!store) { throw exceptions::illegal_state("Store disconnected"); + } return shared_ptr <maildirFolder>(new maildirFolder(m_path / name, store)); } -std::vector <shared_ptr <folder> > maildirFolder::getFolders(const bool recursive) -{ +std::vector <shared_ptr <folder> > maildirFolder::getFolders(const bool recursive) { + shared_ptr <maildirStore> store = m_store.lock(); - if (!isOpen() && !store) + if (!isOpen() && !store) { throw exceptions::illegal_state("Store disconnected"); + } std::vector <shared_ptr <folder> > list; listFolders(list, recursive); - return (list); + return list; } -void maildirFolder::listFolders(std::vector <shared_ptr <folder> >& list, const bool recursive) -{ +void maildirFolder::listFolders(std::vector <shared_ptr <folder> >& list, const bool recursive) { + shared_ptr <maildirStore> store = m_store.lock(); - try - { + try { + std::vector <folder::path> pathList = store->getFormat()->listFolders(m_path, recursive); list.reserve(pathList.size()); - for (std::vector <folder::path>::size_type i = 0, n = pathList.size() ; i < n ; ++i) - { - shared_ptr <maildirFolder> subFolder = - shared_ptr <maildirFolder>(new maildirFolder(pathList[i], store)); + for (std::vector <folder::path>::size_type i = 0, n = pathList.size() ; i < n ; ++i) { + + shared_ptr <maildirFolder> subFolder( + new maildirFolder(pathList[i], store) + ); list.push_back(subFolder); } - } - catch (exceptions::filesystem_exception& e) - { + + } catch (exceptions::filesystem_exception& e) { + throw exceptions::command_error("LIST", "", "", e); } } -void maildirFolder::rename(const folder::path& newPath) -{ +void maildirFolder::rename(const folder::path& newPath) { + shared_ptr <maildirStore> store = m_store.lock(); - if (!store) + if (!store) { throw exceptions::illegal_state("Store disconnected"); - else if (m_path.isEmpty() || newPath.isEmpty()) + } else if (m_path.isEmpty() || newPath.isEmpty()) { throw exceptions::illegal_operation("Cannot rename root folder"); - else if (!store->isValidFolderName(newPath.getLastComponent())) + } else if (!store->isValidFolderName(newPath.getLastComponent())) { throw exceptions::invalid_folder_name(); + } // Rename the directory on the file system - try - { + try { store->getFormat()->renameFolder(m_path, newPath); - } - catch (vmime::exception& e) - { + } catch (vmime::exception& e) { throw exceptions::command_error("RENAME", "", "", e); } @@ -535,38 +563,44 @@ void maildirFolder::rename(const folder::path& newPath) m_name = newPath.getLastComponent(); shared_ptr <events::folderEvent> event = - make_shared <events::folderEvent> - (dynamicCast <folder>(shared_from_this()), - events::folderEvent::TYPE_RENAMED, oldPath, newPath); + make_shared <events::folderEvent>( + dynamicCast <folder>(shared_from_this()), + events::folderEvent::TYPE_RENAMED, + oldPath, newPath + ); notifyFolder(event); // Notify folders with the same path for (std::list <maildirFolder*>::iterator it = store->m_folders.begin() ; - it != store->m_folders.end() ; ++it) - { - if ((*it) != this && (*it)->getFullPath() == oldPath) - { + it != store->m_folders.end() ; ++it) { + + if ((*it) != this && (*it)->getFullPath() == oldPath) { + (*it)->m_path = newPath; (*it)->m_name = newPath.getLastComponent(); shared_ptr <events::folderEvent> event = - make_shared <events::folderEvent> - (dynamicCast <folder>((*it)->shared_from_this()), - events::folderEvent::TYPE_RENAMED, oldPath, newPath); + make_shared <events::folderEvent>( + dynamicCast <folder>((*it)->shared_from_this()), + events::folderEvent::TYPE_RENAMED, + oldPath, newPath + ); (*it)->notifyFolder(event); - } - else if ((*it) != this && oldPath.isParentOf((*it)->getFullPath())) - { + + } else if ((*it) != this && oldPath.isParentOf((*it)->getFullPath())) { + folder::path oldPath((*it)->m_path); (*it)->m_path.renameParent(oldPath, newPath); shared_ptr <events::folderEvent> event = - make_shared <events::folderEvent> - (dynamicCast <folder>((*it)->shared_from_this()), - events::folderEvent::TYPE_RENAMED, oldPath, (*it)->m_path); + make_shared <events::folderEvent>( + dynamicCast <folder>((*it)->shared_from_this()), + events::folderEvent::TYPE_RENAMED, + oldPath, (*it)->m_path + ); (*it)->notifyFolder(event); } @@ -574,27 +608,31 @@ void maildirFolder::rename(const folder::path& newPath) } -void maildirFolder::deleteMessages(const messageSet& msgs) -{ +void maildirFolder::deleteMessages(const messageSet& msgs) { + // Mark messages as deleted setMessageFlags(msgs, message::FLAG_DELETED, message::FLAG_MODE_ADD); } -void maildirFolder::setMessageFlags - (const messageSet& msgs, const int flags, const int mode) -{ +void maildirFolder::setMessageFlags( + const messageSet& msgs, + const int flags, + const int mode +) { + shared_ptr <maildirStore> store = m_store.lock(); - if (!store) + if (!store) { throw exceptions::illegal_state("Store disconnected"); - else if (!isOpen()) + } else if (!isOpen()) { throw exceptions::illegal_state("Folder not open"); - else if (m_mode == MODE_READ_ONLY) + } else if (m_mode == MODE_READ_ONLY) { throw exceptions::illegal_state("Folder is read-only"); + } + + if (msgs.isNumberSet()) { - if (msgs.isNumberSet()) - { const std::vector <size_t> nums = maildirUtils::messageSetToNumberList(msgs, m_messageCount); // Change message flags @@ -604,113 +642,118 @@ void maildirFolder::setMessageFlags folderPathToFileSystemPath(m_path, maildirFormat::CUR_DIRECTORY); for (std::vector <size_t>::const_iterator it = - nums.begin() ; it != nums.end() ; ++it) - { + nums.begin() ; it != nums.end() ; ++it) { + const size_t num = *it - 1; - try - { + try { + const utility::file::path::component path = m_messageInfos[num].path; shared_ptr <utility::file> file = fsf->create(curDirPath / path); int newFlags = maildirUtils::extractFlags(path); - switch (mode) - { - case message::FLAG_MODE_ADD: newFlags |= flags; break; - case message::FLAG_MODE_REMOVE: newFlags &= ~flags; break; - default: - case message::FLAG_MODE_SET: newFlags = flags; break; + switch (mode) { + case message::FLAG_MODE_ADD: newFlags |= flags; break; + case message::FLAG_MODE_REMOVE: newFlags &= ~flags; break; + default: + case message::FLAG_MODE_SET: newFlags = flags; break; } - const utility::file::path::component newPath = maildirUtils::buildFilename - (maildirUtils::extractId(path), newFlags); + const utility::file::path::component newPath = + maildirUtils::buildFilename(maildirUtils::extractId(path), newFlags); file->rename(curDirPath / newPath); - if (flags & message::FLAG_DELETED) + if (flags & message::FLAG_DELETED) { m_messageInfos[num].type = messageInfos::TYPE_DELETED; - else + } else { m_messageInfos[num].type = messageInfos::TYPE_CUR; + } m_messageInfos[num].path = newPath; - } - catch (exceptions::filesystem_exception& e) - { + + } catch (exceptions::filesystem_exception& e) { + // Ignore (not important) } } // Update local flags - switch (mode) - { - case message::FLAG_MODE_ADD: - { - for (std::vector <maildirMessage*>::iterator it = - m_messages.begin() ; it != m_messages.end() ; ++it) - { - if (std::binary_search(nums.begin(), nums.end(), (*it)->getNumber()) && - (*it)->m_flags != maildirMessage::FLAG_UNDEFINED) - { - (*it)->m_flags |= flags; + switch (mode) { + + case message::FLAG_MODE_ADD: { + + for (std::vector <maildirMessage*>::iterator it = + m_messages.begin() ; it != m_messages.end() ; ++it) { + + if (std::binary_search(nums.begin(), nums.end(), (*it)->getNumber()) && + (*it)->m_flags != maildirMessage::FLAG_UNDEFINED) { + + (*it)->m_flags |= flags; + } } + + break; } + case message::FLAG_MODE_REMOVE: { - break; - } - case message::FLAG_MODE_REMOVE: - { - for (std::vector <maildirMessage*>::iterator it = - m_messages.begin() ; it != m_messages.end() ; ++it) - { - if (std::binary_search(nums.begin(), nums.end(), (*it)->getNumber()) && - (*it)->m_flags != maildirMessage::FLAG_UNDEFINED) - { - (*it)->m_flags &= ~flags; + for (std::vector <maildirMessage*>::iterator it = + m_messages.begin() ; it != m_messages.end() ; ++it) { + + if (std::binary_search(nums.begin(), nums.end(), (*it)->getNumber()) && + (*it)->m_flags != maildirMessage::FLAG_UNDEFINED) { + + (*it)->m_flags &= ~flags; + } } + + break; } + default: + case message::FLAG_MODE_SET: { - break; - } - default: - case message::FLAG_MODE_SET: - { - for (std::vector <maildirMessage*>::iterator it = - m_messages.begin() ; it != m_messages.end() ; ++it) - { - if (std::binary_search(nums.begin(), nums.end(), (*it)->getNumber()) && - (*it)->m_flags != maildirMessage::FLAG_UNDEFINED) - { - (*it)->m_flags = flags; + for (std::vector <maildirMessage*>::iterator it = + m_messages.begin() ; it != m_messages.end() ; ++it) { + + if (std::binary_search(nums.begin(), nums.end(), (*it)->getNumber()) && + (*it)->m_flags != maildirMessage::FLAG_UNDEFINED) { + + (*it)->m_flags = flags; + } } - } - break; - } + break; + } } // Notify message flags changed shared_ptr <events::messageChangedEvent> event = - make_shared <events::messageChangedEvent> - (dynamicCast <folder>(shared_from_this()), - events::messageChangedEvent::TYPE_FLAGS, nums); + make_shared <events::messageChangedEvent>( + dynamicCast <folder>(shared_from_this()), + events::messageChangedEvent::TYPE_FLAGS, + nums + ); notifyMessageChanged(event); // TODO: notify other folders with the same path - } - else - { + + } else { + throw exceptions::operation_not_supported(); } } -messageSet maildirFolder::addMessage - (shared_ptr <vmime::message> msg, const int flags, - vmime::datetime* date, utility::progressListener* progress) -{ +messageSet maildirFolder::addMessage( + const shared_ptr <vmime::message>& msg, + const int flags, + vmime::datetime* date, + utility::progressListener* progress +) { + std::ostringstream oss; utility::outputStreamAdapter ossAdapter(oss); @@ -723,50 +766,50 @@ messageSet maildirFolder::addMessage } -messageSet maildirFolder::addMessage - (utility::inputStream& is, const size_t size, - const int flags, vmime::datetime* /* date */, utility::progressListener* progress) -{ +messageSet maildirFolder::addMessage( + utility::inputStream& is, + const size_t size, + const int flags, + vmime::datetime* /* date */, + utility::progressListener* progress +) { + shared_ptr <maildirStore> store = m_store.lock(); - if (!store) + if (!store) { throw exceptions::illegal_state("Store disconnected"); - else if (!isOpen()) + } else if (!isOpen()) { throw exceptions::illegal_state("Folder not open"); - else if (m_mode == MODE_READ_ONLY) + } else if (m_mode == MODE_READ_ONLY) { throw exceptions::illegal_state("Folder is read-only"); + } shared_ptr <utility::fileSystemFactory> fsf = platform::getHandler()->getFileSystemFactory(); utility::file::path tmpDirPath = store->getFormat()-> folderPathToFileSystemPath(m_path,maildirFormat::TMP_DIRECTORY); utility::file::path dstDirPath = store->getFormat()-> - folderPathToFileSystemPath(m_path, + folderPathToFileSystemPath( + m_path, flags == message::FLAG_RECENT ? maildirFormat::NEW_DIRECTORY : - maildirFormat::CUR_DIRECTORY); + maildirFormat::CUR_DIRECTORY + ); const utility::file::path::component filename = - maildirUtils::buildFilename(maildirUtils::generateId(), - ((flags == -1) ? 0 : flags)); + maildirUtils::buildFilename(maildirUtils::generateId(), ((flags == -1) ? 0 : flags)); - try - { + try { shared_ptr <utility::file> tmpDir = fsf->create(tmpDirPath); tmpDir->createDirectory(true); - } - catch (exceptions::filesystem_exception&) - { + } catch (exceptions::filesystem_exception&) { // Don't throw now, it will fail later... } - try - { + try { shared_ptr <utility::file> curDir = fsf->create(dstDirPath); curDir->createDirectory(true); - } - catch (exceptions::filesystem_exception&) - { + } catch (exceptions::filesystem_exception&) { // Don't throw now, it will fail later... } @@ -781,26 +824,29 @@ messageSet maildirFolder::addMessage m_messageInfos.push_back(msgInfos); m_messageCount++; - if ((flags == -1) || !(flags & message::FLAG_SEEN)) + if ((flags == -1) || !(flags & message::FLAG_SEEN)) { m_unreadMessageCount++; + } // Notification std::vector <size_t> nums; nums.push_back(m_messageCount); shared_ptr <events::messageCountEvent> event = - make_shared <events::messageCountEvent> - (dynamicCast <folder>(shared_from_this()), - events::messageCountEvent::TYPE_ADDED, nums); + make_shared <events::messageCountEvent>( + dynamicCast <folder>(shared_from_this()), + events::messageCountEvent::TYPE_ADDED, + nums + ); notifyMessageCount(event); // Notify folders with the same path for (std::list <maildirFolder*>::iterator it = store->m_folders.begin() ; - it != store->m_folders.end() ; ++it) - { - if ((*it) != this && (*it)->getFullPath() == m_path) - { + it != store->m_folders.end() ; ++it) { + + if ((*it) != this && (*it)->getFullPath() == m_path) { + (*it)->m_messageCount = m_messageCount; (*it)->m_unreadMessageCount = m_unreadMessageCount; @@ -808,9 +854,11 @@ messageSet maildirFolder::addMessage std::copy(m_messageInfos.begin(), m_messageInfos.end(), (*it)->m_messageInfos.begin()); shared_ptr <events::messageCountEvent> event = - make_shared <events::messageCountEvent> - (dynamicCast <folder>((*it)->shared_from_this()), - events::messageCountEvent::TYPE_ADDED, nums); + make_shared <events::messageCountEvent>( + dynamicCast <folder>((*it)->shared_from_this()), + events::messageCountEvent::TYPE_ADDED, + nums + ); (*it)->notifyMessageCount(event); } @@ -820,22 +868,25 @@ messageSet maildirFolder::addMessage } -void maildirFolder::copyMessageImpl(const utility::file::path& tmpDirPath, +void maildirFolder::copyMessageImpl( + const utility::file::path& tmpDirPath, const utility::file::path& dstDirPath, const utility::file::path::component& filename, utility::inputStream& is, const size_t size, - utility::progressListener* progress) -{ + utility::progressListener* progress +) { + shared_ptr <utility::fileSystemFactory> fsf = platform::getHandler()->getFileSystemFactory(); shared_ptr <utility::file> file = fsf->create(tmpDirPath / filename); - if (progress) + if (progress) { progress->start(size); + } // First, write the message into 'tmp'... - try - { + try { + file->createFile(); shared_ptr <utility::fileWriter> fw = file->getFileWriter(); @@ -844,35 +895,33 @@ void maildirFolder::copyMessageImpl(const utility::file::path& tmpDirPath, byte_t buffer[65536]; size_t total = 0; - while (!is.eof()) - { + while (!is.eof()) { + const size_t read = is.read(buffer, sizeof(buffer)); - if (read != 0) - { + if (read != 0) { os->write(buffer, read); total += read; } - if (progress) + if (progress) { progress->progress(total, size); + } } os->flush(); - } - catch (exception& e) - { - if (progress) + + } catch (exception& e) { + + if (progress) { progress->stop(size); + } // Delete temporary file - try - { + try { shared_ptr <utility::file> file = fsf->create(tmpDirPath / filename); file->remove(); - } - catch (exceptions::filesystem_exception&) - { + } catch (exceptions::filesystem_exception&) { // Ignore } @@ -880,48 +929,51 @@ void maildirFolder::copyMessageImpl(const utility::file::path& tmpDirPath, } // ...then, move it to 'cur' - try - { + try { + file->rename(dstDirPath / filename); - } - catch (exception& e) - { - if (progress) + + } catch (exception& e) { + + if (progress) { progress->stop(size); + } // Delete temporary file - try - { + try { + file->remove(); shared_ptr <utility::file> file = fsf->create(dstDirPath / filename); file->remove(); - } - catch (exceptions::filesystem_exception&) - { + + } catch (exceptions::filesystem_exception&) { + // Ignore } throw exceptions::command_error("ADD", "", "", e); } - if (progress) + if (progress) { progress->stop(size); + } } -messageSet maildirFolder::copyMessages(const folder::path& dest, const messageSet& msgs) -{ +messageSet maildirFolder::copyMessages(const folder::path& dest, const messageSet& msgs) { + shared_ptr <maildirStore> store = m_store.lock(); - if (!store) + if (!store) { throw exceptions::illegal_state("Store disconnected"); - else if (!isOpen()) + } else if (!isOpen()) { throw exceptions::illegal_state("Folder not open"); + } shared_ptr <utility::fileSystemFactory> fsf = platform::getHandler()->getFileSystemFactory(); - utility::file::path curDirPath = store->getFormat()->folderPathToFileSystemPath - (m_path, maildirFormat::CUR_DIRECTORY); + utility::file::path curDirPath = + store->getFormat()->folderPathToFileSystemPath(m_path, maildirFormat::CUR_DIRECTORY); utility::file::path destCurDirPath = store->getFormat()-> folderPathToFileSystemPath(dest, maildirFormat::CUR_DIRECTORY); @@ -929,34 +981,34 @@ messageSet maildirFolder::copyMessages(const folder::path& dest, const messageSe folderPathToFileSystemPath(dest, maildirFormat::TMP_DIRECTORY); // Create destination directories - try - { + try { + shared_ptr <utility::file> destTmpDir = fsf->create(destTmpDirPath); destTmpDir->createDirectory(true); - } - catch (exceptions::filesystem_exception&) - { + + } catch (exceptions::filesystem_exception&) { + // Don't throw now, it will fail later... } - try - { + try { + shared_ptr <utility::file> destCurDir = fsf->create(destCurDirPath); destCurDir->createDirectory(true); - } - catch (exceptions::filesystem_exception&) - { + + } catch (exceptions::filesystem_exception&) { + // Don't throw now, it will fail later... } // Copy messages const std::vector <size_t> nums = maildirUtils::messageSetToNumberList(msgs, m_messageCount); - try - { + try { + for (std::vector <size_t>::const_iterator it = - nums.begin() ; it != nums.end() ; ++it) - { + nums.begin() ; it != nums.end() ; ++it) { + const size_t num = *it; const messageInfos& msg = m_messageInfos[num - 1]; const int flags = maildirUtils::extractFlags(msg.path); @@ -971,9 +1023,9 @@ messageSet maildirFolder::copyMessages(const folder::path& dest, const messageSe copyMessageImpl(destTmpDirPath, destCurDirPath, filename, *is, file->getLength(), NULL); } - } - catch (exception& e) - { + + } catch (exception& e) { + notifyMessagesCopied(dest); throw exceptions::command_error("COPY", "", "", e); } @@ -984,15 +1036,15 @@ messageSet maildirFolder::copyMessages(const folder::path& dest, const messageSe } -void maildirFolder::notifyMessagesCopied(const folder::path& dest) -{ +void maildirFolder::notifyMessagesCopied(const folder::path& dest) { + shared_ptr <maildirStore> store = m_store.lock(); for (std::list <maildirFolder*>::iterator it = store->m_folders.begin() ; - it != store->m_folders.end() ; ++it) - { - if ((*it) != this && (*it)->getFullPath() == dest) - { + it != store->m_folders.end() ; ++it) { + + if ((*it) != this && (*it)->getFullPath() == dest) { + // We only need to update the first folder we found as calling // status() will notify all the folders with the same path. size_t count, unseen; @@ -1004,8 +1056,8 @@ void maildirFolder::notifyMessagesCopied(const folder::path& dest) } -void maildirFolder::status(size_t& count, size_t& unseen) -{ +void maildirFolder::status(size_t& count, size_t& unseen) { + count = 0; unseen = 0; @@ -1018,8 +1070,8 @@ void maildirFolder::status(size_t& count, size_t& unseen) } -shared_ptr <folderStatus> maildirFolder::getStatus() -{ +shared_ptr <folderStatus> maildirFolder::getStatus() { + shared_ptr <maildirStore> store = m_store.lock(); const size_t oldCount = m_messageCount; @@ -1032,27 +1084,30 @@ shared_ptr <folderStatus> maildirFolder::getStatus() status->setUnseenCount(m_unreadMessageCount); // Notify message count changed (new messages) - if (m_messageCount > oldCount) - { + if (m_messageCount > oldCount) { + std::vector <size_t> nums; nums.reserve(m_messageCount - oldCount); - for (size_t i = oldCount + 1, j = 0 ; i <= m_messageCount ; ++i, ++j) + for (size_t i = oldCount + 1, j = 0 ; i <= m_messageCount ; ++i, ++j) { nums[j] = i; + } shared_ptr <events::messageCountEvent> event = - make_shared <events::messageCountEvent> - (dynamicCast <folder>(shared_from_this()), - events::messageCountEvent::TYPE_ADDED, nums); + make_shared <events::messageCountEvent>( + dynamicCast <folder>(shared_from_this()), + events::messageCountEvent::TYPE_ADDED, + nums + ); notifyMessageCount(event); // Notify folders with the same path for (std::list <maildirFolder*>::iterator it = store->m_folders.begin() ; - it != store->m_folders.end() ; ++it) - { - if ((*it) != this && (*it)->getFullPath() == m_path) - { + it != store->m_folders.end() ; ++it) { + + if ((*it) != this && (*it)->getFullPath() == m_path) { + (*it)->m_messageCount = m_messageCount; (*it)->m_unreadMessageCount = m_unreadMessageCount; @@ -1060,9 +1115,11 @@ shared_ptr <folderStatus> maildirFolder::getStatus() std::copy(m_messageInfos.begin(), m_messageInfos.end(), (*it)->m_messageInfos.begin()); shared_ptr <events::messageCountEvent> event = - make_shared <events::messageCountEvent> - (dynamicCast <folder>((*it)->shared_from_this()), - events::messageCountEvent::TYPE_ADDED, nums); + make_shared <events::messageCountEvent>( + dynamicCast <folder>((*it)->shared_from_this()), + events::messageCountEvent::TYPE_ADDED, + nums + ); (*it)->notifyMessageCount(event); } @@ -1073,16 +1130,17 @@ shared_ptr <folderStatus> maildirFolder::getStatus() } -void maildirFolder::expunge() -{ +void maildirFolder::expunge() { + shared_ptr <maildirStore> store = m_store.lock(); - if (!store) + if (!store) { throw exceptions::illegal_state("Store disconnected"); - else if (!isOpen()) + } else if (!isOpen()) { throw exceptions::illegal_state("Folder not open"); - else if (m_mode == MODE_READ_ONLY) + } else if (m_mode == MODE_READ_ONLY) { throw exceptions::illegal_state("Folder is read-only"); + } shared_ptr <utility::fileSystemFactory> fsf = platform::getHandler()->getFileSystemFactory(); @@ -1092,43 +1150,43 @@ void maildirFolder::expunge() std::vector <size_t> nums; size_t unreadCount = 0; - for (size_t num = 1 ; num <= m_messageCount ; ++num) - { + for (size_t num = 1 ; num <= m_messageCount ; ++num) { + messageInfos& infos = m_messageInfos[num - 1]; - if (infos.type == messageInfos::TYPE_DELETED) - { + if (infos.type == messageInfos::TYPE_DELETED) { + nums.push_back(num); for (std::vector <maildirMessage*>::iterator it = - m_messages.begin() ; it != m_messages.end() ; ++it) - { - if ((*it)->m_num == num) + m_messages.begin() ; it != m_messages.end() ; ++it) { + + if ((*it)->m_num == num) { (*it)->m_expunged = true; - else if ((*it)->m_num > num) + } else if ((*it)->m_num > num) { (*it)->m_num--; + } } - if (maildirUtils::extractFlags(infos.path) & message::FLAG_SEEN) + if (maildirUtils::extractFlags(infos.path) & message::FLAG_SEEN) { ++unreadCount; + } // Delete file from file system - try - { + try { shared_ptr <utility::file> file = fsf->create(curDirPath / infos.path); file->remove(); - } - catch (exceptions::filesystem_exception& e) - { + } catch (exceptions::filesystem_exception& e) { // Ignore (not important) } } } - if (!nums.empty()) - { - for (std::vector <size_t>::size_type i = nums.size() ; i != 0 ; --i) + if (!nums.empty()) { + + for (std::vector <size_t>::size_type i = nums.size() ; i != 0 ; --i) { m_messageInfos.erase(m_messageInfos.begin() + (i - 1)); + } } m_messageCount -= static_cast <size_t>(nums.size()); @@ -1136,18 +1194,20 @@ void maildirFolder::expunge() // Notify message expunged shared_ptr <events::messageCountEvent> event = - make_shared <events::messageCountEvent> - (dynamicCast <folder>(shared_from_this()), - events::messageCountEvent::TYPE_REMOVED, nums); + make_shared <events::messageCountEvent>( + dynamicCast <folder>(shared_from_this()), + events::messageCountEvent::TYPE_REMOVED, + nums + ); notifyMessageCount(event); // Notify folders with the same path for (std::list <maildirFolder*>::iterator it = store->m_folders.begin() ; - it != store->m_folders.end() ; ++it) - { - if ((*it) != this && (*it)->getFullPath() == m_path) - { + it != store->m_folders.end() ; ++it) { + + if ((*it) != this && (*it)->getFullPath() == m_path) { + (*it)->m_messageCount = m_messageCount; (*it)->m_unreadMessageCount = m_unreadMessageCount; @@ -1155,9 +1215,11 @@ void maildirFolder::expunge() std::copy(m_messageInfos.begin(), m_messageInfos.end(), (*it)->m_messageInfos.begin()); shared_ptr <events::messageCountEvent> event = - make_shared <events::messageCountEvent> - (dynamicCast <folder>((*it)->shared_from_this()), - events::messageCountEvent::TYPE_REMOVED, nums); + make_shared <events::messageCountEvent>( + dynamicCast <folder>((*it)->shared_from_this()), + events::messageCountEvent::TYPE_REMOVED, + nums + ); (*it)->notifyMessageCount(event); } @@ -1165,81 +1227,99 @@ void maildirFolder::expunge() } -shared_ptr <folder> maildirFolder::getParent() -{ - if (m_path.isEmpty()) +shared_ptr <folder> maildirFolder::getParent() { + + if (m_path.isEmpty()) { return null; - else + } else { return shared_ptr <maildirFolder>(new maildirFolder(m_path.getParent(), m_store.lock())); + } } -shared_ptr <const store> maildirFolder::getStore() const -{ +shared_ptr <const store> maildirFolder::getStore() const { + return m_store.lock(); } -shared_ptr <store> maildirFolder::getStore() -{ +shared_ptr <store> maildirFolder::getStore() { + return m_store.lock(); } -void maildirFolder::fetchMessages(std::vector <shared_ptr <message> >& msg, - const fetchAttributes& options, utility::progressListener* progress) -{ +void maildirFolder::fetchMessages( + std::vector <shared_ptr <message> >& msg, + const fetchAttributes& options, + utility::progressListener* progress +) { + shared_ptr <maildirStore> store = m_store.lock(); - if (!store) + if (!store) { throw exceptions::illegal_state("Store disconnected"); - else if (!isOpen()) + } else if (!isOpen()) { throw exceptions::illegal_state("Folder not open"); + } - if (msg.empty()) + if (msg.empty()) { return; + } const size_t total = msg.size(); size_t current = 0; - if (progress) + if (progress) { progress->start(total); + } shared_ptr <maildirFolder> thisFolder = dynamicCast <maildirFolder>(shared_from_this()); for (std::vector <shared_ptr <message> >::iterator it = msg.begin() ; - it != msg.end() ; ++it) - { + it != msg.end() ; ++it) { + dynamicCast <maildirMessage>(*it)->fetch(thisFolder, options); - if (progress) + if (progress) { progress->progress(++current, total); + } } - if (progress) + if (progress) { progress->stop(total); + } } -void maildirFolder::fetchMessage(shared_ptr <message> msg, const fetchAttributes& options) -{ +void maildirFolder::fetchMessage( + const shared_ptr <message>& msg, + const fetchAttributes& options +) { + shared_ptr <maildirStore> store = m_store.lock(); - if (!store) + if (!store) { throw exceptions::illegal_state("Store disconnected"); - else if (!isOpen()) + } else if (!isOpen()) { throw exceptions::illegal_state("Folder not open"); + } - dynamicCast <maildirMessage>(msg)->fetch - (dynamicCast <maildirFolder>(shared_from_this()), options); + dynamicCast <maildirMessage>(msg)->fetch( + dynamicCast <maildirFolder>(shared_from_this()), + options + ); } -std::vector <shared_ptr <message> > maildirFolder::getAndFetchMessages - (const messageSet& msgs, const fetchAttributes& attribs) -{ - if (msgs.isEmpty()) +std::vector <shared_ptr <message> > maildirFolder::getAndFetchMessages( + const messageSet& msgs, + const fetchAttributes& attribs +) { + + if (msgs.isEmpty()) { return std::vector <shared_ptr <message> >(); + } std::vector <shared_ptr <message> > messages = getMessages(msgs); fetchMessages(messages, attribs); @@ -1248,26 +1328,30 @@ std::vector <shared_ptr <message> > maildirFolder::getAndFetchMessages } -int maildirFolder::getFetchCapabilities() const -{ - return fetchAttributes::ENVELOPE | fetchAttributes::STRUCTURE | - fetchAttributes::CONTENT_INFO | fetchAttributes::FLAGS | - fetchAttributes::SIZE | fetchAttributes::FULL_HEADER | - fetchAttributes::UID | fetchAttributes::IMPORTANCE; +int maildirFolder::getFetchCapabilities() const { + + return fetchAttributes::ENVELOPE | + fetchAttributes::STRUCTURE | + fetchAttributes::CONTENT_INFO | + fetchAttributes::FLAGS | + fetchAttributes::SIZE | + fetchAttributes::FULL_HEADER | + fetchAttributes::UID | + fetchAttributes::IMPORTANCE; } -const utility::file::path maildirFolder::getMessageFSPath(const size_t number) const -{ +const utility::file::path maildirFolder::getMessageFSPath(const size_t number) const { + utility::file::path curDirPath = m_store.lock()->getFormat()-> folderPathToFileSystemPath(m_path, maildirFormat::CUR_DIRECTORY); - return (curDirPath / m_messageInfos[number - 1].path); + return curDirPath / m_messageInfos[number - 1].path; } -std::vector <size_t> maildirFolder::getMessageNumbersStartingOnUID(const message::uid& /* uid */) -{ +std::vector <size_t> maildirFolder::getMessageNumbersStartingOnUID(const message::uid& /* uid */) { + throw exceptions::operation_not_supported(); } diff --git a/src/vmime/net/maildir/maildirFolder.hpp b/src/vmime/net/maildir/maildirFolder.hpp index d6bdb7e8..24f2bf86 100644 --- a/src/vmime/net/maildir/maildirFolder.hpp +++ b/src/vmime/net/maildir/maildirFolder.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard <[email protected]> +// Copyright (C) 2002 Vincent Richard <[email protected]> // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License as @@ -52,16 +52,15 @@ class maildirMessage; /** maildir folder implementation. */ +class VMIME_EXPORT maildirFolder : public folder { -class VMIME_EXPORT maildirFolder : public folder -{ private: friend class maildirStore; friend class maildirMessage; maildirFolder(const maildirFolder&) : folder() { } - maildirFolder(const folder::path& path, shared_ptr <maildirStore> store); + maildirFolder(const folder::path& path, const shared_ptr <maildirStore>& store); public: @@ -97,10 +96,26 @@ public: void deleteMessages(const messageSet& msgs); - void setMessageFlags(const messageSet& msgs, const int flags, const int mode = message::FLAG_MODE_SET); - - messageSet addMessage(shared_ptr <vmime::message> msg, const int flags = -1, vmime::datetime* date = NULL, utility::progressListener* progress = NULL); - messageSet addMessage(utility::inputStream& is, const size_t size, const int flags = -1, vmime::datetime* date = NULL, utility::progressListener* progress = NULL); + void setMessageFlags( + const messageSet& msgs, + const int flags, + const int mode = message::FLAG_MODE_SET + ); + + messageSet addMessage( + const shared_ptr <vmime::message>& msg, + const int flags = -1, + vmime::datetime* date = NULL, + utility::progressListener* progress = NULL + ); + + messageSet addMessage( + utility::inputStream& is, + const size_t size, + const int flags = -1, + vmime::datetime* date = NULL, + utility::progressListener* progress = NULL + ); messageSet copyMessages(const folder::path& dest, const messageSet& msgs); @@ -115,11 +130,18 @@ public: shared_ptr <store> getStore(); - void fetchMessages(std::vector <shared_ptr <message> >& msg, const fetchAttributes& options, utility::progressListener* progress = NULL); - void fetchMessage(shared_ptr <message> msg, const fetchAttributes& options); + void fetchMessages( + std::vector <shared_ptr <message> >& msg, + const fetchAttributes& options, + utility::progressListener* progress = NULL + ); + + void fetchMessage(const shared_ptr <message>& msg, const fetchAttributes& options); - std::vector <shared_ptr <message> > getAndFetchMessages - (const messageSet& msgs, const fetchAttributes& attribs); + std::vector <shared_ptr <message> > getAndFetchMessages( + const messageSet& msgs, + const fetchAttributes& attribs + ); int getFetchCapabilities() const; @@ -161,10 +183,9 @@ private: size_t m_messageCount; // Store information about scanned messages - struct messageInfos - { - enum Type - { + struct messageInfos { + + enum Type { TYPE_CUR, TYPE_DELETED }; diff --git a/src/vmime/net/maildir/maildirFolderStatus.cpp b/src/vmime/net/maildir/maildirFolderStatus.cpp index 9817c1ca..7438d8cf 100644 --- a/src/vmime/net/maildir/maildirFolderStatus.cpp +++ b/src/vmime/net/maildir/maildirFolderStatus.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard <[email protected]> +// Copyright (C) 2002 Vincent Richard <[email protected]> // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License as @@ -37,45 +37,45 @@ namespace maildir { maildirFolderStatus::maildirFolderStatus() : m_count(0), - m_unseen(0) -{ + m_unseen(0) { + } maildirFolderStatus::maildirFolderStatus(const maildirFolderStatus& other) : folderStatus(), m_count(other.m_count), - m_unseen(other.m_unseen) -{ + m_unseen(other.m_unseen) { + } -size_t maildirFolderStatus::getMessageCount() const -{ +size_t maildirFolderStatus::getMessageCount() const { + return m_count; } -size_t maildirFolderStatus::getUnseenCount() const -{ +size_t maildirFolderStatus::getUnseenCount() const { + return m_unseen; } -void maildirFolderStatus::setMessageCount(const size_t count) -{ +void maildirFolderStatus::setMessageCount(const size_t count) { + m_count = count; } -void maildirFolderStatus::setUnseenCount(const size_t unseen) -{ +void maildirFolderStatus::setUnseenCount(const size_t unseen) { + m_unseen = unseen; } -shared_ptr <folderStatus> maildirFolderStatus::clone() const -{ +shared_ptr <folderStatus> maildirFolderStatus::clone() const { + return make_shared <maildirFolderStatus>(*this); } diff --git a/src/vmime/net/maildir/maildirFolderStatus.hpp b/src/vmime/net/maildir/maildirFolderStatus.hpp index 0921f01e..3b69375a 100644 --- a/src/vmime/net/maildir/maildirFolderStatus.hpp +++ b/src/vmime/net/maildir/maildirFolderStatus.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard <[email protected]> +// Copyright (C) 2002 Vincent Richard <[email protected]> // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License as @@ -41,9 +41,8 @@ namespace maildir { /** Holds the status of a Maildir folder. */ +class VMIME_EXPORT maildirFolderStatus : public folderStatus { -class VMIME_EXPORT maildirFolderStatus : public folderStatus -{ public: maildirFolderStatus(); diff --git a/src/vmime/net/maildir/maildirFormat.cpp b/src/vmime/net/maildir/maildirFormat.cpp index f7a3c8fe..914c0786 100644 --- a/src/vmime/net/maildir/maildirFormat.cpp +++ b/src/vmime/net/maildir/maildirFormat.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard <[email protected]> +// Copyright (C) 2002 Vincent Richard <[email protected]> // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License as @@ -50,15 +50,15 @@ const utility::file::path::component maildirFormat::NEW_DIR("new", vmime::charse // maildirFormat::context // -maildirFormat::context::context(shared_ptr <maildirStore> store) - : m_store(store) -{ +maildirFormat::context::context(const shared_ptr <maildirStore>& store) + : m_store(store) { + } -shared_ptr <maildirStore> maildirFormat::context::getStore() const -{ - return constCast <maildirStore>(m_store.lock()); +shared_ptr <maildirStore> maildirFormat::context::getStore() { + + return m_store.lock(); } @@ -66,34 +66,29 @@ shared_ptr <maildirStore> maildirFormat::context::getStore() const // maildirFormat // -maildirFormat::maildirFormat(shared_ptr <context> ctx) - : m_context(ctx) -{ -} - +maildirFormat::maildirFormat(const shared_ptr <context>& ctx) + : m_context(ctx) { -shared_ptr <maildirFormat::context> maildirFormat::getContext() -{ - return m_context; } -shared_ptr <const maildirFormat::context> maildirFormat::getContext() const -{ +shared_ptr <maildirFormat::context> maildirFormat::getContext() const { + return m_context; } // static -shared_ptr <maildirFormat> maildirFormat::detect(shared_ptr <maildirStore> store) -{ +shared_ptr <maildirFormat> maildirFormat::detect(const shared_ptr <maildirStore>& store) { + shared_ptr <context> ctx = make_shared <context>(store); // Try Courier format shared_ptr <maildirFormat> fmt = make_shared <format::courierMaildirFormat>(ctx); - if (fmt->supports()) + if (fmt->supports()) { return fmt; + } // Default is KMail format return make_shared <format::kmailMaildirFormat>(ctx); diff --git a/src/vmime/net/maildir/maildirFormat.hpp b/src/vmime/net/maildir/maildirFormat.hpp index c0daf288..9b9e0636 100644 --- a/src/vmime/net/maildir/maildirFormat.hpp +++ b/src/vmime/net/maildir/maildirFormat.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard <[email protected]> +// Copyright (C) 2002 Vincent Richard <[email protected]> // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License as @@ -45,19 +45,19 @@ namespace maildir { class maildirStore; -/** Interface for an object capable of reading a specific Maildir format. */ +/** Interface for an object capable of reading a specific Maildir format. + */ +class VMIME_EXPORT maildirFormat : public object { -class VMIME_EXPORT maildirFormat : public object -{ public: - class context : public object - { + class context : public object { + public: - context(shared_ptr <maildirStore> store); + context(const shared_ptr <maildirStore>& store); - shared_ptr <maildirStore> getStore() const; + shared_ptr <maildirStore> getStore(); private: @@ -66,8 +66,7 @@ public: /** Physical directory types. */ - enum DirectoryType - { + enum DirectoryType { ROOT_DIRECTORY, /**< Root directory. */ NEW_DIRECTORY, /**< Directory containing unread messages. */ CUR_DIRECTORY, /**< Directory containing messages that have been seen. */ @@ -125,8 +124,10 @@ public: * @param type type of directory to return * @return corresponding directory on the file system */ - virtual const utility::file::path folderPathToFileSystemPath - (const folder::path& path, const DirectoryType type) const = 0; + virtual const utility::file::path folderPathToFileSystemPath( + const folder::path& path, + const DirectoryType type + ) const = 0; /** List subfolders in the specified folder. * @@ -135,8 +136,10 @@ public: * returned; if set to false, only direct children are returned. * @return list of subfolders */ - virtual const std::vector <folder::path> listFolders - (const folder::path& root, const bool recursive) const = 0; + virtual const std::vector <folder::path> listFolders( + const folder::path& root, + const bool recursive + ) const = 0; /** Try to detect the format of the specified Maildir store. @@ -146,7 +149,7 @@ public: * @param store of which to detect format * @return a Maildir format implementation for the specified store */ - static shared_ptr <maildirFormat> detect(shared_ptr <maildirStore> store); + static shared_ptr <maildirFormat> detect(const shared_ptr <maildirStore>& store); protected: @@ -155,20 +158,14 @@ protected: static const utility::file::path::component NEW_DIR; /**< Unread messages. */ - maildirFormat(shared_ptr <context> ctx); + maildirFormat(const shared_ptr <context>& ctx); /** Returns the current context. * * @return current context */ - shared_ptr <context> getContext(); - - /** Returns the current context (const version). - * - * @return current context - */ - shared_ptr <const context> getContext() const; + shared_ptr <context> getContext() const; /** Quick checks whether this implementation can read the Maildir * format in the specified directory. diff --git a/src/vmime/net/maildir/maildirMessage.cpp b/src/vmime/net/maildir/maildirMessage.cpp index faf00f6a..ae99c597 100644 --- a/src/vmime/net/maildir/maildirMessage.cpp +++ b/src/vmime/net/maildir/maildirMessage.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard <[email protected]> +// Copyright (C) 2002 Vincent Richard <[email protected]> // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License as @@ -48,133 +48,161 @@ namespace net { namespace maildir { -maildirMessage::maildirMessage(shared_ptr <maildirFolder> folder, const size_t num) - : m_folder(folder), m_num(num), m_size(-1), m_flags(FLAG_UNDEFINED), - m_expunged(false), m_structure(null) -{ +maildirMessage::maildirMessage(const shared_ptr <maildirFolder>& folder, const size_t num) + : m_folder(folder), + m_num(num), + m_size(-1), + m_flags(FLAG_UNDEFINED), + m_expunged(false), + m_structure(null) { + folder->registerMessage(this); } -maildirMessage::~maildirMessage() -{ - try - { +maildirMessage::~maildirMessage() { + + try { + shared_ptr <maildirFolder> folder = m_folder.lock(); - if (folder) + if (folder) { folder->unregisterMessage(this); - } - catch (...) - { + } + + } catch (...) { + // Don't throw in destructor } } -void maildirMessage::onFolderClosed() -{ +void maildirMessage::onFolderClosed() { + m_folder.reset(); } -size_t maildirMessage::getNumber() const -{ - return (m_num); +size_t maildirMessage::getNumber() const { + + return m_num; } -const message::uid maildirMessage::getUID() const -{ - return (m_uid); +const message::uid maildirMessage::getUID() const { + + return m_uid; } -size_t maildirMessage::getSize() const -{ - if (m_size == static_cast <size_t>(-1)) +size_t maildirMessage::getSize() const { + + if (m_size == static_cast <size_t>(-1)) { throw exceptions::unfetched_object(); + } - return (m_size); + return m_size; } -bool maildirMessage::isExpunged() const -{ - return (m_expunged); +bool maildirMessage::isExpunged() const { + + return m_expunged; } -shared_ptr <const messageStructure> maildirMessage::getStructure() const -{ - if (m_structure == NULL) +shared_ptr <const messageStructure> maildirMessage::getStructure() const { + + if (!m_structure) { throw exceptions::unfetched_object(); + } return m_structure; } -shared_ptr <messageStructure> maildirMessage::getStructure() -{ - if (m_structure == NULL) +shared_ptr <messageStructure> maildirMessage::getStructure() { + + if (!m_structure) { throw exceptions::unfetched_object(); + } return m_structure; } -shared_ptr <const header> maildirMessage::getHeader() const -{ - if (m_header == NULL) +shared_ptr <const header> maildirMessage::getHeader() const { + + if (!m_header) { throw exceptions::unfetched_object(); + } - return (m_header); + return m_header; } -int maildirMessage::getFlags() const -{ - if (m_flags == FLAG_UNDEFINED) +int maildirMessage::getFlags() const { + + if (m_flags == FLAG_UNDEFINED) { throw exceptions::unfetched_object(); + } - return (m_flags); + return m_flags; } -void maildirMessage::setFlags(const int flags, const int mode) -{ +void maildirMessage::setFlags(const int flags, const int mode) { + shared_ptr <maildirFolder> folder = m_folder.lock(); - if (!folder) + if (!folder) { throw exceptions::folder_not_found(); + } folder->setMessageFlags(messageSet::byNumber(m_num), flags, mode); } -void maildirMessage::extract(utility::outputStream& os, - utility::progressListener* progress, const size_t start, - const size_t length, const bool peek) const -{ +void maildirMessage::extract( + utility::outputStream& os, + utility::progressListener* progress, + const size_t start, + const size_t length, + const bool peek +) const { + extractImpl(os, progress, 0, m_size, start, length, peek); } -void maildirMessage::extractPart(shared_ptr <const messagePart> p, utility::outputStream& os, - utility::progressListener* progress, const size_t start, - const size_t length, const bool peek) const -{ +void maildirMessage::extractPart( + const shared_ptr <const messagePart>& p, + utility::outputStream& os, + utility::progressListener* progress, + const size_t start, + const size_t length, + const bool peek +) const { + shared_ptr <const maildirMessagePart> mp = dynamicCast <const maildirMessagePart>(p); - extractImpl(os, progress, mp->getBodyParsedOffset(), mp->getBodyParsedLength(), - start, length, peek); + extractImpl( + os, progress, mp->getBodyParsedOffset(), mp->getBodyParsedLength(), + start, length, peek + ); } -void maildirMessage::extractImpl(utility::outputStream& os, utility::progressListener* progress, - const size_t start, const size_t length, const size_t partialStart, const size_t partialLength, - const bool /* peek */) const -{ +void maildirMessage::extractImpl( + utility::outputStream& os, + utility::progressListener* progress, + const size_t start, + const size_t length, + const size_t partialStart, + const size_t partialLength, + const bool /* peek */ +) const { + shared_ptr <const maildirFolder> folder = m_folder.lock(); shared_ptr <utility::fileSystemFactory> fsf = platform::getHandler()->getFileSystemFactory(); @@ -188,17 +216,21 @@ void maildirMessage::extractImpl(utility::outputStream& os, utility::progressLis is->skip(start + partialStart); byte_t buffer[8192]; - size_t remaining = (partialLength == static_cast <size_t>(-1) - ? length : std::min(partialLength, length)); + size_t remaining = + (partialLength == static_cast <size_t>(-1) + ? length + : std::min(partialLength, length) + ); const size_t total = remaining; size_t current = 0; - if (progress) + if (progress) { progress->start(total); + } + + while (!is->eof() && remaining > 0) { - while (!is->eof() && remaining > 0) - { const size_t read = is->read(buffer, std::min(remaining, sizeof(buffer))); remaining -= read; @@ -206,19 +238,21 @@ void maildirMessage::extractImpl(utility::outputStream& os, utility::progressLis os.write(buffer, read); - if (progress) + if (progress) { progress->progress(current, total); + } } - if (progress) + if (progress) { progress->stop(total); + } // TODO: mark as read unless 'peek' is set } -void maildirMessage::fetchPartHeader(shared_ptr <messagePart> p) -{ +void maildirMessage::fetchPartHeader(const shared_ptr <messagePart>& p) { + shared_ptr <maildirFolder> folder = m_folder.lock(); shared_ptr <maildirMessagePart> mp = dynamicCast <maildirMessagePart>(p); @@ -239,8 +273,8 @@ void maildirMessage::fetchPartHeader(shared_ptr <messagePart> p) string contents; contents.reserve(remaining); - while (!is->eof() && remaining > 0) - { + while (!is->eof() && remaining > 0) { + const size_t read = is->read(buffer, std::min(remaining, sizeof(buffer))); remaining -= read; @@ -252,71 +286,71 @@ void maildirMessage::fetchPartHeader(shared_ptr <messagePart> p) } -void maildirMessage::fetch(shared_ptr <maildirFolder> msgFolder, const fetchAttributes& options) -{ +void maildirMessage::fetch(const shared_ptr <maildirFolder>& msgFolder, const fetchAttributes& options) { + shared_ptr <maildirFolder> folder = m_folder.lock(); - if (folder != msgFolder) + if (folder != msgFolder) { throw exceptions::folder_not_found(); + } shared_ptr <utility::fileSystemFactory> fsf = platform::getHandler()->getFileSystemFactory(); const utility::file::path path = folder->getMessageFSPath(m_num); shared_ptr <utility::file> file = fsf->create(path); - if (options.has(fetchAttributes::FLAGS)) + if (options.has(fetchAttributes::FLAGS)) { m_flags = maildirUtils::extractFlags(path.getLastComponent()); + } - if (options.has(fetchAttributes::SIZE)) + if (options.has(fetchAttributes::SIZE)) { m_size = file->getLength(); + } - if (options.has(fetchAttributes::UID)) + if (options.has(fetchAttributes::UID)) { m_uid = maildirUtils::extractId(path.getLastComponent()).getBuffer(); + } if (options.has(fetchAttributes::ENVELOPE | fetchAttributes::CONTENT_INFO | fetchAttributes::FULL_HEADER | fetchAttributes::STRUCTURE | - fetchAttributes::IMPORTANCE)) - { + fetchAttributes::IMPORTANCE)) { + string contents; shared_ptr <utility::fileReader> reader = file->getFileReader(); shared_ptr <utility::inputStream> is = reader->getInputStream(); // Need whole message contents for structure - if (options.has(fetchAttributes::STRUCTURE)) - { + if (options.has(fetchAttributes::STRUCTURE)) { + byte_t buffer[16384]; contents.reserve(file->getLength()); - while (!is->eof()) - { + while (!is->eof()) { const size_t read = is->read(buffer, sizeof(buffer)); vmime::utility::stringUtils::appendBytesToString(contents, buffer, read); } - } + // Need only header - else - { + } else { + byte_t buffer[1024]; contents.reserve(4096); - while (!is->eof()) - { + while (!is->eof()) { + const size_t read = is->read(buffer, sizeof(buffer)); vmime::utility::stringUtils::appendBytesToString(contents, buffer, read); const size_t sep1 = contents.rfind("\r\n\r\n"); const size_t sep2 = contents.rfind("\n\n"); - if (sep1 != string::npos) - { + if (sep1 != string::npos) { contents.erase(contents.begin() + sep1 + 4, contents.end()); break; - } - else if (sep2 != string::npos) - { + } else if (sep2 != string::npos) { contents.erase(contents.begin() + sep2 + 2, contents.end()); break; } @@ -327,8 +361,7 @@ void maildirMessage::fetch(shared_ptr <maildirFolder> msgFolder, const fetchAttr msg.parse(contents); // Extract structure - if (options.has(fetchAttributes::STRUCTURE)) - { + if (options.has(fetchAttributes::STRUCTURE)) { m_structure = make_shared <maildirMessageStructure>(shared_ptr <maildirMessagePart>(), msg); } @@ -336,25 +369,26 @@ void maildirMessage::fetch(shared_ptr <maildirFolder> msgFolder, const fetchAttr if (options.has(fetchAttributes::ENVELOPE | fetchAttributes::CONTENT_INFO | fetchAttributes::FULL_HEADER | - fetchAttributes::IMPORTANCE)) - { + fetchAttributes::IMPORTANCE)) { + getOrCreateHeader()->copyFrom(*(msg.getHeader())); } } } -shared_ptr <header> maildirMessage::getOrCreateHeader() -{ - if (m_header != NULL) - return (m_header); - else +shared_ptr <header> maildirMessage::getOrCreateHeader() { + + if (m_header) { + return m_header; + } else { return (m_header = make_shared <header>()); + } } -shared_ptr <vmime::message> maildirMessage::getParsedMessage() -{ +shared_ptr <vmime::message> maildirMessage::getParsedMessage() { + std::ostringstream oss; utility::outputStreamAdapter os(oss); diff --git a/src/vmime/net/maildir/maildirMessage.hpp b/src/vmime/net/maildir/maildirMessage.hpp index 5cdabfc9..8cd0aac2 100644 --- a/src/vmime/net/maildir/maildirMessage.hpp +++ b/src/vmime/net/maildir/maildirMessage.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard <[email protected]> +// Copyright (C) 2002 Vincent Richard <[email protected]> // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License as @@ -45,16 +45,15 @@ class maildirFolder; /** maildir message implementation. */ +class VMIME_EXPORT maildirMessage : public message { -class VMIME_EXPORT maildirMessage : public message -{ friend class maildirFolder; maildirMessage(const maildirMessage&) : message() { } public: - maildirMessage(shared_ptr <maildirFolder> folder, const size_t num); + maildirMessage(const shared_ptr <maildirFolder>& folder, const size_t num); ~maildirMessage(); @@ -75,22 +74,44 @@ public: int getFlags() const; void setFlags(const int flags, const int mode = FLAG_MODE_SET); - void extract(utility::outputStream& os, utility::progressListener* progress = NULL, const size_t start = 0, const size_t length = -1, const bool peek = false) const; - void extractPart(shared_ptr <const messagePart> p, utility::outputStream& os, utility::progressListener* progress = NULL, const size_t start = 0, const size_t length = -1, const bool peek = false) const; - - void fetchPartHeader(shared_ptr <messagePart> p); + void extract( + utility::outputStream& os, + utility::progressListener* progress = NULL, + const size_t start = 0, + const size_t length = -1, + const bool peek = false + ) const; + + void extractPart( + const shared_ptr <const messagePart>& p, + utility::outputStream& os, + utility::progressListener* progress = NULL, + const size_t start = 0, + const size_t length = -1, + const bool peek = false + ) const; + + void fetchPartHeader(const shared_ptr <messagePart>& p); shared_ptr <vmime::message> getParsedMessage(); private: - void fetch(shared_ptr <maildirFolder> folder, const fetchAttributes& options); + void fetch(const shared_ptr <maildirFolder>& folder, const fetchAttributes& options); void onFolderClosed(); shared_ptr <header> getOrCreateHeader(); - void extractImpl(utility::outputStream& os, utility::progressListener* progress, const size_t start, const size_t length, const size_t partialStart, const size_t partialLength, const bool peek) const; + void extractImpl( + utility::outputStream& os, + utility::progressListener* progress, + const size_t start, + const size_t length, + const size_t partialStart, + const size_t partialLength, + const bool peek + ) const; weak_ptr <maildirFolder> m_folder; diff --git a/src/vmime/net/maildir/maildirMessagePart.cpp b/src/vmime/net/maildir/maildirMessagePart.cpp index 0b813749..9d30e24d 100644 --- a/src/vmime/net/maildir/maildirMessagePart.cpp +++ b/src/vmime/net/maildir/maildirMessagePart.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard <[email protected]> +// Copyright (C) 2002 Vincent Richard <[email protected]> // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License as @@ -36,9 +36,15 @@ namespace net { namespace maildir { -maildirMessagePart::maildirMessagePart(shared_ptr <maildirMessagePart> parent, const size_t number, const bodyPart& part) - : m_parent(parent), m_header(null), m_number(number) -{ +maildirMessagePart::maildirMessagePart( + const shared_ptr <maildirMessagePart>& parent, + const size_t number, + const bodyPart& part +) + : m_parent(parent), + m_header(null), + m_number(number) { + m_headerParsedOffset = part.getHeader()->getParsedOffset(); m_headerParsedLength = part.getHeader()->getParsedLength(); @@ -51,98 +57,104 @@ maildirMessagePart::maildirMessagePart(shared_ptr <maildirMessagePart> parent, c } -maildirMessagePart::~maildirMessagePart() -{ +maildirMessagePart::~maildirMessagePart() { + } -void maildirMessagePart::initStructure(const bodyPart& part) -{ - if (part.getBody()->getPartList().size() == 0) +void maildirMessagePart::initStructure(const bodyPart& part) { + + if (part.getBody()->getPartList().size() == 0) { + m_structure = null; - else - { - m_structure = make_shared <maildirMessageStructure> - (dynamicCast <maildirMessagePart>(shared_from_this()), - part.getBody()->getPartList()); + + } else { + + m_structure = make_shared <maildirMessageStructure>( + dynamicCast <maildirMessagePart>(shared_from_this()), part.getBody()->getPartList() + ); } } -shared_ptr <const messageStructure> maildirMessagePart::getStructure() const -{ - if (m_structure != NULL) +shared_ptr <const messageStructure> maildirMessagePart::getStructure() const { + + if (m_structure) { return m_structure; - else + } else { return maildirMessageStructure::emptyStructure(); + } } -shared_ptr <messageStructure> maildirMessagePart::getStructure() -{ - if (m_structure != NULL) +shared_ptr <messageStructure> maildirMessagePart::getStructure() { + + if (m_structure) { return m_structure; - else + } else { return maildirMessageStructure::emptyStructure(); + } } -const mediaType& maildirMessagePart::getType() const -{ +const mediaType& maildirMessagePart::getType() const { + return m_mediaType; } -size_t maildirMessagePart::getSize() const -{ +size_t maildirMessagePart::getSize() const { + return m_size; } -size_t maildirMessagePart::getNumber() const -{ +size_t maildirMessagePart::getNumber() const { + return m_number; } -shared_ptr <const header> maildirMessagePart::getHeader() const -{ - if (m_header == NULL) +shared_ptr <const header> maildirMessagePart::getHeader() const { + + if (!m_header) { throw exceptions::unfetched_object(); - else + } else { return m_header; + } } -header& maildirMessagePart::getOrCreateHeader() -{ - if (m_header != NULL) +header& maildirMessagePart::getOrCreateHeader() { + + if (m_header) { return *m_header; - else + } else { return *(m_header = make_shared <header>()); + } } -size_t maildirMessagePart::getHeaderParsedOffset() const -{ +size_t maildirMessagePart::getHeaderParsedOffset() const { + return m_headerParsedOffset; } -size_t maildirMessagePart::getHeaderParsedLength() const -{ +size_t maildirMessagePart::getHeaderParsedLength() const { + return m_headerParsedLength; } -size_t maildirMessagePart::getBodyParsedOffset() const -{ +size_t maildirMessagePart::getBodyParsedOffset() const { + return m_bodyParsedOffset; } -size_t maildirMessagePart::getBodyParsedLength() const -{ +size_t maildirMessagePart::getBodyParsedLength() const { + return m_bodyParsedLength; } diff --git a/src/vmime/net/maildir/maildirMessagePart.hpp b/src/vmime/net/maildir/maildirMessagePart.hpp index db1aeb75..dd863a2b 100644 --- a/src/vmime/net/maildir/maildirMessagePart.hpp +++ b/src/vmime/net/maildir/maildirMessagePart.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard <[email protected]> +// Copyright (C) 2002 Vincent Richard <[email protected]> // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License as @@ -46,7 +46,12 @@ class maildirMessagePart : public messagePart { public: - maildirMessagePart(shared_ptr <maildirMessagePart> parent, const size_t number, const bodyPart& part); + maildirMessagePart( + const shared_ptr <maildirMessagePart>& parent, + const size_t number, + const bodyPart& part + ); + ~maildirMessagePart(); diff --git a/src/vmime/net/maildir/maildirMessageStructure.cpp b/src/vmime/net/maildir/maildirMessageStructure.cpp index 54eba981..1e2f2cc5 100644 --- a/src/vmime/net/maildir/maildirMessageStructure.cpp +++ b/src/vmime/net/maildir/maildirMessageStructure.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard <[email protected]> +// Copyright (C) 2002 Vincent Richard <[email protected]> // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License as @@ -44,8 +44,11 @@ maildirMessageStructure::maildirMessageStructure() } -maildirMessageStructure::maildirMessageStructure(shared_ptr <maildirMessagePart> parent, const bodyPart& part) -{ +maildirMessageStructure::maildirMessageStructure( + const shared_ptr <maildirMessagePart>& parent, + const bodyPart& part +) { + shared_ptr <maildirMessagePart> mpart = make_shared <maildirMessagePart>(parent, 0, part); mpart->initStructure(part); @@ -53,10 +56,13 @@ maildirMessageStructure::maildirMessageStructure(shared_ptr <maildirMessagePart> } -maildirMessageStructure::maildirMessageStructure(shared_ptr <maildirMessagePart> parent, const std::vector <shared_ptr <const vmime::bodyPart> >& list) -{ - for (size_t i = 0 ; i < list.size() ; ++i) - { +maildirMessageStructure::maildirMessageStructure( + const shared_ptr <maildirMessagePart>& parent, + const std::vector <shared_ptr <const vmime::bodyPart> >& list +) { + + for (size_t i = 0 ; i < list.size() ; ++i) { + shared_ptr <maildirMessagePart> mpart = make_shared <maildirMessagePart>(parent, i, *list[i]); mpart->initStructure(*list[i]); @@ -65,27 +71,27 @@ maildirMessageStructure::maildirMessageStructure(shared_ptr <maildirMessagePart> } -shared_ptr <const messagePart> maildirMessageStructure::getPartAt(const size_t x) const -{ +shared_ptr <const messagePart> maildirMessageStructure::getPartAt(const size_t x) const { + return m_parts[x]; } -shared_ptr <messagePart> maildirMessageStructure::getPartAt(const size_t x) -{ +shared_ptr <messagePart> maildirMessageStructure::getPartAt(const size_t x) { + return m_parts[x]; } -size_t maildirMessageStructure::getPartCount() const -{ +size_t maildirMessageStructure::getPartCount() const { + return m_parts.size(); } // static -shared_ptr <maildirMessageStructure> maildirMessageStructure::emptyStructure() -{ +shared_ptr <maildirMessageStructure> maildirMessageStructure::emptyStructure() { + return m_emptyStructure; } diff --git a/src/vmime/net/maildir/maildirMessageStructure.hpp b/src/vmime/net/maildir/maildirMessageStructure.hpp index a43fc15c..1a20ea45 100644 --- a/src/vmime/net/maildir/maildirMessageStructure.hpp +++ b/src/vmime/net/maildir/maildirMessageStructure.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard <[email protected]> +// Copyright (C) 2002 Vincent Richard <[email protected]> // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License as @@ -42,13 +42,19 @@ namespace maildir { class maildirMessagePart; -class maildirMessageStructure : public messageStructure -{ +class maildirMessageStructure : public messageStructure { + public: maildirMessageStructure(); - maildirMessageStructure(shared_ptr <maildirMessagePart> parent, const bodyPart& part); - maildirMessageStructure(shared_ptr <maildirMessagePart> parent, const std::vector <shared_ptr <const vmime::bodyPart> >& list); + maildirMessageStructure( + const shared_ptr <maildirMessagePart>& parent, + const bodyPart& part + ); + maildirMessageStructure( + const shared_ptr <maildirMessagePart>& parent, + const std::vector <shared_ptr <const vmime::bodyPart> >& list + ); shared_ptr <const messagePart> getPartAt(const size_t x) const; diff --git a/src/vmime/net/maildir/maildirServiceInfos.cpp b/src/vmime/net/maildir/maildirServiceInfos.cpp index 974a0c21..f9d92d37 100644 --- a/src/vmime/net/maildir/maildirServiceInfos.cpp +++ b/src/vmime/net/maildir/maildirServiceInfos.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard <[email protected]> +// Copyright (C) 2002 Vincent Richard <[email protected]> // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License as @@ -35,21 +35,20 @@ namespace net { namespace maildir { -maildirServiceInfos::maildirServiceInfos() -{ +maildirServiceInfos::maildirServiceInfos() { + } -const string maildirServiceInfos::getPropertyPrefix() const -{ +const string maildirServiceInfos::getPropertyPrefix() const { + return "store.maildir."; } -const maildirServiceInfos::props& maildirServiceInfos::getProperties() const -{ - static props maildirProps = - { +const maildirServiceInfos::props& maildirServiceInfos::getProperties() const { + + static props maildirProps = { property(serviceInfos::property::SERVER_ROOTPATH, serviceInfos::property::FLAG_REQUIRED) }; @@ -57,8 +56,8 @@ const maildirServiceInfos::props& maildirServiceInfos::getProperties() const } -const std::vector <serviceInfos::property> maildirServiceInfos::getAvailableProperties() const -{ +const std::vector <serviceInfos::property> maildirServiceInfos::getAvailableProperties() const { + std::vector <property> list; const props& p = getProperties(); diff --git a/src/vmime/net/maildir/maildirServiceInfos.hpp b/src/vmime/net/maildir/maildirServiceInfos.hpp index 70ddc6dc..827a7d78 100644 --- a/src/vmime/net/maildir/maildirServiceInfos.hpp +++ b/src/vmime/net/maildir/maildirServiceInfos.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard <[email protected]> +// Copyright (C) 2002 Vincent Richard <[email protected]> // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License as @@ -41,15 +41,13 @@ namespace maildir { /** Information about maildir service. */ +class VMIME_EXPORT maildirServiceInfos : public serviceInfos { -class VMIME_EXPORT maildirServiceInfos : public serviceInfos -{ public: maildirServiceInfos(); - struct props - { + struct props { serviceInfos::property PROPERTY_SERVER_ROOTPATH; }; diff --git a/src/vmime/net/maildir/maildirStore.cpp b/src/vmime/net/maildir/maildirStore.cpp index 3c777551..a994f45c 100644 --- a/src/vmime/net/maildir/maildirStore.cpp +++ b/src/vmime/net/maildir/maildirStore.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard <[email protected]> +// Copyright (C) 2002 Vincent Richard <[email protected]> // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License as @@ -52,90 +52,112 @@ namespace net { namespace maildir { -maildirStore::maildirStore(shared_ptr <session> sess, shared_ptr <security::authenticator> auth) - : store(sess, getInfosInstance(), auth), m_connected(false) -{ +maildirStore::maildirStore( + const shared_ptr <session>& sess, + const shared_ptr <security::authenticator>& auth +) + : store(sess, getInfosInstance(), auth), + m_connected(false) { + } -maildirStore::~maildirStore() -{ - try - { - if (isConnected()) +maildirStore::~maildirStore() { + + try { + + if (isConnected()) { disconnect(); - } - catch (...) - { + } + + } catch (...) { + // Don't throw in destructor } } -const string maildirStore::getProtocolName() const -{ +const string maildirStore::getProtocolName() const { + return "maildir"; } -shared_ptr <folder> maildirStore::getRootFolder() -{ - if (!isConnected()) +shared_ptr <folder> maildirStore::getRootFolder() { + + if (!isConnected()) { throw exceptions::illegal_state("Not connected"); + } - return shared_ptr <maildirFolder> - (new maildirFolder(folder::path(), - dynamicCast <maildirStore>(shared_from_this()))); + return shared_ptr <maildirFolder>( + new maildirFolder( + folder::path(), + dynamicCast <maildirStore>(shared_from_this()) + ) + ); } -shared_ptr <folder> maildirStore::getDefaultFolder() -{ - if (!isConnected()) +shared_ptr <folder> maildirStore::getDefaultFolder() { + + if (!isConnected()) { throw exceptions::illegal_state("Not connected"); + } - return shared_ptr <maildirFolder> - (new maildirFolder(folder::path::component("inbox"), - dynamicCast <maildirStore>(shared_from_this()))); + return shared_ptr <maildirFolder>( + new maildirFolder( + folder::path::component("inbox"), + dynamicCast <maildirStore>(shared_from_this()) + ) + ); } -shared_ptr <folder> maildirStore::getFolder(const folder::path& path) -{ - if (!isConnected()) +shared_ptr <folder> maildirStore::getFolder(const folder::path& path) { + + if (!isConnected()) { throw exceptions::illegal_state("Not connected"); + } - return shared_ptr <maildirFolder> - (new maildirFolder(path, dynamicCast <maildirStore>(shared_from_this()))); + return shared_ptr <maildirFolder>( + new maildirFolder( + path, + dynamicCast <maildirStore>(shared_from_this()) + ) + ); } -bool maildirStore::isValidFolderName(const folder::path::component& name) const -{ - if (!platform::getHandler()->getFileSystemFactory()->isValidPathComponent(name)) +bool maildirStore::isValidFolderName(const folder::path::component& name) const { + + if (!platform::getHandler()->getFileSystemFactory()->isValidPathComponent(name)) { return false; + } const string& buf = name.getBuffer(); // Name cannot start/end with spaces - if (utility::stringUtils::trim(buf) != buf) + if (utility::stringUtils::trim(buf) != buf) { return false; + } // Name cannot start with '.' const size_t length = buf.length(); size_t pos = 0; - while ((pos < length) && (buf[pos] == '.')) + while ((pos < length) && (buf[pos] == '.')) { ++pos; + } return (pos == 0); } -void maildirStore::connect() -{ - if (isConnected()) +void maildirStore::connect() { + + if (isConnected()) { throw exceptions::already_connected(); + } // Get root directory shared_ptr <utility::fileSystemFactory> fsf = platform::getHandler()->getFileSystemFactory(); @@ -145,14 +167,11 @@ void maildirStore::connect() shared_ptr <utility::file> rootDir = fsf->create(m_fsPath); // Try to create the root directory if it does not exist - if (!(rootDir->exists() && rootDir->isDirectory())) - { - try - { + if (!(rootDir->exists() && rootDir->isDirectory())) { + + try { rootDir->createDirectory(); - } - catch (exceptions::filesystem_exception& e) - { + } catch (exceptions::filesystem_exception& e) { throw exceptions::connection_error("Cannot create root directory.", e); } } @@ -163,29 +182,29 @@ void maildirStore::connect() } -bool maildirStore::isConnected() const -{ - return (m_connected); +bool maildirStore::isConnected() const { + + return m_connected; } -bool maildirStore::isSecuredConnection() const -{ +bool maildirStore::isSecuredConnection() const { + return false; } -shared_ptr <connectionInfos> maildirStore::getConnectionInfos() const -{ +shared_ptr <connectionInfos> maildirStore::getConnectionInfos() const { + return make_shared <defaultConnectionInfos>("localhost", static_cast <port_t>(0)); } -void maildirStore::disconnect() -{ +void maildirStore::disconnect() { + for (std::list <maildirFolder*>::iterator it = m_folders.begin() ; - it != m_folders.end() ; ++it) - { + it != m_folders.end() ; ++it) { + (*it)->onStoreDisconnected(); } @@ -195,53 +214,56 @@ void maildirStore::disconnect() } -void maildirStore::noop() -{ +void maildirStore::noop() { + // Nothing to do. } -shared_ptr <maildirFormat> maildirStore::getFormat() -{ +shared_ptr <maildirFormat> maildirStore::getFormat() { + return m_format; } -shared_ptr <const maildirFormat> maildirStore::getFormat() const -{ +shared_ptr <const maildirFormat> maildirStore::getFormat() const { + return m_format; } -void maildirStore::registerFolder(maildirFolder* folder) -{ +void maildirStore::registerFolder(maildirFolder* folder) { + m_folders.push_back(folder); } -void maildirStore::unregisterFolder(maildirFolder* folder) -{ +void maildirStore::unregisterFolder(maildirFolder* folder) { + std::list <maildirFolder*>::iterator it = std::find(m_folders.begin(), m_folders.end(), folder); - if (it != m_folders.end()) m_folders.erase(it); + + if (it != m_folders.end()) { + m_folders.erase(it); + } } -const utility::path& maildirStore::getFileSystemPath() const -{ - return (m_fsPath); +const utility::path& maildirStore::getFileSystemPath() const { + + return m_fsPath; } -int maildirStore::getCapabilities() const -{ - return (CAPABILITY_CREATE_FOLDER | - CAPABILITY_RENAME_FOLDER | - CAPABILITY_ADD_MESSAGE | - CAPABILITY_COPY_MESSAGE | - CAPABILITY_DELETE_MESSAGE | - CAPABILITY_PARTIAL_FETCH | - CAPABILITY_MESSAGE_FLAGS | - CAPABILITY_EXTRACT_PART); +int maildirStore::getCapabilities() const { + + return CAPABILITY_CREATE_FOLDER | + CAPABILITY_RENAME_FOLDER | + CAPABILITY_ADD_MESSAGE | + CAPABILITY_COPY_MESSAGE | + CAPABILITY_DELETE_MESSAGE | + CAPABILITY_PARTIAL_FETCH | + CAPABILITY_MESSAGE_FLAGS | + CAPABILITY_EXTRACT_PART; } @@ -251,14 +273,14 @@ int maildirStore::getCapabilities() const maildirServiceInfos maildirStore::sm_infos; -const serviceInfos& maildirStore::getInfosInstance() -{ +const serviceInfos& maildirStore::getInfosInstance() { + return sm_infos; } -const serviceInfos& maildirStore::getInfos() const -{ +const serviceInfos& maildirStore::getInfos() const { + return sm_infos; } diff --git a/src/vmime/net/maildir/maildirStore.hpp b/src/vmime/net/maildir/maildirStore.hpp index efadfdfe..13255c0a 100644 --- a/src/vmime/net/maildir/maildirStore.hpp +++ b/src/vmime/net/maildir/maildirStore.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard <[email protected]> +// Copyright (C) 2002 Vincent Richard <[email protected]> // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License as @@ -53,14 +53,17 @@ class maildirFolder; /** maildir store service. */ +class VMIME_EXPORT maildirStore : public store { -class VMIME_EXPORT maildirStore : public store -{ friend class maildirFolder; public: - maildirStore(shared_ptr <session> sess, shared_ptr <security::authenticator> auth); + maildirStore( + const shared_ptr <session>& sess, + const shared_ptr <security::authenticator>& auth + ); + ~maildirStore(); const string getProtocolName() const; diff --git a/src/vmime/net/maildir/maildirUtils.cpp b/src/vmime/net/maildir/maildirUtils.cpp index b31eb931..9942e56e 100644 --- a/src/vmime/net/maildir/maildirUtils.cpp +++ b/src/vmime/net/maildir/maildirUtils.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard <[email protected]> +// Copyright (C) 2002 Vincent Richard <[email protected]> // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License as @@ -41,17 +41,17 @@ namespace net { namespace maildir { -bool maildirUtils::isMessageFile(const utility::file& file) -{ +bool maildirUtils::isMessageFile(const utility::file& file) { + // Ignore files which name begins with '.' if (file.isFile() && file.getFullPath().getLastComponent().getBuffer().length() >= 1 && - file.getFullPath().getLastComponent().getBuffer()[0] != '.') - { - return (true); + file.getFullPath().getLastComponent().getBuffer()[0] != '.') { + + return true; } - return (false); + return false; } @@ -68,28 +68,28 @@ bool maildirUtils::isMessageFile(const utility::file& file) // characters when reading file names. -const utility::file::path::component maildirUtils::extractId - (const utility::file::path::component& filename) -{ +const utility::file::path::component maildirUtils::extractId( + const utility::file::path::component& filename +) { + size_t sep = filename.getBuffer().rfind(':'); // try colon - if (sep == string::npos) - { + if (sep == string::npos) { sep = filename.getBuffer().rfind('-'); // try dash (Windows) if (sep == string::npos) return (filename); } - return (utility::path::component - (string(filename.getBuffer().begin(), filename.getBuffer().begin() + sep))); + return utility::path::component( + string(filename.getBuffer().begin(), filename.getBuffer().begin() + sep) + ); } -int maildirUtils::extractFlags(const utility::file::path::component& comp) -{ +int maildirUtils::extractFlags(const utility::file::path::component& comp) { + size_t sep = comp.getBuffer().rfind(':'); // try colon - if (sep == string::npos) - { + if (sep == string::npos) { sep = comp.getBuffer().rfind('-'); // try dash (Windows) if (sep == string::npos) return 0; } @@ -99,25 +99,24 @@ int maildirUtils::extractFlags(const utility::file::path::component& comp) int flags = 0; - for (size_t i = 0 ; i < count ; ++i) - { - switch (flagsString[i]) - { - case 'R': case 'r': flags |= message::FLAG_REPLIED; break; - case 'S': case 's': flags |= message::FLAG_SEEN; break; - case 'T': case 't': flags |= message::FLAG_DELETED; break; - case 'F': case 'f': flags |= message::FLAG_MARKED; break; - case 'P': case 'p': flags |= message::FLAG_PASSED; break; - case 'D': case 'd': flags |= message::FLAG_DRAFT; break; + for (size_t i = 0 ; i < count ; ++i) { + + switch (flagsString[i]) { + case 'R': case 'r': flags |= message::FLAG_REPLIED; break; + case 'S': case 's': flags |= message::FLAG_SEEN; break; + case 'T': case 't': flags |= message::FLAG_DELETED; break; + case 'F': case 'f': flags |= message::FLAG_MARKED; break; + case 'P': case 'p': flags |= message::FLAG_PASSED; break; + case 'D': case 'd': flags |= message::FLAG_DRAFT; break; } } - return (flags); + return flags; } -const utility::file::path::component maildirUtils::buildFlags(const int flags) -{ +const utility::file::path::component maildirUtils::buildFlags(const int flags) { + string str; str.reserve(8); @@ -130,24 +129,28 @@ const utility::file::path::component maildirUtils::buildFlags(const int flags) if (flags & message::FLAG_DELETED) str += "T"; if (flags & message::FLAG_DRAFT) str += "D"; - return (utility::file::path::component(str)); + return utility::file::path::component(str); } -const utility::file::path::component maildirUtils::buildFilename - (const utility::file::path::component& id, const int flags) -{ - if (flags == message::FLAG_RECENT) +const utility::file::path::component maildirUtils::buildFilename( + const utility::file::path::component& id, + const int flags +) { + + if (flags == message::FLAG_RECENT) { return id; - else - return (buildFilename(id, buildFlags(flags))); + } else { + return buildFilename(id, buildFlags(flags)); + } } -const utility::file::path::component maildirUtils::buildFilename - (const utility::file::path::component& id, - const utility::file::path::component& flags) -{ +const utility::file::path::component maildirUtils::buildFilename( + const utility::file::path::component& id, + const utility::file::path::component& flags +) { + #if VMIME_PLATFORM_IS_WINDOWS static const char DELIMITER[] = "-"; #else @@ -158,8 +161,8 @@ const utility::file::path::component maildirUtils::buildFilename } -const utility::file::path::component maildirUtils::generateId() -{ +const utility::file::path::component maildirUtils::generateId() { + std::ostringstream oss; oss.imbue(std::locale::classic()); @@ -171,70 +174,64 @@ const utility::file::path::component maildirUtils::generateId() oss << "."; oss << platform::getHandler()->getHostName(); - return (utility::file::path::component(oss.str())); + return utility::file::path::component(oss.str()); } -void maildirUtils::recursiveFSDelete(shared_ptr <utility::file> dir) -{ +void maildirUtils::recursiveFSDelete(const shared_ptr <utility::file>& dir) { + shared_ptr <utility::fileIterator> files = dir->getFiles(); // First, delete files and subdirectories in this directory - while (files->hasMoreElements()) - { + while (files->hasMoreElements()) { + shared_ptr <utility::file> file = files->nextElement(); - if (file->isDirectory()) - { + if (file->isDirectory()) { + maildirUtils::recursiveFSDelete(file); - } - else - { - try - { + + } else { + + try { file->remove(); - } - catch (exceptions::filesystem_exception&) - { + } catch (exceptions::filesystem_exception&) { // Ignore } } } // Then, delete this (empty) directory - try - { + try { dir->remove(); - } - catch (exceptions::filesystem_exception&) - { + } catch (exceptions::filesystem_exception&) { // Ignore } } -class maildirMessageSetEnumerator : public messageSetEnumerator -{ +class maildirMessageSetEnumerator : public messageSetEnumerator { + public: maildirMessageSetEnumerator(const size_t msgCount) - : m_msgCount(msgCount) - { + : m_msgCount(msgCount) { } - void enumerateNumberMessageRange(const vmime::net::numberMessageRange& range) - { + void enumerateNumberMessageRange(const vmime::net::numberMessageRange& range) { + size_t last = range.getLast(); if (last == size_t(-1)) last = m_msgCount; - for (size_t i = range.getFirst() ; i <= last ; ++i) + for (size_t i = range.getFirst() ; i <= last ; ++i) { list.push_back(i); + } } - void enumerateUIDMessageRange(const vmime::net::UIDMessageRange& /* range */) - { + void enumerateUIDMessageRange(const vmime::net::UIDMessageRange& /* range */) { + // Not supported } @@ -249,8 +246,11 @@ private: // static -const std::vector <size_t> maildirUtils::messageSetToNumberList(const messageSet& msgs, const size_t msgCount) -{ +const std::vector <size_t> maildirUtils::messageSetToNumberList( + const messageSet& msgs, + const size_t msgCount +) { + maildirMessageSetEnumerator en(msgCount); msgs.enumerate(en); @@ -263,17 +263,19 @@ const std::vector <size_t> maildirUtils::messageSetToNumberList(const messageSet // messageIdComparator // -maildirUtils::messageIdComparator::messageIdComparator - (const utility::file::path::component& comp) - : m_comp(maildirUtils::extractId(comp)) -{ +maildirUtils::messageIdComparator::messageIdComparator( + const utility::file::path::component& comp +) + : m_comp(maildirUtils::extractId(comp)) { + } -bool maildirUtils::messageIdComparator::operator() - (const utility::file::path::component& other) const -{ - return (m_comp == maildirUtils::extractId(other)); +bool maildirUtils::messageIdComparator::operator()( + const utility::file::path::component& other +) const { + + return m_comp == maildirUtils::extractId(other); } diff --git a/src/vmime/net/maildir/maildirUtils.hpp b/src/vmime/net/maildir/maildirUtils.hpp index 8899bdd7..94ab9983 100644 --- a/src/vmime/net/maildir/maildirUtils.hpp +++ b/src/vmime/net/maildir/maildirUtils.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard <[email protected]> +// Copyright (C) 2002 Vincent Richard <[email protected]> // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License as @@ -47,16 +47,15 @@ class maildirStore; /** Miscellaneous helpers functions for maildir messaging system. */ +class VMIME_EXPORT maildirUtils { -class VMIME_EXPORT maildirUtils -{ public: /** Comparator for message filenames, based only on the * unique identifier part of the filename. */ - class messageIdComparator - { + class messageIdComparator { + public: messageIdComparator(const utility::file::path::component& comp); @@ -110,7 +109,10 @@ public: * @param flags flags part of the filename * @return message filename */ - static const utility::file::path::component buildFilename(const utility::file::path::component& id, const utility::file::path::component& flags); + static const utility::file::path::component buildFilename( + const utility::file::path::component& id, + const utility::file::path::component& flags + ); /** Build a filename with the specified id and flags. * @@ -118,7 +120,10 @@ public: * @param flags set of flags * @return message filename */ - static const utility::file::path::component buildFilename(const utility::file::path::component& id, const int flags); + static const utility::file::path::component buildFilename( + const utility::file::path::component& id, + const int flags + ); /** Generate a new unique message identifier. * @@ -130,7 +135,7 @@ public: * * @param dir directory to delete */ - static void recursiveFSDelete(shared_ptr <utility::file> dir); + static void recursiveFSDelete(const shared_ptr <utility::file>& dir); /** Returns a list of message numbers given a message set. * @@ -138,7 +143,10 @@ public: * @param msgCount number of messages in folder * @return list of message numbers */ - static const std::vector <size_t> messageSetToNumberList(const messageSet& msgs, const size_t msgCount); + static const std::vector <size_t> messageSetToNumberList( + const messageSet& msgs, + const size_t msgCount + ); }; diff --git a/src/vmime/net/message.cpp b/src/vmime/net/message.cpp index 6765e73c..2d6f995a 100644 --- a/src/vmime/net/message.cpp +++ b/src/vmime/net/message.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard <[email protected]> +// Copyright (C) 2002 Vincent Richard <[email protected]> // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License as @@ -36,20 +36,25 @@ namespace vmime { namespace net { -shared_ptr <const messagePart> messagePart::getPartAt(const size_t pos) const +string messagePart::getName() const { + return {}; +} + +shared_ptr <const messagePart> messagePart::getPartAt(const size_t pos) const { + return getStructure()->getPartAt(pos); } -shared_ptr <messagePart> messagePart::getPartAt(const size_t pos) -{ +shared_ptr <messagePart> messagePart::getPartAt(const size_t pos) { + return getStructure()->getPartAt(pos); } -size_t messagePart::getPartCount() const -{ +size_t messagePart::getPartCount() const { + return getStructure()->getPartCount(); } @@ -58,19 +63,19 @@ size_t messagePart::getPartCount() const // message::uid -message::uid::uid() -{ +message::uid::uid() { + } message::uid::uid(const string& uid) - : m_str(uid) -{ + : m_str(uid) { + } -message::uid::uid(const unsigned long uid) -{ +message::uid::uid(const unsigned long uid) { + std::ostringstream oss; oss.imbue(std::locale::classic()); oss << uid; @@ -80,33 +85,33 @@ message::uid::uid(const unsigned long uid) message::uid::uid(const char* uid) - : m_str(uid) -{ + : m_str(uid) { + } -message::uid::uid(const uid& other) -{ +message::uid::uid(const uid& other) { + m_str = other.m_str; } -message::uid& message::uid::operator=(const uid& other) -{ +message::uid& message::uid::operator=(const uid& other) { + m_str = other.m_str; return *this; } -message::uid& message::uid::operator=(const string& uid) -{ +message::uid& message::uid::operator=(const string& uid) { + m_str = uid; return *this; } -message::uid& message::uid::operator=(const unsigned long uid) -{ +message::uid& message::uid::operator=(const unsigned long uid) { + std::ostringstream oss; oss.imbue(std::locale::classic()); oss << uid; @@ -117,26 +122,26 @@ message::uid& message::uid::operator=(const unsigned long uid) } -message::uid::operator string() const -{ +message::uid::operator string() const { + return m_str; } -bool message::uid::empty() const -{ +bool message::uid::empty() const { + return m_str.empty(); } -bool message::uid::operator==(const uid& other) const -{ +bool message::uid::operator==(const uid& other) const { + return m_str == other.m_str; } -std::ostream& operator<<(std::ostream& os, const message::uid& uid) -{ +std::ostream& operator<<(std::ostream& os, const message::uid& uid) { + os << static_cast <string>(uid); return os; } diff --git a/src/vmime/net/message.hpp b/src/vmime/net/message.hpp index 4c64a1cf..c0a2839b 100644 --- a/src/vmime/net/message.hpp +++ b/src/vmime/net/message.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard <[email protected]> +// Copyright (C) 2002 Vincent Richard <[email protected]> // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License as @@ -49,13 +49,12 @@ class messageStructure; /** A MIME part in a message. */ +class VMIME_EXPORT messagePart : public object, public enable_shared_from_this <messagePart> { -class VMIME_EXPORT messagePart : public object, public enable_shared_from_this <messagePart> -{ protected: messagePart() { } - messagePart(const messagePart&) : object(), enable_shared_from_this <messagePart>() { } + messagePart(const messagePart&); virtual ~messagePart() { } @@ -99,6 +98,16 @@ public: */ virtual size_t getNumber() const = 0; + /** Return the name of this part. In particular, this corresponds to + * the attachment file name for attachment parts. + * + * The part name may be empty if the part does not advertise it or + * if the underlying protocol does not support it. + * + * @return part name + */ + virtual string getName() const; + /** Return the sub-part at the specified position (zero is the * first part). * @@ -125,13 +134,12 @@ public: /** Structure of a MIME part/message. */ +class VMIME_EXPORT messageStructure : public object, public enable_shared_from_this <messageStructure> { -class VMIME_EXPORT messageStructure : public object, public enable_shared_from_this <messageStructure> -{ protected: messageStructure() { } - messageStructure(const messageStructure&) : object(), enable_shared_from_this <messageStructure>() { } + messageStructure(const messageStructure&); public: @@ -163,28 +171,24 @@ public: /** Abstract representation of a message in a store/transport service. */ +class VMIME_EXPORT message : public object, public enable_shared_from_this <message> { -class VMIME_EXPORT message : public object, public enable_shared_from_this <message> -{ protected: message() { } - message(const message&) : object(), enable_shared_from_this <message>() { } + message(const message&); - enum PrivateConstants - { + enum PrivateConstants { FLAG_UNDEFINED = 9999 /**< Used internally to indicate flags have not been initialized yet. */ }; public: - virtual ~message() { } - /** The type for an unique message identifier. */ - class VMIME_EXPORT uid - { + class VMIME_EXPORT uid { + public: uid(); @@ -255,8 +259,7 @@ public: /** Possible flags for a message. */ - enum Flags - { + enum Flags { FLAG_SEEN = (1 << 0), /**< Message has been seen. */ FLAG_RECENT = (1 << 1), /**< Message has been recently received. */ FLAG_DELETED = (1 << 2), /**< Message is marked for deletion. */ @@ -268,8 +271,7 @@ public: /** Methods for setting the flags. */ - enum FlagsModes - { + enum FlagsModes { FLAG_MODE_SET, /**< Set (replace) the flags. */ FLAG_MODE_ADD, /**< Add the flags. */ FLAG_MODE_REMOVE /**< Remove the flags. */ @@ -300,12 +302,13 @@ public: * be supported by the protocol (IMAP supports this), but it will NOT throw * an exception if not supported. */ - virtual void extract - (utility::outputStream& os, - utility::progressListener* progress = NULL, - const size_t start = 0, - const size_t length = -1, - const bool peek = false) const = 0; + virtual void extract( + utility::outputStream& os, + utility::progressListener* progress = NULL, + const size_t start = 0, + const size_t length = -1, + const bool peek = false + ) const = 0; /** Extract the specified MIME part of the message (header + contents). * @@ -320,19 +323,20 @@ public: * be supported by the protocol (IMAP supports this), but it will NOT throw * an exception if not supported. */ - virtual void extractPart - (shared_ptr <const messagePart> p, - utility::outputStream& os, - utility::progressListener* progress = NULL, - const size_t start = 0, - const size_t length = -1, - const bool peek = false) const = 0; + virtual void extractPart( + const shared_ptr <const messagePart>& p, + utility::outputStream& os, + utility::progressListener* progress = NULL, + const size_t start = 0, + const size_t length = -1, + const bool peek = false + ) const = 0; /** Fetch the MIME header for the specified part. * * @param p the part for which to fetch the header */ - virtual void fetchPartHeader(shared_ptr <messagePart> p) = 0; + virtual void fetchPartHeader(const shared_ptr <messagePart>& p) = 0; /** Get the RFC-822 message for this abstract message. * Warning: This may require getting some data (ie: structure and headers) from diff --git a/src/vmime/net/messageSet.cpp b/src/vmime/net/messageSet.cpp index 0b3ea961..fe2d6452 100644 --- a/src/vmime/net/messageSet.cpp +++ b/src/vmime/net/messageSet.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard <[email protected]> +// Copyright (C) 2002 Vincent Richard <[email protected]> // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License as @@ -45,62 +45,68 @@ messageSetEnumerator::~messageSetEnumerator() // messageRange -messageRange::messageRange() -{ +messageRange::messageRange() { + } -messageRange::~messageRange() -{ +messageRange::~messageRange() { + } // numberMessageRange numberMessageRange::numberMessageRange(const size_t number) - : m_first(number), m_last(number) -{ - if (number < 1) + : m_first(number), + m_last(number) { + + if (number < 1) { throw std::invalid_argument("number"); + } } numberMessageRange::numberMessageRange(const size_t first, const size_t last) - : m_first(first), m_last(last) -{ - if (first < 1 || first == static_cast <size_t>(-1)) + : m_first(first), + m_last(last) { + + if (first < 1 || first == static_cast <size_t>(-1)) { throw std::invalid_argument("first"); - else if (last != static_cast <size_t>(-1) && last < first) + } else if (last != static_cast <size_t>(-1) && last < first) { throw std::invalid_argument("last"); + } } numberMessageRange::numberMessageRange(const numberMessageRange& other) - : messageRange(), m_first(other.m_first), m_last(other.m_last) -{ + : messageRange(), + m_first(other.m_first), + m_last(other.m_last) { + } -size_t numberMessageRange::getFirst() const -{ +size_t numberMessageRange::getFirst() const { + return m_first; } -size_t numberMessageRange::getLast() const -{ +size_t numberMessageRange::getLast() const { + return m_last; } -void numberMessageRange::enumerate(messageSetEnumerator& en) const -{ +void numberMessageRange::enumerate(messageSetEnumerator& en) const { + en.enumerateNumberMessageRange(*this); } -messageRange* numberMessageRange::clone() const -{ +messageRange* numberMessageRange::clone() const { + return new numberMessageRange(*this); } @@ -108,43 +114,47 @@ messageRange* numberMessageRange::clone() const // UIDMessageRange UIDMessageRange::UIDMessageRange(const message::uid& uid) - : m_first(uid), m_last(uid) -{ + : m_first(uid), + m_last(uid) { + } UIDMessageRange::UIDMessageRange(const message::uid& first, const message::uid& last) - : m_first(first), m_last(last) -{ + : m_first(first), + m_last(last) { + } UIDMessageRange::UIDMessageRange(const UIDMessageRange& other) - : messageRange(), m_first(other.m_first), m_last(other.m_last) -{ + : messageRange(), + m_first(other.m_first), + m_last(other.m_last) { + } -const message::uid UIDMessageRange::getFirst() const -{ +const message::uid UIDMessageRange::getFirst() const { + return m_first; } -const message::uid UIDMessageRange::getLast() const -{ +const message::uid UIDMessageRange::getLast() const { + return m_last; } -void UIDMessageRange::enumerate(messageSetEnumerator& en) const -{ +void UIDMessageRange::enumerate(messageSetEnumerator& en) const { + en.enumerateUIDMessageRange(*this); } -messageRange* UIDMessageRange::clone() const -{ +messageRange* UIDMessageRange::clone() const { + return new UIDMessageRange(*this); } @@ -152,38 +162,40 @@ messageRange* UIDMessageRange::clone() const // messageSet -messageSet::messageSet() -{ +messageSet::messageSet() { + } messageSet::messageSet(const messageSet& other) - : object() -{ + : object() { + m_ranges.resize(other.m_ranges.size()); - for (size_t i = 0, n = other.m_ranges.size() ; i < n ; ++i) + for (size_t i = 0, n = other.m_ranges.size() ; i < n ; ++i) { m_ranges[i] = other.m_ranges[i]->clone(); + } } -messageSet::~messageSet() -{ - for (size_t i = 0, n = m_ranges.size() ; i < n ; ++i) +messageSet::~messageSet() { + + for (size_t i = 0, n = m_ranges.size() ; i < n ; ++i) { delete m_ranges[i]; + } } // static -messageSet messageSet::empty() -{ +messageSet messageSet::empty() { + return messageSet(); } // static -messageSet messageSet::byNumber(const size_t number) -{ +messageSet messageSet::byNumber(const size_t number) { + messageSet set; set.m_ranges.push_back(new numberMessageRange(number)); @@ -192,8 +204,8 @@ messageSet messageSet::byNumber(const size_t number) // static -messageSet messageSet::byNumber(const size_t first, const size_t last) -{ +messageSet messageSet::byNumber(const size_t first, const size_t last) { + messageSet set; set.m_ranges.push_back(new numberMessageRange(first, last)); @@ -202,8 +214,8 @@ messageSet messageSet::byNumber(const size_t first, const size_t last) // static -messageSet messageSet::byNumber(const std::vector <size_t>& numbers) -{ +messageSet messageSet::byNumber(const std::vector <size_t>& numbers) { + // Sort a copy of the list std::vector <size_t> sortedNumbers; @@ -217,29 +229,31 @@ messageSet messageSet::byNumber(const std::vector <size_t>& numbers) messageSet set; for (std::vector <size_t>::const_iterator it = sortedNumbers.begin() ; - it != sortedNumbers.end() ; ++it) - { + it != sortedNumbers.end() ; ++it) { + const size_t current = *it; - if (current == previous) + if (current == previous) { continue; // skip duplicates + } - if (current == static_cast <size_t>(-1)) + if (current == static_cast <size_t>(-1)) { throw std::invalid_argument("numbers"); + } + + if (previous == static_cast <size_t>(-1)) { - if (previous == static_cast <size_t>(-1)) - { previous = current; rangeStart = current; - } - else - { - if (current == previous + 1) - { + + } else { + + if (current == previous + 1) { + previous = current; - } - else - { + + } else { + set.m_ranges.push_back(new numberMessageRange(rangeStart, previous)); previous = current; @@ -255,8 +269,8 @@ messageSet messageSet::byNumber(const std::vector <size_t>& numbers) // static -messageSet messageSet::byUID(const message::uid& uid) -{ +messageSet messageSet::byUID(const message::uid& uid) { + messageSet set; set.m_ranges.push_back(new UIDMessageRange(uid)); @@ -264,8 +278,8 @@ messageSet messageSet::byUID(const message::uid& uid) } -messageSet messageSet::byUID(const message::uid& first, const message::uid& last) -{ +messageSet messageSet::byUID(const message::uid& first, const message::uid& last) { + messageSet set; set.m_ranges.push_back(new UIDMessageRange(first, last)); @@ -273,27 +287,29 @@ messageSet messageSet::byUID(const message::uid& first, const message::uid& last } -messageSet messageSet::byUID(const std::vector <message::uid>& uids) -{ +messageSet messageSet::byUID(const std::vector <message::uid>& uids) { + std::vector <vmime_uint32> numericUIDs; - for (size_t i = 0, n = uids.size() ; i < n ; ++i) - { + for (size_t i = 0, n = uids.size() ; i < n ; ++i) { + const string uid = uids[i]; int numericUID = 0; const char* p = uid.c_str(); - for ( ; *p >= '0' && *p <= '9' ; ++p) - numericUID = (numericUID * 10) + (*p - '0'); + for ( ; *p >= '0' && *p <= '9' ; ++p) { + numericUID = (numericUID * 10) + (*p - '0'); + } + + if (*p != '\0') { - if (*p != '\0') - { messageSet set; // Non-numeric UID, fall back to plain UID list (single-UID ranges) - for (size_t i = 0, n = uids.size() ; i < n ; ++i) + for (size_t i = 0, n = uids.size() ; i < n ; ++i) { set.m_ranges.push_back(new UIDMessageRange(uids[i])); + } return set; } @@ -314,29 +330,33 @@ messageSet messageSet::byUID(const std::vector <message::uid>& uids) messageSet set; for (std::vector <vmime_uint32>::const_iterator it = sortedUIDs.begin() ; - it != sortedUIDs.end() ; ++it) - { + it != sortedUIDs.end() ; ++it) { + const vmime_uint32 current = *it; - if (current == previous) + if (current == previous) { continue; // skip duplicates + } + + if (previous == static_cast <vmime_uint32>(-1)) { - if (previous == static_cast <vmime_uint32>(-1)) - { previous = current; rangeStart = current; - } - else - { - if (current == previous + 1) - { + + } else { + + if (current == previous + 1) { + previous = current; - } - else - { - set.m_ranges.push_back(new UIDMessageRange - (utility::stringUtils::toString(rangeStart), - utility::stringUtils::toString(previous))); + + } else { + + set.m_ranges.push_back( + new UIDMessageRange( + utility::stringUtils::toString(rangeStart), + utility::stringUtils::toString(previous) + ) + ); previous = current; rangeStart = current; @@ -344,56 +364,61 @@ messageSet messageSet::byUID(const std::vector <message::uid>& uids) } } - set.m_ranges.push_back(new UIDMessageRange - (utility::stringUtils::toString(rangeStart), - utility::stringUtils::toString(previous))); + set.m_ranges.push_back( + new UIDMessageRange( + utility::stringUtils::toString(rangeStart), + utility::stringUtils::toString(previous) + ) + ); return set; } -void messageSet::addRange(const messageRange& range) -{ - if (!m_ranges.empty() && typeid(*m_ranges[0]) != typeid(range)) +void messageSet::addRange(const messageRange& range) { + + if (!m_ranges.empty() && typeid(*m_ranges[0]) != typeid(range)) { throw std::invalid_argument("range"); + } m_ranges.push_back(range.clone()); } -void messageSet::enumerate(messageSetEnumerator& en) const -{ - for (size_t i = 0, n = m_ranges.size() ; i < n ; ++i) +void messageSet::enumerate(messageSetEnumerator& en) const { + + for (size_t i = 0, n = m_ranges.size() ; i < n ; ++i) { m_ranges[i]->enumerate(en); + } } -bool messageSet::isEmpty() const -{ +bool messageSet::isEmpty() const { + return m_ranges.empty(); } -bool messageSet::isNumberSet() const -{ +bool messageSet::isNumberSet() const { + return !isEmpty() && dynamic_cast <numberMessageRange*>(m_ranges[0]) != NULL; } -bool messageSet::isUIDSet() const -{ +bool messageSet::isUIDSet() const { + return !isEmpty() && dynamic_cast <UIDMessageRange*>(m_ranges[0]) != NULL; } -size_t messageSet::getRangeCount() const -{ +size_t messageSet::getRangeCount() const { + return m_ranges.size(); } -const messageRange& messageSet::getRangeAt(const size_t i) const -{ +const messageRange& messageSet::getRangeAt(const size_t i) const { + return *m_ranges[i]; } diff --git a/src/vmime/net/messageSet.hpp b/src/vmime/net/messageSet.hpp index 9d6ca4f4..848c4c97 100644 --- a/src/vmime/net/messageSet.hpp +++ b/src/vmime/net/messageSet.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard <[email protected]> +// Copyright (C) 2002 Vincent Richard <[email protected]> // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License as @@ -46,9 +46,8 @@ class UIDMessageRange; /** Enumerator used to retrieve the message number/UID ranges contained * in a messageSet object. */ +class VMIME_EXPORT messageSetEnumerator { -class VMIME_EXPORT messageSetEnumerator -{ public: virtual ~messageSetEnumerator(); virtual void enumerateNumberMessageRange(const numberMessageRange& range) = 0; @@ -59,9 +58,8 @@ public: /** A range of (continuous) messages, designated either by their * sequence number, or by their UID. */ +class VMIME_EXPORT messageRange : public object { -class VMIME_EXPORT messageRange : public object -{ public: virtual ~messageRange(); @@ -86,9 +84,8 @@ protected: /** A range of (continuous) messages designated by their sequence number. */ +class VMIME_EXPORT numberMessageRange : public messageRange { -class VMIME_EXPORT numberMessageRange : public messageRange -{ public: /** Constructs a message range containing a single message. @@ -137,9 +134,8 @@ private: /** A range of (continuous) messages represented by their UID. */ +class VMIME_EXPORT UIDMessageRange : public messageRange { -class VMIME_EXPORT UIDMessageRange : public messageRange -{ public: /** Constructs a message range containing a single message. @@ -211,9 +207,8 @@ private: * vmime::net::messageSet::byUID(1000, "*") * \endcode */ +class VMIME_EXPORT messageSet : public object { -class VMIME_EXPORT messageSet : public object -{ public: ~messageSet(); diff --git a/src/vmime/net/pop3/POP3Command.cpp b/src/vmime/net/pop3/POP3Command.cpp index 9dfaf17a..0e798884 100644 --- a/src/vmime/net/pop3/POP3Command.cpp +++ b/src/vmime/net/pop3/POP3Command.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard <[email protected]> +// Copyright (C) 2002 Vincent Richard <[email protected]> // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License as @@ -43,28 +43,29 @@ namespace pop3 { POP3Command::POP3Command(const string& text, const string& traceText) - : m_text(text), m_traceText(traceText) -{ + : m_text(text), + m_traceText(traceText) { + } // static -shared_ptr <POP3Command> POP3Command::CAPA() -{ +shared_ptr <POP3Command> POP3Command::CAPA() { + return createCommand("CAPA"); } // static -shared_ptr <POP3Command> POP3Command::NOOP() -{ +shared_ptr <POP3Command> POP3Command::NOOP() { + return createCommand("NOOP"); } // static -shared_ptr <POP3Command> POP3Command::AUTH(const string& mechName) -{ +shared_ptr <POP3Command> POP3Command::AUTH(const string& mechName) { + std::ostringstream cmd; cmd.imbue(std::locale::classic()); cmd << "AUTH " << mechName; @@ -74,8 +75,8 @@ shared_ptr <POP3Command> POP3Command::AUTH(const string& mechName) // static -shared_ptr <POP3Command> POP3Command::AUTH(const string& mechName, const string& initialResponse) -{ +shared_ptr <POP3Command> POP3Command::AUTH(const string& mechName, const string& initialResponse) { + std::ostringstream cmd; cmd.imbue(std::locale::classic()); cmd << "AUTH " << mechName << " " << initialResponse; @@ -85,15 +86,15 @@ shared_ptr <POP3Command> POP3Command::AUTH(const string& mechName, const string& // static -shared_ptr <POP3Command> POP3Command::STLS() -{ +shared_ptr <POP3Command> POP3Command::STLS() { + return createCommand("STLS"); } // static -shared_ptr <POP3Command> POP3Command::APOP(const string& username, const string& digest) -{ +shared_ptr <POP3Command> POP3Command::APOP(const string& username, const string& digest) { + std::ostringstream cmd; cmd.imbue(std::locale::classic()); cmd << "APOP " << username << " " << digest; @@ -103,8 +104,8 @@ shared_ptr <POP3Command> POP3Command::APOP(const string& username, const string& // static -shared_ptr <POP3Command> POP3Command::USER(const string& username) -{ +shared_ptr <POP3Command> POP3Command::USER(const string& username) { + std::ostringstream cmd; cmd.imbue(std::locale::classic()); cmd << "USER " << username; @@ -118,8 +119,8 @@ shared_ptr <POP3Command> POP3Command::USER(const string& username) // static -shared_ptr <POP3Command> POP3Command::PASS(const string& password) -{ +shared_ptr <POP3Command> POP3Command::PASS(const string& password) { + std::ostringstream cmd; cmd.imbue(std::locale::classic()); cmd << "PASS " << password; @@ -133,22 +134,22 @@ shared_ptr <POP3Command> POP3Command::PASS(const string& password) // static -shared_ptr <POP3Command> POP3Command::STAT() -{ +shared_ptr <POP3Command> POP3Command::STAT() { + return createCommand("STAT"); } // static -shared_ptr <POP3Command> POP3Command::LIST() -{ +shared_ptr <POP3Command> POP3Command::LIST() { + return createCommand("LIST"); } // static -shared_ptr <POP3Command> POP3Command::LIST(const unsigned long msg) -{ +shared_ptr <POP3Command> POP3Command::LIST(const unsigned long msg) { + std::ostringstream cmd; cmd.imbue(std::locale::classic()); cmd << "LIST " << msg; @@ -158,15 +159,15 @@ shared_ptr <POP3Command> POP3Command::LIST(const unsigned long msg) // static -shared_ptr <POP3Command> POP3Command::UIDL() -{ +shared_ptr <POP3Command> POP3Command::UIDL() { + return createCommand("UIDL"); } // static -shared_ptr <POP3Command> POP3Command::UIDL(const unsigned long msg) -{ +shared_ptr <POP3Command> POP3Command::UIDL(const unsigned long msg) { + std::ostringstream cmd; cmd.imbue(std::locale::classic()); cmd << "UIDL " << msg; @@ -176,8 +177,8 @@ shared_ptr <POP3Command> POP3Command::UIDL(const unsigned long msg) // static -shared_ptr <POP3Command> POP3Command::DELE(const unsigned long msg) -{ +shared_ptr <POP3Command> POP3Command::DELE(const unsigned long msg) { + std::ostringstream cmd; cmd.imbue(std::locale::classic()); cmd << "DELE " << msg; @@ -187,8 +188,8 @@ shared_ptr <POP3Command> POP3Command::DELE(const unsigned long msg) // static -shared_ptr <POP3Command> POP3Command::RETR(const unsigned long msg) -{ +shared_ptr <POP3Command> POP3Command::RETR(const unsigned long msg) { + std::ostringstream cmd; cmd.imbue(std::locale::classic()); cmd << "RETR " << msg; @@ -198,8 +199,8 @@ shared_ptr <POP3Command> POP3Command::RETR(const unsigned long msg) // static -shared_ptr <POP3Command> POP3Command::TOP(const unsigned long msg, const unsigned long lines) -{ +shared_ptr <POP3Command> POP3Command::TOP(const unsigned long msg, const unsigned long lines) { + std::ostringstream cmd; cmd.imbue(std::locale::classic()); cmd << "TOP " << msg << " " << lines; @@ -209,48 +210,52 @@ shared_ptr <POP3Command> POP3Command::TOP(const unsigned long msg, const unsigne // static -shared_ptr <POP3Command> POP3Command::RSET() -{ +shared_ptr <POP3Command> POP3Command::RSET() { + return createCommand("RSET"); } // static -shared_ptr <POP3Command> POP3Command::QUIT() -{ +shared_ptr <POP3Command> POP3Command::QUIT() { + return createCommand("QUIT"); } // static -shared_ptr <POP3Command> POP3Command::createCommand - (const string& text, const string& traceText) -{ - if (traceText.empty()) +shared_ptr <POP3Command> POP3Command::createCommand( + const string& text, + const string& traceText +) { + + if (traceText.empty()) { return shared_ptr <POP3Command>(new POP3Command(text, text)); - else + } else { return shared_ptr <POP3Command>(new POP3Command(text, traceText)); + } } -const string POP3Command::getText() const -{ +const string POP3Command::getText() const { + return m_text; } -const string POP3Command::getTraceText() const -{ +const string POP3Command::getTraceText() const { + return m_traceText; } -void POP3Command::send(shared_ptr <POP3Connection> conn) -{ +void POP3Command::send(const shared_ptr <POP3Connection>& conn) { + conn->getSocket()->send(m_text + "\r\n"); - if (conn->getTracer()) + if (conn->getTracer()) { conn->getTracer()->traceSend(m_traceText); + } } diff --git a/src/vmime/net/pop3/POP3Command.hpp b/src/vmime/net/pop3/POP3Command.hpp index 45aff661..06a61b9b 100644 --- a/src/vmime/net/pop3/POP3Command.hpp +++ b/src/vmime/net/pop3/POP3Command.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard <[email protected]> +// Copyright (C) 2002 Vincent Richard <[email protected]> // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License as @@ -50,8 +50,8 @@ class POP3Connection; /** A POP3 command that will be sent to the server. */ -class VMIME_EXPORT POP3Command : public object -{ +class VMIME_EXPORT POP3Command : public object { + public: static shared_ptr <POP3Command> CAPA(); @@ -85,7 +85,7 @@ public: * * @param conn connection onto which the command will be sent */ - virtual void send(shared_ptr <POP3Connection> conn); + virtual void send(const shared_ptr <POP3Connection>& conn); /** Returns the full text of the command, including command name * and parameters (if any). diff --git a/src/vmime/net/pop3/POP3Connection.cpp b/src/vmime/net/pop3/POP3Connection.cpp index 27ab7aa2..749f7ef1 100644 --- a/src/vmime/net/pop3/POP3Connection.cpp +++ b/src/vmime/net/pop3/POP3Connection.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard <[email protected]> +// Copyright (C) 2002 Vincent Richard <[email protected]> // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License as @@ -63,37 +63,48 @@ namespace pop3 { -POP3Connection::POP3Connection(shared_ptr <POP3Store> store, shared_ptr <security::authenticator> auth) - : m_store(store), m_auth(auth), m_socket(null), m_timeoutHandler(null), - m_authenticated(false), m_secured(false), m_capabilitiesFetched(false) -{ +POP3Connection::POP3Connection( + const shared_ptr <POP3Store>& store, + const shared_ptr <security::authenticator>& auth +) + : m_store(store), + m_auth(auth), + m_socket(null), + m_timeoutHandler(null), + m_authenticated(false), + m_secured(false), + m_capabilitiesFetched(false) { + static int connectionId = 0; - if (store->getTracerFactory()) + if (store->getTracerFactory()) { m_tracer = store->getTracerFactory()->create(store, ++connectionId); + } } -POP3Connection::~POP3Connection() -{ - try - { - if (isConnected()) +POP3Connection::~POP3Connection() { + + try { + + if (isConnected()) { disconnect(); - else if (m_socket) + } else if (m_socket) { internalDisconnect(); - } - catch (...) - { + } + + } catch (...) { + // Don't throw in destructor } } -void POP3Connection::connect() -{ - if (isConnected()) +void POP3Connection::connect() { + + if (isConnected()) { throw exceptions::already_connected(); + } const string address = GET_PROPERTY(string, PROPERTY_SERVER_ADDRESS); const port_t port = GET_PROPERTY(port_t, PROPERTY_SERVER_PORT); @@ -101,16 +112,17 @@ void POP3Connection::connect() shared_ptr <POP3Store> store = m_store.lock(); // Create the time-out handler - if (store->getTimeoutHandlerFactory()) + if (store->getTimeoutHandlerFactory()) { m_timeoutHandler = store->getTimeoutHandlerFactory()->create(); + } // Create and connect the socket m_socket = store->getSocketFactory()->create(m_timeoutHandler); m_socket->setTracer(m_tracer); #if VMIME_HAVE_TLS_SUPPORT - if (store->isPOP3S()) // dedicated port/POP3S - { + if (store->isPOP3S()) { // dedicated port/POP3S + shared_ptr <tls::TLSSession> tlsSession = tls::TLSSession::create (store->getCertificateVerifier(), store->getSession()->getTLSProperties()); @@ -122,8 +134,7 @@ void POP3Connection::connect() m_secured = true; m_cntInfos = make_shared <tls::TLSSecuredConnectionInfos>(address, port, tlsSession, tlsSocket); - } - else + } else #endif // VMIME_HAVE_TLS_SUPPORT { m_cntInfos = make_shared <defaultConnectionInfos>(address, port); @@ -136,11 +147,12 @@ void POP3Connection::connect() // eg: C: <connection to server> // --- S: +OK MailSite POP3 Server 5.3.4.0 Ready <[email protected]> - shared_ptr <POP3Response> response = POP3Response::readResponse - (dynamicCast <POP3Connection>(shared_from_this())); + shared_ptr <POP3Response> response = POP3Response::readResponse( + dynamicCast <POP3Connection>(shared_from_this()) + ); + + if (!response->isSuccess()) { - if (!response->isSuccess()) - { internalDisconnect(); throw exceptions::connection_greeting_error(response->getFirstLine()); } @@ -152,27 +164,23 @@ void POP3Connection::connect() const bool tlsRequired = HAS_PROPERTY(PROPERTY_CONNECTION_TLS_REQUIRED) && GET_PROPERTY(bool, PROPERTY_CONNECTION_TLS_REQUIRED); - if (!store->isPOP3S() && tls) // only if not POP3S - { - try - { + if (!store->isPOP3S() && tls) { // only if not POP3S + + try { + startTLS(); - } + // Non-fatal error - catch (exceptions::command_error&) - { - if (tlsRequired) - { + } catch (exceptions::command_error&) { + + if (tlsRequired) { throw; - } - else - { + } else { // TLS is not required, so don't bother } - } + // Fatal error - catch (...) - { + } catch (...) { throw; } } @@ -183,28 +191,29 @@ void POP3Connection::connect() } -void POP3Connection::disconnect() -{ - if (!isConnected()) +void POP3Connection::disconnect() { + + if (!isConnected()) { throw exceptions::not_connected(); + } internalDisconnect(); } -void POP3Connection::internalDisconnect() -{ - if (m_socket) - { - if (m_socket->isConnected()) - { - try - { +void POP3Connection::internalDisconnect() { + + if (m_socket) { + + if (m_socket->isConnected()) { + + try { + POP3Command::QUIT()->send(dynamicCast <POP3Connection>(shared_from_this())); POP3Response::readResponse(dynamicCast <POP3Connection>(shared_from_this())); - } - catch (exception&) - { + + } catch (exception&) { + // Not important } @@ -223,36 +232,36 @@ void POP3Connection::internalDisconnect() } -void POP3Connection::authenticate(const messageId& randomMID) -{ +void POP3Connection::authenticate(const messageId& randomMID) { + getAuthenticator()->setService(m_store.lock()); #if VMIME_HAVE_SASL_SUPPORT // First, try SASL authentication - if (GET_PROPERTY(bool, PROPERTY_OPTIONS_SASL)) - { - try - { + if (GET_PROPERTY(bool, PROPERTY_OPTIONS_SASL)) { + + try { + authenticateSASL(); m_authenticated = true; return; - } - catch (exceptions::authentication_error&) - { - if (!GET_PROPERTY(bool, PROPERTY_OPTIONS_SASL_FALLBACK)) - { + + } catch (exceptions::authentication_error&) { + + if (!GET_PROPERTY(bool, PROPERTY_OPTIONS_SASL_FALLBACK)) { + // Can't fallback on APOP/normal authentication internalDisconnect(); throw; - } - else - { + + } else { + // Ignore, will try APOP/normal authentication } - } - catch (exception&) - { + + } catch (exception&) { + internalDisconnect(); throw; } @@ -270,11 +279,11 @@ void POP3Connection::authenticate(const messageId& randomMID) shared_ptr <POP3Connection> conn = dynamicCast <POP3Connection>(shared_from_this()); shared_ptr <POP3Response> response; - if (GET_PROPERTY(bool, PROPERTY_OPTIONS_APOP)) - { + if (GET_PROPERTY(bool, PROPERTY_OPTIONS_APOP)) { + if (randomMID.getLeft().length() != 0 && - randomMID.getRight().length() != 0) - { + randomMID.getRight().length() != 0) { + // <digest> is the result of MD5 applied to "<message-id>password" shared_ptr <security::digest::messageDigest> md5 = security::digest::messageDigestFactory::getInstance()->create("md5"); @@ -285,13 +294,13 @@ void POP3Connection::authenticate(const messageId& randomMID) POP3Command::APOP(username, md5->getHexDigest())->send(conn); response = POP3Response::readResponse(conn); - if (response->isSuccess()) - { + if (response->isSuccess()) { + m_authenticated = true; return; - } - else - { + + } else { + // Some servers close the connection after an unsuccessful APOP // command, so the fallback may not always work... // @@ -301,31 +310,31 @@ void POP3Connection::authenticate(const messageId& randomMID) // S: +OK Pop server at xxx signing off. // [Connection closed by foreign host.] - if (!GET_PROPERTY(bool, PROPERTY_OPTIONS_APOP_FALLBACK)) - { + if (!GET_PROPERTY(bool, PROPERTY_OPTIONS_APOP_FALLBACK)) { + // Can't fallback on basic authentication internalDisconnect(); throw exceptions::authentication_error(response->getFirstLine()); } // Ensure connection is valid (cf. note above) - try - { + try { + POP3Command::NOOP()->send(conn); POP3Response::readResponse(conn); - } - catch (exceptions::socket_exception&) - { + + } catch (exceptions::socket_exception&) { + internalDisconnect(); throw exceptions::authentication_error(response->getFirstLine()); } } - } - else - { + + } else { + // APOP not supported - if (!GET_PROPERTY(bool, PROPERTY_OPTIONS_APOP_FALLBACK)) - { + if (!GET_PROPERTY(bool, PROPERTY_OPTIONS_APOP_FALLBACK)) { + // Can't fallback on basic authentication internalDisconnect(); throw exceptions::authentication_error("APOP not supported"); @@ -343,8 +352,8 @@ void POP3Connection::authenticate(const messageId& randomMID) POP3Command::USER(username)->send(conn); response = POP3Response::readResponse(conn); - if (!response->isSuccess()) - { + if (!response->isSuccess()) { + internalDisconnect(); throw exceptions::authentication_error(response->getFirstLine()); } @@ -352,8 +361,8 @@ void POP3Connection::authenticate(const messageId& randomMID) POP3Command::PASS(password)->send(conn); response = POP3Response::readResponse(conn); - if (!response->isSuccess()) - { + if (!response->isSuccess()) { + internalDisconnect(); throw exceptions::authentication_error(response->getFirstLine()); } @@ -364,16 +373,17 @@ void POP3Connection::authenticate(const messageId& randomMID) #if VMIME_HAVE_SASL_SUPPORT -void POP3Connection::authenticateSASL() -{ - if (!dynamicCast <security::sasl::SASLAuthenticator>(getAuthenticator())) +void POP3Connection::authenticateSASL() { + + if (!dynamicCast <security::sasl::SASLAuthenticator>(getAuthenticator())) { throw exceptions::authentication_error("No SASL authenticator available."); + } std::vector <string> capa = getCapabilities(); std::vector <string> saslMechs; - for (unsigned int i = 0 ; i < capa.size() ; ++i) - { + for (unsigned int i = 0 ; i < capa.size() ; ++i) { + const string& x = capa[i]; // C: CAPA @@ -391,8 +401,8 @@ void POP3Connection::authenticateSASL() (x[1] == 'A' || x[1] == 'a') && (x[2] == 'S' || x[2] == 's') && (x[3] == 'L' || x[3] == 'l') && - (x[4] == ' ' || x[4] == '\t')) - { + (x[4] == ' ' || x[4] == '\t')) { + const string list(x.begin() + 5, x.end()); std::istringstream iss(list); @@ -400,52 +410,53 @@ void POP3Connection::authenticateSASL() string mech; - while (iss >> mech) + while (iss >> mech) { saslMechs.push_back(mech); + } } } - if (saslMechs.empty()) + if (saslMechs.empty()) { throw exceptions::authentication_error("No SASL mechanism available."); + } std::vector <shared_ptr <security::sasl::SASLMechanism> > mechList; shared_ptr <security::sasl::SASLContext> saslContext = security::sasl::SASLContext::create(); - for (unsigned int i = 0 ; i < saslMechs.size() ; ++i) - { - try - { - mechList.push_back - (saslContext->createMechanism(saslMechs[i])); - } - catch (exceptions::no_such_mechanism&) - { + for (unsigned int i = 0 ; i < saslMechs.size() ; ++i) { + + try { + mechList.push_back(saslContext->createMechanism(saslMechs[i])); + } catch (exceptions::no_such_mechanism&) { // Ignore mechanism } } - if (mechList.empty()) + if (mechList.empty()) { throw exceptions::authentication_error("No SASL mechanism available."); + } // Try to suggest a mechanism among all those supported shared_ptr <security::sasl::SASLMechanism> suggestedMech = saslContext->suggestMechanism(mechList); - if (!suggestedMech) + if (!suggestedMech) { throw exceptions::authentication_error("Unable to suggest SASL mechanism."); + } // Allow application to choose which mechanisms to use mechList = dynamicCast <security::sasl::SASLAuthenticator>(getAuthenticator())-> getAcceptableMechanisms(mechList, suggestedMech); - if (mechList.empty()) + if (mechList.empty()) { throw exceptions::authentication_error("No SASL mechanism available."); + } // Try each mechanism in the list in turn - for (unsigned int i = 0 ; i < mechList.size() ; ++i) - { + for (unsigned int i = 0 ; i < mechList.size() ; ++i) { + shared_ptr <security::sasl::SASLMechanism> mech = mechList[i]; shared_ptr <security::sasl::SASLSession> saslSession = @@ -455,8 +466,8 @@ void POP3Connection::authenticateSASL() shared_ptr <POP3Command> authCmd; - if (saslSession->getMechanism()->hasInitialResponse()) - { + if (saslSession->getMechanism()->hasInitialResponse()) { + byte_t* initialResp = 0; size_t initialRespLen = 0; @@ -465,103 +476,108 @@ void POP3Connection::authenticateSASL() string encodedInitialResp(saslContext->encodeB64(initialResp, initialRespLen)); delete [] initialResp; - if (encodedInitialResp.empty()) + if (encodedInitialResp.empty()) { authCmd = POP3Command::AUTH(mech->getName(), "="); - else + } else { authCmd = POP3Command::AUTH(mech->getName(), encodedInitialResp); - } - else - { + } + + } else { + authCmd = POP3Command::AUTH(mech->getName()); } authCmd->send(dynamicCast <POP3Connection>(shared_from_this())); - for (bool cont = true ; cont ; ) - { + for (bool cont = true ; cont ; ) { + shared_ptr <POP3Response> response = POP3Response::readResponse(dynamicCast <POP3Connection>(shared_from_this())); - switch (response->getCode()) - { - case POP3Response::CODE_OK: - { - m_socket = saslSession->getSecuredSocket(m_socket); - return; - } - case POP3Response::CODE_READY: - { - byte_t* challenge = 0; - size_t challengeLen = 0; + switch (response->getCode()) { - byte_t* resp = 0; - size_t respLen = 0; + case POP3Response::CODE_OK: { - try - { - // Extract challenge - saslContext->decodeB64(response->getText(), &challenge, &challengeLen); + m_socket = saslSession->getSecuredSocket(m_socket); + return; + } - // Prepare response - saslSession->evaluateChallenge - (challenge, challengeLen, &resp, &respLen); + case POP3Response::CODE_READY: { - // Send response - const string respB64 = saslContext->encodeB64(resp, respLen) + "\r\n"; - m_socket->sendRaw(utility::stringUtils::bytesFromString(respB64), respB64.length()); + byte_t* challenge = 0; + size_t challengeLen = 0; - if (m_tracer) - m_tracer->traceSendBytes(respB64.length() - 2, "SASL exchange"); - } - catch (exceptions::sasl_exception& e) - { - if (challenge) - { - delete [] challenge; - challenge = NULL; - } + byte_t* resp = 0; + size_t respLen = 0; - if (resp) - { - delete [] resp; - resp = NULL; - } + try { - // Cancel SASL exchange - m_socket->send("*\r\n"); + // Extract challenge + saslContext->decodeB64(response->getText(), &challenge, &challengeLen); - if (m_tracer) - m_tracer->traceSend("*"); - } - catch (...) - { - if (challenge) + // Prepare response + saslSession->evaluateChallenge(challenge, challengeLen, &resp, &respLen); + + // Send response + const string respB64 = saslContext->encodeB64(resp, respLen) + "\r\n"; + m_socket->sendRaw(utility::stringUtils::bytesFromString(respB64), respB64.length()); + + if (m_tracer) { + m_tracer->traceSendBytes(respB64.length() - 2, "SASL exchange"); + } + + } catch (exceptions::sasl_exception& e) { + + if (challenge) { + delete [] challenge; + challenge = NULL; + } + + if (resp) { + delete [] resp; + resp = NULL; + } + + // Cancel SASL exchange + m_socket->send("*\r\n"); + + if (m_tracer) { + m_tracer->traceSend("*"); + } + + } catch (...) { + + if (challenge) { + delete [] challenge; + } + + if (resp) { + delete [] resp; + } + + throw; + } + + if (challenge) { delete [] challenge; + } - if (resp) + if (resp) { delete [] resp; + } - throw; + break; } - if (challenge) - delete [] challenge; - - if (resp) - delete [] resp; - - break; - } - default: + default: - cont = false; - break; + cont = false; + break; } } } - throw exceptions::authentication_error - ("Could not authenticate using SASL: all mechanisms failed."); + throw exceptions::authentication_error("Could not authenticate using SASL: all mechanisms failed."); } #endif // VMIME_HAVE_SASL_SUPPORT @@ -569,32 +585,34 @@ void POP3Connection::authenticateSASL() #if VMIME_HAVE_TLS_SUPPORT -void POP3Connection::startTLS() -{ - try - { +void POP3Connection::startTLS() { + + try { + POP3Command::STLS()->send(dynamicCast <POP3Connection>(shared_from_this())); shared_ptr <POP3Response> response = POP3Response::readResponse(dynamicCast <POP3Connection>(shared_from_this())); - if (!response->isSuccess()) + if (!response->isSuccess()) { throw exceptions::command_error("STLS", response->getFirstLine()); + } - shared_ptr <tls::TLSSession> tlsSession = tls::TLSSession::create - (m_store.lock()->getCertificateVerifier(), - m_store.lock()->getSession()->getTLSProperties()); + shared_ptr <tls::TLSSession> tlsSession = tls::TLSSession::create( + m_store.lock()->getCertificateVerifier(), + m_store.lock()->getSession()->getTLSProperties() + ); - shared_ptr <tls::TLSSocket> tlsSocket = - tlsSession->getSocket(m_socket); + shared_ptr <tls::TLSSocket> tlsSocket = tlsSession->getSocket(m_socket); tlsSocket->handshake(); m_socket = tlsSocket; m_secured = true; - m_cntInfos = make_shared <tls::TLSSecuredConnectionInfos> - (m_cntInfos->getHost(), m_cntInfos->getPort(), tlsSession, tlsSocket); + m_cntInfos = make_shared <tls::TLSSecuredConnectionInfos>( + m_cntInfos->getHost(), m_cntInfos->getPort(), tlsSession, tlsSocket + ); // " Once TLS has been started, the client MUST discard cached // information about server capabilities and SHOULD re-issue @@ -602,14 +620,14 @@ void POP3Connection::startTLS() // man-in-the-middle attacks which alter the capabilities list // prior to STLS. " (RFC-2595) invalidateCapabilities(); - } - catch (exceptions::command_error&) - { + + } catch (exceptions::command_error&) { + // Non-fatal error throw; - } - catch (exception&) - { + + } catch (exception&) { + // Fatal error internalDisconnect(); throw; @@ -619,24 +637,25 @@ void POP3Connection::startTLS() #endif // VMIME_HAVE_TLS_SUPPORT -const std::vector <string> POP3Connection::getCapabilities() -{ - if (!m_capabilitiesFetched) +const std::vector <string> POP3Connection::getCapabilities() { + + if (!m_capabilitiesFetched) { fetchCapabilities(); + } return m_capabilities; } -void POP3Connection::invalidateCapabilities() -{ +void POP3Connection::invalidateCapabilities() { + m_capabilities.clear(); m_capabilitiesFetched = false; } -void POP3Connection::fetchCapabilities() -{ +void POP3Connection::fetchCapabilities() { + POP3Command::CAPA()->send(dynamicCast <POP3Connection>(shared_from_this())); shared_ptr <POP3Response> response = @@ -644,10 +663,11 @@ void POP3Connection::fetchCapabilities() std::vector <string> res; - if (response->isSuccess()) - { - for (size_t i = 0, n = response->getLineCount() ; i < n ; ++i) + if (response->isSuccess()) { + + for (size_t i = 0, n = response->getLineCount() ; i < n ; ++i) { res.push_back(response->getLineAt(i)); + } } m_capabilities = res; @@ -655,56 +675,56 @@ void POP3Connection::fetchCapabilities() } -bool POP3Connection::isConnected() const -{ +bool POP3Connection::isConnected() const { + return m_socket && m_socket->isConnected() && m_authenticated; } -bool POP3Connection::isSecuredConnection() const -{ +bool POP3Connection::isSecuredConnection() const { + return m_secured; } -shared_ptr <connectionInfos> POP3Connection::getConnectionInfos() const -{ +shared_ptr <connectionInfos> POP3Connection::getConnectionInfos() const { + return m_cntInfos; } -shared_ptr <POP3Store> POP3Connection::getStore() -{ +shared_ptr <POP3Store> POP3Connection::getStore() { + return m_store.lock(); } -shared_ptr <session> POP3Connection::getSession() -{ +shared_ptr <session> POP3Connection::getSession() { + return m_store.lock()->getSession(); } -shared_ptr <socket> POP3Connection::getSocket() -{ +shared_ptr <socket> POP3Connection::getSocket() { + return m_socket; } -shared_ptr <tracer> POP3Connection::getTracer() -{ +shared_ptr <tracer> POP3Connection::getTracer() { + return m_tracer; } -shared_ptr <timeoutHandler> POP3Connection::getTimeoutHandler() -{ +shared_ptr <timeoutHandler> POP3Connection::getTimeoutHandler() { + return m_timeoutHandler; } -shared_ptr <security::authenticator> POP3Connection::getAuthenticator() -{ +shared_ptr <security::authenticator> POP3Connection::getAuthenticator() { + return m_auth; } diff --git a/src/vmime/net/pop3/POP3Connection.hpp b/src/vmime/net/pop3/POP3Connection.hpp index f40f1193..26b3f3c6 100644 --- a/src/vmime/net/pop3/POP3Connection.hpp +++ b/src/vmime/net/pop3/POP3Connection.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard <[email protected]> +// Copyright (C) 2002 Vincent Richard <[email protected]> // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License as @@ -61,11 +61,15 @@ class POP3Store; /** Manage connection to a POP3 server. */ -class VMIME_EXPORT POP3Connection : public object, public enable_shared_from_this <POP3Connection> -{ +class VMIME_EXPORT POP3Connection : public object, public enable_shared_from_this <POP3Connection> { + public: - POP3Connection(shared_ptr <POP3Store> store, shared_ptr <security::authenticator> auth); + POP3Connection( + const shared_ptr <POP3Store>& store, + const shared_ptr <security::authenticator>& auth + ); + virtual ~POP3Connection(); diff --git a/src/vmime/net/pop3/POP3Folder.cpp b/src/vmime/net/pop3/POP3Folder.cpp index 0e232c1a..4ca494fe 100644 --- a/src/vmime/net/pop3/POP3Folder.cpp +++ b/src/vmime/net/pop3/POP3Folder.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard <[email protected]> +// Copyright (C) 2002 Vincent Richard <[email protected]> // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License as @@ -45,59 +45,67 @@ namespace net { namespace pop3 { -POP3Folder::POP3Folder(const folder::path& path, shared_ptr <POP3Store> store) - : m_store(store), m_path(path), +POP3Folder::POP3Folder( + const folder::path& path, + const shared_ptr <POP3Store>& store +) + : m_store(store), + m_path(path), m_name(path.isEmpty() ? folder::path::component("") : path.getLastComponent()), - m_mode(-1), m_open(false) -{ + m_mode(-1), + m_open(false) { + store->registerFolder(this); } -POP3Folder::~POP3Folder() -{ - try - { +POP3Folder::~POP3Folder() { + + try { + shared_ptr <POP3Store> store = m_store.lock(); - if (store) - { - if (m_open) + if (store) { + + if (m_open) { close(false); + } store->unregisterFolder(this); - } - else if (m_open) - { + + } else if (m_open) { + onClose(); } - } - catch (...) - { + + } catch (...) { + // Don't throw in destructor } } -int POP3Folder::getMode() const -{ - if (!isOpen()) +int POP3Folder::getMode() const { + + if (!isOpen()) { throw exceptions::illegal_state("Folder not open"); + } - return (m_mode); + return m_mode; } -const folderAttributes POP3Folder::getAttributes() -{ +const folderAttributes POP3Folder::getAttributes() { + folderAttributes attribs; - if (m_path.isEmpty()) + if (m_path.isEmpty()) { attribs.setType(folderAttributes::TYPE_CONTAINS_FOLDERS); - else if (m_path.getSize() == 1 && m_path[0].getBuffer() == "INBOX") + } else if (m_path.getSize() == 1 && m_path[0].getBuffer() == "INBOX") { attribs.setType(folderAttributes::TYPE_CONTAINS_MESSAGES); - else + } else { throw exceptions::folder_not_found(); + } attribs.setFlags(0); @@ -105,72 +113,78 @@ const folderAttributes POP3Folder::getAttributes() } -const folder::path::component POP3Folder::getName() const -{ - return (m_name); +const folder::path::component POP3Folder::getName() const { + + return m_name; } -const folder::path POP3Folder::getFullPath() const -{ - return (m_path); +const folder::path POP3Folder::getFullPath() const { + + return m_path; } -void POP3Folder::open(const int mode, bool failIfModeIsNotAvailable) -{ +void POP3Folder::open(const int mode, bool failIfModeIsNotAvailable) { + shared_ptr <POP3Store> store = m_store.lock(); - if (!store) + if (!store) { throw exceptions::illegal_state("Store disconnected"); + } - if (m_path.isEmpty()) - { - if (mode != MODE_READ_ONLY && failIfModeIsNotAvailable) + if (m_path.isEmpty()) { + + if (mode != MODE_READ_ONLY && failIfModeIsNotAvailable) { throw exceptions::operation_not_supported(); + } m_open = true; m_mode = mode; m_messageCount = 0; - } - else if (m_path.getSize() == 1 && m_path[0].getBuffer() == "INBOX") - { + + } else if (m_path.getSize() == 1 && m_path[0].getBuffer() == "INBOX") { + POP3Command::STAT()->send(store->getConnection()); shared_ptr <POP3Response> response = POP3Response::readResponse(store->getConnection()); - if (!response->isSuccess()) + if (!response->isSuccess()) { throw exceptions::command_error("STAT", response->getFirstLine()); + } std::istringstream iss(response->getText()); iss.imbue(std::locale::classic()); iss >> m_messageCount; - if (iss.fail()) + if (iss.fail()) { throw exceptions::invalid_response("STAT", response->getFirstLine()); + } m_open = true; m_mode = mode; - } - else - { + + } else { + throw exceptions::folder_not_found(); } } -void POP3Folder::close(const bool expunge) -{ + +void POP3Folder::close(const bool expunge) { + shared_ptr <POP3Store> store = m_store.lock(); - if (!store) + if (!store) { throw exceptions::illegal_state("Store disconnected"); + } - if (!isOpen()) + if (!isOpen()) { throw exceptions::illegal_state("Folder not open"); + } - if (!expunge) - { + if (!expunge) { POP3Command::RSET()->send(store->getConnection()); POP3Response::readResponse(store->getConnection()); } @@ -182,168 +196,185 @@ void POP3Folder::close(const bool expunge) } -void POP3Folder::onClose() -{ - for (MessageMap::iterator it = m_messages.begin() ; it != m_messages.end() ; ++it) +void POP3Folder::onClose() { + + for (MessageMap::iterator it = m_messages.begin() ; it != m_messages.end() ; ++it) { (*it).first->onFolderClosed(); + } m_messages.clear(); } -void POP3Folder::create(const folderAttributes& /* attribs */) -{ +void POP3Folder::create(const folderAttributes& /* attribs */) { + throw exceptions::operation_not_supported(); } -void POP3Folder::destroy() -{ +void POP3Folder::destroy() { + throw exceptions::operation_not_supported(); } -bool POP3Folder::exists() -{ +bool POP3Folder::exists() { + shared_ptr <POP3Store> store = m_store.lock(); - if (!store) + if (!store) { throw exceptions::illegal_state("Store disconnected"); + } - return (m_path.isEmpty() || (m_path.getSize() == 1 && m_path[0].getBuffer() == "INBOX")); + return m_path.isEmpty() || (m_path.getSize() == 1 && m_path[0].getBuffer() == "INBOX"); } -bool POP3Folder::isOpen() const -{ - return (m_open); +bool POP3Folder::isOpen() const { + + return m_open; } -shared_ptr <message> POP3Folder::getMessage(const size_t num) -{ +shared_ptr <message> POP3Folder::getMessage(const size_t num) { + shared_ptr <POP3Store> store = m_store.lock(); - if (!store) + if (!store) { throw exceptions::illegal_state("Store disconnected"); - else if (!isOpen()) + } else if (!isOpen()) { throw exceptions::illegal_state("Folder not open"); - else if (num < 1 || num > m_messageCount) + } else if (num < 1 || num > m_messageCount) { throw exceptions::message_not_found(); + } return make_shared <POP3Message>(dynamicCast <POP3Folder>(shared_from_this()), num); } -std::vector <shared_ptr <message> > POP3Folder::getMessages(const messageSet& msgs) -{ +std::vector <shared_ptr <message> > POP3Folder::getMessages(const messageSet& msgs) { + shared_ptr <POP3Store> store = m_store.lock(); - if (!store) + if (!store) { throw exceptions::illegal_state("Store disconnected"); - else if (!isOpen()) + } else if (!isOpen()) { throw exceptions::illegal_state("Folder not open"); + } + + if (msgs.isNumberSet()) { - if (msgs.isNumberSet()) - { const std::vector <size_t> numbers = POP3Utils::messageSetToNumberList(msgs, m_messageCount); std::vector <shared_ptr <message> > messages; shared_ptr <POP3Folder> thisFolder(dynamicCast <POP3Folder>(shared_from_this())); - for (std::vector <size_t>::const_iterator it = numbers.begin() ; it != numbers.end() ; ++it) - { - if (*it < 1|| *it > m_messageCount) + for (std::vector <size_t>::const_iterator it = numbers.begin() ; it != numbers.end() ; ++it) { + + if (*it < 1|| *it > m_messageCount) { throw exceptions::message_not_found(); + } messages.push_back(make_shared <POP3Message>(thisFolder, *it)); } return messages; - } - else - { + + } else { + throw exceptions::operation_not_supported(); } } -size_t POP3Folder::getMessageCount() -{ +size_t POP3Folder::getMessageCount() { + shared_ptr <POP3Store> store = m_store.lock(); - if (!store) + if (!store) { throw exceptions::illegal_state("Store disconnected"); - else if (!isOpen()) + } else if (!isOpen()) { throw exceptions::illegal_state("Folder not open"); + } - return (m_messageCount); + return m_messageCount; } -shared_ptr <folder> POP3Folder::getFolder(const folder::path::component& name) -{ +shared_ptr <folder> POP3Folder::getFolder(const folder::path::component& name) { + shared_ptr <POP3Store> store = m_store.lock(); - if (!store) + if (!store) { throw exceptions::illegal_state("Store disconnected"); + } return shared_ptr <POP3Folder>(new POP3Folder(m_path / name, store)); } -std::vector <shared_ptr <folder> > POP3Folder::getFolders(const bool /* recursive */) -{ +std::vector <shared_ptr <folder> > POP3Folder::getFolders(const bool /* recursive */) { + shared_ptr <POP3Store> store = m_store.lock(); - if (!store) + if (!store) { throw exceptions::illegal_state("Store disconnected"); + } + + if (m_path.isEmpty()) { - if (m_path.isEmpty()) - { std::vector <shared_ptr <folder> > v; v.push_back(shared_ptr <POP3Folder>(new POP3Folder(folder::path::component("INBOX"), store))); - return (v); - } - else - { + return v; + + } else { + std::vector <shared_ptr <folder> > v; - return (v); + return v; } } -void POP3Folder::fetchMessages(std::vector <shared_ptr <message> >& msg, const fetchAttributes& options, - utility::progressListener* progress) -{ +void POP3Folder::fetchMessages( + std::vector <shared_ptr <message> >& msg, + const fetchAttributes& options, + utility::progressListener* progress +) { + shared_ptr <POP3Store> store = m_store.lock(); - if (!store) + if (!store) { throw exceptions::illegal_state("Store disconnected"); - else if (!isOpen()) + } else if (!isOpen()) { throw exceptions::illegal_state("Folder not open"); + } - if (msg.empty()) + if (msg.empty()) { return; + } const size_t total = msg.size(); size_t current = 0; - if (progress) + if (progress) { progress->start(total); + } for (std::vector <shared_ptr <message> >::iterator it = msg.begin() ; - it != msg.end() ; ++it) - { - dynamicCast <POP3Message>(*it)->fetch - (dynamicCast <POP3Folder>(shared_from_this()), options); + it != msg.end() ; ++it) { - if (progress) + dynamicCast <POP3Message>(*it)->fetch( + dynamicCast <POP3Folder>(shared_from_this()), + options + ); + + if (progress) { progress->progress(++current, total); + } } - if (options.has(fetchAttributes::SIZE)) - { + if (options.has(fetchAttributes::SIZE)) { + // Send the "LIST" command POP3Command::LIST()->send(store->getConnection()); @@ -351,8 +382,8 @@ void POP3Folder::fetchMessages(std::vector <shared_ptr <message> >& msg, const f shared_ptr <POP3Response> response = POP3Response::readMultilineResponse(store->getConnection()); - if (response->isSuccess()) - { + if (response->isSuccess()) { + // C: LIST // S: +OK // S: 1 47548 @@ -362,14 +393,14 @@ void POP3Folder::fetchMessages(std::vector <shared_ptr <message> >& msg, const f POP3Utils::parseMultiListOrUidlResponse(response, result); for (std::vector <shared_ptr <message> >::iterator it = msg.begin() ; - it != msg.end() ; ++it) - { + it != msg.end() ; ++it) { + shared_ptr <POP3Message> m = dynamicCast <POP3Message>(*it); std::map <size_t, string>::const_iterator x = result.find(m->m_num); - if (x != result.end()) - { + if (x != result.end()) { + size_t size = 0; std::istringstream iss((*x).second); @@ -380,11 +411,10 @@ void POP3Folder::fetchMessages(std::vector <shared_ptr <message> >& msg, const f } } } - } - if (options.has(fetchAttributes::UID)) - { + if (options.has(fetchAttributes::UID)) { + // Send the "UIDL" command POP3Command::UIDL()->send(store->getConnection()); @@ -392,8 +422,8 @@ void POP3Folder::fetchMessages(std::vector <shared_ptr <message> >& msg, const f shared_ptr <POP3Response> response = POP3Response::readMultilineResponse(store->getConnection()); - if (response->isSuccess()) - { + if (response->isSuccess()) { + // C: UIDL // S: +OK // S: 1 whqtswO00WBw418f9t5JxYwZ @@ -403,37 +433,42 @@ void POP3Folder::fetchMessages(std::vector <shared_ptr <message> >& msg, const f POP3Utils::parseMultiListOrUidlResponse(response, result); for (std::vector <shared_ptr <message> >::iterator it = msg.begin() ; - it != msg.end() ; ++it) - { + it != msg.end() ; ++it) { + shared_ptr <POP3Message> m = dynamicCast <POP3Message>(*it); std::map <size_t, string>::const_iterator x = result.find(m->m_num); - if (x != result.end()) + if (x != result.end()) { m->m_uid = (*x).second; + } } } } - if (progress) + if (progress) { progress->stop(total); + } } -void POP3Folder::fetchMessage(shared_ptr <message> msg, const fetchAttributes& options) -{ +void POP3Folder::fetchMessage(const shared_ptr <message>& msg, const fetchAttributes& options) { + shared_ptr <POP3Store> store = m_store.lock(); - if (!store) + if (!store) { throw exceptions::illegal_state("Store disconnected"); - else if (!isOpen()) + } else if (!isOpen()) { throw exceptions::illegal_state("Folder not open"); + } + + dynamicCast <POP3Message>(msg)->fetch( + dynamicCast <POP3Folder>(shared_from_this()), + options + ); - dynamicCast <POP3Message>(msg)->fetch - (dynamicCast <POP3Folder>(shared_from_this()), options); + if (options.has(fetchAttributes::SIZE)) { - if (options.has(fetchAttributes::SIZE)) - { // Send the "LIST" command POP3Command::LIST(msg->getNumber())->send(store->getConnection()); @@ -441,8 +476,8 @@ void POP3Folder::fetchMessage(shared_ptr <message> msg, const fetchAttributes& o shared_ptr <POP3Response> response = POP3Response::readResponse(store->getConnection()); - if (response->isSuccess()) - { + if (response->isSuccess()) { + string responseText = response->getText(); // C: LIST 2 @@ -453,8 +488,8 @@ void POP3Folder::fetchMessage(shared_ptr <message> msg, const fetchAttributes& o while (it != responseText.end() && !(*it == ' ' || *it == '\t')) ++it; while (it != responseText.end() && (*it == ' ' || *it == '\t')) ++it; - if (it != responseText.end()) - { + if (it != responseText.end()) { + size_t size = 0; std::istringstream iss(string(it, responseText.end())); @@ -466,8 +501,8 @@ void POP3Folder::fetchMessage(shared_ptr <message> msg, const fetchAttributes& o } } - if (options.has(fetchAttributes::UID)) - { + if (options.has(fetchAttributes::UID)) { + // Send the "UIDL" command POP3Command::UIDL(msg->getNumber())->send(store->getConnection()); @@ -475,8 +510,8 @@ void POP3Folder::fetchMessage(shared_ptr <message> msg, const fetchAttributes& o shared_ptr <POP3Response> response = POP3Response::readResponse(store->getConnection()); - if (response->isSuccess()) - { + if (response->isSuccess()) { + string responseText = response->getText(); // C: UIDL 2 @@ -487,21 +522,22 @@ void POP3Folder::fetchMessage(shared_ptr <message> msg, const fetchAttributes& o while (it != responseText.end() && !(*it == ' ' || *it == '\t')) ++it; while (it != responseText.end() && (*it == ' ' || *it == '\t')) ++it; - if (it != responseText.end()) - { - dynamicCast <POP3Message>(msg)->m_uid = - string(it, responseText.end()); + if (it != responseText.end()) { + dynamicCast <POP3Message>(msg)->m_uid = string(it, responseText.end()); } } } } -std::vector <shared_ptr <message> > POP3Folder::getAndFetchMessages - (const messageSet& msgs, const fetchAttributes& attribs) -{ - if (msgs.isEmpty()) +std::vector <shared_ptr <message> > POP3Folder::getAndFetchMessages( + const messageSet& msgs, + const fetchAttributes& attribs +) { + + if (msgs.isEmpty()) { return std::vector <shared_ptr <message> >(); + } std::vector <shared_ptr <message> > messages = getMessages(msgs); fetchMessages(messages, attribs); @@ -510,77 +546,84 @@ std::vector <shared_ptr <message> > POP3Folder::getAndFetchMessages } -int POP3Folder::getFetchCapabilities() const -{ - return fetchAttributes::ENVELOPE | fetchAttributes::CONTENT_INFO | - fetchAttributes::SIZE | fetchAttributes::FULL_HEADER | - fetchAttributes::UID | fetchAttributes::IMPORTANCE; +int POP3Folder::getFetchCapabilities() const { + + return fetchAttributes::ENVELOPE | + fetchAttributes::CONTENT_INFO | + fetchAttributes::SIZE | + fetchAttributes::FULL_HEADER | + fetchAttributes::UID | + fetchAttributes::IMPORTANCE; } -shared_ptr <folder> POP3Folder::getParent() -{ - if (m_path.isEmpty()) +shared_ptr <folder> POP3Folder::getParent() { + + if (m_path.isEmpty()) { return null; - else + } else { return shared_ptr <POP3Folder>(new POP3Folder(m_path.getParent(), m_store.lock())); + } } -shared_ptr <const store> POP3Folder::getStore() const -{ +shared_ptr <const store> POP3Folder::getStore() const { + return m_store.lock(); } -shared_ptr <store> POP3Folder::getStore() -{ +shared_ptr <store> POP3Folder::getStore() { + return m_store.lock(); } -void POP3Folder::registerMessage(POP3Message* msg) -{ +void POP3Folder::registerMessage(POP3Message* msg) { + m_messages.insert(MessageMap::value_type(msg, msg->getNumber())); } -void POP3Folder::unregisterMessage(POP3Message* msg) -{ +void POP3Folder::unregisterMessage(POP3Message* msg) { + m_messages.erase(msg); } -void POP3Folder::onStoreDisconnected() -{ +void POP3Folder::onStoreDisconnected() { + m_store.reset(); } -void POP3Folder::deleteMessages(const messageSet& msgs) -{ +void POP3Folder::deleteMessages(const messageSet& msgs) { + shared_ptr <POP3Store> store = m_store.lock(); const std::vector <size_t> nums = POP3Utils::messageSetToNumberList(msgs, m_messageCount); - if (nums.empty()) + if (nums.empty()) { throw exceptions::invalid_argument(); + } - if (!store) + if (!store) { throw exceptions::illegal_state("Store disconnected"); - else if (!isOpen()) + } else if (!isOpen()) { throw exceptions::illegal_state("Folder not open"); + } for (std::vector <size_t>::const_iterator - it = nums.begin() ; it != nums.end() ; ++it) - { + it = nums.begin() ; it != nums.end() ; ++it) { + POP3Command::DELE(*it)->send(store->getConnection()); shared_ptr <POP3Response> response = POP3Response::readResponse(store->getConnection()); - if (!response->isSuccess()) + if (!response->isSuccess()) { throw exceptions::command_error("DELE", response->getFirstLine()); + } } // Sort message list @@ -593,62 +636,77 @@ void POP3Folder::deleteMessages(const messageSet& msgs) // Update local flags for (std::map <POP3Message*, size_t>::iterator it = - m_messages.begin() ; it != m_messages.end() ; ++it) - { + m_messages.begin() ; it != m_messages.end() ; ++it) { + POP3Message* msg = (*it).first; - if (std::binary_search(list.begin(), list.end(), msg->getNumber())) + if (std::binary_search(list.begin(), list.end(), msg->getNumber())) { msg->m_deleted = true; + } } // Notify message flags changed shared_ptr <events::messageChangedEvent> event = - make_shared <events::messageChangedEvent> - (dynamicCast <folder>(shared_from_this()), - events::messageChangedEvent::TYPE_FLAGS, list); + make_shared <events::messageChangedEvent>( + dynamicCast <folder>(shared_from_this()), + events::messageChangedEvent::TYPE_FLAGS, + list + ); notifyMessageChanged(event); } -void POP3Folder::setMessageFlags(const messageSet& /* msgs */, - const int /* flags */, const int /* mode */) -{ +void POP3Folder::setMessageFlags( + const messageSet& /* msgs */, + const int /* flags */, + const int /* mode */ +) { + throw exceptions::operation_not_supported(); } -void POP3Folder::rename(const folder::path& /* newPath */) -{ +void POP3Folder::rename(const folder::path& /* newPath */) { + throw exceptions::operation_not_supported(); } -messageSet POP3Folder::addMessage - (shared_ptr <vmime::message> /* msg */, const int /* flags */, - vmime::datetime* /* date */, utility::progressListener* /* progress */) -{ +messageSet POP3Folder::addMessage( + const shared_ptr <vmime::message>& /* msg */, + const int /* flags */, + vmime::datetime* /* date */, + utility::progressListener* /* progress */ +) { + throw exceptions::operation_not_supported(); } -messageSet POP3Folder::addMessage - (utility::inputStream& /* is */, const size_t /* size */, const int /* flags */, - vmime::datetime* /* date */, utility::progressListener* /* progress */) -{ +messageSet POP3Folder::addMessage( + utility::inputStream& /* is */, + const size_t /* size */, + const int /* flags */, + vmime::datetime* /* date */, + utility::progressListener* /* progress */ +) { + throw exceptions::operation_not_supported(); } -messageSet POP3Folder::copyMessages - (const folder::path& /* dest */, const messageSet& /* msgs */) -{ +messageSet POP3Folder::copyMessages( + const folder::path& /* dest */, + const messageSet& /* msgs */ +) { + throw exceptions::operation_not_supported(); } -void POP3Folder::status(size_t& count, size_t& unseen) -{ +void POP3Folder::status(size_t& count, size_t& unseen) { + count = 0; unseen = 0; @@ -661,20 +719,22 @@ void POP3Folder::status(size_t& count, size_t& unseen) } -shared_ptr <folderStatus> POP3Folder::getStatus() -{ +shared_ptr <folderStatus> POP3Folder::getStatus() { + shared_ptr <POP3Store> store = m_store.lock(); - if (!store) + if (!store) { throw exceptions::illegal_state("Store disconnected"); + } POP3Command::STAT()->send(store->getConnection()); shared_ptr <POP3Response> response = POP3Response::readResponse(store->getConnection()); - if (!response->isSuccess()) + if (!response->isSuccess()) { throw exceptions::command_error("STAT", response->getFirstLine()); + } size_t count = 0; @@ -689,40 +749,45 @@ shared_ptr <folderStatus> POP3Folder::getStatus() status->setUnseenCount(count); // Update local message count - if (m_messageCount != count) - { + if (m_messageCount != count) { + const size_t oldCount = m_messageCount; m_messageCount = count; - if (count > oldCount) - { + if (count > oldCount) { + std::vector <size_t> nums; nums.resize(count - oldCount); - for (size_t i = oldCount + 1, j = 0 ; i <= count ; ++i, ++j) + for (size_t i = oldCount + 1, j = 0 ; i <= count ; ++i, ++j) { nums[j] = i; + } // Notify message count changed shared_ptr <events::messageCountEvent> event = - make_shared <events::messageCountEvent> - (dynamicCast <folder>(shared_from_this()), - events::messageCountEvent::TYPE_ADDED, nums); + make_shared <events::messageCountEvent>( + dynamicCast <folder>(shared_from_this()), + events::messageCountEvent::TYPE_ADDED, + nums + ); notifyMessageCount(event); // Notify folders with the same path for (std::list <POP3Folder*>::iterator it = store->m_folders.begin() ; - it != store->m_folders.end() ; ++it) - { - if ((*it) != this && (*it)->getFullPath() == m_path) - { + it != store->m_folders.end() ; ++it) { + + if ((*it) != this && (*it)->getFullPath() == m_path) { + (*it)->m_messageCount = count; shared_ptr <events::messageCountEvent> event = - make_shared <events::messageCountEvent> - (dynamicCast <folder>((*it)->shared_from_this()), - events::messageCountEvent::TYPE_ADDED, nums); + make_shared <events::messageCountEvent>( + dynamicCast <folder>((*it)->shared_from_this()), + events::messageCountEvent::TYPE_ADDED, + nums + ); (*it)->notifyMessageCount(event); } @@ -734,15 +799,15 @@ shared_ptr <folderStatus> POP3Folder::getStatus() } -void POP3Folder::expunge() -{ +void POP3Folder::expunge() { + // Not supported by POP3 protocol (deleted messages are automatically // expunged at the end of the session...). } -std::vector <size_t> POP3Folder::getMessageNumbersStartingOnUID(const message::uid& /* uid */) -{ +std::vector <size_t> POP3Folder::getMessageNumbersStartingOnUID(const message::uid& /* uid */) { + throw exceptions::operation_not_supported(); } diff --git a/src/vmime/net/pop3/POP3Folder.hpp b/src/vmime/net/pop3/POP3Folder.hpp index 339399d8..73e29f99 100644 --- a/src/vmime/net/pop3/POP3Folder.hpp +++ b/src/vmime/net/pop3/POP3Folder.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard <[email protected]> +// Copyright (C) 2002 Vincent Richard <[email protected]> // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License as @@ -50,16 +50,15 @@ class POP3Message; /** POP3 folder implementation. */ +class VMIME_EXPORT POP3Folder : public folder { -class VMIME_EXPORT POP3Folder : public folder -{ private: friend class POP3Store; friend class POP3Message; POP3Folder(const POP3Folder&); - POP3Folder(const folder::path& path, shared_ptr <POP3Store> store); + POP3Folder(const folder::path& path, const shared_ptr <POP3Store>& store); public: @@ -94,10 +93,26 @@ public: void deleteMessages(const messageSet& msgs); - void setMessageFlags(const messageSet& msgs, const int flags, const int mode = message::FLAG_MODE_SET); - - messageSet addMessage(shared_ptr <vmime::message> msg, const int flags = -1, vmime::datetime* date = NULL, utility::progressListener* progress = NULL); - messageSet addMessage(utility::inputStream& is, const size_t size, const int flags = -1, vmime::datetime* date = NULL, utility::progressListener* progress = NULL); + void setMessageFlags( + const messageSet& msgs, + const int flags, + const int mode = message::FLAG_MODE_SET + ); + + messageSet addMessage( + const shared_ptr <vmime::message>& msg, + const int flags = -1, + vmime::datetime* date = NULL, + utility::progressListener* progress = NULL + ); + + messageSet addMessage( + utility::inputStream& is, + const size_t size, + const int flags = -1, + vmime::datetime* date = NULL, + utility::progressListener* progress = NULL + ); messageSet copyMessages(const folder::path& dest, const messageSet& msgs); @@ -112,11 +127,18 @@ public: shared_ptr <store> getStore(); - void fetchMessages(std::vector <shared_ptr <message> >& msg, const fetchAttributes& options, utility::progressListener* progress = NULL); - void fetchMessage(shared_ptr <message> msg, const fetchAttributes& options); + void fetchMessages( + std::vector <shared_ptr <message> >& msg, + const fetchAttributes& options, + utility::progressListener* progress = NULL + ); + + void fetchMessage(const shared_ptr <message>& msg, const fetchAttributes& options); - std::vector <shared_ptr <message> > getAndFetchMessages - (const messageSet& msgs, const fetchAttributes& attribs); + std::vector <shared_ptr <message> > getAndFetchMessages( + const messageSet& msgs, + const fetchAttributes& attribs + ); int getFetchCapabilities() const; diff --git a/src/vmime/net/pop3/POP3FolderStatus.cpp b/src/vmime/net/pop3/POP3FolderStatus.cpp index 15e4cc92..9f2c49fb 100644 --- a/src/vmime/net/pop3/POP3FolderStatus.cpp +++ b/src/vmime/net/pop3/POP3FolderStatus.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard <[email protected]> +// Copyright (C) 2002 Vincent Richard <[email protected]> // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License as @@ -37,45 +37,45 @@ namespace pop3 { POP3FolderStatus::POP3FolderStatus() : m_count(0), - m_unseen(0) -{ + m_unseen(0) { + } POP3FolderStatus::POP3FolderStatus(const POP3FolderStatus& other) : folderStatus(), m_count(other.m_count), - m_unseen(other.m_unseen) -{ + m_unseen(other.m_unseen) { + } -size_t POP3FolderStatus::getMessageCount() const -{ +size_t POP3FolderStatus::getMessageCount() const { + return m_count; } -size_t POP3FolderStatus::getUnseenCount() const -{ +size_t POP3FolderStatus::getUnseenCount() const { + return m_unseen; } -void POP3FolderStatus::setMessageCount(const size_t count) -{ +void POP3FolderStatus::setMessageCount(const size_t count) { + m_count = count; } -void POP3FolderStatus::setUnseenCount(const size_t unseen) -{ +void POP3FolderStatus::setUnseenCount(const size_t unseen) { + m_unseen = unseen; } -shared_ptr <folderStatus> POP3FolderStatus::clone() const -{ +shared_ptr <folderStatus> POP3FolderStatus::clone() const { + return make_shared <POP3FolderStatus>(*this); } diff --git a/src/vmime/net/pop3/POP3FolderStatus.hpp b/src/vmime/net/pop3/POP3FolderStatus.hpp index 74c07a51..0ce413e4 100644 --- a/src/vmime/net/pop3/POP3FolderStatus.hpp +++ b/src/vmime/net/pop3/POP3FolderStatus.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard <[email protected]> +// Copyright (C) 2002 Vincent Richard <[email protected]> // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License as @@ -41,9 +41,8 @@ namespace pop3 { /** Holds the status of a POP3 folder. */ +class VMIME_EXPORT POP3FolderStatus : public folderStatus { -class VMIME_EXPORT POP3FolderStatus : public folderStatus -{ public: POP3FolderStatus(); diff --git a/src/vmime/net/pop3/POP3Message.cpp b/src/vmime/net/pop3/POP3Message.cpp index 67ad6d16..8d6b7f53 100644 --- a/src/vmime/net/pop3/POP3Message.cpp +++ b/src/vmime/net/pop3/POP3Message.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard <[email protected]> +// Copyright (C) 2002 Vincent Richard <[email protected]> // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License as @@ -44,162 +44,186 @@ namespace net { namespace pop3 { -POP3Message::POP3Message(shared_ptr <POP3Folder> folder, const size_t num) - : m_folder(folder), m_num(num), m_size(-1), m_deleted(false) -{ +POP3Message::POP3Message( + const shared_ptr <POP3Folder>& folder, + const size_t num +) + : m_folder(folder), + m_num(num), + m_size(-1), + m_deleted(false) { + folder->registerMessage(this); } -POP3Message::~POP3Message() -{ - try - { +POP3Message::~POP3Message() { + + try { + shared_ptr <POP3Folder> folder = m_folder.lock(); - if (folder) + if (folder) { folder->unregisterMessage(this); - } - catch (...) - { + } + + } catch (...) { + // Don't throw in destructor } } -void POP3Message::onFolderClosed() -{ +void POP3Message::onFolderClosed() { + m_folder.reset(); } -size_t POP3Message::getNumber() const -{ - return (m_num); +size_t POP3Message::getNumber() const { + + return m_num; } -const message::uid POP3Message::getUID() const -{ - return (m_uid); +const message::uid POP3Message::getUID() const { + + return m_uid; } -size_t POP3Message::getSize() const -{ - if (m_size == static_cast <size_t>(-1)) +size_t POP3Message::getSize() const { + + if (m_size == static_cast <size_t>(-1)) { throw exceptions::unfetched_object(); + } - return (m_size); + return m_size; } -bool POP3Message::isExpunged() const -{ - return (false); +bool POP3Message::isExpunged() const { + + return false; } -int POP3Message::getFlags() const -{ +int POP3Message::getFlags() const { + int flags = 0; - if (m_deleted) + if (m_deleted) { flags |= FLAG_DELETED; + } - return (flags); + return flags; } -shared_ptr <const messageStructure> POP3Message::getStructure() const -{ +shared_ptr <const messageStructure> POP3Message::getStructure() const { + throw exceptions::operation_not_supported(); } -shared_ptr <messageStructure> POP3Message::getStructure() -{ +shared_ptr <messageStructure> POP3Message::getStructure() { + throw exceptions::operation_not_supported(); } -shared_ptr <const header> POP3Message::getHeader() const -{ - if (m_header == NULL) +shared_ptr <const header> POP3Message::getHeader() const { + + if (!m_header) { throw exceptions::unfetched_object(); + } - return (m_header); + return m_header; } -void POP3Message::extract - (utility::outputStream& os, - utility::progressListener* progress, - const size_t start, const size_t length, - const bool /* peek */) const -{ +void POP3Message::extract( + utility::outputStream& os, + utility::progressListener* progress, + const size_t start, + const size_t length, + const bool /* peek */ +) const { + shared_ptr <const POP3Folder> folder = m_folder.lock(); - if (!folder) + if (!folder) { throw exceptions::illegal_state("Folder closed"); - else if (!folder->getStore()) + } else if (!folder->getStore()) { throw exceptions::illegal_state("Store disconnected"); + } - if (start != 0 && length != static_cast <size_t>(-1)) + if (start != 0 && length != static_cast <size_t>(-1)) { throw exceptions::partial_fetch_not_supported(); + } // Emit the "RETR" command - shared_ptr <POP3Store> store = constCast <POP3Folder>(folder)->m_store.lock(); + shared_ptr <POP3Store> store = folder->m_store.lock(); POP3Command::RETR(m_num)->send(store->getConnection()); - try - { - POP3Response::readLargeResponse - (store->getConnection(), os, progress, m_size == static_cast <size_t>(-1) ? 0 : m_size); - } - catch (exceptions::command_error& e) - { + try { + + POP3Response::readLargeResponse( + store->getConnection(), os, progress, + m_size == static_cast <size_t>(-1) ? 0 : m_size + ); + + } catch (exceptions::command_error& e) { + throw exceptions::command_error("RETR", e.response()); } } -void POP3Message::extractPart - (shared_ptr <const messagePart> /* p */, - utility::outputStream& /* os */, - utility::progressListener* /* progress */, - const size_t /* start */, const size_t /* length */, - const bool /* peek */) const -{ +void POP3Message::extractPart( + const shared_ptr <const messagePart>& /* p */, + utility::outputStream& /* os */, + utility::progressListener* /* progress */, + const size_t /* start */, + const size_t /* length */, + const bool /* peek */ +) const { + throw exceptions::operation_not_supported(); } -void POP3Message::fetchPartHeader(shared_ptr <messagePart> /* p */) -{ +void POP3Message::fetchPartHeader(const shared_ptr <messagePart>& /* p */) { + throw exceptions::operation_not_supported(); } -void POP3Message::fetch(shared_ptr <POP3Folder> msgFolder, const fetchAttributes& options) -{ +void POP3Message::fetch( + const shared_ptr <POP3Folder>& msgFolder, + const fetchAttributes& options +) { + shared_ptr <POP3Folder> folder = m_folder.lock(); - if (folder != msgFolder) + if (folder != msgFolder) { throw exceptions::folder_not_found(); + } // STRUCTURE and FLAGS attributes are not supported by POP3 - if (options.has(fetchAttributes::STRUCTURE | fetchAttributes::FLAGS)) + if (options.has(fetchAttributes::STRUCTURE | fetchAttributes::FLAGS)) { throw exceptions::operation_not_supported(); + } // Check for the real need to fetch the full header static const int optionsRequiringHeader = fetchAttributes::ENVELOPE | fetchAttributes::CONTENT_INFO | fetchAttributes::FULL_HEADER | fetchAttributes::IMPORTANCE; - if (!options.has(optionsRequiringHeader)) + if (!options.has(optionsRequiringHeader)) { return; + } // No need to differenciate between ENVELOPE, CONTENT_INFO, ... // since POP3 only permits to retrieve the whole header and not @@ -210,32 +234,34 @@ void POP3Message::fetch(shared_ptr <POP3Folder> msgFolder, const fetchAttributes POP3Command::TOP(m_num, 0)->send(store->getConnection()); - try - { + try { + string buffer; utility::outputStreamStringAdapter bufferStream(buffer); - POP3Response::readLargeResponse(store->getConnection(), - bufferStream, /* progress */ NULL, /* predictedSize */ 0); + POP3Response::readLargeResponse( + store->getConnection(), + bufferStream, /* progress */ NULL, /* predictedSize */ 0 + ); m_header = make_shared <header>(); m_header->parse(buffer); - } - catch (exceptions::command_error& e) - { + + } catch (exceptions::command_error& e) { + throw exceptions::command_error("TOP", e.response()); } } -void POP3Message::setFlags(const int /* flags */, const int /* mode */) -{ +void POP3Message::setFlags(const int /* flags */, const int /* mode */) { + throw exceptions::operation_not_supported(); } -shared_ptr <vmime::message> POP3Message::getParsedMessage() -{ +shared_ptr <vmime::message> POP3Message::getParsedMessage() { + std::ostringstream oss; utility::outputStreamAdapter os(oss); diff --git a/src/vmime/net/pop3/POP3Message.hpp b/src/vmime/net/pop3/POP3Message.hpp index e4e3b079..3d6dc921 100644 --- a/src/vmime/net/pop3/POP3Message.hpp +++ b/src/vmime/net/pop3/POP3Message.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard <[email protected]> +// Copyright (C) 2002 Vincent Richard <[email protected]> // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License as @@ -45,9 +45,8 @@ class POP3Folder; /** POP3 message implementation. */ +class VMIME_EXPORT POP3Message : public message { -class VMIME_EXPORT POP3Message : public message -{ private: friend class POP3Folder; @@ -56,7 +55,7 @@ private: public: - POP3Message(shared_ptr <POP3Folder> folder, const size_t num); + POP3Message(const shared_ptr <POP3Folder>& folder, const size_t num); ~POP3Message(); @@ -77,26 +76,30 @@ public: int getFlags() const; void setFlags(const int flags, const int mode = FLAG_MODE_SET); - void extract - (utility::outputStream& os, - utility::progressListener* progress = NULL, - const size_t start = 0, const size_t length = -1, - const bool peek = false) const; - - void extractPart - (shared_ptr <const messagePart> p, - utility::outputStream& os, - utility::progressListener* progress = NULL, - const size_t start = 0, const size_t length = -1, - const bool peek = false) const; - - void fetchPartHeader(shared_ptr <messagePart> p); + void extract( + utility::outputStream& os, + utility::progressListener* progress = NULL, + const size_t start = 0, + const size_t length = -1, + const bool peek = false + ) const; + + void extractPart( + const shared_ptr <const messagePart>& p, + utility::outputStream& os, + utility::progressListener* progress = NULL, + const size_t start = 0, + const size_t length = -1, + const bool peek = false + ) const; + + void fetchPartHeader(const shared_ptr <messagePart>& p); shared_ptr <vmime::message> getParsedMessage(); private: - void fetch(shared_ptr <POP3Folder> folder, const fetchAttributes& options); + void fetch(const shared_ptr <POP3Folder>& folder, const fetchAttributes& options); void onFolderClosed(); diff --git a/src/vmime/net/pop3/POP3Response.cpp b/src/vmime/net/pop3/POP3Response.cpp index de3c2cf3..725841e3 100644 --- a/src/vmime/net/pop3/POP3Response.cpp +++ b/src/vmime/net/pop3/POP3Response.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard <[email protected]> +// Copyright (C) 2002 Vincent Richard <[email protected]> // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License as @@ -46,17 +46,26 @@ namespace net { namespace pop3 { -POP3Response::POP3Response(shared_ptr <socket> sok, shared_ptr <timeoutHandler> toh, shared_ptr <tracer> tracer) - : m_socket(sok), m_timeoutHandler(toh), m_tracer(tracer) -{ +POP3Response::POP3Response( + const shared_ptr <socket>& sok, + const shared_ptr <timeoutHandler>& toh, + const shared_ptr <tracer>& tracer +) + : m_socket(sok), + m_timeoutHandler(toh), + m_tracer(tracer) { + } // static -shared_ptr <POP3Response> POP3Response::readResponse(shared_ptr <POP3Connection> conn) -{ - shared_ptr <POP3Response> resp = shared_ptr <POP3Response> - (new POP3Response(conn->getSocket(), conn->getTimeoutHandler(), conn->getTracer())); +shared_ptr <POP3Response> POP3Response::readResponse( + const shared_ptr <POP3Connection>& conn +) { + + shared_ptr <POP3Response> resp = shared_ptr <POP3Response>( + new POP3Response(conn->getSocket(), conn->getTimeoutHandler(), conn->getTracer()) + ); string buffer; resp->readResponseImpl(buffer, /* multiLine */ false); @@ -65,18 +74,22 @@ shared_ptr <POP3Response> POP3Response::readResponse(shared_ptr <POP3Connection> resp->m_code = getResponseCode(buffer); stripResponseCode(buffer, resp->m_text); - if (resp->m_tracer) + if (resp->m_tracer) { resp->m_tracer->traceReceive(buffer); + } return resp; } // static -shared_ptr <POP3Response> POP3Response::readMultilineResponse(shared_ptr <POP3Connection> conn) -{ - shared_ptr <POP3Response> resp = shared_ptr <POP3Response> - (new POP3Response(conn->getSocket(), conn->getTimeoutHandler(), conn->getTracer())); +shared_ptr <POP3Response> POP3Response::readMultilineResponse( + const shared_ptr <POP3Connection>& conn +) { + + shared_ptr <POP3Response> resp = shared_ptr <POP3Response>( + new POP3Response(conn->getSocket(), conn->getTimeoutHandler(), conn->getTracer()) + ); string buffer; resp->readResponseImpl(buffer, /* multiLine */ true); @@ -91,32 +104,39 @@ shared_ptr <POP3Response> POP3Response::readMultilineResponse(shared_ptr <POP3Co std::istringstream iss(nextLines); string line; - if (resp->m_tracer) + if (resp->m_tracer) { resp->m_tracer->traceReceive(firstLine); + } + + while (std::getline(iss, line, '\n')) { - while (std::getline(iss, line, '\n')) - { line = utility::stringUtils::trim(line); resp->m_lines.push_back(line); - if (resp->m_tracer) + if (resp->m_tracer) { resp->m_tracer->traceReceive(line); + } } - if (resp->m_tracer) + if (resp->m_tracer) { resp->m_tracer->traceReceive("."); + } return resp; } // static -shared_ptr <POP3Response> POP3Response::readLargeResponse - (shared_ptr <POP3Connection> conn, utility::outputStream& os, - utility::progressListener* progress, const size_t predictedSize) -{ - shared_ptr <POP3Response> resp = shared_ptr <POP3Response> - (new POP3Response(conn->getSocket(), conn->getTimeoutHandler(), conn->getTracer())); +shared_ptr <POP3Response> POP3Response::readLargeResponse( + const shared_ptr <POP3Connection>& conn, + utility::outputStream& os, + utility::progressListener* progress, + const size_t predictedSize +) { + + shared_ptr <POP3Response> resp = shared_ptr <POP3Response>( + new POP3Response(conn->getSocket(), conn->getTimeoutHandler(), conn->getTracer()) + ); string firstLine; const size_t length = resp->readResponseImpl(firstLine, os, progress, predictedSize); @@ -125,8 +145,7 @@ shared_ptr <POP3Response> POP3Response::readLargeResponse resp->m_code = getResponseCode(firstLine); stripResponseCode(firstLine, resp->m_text); - if (resp->m_tracer) - { + if (resp->m_tracer) { resp->m_tracer->traceReceive(firstLine); resp->m_tracer->traceReceiveBytes(length - firstLine.length()); resp->m_tracer->traceReceive("."); @@ -136,60 +155,62 @@ shared_ptr <POP3Response> POP3Response::readLargeResponse } -bool POP3Response::isSuccess() const -{ +bool POP3Response::isSuccess() const { + return m_code == CODE_OK; } -const string POP3Response::getFirstLine() const -{ +const string POP3Response::getFirstLine() const { + return m_firstLine; } -POP3Response::ResponseCode POP3Response::getCode() const -{ +POP3Response::ResponseCode POP3Response::getCode() const { + return m_code; } -const string POP3Response::getText() const -{ +const string POP3Response::getText() const { + return m_text; } -const string POP3Response::getLineAt(const size_t pos) const -{ +const string POP3Response::getLineAt(const size_t pos) const { + return m_lines[pos]; } -size_t POP3Response::getLineCount() const -{ +size_t POP3Response::getLineCount() const { + return m_lines.size(); } -void POP3Response::readResponseImpl(string& buffer, const bool multiLine) -{ +void POP3Response::readResponseImpl(string& buffer, const bool multiLine) { + bool foundTerminator = false; - if (m_timeoutHandler) + if (m_timeoutHandler) { m_timeoutHandler->resetTimeOut(); + } buffer.clear(); char last1 = '\0', last2 = '\0'; - for ( ; !foundTerminator ; ) - { + for ( ; !foundTerminator ; ) { + // Check whether the time-out delay is elapsed - if (m_timeoutHandler && m_timeoutHandler->isTimeOut()) - { - if (!m_timeoutHandler->handleTimeOut()) + if (m_timeoutHandler && m_timeoutHandler->isTimeOut()) { + + if (!m_timeoutHandler->handleTimeOut()) { throw exceptions::operation_timed_out(); + } m_timeoutHandler->resetTimeOut(); } @@ -198,36 +219,38 @@ void POP3Response::readResponseImpl(string& buffer, const bool multiLine) string receiveBuffer; m_socket->receive(receiveBuffer); - if (receiveBuffer.empty()) // buffer is empty - { - if (m_socket->getStatus() & socket::STATUS_WANT_WRITE) + if (receiveBuffer.empty()) { // buffer is empty + + if (m_socket->getStatus() & socket::STATUS_WANT_WRITE) { m_socket->waitForWrite(); - else + } else { m_socket->waitForRead(); + } continue; } // We have received data: reset the time-out counter - if (m_timeoutHandler) + if (m_timeoutHandler) { m_timeoutHandler->resetTimeOut(); + } // Check for transparent characters: '\n..' becomes '\n.' const char first = receiveBuffer[0]; - if (first == '.' && last2 == '\n' && last1 == '.') - { + if (first == '.' && last2 == '\n' && last1 == '.') { + receiveBuffer.erase(receiveBuffer.begin()); - } - else if (receiveBuffer.length() >= 2 && first == '.' && - receiveBuffer[1] == '.' && last1 == '\n') - { + + } else if (receiveBuffer.length() >= 2 && first == '.' && + receiveBuffer[1] == '.' && last1 == '\n') { + receiveBuffer.erase(receiveBuffer.begin()); } for (size_t trans ; - string::npos != (trans = receiveBuffer.find("\n..")) ; ) - { + string::npos != (trans = receiveBuffer.find("\n..")) ; ) { + receiveBuffer.replace(trans, 3, "\n."); } @@ -244,28 +267,35 @@ void POP3Response::readResponseImpl(string& buffer, const bool multiLine) // requires a multi-line response, the error response will // include only one line, so we stop waiting for a multi-line // terminator and check for a "normal" one. - if (multiLine && !foundTerminator && buffer.length() >= 4 && buffer[0] == '-') - { + if (multiLine && + !foundTerminator && + buffer.length() >= 4 && buffer[0] == '-') { + foundTerminator = checkTerminator(buffer, false); } } } -size_t POP3Response::readResponseImpl - (string& firstLine, utility::outputStream& os, - utility::progressListener* progress, const size_t predictedSize) -{ +size_t POP3Response::readResponseImpl( + string& firstLine, + utility::outputStream& os, + utility::progressListener* progress, + const size_t predictedSize +) { + size_t current = 0, total = predictedSize; string temp; bool codeDone = false; - if (progress) + if (progress) { progress->start(total); + } - if (m_timeoutHandler) + if (m_timeoutHandler) { m_timeoutHandler->resetTimeOut(); + } utility::inputStreamSocketAdapter sis(*m_socket); utility::stopSequenceFilteredInputStream <5> sfis1(sis, "\r\n.\r\n"); @@ -274,31 +304,27 @@ size_t POP3Response::readResponseImpl utility::inputStream& is = dfis; - while (!is.eof()) - { + while (!is.eof()) { + // Check whether the time-out delay is elapsed - if (m_timeoutHandler && m_timeoutHandler->isTimeOut()) - { - if (!m_timeoutHandler->handleTimeOut()) + if (m_timeoutHandler && m_timeoutHandler->isTimeOut()) { + + if (!m_timeoutHandler->handleTimeOut()) { throw exceptions::operation_timed_out(); + } } // Receive data from the socket byte_t buffer[65536]; const size_t read = is.read(buffer, sizeof(buffer)); - if (read == 0) // buffer is empty - { - if (m_socket->getStatus() & socket::STATUS_WANT_WRITE) - { + if (read == 0) { // buffer is empty + + if (m_socket->getStatus() & socket::STATUS_WANT_WRITE) { m_socket->waitForWrite(); - } - else if (m_socket->getStatus() & socket::STATUS_WANT_READ) - { + } else if (m_socket->getStatus() & socket::STATUS_WANT_READ) { m_socket->waitForRead(); - } - else - { + } else { // Input stream needs more bytes to continue, but there // is enough data into socket buffer. Do not waitForRead(), // just retry read()ing on the stream. @@ -308,29 +334,30 @@ size_t POP3Response::readResponseImpl } // We have received data: reset the time-out counter - if (m_timeoutHandler) + if (m_timeoutHandler) { m_timeoutHandler->resetTimeOut(); + } // Notify progress current += read; - if (progress) - { + if (progress) { total = std::max(total, current); progress->progress(current, total); } // If we don't have extracted the response code yet - if (!codeDone) - { + if (!codeDone) { + vmime::utility::stringUtils::appendBytesToString(temp, buffer, read); string responseData; - if (stripFirstLine(temp, responseData, &firstLine) == true) - { - if (getResponseCode(firstLine) != CODE_OK) + if (stripFirstLine(temp, responseData, &firstLine) == true) { + + if (getResponseCode(firstLine) != CODE_OK) { throw exceptions::command_error("?", firstLine); + } codeDone = true; @@ -339,61 +366,73 @@ size_t POP3Response::readResponseImpl continue; } - } - else - { + + } else { + // Inject the data into the output stream os.write(buffer, read); } } - if (progress) + if (progress) { progress->stop(total); + } return current; } // static -bool POP3Response::stripFirstLine - (const string& buffer, string& result, string* firstLine) -{ +bool POP3Response::stripFirstLine( + const string& buffer, + string& result, + string* firstLine +) { + const size_t end = buffer.find('\n'); - if (end != string::npos) - { - if (firstLine) *firstLine = utility::stringUtils::trim(buffer.substr(0, end)); + if (end != string::npos) { + + if (firstLine) { + *firstLine = utility::stringUtils::trim(buffer.substr(0, end)); + } + result = buffer.substr(end + 1); + return true; - } - else - { - if (firstLine) *firstLine = utility::stringUtils::trim(buffer); + + } else { + + if (firstLine) { + *firstLine = utility::stringUtils::trim(buffer); + } + result = ""; + return false; } } // static -POP3Response::ResponseCode POP3Response::getResponseCode(const string& buffer) -{ - if (buffer.length() >= 2) - { +POP3Response::ResponseCode POP3Response::getResponseCode(const string& buffer) { + + if (buffer.length() >= 2) { + // +[space] if (buffer[0] == '+' && - (buffer[1] == ' ' || buffer[1] == '\t')) - { + (buffer[1] == ' ' || buffer[1] == '\t')) { + return CODE_READY; } // +OK - if (buffer.length() >= 3) - { + if (buffer.length() >= 3) { + if (buffer[0] == '+' && (buffer[1] == 'O' || buffer[1] == 'o') && - (buffer[2] == 'K' || buffer[1] == 'k')) - { + (buffer[2] == 'K' || buffer[1] == 'k')) { + return CODE_OK; } } @@ -405,37 +444,38 @@ POP3Response::ResponseCode POP3Response::getResponseCode(const string& buffer) // static -void POP3Response::stripResponseCode(const string& buffer, string& result) -{ +void POP3Response::stripResponseCode(const string& buffer, string& result) { + const size_t pos = buffer.find_first_of(" \t"); - if (pos != string::npos) + if (pos != string::npos) { result = buffer.substr(pos + 1); - else + } else { result = buffer; + } } // static -bool POP3Response::checkTerminator(string& buffer, const bool multiLine) -{ +bool POP3Response::checkTerminator(string& buffer, const bool multiLine) { + // Multi-line response - if (multiLine) - { + if (multiLine) { + static const string term1("\r\n.\r\n"); static const string term2("\n.\n"); - return (checkOneTerminator(buffer, term1) || - checkOneTerminator(buffer, term2)); - } + return checkOneTerminator(buffer, term1) || + checkOneTerminator(buffer, term2); + // Normal response - else - { + } else { + static const string term1("\r\n"); static const string term2("\n"); - return (checkOneTerminator(buffer, term1) || - checkOneTerminator(buffer, term2)); + return checkOneTerminator(buffer, term1) || + checkOneTerminator(buffer, term2); } return false; @@ -443,11 +483,11 @@ bool POP3Response::checkTerminator(string& buffer, const bool multiLine) // static -bool POP3Response::checkOneTerminator(string& buffer, const string& term) -{ +bool POP3Response::checkOneTerminator(string& buffer, const string& term) { + if (buffer.length() >= term.length() && - std::equal(buffer.end() - term.length(), buffer.end(), term.begin())) - { + std::equal(buffer.end() - term.length(), buffer.end(), term.begin())) { + buffer.erase(buffer.end() - term.length(), buffer.end()); return true; } diff --git a/src/vmime/net/pop3/POP3Response.hpp b/src/vmime/net/pop3/POP3Response.hpp index d85b5405..69f8d5de 100644 --- a/src/vmime/net/pop3/POP3Response.hpp +++ b/src/vmime/net/pop3/POP3Response.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard <[email protected]> +// Copyright (C) 2002 Vincent Richard <[email protected]> // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License as @@ -56,13 +56,12 @@ class POP3Connection; /** A POP3 response, as sent by the server. */ -class VMIME_EXPORT POP3Response : public object -{ +class VMIME_EXPORT POP3Response : public object { + public: /** Possible response codes. */ - enum ResponseCode - { + enum ResponseCode { CODE_OK = 0, CODE_READY, CODE_ERR @@ -77,7 +76,7 @@ public: * @throws exceptions::operation_timed_out if no data * has been received within the granted time */ - static shared_ptr <POP3Response> readResponse(shared_ptr <POP3Connection> conn); + static shared_ptr <POP3Response> readResponse(const shared_ptr <POP3Connection>& conn); /** Receive and parse a multiline POP3 response from * the specified connection. @@ -87,7 +86,7 @@ public: * @throws exceptions::operation_timed_out if no data * has been received within the granted time */ - static shared_ptr <POP3Response> readMultilineResponse(shared_ptr <POP3Connection> conn); + static shared_ptr <POP3Response> readMultilineResponse(const shared_ptr <POP3Connection>& conn); /** Receive and parse a large POP3 response (eg. message data) * from the specified connection. @@ -100,9 +99,12 @@ public: * @throws exceptions::operation_timed_out if no data * has been received within the granted time */ - static shared_ptr <POP3Response> readLargeResponse - (shared_ptr <POP3Connection> conn, utility::outputStream& os, - utility::progressListener* progress, const size_t predictedSize); + static shared_ptr <POP3Response> readLargeResponse( + const shared_ptr <POP3Connection>& conn, + utility::outputStream& os, + utility::progressListener* progress, + const size_t predictedSize + ); /** Returns whether the response is successful ("OK"). @@ -144,12 +146,20 @@ public: private: - POP3Response(shared_ptr <socket> sok, shared_ptr <timeoutHandler> toh, shared_ptr <tracer> tracer); + POP3Response( + const shared_ptr <socket>& sok, + const shared_ptr <timeoutHandler>& toh, + const shared_ptr <tracer>& tracer + ); void readResponseImpl(string& buffer, const bool multiLine); - size_t readResponseImpl - (string& firstLine, utility::outputStream& os, - utility::progressListener* progress, const size_t predictedSize); + + size_t readResponseImpl( + string& firstLine, + utility::outputStream& os, + utility::progressListener* progress, + const size_t predictedSize + ); static bool stripFirstLine(const string& buffer, string& result, string* firstLine); diff --git a/src/vmime/net/pop3/POP3SStore.cpp b/src/vmime/net/pop3/POP3SStore.cpp index f1c3da74..81a50bc0 100644 --- a/src/vmime/net/pop3/POP3SStore.cpp +++ b/src/vmime/net/pop3/POP3SStore.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard <[email protected]> +// Copyright (C) 2002 Vincent Richard <[email protected]> // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License as @@ -35,19 +35,22 @@ namespace net { namespace pop3 { -POP3SStore::POP3SStore(shared_ptr <session> sess, shared_ptr <security::authenticator> auth) - : POP3Store(sess, auth, true) -{ +POP3SStore::POP3SStore( + const shared_ptr <session>& sess, + const shared_ptr <security::authenticator>& auth +) + : POP3Store(sess, auth, true) { + } -POP3SStore::~POP3SStore() -{ +POP3SStore::~POP3SStore() { + } -const string POP3SStore::getProtocolName() const -{ +const string POP3SStore::getProtocolName() const { + return "pop3s"; } @@ -58,14 +61,14 @@ const string POP3SStore::getProtocolName() const POP3ServiceInfos POP3SStore::sm_infos(true); -const serviceInfos& POP3SStore::getInfosInstance() -{ +const serviceInfos& POP3SStore::getInfosInstance() { + return sm_infos; } -const serviceInfos& POP3SStore::getInfos() const -{ +const serviceInfos& POP3SStore::getInfos() const { + return sm_infos; } diff --git a/src/vmime/net/pop3/POP3SStore.hpp b/src/vmime/net/pop3/POP3SStore.hpp index e60b4ef8..76a6ee17 100644 --- a/src/vmime/net/pop3/POP3SStore.hpp +++ b/src/vmime/net/pop3/POP3SStore.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard <[email protected]> +// Copyright (C) 2002 Vincent Richard <[email protected]> // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License as @@ -41,12 +41,15 @@ namespace pop3 { /** POP3S store service. */ +class VMIME_EXPORT POP3SStore : public POP3Store { -class VMIME_EXPORT POP3SStore : public POP3Store -{ public: - POP3SStore(shared_ptr <session> sess, shared_ptr <security::authenticator> auth); + POP3SStore( + const shared_ptr <session>& sess, + const shared_ptr <security::authenticator>& auth + ); + ~POP3SStore(); const string getProtocolName() const; diff --git a/src/vmime/net/pop3/POP3ServiceInfos.cpp b/src/vmime/net/pop3/POP3ServiceInfos.cpp index 4760d4f2..4deee74d 100644 --- a/src/vmime/net/pop3/POP3ServiceInfos.cpp +++ b/src/vmime/net/pop3/POP3ServiceInfos.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard <[email protected]> +// Copyright (C) 2002 Vincent Richard <[email protected]> // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License as @@ -36,24 +36,24 @@ namespace pop3 { POP3ServiceInfos::POP3ServiceInfos(const bool pop3s) - : m_pop3s(pop3s) -{ + : m_pop3s(pop3s) { + } -const string POP3ServiceInfos::getPropertyPrefix() const -{ - if (m_pop3s) +const string POP3ServiceInfos::getPropertyPrefix() const { + + if (m_pop3s) { return "store.pop3s."; - else + } else { return "store.pop3."; + } } -const POP3ServiceInfos::props& POP3ServiceInfos::getProperties() const -{ - static props pop3Props = - { +const POP3ServiceInfos::props& POP3ServiceInfos::getProperties() const { + + static props pop3Props = { // POP3-specific options property("options.apop", serviceInfos::property::TYPE_BOOLEAN, "true"), property("options.apop.fallback", serviceInfos::property::TYPE_BOOLEAN, "true"), @@ -75,8 +75,8 @@ const POP3ServiceInfos::props& POP3ServiceInfos::getProperties() const property(serviceInfos::property::SERVER_PORT, "110"), }; - static props pop3sProps = - { + static props pop3sProps = { + // POP3-specific options property("options.apop", serviceInfos::property::TYPE_BOOLEAN, "true"), property("options.apop.fallback", serviceInfos::property::TYPE_BOOLEAN, "true"), @@ -102,8 +102,8 @@ const POP3ServiceInfos::props& POP3ServiceInfos::getProperties() const } -const std::vector <serviceInfos::property> POP3ServiceInfos::getAvailableProperties() const -{ +const std::vector <serviceInfos::property> POP3ServiceInfos::getAvailableProperties() const { + std::vector <property> list; const props& p = getProperties(); @@ -120,8 +120,7 @@ const std::vector <serviceInfos::property> POP3ServiceInfos::getAvailablePropert list.push_back(p.PROPERTY_AUTH_PASSWORD); #if VMIME_HAVE_TLS_SUPPORT - if (!m_pop3s) - { + if (!m_pop3s) { list.push_back(p.PROPERTY_CONNECTION_TLS); list.push_back(p.PROPERTY_CONNECTION_TLS_REQUIRED); } diff --git a/src/vmime/net/pop3/POP3ServiceInfos.hpp b/src/vmime/net/pop3/POP3ServiceInfos.hpp index 710d8be3..590a6bea 100644 --- a/src/vmime/net/pop3/POP3ServiceInfos.hpp +++ b/src/vmime/net/pop3/POP3ServiceInfos.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard <[email protected]> +// Copyright (C) 2002 Vincent Richard <[email protected]> // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License as @@ -41,15 +41,13 @@ namespace pop3 { /** Information about POP3 service. */ +class VMIME_EXPORT POP3ServiceInfos : public serviceInfos { -class VMIME_EXPORT POP3ServiceInfos : public serviceInfos -{ public: POP3ServiceInfos(const bool pop3s); - struct props - { + struct props { // POP3-specific options serviceInfos::property PROPERTY_OPTIONS_APOP; serviceInfos::property PROPERTY_OPTIONS_APOP_FALLBACK; diff --git a/src/vmime/net/pop3/POP3Store.cpp b/src/vmime/net/pop3/POP3Store.cpp index 4d1bb432..b06640fe 100644 --- a/src/vmime/net/pop3/POP3Store.cpp +++ b/src/vmime/net/pop3/POP3Store.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard <[email protected]> +// Copyright (C) 2002 Vincent Richard <[email protected]> // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License as @@ -42,125 +42,150 @@ namespace net { namespace pop3 { -POP3Store::POP3Store(shared_ptr <session> sess, shared_ptr <security::authenticator> auth, const bool secured) - : store(sess, getInfosInstance(), auth), m_isPOP3S(secured) -{ +POP3Store::POP3Store( + const shared_ptr <session>& sess, + const shared_ptr <security::authenticator>& auth, + const bool secured +) + : store(sess, getInfosInstance(), auth), + m_isPOP3S(secured) { + } -POP3Store::~POP3Store() -{ - try - { - if (isConnected()) +POP3Store::~POP3Store() { + + try { + + if (isConnected()) { disconnect(); - } - catch (...) - { + } + + } catch (...) { + // Don't throw in destructor } } -const string POP3Store::getProtocolName() const -{ +const string POP3Store::getProtocolName() const { + return "pop3"; } -shared_ptr <folder> POP3Store::getDefaultFolder() -{ - if (!isConnected()) +shared_ptr <folder> POP3Store::getDefaultFolder() { + + if (!isConnected()) { throw exceptions::illegal_state("Not connected"); + } - return shared_ptr <POP3Folder> - (new POP3Folder(folder::path(folder::path::component("INBOX")), - dynamicCast <POP3Store>(shared_from_this()))); + return shared_ptr <POP3Folder>( + new POP3Folder( + folder::path(folder::path::component("INBOX")), + dynamicCast <POP3Store>(shared_from_this()) + ) + ); } -shared_ptr <folder> POP3Store::getRootFolder() -{ - if (!isConnected()) +shared_ptr <folder> POP3Store::getRootFolder() { + + if (!isConnected()) { throw exceptions::illegal_state("Not connected"); + } - return shared_ptr <POP3Folder> - (new POP3Folder(folder::path(), dynamicCast <POP3Store>(shared_from_this()))); + return shared_ptr <POP3Folder>( + new POP3Folder( + folder::path(), + dynamicCast <POP3Store>(shared_from_this()) + ) + ); } -shared_ptr <folder> POP3Store::getFolder(const folder::path& path) -{ - if (!isConnected()) +shared_ptr <folder> POP3Store::getFolder(const folder::path& path) { + + if (!isConnected()) { throw exceptions::illegal_state("Not connected"); + } - return shared_ptr <POP3Folder> - (new POP3Folder(path, dynamicCast <POP3Store>(shared_from_this()))); + return shared_ptr <POP3Folder>( + new POP3Folder( + path, + dynamicCast <POP3Store>(shared_from_this()) + ) + ); } -bool POP3Store::isValidFolderName(const folder::path::component& /* name */) const -{ +bool POP3Store::isValidFolderName(const folder::path::component& /* name */) const { + return true; } -void POP3Store::connect() -{ - if (isConnected()) +void POP3Store::connect() { + + if (isConnected()) { throw exceptions::already_connected(); + } - m_connection = make_shared <POP3Connection> - (dynamicCast <POP3Store>(shared_from_this()), getAuthenticator()); + m_connection = make_shared <POP3Connection>( + dynamicCast <POP3Store>(shared_from_this()), getAuthenticator() + ); m_connection->connect(); } -bool POP3Store::isPOP3S() const -{ +bool POP3Store::isPOP3S() const { + return m_isPOP3S; } -bool POP3Store::isConnected() const -{ +bool POP3Store::isConnected() const { + return m_connection && m_connection->isConnected(); } -bool POP3Store::isSecuredConnection() const -{ - if (m_connection == NULL) +bool POP3Store::isSecuredConnection() const { + + if (!m_connection) { return false; + } return m_connection->isSecuredConnection(); } -shared_ptr <connectionInfos> POP3Store::getConnectionInfos() const -{ - if (m_connection == NULL) +shared_ptr <connectionInfos> POP3Store::getConnectionInfos() const { + + if (!m_connection) { return null; + } return m_connection->getConnectionInfos(); } -shared_ptr <POP3Connection> POP3Store::getConnection() -{ +shared_ptr <POP3Connection> POP3Store::getConnection() { + return m_connection; } -void POP3Store::disconnect() -{ - if (!isConnected()) +void POP3Store::disconnect() { + + if (!isConnected()) { throw exceptions::not_connected(); + } for (std::list <POP3Folder*>::iterator it = m_folders.begin() ; - it != m_folders.end() ; ++it) - { + it != m_folders.end() ; ++it) { + (*it)->onStoreDisconnected(); } @@ -172,36 +197,41 @@ void POP3Store::disconnect() } -void POP3Store::noop() -{ - if (!m_connection) +void POP3Store::noop() { + + if (!m_connection) { throw exceptions::not_connected(); + } POP3Command::NOOP()->send(m_connection); shared_ptr <POP3Response> response = POP3Response::readResponse(m_connection); - if (!response->isSuccess()) + if (!response->isSuccess()) { throw exceptions::command_error("NOOP", response->getFirstLine()); + } } -void POP3Store::registerFolder(POP3Folder* folder) -{ +void POP3Store::registerFolder(POP3Folder* folder) { + m_folders.push_back(folder); } -void POP3Store::unregisterFolder(POP3Folder* folder) -{ +void POP3Store::unregisterFolder(POP3Folder* folder) { + std::list <POP3Folder*>::iterator it = std::find(m_folders.begin(), m_folders.end(), folder); - if (it != m_folders.end()) m_folders.erase(it); + + if (it != m_folders.end()) { + m_folders.erase(it); + } } -int POP3Store::getCapabilities() const -{ - return (CAPABILITY_DELETE_MESSAGE); +int POP3Store::getCapabilities() const { + + return CAPABILITY_DELETE_MESSAGE; } @@ -211,14 +241,14 @@ int POP3Store::getCapabilities() const POP3ServiceInfos POP3Store::sm_infos(false); -const serviceInfos& POP3Store::getInfosInstance() -{ +const serviceInfos& POP3Store::getInfosInstance() { + return sm_infos; } -const serviceInfos& POP3Store::getInfos() const -{ +const serviceInfos& POP3Store::getInfos() const { + return sm_infos; } diff --git a/src/vmime/net/pop3/POP3Store.hpp b/src/vmime/net/pop3/POP3Store.hpp index b35659a0..140a1ab9 100644 --- a/src/vmime/net/pop3/POP3Store.hpp +++ b/src/vmime/net/pop3/POP3Store.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard <[email protected]> +// Copyright (C) 2002 Vincent Richard <[email protected]> // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License as @@ -51,15 +51,19 @@ class POP3Response; /** POP3 store service. */ +class VMIME_EXPORT POP3Store : public store { -class VMIME_EXPORT POP3Store : public store -{ friend class POP3Folder; friend class POP3Message; public: - POP3Store(shared_ptr <session> sess, shared_ptr <security::authenticator> auth, const bool secured = false); + POP3Store( + const shared_ptr <session>& sess, + const shared_ptr <security::authenticator>& auth, + const bool secured = false + ); + ~POP3Store(); const string getProtocolName() const; diff --git a/src/vmime/net/pop3/POP3Utils.cpp b/src/vmime/net/pop3/POP3Utils.cpp index 0649fb79..b38161e8 100644 --- a/src/vmime/net/pop3/POP3Utils.cpp +++ b/src/vmime/net/pop3/POP3Utils.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard <[email protected]> +// Copyright (C) 2002 Vincent Richard <[email protected]> // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License as @@ -39,24 +39,27 @@ namespace pop3 { // static -void POP3Utils::parseMultiListOrUidlResponse(shared_ptr <POP3Response> response, std::map <size_t, string>& result) -{ +void POP3Utils::parseMultiListOrUidlResponse( + const shared_ptr <POP3Response>& response, + std::map <size_t, string>& result +) { + std::map <size_t, string> ids; - for (size_t i = 0, n = response->getLineCount() ; i < n ; ++i) - { + for (size_t i = 0, n = response->getLineCount() ; i < n ; ++i) { + string line = response->getLineAt(i); string::iterator it = line.begin(); - while (it != line.end() && (*it == ' ' || *it == '\t')) + while (it != line.end() && (*it == ' ' || *it == '\t')) { ++it; + } + + if (it != line.end()) { - if (it != line.end()) - { size_t number = 0; - while (it != line.end() && (*it >= '0' && *it <= '9')) - { + while (it != line.end() && (*it >= '0' && *it <= '9')) { number = (number * 10) + (*it - '0'); ++it; } @@ -64,8 +67,7 @@ void POP3Utils::parseMultiListOrUidlResponse(shared_ptr <POP3Response> response, while (it != line.end() && !(*it == ' ' || *it == '\t')) ++it; while (it != line.end() && (*it == ' ' || *it == '\t')) ++it; - if (it != line.end()) - { + if (it != line.end()) { result.insert(std::map <size_t, string>::value_type(number, string(it, line.end()))); } } @@ -74,27 +76,30 @@ void POP3Utils::parseMultiListOrUidlResponse(shared_ptr <POP3Response> response, -class POP3MessageSetEnumerator : public messageSetEnumerator -{ +class POP3MessageSetEnumerator : public messageSetEnumerator { + public: POP3MessageSetEnumerator(const size_t msgCount) - : m_msgCount(msgCount) - { + : m_msgCount(msgCount) { } - void enumerateNumberMessageRange(const vmime::net::numberMessageRange& range) - { + void enumerateNumberMessageRange(const vmime::net::numberMessageRange& range) { + size_t last = range.getLast(); - if (last == size_t(-1)) last = m_msgCount; - for (size_t i = range.getFirst() ; i <= last ; ++i) + if (last == size_t(-1)) { + last = m_msgCount; + } + + for (size_t i = range.getFirst() ; i <= last ; ++i) { list.push_back(i); + } } - void enumerateUIDMessageRange(const vmime::net::UIDMessageRange& /* range */) - { + void enumerateUIDMessageRange(const vmime::net::UIDMessageRange& /* range */) { + // Not supported } @@ -109,8 +114,11 @@ private: // static -const std::vector <size_t> POP3Utils::messageSetToNumberList(const messageSet& msgs, const size_t msgCount) -{ +const std::vector <size_t> POP3Utils::messageSetToNumberList( + const messageSet& msgs, + const size_t msgCount +) { + POP3MessageSetEnumerator en(msgCount); msgs.enumerate(en); diff --git a/src/vmime/net/pop3/POP3Utils.hpp b/src/vmime/net/pop3/POP3Utils.hpp index c7d15b07..09d15d5b 100644 --- a/src/vmime/net/pop3/POP3Utils.hpp +++ b/src/vmime/net/pop3/POP3Utils.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard <[email protected]> +// Copyright (C) 2002 Vincent Richard <[email protected]> // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License as @@ -46,8 +46,8 @@ namespace pop3 { class POP3Response; -class VMIME_EXPORT POP3Utils -{ +class VMIME_EXPORT POP3Utils { + public: /** Parse a response of type ([integer] [string] \n)*. @@ -63,8 +63,10 @@ public: * @param result points to an associative array which maps a message * number to its corresponding data (either UID or size) */ - static void parseMultiListOrUidlResponse - (shared_ptr <POP3Response> response, std::map <size_t, string>& result); + static void parseMultiListOrUidlResponse( + const shared_ptr <POP3Response>& response, + std::map <size_t, string>& result + ); /** Returns a list of message numbers given a message set. * @@ -72,7 +74,10 @@ public: * @param msgCount number of messages in folder * @return list of message numbers */ - static const std::vector <size_t> messageSetToNumberList(const messageSet& msgs, const size_t msgCount); + static const std::vector <size_t> messageSetToNumberList( + const messageSet& msgs, + const size_t msgCount + ); }; diff --git a/src/vmime/net/pop3/pop3.hpp b/src/vmime/net/pop3/pop3.hpp index 366b1e4a..ced3a97c 100644 --- a/src/vmime/net/pop3/pop3.hpp +++ b/src/vmime/net/pop3/pop3.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard <[email protected]> +// Copyright (C) 2002 Vincent Richard <[email protected]> // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License as diff --git a/src/vmime/net/securedConnectionInfos.hpp b/src/vmime/net/securedConnectionInfos.hpp index 8ed8b138..60258018 100644 --- a/src/vmime/net/securedConnectionInfos.hpp +++ b/src/vmime/net/securedConnectionInfos.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard <[email protected]> +// Copyright (C) 2002 Vincent Richard <[email protected]> // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License as @@ -40,8 +40,8 @@ namespace net { /** Information about the secured connection used by a service. */ -class VMIME_EXPORT securedConnectionInfos : public connectionInfos -{ +class VMIME_EXPORT securedConnectionInfos : public connectionInfos { + }; diff --git a/src/vmime/net/sendmail/sendmail.hpp b/src/vmime/net/sendmail/sendmail.hpp index b3692526..a8d1412a 100644 --- a/src/vmime/net/sendmail/sendmail.hpp +++ b/src/vmime/net/sendmail/sendmail.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard <[email protected]> +// Copyright (C) 2002 Vincent Richard <[email protected]> // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License as diff --git a/src/vmime/net/sendmail/sendmailServiceInfos.cpp b/src/vmime/net/sendmail/sendmailServiceInfos.cpp index 21cac00c..b8654461 100644 --- a/src/vmime/net/sendmail/sendmailServiceInfos.cpp +++ b/src/vmime/net/sendmail/sendmailServiceInfos.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard <[email protected]> +// Copyright (C) 2002 Vincent Richard <[email protected]> // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License as @@ -35,21 +35,20 @@ namespace net { namespace sendmail { -sendmailServiceInfos::sendmailServiceInfos() -{ +sendmailServiceInfos::sendmailServiceInfos() { + } -const string sendmailServiceInfos::getPropertyPrefix() const -{ +const string sendmailServiceInfos::getPropertyPrefix() const { + return "transport.sendmail."; } -const sendmailServiceInfos::props& sendmailServiceInfos::getProperties() const -{ - static props sendmailProps = - { +const sendmailServiceInfos::props& sendmailServiceInfos::getProperties() const { + + static props sendmailProps = { // Path to sendmail (override default) property("binpath", serviceInfos::property::TYPE_STRING, string(VMIME_SENDMAIL_PATH)) }; @@ -58,8 +57,8 @@ const sendmailServiceInfos::props& sendmailServiceInfos::getProperties() const } -const std::vector <serviceInfos::property> sendmailServiceInfos::getAvailableProperties() const -{ +const std::vector <serviceInfos::property> sendmailServiceInfos::getAvailableProperties() const { + std::vector <property> list; const props& p = getProperties(); diff --git a/src/vmime/net/sendmail/sendmailServiceInfos.hpp b/src/vmime/net/sendmail/sendmailServiceInfos.hpp index de94e392..bfec2e0c 100644 --- a/src/vmime/net/sendmail/sendmailServiceInfos.hpp +++ b/src/vmime/net/sendmail/sendmailServiceInfos.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard <[email protected]> +// Copyright (C) 2002 Vincent Richard <[email protected]> // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License as @@ -41,15 +41,13 @@ namespace sendmail { /** Information about sendmail service. */ +class VMIME_EXPORT sendmailServiceInfos : public serviceInfos { -class VMIME_EXPORT sendmailServiceInfos : public serviceInfos -{ public: sendmailServiceInfos(); - struct props - { + struct props { serviceInfos::property PROPERTY_BINPATH; }; diff --git a/src/vmime/net/sendmail/sendmailTransport.cpp b/src/vmime/net/sendmail/sendmailTransport.cpp index 822e1114..e39cdd36 100644 --- a/src/vmime/net/sendmail/sendmailTransport.cpp +++ b/src/vmime/net/sendmail/sendmailTransport.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard <[email protected]> +// Copyright (C) 2002 Vincent Richard <[email protected]> // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License as @@ -58,36 +58,42 @@ namespace net { namespace sendmail { -sendmailTransport::sendmailTransport(shared_ptr <session> sess, shared_ptr <security::authenticator> auth) - : transport(sess, getInfosInstance(), auth), m_connected(false) -{ +sendmailTransport::sendmailTransport( + const shared_ptr <session>& sess, + const shared_ptr <security::authenticator>& auth +) + : transport(sess, getInfosInstance(), auth), + m_connected(false) { + } -sendmailTransport::~sendmailTransport() -{ - try - { - if (isConnected()) +sendmailTransport::~sendmailTransport() { + + try { + + if (isConnected()) { disconnect(); - } - catch (...) - { + } + + } catch (...) { + // Don't throw in destructor } } -const string sendmailTransport::getProtocolName() const -{ +const string sendmailTransport::getProtocolName() const { + return "sendmail"; } -void sendmailTransport::connect() -{ - if (isConnected()) +void sendmailTransport::connect() { + + if (isConnected()) { throw exceptions::already_connected(); + } // Use the specified path for 'sendmail' or a default one if no path is specified m_sendmailPath = GET_PROPERTY(string, PROPERTY_BINPATH); @@ -96,55 +102,61 @@ void sendmailTransport::connect() } -bool sendmailTransport::isConnected() const -{ - return (m_connected); +bool sendmailTransport::isConnected() const { + + return m_connected; } -bool sendmailTransport::isSecuredConnection() const -{ +bool sendmailTransport::isSecuredConnection() const { + return false; } -shared_ptr <connectionInfos> sendmailTransport::getConnectionInfos() const -{ +shared_ptr <connectionInfos> sendmailTransport::getConnectionInfos() const { + return make_shared <defaultConnectionInfos>("localhost", static_cast <port_t>(0)); } -void sendmailTransport::disconnect() -{ - if (!isConnected()) +void sendmailTransport::disconnect() { + + if (!isConnected()) { throw exceptions::not_connected(); + } internalDisconnect(); } -void sendmailTransport::internalDisconnect() -{ +void sendmailTransport::internalDisconnect() { + m_connected = false; } -void sendmailTransport::noop() -{ +void sendmailTransport::noop() { + // Do nothing } -void sendmailTransport::send - (const mailbox& expeditor, const mailboxList& recipients, - utility::inputStream& is, const size_t size, - utility::progressListener* progress, const mailbox& sender) -{ +void sendmailTransport::send( + const mailbox& expeditor, + const mailboxList& recipients, + utility::inputStream& is, + const size_t size, + utility::progressListener* progress, + const mailbox& sender +) { + // If no recipient/expeditor was found, throw an exception - if (recipients.isEmpty()) + if (recipients.isEmpty()) { throw exceptions::no_recipient(); - else if (expeditor.isEmpty()) + } else if (expeditor.isEmpty()) { throw exceptions::no_expeditor(); + } // Construct the argument list std::vector <string> args; @@ -152,38 +164,39 @@ void sendmailTransport::send args.push_back("-i"); args.push_back("-f"); - if (!sender.isEmpty()) + if (!sender.isEmpty()) { args.push_back(expeditor.getEmail().generate()); - else + } else { args.push_back(sender.getEmail().generate()); + } args.push_back("--"); - for (size_t i = 0 ; i < recipients.getMailboxCount() ; ++i) + for (size_t i = 0 ; i < recipients.getMailboxCount() ; ++i) { args.push_back(recipients.getMailboxAt(i)->getEmail().generate()); + } // Call sendmail - try - { + try { internalSend(args, is, size, progress); - } - catch (vmime::exception& e) - { + } catch (vmime::exception& e) { throw exceptions::command_error("SEND", "", "sendmail failed", e); } } -void sendmailTransport::internalSend - (const std::vector <string> args, utility::inputStream& is, - const size_t size, utility::progressListener* progress) -{ +void sendmailTransport::internalSend( + const std::vector <string>& args, + utility::inputStream& is, + const size_t size, + utility::progressListener* progress +) { + const utility::file::path path = vmime::platform::getHandler()-> getFileSystemFactory()->stringToPath(m_sendmailPath); shared_ptr <utility::childProcess> proc = - vmime::platform::getHandler()-> - getChildProcessFactory()->create(path); + vmime::platform::getHandler()->getChildProcessFactory()->create(path); proc->start(args, utility::childProcess::FLAG_REDIRECT_STDIN); @@ -209,14 +222,14 @@ void sendmailTransport::internalSend sendmailServiceInfos sendmailTransport::sm_infos; -const serviceInfos& sendmailTransport::getInfosInstance() -{ +const serviceInfos& sendmailTransport::getInfosInstance() { + return sm_infos; } -const serviceInfos& sendmailTransport::getInfos() const -{ +const serviceInfos& sendmailTransport::getInfos() const { + return sm_infos; } diff --git a/src/vmime/net/sendmail/sendmailTransport.hpp b/src/vmime/net/sendmail/sendmailTransport.hpp index d1c6aec0..76e95726 100644 --- a/src/vmime/net/sendmail/sendmailTransport.hpp +++ b/src/vmime/net/sendmail/sendmailTransport.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard <[email protected]> +// Copyright (C) 2002 Vincent Richard <[email protected]> // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License as @@ -45,12 +45,15 @@ namespace sendmail { /** Sendmail local transport service. */ +class VMIME_EXPORT sendmailTransport : public transport { -class VMIME_EXPORT sendmailTransport : public transport -{ public: - sendmailTransport(shared_ptr <session> sess, shared_ptr <security::authenticator> auth); + sendmailTransport( + const shared_ptr <session>& sess, + const shared_ptr <security::authenticator>& auth + ); + ~sendmailTransport(); const string getProtocolName() const; @@ -64,13 +67,14 @@ public: void noop(); - void send - (const mailbox& expeditor, - const mailboxList& recipients, - utility::inputStream& is, - const size_t size, - utility::progressListener* progress = NULL, - const mailbox& sender = mailbox()); + void send( + const mailbox& expeditor, + const mailboxList& recipients, + utility::inputStream& is, + const size_t size, + utility::progressListener* progress = NULL, + const mailbox& sender = mailbox() + ); bool isSecuredConnection() const; shared_ptr <connectionInfos> getConnectionInfos() const; @@ -79,8 +83,12 @@ private: void internalDisconnect(); - void internalSend(const std::vector <string> args, utility::inputStream& is, - const size_t size, utility::progressListener* progress); + void internalSend( + const std::vector <string>& args, + utility::inputStream& is, + const size_t size, + utility::progressListener* progress + ); string m_sendmailPath; diff --git a/src/vmime/net/service.cpp b/src/vmime/net/service.cpp index 3cf94d5e..b43c3e2f 100644 --- a/src/vmime/net/service.cpp +++ b/src/vmime/net/service.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard <[email protected]> +// Copyright (C) 2002 Vincent Richard <[email protected]> // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License as @@ -48,18 +48,20 @@ namespace vmime { namespace net { -service::service(shared_ptr <session> sess, const serviceInfos& /* infos */, - shared_ptr <security::authenticator> auth) - : m_session(sess), m_auth(auth) -{ - if (!auth) - { +service::service( + const shared_ptr <session>& sess, + const serviceInfos& /* infos */, + const shared_ptr <security::authenticator>& auth +) + : m_session(sess), + m_auth(auth) { + + if (!auth) { + #if VMIME_HAVE_SASL_SUPPORT - m_auth = make_shared - <security::sasl::defaultSASLAuthenticator>(); + m_auth = make_shared <security::sasl::defaultSASLAuthenticator>(); #else - m_auth = make_shared - <security::defaultAuthenticator>(); + m_auth = make_shared <security::defaultAuthenticator>(); #endif // VMIME_HAVE_SASL_SUPPORT } @@ -73,89 +75,89 @@ service::service(shared_ptr <session> sess, const serviceInfos& /* infos */, } -service::~service() -{ +service::~service() { + } -shared_ptr <const session> service::getSession() const -{ - return (m_session); +shared_ptr <const session> service::getSession() const { + + return m_session; } -shared_ptr <session> service::getSession() -{ - return (m_session); +shared_ptr <session> service::getSession() { + + return m_session; } -shared_ptr <const security::authenticator> service::getAuthenticator() const -{ - return (m_auth); +shared_ptr <const security::authenticator> service::getAuthenticator() const { + + return m_auth; } -shared_ptr <security::authenticator> service::getAuthenticator() -{ - return (m_auth); +shared_ptr <security::authenticator> service::getAuthenticator() { + + return m_auth; } -void service::setAuthenticator(shared_ptr <security::authenticator> auth) -{ +void service::setAuthenticator(const shared_ptr <security::authenticator>& auth) { + m_auth = auth; } #if VMIME_HAVE_TLS_SUPPORT -void service::setCertificateVerifier(shared_ptr <security::cert::certificateVerifier> cv) -{ +void service::setCertificateVerifier(const shared_ptr <security::cert::certificateVerifier>& cv) { + m_certVerifier = cv; } -shared_ptr <security::cert::certificateVerifier> service::getCertificateVerifier() -{ +shared_ptr <security::cert::certificateVerifier> service::getCertificateVerifier() { + return m_certVerifier; } #endif // VMIME_HAVE_TLS_SUPPORT -void service::setSocketFactory(shared_ptr <socketFactory> sf) -{ +void service::setSocketFactory(const shared_ptr <socketFactory>& sf) { + m_socketFactory = sf; } -shared_ptr <socketFactory> service::getSocketFactory() -{ +shared_ptr <socketFactory> service::getSocketFactory() { + return m_socketFactory; } -void service::setTracerFactory(shared_ptr <tracerFactory> tf) -{ +void service::setTracerFactory(const shared_ptr <tracerFactory>& tf) { + m_tracerFactory = tf; } -shared_ptr <tracerFactory> service::getTracerFactory() -{ +shared_ptr <tracerFactory> service::getTracerFactory() { + return m_tracerFactory; } -void service::setTimeoutHandlerFactory(shared_ptr <timeoutHandlerFactory> thf) -{ +void service::setTimeoutHandlerFactory(const shared_ptr <timeoutHandlerFactory>& thf) { + m_toHandlerFactory = thf; } -shared_ptr <timeoutHandlerFactory> service::getTimeoutHandlerFactory() -{ +shared_ptr <timeoutHandlerFactory> service::getTimeoutHandlerFactory() { + return m_toHandlerFactory; } diff --git a/src/vmime/net/service.hpp b/src/vmime/net/service.hpp index 8d144aec..bbd2a03d 100644 --- a/src/vmime/net/service.hpp +++ b/src/vmime/net/service.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard <[email protected]> +// Copyright (C) 2002 Vincent Richard <[email protected]> // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License as @@ -55,20 +55,22 @@ namespace net { /** Base class for messaging services. */ +class VMIME_EXPORT service : public object, public enable_shared_from_this <service> { -class VMIME_EXPORT service : public object, public enable_shared_from_this <service> -{ protected: - service(shared_ptr <session> sess, const serviceInfos& infos, shared_ptr <security::authenticator> auth); + service( + const shared_ptr <session>& sess, + const serviceInfos& infos, + const shared_ptr <security::authenticator>& auth + ); public: virtual ~service(); /** Possible service types. */ - enum Type - { + enum Type { TYPE_STORE = 0, /**< The service is a message store. */ TYPE_TRANSPORT /**< The service sends messages. */ }; @@ -139,14 +141,14 @@ public: * * @param auth authenticator object */ - void setAuthenticator(shared_ptr <security::authenticator> auth); + void setAuthenticator(const shared_ptr <security::authenticator>& auth); #if VMIME_HAVE_TLS_SUPPORT /** Set the object responsible for verifying certificates when * using secured connections (TLS/SSL). */ - void setCertificateVerifier(shared_ptr <security::cert::certificateVerifier> cv); + void setCertificateVerifier(const shared_ptr <security::cert::certificateVerifier>& cv); /** Get the object responsible for verifying certificates when * using secured connections (TLS/SSL). @@ -160,7 +162,7 @@ public: * * @param sf socket factory */ - void setSocketFactory(shared_ptr <socketFactory> sf); + void setSocketFactory(const shared_ptr <socketFactory>& sf); /** Return the factory used to create socket objects for this * service. @@ -175,7 +177,7 @@ public: * * @param thf timeoutHandler factory */ - void setTimeoutHandlerFactory(shared_ptr <timeoutHandlerFactory> thf); + void setTimeoutHandlerFactory(const shared_ptr <timeoutHandlerFactory>& thf); /** Return the factory used to create timeoutHandler objects for * this service. @@ -185,7 +187,7 @@ public: shared_ptr <timeoutHandlerFactory> getTimeoutHandlerFactory(); - void setTracerFactory(shared_ptr <tracerFactory> tf); + void setTracerFactory(const shared_ptr <tracerFactory>& tf); shared_ptr <tracerFactory> getTracerFactory(); @@ -198,8 +200,7 @@ public: * @param value property value */ template <typename TYPE> - void setProperty(const string& name, const TYPE& value) - { + void setProperty(const string& name, const TYPE& value) { m_session->getProperties()[getInfos().getPropertyPrefix() + name] = value; } diff --git a/src/vmime/net/serviceFactory.cpp b/src/vmime/net/serviceFactory.cpp index b6f90eb2..72b96fef 100644 --- a/src/vmime/net/serviceFactory.cpp +++ b/src/vmime/net/serviceFactory.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard <[email protected]> +// Copyright (C) 2002 Vincent Richard <[email protected]> // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License as @@ -39,96 +39,103 @@ namespace vmime { namespace net { -serviceFactory::serviceFactory() -{ +serviceFactory::serviceFactory() { + } -serviceFactory::~serviceFactory() -{ +serviceFactory::~serviceFactory() { + } -shared_ptr <serviceFactory> serviceFactory::getInstance() -{ +shared_ptr <serviceFactory> serviceFactory::getInstance() { + static serviceFactory instance; return shared_ptr <serviceFactory>(&instance, noop_shared_ptr_deleter <serviceFactory>()); } -shared_ptr <service> serviceFactory::create - (shared_ptr <session> sess, const string& protocol, - shared_ptr <security::authenticator> auth) -{ +shared_ptr <service> serviceFactory::create( + const shared_ptr <session>& sess, + const string& protocol, + const shared_ptr <security::authenticator>& auth +) { + shared_ptr <const registeredService> rserv = getServiceByProtocol(protocol); - if (!rserv) + if (!rserv) { throw exceptions::no_factory_available("No service is registered for protocol '" + protocol + "'."); + } return rserv->create(sess, auth); } -shared_ptr <service> serviceFactory::create - (shared_ptr <session> sess, const utility::url& u, - shared_ptr <security::authenticator> auth) -{ +shared_ptr <service> serviceFactory::create( + const shared_ptr <session>& sess, + const utility::url& u, + const shared_ptr <security::authenticator>& auth +) { + shared_ptr <service> serv = create(sess, u.getProtocol(), auth); sess->getProperties()[serv->getInfos().getPropertyPrefix() + "server.address"] = u.getHost(); - if (u.getPort() != utility::url::UNSPECIFIED_PORT) + if (u.getPort() != utility::url::UNSPECIFIED_PORT) { sess->getProperties()[serv->getInfos().getPropertyPrefix() + "server.port"] = u.getPort(); + } // Path portion of the URL is used to point a specific folder (empty = root). // In maildir, this is used to point to the root of the message repository. - if (!u.getPath().empty()) + if (!u.getPath().empty()) { sess->getProperties()[serv->getInfos().getPropertyPrefix() + "server.rootpath"] = u.getPath(); + } - if (!u.getUsername().empty()) - { + if (!u.getUsername().empty()) { sess->getProperties()[serv->getInfos().getPropertyPrefix() + "auth.username"] = u.getUsername(); sess->getProperties()[serv->getInfos().getPropertyPrefix() + "auth.password"] = u.getPassword(); } - return (serv); + return serv; } -shared_ptr <const serviceFactory::registeredService> serviceFactory::getServiceByProtocol(const string& protocol) const -{ +shared_ptr <const serviceFactory::registeredService> serviceFactory::getServiceByProtocol(const string& protocol) const { + const string name(utility::stringUtils::toLower(protocol)); for (std::vector <shared_ptr <registeredService> >::const_iterator it = m_services.begin() ; - it != m_services.end() ; ++it) - { - if ((*it)->getName() == name) + it != m_services.end() ; ++it) { + + if ((*it)->getName() == name) { return (*it); + } } return null; } -size_t serviceFactory::getServiceCount() const -{ - return (m_services.size()); +size_t serviceFactory::getServiceCount() const { + + return m_services.size(); } -shared_ptr <const serviceFactory::registeredService> serviceFactory::getServiceAt(const size_t pos) const -{ - return (m_services[pos]); +shared_ptr <const serviceFactory::registeredService> serviceFactory::getServiceAt(const size_t pos) const { + + return m_services[pos]; } -const std::vector <shared_ptr <const serviceFactory::registeredService> > serviceFactory::getServiceList() const -{ +const std::vector <shared_ptr <const serviceFactory::registeredService> > serviceFactory::getServiceList() const { + std::vector <shared_ptr <const registeredService> > res; for (std::vector <shared_ptr <registeredService> >::const_iterator it = m_services.begin() ; - it != m_services.end() ; ++it) - { + it != m_services.end() ; ++it) { + res.push_back(*it); } @@ -136,8 +143,8 @@ const std::vector <shared_ptr <const serviceFactory::registeredService> > servic } -void serviceFactory::registerService(shared_ptr <registeredService> reg) -{ +void serviceFactory::registerService(const shared_ptr <registeredService>& reg) { + m_services.push_back(reg); } diff --git a/src/vmime/net/serviceFactory.hpp b/src/vmime/net/serviceFactory.hpp index 9295b345..8911e080 100644 --- a/src/vmime/net/serviceFactory.hpp +++ b/src/vmime/net/serviceFactory.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard <[email protected]> +// Copyright (C) 2002 Vincent Richard <[email protected]> // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License as @@ -58,8 +58,8 @@ class session; /** A factory to create 'service' objects for a specified protocol. */ -class VMIME_EXPORT serviceFactory -{ +class VMIME_EXPORT serviceFactory { + private: serviceFactory(); @@ -70,8 +70,8 @@ public: static shared_ptr <serviceFactory> getInstance(); /** Information about a registered service. */ - class registeredService : public object - { + class registeredService : public object { + friend class serviceFactory; protected: @@ -80,9 +80,10 @@ public: public: - virtual shared_ptr <service> create - (shared_ptr <session> sess, - shared_ptr <security::authenticator> auth) const = 0; + virtual shared_ptr <service> create( + const shared_ptr <session>& sess, + const shared_ptr <security::authenticator>& auth + ) const = 0; virtual int getType() const = 0; virtual const string& getName() const = 0; @@ -94,7 +95,7 @@ public: * * @param reg service registration infos */ - void registerService(shared_ptr <registeredService> reg); + void registerService(const shared_ptr <registeredService>& reg); /** Create a new service instance from a protocol name. * @@ -104,10 +105,11 @@ public: * @return a new service instance for the specified protocol, or NULL if no service * is registered for this protocol */ - shared_ptr <service> create - (shared_ptr <session> sess, - const string& protocol, - shared_ptr <security::authenticator> auth = null); + shared_ptr <service> create( + const shared_ptr <session>& sess, + const string& protocol, + const shared_ptr <security::authenticator>& auth = null + ); /** Create a new service instance from a URL. * @@ -118,10 +120,11 @@ public: * @return a new service instance for the specified protocol or NULL if no service * is registered for this protocol */ - shared_ptr <service> create - (shared_ptr <session> sess, - const utility::url& u, - shared_ptr <security::authenticator> auth = null); + shared_ptr <service> create( + const shared_ptr <session>& sess, + const utility::url& u, + const shared_ptr <security::authenticator>& auth = null + ); /** Return information about a registered protocol. * diff --git a/src/vmime/net/serviceInfos.cpp b/src/vmime/net/serviceInfos.cpp index c5d0124a..6efab13f 100644 --- a/src/vmime/net/serviceInfos.cpp +++ b/src/vmime/net/serviceInfos.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard <[email protected]> +// Copyright (C) 2002 Vincent Richard <[email protected]> // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License as @@ -35,31 +35,49 @@ namespace net { // Common properties -const serviceInfos::property serviceInfos::property::SERVER_ADDRESS - ("server.address", serviceInfos::property::TYPE_STRING); - -const serviceInfos::property serviceInfos::property::SERVER_PORT - ("server.port", serviceInfos::property::TYPE_INTEGER); - -const serviceInfos::property serviceInfos::property::SERVER_ROOTPATH - ("server.rootpath", serviceInfos::property::TYPE_STRING); - -const serviceInfos::property serviceInfos::property::AUTH_USERNAME - ("auth.username", serviceInfos::property::TYPE_STRING); - -const serviceInfos::property serviceInfos::property::AUTH_PASSWORD - ("auth.password", serviceInfos::property::TYPE_STRING); - -const serviceInfos::property serviceInfos::property::AUTH_ACCESS_TOKEN - ("auth.accesstoken", serviceInfos::property::TYPE_STRING); +const serviceInfos::property serviceInfos::property::SERVER_ADDRESS( + "server.address", + serviceInfos::property::TYPE_STRING +); + +const serviceInfos::property serviceInfos::property::SERVER_PORT( + "server.port", + serviceInfos::property::TYPE_INTEGER +); + +const serviceInfos::property serviceInfos::property::SERVER_ROOTPATH( + "server.rootpath", + serviceInfos::property::TYPE_STRING +); + +const serviceInfos::property serviceInfos::property::AUTH_USERNAME( + "auth.username", + serviceInfos::property::TYPE_STRING +); + +const serviceInfos::property serviceInfos::property::AUTH_PASSWORD( + "auth.password", + serviceInfos::property::TYPE_STRING +); + +const serviceInfos::property serviceInfos::property::AUTH_ACCESS_TOKEN( + "auth.accesstoken", + serviceInfos::property::TYPE_STRING +); #if VMIME_HAVE_TLS_SUPPORT -const serviceInfos::property serviceInfos::property::CONNECTION_TLS - ("connection.tls", serviceInfos::property::TYPE_BOOLEAN, "false"); +const serviceInfos::property serviceInfos::property::CONNECTION_TLS( + "connection.tls", + serviceInfos::property::TYPE_BOOLEAN, + "false" +); -const serviceInfos::property serviceInfos::property::CONNECTION_TLS_REQUIRED - ("connection.tls.required", serviceInfos::property::TYPE_BOOLEAN, "false"); +const serviceInfos::property serviceInfos::property::CONNECTION_TLS_REQUIRED( + "connection.tls.required", + serviceInfos::property::TYPE_BOOLEAN, + "false" +); #endif // VMIME_HAVE_TLS_SUPPORT @@ -67,29 +85,29 @@ const serviceInfos::property serviceInfos::property::CONNECTION_TLS_REQUIRED // serviceInfos -serviceInfos::serviceInfos() -{ +serviceInfos::serviceInfos() { + } -serviceInfos::serviceInfos(const serviceInfos&) -{ +serviceInfos::serviceInfos(const serviceInfos&) { + } -serviceInfos& serviceInfos::operator=(const serviceInfos&) -{ - return (*this); +serviceInfos& serviceInfos::operator=(const serviceInfos&) { + + return *this; } -serviceInfos::~serviceInfos() -{ +serviceInfos::~serviceInfos() { + } -bool serviceInfos::hasProperty(shared_ptr <session> s, const property& p) const -{ +bool serviceInfos::hasProperty(const shared_ptr <session>& s, const property& p) const { + return s->getProperties().hasProperty(getPropertyPrefix() + p.getName()); } @@ -97,18 +115,26 @@ bool serviceInfos::hasProperty(shared_ptr <session> s, const property& p) const // serviceInfos::property -serviceInfos::property::property - (const string& name, const Types type, - const string& defaultValue, const int flags) - : m_name(name), m_defaultValue(defaultValue), - m_type(type), m_flags(flags) -{ +serviceInfos::property::property( + const string& name, + const Types type, + const string& defaultValue, + const int flags +) + : m_name(name), + m_defaultValue(defaultValue), + m_type(type), + m_flags(flags) { + } -serviceInfos::property::property - (const property& p, const int addFlags, const int removeFlags) -{ +serviceInfos::property::property( + const property& p, + const int addFlags, + const int removeFlags +) { + m_name = p.m_name; m_type = p.m_type; m_defaultValue = p.m_defaultValue; @@ -116,10 +142,13 @@ serviceInfos::property::property } -serviceInfos::property::property - (const property& p, const string& newDefaultValue, - const int addFlags, const int removeFlags) -{ +serviceInfos::property::property( + const property& p, + const string& newDefaultValue, + const int addFlags, + const int removeFlags +) { + m_name = p.m_name; m_type = p.m_type; m_defaultValue = newDefaultValue; @@ -127,38 +156,38 @@ serviceInfos::property::property } -serviceInfos::property& serviceInfos::property::operator=(const property& p) -{ +serviceInfos::property& serviceInfos::property::operator=(const property& p) { + m_name = p.m_name; m_type = p.m_type; m_defaultValue = p.m_defaultValue; m_flags = p.m_flags; - return (*this); + return *this; } -const string& serviceInfos::property::getName() const -{ - return (m_name); +const string& serviceInfos::property::getName() const { + + return m_name; } -const string& serviceInfos::property::getDefaultValue() const -{ - return (m_defaultValue); +const string& serviceInfos::property::getDefaultValue() const { + + return m_defaultValue; } -serviceInfos::property::Types serviceInfos::property::getType() const -{ - return (m_type); +serviceInfos::property::Types serviceInfos::property::getType() const { + + return m_type; } -int serviceInfos::property::getFlags() const -{ - return (m_flags); +int serviceInfos::property::getFlags() const { + + return m_flags; } diff --git a/src/vmime/net/serviceInfos.hpp b/src/vmime/net/serviceInfos.hpp index 5c3909b2..ef7d0f45 100644 --- a/src/vmime/net/serviceInfos.hpp +++ b/src/vmime/net/serviceInfos.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard <[email protected]> +// Copyright (C) 2002 Vincent Richard <[email protected]> // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License as @@ -44,9 +44,8 @@ namespace net { /** Stores information about a messaging service. */ +class VMIME_EXPORT serviceInfos { -class VMIME_EXPORT serviceInfos -{ friend class serviceFactory; protected: @@ -65,8 +64,8 @@ public: /** A service property. */ - class VMIME_EXPORT property - { + class VMIME_EXPORT property { + public: /** The common property 'server.address' which is @@ -114,8 +113,7 @@ public: /** Value types. */ - enum Types - { + enum Types { TYPE_INTEGER, /*< Integer number. */ TYPE_STRING, /*< Character string. */ TYPE_BOOLEAN, /*< Boolean (true or false). */ @@ -125,8 +123,7 @@ public: /** Property flags. */ - enum Flags - { + enum Flags { FLAG_NONE = 0, /*< No flags. */ FLAG_REQUIRED = (1 << 0), /*< The property must be valued. */ FLAG_HIDDEN = (1 << 1), /*< The property should not be shown @@ -143,7 +140,12 @@ public: * @param defaultValue default value * @param flags property attributes */ - property(const string& name, const Types type, const string& defaultValue = "", const int flags = FLAG_DEFAULT); + property( + const string& name, + const Types type, + const string& defaultValue = "", + const int flags = FLAG_DEFAULT + ); /** Construct a new property from an existing property. * @@ -151,7 +153,11 @@ public: * @param addFlags flags to add * @param removeFlags flags to remove */ - property(const property& p, const int addFlags = FLAG_NONE, const int removeFlags = FLAG_NONE); + property( + const property& p, + const int addFlags = FLAG_NONE, + const int removeFlags = FLAG_NONE + ); /** Construct a new property from an existing property. * @@ -160,7 +166,12 @@ public: * @param addFlags flags to add * @param removeFlags flags to remove */ - property(const property& p, const string& newDefaultValue, const int addFlags = FLAG_NONE, const int removeFlags = FLAG_NONE); + property( + const property& p, + const string& newDefaultValue, + const int addFlags = FLAG_NONE, + const int removeFlags = FLAG_NONE + ); property& operator=(const property& p); @@ -221,13 +232,16 @@ public: * @return value of the property */ template <typename TYPE> - const TYPE getPropertyValue(shared_ptr <session> s, const property& p) const - { - if (p.getFlags() & property::FLAG_REQUIRED) + const TYPE getPropertyValue(const shared_ptr <session>& s, const property& p) const { + + if (p.getFlags() & property::FLAG_REQUIRED) { return s->getProperties()[getPropertyPrefix() + p.getName()].template getValue <TYPE>(); + } - return s->getProperties().template getProperty <TYPE>(getPropertyPrefix() + p.getName(), - propertySet::valueFromString <TYPE>(p.getDefaultValue())); + return s->getProperties().template getProperty <TYPE>( + getPropertyPrefix() + p.getName(), + propertySet::valueFromString <TYPE>(p.getDefaultValue()) + ); } /** Helper function to test if the specified property is set in @@ -237,7 +251,7 @@ public: * @param p property to test * @return true if the property is set, false otherwise */ - bool hasProperty(shared_ptr <session> s, const property& p) const; + bool hasProperty(const shared_ptr <session>& s, const property& p) const; }; diff --git a/src/vmime/net/serviceRegistration.inl b/src/vmime/net/serviceRegistration.inl index 2366fe01..93651999 100644 --- a/src/vmime/net/serviceRegistration.inl +++ b/src/vmime/net/serviceRegistration.inl @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard <[email protected]> +// Copyright (C) 2002 Vincent Richard <[email protected]> // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License as @@ -32,35 +32,41 @@ namespace net { template <class S> -class registeredServiceImpl : public serviceFactory::registeredService -{ +class registeredServiceImpl : public serviceFactory::registeredService { + public: - registeredServiceImpl(const string& name, const int type) - : m_type(type), m_name(name), m_servInfos(S::getInfosInstance()) - { + registeredServiceImpl( + const string& name, + const int type + ) + : m_type(type), + m_name(name), + m_servInfos(S::getInfosInstance()) { + } - shared_ptr <service> create - (shared_ptr <session> sess, - shared_ptr <security::authenticator> auth) const - { + shared_ptr <service> create( + const shared_ptr <session>& sess, + const shared_ptr <security::authenticator>& auth + ) const { + return make_shared <S>(sess, auth); } - const serviceInfos& getInfos() const - { - return (m_servInfos); + const serviceInfos& getInfos() const { + + return m_servInfos; } - const string& getName() const - { - return (m_name); + const string& getName() const { + + return m_name; } - int getType() const - { - return (m_type); + int getType() const { + + return m_type; } private: @@ -73,14 +79,15 @@ private: // Basic service registerer template <class S> -class serviceRegisterer -{ +class serviceRegisterer { + public: - serviceRegisterer(const string& protocol, const service::Type type) - { - serviceFactory::getInstance()->registerService - (make_shared <registeredServiceImpl <S> >(protocol, type)); + serviceRegisterer(const string& protocol, const service::Type type) { + + serviceFactory::getInstance()->registerService( + make_shared <registeredServiceImpl <S> >(protocol, type) + ); } }; diff --git a/src/vmime/net/session.cpp b/src/vmime/net/session.cpp index 7e335899..d4b13b47 100644 --- a/src/vmime/net/session.cpp +++ b/src/vmime/net/session.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard <[email protected]> +// Copyright (C) 2002 Vincent Richard <[email protected]> // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License as @@ -38,8 +38,7 @@ namespace vmime { namespace net { -session::session() -{ +session::session() { #if VMIME_HAVE_TLS_SUPPORT m_tlsProps = make_shared <tls::TLSProperties>(); @@ -49,8 +48,7 @@ session::session() session::session(const propertySet& props) - : m_props(props) -{ + : m_props(props) { #if VMIME_HAVE_TLS_SUPPORT m_tlsProps = make_shared <tls::TLSProperties>(); @@ -59,111 +57,123 @@ session::session(const propertySet& props) } -session::~session() -{ +session::~session() { + } // static -shared_ptr <session> session::create() -{ +shared_ptr <session> session::create() { + return shared_ptr <session>(new session()); } // static -shared_ptr <session> session::create(const propertySet& props) -{ +shared_ptr <session> session::create(const propertySet& props) { + return shared_ptr <session>(new session(props)); } -shared_ptr <transport> session::getTransport(shared_ptr <security::authenticator> auth) -{ - return (getTransport(m_props["transport.protocol"], auth)); +shared_ptr <transport> session::getTransport(const shared_ptr <security::authenticator>& auth) { + + return getTransport(m_props["transport.protocol"], auth); } -shared_ptr <transport> session::getTransport - (const string& protocol, shared_ptr <security::authenticator> auth) -{ +shared_ptr <transport> session::getTransport( + const string& protocol, + const shared_ptr <security::authenticator>& auth +) { + shared_ptr <session> sess(dynamicCast <session>(shared_from_this())); shared_ptr <service> sv = serviceFactory::getInstance()->create(sess, protocol, auth); - if (!sv || sv->getType() != service::TYPE_TRANSPORT) + if (!sv || sv->getType() != service::TYPE_TRANSPORT) { return null; + } return dynamicCast <transport>(sv); } -shared_ptr <transport> session::getTransport - (const utility::url& url, shared_ptr <security::authenticator> auth) -{ +shared_ptr <transport> session::getTransport( + const utility::url& url, + const shared_ptr <security::authenticator>& auth +) { + shared_ptr <session> sess(dynamicCast <session>(shared_from_this())); shared_ptr <service> sv = serviceFactory::getInstance()->create(sess, url, auth); - if (!sv || sv->getType() != service::TYPE_TRANSPORT) + if (!sv || sv->getType() != service::TYPE_TRANSPORT) { return null; + } return dynamicCast <transport>(sv); } -shared_ptr <store> session::getStore(shared_ptr <security::authenticator> auth) -{ - return (getStore(m_props["store.protocol"], auth)); +shared_ptr <store> session::getStore(const shared_ptr <security::authenticator>& auth) { + + return getStore(m_props["store.protocol"], auth); } -shared_ptr <store> session::getStore - (const string& protocol, shared_ptr <security::authenticator> auth) -{ +shared_ptr <store> session::getStore( + const string& protocol, + const shared_ptr <security::authenticator>& auth +) { + shared_ptr <session> sess(dynamicCast <session>(shared_from_this())); shared_ptr <service> sv = serviceFactory::getInstance()->create(sess, protocol, auth); - if (!sv || sv->getType() != service::TYPE_STORE) + if (!sv || sv->getType() != service::TYPE_STORE) { return null; + } return dynamicCast <store>(sv); } -shared_ptr <store> session::getStore - (const utility::url& url, shared_ptr <security::authenticator> auth) -{ +shared_ptr <store> session::getStore( + const utility::url& url, + const shared_ptr <security::authenticator>& auth +) { + shared_ptr <session> sess(dynamicCast <session>(shared_from_this())); shared_ptr <service> sv = serviceFactory::getInstance()->create(sess, url, auth); - if (!sv || sv->getType() != service::TYPE_STORE) + if (!sv || sv->getType() != service::TYPE_STORE) { return null; + } return dynamicCast <store>(sv); } -const propertySet& session::getProperties() const -{ - return (m_props); +const propertySet& session::getProperties() const { + + return m_props; } -propertySet& session::getProperties() -{ - return (m_props); +propertySet& session::getProperties() { + + return m_props; } #if VMIME_HAVE_TLS_SUPPORT -void session::setTLSProperties(shared_ptr <tls::TLSProperties> tlsProps) -{ +void session::setTLSProperties(const shared_ptr <tls::TLSProperties>& tlsProps) { + m_tlsProps = make_shared <tls::TLSProperties>(*tlsProps); } -shared_ptr <tls::TLSProperties> session::getTLSProperties() const -{ +shared_ptr <tls::TLSProperties> session::getTLSProperties() const { + return m_tlsProps; } diff --git a/src/vmime/net/session.hpp b/src/vmime/net/session.hpp index 3165e1ce..7ccd0be6 100644 --- a/src/vmime/net/session.hpp +++ b/src/vmime/net/session.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard <[email protected]> +// Copyright (C) 2002 Vincent Richard <[email protected]> // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License as @@ -53,9 +53,8 @@ class transport; /** An object that contains all the information needed * for connection to a service. */ +class VMIME_EXPORT session : public object, public enable_shared_from_this <session> { -class VMIME_EXPORT session : public object, public enable_shared_from_this <session> -{ public: /** Construct a new session. @@ -84,8 +83,9 @@ public: * @return a new transport service, or NULL if no service is registered for this * protocol or is not a transport protocol */ - shared_ptr <transport> getTransport - (shared_ptr <security::authenticator> auth = null); + shared_ptr <transport> getTransport( + const shared_ptr <security::authenticator>& auth = null + ); /** Return a transport service instance for the specified protocol. * @@ -96,9 +96,10 @@ public: * @return a new transport service, or NULL if no service is registered for this * protocol or is not a transport protocol */ - shared_ptr <transport> getTransport - (const string& protocol, - shared_ptr <security::authenticator> auth = null); + shared_ptr <transport> getTransport( + const string& protocol, + const shared_ptr <security::authenticator>& auth = null + ); /** Return a transport service instance for the specified URL. * @@ -109,9 +110,10 @@ public: * @return a new transport service, or NULL if no service is registered for this * protocol or is not a transport protocol */ - shared_ptr <transport> getTransport - (const utility::url& url, - shared_ptr <security::authenticator> auth = null); + shared_ptr <transport> getTransport( + const utility::url& url, + const shared_ptr <security::authenticator>& auth = null + ); /** Return a transport service instance for the protocol specified * in the session properties. @@ -124,7 +126,9 @@ public: * @return a new store service, or NULL if no service is registered for this * protocol or is not a store protocol */ - shared_ptr <store> getStore(shared_ptr <security::authenticator> auth = null); + shared_ptr <store> getStore( + const shared_ptr <security::authenticator>& auth = null + ); /** Return a store service instance for the specified protocol. * @@ -135,9 +139,10 @@ public: * @return a new store service, or NULL if no service is registered for this * protocol or is not a store protocol */ - shared_ptr <store> getStore - (const string& protocol, - shared_ptr <security::authenticator> auth = null); + shared_ptr <store> getStore( + const string& protocol, + const shared_ptr <security::authenticator>& auth = null + ); /** Return a store service instance for the specified URL. * @@ -148,9 +153,10 @@ public: * @return a new store service, or NULL if no service is registered for this * protocol or is not a store protocol */ - shared_ptr <store> getStore - (const utility::url& url, - shared_ptr <security::authenticator> auth = null); + shared_ptr <store> getStore( + const utility::url& url, + const shared_ptr <security::authenticator>& auth = null + ); /** Properties for the session and for the services. */ @@ -166,7 +172,7 @@ public: * * @param tlsProps SSL/TLS properties */ - void setTLSProperties(shared_ptr <tls::TLSProperties> tlsProps); + void setTLSProperties(const shared_ptr <tls::TLSProperties>& tlsProps); /** Get properties for SSL/TLS secured connections in this session. * diff --git a/src/vmime/net/smtp/SMTPChunkingOutputStreamAdapter.cpp b/src/vmime/net/smtp/SMTPChunkingOutputStreamAdapter.cpp index f6ecc54d..3b242d1b 100644 --- a/src/vmime/net/smtp/SMTPChunkingOutputStreamAdapter.cpp +++ b/src/vmime/net/smtp/SMTPChunkingOutputStreamAdapter.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard <[email protected]> +// Copyright (C) 2002 Vincent Richard <[email protected]> // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License as @@ -40,21 +40,31 @@ namespace net { namespace smtp { -SMTPChunkingOutputStreamAdapter::SMTPChunkingOutputStreamAdapter - (shared_ptr <SMTPConnection> conn, const size_t size, utility::progressListener* progress) - : m_connection(conn), m_bufferSize(0), m_chunkCount(0), - m_totalSize(size), m_totalSent(0), m_progress(progress) -{ - if (progress) +SMTPChunkingOutputStreamAdapter::SMTPChunkingOutputStreamAdapter( + const shared_ptr <SMTPConnection>& conn, + const size_t size, + utility::progressListener* progress +) + : m_connection(conn), + m_bufferSize(0), + m_chunkCount(0), + m_totalSize(size), + m_totalSent(0), + m_progress(progress) { + + if (progress) { progress->start(size); + } } -void SMTPChunkingOutputStreamAdapter::sendChunk - (const byte_t* const data, const size_t count, const bool last) -{ - if (count == 0 && !last) - { +void SMTPChunkingOutputStreamAdapter::sendChunk( + const byte_t* const data, + const size_t count, + const bool last +) { + + if (count == 0 && !last) { // Nothing to send return; } @@ -65,45 +75,45 @@ void SMTPChunkingOutputStreamAdapter::sendChunk ++m_chunkCount; - if (m_progress) - { + if (m_progress) { + m_totalSent += count; m_totalSize = std::max(m_totalSize, m_totalSent); m_progress->progress(m_totalSent, m_totalSize); } - if (m_connection->getTracer()) + if (m_connection->getTracer()) { m_connection->getTracer()->traceSendBytes(count); + } // If PIPELINING is not supported, read one response for this BDAT command - if (!m_connection->hasExtension("PIPELINING")) - { + if (!m_connection->hasExtension("PIPELINING")) { + shared_ptr <SMTPResponse> resp = m_connection->readResponse(); - if (resp->getCode() != 250) - { + if (resp->getCode() != 250) { m_connection->getTransport()->disconnect(); throw exceptions::command_error("BDAT", resp->getText()); } - } + // If PIPELINING is supported, read one response for each chunk (ie. number // of BDAT commands issued) after the last chunk has been sent - else if (last) - { + } else if (last) { + bool invalidReply = false; shared_ptr <SMTPResponse> resp; - for (unsigned int i = 0 ; i < m_chunkCount ; ++i) - { + for (unsigned int i = 0 ; i < m_chunkCount ; ++i) { + resp = m_connection->readResponse(); - if (resp->getCode() != 250) + if (resp->getCode() != 250) { invalidReply = true; + } } - if (invalidReply) - { + if (invalidReply) { m_connection->getTransport()->disconnect(); throw exceptions::command_error("BDAT", resp->getText()); } @@ -111,14 +121,16 @@ void SMTPChunkingOutputStreamAdapter::sendChunk } -void SMTPChunkingOutputStreamAdapter::writeImpl - (const byte_t* const data, const size_t count) -{ +void SMTPChunkingOutputStreamAdapter::writeImpl( + const byte_t* const data, + const size_t count +) { + const byte_t* curData = data; size_t curCount = count; - while (curCount != 0) - { + while (curCount != 0) { + // Fill the buffer const size_t remaining = sizeof(m_buffer) - m_bufferSize; const size_t bytesToCopy = std::min(remaining, curCount); @@ -130,8 +142,8 @@ void SMTPChunkingOutputStreamAdapter::writeImpl curCount -= bytesToCopy; // If the buffer is full, send this chunk - if (m_bufferSize >= sizeof(m_buffer)) - { + if (m_bufferSize >= sizeof(m_buffer)) { + sendChunk(m_buffer, m_bufferSize, /* last */ false); m_bufferSize = 0; } @@ -139,21 +151,23 @@ void SMTPChunkingOutputStreamAdapter::writeImpl } -void SMTPChunkingOutputStreamAdapter::flush() -{ +void SMTPChunkingOutputStreamAdapter::flush() { + sendChunk(m_buffer, m_bufferSize, /* last */ true); m_bufferSize = 0; - if (m_progress) + if (m_progress) { m_progress->stop(m_totalSize); + } - if (m_connection->getTracer()) + if (m_connection->getTracer()) { m_connection->getTracer()->traceSendBytes(m_bufferSize); + } } -size_t SMTPChunkingOutputStreamAdapter::getBlockSize() -{ +size_t SMTPChunkingOutputStreamAdapter::getBlockSize() { + return sizeof(m_buffer); } diff --git a/src/vmime/net/smtp/SMTPChunkingOutputStreamAdapter.hpp b/src/vmime/net/smtp/SMTPChunkingOutputStreamAdapter.hpp index 56d72fb1..4ef466a2 100644 --- a/src/vmime/net/smtp/SMTPChunkingOutputStreamAdapter.hpp +++ b/src/vmime/net/smtp/SMTPChunkingOutputStreamAdapter.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard <[email protected]> +// Copyright (C) 2002 Vincent Richard <[email protected]> // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License as @@ -45,12 +45,15 @@ class SMTPConnection; /** An output stream adapter used with ESMTP CHUNKING extension. */ -class VMIME_EXPORT SMTPChunkingOutputStreamAdapter : public utility::outputStream -{ +class VMIME_EXPORT SMTPChunkingOutputStreamAdapter : public utility::outputStream { + public: - SMTPChunkingOutputStreamAdapter(shared_ptr <SMTPConnection> conn, - const size_t size, utility::progressListener* progress); + SMTPChunkingOutputStreamAdapter( + const shared_ptr <SMTPConnection>& conn, + const size_t size, + utility::progressListener* progress + ); void flush(); diff --git a/src/vmime/net/smtp/SMTPCommand.cpp b/src/vmime/net/smtp/SMTPCommand.cpp index 27c8ec1b..8581a994 100644 --- a/src/vmime/net/smtp/SMTPCommand.cpp +++ b/src/vmime/net/smtp/SMTPCommand.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard <[email protected]> +// Copyright (C) 2002 Vincent Richard <[email protected]> // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License as @@ -42,14 +42,15 @@ namespace smtp { SMTPCommand::SMTPCommand(const string& text, const string& traceText) - : m_text(text), m_traceText(traceText) + : m_text(text), + m_traceText(traceText) { } // static -shared_ptr <SMTPCommand> SMTPCommand::EHLO(const string& hostname) -{ +shared_ptr <SMTPCommand> SMTPCommand::EHLO(const string& hostname) { + std::ostringstream cmd; cmd.imbue(std::locale::classic()); cmd << "EHLO " << hostname; @@ -59,8 +60,8 @@ shared_ptr <SMTPCommand> SMTPCommand::EHLO(const string& hostname) // static -shared_ptr <SMTPCommand> SMTPCommand::HELO(const string& hostname) -{ +shared_ptr <SMTPCommand> SMTPCommand::HELO(const string& hostname) { + std::ostringstream cmd; cmd.imbue(std::locale::classic()); cmd << "HELO " << hostname; @@ -70,8 +71,8 @@ shared_ptr <SMTPCommand> SMTPCommand::HELO(const string& hostname) // static -shared_ptr <SMTPCommand> SMTPCommand::AUTH(const string& mechName) -{ +shared_ptr <SMTPCommand> SMTPCommand::AUTH(const string& mechName) { + std::ostringstream cmd; cmd.imbue(std::locale::classic()); cmd << "AUTH " << mechName; @@ -81,8 +82,8 @@ shared_ptr <SMTPCommand> SMTPCommand::AUTH(const string& mechName) // static -shared_ptr <SMTPCommand> SMTPCommand::AUTH(const string& mechName, const std::string& initialResponse) -{ +shared_ptr <SMTPCommand> SMTPCommand::AUTH(const string& mechName, const std::string& initialResponse) { + std::ostringstream cmd; cmd.imbue(std::locale::classic()); cmd << "AUTH " << mechName << " " << initialResponse; @@ -92,61 +93,63 @@ shared_ptr <SMTPCommand> SMTPCommand::AUTH(const string& mechName, const std::st // static -shared_ptr <SMTPCommand> SMTPCommand::STARTTLS() -{ +shared_ptr <SMTPCommand> SMTPCommand::STARTTLS() { + return createCommand("STARTTLS"); } // static -shared_ptr <SMTPCommand> SMTPCommand::MAIL(const mailbox& mbox, const bool utf8) -{ +shared_ptr <SMTPCommand> SMTPCommand::MAIL(const mailbox& mbox, const bool utf8) { + return MAIL(mbox, utf8, 0); } // static -shared_ptr <SMTPCommand> SMTPCommand::MAIL(const mailbox& mbox, const bool utf8, const size_t size) -{ +shared_ptr <SMTPCommand> SMTPCommand::MAIL(const mailbox& mbox, const bool utf8, const size_t size) { + std::ostringstream cmd; cmd.imbue(std::locale::classic()); cmd << "MAIL FROM:<"; - if (utf8) - { + if (utf8) { + cmd << mbox.getEmail().toText().getConvertedText(vmime::charsets::UTF_8); - } - else - { + + } else { + vmime::utility::outputStreamAdapter cmd2(cmd); mbox.getEmail().generate(cmd2); } cmd << ">"; - if (utf8) + if (utf8) { cmd << " SMTPUTF8"; + } - if (size != 0) + if (size != 0) { cmd << " SIZE=" << size; + } return createCommand(cmd.str()); } // static -shared_ptr <SMTPCommand> SMTPCommand::RCPT(const mailbox& mbox, const bool utf8) -{ +shared_ptr <SMTPCommand> SMTPCommand::RCPT(const mailbox& mbox, const bool utf8) { + std::ostringstream cmd; cmd.imbue(std::locale::classic()); cmd << "RCPT TO:<"; - if (utf8) - { + if (utf8) { + cmd << mbox.getEmail().toText().getConvertedText(vmime::charsets::UTF_8); - } - else - { + + } else { + vmime::utility::outputStreamAdapter cmd2(cmd); mbox.getEmail().generate(cmd2); } @@ -158,75 +161,78 @@ shared_ptr <SMTPCommand> SMTPCommand::RCPT(const mailbox& mbox, const bool utf8) // static -shared_ptr <SMTPCommand> SMTPCommand::RSET() -{ +shared_ptr <SMTPCommand> SMTPCommand::RSET() { + return createCommand("RSET"); } // static -shared_ptr <SMTPCommand> SMTPCommand::DATA() -{ +shared_ptr <SMTPCommand> SMTPCommand::DATA() { + return createCommand("DATA"); } // static -shared_ptr <SMTPCommand> SMTPCommand::BDAT(const size_t chunkSize, const bool last) -{ +shared_ptr <SMTPCommand> SMTPCommand::BDAT(const size_t chunkSize, const bool last) { + std::ostringstream cmd; cmd.imbue(std::locale::classic()); cmd << "BDAT " << chunkSize; - if (last) + if (last) { cmd << " LAST"; + } return createCommand(cmd.str()); } // static -shared_ptr <SMTPCommand> SMTPCommand::NOOP() -{ +shared_ptr <SMTPCommand> SMTPCommand::NOOP() { + return createCommand("NOOP"); } // static -shared_ptr <SMTPCommand> SMTPCommand::QUIT() -{ +shared_ptr <SMTPCommand> SMTPCommand::QUIT() { + return createCommand("QUIT"); } // static -shared_ptr <SMTPCommand> SMTPCommand::createCommand(const string& text, const string& traceText) -{ - if (traceText.empty()) +shared_ptr <SMTPCommand> SMTPCommand::createCommand(const string& text, const string& traceText) { + + if (traceText.empty()) { return shared_ptr <SMTPCommand>(new SMTPCommand(text, text)); - else + } else { return shared_ptr <SMTPCommand>(new SMTPCommand(text, traceText)); + } } -const string SMTPCommand::getText() const -{ +const string SMTPCommand::getText() const { + return m_text; } -const string SMTPCommand::getTraceText() const -{ +const string SMTPCommand::getTraceText() const { + return m_traceText; } -void SMTPCommand::writeToSocket(shared_ptr <socket> sok, shared_ptr <tracer> tr) -{ +void SMTPCommand::writeToSocket(const shared_ptr <socket>& sok, shared_ptr <tracer> tr) { + sok->send(m_text + "\r\n"); - if (tr) + if (tr) { tr->traceSend(m_traceText); + } } diff --git a/src/vmime/net/smtp/SMTPCommand.hpp b/src/vmime/net/smtp/SMTPCommand.hpp index 7c00d156..137993c4 100644 --- a/src/vmime/net/smtp/SMTPCommand.hpp +++ b/src/vmime/net/smtp/SMTPCommand.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard <[email protected]> +// Copyright (C) 2002 Vincent Richard <[email protected]> // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License as @@ -54,8 +54,8 @@ namespace smtp { /** A SMTP command, as sent to server. */ -class VMIME_EXPORT SMTPCommand : public object -{ +class VMIME_EXPORT SMTPCommand : public object { + public: static shared_ptr <SMTPCommand> HELO(const string& hostname); @@ -84,7 +84,7 @@ public: * @param sok socket to which the command will be written * @param tr tracer */ - virtual void writeToSocket(shared_ptr <socket> sok, shared_ptr <tracer> tr); + virtual void writeToSocket(const shared_ptr <socket>& sok, shared_ptr <tracer> tr); /** Returns the full text of the command, including command name * and parameters (if any). diff --git a/src/vmime/net/smtp/SMTPCommandSet.cpp b/src/vmime/net/smtp/SMTPCommandSet.cpp index 85f58fed..eab7086a 100644 --- a/src/vmime/net/smtp/SMTPCommandSet.cpp +++ b/src/vmime/net/smtp/SMTPCommandSet.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard <[email protected]> +// Copyright (C) 2002 Vincent Richard <[email protected]> // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License as @@ -42,23 +42,24 @@ namespace smtp { SMTPCommandSet::SMTPCommandSet(const bool pipeline) - : SMTPCommand("", ""), m_pipeline(pipeline), - m_started(false), m_lastCommandSent() -{ + : SMTPCommand("", ""), + m_pipeline(pipeline), + m_started(false), + m_lastCommandSent() { + } // static -shared_ptr <SMTPCommandSet> SMTPCommandSet::create(const bool pipeline) -{ +shared_ptr <SMTPCommandSet> SMTPCommandSet::create(const bool pipeline) { + return shared_ptr <SMTPCommandSet>(new SMTPCommandSet(pipeline)); } -void SMTPCommandSet::addCommand(shared_ptr <SMTPCommand> cmd) -{ - if (m_started) - { +void SMTPCommandSet::addCommand(const shared_ptr <SMTPCommand>& cmd) { + + if (m_started) { throw std::runtime_error("Could not add command to pipeline: " "one or more commands have already been sent to the server."); } @@ -67,34 +68,34 @@ void SMTPCommandSet::addCommand(shared_ptr <SMTPCommand> cmd) } -void SMTPCommandSet::writeToSocket(shared_ptr <socket> sok, shared_ptr <tracer> tr) -{ - if (m_pipeline) - { - if (!m_started) - { +void SMTPCommandSet::writeToSocket(const shared_ptr <socket>& sok, const shared_ptr <tracer>& tr) { + + if (m_pipeline) { + + if (!m_started) { + // Send all commands at once for (std::list <shared_ptr <SMTPCommand> >::const_iterator it = m_commands.begin() ; - it != m_commands.end() ; ++it) - { + it != m_commands.end() ; ++it) { + shared_ptr <SMTPCommand> cmd = *it; cmd->writeToSocket(sok, tr); } } - if (!m_commands.empty()) - { + if (!m_commands.empty()) { + // Advance the pointer to last command sent shared_ptr <SMTPCommand> cmd = m_commands.front(); m_commands.pop_front(); m_lastCommandSent = cmd; } - } - else - { - if (!m_commands.empty()) - { + + } else { + + if (!m_commands.empty()) { + // Send only one command shared_ptr <SMTPCommand> cmd = m_commands.front(); m_commands.pop_front(); @@ -109,14 +110,14 @@ void SMTPCommandSet::writeToSocket(shared_ptr <socket> sok, shared_ptr <tracer> } -const string SMTPCommandSet::getText() const -{ +const string SMTPCommandSet::getText() const { + std::ostringstream cmd; cmd.imbue(std::locale::classic()); for (std::list <shared_ptr <SMTPCommand> >::const_iterator it = m_commands.begin() ; - it != m_commands.end() ; ++it) - { + it != m_commands.end() ; ++it) { + cmd << (*it)->getText() << "\r\n"; } @@ -124,14 +125,14 @@ const string SMTPCommandSet::getText() const } -const string SMTPCommandSet::getTraceText() const -{ +const string SMTPCommandSet::getTraceText() const { + std::ostringstream cmd; cmd.imbue(std::locale::classic()); for (std::list <shared_ptr <SMTPCommand> >::const_iterator it = m_commands.begin() ; - it != m_commands.end() ; ++it) - { + it != m_commands.end() ; ++it) { + cmd << (*it)->getTraceText() << "\r\n"; } @@ -139,14 +140,14 @@ const string SMTPCommandSet::getTraceText() const } -bool SMTPCommandSet::isFinished() const -{ +bool SMTPCommandSet::isFinished() const { + return (m_pipeline && m_started) || (m_commands.size() == 0 && m_started); } -shared_ptr <SMTPCommand> SMTPCommandSet::getLastCommandSent() const -{ +shared_ptr <SMTPCommand> SMTPCommandSet::getLastCommandSent() const { + return m_lastCommandSent; } diff --git a/src/vmime/net/smtp/SMTPCommandSet.hpp b/src/vmime/net/smtp/SMTPCommandSet.hpp index 83c7fe46..2fd977c9 100644 --- a/src/vmime/net/smtp/SMTPCommandSet.hpp +++ b/src/vmime/net/smtp/SMTPCommandSet.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard <[email protected]> +// Copyright (C) 2002 Vincent Richard <[email protected]> // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License as @@ -44,8 +44,8 @@ namespace smtp { /** A set of SMTP commands, which may be sent all at once * to the server if pipelining is supported. */ -class VMIME_EXPORT SMTPCommandSet : public SMTPCommand -{ +class VMIME_EXPORT SMTPCommandSet : public SMTPCommand { + public: /** Creates a new set of SMTP commands. @@ -61,7 +61,7 @@ public: * * @param cmd command to add */ - void addCommand(shared_ptr <SMTPCommand> cmd); + void addCommand(const shared_ptr <SMTPCommand>& cmd); /** Tests whether all commands have been sent. * @@ -78,7 +78,7 @@ public: shared_ptr <SMTPCommand> getLastCommandSent() const; - void writeToSocket(shared_ptr <socket> sok, shared_ptr <tracer> tr); + void writeToSocket(const shared_ptr <socket>& sok, const shared_ptr <tracer>& tr); const string getText() const; const string getTraceText() const; diff --git a/src/vmime/net/smtp/SMTPConnection.cpp b/src/vmime/net/smtp/SMTPConnection.cpp index 8709efe4..7680fecf 100644 --- a/src/vmime/net/smtp/SMTPConnection.cpp +++ b/src/vmime/net/smtp/SMTPConnection.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard <[email protected]> +// Copyright (C) 2002 Vincent Richard <[email protected]> // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License as @@ -67,37 +67,48 @@ namespace smtp { -SMTPConnection::SMTPConnection(shared_ptr <SMTPTransport> transport, shared_ptr <security::authenticator> auth) - : m_transport(transport), m_auth(auth), m_socket(null), m_timeoutHandler(null), - m_authenticated(false), m_secured(false), m_extendedSMTP(false) -{ +SMTPConnection::SMTPConnection( + const shared_ptr <SMTPTransport>& transport, + const shared_ptr <security::authenticator>& auth +) + : m_transport(transport), + m_auth(auth), + m_socket(null), + m_timeoutHandler(null), + m_authenticated(false), + m_secured(false), + m_extendedSMTP(false) { + static int connectionId = 0; - if (transport->getTracerFactory()) + if (transport->getTracerFactory()) { m_tracer = transport->getTracerFactory()->create(transport, ++connectionId); + } } -SMTPConnection::~SMTPConnection() -{ - try - { - if (isConnected()) +SMTPConnection::~SMTPConnection() { + + try { + + if (isConnected()) { disconnect(); - else if (m_socket) + } else if (m_socket) { internalDisconnect(); - } - catch (...) - { + } + + } catch (...) { + // Don't throw in destructor } } -void SMTPConnection::connect() -{ - if (isConnected()) +void SMTPConnection::connect() { + + if (isConnected()) { throw exceptions::already_connected(); + } const string address = GET_PROPERTY(string, PROPERTY_SERVER_ADDRESS); const port_t port = GET_PROPERTY(port_t, PROPERTY_SERVER_PORT); @@ -105,29 +116,30 @@ void SMTPConnection::connect() shared_ptr <SMTPTransport> transport = m_transport.lock(); // Create the time-out handler - if (transport->getTimeoutHandlerFactory()) + if (transport->getTimeoutHandlerFactory()) { m_timeoutHandler = transport->getTimeoutHandlerFactory()->create(); + } // Create and connect the socket m_socket = transport->getSocketFactory()->create(m_timeoutHandler); m_socket->setTracer(m_tracer); #if VMIME_HAVE_TLS_SUPPORT - if (transport->isSMTPS()) // dedicated port/SMTPS - { - shared_ptr <tls::TLSSession> tlsSession = tls::TLSSession::create - (transport->getCertificateVerifier(), - transport->getSession()->getTLSProperties()); + if (transport->isSMTPS()) { // dedicated port/SMTPS - shared_ptr <tls::TLSSocket> tlsSocket = - tlsSession->getSocket(m_socket); + shared_ptr <tls::TLSSession> tlsSession = tls::TLSSession::create( + transport->getCertificateVerifier(), + transport->getSession()->getTLSProperties() + ); + + shared_ptr <tls::TLSSocket> tlsSocket = tlsSession->getSocket(m_socket); m_socket = tlsSocket; m_secured = true; m_cntInfos = make_shared <tls::TLSSecuredConnectionInfos>(address, port, tlsSession, tlsSocket); - } - else + + } else #endif // VMIME_HAVE_TLS_SUPPORT { m_cntInfos = make_shared <defaultConnectionInfos>(address, port); @@ -142,8 +154,7 @@ void SMTPConnection::connect() shared_ptr <SMTPResponse> resp; - if ((resp = readResponse())->getCode() != 220) - { + if ((resp = readResponse())->getCode() != 220) { internalDisconnect(); throw exceptions::connection_greeting_error(resp->getText()); } @@ -158,27 +169,24 @@ void SMTPConnection::connect() const bool tlsRequired = HAS_PROPERTY(PROPERTY_CONNECTION_TLS_REQUIRED) && GET_PROPERTY(bool, PROPERTY_CONNECTION_TLS_REQUIRED); - if (!transport->isSMTPS() && tls) // only if not SMTPS - { - try - { + if (!transport->isSMTPS() && tls) { // only if not SMTPS + + try { + startTLS(); - } + // Non-fatal error - catch (exceptions::command_error&) - { - if (tlsRequired) - { + } catch (exceptions::command_error&) { + + if (tlsRequired) { throw; - } - else - { + } else { // TLS is not required, so don't bother } - } + // Fatal error - catch (...) - { + } catch (...) { + throw; } @@ -188,15 +196,16 @@ void SMTPConnection::connect() #endif // VMIME_HAVE_TLS_SUPPORT // Authentication - if (GET_PROPERTY(bool, PROPERTY_OPTIONS_NEEDAUTH)) + if (GET_PROPERTY(bool, PROPERTY_OPTIONS_NEEDAUTH)) { authenticate(); - else + } else { m_authenticated = true; + } } -void SMTPConnection::helo() -{ +void SMTPConnection::helo() { + // First, try Extended SMTP (ESMTP) // // eg: C: EHLO thismachine.ourdomain.com @@ -209,8 +218,8 @@ void SMTPConnection::helo() shared_ptr <SMTPResponse> resp; - if ((resp = readResponse())->getCode() != 250) - { + if ((resp = readResponse())->getCode() != 250) { + // Next, try "Basic" SMTP // // eg: C: HELO thismachine.ourdomain.com @@ -218,24 +227,23 @@ void SMTPConnection::helo() sendRequest(SMTPCommand::HELO(platform::getHandler()->getHostName())); - if ((resp = readResponse())->getCode() != 250) - { + if ((resp = readResponse())->getCode() != 250) { internalDisconnect(); throw exceptions::connection_greeting_error(resp->getLastLine().getText()); } m_extendedSMTP = false; m_extensions.clear(); - } - else - { + + } else { + m_extendedSMTP = true; m_extensions.clear(); // Get supported extensions from SMTP response // One extension per line, format is: EXT PARAM1 PARAM2... - for (size_t i = 1, n = resp->getLineCount() ; i < n ; ++i) - { + for (size_t i = 1, n = resp->getLineCount() ; i < n ; ++i) { + const string line = resp->getLineAt(i).getText(); std::istringstream iss(line); @@ -248,14 +256,15 @@ void SMTPConnection::helo() string param; // Special case: some servers send "AUTH=MECH [MECH MECH...]" - if (ext.length() >= 5 && utility::stringUtils::toUpper(ext.substr(0, 5)) == "AUTH=") - { + if (ext.length() >= 5 && utility::stringUtils::toUpper(ext.substr(0, 5)) == "AUTH=") { + params.push_back(utility::stringUtils::toUpper(ext.substr(5))); ext = "AUTH"; } - while (iss >> param) + while (iss >> param) { params.push_back(utility::stringUtils::toUpper(param)); + } m_extensions[ext] = params; } @@ -263,30 +272,32 @@ void SMTPConnection::helo() } -bool SMTPConnection::hasExtension - (const std::string& extName, std::vector <string>* params) const -{ +bool SMTPConnection::hasExtension( + const std::string& extName, + std::vector <string>* params +) const { + std::map <string, std::vector <string> >::const_iterator it = m_extensions.find(extName); - if (it != m_extensions.end()) - { - if (params) + if (it != m_extensions.end()) { + + if (params) { *params = (*it).second; + } return true; - } - else - { + + } else { + return false; } } -void SMTPConnection::authenticate() -{ - if (!m_extendedSMTP) - { +void SMTPConnection::authenticate() { + + if (!m_extendedSMTP) { internalDisconnect(); throw exceptions::command_error("AUTH", "ESMTP not supported."); } @@ -295,17 +306,17 @@ void SMTPConnection::authenticate() #if VMIME_HAVE_SASL_SUPPORT // Try SASL authentication - if (GET_PROPERTY(bool, PROPERTY_OPTIONS_SASL)) - { - try - { + if (GET_PROPERTY(bool, PROPERTY_OPTIONS_SASL)) { + + try { + authenticateSASL(); m_authenticated = true; return; - } - catch (exception&) - { + + } catch (exception&) { + internalDisconnect(); throw; } @@ -313,30 +324,36 @@ void SMTPConnection::authenticate() #else // no SASL // allow AUTH PLAIN over TLS - it is a popular and simple mechanism - if (m_secured) - { + if (m_secured) { + std::vector <string> authMechs; hasExtension("AUTH", &authMechs); - if (authMechs.empty()) + if (authMechs.empty()) { throw exceptions::authentication_error("No AUTH mechanism available."); + } const string plain("PLAIN"); - if (std::find(authMechs.begin(), authMechs.end(), plain) != authMechs.end()) - { + + if (std::find(authMechs.begin(), authMechs.end(), plain) != authMechs.end()) { + const string username = getAuthenticator()->getUsername(); const string password = getAuthenticator()->getPassword(); const string authToken = username + '\0' + username + '\0' + password; + auto encoder = new vmime::utility::encoder::b64Encoder(); utility::inputStreamStringAdapter in(authToken); string authTokenBase64; utility::outputStreamStringAdapter out(authTokenBase64); encoder->encode(in, out); + sendRequest(SMTPCommand::AUTH(plain, authTokenBase64)); + shared_ptr <SMTPResponse> response = readResponse(); + const int code = response ? response->getCode() : -1; - if (code == 235) - { + + if (code == 235) { m_authenticated = true; return; } @@ -353,56 +370,61 @@ void SMTPConnection::authenticate() #if VMIME_HAVE_SASL_SUPPORT -void SMTPConnection::authenticateSASL() -{ - if (!dynamicCast <security::sasl::SASLAuthenticator>(getAuthenticator())) +void SMTPConnection::authenticateSASL() { + + if (!dynamicCast <security::sasl::SASLAuthenticator>(getAuthenticator())) { throw exceptions::authentication_error("No SASL authenticator available."); + } // Obtain SASL mechanisms supported by server from ESMTP extensions std::vector <string> saslMechs; hasExtension("AUTH", &saslMechs); - if (saslMechs.empty()) + if (saslMechs.empty()) { throw exceptions::authentication_error("No SASL mechanism available."); + } std::vector <shared_ptr <security::sasl::SASLMechanism> > mechList; shared_ptr <security::sasl::SASLContext> saslContext = security::sasl::SASLContext::create(); - for (unsigned int i = 0 ; i < saslMechs.size() ; ++i) - { - try - { + for (unsigned int i = 0 ; i < saslMechs.size() ; ++i) { + + try { + mechList.push_back (saslContext->createMechanism(saslMechs[i])); - } - catch (exceptions::no_such_mechanism&) - { + + } catch (exceptions::no_such_mechanism&) { + // Ignore mechanism } } - if (mechList.empty()) + if (mechList.empty()) { throw exceptions::authentication_error("No SASL mechanism available."); + } // Try to suggest a mechanism among all those supported shared_ptr <security::sasl::SASLMechanism> suggestedMech = saslContext->suggestMechanism(mechList); - if (!suggestedMech) + if (!suggestedMech) { throw exceptions::authentication_error("Unable to suggest SASL mechanism."); + } // Allow application to choose which mechanisms to use mechList = dynamicCast <security::sasl::SASLAuthenticator>(getAuthenticator())-> getAcceptableMechanisms(mechList, suggestedMech); - if (mechList.empty()) + if (mechList.empty()) { throw exceptions::authentication_error("No SASL mechanism available."); + } // Try each mechanism in the list in turn - for (unsigned int i = 0 ; i < mechList.size() ; ++i) - { + for (unsigned int i = 0 ; i < mechList.size() ; ++i) { + shared_ptr <security::sasl::SASLMechanism> mech = mechList[i]; shared_ptr <security::sasl::SASLSession> saslSession = @@ -410,8 +432,8 @@ void SMTPConnection::authenticateSASL() saslSession->init(); - if (saslSession->getMechanism()->hasInitialResponse()) - { + if (saslSession->getMechanism()->hasInitialResponse()) { + byte_t* initialResp = 0; size_t initialRespLen = 0; @@ -420,100 +442,103 @@ void SMTPConnection::authenticateSASL() string encodedInitialResp(saslContext->encodeB64(initialResp, initialRespLen)); delete [] initialResp; - if (encodedInitialResp.empty()) + if (encodedInitialResp.empty()) { sendRequest(SMTPCommand::AUTH(mech->getName(), "=")); - else + } else { sendRequest(SMTPCommand::AUTH(mech->getName(), encodedInitialResp)); - } - else - { + } + + } else { + sendRequest(SMTPCommand::AUTH(mech->getName())); } - for (bool cont = true ; cont ; ) - { + for (bool cont = true ; cont ; ) { + shared_ptr <SMTPResponse> response = readResponse(); - switch (response->getCode()) - { - case 235: - { - m_socket = saslSession->getSecuredSocket(m_socket); - return; - } - case 334: - { - byte_t* challenge = 0; - size_t challengeLen = 0; + switch (response->getCode()) { - byte_t* resp = 0; - size_t respLen = 0; + case 235: { - try - { - // Extract challenge - saslContext->decodeB64(response->getText(), &challenge, &challengeLen); + m_socket = saslSession->getSecuredSocket(m_socket); + return; + } + case 334: { - // Prepare response - saslSession->evaluateChallenge - (challenge, challengeLen, &resp, &respLen); + byte_t* challenge = 0; + size_t challengeLen = 0; - // Send response - const string respB64 = saslContext->encodeB64(resp, respLen) + "\r\n"; - m_socket->sendRaw(utility::stringUtils::bytesFromString(respB64), respB64.length()); + byte_t* resp = 0; + size_t respLen = 0; - if (m_tracer) - m_tracer->traceSendBytes(respB64.length() - 2, "SASL exchange"); - } - catch (exceptions::sasl_exception& e) - { - if (challenge) - { - delete [] challenge; - challenge = NULL; - } + try { - if (resp) - { - delete [] resp; - resp = NULL; - } + // Extract challenge + saslContext->decodeB64(response->getText(), &challenge, &challengeLen); - // Cancel SASL exchange - m_socket->send("*\r\n"); + // Prepare response + saslSession->evaluateChallenge(challenge, challengeLen, &resp, &respLen); - if (m_tracer) - m_tracer->traceSend("*"); - } - catch (...) - { - if (challenge) - delete [] challenge; + // Send response + const string respB64 = saslContext->encodeB64(resp, respLen) + "\r\n"; + m_socket->sendRaw(utility::stringUtils::bytesFromString(respB64), respB64.length()); - if (resp) - delete [] resp; + if (m_tracer) { + m_tracer->traceSendBytes(respB64.length() - 2, "SASL exchange"); + } - throw; - } + } catch (exceptions::sasl_exception& e) { - if (challenge) - delete [] challenge; + if (challenge) { + delete [] challenge; + challenge = NULL; + } - if (resp) - delete [] resp; + if (resp) { + delete [] resp; + resp = NULL; + } - break; - } - default: + // Cancel SASL exchange + m_socket->send("*\r\n"); + + if (m_tracer) { + m_tracer->traceSend("*"); + } + + } catch (...) { + + if (challenge) { + delete [] challenge; + } + + if (resp) { + delete [] resp; + } + + throw; + } + + if (challenge) { + delete [] challenge; + } + + if (resp) { + delete [] resp; + } - cont = false; - break; + break; + } + default: + + cont = false; + break; } } } - throw exceptions::authentication_error - ("Could not authenticate using SASL: all mechanisms failed."); + throw exceptions::authentication_error("Could not authenticate using SASL: all mechanisms failed."); } #endif // VMIME_HAVE_SASL_SUPPORT @@ -521,42 +546,44 @@ void SMTPConnection::authenticateSASL() #if VMIME_HAVE_TLS_SUPPORT -void SMTPConnection::startTLS() -{ - try - { +void SMTPConnection::startTLS() { + + try { + sendRequest(SMTPCommand::STARTTLS()); shared_ptr <SMTPResponse> resp = readResponse(); - if (resp->getCode() != 220) - { - throw SMTPCommandError("STARTTLS", resp->getText(), - resp->getCode(), resp->getEnhancedCode()); + if (resp->getCode() != 220) { + + throw SMTPCommandError( + "STARTTLS", resp->getText(), resp->getCode(), resp->getEnhancedCode() + ); } - shared_ptr <tls::TLSSession> tlsSession = tls::TLSSession::create - (getTransport()->getCertificateVerifier(), - getTransport()->getSession()->getTLSProperties()); + shared_ptr <tls::TLSSession> tlsSession = tls::TLSSession::create( + getTransport()->getCertificateVerifier(), + getTransport()->getSession()->getTLSProperties() + ); - shared_ptr <tls::TLSSocket> tlsSocket = - tlsSession->getSocket(m_socket); + shared_ptr <tls::TLSSocket> tlsSocket = tlsSession->getSocket(m_socket); tlsSocket->handshake(); m_socket = tlsSocket; m_secured = true; - m_cntInfos = make_shared <tls::TLSSecuredConnectionInfos> - (m_cntInfos->getHost(), m_cntInfos->getPort(), tlsSession, tlsSocket); - } - catch (exceptions::command_error&) - { + m_cntInfos = make_shared <tls::TLSSecuredConnectionInfos>( + m_cntInfos->getHost(), m_cntInfos->getPort(), tlsSession, tlsSocket + ); + + } catch (exceptions::command_error&) { + // Non-fatal error throw; - } - catch (exception&) - { + + } catch (exception&) { + // Fatal error internalDisconnect(); throw; @@ -566,28 +593,29 @@ void SMTPConnection::startTLS() #endif // VMIME_HAVE_TLS_SUPPORT -void SMTPConnection::disconnect() -{ - if (!isConnected()) +void SMTPConnection::disconnect() { + + if (!isConnected()) { throw exceptions::not_connected(); + } internalDisconnect(); } -void SMTPConnection::internalDisconnect() -{ - if (isConnected()) - { - try - { +void SMTPConnection::internalDisconnect() { + + if (isConnected()) { + + try { + sendRequest(SMTPCommand::QUIT()); // Do not wait for server response. This is contrary to the RFC, but // some servers never send a response to a QUIT command. - } - catch (exception&) - { + + } catch (exception&) { + // Not important } } @@ -605,16 +633,17 @@ void SMTPConnection::internalDisconnect() } -void SMTPConnection::sendRequest(shared_ptr <SMTPCommand> cmd) -{ +void SMTPConnection::sendRequest(const shared_ptr <SMTPCommand>& cmd) { + cmd->writeToSocket(m_socket, m_tracer); } -shared_ptr <SMTPResponse> SMTPConnection::readResponse() -{ - shared_ptr <SMTPResponse> resp = SMTPResponse::readResponse - (m_tracer, m_socket, m_timeoutHandler, m_responseState); +shared_ptr <SMTPResponse> SMTPConnection::readResponse() { + + shared_ptr <SMTPResponse> resp = SMTPResponse::readResponse( + m_tracer, m_socket, m_timeoutHandler, m_responseState + ); m_responseState = resp->getCurrentState(); @@ -622,56 +651,56 @@ shared_ptr <SMTPResponse> SMTPConnection::readResponse() } -bool SMTPConnection::isConnected() const -{ +bool SMTPConnection::isConnected() const { + return m_socket && m_socket->isConnected() && m_authenticated; } -bool SMTPConnection::isSecuredConnection() const -{ +bool SMTPConnection::isSecuredConnection() const { + return m_secured; } -shared_ptr <connectionInfos> SMTPConnection::getConnectionInfos() const -{ +shared_ptr <connectionInfos> SMTPConnection::getConnectionInfos() const { + return m_cntInfos; } -shared_ptr <SMTPTransport> SMTPConnection::getTransport() -{ +shared_ptr <SMTPTransport> SMTPConnection::getTransport() { + return m_transport.lock(); } -shared_ptr <session> SMTPConnection::getSession() -{ +shared_ptr <session> SMTPConnection::getSession() { + return m_transport.lock()->getSession(); } -shared_ptr <socket> SMTPConnection::getSocket() -{ +shared_ptr <socket> SMTPConnection::getSocket() { + return m_socket; } -shared_ptr <tracer> SMTPConnection::getTracer() -{ +shared_ptr <tracer> SMTPConnection::getTracer() { + return m_tracer; } -shared_ptr <timeoutHandler> SMTPConnection::getTimeoutHandler() -{ +shared_ptr <timeoutHandler> SMTPConnection::getTimeoutHandler() { + return m_timeoutHandler; } -shared_ptr <security::authenticator> SMTPConnection::getAuthenticator() -{ +shared_ptr <security::authenticator> SMTPConnection::getAuthenticator() { + return m_auth; } diff --git a/src/vmime/net/smtp/SMTPConnection.hpp b/src/vmime/net/smtp/SMTPConnection.hpp index c7614920..d8a2375e 100644 --- a/src/vmime/net/smtp/SMTPConnection.hpp +++ b/src/vmime/net/smtp/SMTPConnection.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard <[email protected]> +// Copyright (C) 2002 Vincent Richard <[email protected]> // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License as @@ -61,12 +61,16 @@ class SMTPTransport; /** Manage connection to a SMTP server. */ -class VMIME_EXPORT SMTPConnection : public object -{ +class VMIME_EXPORT SMTPConnection : public object { + public: - SMTPConnection(shared_ptr <SMTPTransport> transport, shared_ptr <security::authenticator> auth); - virtual ~SMTPConnection(); + SMTPConnection( + const shared_ptr <SMTPTransport>& transport, + const shared_ptr <security::authenticator>& auth + ); + + ~SMTPConnection(); virtual void connect(); @@ -83,7 +87,7 @@ public: virtual shared_ptr <session> getSession(); virtual shared_ptr <tracer> getTracer(); - void sendRequest(shared_ptr <SMTPCommand> cmd); + void sendRequest(const shared_ptr <SMTPCommand>& cmd); shared_ptr <SMTPResponse> readResponse(); bool hasExtension(const std::string& extName, std::vector <string>* params = NULL) const; diff --git a/src/vmime/net/smtp/SMTPExceptions.cpp b/src/vmime/net/smtp/SMTPExceptions.cpp index 0c3112c0..641632c5 100644 --- a/src/vmime/net/smtp/SMTPExceptions.cpp +++ b/src/vmime/net/smtp/SMTPExceptions.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard <[email protected]> +// Copyright (C) 2002 Vincent Richard <[email protected]> // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License as @@ -39,52 +39,60 @@ namespace smtp { // SMTPCommandError // -SMTPCommandError::SMTPCommandError - (const string& command, const string& response, - const string& desc, const int statusCode, - const SMTPResponse::enhancedStatusCode& extendedStatusCode, - const exception& other) +SMTPCommandError::SMTPCommandError( + const string& command, + const string& response, + const string& desc, + const int statusCode, + const SMTPResponse::enhancedStatusCode& extendedStatusCode, + const exception& other +) : command_error(command, response, desc, other), - m_status(statusCode), m_exStatus(extendedStatusCode) -{ + m_status(statusCode), + m_exStatus(extendedStatusCode) { + } -SMTPCommandError::SMTPCommandError - (const string& command, const string& response, - const int statusCode, const SMTPResponse::enhancedStatusCode& extendedStatusCode, - const exception& other) +SMTPCommandError::SMTPCommandError( + const string& command, + const string& response, + const int statusCode, + const SMTPResponse::enhancedStatusCode& extendedStatusCode, + const exception& other +) : command_error(command, response, "", other), - m_status(statusCode), m_exStatus(extendedStatusCode) -{ + m_status(statusCode), + m_exStatus(extendedStatusCode) { + } -SMTPCommandError::~SMTPCommandError() throw() -{ +SMTPCommandError::~SMTPCommandError() throw() { + } -int SMTPCommandError::statusCode() const -{ +int SMTPCommandError::statusCode() const { + return m_status; } -const SMTPResponse::enhancedStatusCode SMTPCommandError::extendedStatusCode() const -{ +const SMTPResponse::enhancedStatusCode SMTPCommandError::extendedStatusCode() const { + return m_exStatus; } -exception* SMTPCommandError::clone() const -{ +exception* SMTPCommandError::clone() const { + return new SMTPCommandError(*this); } -const char* SMTPCommandError::name() const throw() -{ +const char* SMTPCommandError::name() const throw() { + return "SMTPCommandError"; } @@ -94,24 +102,24 @@ const char* SMTPCommandError::name() const throw() // SMTPMessageSizeExceedsMaxLimitsException::SMTPMessageSizeExceedsMaxLimitsException(const exception& other) - : net_exception("Message size exceeds maximum server limits (permanent error).", other) -{ + : net_exception("Message size exceeds maximum server limits (permanent error).", other) { + } -SMTPMessageSizeExceedsMaxLimitsException::~SMTPMessageSizeExceedsMaxLimitsException() throw() -{ +SMTPMessageSizeExceedsMaxLimitsException::~SMTPMessageSizeExceedsMaxLimitsException() throw() { + } -exception* SMTPMessageSizeExceedsMaxLimitsException::clone() const -{ +exception* SMTPMessageSizeExceedsMaxLimitsException::clone() const { + return new SMTPMessageSizeExceedsMaxLimitsException(*this); } -const char* SMTPMessageSizeExceedsMaxLimitsException::name() const throw() -{ +const char* SMTPMessageSizeExceedsMaxLimitsException::name() const throw() { + return "SMTPMessageSizeExceedsMaxLimitsException"; } @@ -121,24 +129,24 @@ const char* SMTPMessageSizeExceedsMaxLimitsException::name() const throw() // SMTPMessageSizeExceedsCurLimitsException::SMTPMessageSizeExceedsCurLimitsException(const exception& other) - : net_exception("Message size exceeds current server limits (temporary storage error).", other) -{ + : net_exception("Message size exceeds current server limits (temporary storage error).", other) { + } -SMTPMessageSizeExceedsCurLimitsException::~SMTPMessageSizeExceedsCurLimitsException() throw() -{ +SMTPMessageSizeExceedsCurLimitsException::~SMTPMessageSizeExceedsCurLimitsException() throw() { + } -exception* SMTPMessageSizeExceedsCurLimitsException::clone() const -{ +exception* SMTPMessageSizeExceedsCurLimitsException::clone() const { + return new SMTPMessageSizeExceedsCurLimitsException(*this); } -const char* SMTPMessageSizeExceedsCurLimitsException::name() const throw() -{ +const char* SMTPMessageSizeExceedsCurLimitsException::name() const throw() { + return "SMTPMessageSizeExceedsCurLimitsException"; } diff --git a/src/vmime/net/smtp/SMTPExceptions.hpp b/src/vmime/net/smtp/SMTPExceptions.hpp index 75842042..70f1e113 100644 --- a/src/vmime/net/smtp/SMTPExceptions.hpp +++ b/src/vmime/net/smtp/SMTPExceptions.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard <[email protected]> +// Copyright (C) 2002 Vincent Richard <[email protected]> // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License as @@ -44,19 +44,25 @@ namespace smtp { /** SMTP Command error: a SMTP command failed. */ +class VMIME_EXPORT SMTPCommandError : public exceptions::command_error { -class VMIME_EXPORT SMTPCommandError : public exceptions::command_error -{ public: - SMTPCommandError(const string& command, const string& response, - const string& desc, const int statusCode, + SMTPCommandError( + const string& command, + const string& response, + const string& desc, + const int statusCode, const SMTPResponse::enhancedStatusCode& extendedStatusCode, - const exception& other = NO_EXCEPTION); + const exception& other = NO_EXCEPTION + ); - SMTPCommandError(const string& command, const string& response, + SMTPCommandError( + const string& command, + const string& response, const int statusCode, const SMTPResponse::enhancedStatusCode& extendedStatusCode, - const exception& other = NO_EXCEPTION); + const exception& other = NO_EXCEPTION + ); ~SMTPCommandError() throw(); @@ -87,9 +93,8 @@ private: /** SMTP error: message size exceeds maximum server limits. * This is a permanent error. */ +class VMIME_EXPORT SMTPMessageSizeExceedsMaxLimitsException : public exceptions::net_exception { -class VMIME_EXPORT SMTPMessageSizeExceedsMaxLimitsException : public exceptions::net_exception -{ public: SMTPMessageSizeExceedsMaxLimitsException(const exception& other = NO_EXCEPTION); @@ -103,9 +108,8 @@ public: /** SMTP error: message size exceeds current server limits. * This is a temporary error (you may retry later). */ +class VMIME_EXPORT SMTPMessageSizeExceedsCurLimitsException : public exceptions::net_exception { -class VMIME_EXPORT SMTPMessageSizeExceedsCurLimitsException : public exceptions::net_exception -{ public: SMTPMessageSizeExceedsCurLimitsException(const exception& other = NO_EXCEPTION); diff --git a/src/vmime/net/smtp/SMTPResponse.cpp b/src/vmime/net/smtp/SMTPResponse.cpp index b4b2c542..22347053 100644 --- a/src/vmime/net/smtp/SMTPResponse.cpp +++ b/src/vmime/net/smtp/SMTPResponse.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard <[email protected]> +// Copyright (C) 2002 Vincent Richard <[email protected]> // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License as @@ -44,50 +44,57 @@ namespace net { namespace smtp { -SMTPResponse::SMTPResponse - (shared_ptr <tracer> tr, shared_ptr <socket> sok, - shared_ptr <timeoutHandler> toh, const state& st) - : m_socket(sok), m_timeoutHandler(toh), m_tracer(tr), - m_responseBuffer(st.responseBuffer), m_responseContinues(false) -{ +SMTPResponse::SMTPResponse( + const shared_ptr <tracer>& tr, + const shared_ptr <socket>& sok, + const shared_ptr <timeoutHandler>& toh, + const state& st +) + : m_socket(sok), + m_timeoutHandler(toh), + m_tracer(tr), + m_responseBuffer(st.responseBuffer), + m_responseContinues(false) { + } SMTPResponse::SMTPResponse(const SMTPResponse&) - : vmime::object() -{ + : vmime::object() { + // Not used } -int SMTPResponse::getCode() const -{ +int SMTPResponse::getCode() const { + const int firstCode = m_lines[0].getCode(); - for (unsigned int i = 1 ; i < m_lines.size() ; ++i) - { + for (unsigned int i = 1 ; i < m_lines.size() ; ++i) { + // All response codes returned must be equal // or else this in an error... - if (m_lines[i].getCode() != firstCode) + if (m_lines[i].getCode() != firstCode) { return 0; + } } return firstCode; } -const SMTPResponse::enhancedStatusCode SMTPResponse::getEnhancedCode() const -{ +const SMTPResponse::enhancedStatusCode SMTPResponse::getEnhancedCode() const { + return m_lines[m_lines.size() - 1].getEnhancedCode(); } -const string SMTPResponse::getText() const -{ +const string SMTPResponse::getText() const { + string text = m_lines[0].getText(); - for (unsigned int i = 1 ; i < m_lines.size() ; ++i) - { + for (unsigned int i = 1 ; i < m_lines.size() ; ++i) { + text += '\n'; text += m_lines[i].getText(); } @@ -97,10 +104,13 @@ const string SMTPResponse::getText() const // static -shared_ptr <SMTPResponse> SMTPResponse::readResponse - (shared_ptr <tracer> tr, shared_ptr <socket> sok, - shared_ptr <timeoutHandler> toh, const state& st) -{ +shared_ptr <SMTPResponse> SMTPResponse::readResponse( + const shared_ptr <tracer>& tr, + const shared_ptr <socket>& sok, + const shared_ptr <timeoutHandler>& toh, + const state& st +) { + shared_ptr <SMTPResponse> resp = shared_ptr <SMTPResponse>(new SMTPResponse(tr, sok, toh, st)); @@ -110,54 +120,57 @@ shared_ptr <SMTPResponse> SMTPResponse::readResponse } -void SMTPResponse::readResponse() -{ +void SMTPResponse::readResponse() { + responseLine line = getNextResponse(); m_lines.push_back(line); - while (m_responseContinues) - { + while (m_responseContinues) { line = getNextResponse(); m_lines.push_back(line); } } -const string SMTPResponse::readResponseLine() -{ +const string SMTPResponse::readResponseLine() { + string currentBuffer = m_responseBuffer; - if (m_timeoutHandler) + if (m_timeoutHandler) { m_timeoutHandler->resetTimeOut(); + } + + while (true) { - while (true) - { // Get a line from the response buffer const size_t lineEnd = currentBuffer.find_first_of('\n'); - if (lineEnd != string::npos) - { + if (lineEnd != string::npos) { + size_t actualLineEnd = lineEnd; - if (actualLineEnd != 0 && currentBuffer[actualLineEnd - 1] == '\r') // CRLF case + if (actualLineEnd != 0 && currentBuffer[actualLineEnd - 1] == '\r') { // CRLF case actualLineEnd--; + } const string line(currentBuffer.begin(), currentBuffer.begin() + actualLineEnd); currentBuffer.erase(currentBuffer.begin(), currentBuffer.begin() + lineEnd + 1); m_responseBuffer = currentBuffer; - if (m_tracer) + if (m_tracer) { m_tracer->traceReceive(line); + } return line; } // Check whether the time-out delay is elapsed - if (m_timeoutHandler && m_timeoutHandler->isTimeOut()) - { - if (!m_timeoutHandler->handleTimeOut()) + if (m_timeoutHandler && m_timeoutHandler->isTimeOut()) { + + if (!m_timeoutHandler->handleTimeOut()) { throw exceptions::operation_timed_out(); + } m_timeoutHandler->resetTimeOut(); } @@ -166,8 +179,7 @@ const string SMTPResponse::readResponseLine() string receiveBuffer; m_socket->receive(receiveBuffer); - if (receiveBuffer.empty()) // buffer is empty - { + if (receiveBuffer.empty()) { // buffer is empty m_socket->waitForRead(); continue; } @@ -177,8 +189,8 @@ const string SMTPResponse::readResponseLine() } -const SMTPResponse::responseLine SMTPResponse::getNextResponse() -{ +const SMTPResponse::responseLine SMTPResponse::getNextResponse() { + string line = readResponseLine(); const int code = extractResponseCode(line); @@ -186,22 +198,23 @@ const SMTPResponse::responseLine SMTPResponse::getNextResponse() m_responseContinues = (line.length() >= 4 && line[3] == '-'); - if (line.length() > 4) + if (line.length() > 4) { text = utility::stringUtils::trim(line.substr(4)); - else + } else { text = ""; + } return responseLine(code, text, extractEnhancedCode(text)); } // static -int SMTPResponse::extractResponseCode(const string& response) -{ +int SMTPResponse::extractResponseCode(const string& response) { + int code = 0; - if (response.length() >= 3) - { + if (response.length() >= 3) { + code = (response[0] - '0') * 100 + (response[1] - '0') * 10 + (response[2] - '0'); @@ -212,23 +225,23 @@ int SMTPResponse::extractResponseCode(const string& response) // static -const SMTPResponse::enhancedStatusCode SMTPResponse::extractEnhancedCode(const string& responseText) -{ +const SMTPResponse::enhancedStatusCode SMTPResponse::extractEnhancedCode(const string& responseText) { + enhancedStatusCode enhCode; std::istringstream iss(responseText); iss.imbue(std::locale::classic()); - if (std::isdigit(iss.peek())) - { + if (std::isdigit(iss.peek())) { + iss >> enhCode.klass; - if (iss.get() == '.' && std::isdigit(iss.peek())) - { + if (iss.get() == '.' && std::isdigit(iss.peek())) { + iss >> enhCode.subject; - if (iss.get() == '.' && std::isdigit(iss.peek())) - { + if (iss.get() == '.' && std::isdigit(iss.peek())) { + iss >> enhCode.detail; return enhCode; } @@ -239,26 +252,26 @@ const SMTPResponse::enhancedStatusCode SMTPResponse::extractEnhancedCode(const s } -const SMTPResponse::responseLine SMTPResponse::getLineAt(const size_t pos) const -{ +const SMTPResponse::responseLine SMTPResponse::getLineAt(const size_t pos) const { + return m_lines[pos]; } -size_t SMTPResponse::getLineCount() const -{ +size_t SMTPResponse::getLineCount() const { + return m_lines.size(); } -const SMTPResponse::responseLine SMTPResponse::getLastLine() const -{ +const SMTPResponse::responseLine SMTPResponse::getLastLine() const { + return m_lines[m_lines.size() - 1]; } -const SMTPResponse::state SMTPResponse::getCurrentState() const -{ +const SMTPResponse::state SMTPResponse::getCurrentState() const { + state st; st.responseBuffer = m_responseBuffer; @@ -269,44 +282,50 @@ const SMTPResponse::state SMTPResponse::getCurrentState() const // SMTPResponse::responseLine -SMTPResponse::responseLine::responseLine(const int code, const string& text, const enhancedStatusCode& enhCode) - : m_code(code), m_text(text), m_enhCode(enhCode) -{ +SMTPResponse::responseLine::responseLine( + const int code, + const string& text, + const enhancedStatusCode& enhCode +) + : m_code(code), + m_text(text), + m_enhCode(enhCode) { + } -void SMTPResponse::responseLine::setCode(const int code) -{ +void SMTPResponse::responseLine::setCode(const int code) { + m_code = code; } -int SMTPResponse::responseLine::getCode() const -{ +int SMTPResponse::responseLine::getCode() const { + return m_code; } -void SMTPResponse::responseLine::setEnhancedCode(const enhancedStatusCode& enhCode) -{ +void SMTPResponse::responseLine::setEnhancedCode(const enhancedStatusCode& enhCode) { + m_enhCode = enhCode; } -const SMTPResponse::enhancedStatusCode SMTPResponse::responseLine::getEnhancedCode() const -{ +const SMTPResponse::enhancedStatusCode SMTPResponse::responseLine::getEnhancedCode() const { + return m_enhCode; } -void SMTPResponse::responseLine::setText(const string& text) -{ +void SMTPResponse::responseLine::setText(const string& text) { + m_text = text; } -const string SMTPResponse::responseLine::getText() const -{ +const string SMTPResponse::responseLine::getText() const { + return m_text; } @@ -316,19 +335,23 @@ const string SMTPResponse::responseLine::getText() const SMTPResponse::enhancedStatusCode::enhancedStatusCode() - : klass(0), subject(0), detail(0) -{ + : klass(0), + subject(0), + detail(0) { + } SMTPResponse::enhancedStatusCode::enhancedStatusCode(const enhancedStatusCode& enhCode) - : klass(enhCode.klass), subject(enhCode.subject), detail(enhCode.detail) -{ + : klass(enhCode.klass), + subject(enhCode.subject), + detail(enhCode.detail) { + } -std::ostream& operator<<(std::ostream& os, const SMTPResponse::enhancedStatusCode& code) -{ +std::ostream& operator<<(std::ostream& os, const SMTPResponse::enhancedStatusCode& code) { + os << code.klass << '.' << code.subject << '.' << code.detail; return os; } diff --git a/src/vmime/net/smtp/SMTPResponse.hpp b/src/vmime/net/smtp/SMTPResponse.hpp index 4d88b6b5..2eec7f4d 100644 --- a/src/vmime/net/smtp/SMTPResponse.hpp +++ b/src/vmime/net/smtp/SMTPResponse.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard <[email protected]> +// Copyright (C) 2002 Vincent Richard <[email protected]> // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License as @@ -49,19 +49,19 @@ namespace smtp { /** A SMTP response, as sent by the server. */ -class VMIME_EXPORT SMTPResponse : public object -{ +class VMIME_EXPORT SMTPResponse : public object { + public: /** Current state of response parser. */ - struct state - { + struct state { + string responseBuffer; }; /** Enhanced status code (as per RFC-3463). */ - struct enhancedStatusCode - { + struct enhancedStatusCode { + enhancedStatusCode(); enhancedStatusCode(const enhancedStatusCode& enhCode); @@ -71,8 +71,8 @@ public: }; /** An element of a SMTP response. */ - class responseLine - { + class responseLine { + public: responseLine(const int code, const string& text, const enhancedStatusCode& enhCode); @@ -104,9 +104,12 @@ public: * @throws exceptions::operation_timed_out if no data * has been received within the granted time */ - static shared_ptr <SMTPResponse> readResponse - (shared_ptr <tracer> tr, shared_ptr <socket> sok, - shared_ptr <timeoutHandler> toh, const state& st); + static shared_ptr <SMTPResponse> readResponse( + const shared_ptr <tracer>& tr, + const shared_ptr <socket>& sok, + const shared_ptr <timeoutHandler>& toh, + const state& st + ); /** Return the SMTP response code. * @@ -154,7 +157,13 @@ public: private: - SMTPResponse(shared_ptr <tracer> tr, shared_ptr <socket> sok, shared_ptr <timeoutHandler> toh, const state& st); + SMTPResponse( + const shared_ptr <tracer>& tr, + const shared_ptr <socket>& sok, + const shared_ptr <timeoutHandler>& toh, + const state& st + ); + SMTPResponse(const SMTPResponse&); void readResponse(); diff --git a/src/vmime/net/smtp/SMTPSTransport.cpp b/src/vmime/net/smtp/SMTPSTransport.cpp index ab64d49d..5158aa98 100644 --- a/src/vmime/net/smtp/SMTPSTransport.cpp +++ b/src/vmime/net/smtp/SMTPSTransport.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard <[email protected]> +// Copyright (C) 2002 Vincent Richard <[email protected]> // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License as @@ -35,19 +35,22 @@ namespace net { namespace smtp { -SMTPSTransport::SMTPSTransport(shared_ptr <session> sess, shared_ptr <security::authenticator> auth) - : SMTPTransport(sess, auth, true) -{ +SMTPSTransport::SMTPSTransport( + const shared_ptr <session>& sess, + const shared_ptr <security::authenticator>& auth +) + : SMTPTransport(sess, auth, true) { + } -SMTPSTransport::~SMTPSTransport() -{ +SMTPSTransport::~SMTPSTransport() { + } -const string SMTPSTransport::getProtocolName() const -{ +const string SMTPSTransport::getProtocolName() const { + return "smtps"; } @@ -58,14 +61,14 @@ const string SMTPSTransport::getProtocolName() const SMTPServiceInfos SMTPSTransport::sm_infos(true); -const serviceInfos& SMTPSTransport::getInfosInstance() -{ +const serviceInfos& SMTPSTransport::getInfosInstance() { + return sm_infos; } -const serviceInfos& SMTPSTransport::getInfos() const -{ +const serviceInfos& SMTPSTransport::getInfos() const { + return sm_infos; } diff --git a/src/vmime/net/smtp/SMTPSTransport.hpp b/src/vmime/net/smtp/SMTPSTransport.hpp index 7782f711..f19b3c55 100644 --- a/src/vmime/net/smtp/SMTPSTransport.hpp +++ b/src/vmime/net/smtp/SMTPSTransport.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard <[email protected]> +// Copyright (C) 2002 Vincent Richard <[email protected]> // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License as @@ -41,12 +41,15 @@ namespace smtp { /** SMTPS transport service. */ +class VMIME_EXPORT SMTPSTransport : public SMTPTransport { -class VMIME_EXPORT SMTPSTransport : public SMTPTransport -{ public: - SMTPSTransport(shared_ptr <session> sess, shared_ptr <security::authenticator> auth); + SMTPSTransport( + const shared_ptr <session>& sess, + const shared_ptr <security::authenticator>& auth + ); + ~SMTPSTransport(); const string getProtocolName() const; diff --git a/src/vmime/net/smtp/SMTPServiceInfos.cpp b/src/vmime/net/smtp/SMTPServiceInfos.cpp index 532bb8b8..a2ee3d57 100644 --- a/src/vmime/net/smtp/SMTPServiceInfos.cpp +++ b/src/vmime/net/smtp/SMTPServiceInfos.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard <[email protected]> +// Copyright (C) 2002 Vincent Richard <[email protected]> // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License as @@ -36,24 +36,24 @@ namespace smtp { SMTPServiceInfos::SMTPServiceInfos(const bool smtps) - : m_smtps(smtps) -{ + : m_smtps(smtps) { + } -const string SMTPServiceInfos::getPropertyPrefix() const -{ - if (m_smtps) +const string SMTPServiceInfos::getPropertyPrefix() const { + + if (m_smtps) { return "transport.smtps."; - else + } else { return "transport.smtp."; + } } -const SMTPServiceInfos::props& SMTPServiceInfos::getProperties() const -{ - static props smtpProps = - { +const SMTPServiceInfos::props& SMTPServiceInfos::getProperties() const { + + static props smtpProps = { // SMTP-specific options property("options.need-authentication", serviceInfos::property::TYPE_BOOLEAN, "false"), #if VMIME_HAVE_SASL_SUPPORT @@ -77,8 +77,7 @@ const SMTPServiceInfos::props& SMTPServiceInfos::getProperties() const property(serviceInfos::property::SERVER_PORT, "25"), }; - static props smtpsProps = - { + static props smtpsProps = { // SMTP-specific options property("options.need-authentication", serviceInfos::property::TYPE_BOOLEAN, "false"), #if VMIME_HAVE_SASL_SUPPORT @@ -106,8 +105,8 @@ const SMTPServiceInfos::props& SMTPServiceInfos::getProperties() const } -const std::vector <serviceInfos::property> SMTPServiceInfos::getAvailableProperties() const -{ +const std::vector <serviceInfos::property> SMTPServiceInfos::getAvailableProperties() const { + std::vector <property> list; const props& p = getProperties(); @@ -123,8 +122,7 @@ const std::vector <serviceInfos::property> SMTPServiceInfos::getAvailablePropert list.push_back(p.PROPERTY_AUTH_PASSWORD); #if VMIME_HAVE_TLS_SUPPORT - if (!m_smtps) - { + if (!m_smtps) { list.push_back(p.PROPERTY_CONNECTION_TLS); list.push_back(p.PROPERTY_CONNECTION_TLS_REQUIRED); } diff --git a/src/vmime/net/smtp/SMTPServiceInfos.hpp b/src/vmime/net/smtp/SMTPServiceInfos.hpp index f783194d..005a0a21 100644 --- a/src/vmime/net/smtp/SMTPServiceInfos.hpp +++ b/src/vmime/net/smtp/SMTPServiceInfos.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard <[email protected]> +// Copyright (C) 2002 Vincent Richard <[email protected]> // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License as @@ -41,15 +41,13 @@ namespace smtp { /** Information about SMTP service. */ +class VMIME_EXPORT SMTPServiceInfos : public serviceInfos { -class VMIME_EXPORT SMTPServiceInfos : public serviceInfos -{ public: SMTPServiceInfos(const bool smtps); - struct props - { + struct props { // SMTP-specific options serviceInfos::property PROPERTY_OPTIONS_NEEDAUTH; #if VMIME_HAVE_SASL_SUPPORT diff --git a/src/vmime/net/smtp/SMTPTransport.cpp b/src/vmime/net/smtp/SMTPTransport.cpp index 2af6a195..72cba7c7 100644 --- a/src/vmime/net/smtp/SMTPTransport.cpp +++ b/src/vmime/net/smtp/SMTPTransport.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard <[email protected]> +// Copyright (C) 2002 Vincent Richard <[email protected]> // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License as @@ -51,117 +51,146 @@ namespace net { namespace smtp { -SMTPTransport::SMTPTransport(shared_ptr <session> sess, shared_ptr <security::authenticator> auth, const bool secured) - : transport(sess, getInfosInstance(), auth), m_isSMTPS(secured), m_needReset(false) -{ +SMTPTransport::SMTPTransport( + const shared_ptr <session>& sess, + const shared_ptr <security::authenticator>& auth, + const bool secured +) + : transport(sess, getInfosInstance(), auth), + m_isSMTPS(secured), + m_needReset(false) { + } -SMTPTransport::~SMTPTransport() -{ - try - { - if (isConnected()) +SMTPTransport::~SMTPTransport() { + + try { + + if (isConnected()) { disconnect(); - } - catch (...) - { + } + + } catch (...) { + // Don't throw in destructor } } -const string SMTPTransport::getProtocolName() const -{ +const string SMTPTransport::getProtocolName() const { + return "smtp"; } -bool SMTPTransport::isSMTPS() const -{ +bool SMTPTransport::isSMTPS() const { + return m_isSMTPS; } -void SMTPTransport::connect() -{ - if (isConnected()) +void SMTPTransport::connect() { + + if (isConnected()) { throw exceptions::already_connected(); + } - m_connection = make_shared <SMTPConnection> - (dynamicCast <SMTPTransport>(shared_from_this()), getAuthenticator()); + m_connection = make_shared <SMTPConnection>( + dynamicCast <SMTPTransport>(shared_from_this()), getAuthenticator() + ); m_connection->connect(); } -bool SMTPTransport::isConnected() const -{ +bool SMTPTransport::isConnected() const { + return m_connection && m_connection->isConnected(); } -bool SMTPTransport::isSecuredConnection() const -{ - if (m_connection == NULL) +bool SMTPTransport::isSecuredConnection() const { + + if (!m_connection) { return false; + } return m_connection->isSecuredConnection(); } -shared_ptr <connectionInfos> SMTPTransport::getConnectionInfos() const -{ - if (m_connection == NULL) +shared_ptr <connectionInfos> SMTPTransport::getConnectionInfos() const { + + if (!m_connection) { return null; + } return m_connection->getConnectionInfos(); } -shared_ptr <SMTPConnection> SMTPTransport::getConnection() -{ +shared_ptr <SMTPConnection> SMTPTransport::getConnection() { + return m_connection; } -void SMTPTransport::disconnect() -{ - if (!isConnected()) +void SMTPTransport::disconnect() { + + if (!isConnected()) { throw exceptions::not_connected(); + } m_connection->disconnect(); m_connection = null; } -void SMTPTransport::noop() -{ - if (!isConnected()) +void SMTPTransport::noop() { + + if (!isConnected()) { throw exceptions::not_connected(); + } m_connection->sendRequest(SMTPCommand::NOOP()); shared_ptr <SMTPResponse> resp = m_connection->readResponse(); - if (resp->getCode() != 250) - { - throw SMTPCommandError - ("NOOP", resp->getText(), resp->getCode(), resp->getEnhancedCode()); + if (resp->getCode() != 250) { + throw SMTPCommandError("NOOP", resp->getText(), resp->getCode(), resp->getEnhancedCode()); + } +} + + +// static +bool SMTPTransport::mailboxNeedsUTF8(const mailbox& mb) { + + bool all7bit = + utility::stringUtils::is7bit(mb.getEmail().getLocalName().getBuffer()) + && utility::stringUtils::is7bit(mb.getEmail().getDomainName().getBuffer()); + + for (size_t i = 0, n = mb.getName().getWordCount() ; all7bit && i != n ; ++i) { + all7bit = utility::stringUtils::is7bit(mb.getName().getWordAt(i)->getBuffer()); } + + return !all7bit; } -void SMTPTransport::sendEnvelope - (const mailbox& expeditor, const mailboxList& recipients, - const mailbox& sender, bool sendDATACommand, - const size_t size) -{ +void SMTPTransport::sendEnvelope( + const mailbox& expeditor, + const mailboxList& recipients, + const mailbox& sender, + bool sendDATACommand, + const size_t size +) { // If no recipient/expeditor was found, throw an exception - if (recipients.isEmpty()) + if (recipients.isEmpty()) { throw exceptions::no_recipient(); - else if (expeditor.isEmpty()) + } else if (expeditor.isEmpty()) { throw exceptions::no_expeditor(); + } const bool needReset = m_needReset; @@ -173,135 +202,185 @@ void SMTPTransport::sendEnvelope shared_ptr <SMTPCommandSet> commands = SMTPCommandSet::create(hasPipelining); // Emit a "RSET" command if we previously sent a message on this connection - if (needReset) + if (needReset) { commands->addCommand(SMTPCommand::RSET()); + } - // Emit the "MAIL" command + // Check whether we need SMTPUTF8 const bool hasSMTPUTF8 = m_connection->hasExtension("SMTPUTF8"); + bool needSMTPUTF8 = false; + + if (!sender.isEmpty()) { + needSMTPUTF8 = needSMTPUTF8 || mailboxNeedsUTF8(sender); + } else { + needSMTPUTF8 = needSMTPUTF8 || mailboxNeedsUTF8(expeditor); + } + + for (size_t i = 0 ; i < recipients.getMailboxCount() ; ++i) { + + const mailbox& mbox = *recipients.getMailboxAt(i); + needSMTPUTF8 = needSMTPUTF8 || mailboxNeedsUTF8(mbox); + } + + // Emit the "MAIL" command const bool hasSize = m_connection->hasExtension("SIZE"); - if (!sender.isEmpty()) - commands->addCommand(SMTPCommand::MAIL(sender, hasSMTPUTF8, hasSize ? size : 0)); - else - commands->addCommand(SMTPCommand::MAIL(expeditor, hasSMTPUTF8, hasSize ? size : 0)); + if (!sender.isEmpty()) { + + commands->addCommand( + SMTPCommand::MAIL( + sender, hasSMTPUTF8 && needSMTPUTF8, hasSize ? size : 0 + ) + ); + + } else { + + commands->addCommand( + SMTPCommand::MAIL( + expeditor, hasSMTPUTF8 && needSMTPUTF8, hasSize ? size : 0 + ) + ); + } // Now, we will need to reset next time m_needReset = true; // Emit a "RCPT TO" command for each recipient - for (size_t i = 0 ; i < recipients.getMailboxCount() ; ++i) - { + for (size_t i = 0 ; i < recipients.getMailboxCount() ; ++i) { + const mailbox& mbox = *recipients.getMailboxAt(i); - commands->addCommand(SMTPCommand::RCPT(mbox, hasSMTPUTF8)); + commands->addCommand(SMTPCommand::RCPT(mbox, hasSMTPUTF8 && needSMTPUTF8)); } // Prepare sending of message data - if (sendDATACommand) + if (sendDATACommand) { commands->addCommand(SMTPCommand::DATA()); + } // Read response for "RSET" command - if (needReset) - { + if (needReset) { + commands->writeToSocket(m_connection->getSocket(), m_connection->getTracer()); resp = m_connection->readResponse(); if (resp->getCode() != 250 && - resp->getCode() != 200) // RFC-876: << In reply to a RSET and/or a NOOP command, - // some servers reply "200" >> - { + resp->getCode() != 200) { // RFC-876: << In reply to a RSET and/or a NOOP command, + // some servers reply "200" >> + disconnect(); - throw SMTPCommandError - (commands->getLastCommandSent()->getText(), resp->getText(), - resp->getCode(), resp->getEnhancedCode()); + throw SMTPCommandError( + commands->getLastCommandSent()->getText(), resp->getText(), + resp->getCode(), resp->getEnhancedCode() + ); } } // Read response for "MAIL" command commands->writeToSocket(m_connection->getSocket(), m_connection->getTracer()); - if ((resp = m_connection->readResponse())->getCode() != 250) - { + if ((resp = m_connection->readResponse())->getCode() != 250) { + // SIZE extension: insufficient system storage - if (resp->getCode() == 452) - { - throw SMTPMessageSizeExceedsCurLimitsException - (SMTPCommandError(commands->getLastCommandSent()->getText(), resp->getText(), - resp->getCode(), resp->getEnhancedCode())); - } + if (resp->getCode() == 452) { + + throw SMTPMessageSizeExceedsCurLimitsException( + SMTPCommandError( + commands->getLastCommandSent()->getText(), resp->getText(), + resp->getCode(), resp->getEnhancedCode() + ) + ); + // SIZE extension: message size exceeds fixed maximum message size - else if (resp->getCode() == 552) - { - throw SMTPMessageSizeExceedsMaxLimitsException - (SMTPCommandError(commands->getLastCommandSent()->getText(), resp->getText(), - resp->getCode(), resp->getEnhancedCode())); - } + } else if (resp->getCode() == 552) { + + throw SMTPMessageSizeExceedsMaxLimitsException( + SMTPCommandError( + commands->getLastCommandSent()->getText(), resp->getText(), + resp->getCode(), resp->getEnhancedCode() + ) + ); + // Other error - else - { - throw SMTPCommandError - (commands->getLastCommandSent()->getText(), resp->getText(), - resp->getCode(), resp->getEnhancedCode()); + } else { + + throw SMTPCommandError( + commands->getLastCommandSent()->getText(), resp->getText(), + resp->getCode(), resp->getEnhancedCode() + ); } } // Read responses for "RCPT TO" commands - for (size_t i = 0 ; i < recipients.getMailboxCount() ; ++i) - { + for (size_t i = 0 ; i < recipients.getMailboxCount() ; ++i) { + commands->writeToSocket(m_connection->getSocket(), m_connection->getTracer()); resp = m_connection->readResponse(); if (resp->getCode() != 250 && - resp->getCode() != 251) - { + resp->getCode() != 251) { + // SIZE extension: insufficient system storage - if (resp->getCode() == 452) - { - throw SMTPMessageSizeExceedsCurLimitsException - (SMTPCommandError(commands->getLastCommandSent()->getText(), resp->getText(), - resp->getCode(), resp->getEnhancedCode())); - } + if (resp->getCode() == 452) { + + throw SMTPMessageSizeExceedsCurLimitsException( + SMTPCommandError( + commands->getLastCommandSent()->getText(), resp->getText(), + resp->getCode(), resp->getEnhancedCode() + ) + ); + // SIZE extension: message size exceeds fixed maximum message size - else if (resp->getCode() == 552) - { - throw SMTPMessageSizeExceedsMaxLimitsException - (SMTPCommandError(commands->getLastCommandSent()->getText(), resp->getText(), - resp->getCode(), resp->getEnhancedCode())); - } + } else if (resp->getCode() == 552) { + + throw SMTPMessageSizeExceedsMaxLimitsException( + SMTPCommandError( + commands->getLastCommandSent()->getText(), resp->getText(), + resp->getCode(), resp->getEnhancedCode() + ) + ); + // Other error - else - { - throw SMTPCommandError - (commands->getLastCommandSent()->getText(), resp->getText(), - resp->getCode(), resp->getEnhancedCode()); + } else { + + throw SMTPCommandError( + commands->getLastCommandSent()->getText(), resp->getText(), + resp->getCode(), resp->getEnhancedCode() + ); } } } // Read response for "DATA" command - if (sendDATACommand) - { + if (sendDATACommand) { + commands->writeToSocket(m_connection->getSocket(), m_connection->getTracer()); - if ((resp = m_connection->readResponse())->getCode() != 354) - { - throw SMTPCommandError - (commands->getLastCommandSent()->getText(), resp->getText(), - resp->getCode(), resp->getEnhancedCode()); + if ((resp = m_connection->readResponse())->getCode() != 354) { + + throw SMTPCommandError( + commands->getLastCommandSent()->getText(), resp->getText(), + resp->getCode(), resp->getEnhancedCode() + ); } } } -void SMTPTransport::send - (const mailbox& expeditor, const mailboxList& recipients, - utility::inputStream& is, const size_t size, - utility::progressListener* progress, const mailbox& sender) -{ - if (!isConnected()) +void SMTPTransport::send( + const mailbox& expeditor, + const mailboxList& recipients, + utility::inputStream& is, + const size_t size, + utility::progressListener* progress, + const mailbox& sender +) { + + if (!isConnected()) { throw exceptions::not_connected(); + } // Send message envelope sendEnvelope(expeditor, recipients, sender, /* sendDATACommand */ true, size); @@ -318,28 +397,30 @@ void SMTPTransport::send // Send end-of-data delimiter m_connection->getSocket()->send("\r\n.\r\n"); - if (m_connection->getTracer()) - { + if (m_connection->getTracer()) { m_connection->getTracer()->traceSendBytes(size); m_connection->getTracer()->traceSend("."); } shared_ptr <SMTPResponse> resp; - if ((resp = m_connection->readResponse())->getCode() != 250) - { - throw SMTPCommandError - ("DATA", resp->getText(), resp->getCode(), resp->getEnhancedCode()); + if ((resp = m_connection->readResponse())->getCode() != 250) { + throw SMTPCommandError("DATA", resp->getText(), resp->getCode(), resp->getEnhancedCode()); } } -void SMTPTransport::send - (shared_ptr <vmime::message> msg, const mailbox& expeditor, const mailboxList& recipients, - utility::progressListener* progress, const mailbox& sender) -{ - if (!isConnected()) +void SMTPTransport::send( + const shared_ptr <vmime::message>& msg, + const mailbox& expeditor, + const mailboxList& recipients, + utility::progressListener* progress, + const mailbox& sender +) { + + if (!isConnected()) { throw exceptions::not_connected(); + } // Generate the message with Internationalized Email support, // if this is supported by the SMTP server @@ -350,9 +431,8 @@ void SMTPTransport::send // buffer then use the send() method which takes an inputStream if (!m_connection->hasExtension("CHUNKING") || !getInfos().getPropertyValue <bool>(getSession(), - dynamic_cast <const SMTPServiceInfos&>(getInfos()).getProperties().PROPERTY_OPTIONS_CHUNKING)) + dynamic_cast <const SMTPServiceInfos&>(getInfos()).getProperties().PROPERTY_OPTIONS_CHUNKING)) { - { std::ostringstream oss; utility::outputStreamAdapter ossAdapter(oss); @@ -369,8 +449,7 @@ void SMTPTransport::send // Send message envelope const size_t msgSize = msg->getGeneratedSize(ctx); - sendEnvelope(expeditor, recipients, sender, - /* sendDATACommand */ false, msgSize); + sendEnvelope(expeditor, recipients, sender, /* sendDATACommand */ false, msgSize); // Send the message by chunks SMTPChunkingOutputStreamAdapter chunkStream(m_connection, msgSize, progress); @@ -387,14 +466,14 @@ void SMTPTransport::send SMTPServiceInfos SMTPTransport::sm_infos(false); -const serviceInfos& SMTPTransport::getInfosInstance() -{ +const serviceInfos& SMTPTransport::getInfosInstance() { + return sm_infos; } -const serviceInfos& SMTPTransport::getInfos() const -{ +const serviceInfos& SMTPTransport::getInfos() const { + return sm_infos; } diff --git a/src/vmime/net/smtp/SMTPTransport.hpp b/src/vmime/net/smtp/SMTPTransport.hpp index a0f02418..67c63a55 100644 --- a/src/vmime/net/smtp/SMTPTransport.hpp +++ b/src/vmime/net/smtp/SMTPTransport.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard <[email protected]> +// Copyright (C) 2002 Vincent Richard <[email protected]> // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License as @@ -49,12 +49,16 @@ class SMTPCommand; /** SMTP transport service. */ +class VMIME_EXPORT SMTPTransport : public transport { -class VMIME_EXPORT SMTPTransport : public transport -{ public: - SMTPTransport(shared_ptr <session> sess, shared_ptr <security::authenticator> auth, const bool secured = false); + SMTPTransport( + const shared_ptr <session>& sess, + const shared_ptr <security::authenticator>& auth, + const bool secured = false + ); + ~SMTPTransport(); const string getProtocolName() const; @@ -68,20 +72,22 @@ public: void noop(); - void send - (const mailbox& expeditor, - const mailboxList& recipients, - utility::inputStream& is, - const size_t size, - utility::progressListener* progress = NULL, - const mailbox& sender = mailbox()); - - void send - (shared_ptr <vmime::message> msg, - const mailbox& expeditor, - const mailboxList& recipients, - utility::progressListener* progress = NULL, - const mailbox& sender = mailbox()); + void send( + const mailbox& expeditor, + const mailboxList& recipients, + utility::inputStream& is, + const size_t size, + utility::progressListener* progress = NULL, + const mailbox& sender = mailbox() + ); + + void send( + const shared_ptr <vmime::message>& msg, + const mailbox& expeditor, + const mailboxList& recipients, + utility::progressListener* progress = NULL, + const mailbox& sender = mailbox() + ); bool isSecuredConnection() const; shared_ptr <connectionInfos> getConnectionInfos() const; @@ -91,6 +97,8 @@ public: private: + static bool mailboxNeedsUTF8(const mailbox& mb); + /** Send the MAIL and RCPT commands to the server, checking the * response, and using pipelining if supported by the server. * Optionally, the DATA command can also be sent. @@ -101,12 +109,13 @@ private: * @param sendDATACommand if true, the DATA command will be sent * @param size message size, in bytes (or 0, if not known) */ - void sendEnvelope - (const mailbox& expeditor, - const mailboxList& recipients, - const mailbox& sender, - bool sendDATACommand, - const size_t size); + void sendEnvelope( + const mailbox& expeditor, + const mailboxList& recipients, + const mailbox& sender, + bool sendDATACommand, + const size_t size + ); shared_ptr <SMTPConnection> m_connection; diff --git a/src/vmime/net/smtp/smtp.hpp b/src/vmime/net/smtp/smtp.hpp index 2a9ee312..4c0b17d7 100644 --- a/src/vmime/net/smtp/smtp.hpp +++ b/src/vmime/net/smtp/smtp.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard <[email protected]> +// Copyright (C) 2002 Vincent Richard <[email protected]> // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License as diff --git a/src/vmime/net/socket.hpp b/src/vmime/net/socket.hpp index 2de83dd1..a236a9f3 100644 --- a/src/vmime/net/socket.hpp +++ b/src/vmime/net/socket.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard <[email protected]> +// Copyright (C) 2002 Vincent Richard <[email protected]> // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License as @@ -43,13 +43,11 @@ namespace net { /** Interface for connecting to servers. */ +class VMIME_EXPORT socket : public object { -class VMIME_EXPORT socket : public object -{ public: - enum Status - { + enum Status { STATUS_WOULDBLOCK = 0xf, /**< The operation would block. Retry later. */ STATUS_WANT_READ = 0x1, /**< The socket wants to read data, retry when data is available. */ STATUS_WANT_WRITE = 0x2 /**< The socket wants to write data, retry when data can be written. */ @@ -175,7 +173,7 @@ public: * * @param tracer tracer to use */ - virtual void setTracer(shared_ptr <tracer> tracer) = 0; + virtual void setTracer(const shared_ptr <tracer>& tracer) = 0; /** Return the tracer used by this socket. * @@ -195,9 +193,8 @@ private: /** A class to create 'socket' objects. */ +class socketFactory : public object { -class socketFactory : public object -{ public: virtual ~socketFactory() { } @@ -213,7 +210,7 @@ public: * @param th timeout handler * @return a new socket */ - virtual shared_ptr <socket> create(shared_ptr <timeoutHandler> th) = 0; + virtual shared_ptr <socket> create(const shared_ptr <timeoutHandler>& th) = 0; }; diff --git a/src/vmime/net/store.cpp b/src/vmime/net/store.cpp new file mode 100644 index 00000000..3c9a66d6 --- /dev/null +++ b/src/vmime/net/store.cpp @@ -0,0 +1,57 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002 Vincent Richard <[email protected]> +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules is making +// a combined work based on this library. Thus, the terms and conditions of +// the GNU General Public License cover the whole combination. +// + +#include "vmime/config.hpp" + + +#if VMIME_HAVE_MESSAGING_FEATURES + + +#include "vmime/net/store.hpp" + + +namespace vmime { +namespace net { + + +store::store( + const shared_ptr <session>& sess, + const serviceInfos& infos, + const shared_ptr <security::authenticator>& auth +) + : service(sess, infos, auth) { + +} + + +store::Type store::getType() const { + + return TYPE_STORE; +} + + +} // net +} // vmime + + +#endif // VMIME_HAVE_MESSAGING_FEATURES diff --git a/src/vmime/net/store.hpp b/src/vmime/net/store.hpp index 37dcadbc..a96f2673 100644 --- a/src/vmime/net/store.hpp +++ b/src/vmime/net/store.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard <[email protected]> +// Copyright (C) 2002 Vincent Richard <[email protected]> // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License as @@ -42,13 +42,15 @@ namespace net { /** A store service. * Encapsulate protocols that provide access to user's mail drop. */ +class VMIME_EXPORT store : public service { -class VMIME_EXPORT store : public service -{ protected: - store(shared_ptr <session> sess, const serviceInfos& infos, shared_ptr <security::authenticator> auth) - : service(sess, infos, auth) { } + store( + const shared_ptr <session>& sess, + const serviceInfos& infos, + const shared_ptr <security::authenticator>& auth + ); public: @@ -81,8 +83,7 @@ public: virtual bool isValidFolderName(const folder::path::component& name) const = 0; /** Store capabilities. */ - enum Capabilities - { + enum Capabilities { CAPABILITY_CREATE_FOLDER = (1 << 0), /**< Can create folders. */ CAPABILITY_RENAME_FOLDER = (1 << 1), /**< Can rename folders. */ CAPABILITY_ADD_MESSAGE = (1 << 2), /**< Can append message to folders. */ @@ -101,7 +102,7 @@ public: virtual int getCapabilities() const = 0; - Type getType() const { return (TYPE_STORE); } + Type getType() const; }; diff --git a/src/vmime/net/timeoutHandler.hpp b/src/vmime/net/timeoutHandler.hpp index 397cc796..fed1bc48 100644 --- a/src/vmime/net/timeoutHandler.hpp +++ b/src/vmime/net/timeoutHandler.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard <[email protected]> +// Copyright (C) 2002 Vincent Richard <[email protected]> // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License as @@ -42,9 +42,8 @@ namespace net { * to stop operations that takes too much time to complete (ie. no data * received from the server for a long time if the network link is down). */ +class VMIME_EXPORT timeoutHandler : public object { -class VMIME_EXPORT timeoutHandler : public object -{ public: virtual ~timeoutHandler() { } @@ -71,9 +70,8 @@ public: /** A class to create 'timeoutHandler' objects. */ +class timeoutHandlerFactory : public object { -class timeoutHandlerFactory : public object -{ public: virtual ~timeoutHandlerFactory() { } diff --git a/src/vmime/net/tls/TLSProperties.cpp b/src/vmime/net/tls/TLSProperties.cpp index 1986db79..f7721d40 100644 --- a/src/vmime/net/tls/TLSProperties.cpp +++ b/src/vmime/net/tls/TLSProperties.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard <[email protected]> +// Copyright (C) 2002 Vincent Richard <[email protected]> // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License as diff --git a/src/vmime/net/tls/TLSProperties.hpp b/src/vmime/net/tls/TLSProperties.hpp index 0dbc8f05..94341cae 100644 --- a/src/vmime/net/tls/TLSProperties.hpp +++ b/src/vmime/net/tls/TLSProperties.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard <[email protected]> +// Copyright (C) 2002 Vincent Richard <[email protected]> // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License as @@ -41,8 +41,8 @@ namespace tls { /** Holds options for a TLS session. */ -class VMIME_EXPORT TLSProperties : public object -{ +class VMIME_EXPORT TLSProperties : public object { + public: TLSProperties(); @@ -50,8 +50,8 @@ public: /** Predefined generic cipher suites (work with all TLS libraries). */ - enum GenericCipherSuite - { + enum GenericCipherSuite { + CIPHERSUITE_HIGH, /**< High encryption cipher suites (> 128 bits). */ CIPHERSUITE_MEDIUM, /**< Medium encryption cipher suites (>= 128 bits). */ CIPHERSUITE_LOW, /**< Low encryption cipher suites (>= 64 bits). */ diff --git a/src/vmime/net/tls/TLSSecuredConnectionInfos.cpp b/src/vmime/net/tls/TLSSecuredConnectionInfos.cpp index 4856e9af..055dfea0 100644 --- a/src/vmime/net/tls/TLSSecuredConnectionInfos.cpp +++ b/src/vmime/net/tls/TLSSecuredConnectionInfos.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard <[email protected]> +// Copyright (C) 2002 Vincent Richard <[email protected]> // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License as @@ -36,29 +36,34 @@ namespace net { namespace tls { -TLSSecuredConnectionInfos::TLSSecuredConnectionInfos - (const string& host, const port_t port, - shared_ptr <TLSSession> tlsSession, shared_ptr <TLSSocket> tlsSocket) - : m_host(host), m_port(port), - m_tlsSession(tlsSession), m_tlsSocket(tlsSocket) -{ +TLSSecuredConnectionInfos::TLSSecuredConnectionInfos( + const string& host, + const port_t port, + const shared_ptr <TLSSession>& tlsSession, + const shared_ptr <TLSSocket>& tlsSocket +) + : m_host(host), + m_port(port), + m_tlsSession(tlsSession), + m_tlsSocket(tlsSocket) { + } -const string TLSSecuredConnectionInfos::getHost() const -{ +const string TLSSecuredConnectionInfos::getHost() const { + return m_host; } -port_t TLSSecuredConnectionInfos::getPort() const -{ +port_t TLSSecuredConnectionInfos::getPort() const { + return m_port; } -shared_ptr <const security::cert::certificateChain> TLSSecuredConnectionInfos::getPeerCertificates() const -{ +shared_ptr <const security::cert::certificateChain> TLSSecuredConnectionInfos::getPeerCertificates() const { + return m_tlsSocket->getPeerCertificates(); } diff --git a/src/vmime/net/tls/TLSSecuredConnectionInfos.hpp b/src/vmime/net/tls/TLSSecuredConnectionInfos.hpp index e552d6f9..c65e9d26 100644 --- a/src/vmime/net/tls/TLSSecuredConnectionInfos.hpp +++ b/src/vmime/net/tls/TLSSecuredConnectionInfos.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard <[email protected]> +// Copyright (C) 2002 Vincent Richard <[email protected]> // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License as @@ -47,12 +47,16 @@ class TLSSocket; /** Information about a TLS-secured connection used by a service. */ -class VMIME_EXPORT TLSSecuredConnectionInfos : public securedConnectionInfos -{ +class VMIME_EXPORT TLSSecuredConnectionInfos : public securedConnectionInfos { + public: - TLSSecuredConnectionInfos(const string& host, const port_t port, - shared_ptr <TLSSession> tlsSession, shared_ptr <TLSSocket> tlsSocket); + TLSSecuredConnectionInfos( + const string& host, + const port_t port, + const shared_ptr <TLSSession>& tlsSession, + const shared_ptr <TLSSocket>& tlsSocket + ); const string getHost() const; port_t getPort() const; diff --git a/src/vmime/net/tls/TLSSession.cpp b/src/vmime/net/tls/TLSSession.cpp index a46f07ca..ab8b7c3a 100644 --- a/src/vmime/net/tls/TLSSession.cpp +++ b/src/vmime/net/tls/TLSSession.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard <[email protected]> +// Copyright (C) 2002 Vincent Richard <[email protected]> // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License as @@ -35,8 +35,8 @@ namespace net { namespace tls { -TLSSession::TLSSession() -{ +TLSSession::TLSSession() { + } diff --git a/src/vmime/net/tls/TLSSession.hpp b/src/vmime/net/tls/TLSSession.hpp index 8951ffa4..9e84fe76 100644 --- a/src/vmime/net/tls/TLSSession.hpp +++ b/src/vmime/net/tls/TLSSession.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard <[email protected]> +// Copyright (C) 2002 Vincent Richard <[email protected]> // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License as @@ -46,8 +46,8 @@ namespace tls { /** Describe a TLS connection between a client and a server. */ -class VMIME_EXPORT TLSSession : public object, public enable_shared_from_this <TLSSession> -{ +class VMIME_EXPORT TLSSession : public object, public enable_shared_from_this <TLSSession> { + public: /** Create and initialize a new TLS session. @@ -57,7 +57,10 @@ public: * @param props TLS properties for this session * @return a new TLS session */ - static shared_ptr <TLSSession> create(shared_ptr <security::cert::certificateVerifier> cv, shared_ptr <TLSProperties> props); + static shared_ptr <TLSSession> create( + const shared_ptr <security::cert::certificateVerifier>& cv, + const shared_ptr <TLSProperties>& props + ); /** Create a new socket that adds a TLS security layer around * an existing socket. You should create only one socket @@ -66,7 +69,7 @@ public: * @param sok socket to wrap * @return TLS socket wrapper */ - virtual shared_ptr <TLSSocket> getSocket(shared_ptr <socket> sok) = 0; + virtual shared_ptr <TLSSocket> getSocket(const shared_ptr <socket>& sok) = 0; /** Get the object responsible for verifying certificates when * using secured connections (TLS/SSL). diff --git a/src/vmime/net/tls/TLSSocket.cpp b/src/vmime/net/tls/TLSSocket.cpp index 0419a571..fbca0820 100644 --- a/src/vmime/net/tls/TLSSocket.cpp +++ b/src/vmime/net/tls/TLSSocket.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard <[email protected]> +// Copyright (C) 2002 Vincent Richard <[email protected]> // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License as diff --git a/src/vmime/net/tls/TLSSocket.hpp b/src/vmime/net/tls/TLSSocket.hpp index be27d1d0..ca50aa8e 100644 --- a/src/vmime/net/tls/TLSSocket.hpp +++ b/src/vmime/net/tls/TLSSocket.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard <[email protected]> +// Copyright (C) 2002 Vincent Richard <[email protected]> // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License as @@ -49,8 +49,8 @@ class TLSSession; /** Add a TLS security layer to an existing socket. */ -class VMIME_EXPORT TLSSocket : public socket -{ +class VMIME_EXPORT TLSSocket : public socket { + public: /** Create a new socket object that adds a security layer @@ -59,7 +59,7 @@ public: * @param session TLS session * @param sok socket to wrap */ - static shared_ptr <TLSSocket> wrap(shared_ptr <TLSSession> session, shared_ptr <socket> sok); + static shared_ptr <TLSSocket> wrap(const shared_ptr <TLSSession>& session, const shared_ptr <socket>& sok); /** Starts a TLS handshake on this connection. * diff --git a/src/vmime/net/tls/gnutls/TLSProperties_GnuTLS.cpp b/src/vmime/net/tls/gnutls/TLSProperties_GnuTLS.cpp index 36ab7d7a..b2996fb3 100644 --- a/src/vmime/net/tls/gnutls/TLSProperties_GnuTLS.cpp +++ b/src/vmime/net/tls/gnutls/TLSProperties_GnuTLS.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard <[email protected]> +// Copyright (C) 2002 Vincent Richard <[email protected]> // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License as @@ -42,63 +42,63 @@ namespace tls { TLSProperties::TLSProperties() - : m_data(make_shared <TLSProperties_GnuTLS>()) -{ + : m_data(make_shared <TLSProperties_GnuTLS>()) { + setCipherSuite(CIPHERSUITE_DEFAULT); } TLSProperties::TLSProperties(const TLSProperties& props) : object(), - m_data(make_shared <TLSProperties_GnuTLS>()) -{ + m_data(make_shared <TLSProperties_GnuTLS>()) { + *dynamicCast <TLSProperties_GnuTLS>(m_data) = *dynamicCast <TLSProperties_GnuTLS>(props.m_data); } -void TLSProperties::setCipherSuite(const GenericCipherSuite cipherSuite) -{ - switch (cipherSuite) - { - case CIPHERSUITE_HIGH: +void TLSProperties::setCipherSuite(const GenericCipherSuite cipherSuite) { + + switch (cipherSuite) { + + case CIPHERSUITE_HIGH: - setCipherSuite("SECURE256:%SSL3_RECORD_VERSION"); - break; + setCipherSuite("SECURE256:%SSL3_RECORD_VERSION"); + break; - case CIPHERSUITE_MEDIUM: + case CIPHERSUITE_MEDIUM: - setCipherSuite("SECURE128:%SSL3_RECORD_VERSION"); - break; + setCipherSuite("SECURE128:%SSL3_RECORD_VERSION"); + break; - case CIPHERSUITE_LOW: + case CIPHERSUITE_LOW: - setCipherSuite("NORMAL:%SSL3_RECORD_VERSION"); - break; + setCipherSuite("NORMAL:%SSL3_RECORD_VERSION"); + break; - default: - case CIPHERSUITE_DEFAULT: + default: + case CIPHERSUITE_DEFAULT: - setCipherSuite("NORMAL:%SSL3_RECORD_VERSION"); - break; + setCipherSuite("NORMAL:%SSL3_RECORD_VERSION"); + break; } } -void TLSProperties::setCipherSuite(const string& cipherSuite) -{ +void TLSProperties::setCipherSuite(const string& cipherSuite) { + dynamicCast <TLSProperties_GnuTLS>(m_data)->cipherSuite = cipherSuite; } -const string TLSProperties::getCipherSuite() const -{ +const string TLSProperties::getCipherSuite() const { + return dynamicCast <TLSProperties_GnuTLS>(m_data)->cipherSuite; } -TLSProperties_GnuTLS& TLSProperties_GnuTLS::operator=(const TLSProperties_GnuTLS& other) -{ +TLSProperties_GnuTLS& TLSProperties_GnuTLS::operator=(const TLSProperties_GnuTLS& other) { + cipherSuite = other.cipherSuite; return *this; diff --git a/src/vmime/net/tls/gnutls/TLSProperties_GnuTLS.hpp b/src/vmime/net/tls/gnutls/TLSProperties_GnuTLS.hpp index 2038778a..96bbaead 100644 --- a/src/vmime/net/tls/gnutls/TLSProperties_GnuTLS.hpp +++ b/src/vmime/net/tls/gnutls/TLSProperties_GnuTLS.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard <[email protected]> +// Copyright (C) 2002 Vincent Richard <[email protected]> // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License as @@ -44,8 +44,8 @@ namespace net { namespace tls { -class TLSProperties_GnuTLS : public object -{ +class TLSProperties_GnuTLS : public object { + public: TLSProperties_GnuTLS& operator=(const TLSProperties_GnuTLS& other); diff --git a/src/vmime/net/tls/gnutls/TLSSession_GnuTLS.cpp b/src/vmime/net/tls/gnutls/TLSSession_GnuTLS.cpp index 2a6450eb..8586537e 100644 --- a/src/vmime/net/tls/gnutls/TLSSession_GnuTLS.cpp +++ b/src/vmime/net/tls/gnutls/TLSSession_GnuTLS.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard <[email protected]> +// Copyright (C) 2002 Vincent Richard <[email protected]> // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License as @@ -82,10 +82,10 @@ namespace tls { #ifndef VMIME_BUILDING_DOC // Initialize GNU TLS library -struct TLSGlobal -{ - TLSGlobal() - { +struct TLSGlobal { + + TLSGlobal() { + #if VMIME_HAVE_PTHREAD && defined(GCRY_THREAD_OPTION_PTHREAD_IMPL) #if VMIME_GNUTLS_NEEDS_GCRYPT gcry_control(GCRYCTL_SET_THREAD_CBS, &gcry_threads_pthread); @@ -104,8 +104,8 @@ struct TLSGlobal gnutls_certificate_allocate_credentials(&certCred); } - ~TLSGlobal() - { + ~TLSGlobal() { + gnutls_anon_free_client_credentials(anonCred); gnutls_certificate_free_credentials(certCred); @@ -114,8 +114,8 @@ struct TLSGlobal #if VMIME_DEBUG && GNUTLS_DEBUG - static void TLSLogFunc(int level, const char *str) - { + static void TLSLogFunc(int level, const char *str) { + std::cerr << "GNUTLS: [" << level << "] " << str << std::endl; } @@ -134,21 +134,29 @@ static TLSGlobal g_gnutlsGlobal; // static -shared_ptr <TLSSession> TLSSession::create(shared_ptr <security::cert::certificateVerifier> cv, shared_ptr <TLSProperties> props) -{ +shared_ptr <TLSSession> TLSSession::create( + const shared_ptr <security::cert::certificateVerifier>& cv, + const shared_ptr <TLSProperties>& props +) { + return make_shared <TLSSession_GnuTLS>(cv, props); } -TLSSession_GnuTLS::TLSSession_GnuTLS(shared_ptr <security::cert::certificateVerifier> cv, shared_ptr <TLSProperties> props) - : m_certVerifier(cv), m_props(props) -{ +TLSSession_GnuTLS::TLSSession_GnuTLS( + const shared_ptr <security::cert::certificateVerifier>& cv, + const shared_ptr <TLSProperties>& props +) + : m_certVerifier(cv), + m_props(props) { + int res; m_gnutlsSession = new gnutls_session_t; - if (gnutls_init(m_gnutlsSession, GNUTLS_CLIENT) != 0) + if (gnutls_init(m_gnutlsSession, GNUTLS_CLIENT) != 0) { throw std::bad_alloc(); + } // Sets some default priority on the ciphers, key exchange methods, // macs and compression methods. @@ -156,8 +164,8 @@ TLSSession_GnuTLS::TLSSession_GnuTLS(shared_ptr <security::cert::certificateVeri gnutls_dh_set_prime_bits(*m_gnutlsSession, 128); if ((res = gnutls_priority_set_direct - (*m_gnutlsSession, m_props->getCipherSuite().c_str(), NULL)) != 0) - { + (*m_gnutlsSession, m_props->getCipherSuite().c_str(), NULL)) != 0) { + throwTLSException("gnutls_priority_set_direct", res); } @@ -170,13 +178,10 @@ TLSSession_GnuTLS::TLSSession_GnuTLS(shared_ptr <security::cert::certificateVeri // specifying the types you want, you must append a 0. const int certTypePriority[] = { GNUTLS_CRT_X509, 0 }; - res = gnutls_certificate_type_set_priority - (*m_gnutlsSession, certTypePriority); + res = gnutls_certificate_type_set_priority(*m_gnutlsSession, certTypePriority); - if (res < 0) - { - throwTLSException - ("gnutls_certificate_type_set_priority", res); + if (res < 0) { + throwTLSException("gnutls_certificate_type_set_priority", res); } // Sets the priority on the protocol types @@ -184,15 +189,12 @@ TLSSession_GnuTLS::TLSSession_GnuTLS(shared_ptr <security::cert::certificateVeri res = gnutls_protocol_set_priority(*m_gnutlsSession, protoPriority); - if (res < 0) - { - throwTLSException - ("gnutls_certificate_type_set_priority", res); + if (res < 0) { + throwTLSException("gnutls_certificate_type_set_priority", res); } // Priority on the ciphers - const int cipherPriority[] = - { + const int cipherPriority[] = { GNUTLS_CIPHER_ARCFOUR_128, GNUTLS_CIPHER_3DES_CBC, GNUTLS_CIPHER_AES_128_CBC, @@ -206,13 +208,16 @@ TLSSession_GnuTLS::TLSSession_GnuTLS(shared_ptr <security::cert::certificateVeri gnutls_cipher_set_priority(*m_gnutlsSession, cipherPriority); // Priority on MACs - const int macPriority[] = { GNUTLS_MAC_SHA, GNUTLS_MAC_MD5, 0}; + const int macPriority[] = { + GNUTLS_MAC_SHA, + GNUTLS_MAC_MD5, + 0 + }; gnutls_mac_set_priority(*m_gnutlsSession, macPriority); // Priority on key exchange methods - const int kxPriority[] = - { + const int kxPriority[] = { GNUTLS_KX_RSA, GNUTLS_KX_DHE_DSS, GNUTLS_KX_DHE_RSA, @@ -227,8 +232,7 @@ TLSSession_GnuTLS::TLSSession_GnuTLS(shared_ptr <security::cert::certificateVeri gnutls_kx_set_priority(*m_gnutlsSession, kxPriority); // Priority on compression methods - const int compressionPriority[] = - { + const int compressionPriority[] = { GNUTLS_COMP_ZLIB, //GNUTLS_COMP_LZO, GNUTLS_COMP_NULL, @@ -240,54 +244,56 @@ TLSSession_GnuTLS::TLSSession_GnuTLS(shared_ptr <security::cert::certificateVeri #endif // !VMIME_HAVE_GNUTLS_PRIORITY_FUNCS // Initialize credentials - gnutls_credentials_set(*m_gnutlsSession, - GNUTLS_CRD_ANON, g_gnutlsGlobal.anonCred); + gnutls_credentials_set( + *m_gnutlsSession, GNUTLS_CRD_ANON, g_gnutlsGlobal.anonCred + ); - gnutls_credentials_set(*m_gnutlsSession, - GNUTLS_CRD_CERTIFICATE, g_gnutlsGlobal.certCred); + gnutls_credentials_set( + *m_gnutlsSession, GNUTLS_CRD_CERTIFICATE, g_gnutlsGlobal.certCred + ); } TLSSession_GnuTLS::TLSSession_GnuTLS(const TLSSession_GnuTLS&) - : TLSSession() -{ + : TLSSession() { + // Not used } -TLSSession_GnuTLS::~TLSSession_GnuTLS() -{ - try - { - if (m_gnutlsSession) - { +TLSSession_GnuTLS::~TLSSession_GnuTLS() { + + try { + + if (m_gnutlsSession) { + gnutls_deinit(*m_gnutlsSession); delete m_gnutlsSession; m_gnutlsSession = NULL; } - } - catch (...) - { + + } catch (...) { + // Don't throw in destructor } } -shared_ptr <TLSSocket> TLSSession_GnuTLS::getSocket(shared_ptr <socket> sok) -{ +shared_ptr <TLSSocket> TLSSession_GnuTLS::getSocket(const shared_ptr <socket>& sok) { + return TLSSocket::wrap(dynamicCast <TLSSession>(shared_from_this()), sok); } -shared_ptr <security::cert::certificateVerifier> TLSSession_GnuTLS::getCertificateVerifier() -{ +shared_ptr <security::cert::certificateVerifier> TLSSession_GnuTLS::getCertificateVerifier() { + return m_certVerifier; } -void TLSSession_GnuTLS::throwTLSException(const string& fname, const int code) -{ +void TLSSession_GnuTLS::throwTLSException(const string& fname, const int code) { + std::ostringstream msg; msg << fname + "() returned code "; diff --git a/src/vmime/net/tls/gnutls/TLSSession_GnuTLS.hpp b/src/vmime/net/tls/gnutls/TLSSession_GnuTLS.hpp index 14172ee0..2a7f9d7f 100644 --- a/src/vmime/net/tls/gnutls/TLSSession_GnuTLS.hpp +++ b/src/vmime/net/tls/gnutls/TLSSession_GnuTLS.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard <[email protected]> +// Copyright (C) 2002 Vincent Richard <[email protected]> // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License as @@ -46,17 +46,21 @@ namespace net { namespace tls { -class TLSSession_GnuTLS : public TLSSession -{ +class TLSSession_GnuTLS : public TLSSession { + friend class TLSSocket_GnuTLS; public: - TLSSession_GnuTLS(shared_ptr <security::cert::certificateVerifier> cv, shared_ptr <TLSProperties> props); + TLSSession_GnuTLS( + const shared_ptr <security::cert::certificateVerifier>& cv, + const shared_ptr <TLSProperties>& props + ); + ~TLSSession_GnuTLS(); - shared_ptr <TLSSocket> getSocket(shared_ptr <socket> sok); + shared_ptr <TLSSocket> getSocket(const shared_ptr <socket>& sok); shared_ptr <security::cert::certificateVerifier> getCertificateVerifier(); diff --git a/src/vmime/net/tls/gnutls/TLSSocket_GnuTLS.cpp b/src/vmime/net/tls/gnutls/TLSSocket_GnuTLS.cpp index 16dabb66..73d52231 100644 --- a/src/vmime/net/tls/gnutls/TLSSocket_GnuTLS.cpp +++ b/src/vmime/net/tls/gnutls/TLSSocket_GnuTLS.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard <[email protected]> +// Copyright (C) 2002 Vincent Richard <[email protected]> // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License as @@ -50,17 +50,26 @@ namespace tls { // static -shared_ptr <TLSSocket> TLSSocket::wrap(shared_ptr <TLSSession> session, shared_ptr <socket> sok) +shared_ptr <TLSSocket> TLSSocket::wrap( + const shared_ptr <TLSSession>& session, + const shared_ptr <socket>& sok +) { - return make_shared <TLSSocket_GnuTLS> - (dynamicCast <TLSSession_GnuTLS>(session), sok); + return make_shared <TLSSocket_GnuTLS>(dynamicCast <TLSSession_GnuTLS>(session), sok); } -TLSSocket_GnuTLS::TLSSocket_GnuTLS(shared_ptr <TLSSession_GnuTLS> session, shared_ptr <socket> sok) - : m_session(session), m_wrapped(sok), m_connected(false), - m_ex(NULL), m_status(0), m_errno(0) -{ +TLSSocket_GnuTLS::TLSSocket_GnuTLS( + const shared_ptr <TLSSession_GnuTLS>& session, + const shared_ptr <socket>& sok +) + : m_session(session), + m_wrapped(sok), + m_connected(false), + m_ex(NULL), + m_status(0), + m_errno(0) { + gnutls_transport_set_ptr(*m_session->m_gnutlsSession, this); gnutls_transport_set_push_function(*m_session->m_gnutlsSession, gnutlsPushFunc); @@ -69,41 +78,38 @@ TLSSocket_GnuTLS::TLSSocket_GnuTLS(shared_ptr <TLSSession_GnuTLS> session, share } -TLSSocket_GnuTLS::~TLSSocket_GnuTLS() -{ +TLSSocket_GnuTLS::~TLSSocket_GnuTLS() { + resetException(); - try - { + try { disconnect(); - } - catch (...) - { + } catch (...) { // Don't throw exception in destructor } } -void TLSSocket_GnuTLS::connect(const string& address, const port_t port) -{ - try - { +void TLSSocket_GnuTLS::connect(const string& address, const port_t port) { + + try { + m_wrapped->connect(address, port); handshake(); - } - catch (...) - { + + } catch (...) { + disconnect(); throw; } } -void TLSSocket_GnuTLS::disconnect() -{ - if (m_connected) - { +void TLSSocket_GnuTLS::disconnect() { + + if (m_connected) { + gnutls_bye(*m_session->m_gnutlsSession, GNUTLS_SHUT_RDWR); m_wrapped->disconnect(); @@ -113,99 +119,101 @@ void TLSSocket_GnuTLS::disconnect() } -bool TLSSocket_GnuTLS::isConnected() const -{ +bool TLSSocket_GnuTLS::isConnected() const { + return m_wrapped->isConnected() && m_connected; } -size_t TLSSocket_GnuTLS::getBlockSize() const -{ +size_t TLSSocket_GnuTLS::getBlockSize() const { + return 16384; // 16 KB } -const string TLSSocket_GnuTLS::getPeerName() const -{ +const string TLSSocket_GnuTLS::getPeerName() const { + return m_wrapped->getPeerName(); } -const string TLSSocket_GnuTLS::getPeerAddress() const -{ +const string TLSSocket_GnuTLS::getPeerAddress() const { + return m_wrapped->getPeerAddress(); } -shared_ptr <timeoutHandler> TLSSocket_GnuTLS::getTimeoutHandler() -{ +shared_ptr <timeoutHandler> TLSSocket_GnuTLS::getTimeoutHandler() { + return m_wrapped->getTimeoutHandler(); } -void TLSSocket_GnuTLS::setTracer(shared_ptr <net::tracer> tracer) -{ +void TLSSocket_GnuTLS::setTracer(const shared_ptr <net::tracer>& tracer) { + m_wrapped->setTracer(tracer); } -shared_ptr <net::tracer> TLSSocket_GnuTLS::getTracer() -{ +shared_ptr <net::tracer> TLSSocket_GnuTLS::getTracer() { + return m_wrapped->getTracer(); } -bool TLSSocket_GnuTLS::waitForRead(const int msecs) -{ +bool TLSSocket_GnuTLS::waitForRead(const int msecs) { + return m_wrapped->waitForRead(msecs); } -bool TLSSocket_GnuTLS::waitForWrite(const int msecs) -{ +bool TLSSocket_GnuTLS::waitForWrite(const int msecs) { + return m_wrapped->waitForWrite(msecs); } -void TLSSocket_GnuTLS::receive(string& buffer) -{ +void TLSSocket_GnuTLS::receive(string& buffer) { + const size_t size = receiveRaw(m_buffer, sizeof(m_buffer)); buffer = utility::stringUtils::makeStringFromBytes(m_buffer, size); } -void TLSSocket_GnuTLS::send(const string& buffer) -{ +void TLSSocket_GnuTLS::send(const string& buffer) { + sendRaw(reinterpret_cast <const byte_t*>(buffer.data()), buffer.length()); } -void TLSSocket_GnuTLS::send(const char* str) -{ +void TLSSocket_GnuTLS::send(const char* str) { + sendRaw(reinterpret_cast <const byte_t*>(str), ::strlen(str)); } -size_t TLSSocket_GnuTLS::receiveRaw(byte_t* buffer, const size_t count) -{ +size_t TLSSocket_GnuTLS::receiveRaw(byte_t* buffer, const size_t count) { + m_status &= ~(STATUS_WANT_WRITE | STATUS_WANT_READ); resetException(); - const ssize_t ret = gnutls_record_recv - (*m_session->m_gnutlsSession, - buffer, static_cast <size_t>(count)); + const ssize_t ret = gnutls_record_recv( + *m_session->m_gnutlsSession, + buffer, static_cast <size_t>(count) + ); throwException(); - if (ret < 0) - { - if (ret == GNUTLS_E_AGAIN) - { - if (gnutls_record_get_direction(*m_session->m_gnutlsSession) == 0) + if (ret < 0) { + + if (ret == GNUTLS_E_AGAIN) { + + if (gnutls_record_get_direction(*m_session->m_gnutlsSession) == 0) { m_status |= STATUS_WANT_READ; - else + } else { m_status |= STATUS_WANT_WRITE; + } return 0; } @@ -217,36 +225,38 @@ size_t TLSSocket_GnuTLS::receiveRaw(byte_t* buffer, const size_t count) } -void TLSSocket_GnuTLS::sendRaw(const byte_t* buffer, const size_t count) -{ +void TLSSocket_GnuTLS::sendRaw(const byte_t* buffer, const size_t count) { + m_status &= ~(STATUS_WANT_WRITE | STATUS_WANT_READ); - for (size_t size = count ; size > 0 ; ) - { + for (size_t size = count ; size > 0 ; ) { + resetException(); - ssize_t ret = gnutls_record_send - (*m_session->m_gnutlsSession, - buffer, static_cast <size_t>(size)); + ssize_t ret = gnutls_record_send( + *m_session->m_gnutlsSession, + buffer, static_cast <size_t>(size) + ); throwException(); - if (ret < 0) - { - if (ret == GNUTLS_E_AGAIN) - { - if (gnutls_record_get_direction(*m_session->m_gnutlsSession) == 0) + if (ret < 0) { + + if (ret == GNUTLS_E_AGAIN) { + + if (gnutls_record_get_direction(*m_session->m_gnutlsSession) == 0) { m_wrapped->waitForRead(); - else + } else { m_wrapped->waitForWrite(); + } continue; } TLSSession_GnuTLS::throwTLSException("gnutls_record_send", static_cast <int>(ret)); - } - else - { + + } else { + buffer += ret; size -= ret; } @@ -254,26 +264,28 @@ void TLSSocket_GnuTLS::sendRaw(const byte_t* buffer, const size_t count) } -size_t TLSSocket_GnuTLS::sendRawNonBlocking(const byte_t* buffer, const size_t count) -{ +size_t TLSSocket_GnuTLS::sendRawNonBlocking(const byte_t* buffer, const size_t count) { + m_status &= ~(STATUS_WANT_WRITE | STATUS_WANT_READ); resetException(); - ssize_t ret = gnutls_record_send - (*m_session->m_gnutlsSession, - buffer, static_cast <size_t>(count)); + ssize_t ret = gnutls_record_send( + *m_session->m_gnutlsSession, + buffer, static_cast <size_t>(count) + ); throwException(); - if (ret < 0) - { - if (ret == GNUTLS_E_AGAIN) - { - if (gnutls_record_get_direction(*m_session->m_gnutlsSession) == 0) + if (ret < 0) { + + if (ret == GNUTLS_E_AGAIN) { + + if (gnutls_record_get_direction(*m_session->m_gnutlsSession) == 0) { m_status |= STATUS_WANT_READ; - else + } else { m_status |= STATUS_WANT_WRITE; + } return 0; } @@ -285,68 +297,72 @@ size_t TLSSocket_GnuTLS::sendRawNonBlocking(const byte_t* buffer, const size_t c } -unsigned int TLSSocket_GnuTLS::getStatus() const -{ +unsigned int TLSSocket_GnuTLS::getStatus() const { + return m_status | m_wrapped->getStatus(); } -void TLSSocket_GnuTLS::handshake() -{ +void TLSSocket_GnuTLS::handshake() { + shared_ptr <timeoutHandler> toHandler = m_wrapped->getTimeoutHandler(); - if (toHandler) + if (toHandler) { toHandler->resetTimeOut(); + } - if (getTracer()) + if (getTracer()) { getTracer()->traceSend("Beginning SSL/TLS handshake"); + } // Start handshaking process - try - { - while (true) - { + try { + + while (true) { + resetException(); const int ret = gnutls_handshake(*m_session->m_gnutlsSession); throwException(); - if (ret < 0) - { - if (ret == GNUTLS_E_AGAIN) - { - if (gnutls_record_get_direction(*m_session->m_gnutlsSession) == 0) + if (ret < 0) { + + if (ret == GNUTLS_E_AGAIN) { + + if (gnutls_record_get_direction(*m_session->m_gnutlsSession) == 0) { m_wrapped->waitForRead(); - else + } else { m_wrapped->waitForWrite(); - } - else if (ret == GNUTLS_E_INTERRUPTED) - { + } + + } else if (ret == GNUTLS_E_INTERRUPTED) { + // Non-fatal error - } - else - { + + } else { + TLSSession_GnuTLS::throwTLSException("gnutls_handshake", ret); } - } - else - { + + } else { + // Successful handshake break; } } - } - catch (...) - { + + } catch (...) { + throw; } // Verify server's certificate(s) shared_ptr <security::cert::certificateChain> certs = getPeerCertificates(); - if (certs == NULL) + if (certs == NULL) { throw exceptions::tls_exception("No peer certificate."); + } m_session->getCertificateVerifier()->verify(certs, getPeerName()); @@ -354,35 +370,38 @@ void TLSSocket_GnuTLS::handshake() } -int TLSSocket_GnuTLS::gnutlsErrnoFunc(gnutls_transport_ptr_t trspt) -{ +int TLSSocket_GnuTLS::gnutlsErrnoFunc(gnutls_transport_ptr_t trspt) { + TLSSocket_GnuTLS* sok = reinterpret_cast <TLSSocket_GnuTLS*>(trspt); return sok->m_errno; } -ssize_t TLSSocket_GnuTLS::gnutlsPushFunc - (gnutls_transport_ptr_t trspt, const void* data, size_t len) -{ +ssize_t TLSSocket_GnuTLS::gnutlsPushFunc( + gnutls_transport_ptr_t trspt, + const void* data, + size_t len +) { + TLSSocket_GnuTLS* sok = reinterpret_cast <TLSSocket_GnuTLS*>(trspt); - try - { - const ssize_t ret = static_cast <ssize_t> - (sok->m_wrapped->sendRawNonBlocking - (reinterpret_cast <const byte_t*>(data), len)); + try { + + const ssize_t ret = static_cast <ssize_t>( + sok->m_wrapped->sendRawNonBlocking(reinterpret_cast <const byte_t*>(data), len) + ); + + if (ret == 0) { - if (ret == 0) - { gnutls_transport_set_errno(*sok->m_session->m_gnutlsSession, EAGAIN); sok->m_errno = EAGAIN; return -1; } return ret; - } - catch (exception& e) - { + + } catch (exception& e) { + // Workaround for non-portable behaviour when throwing C++ exceptions // from C functions (GNU TLS) sok->m_ex = e.clone(); @@ -391,28 +410,31 @@ ssize_t TLSSocket_GnuTLS::gnutlsPushFunc } -ssize_t TLSSocket_GnuTLS::gnutlsPullFunc - (gnutls_transport_ptr_t trspt, void* data, size_t len) -{ +ssize_t TLSSocket_GnuTLS::gnutlsPullFunc( + gnutls_transport_ptr_t trspt, + void* data, + size_t len +) { + TLSSocket_GnuTLS* sok = reinterpret_cast <TLSSocket_GnuTLS*>(trspt); - try - { - const ssize_t n = static_cast <ssize_t> - (sok->m_wrapped->receiveRaw - (reinterpret_cast <byte_t*>(data), len)); + try { + + const ssize_t n = static_cast <ssize_t>( + sok->m_wrapped->receiveRaw(reinterpret_cast <byte_t*>(data), len) + ); + + if (n == 0) { - if (n == 0) - { gnutls_transport_set_errno(*sok->m_session->m_gnutlsSession, EAGAIN); sok->m_errno = EAGAIN; return -1; } return n; - } - catch (exception& e) - { + + } catch (exception& e) { + // Workaround for non-portable behaviour when throwing C++ exceptions // from C functions (GNU TLS) sok->m_ex = e.clone(); @@ -421,74 +443,74 @@ ssize_t TLSSocket_GnuTLS::gnutlsPullFunc } -shared_ptr <security::cert::certificateChain> TLSSocket_GnuTLS::getPeerCertificates() -{ - if (getTracer()) +shared_ptr <security::cert::certificateChain> TLSSocket_GnuTLS::getPeerCertificates() { + + if (getTracer()) { getTracer()->traceSend("Getting peer certificates"); + } unsigned int certCount = 0; - const gnutls_datum_t* rawData = gnutls_certificate_get_peers - (*m_session->m_gnutlsSession, &certCount); + const gnutls_datum_t* rawData = gnutls_certificate_get_peers( + *m_session->m_gnutlsSession, &certCount + ); - if (rawData == NULL) + if (rawData == NULL) { return null; + } // Try X.509 gnutls_x509_crt_t* x509Certs = new gnutls_x509_crt_t[certCount]; - for (unsigned int i = 0; i < certCount; ++i) - { + for (unsigned int i = 0; i < certCount; ++i) { + gnutls_x509_crt_init(x509Certs + i); - int res = gnutls_x509_crt_import(x509Certs[i], rawData + i, - GNUTLS_X509_FMT_DER); + int res = gnutls_x509_crt_import(x509Certs[i], rawData + i, GNUTLS_X509_FMT_DER); + + if (res < 0) { + + for (unsigned int j = 0 ; j <= i ; ++j) { + gnutls_x509_crt_deinit(x509Certs[j]); + } - if (res < 0) - { // XXX more fine-grained error reporting? delete [] x509Certs; return null; } } - { - std::vector <shared_ptr <security::cert::certificate> > certs; - bool error = false; + std::vector <shared_ptr <security::cert::certificate> > certs; + bool error = false; - for (unsigned int i = 0 ; i < certCount ; ++i) - { - size_t dataSize = 0; + for (unsigned int i = 0 ; i < certCount ; ++i) { - gnutls_x509_crt_export(x509Certs[i], - GNUTLS_X509_FMT_DER, NULL, &dataSize); + size_t dataSize = 0; - std::vector <byte_t> data(dataSize); + gnutls_x509_crt_export(x509Certs[i], GNUTLS_X509_FMT_DER, NULL, &dataSize); - gnutls_x509_crt_export(x509Certs[i], - GNUTLS_X509_FMT_DER, &data[0], &dataSize); + std::vector <byte_t> data(dataSize); - shared_ptr <security::cert::X509Certificate> cert = - security::cert::X509Certificate::import(&data[0], dataSize); + gnutls_x509_crt_export(x509Certs[i], GNUTLS_X509_FMT_DER, &data[0], &dataSize); - if (cert != NULL) - certs.push_back(cert); - else - error = true; + shared_ptr <security::cert::X509Certificate> cert = + security::cert::X509Certificate::import(&data[0], dataSize); - gnutls_x509_crt_deinit(x509Certs[i]); + if (cert != NULL) { + certs.push_back(cert); + } else { + error = true; } - delete [] x509Certs; - - if (error) - return null; - - return make_shared <security::cert::certificateChain>(certs); + gnutls_x509_crt_deinit(x509Certs[i]); } delete [] x509Certs; - return null; + if (error) { + return null; + } + + return make_shared <security::cert::certificateChain>(certs); } @@ -498,19 +520,17 @@ shared_ptr <security::cert::certificateChain> TLSSocket_GnuTLS::getPeerCertifica // gnutls_record_recv() calls TLSSocket::gnutlsPullFunc, and exceptions // thrown by the socket can not be caught. -void TLSSocket_GnuTLS::throwException() -{ - if (m_ex) - { +void TLSSocket_GnuTLS::throwException() { + + if (m_ex) { throw *m_ex; } } -void TLSSocket_GnuTLS::resetException() -{ - if (m_ex) - { +void TLSSocket_GnuTLS::resetException() { + + if (m_ex) { delete m_ex; m_ex = NULL; } diff --git a/src/vmime/net/tls/gnutls/TLSSocket_GnuTLS.hpp b/src/vmime/net/tls/gnutls/TLSSocket_GnuTLS.hpp index 931cb993..0ac3e700 100644 --- a/src/vmime/net/tls/gnutls/TLSSocket_GnuTLS.hpp +++ b/src/vmime/net/tls/gnutls/TLSSocket_GnuTLS.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard <[email protected]> +// Copyright (C) 2002 Vincent Richard <[email protected]> // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License as @@ -46,11 +46,11 @@ class TLSSession; class TLSSession_GnuTLS; -class TLSSocket_GnuTLS : public TLSSocket -{ +class TLSSocket_GnuTLS : public TLSSocket { + public: - TLSSocket_GnuTLS(shared_ptr <TLSSession_GnuTLS> session, shared_ptr <socket> sok); + TLSSocket_GnuTLS(const shared_ptr <TLSSession_GnuTLS>& session, const shared_ptr <socket>& sok); ~TLSSocket_GnuTLS(); @@ -83,7 +83,7 @@ public: shared_ptr <timeoutHandler> getTimeoutHandler(); - void setTracer(shared_ptr <net::tracer> tracer); + void setTracer(const shared_ptr <net::tracer>& tracer); shared_ptr <net::tracer> getTracer(); private: diff --git a/src/vmime/net/tls/openssl/OpenSSLInitializer.cpp b/src/vmime/net/tls/openssl/OpenSSLInitializer.cpp index 1bbb9ee5..74474480 100644 --- a/src/vmime/net/tls/openssl/OpenSSLInitializer.cpp +++ b/src/vmime/net/tls/openssl/OpenSSLInitializer.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard <[email protected]> +// Copyright (C) 2002 Vincent Richard <[email protected]> // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License as @@ -52,34 +52,34 @@ namespace tls { shared_ptr <vmime::utility::sync::criticalSection >* OpenSSLInitializer::sm_mutexes; -OpenSSLInitializer::autoInitializer::autoInitializer() -{ +OpenSSLInitializer::autoInitializer::autoInitializer() { + // The construction of this unique 'oneTimeInitializer' object will be triggered // by the 'autoInitializer' objects from the other translation units static OpenSSLInitializer::oneTimeInitializer oneTimeInitializer; } -OpenSSLInitializer::autoInitializer::~autoInitializer() -{ +OpenSSLInitializer::autoInitializer::~autoInitializer() { + } -OpenSSLInitializer::oneTimeInitializer::oneTimeInitializer() -{ +OpenSSLInitializer::oneTimeInitializer::oneTimeInitializer() { + initialize(); } -OpenSSLInitializer::oneTimeInitializer::~oneTimeInitializer() -{ +OpenSSLInitializer::oneTimeInitializer::~oneTimeInitializer() { + uninitialize(); } // static -void OpenSSLInitializer::initialize() -{ +void OpenSSLInitializer::initialize() { + #if OPENSSL_VERSION_NUMBER >= 0x0907000L OPENSSL_config(NULL); #endif @@ -95,8 +95,9 @@ void OpenSSLInitializer::initialize() int numMutexes = CRYPTO_num_locks(); sm_mutexes = new shared_ptr <vmime::utility::sync::criticalSection>[numMutexes]; - for (int i = 0 ; i < numMutexes ; ++i) + for (int i = 0 ; i < numMutexes ; ++i) { sm_mutexes[i] = vmime::platform::getHandler()->createCriticalSection(); + } CRYPTO_set_locking_callback(&OpenSSLInitializer::lock); CRYPTO_set_id_callback(&OpenSSLInitializer::id); @@ -104,8 +105,8 @@ void OpenSSLInitializer::initialize() // static -void OpenSSLInitializer::uninitialize() -{ +void OpenSSLInitializer::uninitialize() { + EVP_cleanup(); ERR_free_strings(); @@ -117,18 +118,19 @@ void OpenSSLInitializer::uninitialize() // static -void OpenSSLInitializer::lock(int mode, int n, const char* /* file */, int /* line */) -{ - if (mode & CRYPTO_LOCK) +void OpenSSLInitializer::lock(int mode, int n, const char* /* file */, int /* line */) { + + if (mode & CRYPTO_LOCK) { sm_mutexes[n]->lock(); - else + } else { sm_mutexes[n]->unlock(); + } } // static -unsigned long OpenSSLInitializer::id() -{ +unsigned long OpenSSLInitializer::id() { + return vmime::platform::getHandler()->getThreadId(); } diff --git a/src/vmime/net/tls/openssl/OpenSSLInitializer.hpp b/src/vmime/net/tls/openssl/OpenSSLInitializer.hpp index d7595aa8..b07c2e61 100644 --- a/src/vmime/net/tls/openssl/OpenSSLInitializer.hpp +++ b/src/vmime/net/tls/openssl/OpenSSLInitializer.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard <[email protected]> +// Copyright (C) 2002 Vincent Richard <[email protected]> // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License as @@ -46,15 +46,13 @@ namespace tls { /** Class responsible for setting up OpenSSL */ -class OpenSSLInitializer -{ +class OpenSSLInitializer { + public: /** Automatically initialize OpenSSL */ - class autoInitializer - { - public: + struct autoInitializer { autoInitializer(); ~autoInitializer(); @@ -62,9 +60,7 @@ public: protected: - class oneTimeInitializer - { - public: + struct oneTimeInitializer { oneTimeInitializer(); ~oneTimeInitializer(); @@ -82,8 +78,7 @@ protected: static shared_ptr <vmime::utility::sync::criticalSection> getMutex(); - enum - { + enum { SEEDSIZE = 256 }; diff --git a/src/vmime/net/tls/openssl/TLSProperties_OpenSSL.cpp b/src/vmime/net/tls/openssl/TLSProperties_OpenSSL.cpp index 932477df..ea22f1cd 100644 --- a/src/vmime/net/tls/openssl/TLSProperties_OpenSSL.cpp +++ b/src/vmime/net/tls/openssl/TLSProperties_OpenSSL.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard <[email protected]> +// Copyright (C) 2002 Vincent Richard <[email protected]> // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License as @@ -40,63 +40,63 @@ namespace tls { TLSProperties::TLSProperties() - : m_data(make_shared <TLSProperties_OpenSSL>()) -{ + : m_data(make_shared <TLSProperties_OpenSSL>()) { + setCipherSuite(CIPHERSUITE_DEFAULT); } TLSProperties::TLSProperties(const TLSProperties& props) : object(), - m_data(make_shared <TLSProperties_OpenSSL>()) -{ + m_data(make_shared <TLSProperties_OpenSSL>()) { + *dynamicCast <TLSProperties_OpenSSL>(m_data) = *dynamicCast <TLSProperties_OpenSSL>(props.m_data); } -void TLSProperties::setCipherSuite(const GenericCipherSuite cipherSuite) -{ - switch (cipherSuite) - { - case CIPHERSUITE_HIGH: +void TLSProperties::setCipherSuite(const GenericCipherSuite cipherSuite) { + + switch (cipherSuite) { + + case CIPHERSUITE_HIGH: - setCipherSuite("HIGH:!ADH:@STRENGTH"); - break; + setCipherSuite("HIGH:!ADH:@STRENGTH"); + break; - case CIPHERSUITE_MEDIUM: + case CIPHERSUITE_MEDIUM: - setCipherSuite("MEDIUM:!ADH:@STRENGTH"); - break; + setCipherSuite("MEDIUM:!ADH:@STRENGTH"); + break; - case CIPHERSUITE_LOW: + case CIPHERSUITE_LOW: - setCipherSuite("LOW:!ADH:@STRENGTH"); - break; + setCipherSuite("LOW:!ADH:@STRENGTH"); + break; - default: - case CIPHERSUITE_DEFAULT: + default: + case CIPHERSUITE_DEFAULT: - setCipherSuite("DEFAULT:!ADH:@STRENGTH"); - break; + setCipherSuite("DEFAULT:!ADH:@STRENGTH"); + break; } } -void TLSProperties::setCipherSuite(const string& cipherSuite) -{ +void TLSProperties::setCipherSuite(const string& cipherSuite) { + dynamicCast <TLSProperties_OpenSSL>(m_data)->cipherSuite = cipherSuite; } -const string TLSProperties::getCipherSuite() const -{ +const string TLSProperties::getCipherSuite() const { + return dynamicCast <TLSProperties_OpenSSL>(m_data)->cipherSuite; } -TLSProperties_OpenSSL& TLSProperties_OpenSSL::operator=(const TLSProperties_OpenSSL& other) -{ +TLSProperties_OpenSSL& TLSProperties_OpenSSL::operator=(const TLSProperties_OpenSSL& other) { + cipherSuite = other.cipherSuite; return *this; diff --git a/src/vmime/net/tls/openssl/TLSProperties_OpenSSL.hpp b/src/vmime/net/tls/openssl/TLSProperties_OpenSSL.hpp index 5d2f075a..8304df23 100644 --- a/src/vmime/net/tls/openssl/TLSProperties_OpenSSL.hpp +++ b/src/vmime/net/tls/openssl/TLSProperties_OpenSSL.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard <[email protected]> +// Copyright (C) 2002 Vincent Richard <[email protected]> // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License as @@ -44,8 +44,8 @@ namespace net { namespace tls { -class TLSProperties_OpenSSL : public object -{ +class TLSProperties_OpenSSL : public object { + public: TLSProperties_OpenSSL& operator=(const TLSProperties_OpenSSL& other); diff --git a/src/vmime/net/tls/openssl/TLSSession_OpenSSL.cpp b/src/vmime/net/tls/openssl/TLSSession_OpenSSL.cpp index 7892de65..019341c7 100644 --- a/src/vmime/net/tls/openssl/TLSSession_OpenSSL.cpp +++ b/src/vmime/net/tls/openssl/TLSSession_OpenSSL.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard <[email protected]> +// Copyright (C) 2002 Vincent Richard <[email protected]> // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License as @@ -46,15 +46,23 @@ static OpenSSLInitializer::autoInitializer openSSLInitializer; // static -shared_ptr <TLSSession> TLSSession::create(shared_ptr <security::cert::certificateVerifier> cv, shared_ptr <TLSProperties> props) -{ +shared_ptr <TLSSession> TLSSession::create( + const shared_ptr <security::cert::certificateVerifier>& cv, + const shared_ptr <TLSProperties>& props +) { + return make_shared <TLSSession_OpenSSL>(cv, props); } -TLSSession_OpenSSL::TLSSession_OpenSSL(shared_ptr <vmime::security::cert::certificateVerifier> cv, shared_ptr <TLSProperties> props) - : m_sslctx(0), m_certVerifier(cv), m_props(props) -{ +TLSSession_OpenSSL::TLSSession_OpenSSL( + const shared_ptr <vmime::security::cert::certificateVerifier>& cv, + const shared_ptr <TLSProperties>& props +) + : m_sslctx(0), + m_certVerifier(cv), + m_props(props) { + m_sslctx = SSL_CTX_new(SSLv23_client_method()); SSL_CTX_set_options(m_sslctx, SSL_OP_ALL | SSL_OP_NO_SSLv2); SSL_CTX_set_mode(m_sslctx, SSL_MODE_AUTO_RETRY); @@ -64,36 +72,36 @@ TLSSession_OpenSSL::TLSSession_OpenSSL(shared_ptr <vmime::security::cert::certif TLSSession_OpenSSL::TLSSession_OpenSSL(const TLSSession_OpenSSL&) - : TLSSession() -{ + : TLSSession() { + // Not used } -TLSSession_OpenSSL::~TLSSession_OpenSSL() -{ +TLSSession_OpenSSL::~TLSSession_OpenSSL() { + SSL_CTX_free(m_sslctx); } -shared_ptr <TLSSocket> TLSSession_OpenSSL::getSocket(shared_ptr <socket> sok) -{ +shared_ptr <TLSSocket> TLSSession_OpenSSL::getSocket(const shared_ptr <socket>& sok) { + return TLSSocket::wrap(dynamicCast <TLSSession>(shared_from_this()), sok); } -shared_ptr <security::cert::certificateVerifier> TLSSession_OpenSSL::getCertificateVerifier() -{ +shared_ptr <security::cert::certificateVerifier> TLSSession_OpenSSL::getCertificateVerifier() { + return m_certVerifier; } -void TLSSession_OpenSSL::usePrivateKeyFile(const vmime::string& keyfile) -{ +void TLSSession_OpenSSL::usePrivateKeyFile(const vmime::string& keyfile) { + ERR_clear_error(); - if (SSL_CTX_use_PrivateKey_file(m_sslctx, keyfile.c_str(), SSL_FILETYPE_PEM) != 1) - { + if (SSL_CTX_use_PrivateKey_file(m_sslctx, keyfile.c_str(), SSL_FILETYPE_PEM) != 1) { + unsigned long errCode = ERR_get_error(); char buffer[256]; ERR_error_string_n(errCode, buffer, sizeof(buffer)); @@ -106,12 +114,12 @@ void TLSSession_OpenSSL::usePrivateKeyFile(const vmime::string& keyfile) } -void TLSSession_OpenSSL::useCertificateChainFile(const vmime::string& chainFile) -{ +void TLSSession_OpenSSL::useCertificateChainFile(const vmime::string& chainFile) { + ERR_clear_error(); - if (SSL_CTX_use_certificate_chain_file(m_sslctx, chainFile.c_str()) != 1) - { + if (SSL_CTX_use_certificate_chain_file(m_sslctx, chainFile.c_str()) != 1) { + unsigned long errCode = ERR_get_error(); char buffer[256]; ERR_error_string_n(errCode, buffer, sizeof(buffer)); @@ -124,8 +132,8 @@ void TLSSession_OpenSSL::useCertificateChainFile(const vmime::string& chainFile) } -SSL_CTX* TLSSession_OpenSSL::getContext() const -{ +SSL_CTX* TLSSession_OpenSSL::getContext() const { + return m_sslctx; } diff --git a/src/vmime/net/tls/openssl/TLSSession_OpenSSL.hpp b/src/vmime/net/tls/openssl/TLSSession_OpenSSL.hpp index 5a2b60a8..518216bc 100644 --- a/src/vmime/net/tls/openssl/TLSSession_OpenSSL.hpp +++ b/src/vmime/net/tls/openssl/TLSSession_OpenSSL.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard <[email protected]> +// Copyright (C) 2002 Vincent Richard <[email protected]> // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License as @@ -49,30 +49,32 @@ namespace net { namespace tls { -class TLSSession_OpenSSL : public TLSSession -{ +class TLSSession_OpenSSL : public TLSSession { + friend class TLSSocket_OpenSSL; public: - TLSSession_OpenSSL(const shared_ptr <security::cert::certificateVerifier> cv, shared_ptr <TLSProperties> props); + TLSSession_OpenSSL( + const shared_ptr <security::cert::certificateVerifier>& cv, + const shared_ptr <TLSProperties>& props + ); + ~TLSSession_OpenSSL(); - shared_ptr <TLSSocket> getSocket(shared_ptr <socket> sok); + shared_ptr <TLSSocket> getSocket(const shared_ptr <socket>& sok); shared_ptr <security::cert::certificateVerifier> getCertificateVerifier(); /** Set the private key to use if server requires a client certificate. * - * @param keyfile Path to the private key in PEM format - * @param passwd_callback If the private key is stored encrypted the + * @param keyfile path to the private key in PEM format */ void usePrivateKeyFile(const vmime::string& keyfile); - /** Supply the certificate chain to present if requested by - * server. + /** Supply the certificate chain to present if requested by server. * * @param chainFile File in PEM format holding certificate chain */ @@ -105,4 +107,3 @@ private: #endif // VMIME_BUILDING_DOC #endif // VMIME_NET_TLS_TLSSESSION_OPENSSL_HPP_INCLUDED - diff --git a/src/vmime/net/tls/openssl/TLSSocket_OpenSSL.cpp b/src/vmime/net/tls/openssl/TLSSocket_OpenSSL.cpp index a663f196..db782bb2 100644 --- a/src/vmime/net/tls/openssl/TLSSocket_OpenSSL.cpp +++ b/src/vmime/net/tls/openssl/TLSSocket_OpenSSL.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard <[email protected]> +// Copyright (C) 2002 Vincent Richard <[email protected]> // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License as @@ -52,9 +52,10 @@ namespace tls { static OpenSSLInitializer::autoInitializer openSSLInitializer; +#if OPENSSL_VERSION_NUMBER < 0x10100000L + // static -BIO_METHOD TLSSocket_OpenSSL::sm_customBIOMethod = -{ +BIO_METHOD TLSSocket_OpenSSL::sm_customBIOMethod = { 100 | BIO_TYPE_SOURCE_SINK, "vmime::socket glue", TLSSocket_OpenSSL::bio_write, @@ -67,46 +68,96 @@ BIO_METHOD TLSSocket_OpenSSL::sm_customBIOMethod = 0 }; +#define BIO_set_init(b, val) b->init = val +#define BIO_set_data(b, val) b->ptr = val +#define BIO_set_num(b, val) b->num = val +#define BIO_set_flags(b, val) b->flags = val +#define BIO_set_shutdown(b, val) b->shutdown = val +#define BIO_get_init(b) b->init +#define BIO_get_data(b) b->ptr +#define BIO_get_shutdown(b) b->shutdown + +#else + +#define BIO_set_num(b, val) + +#endif + + // static -shared_ptr <TLSSocket> TLSSocket::wrap(shared_ptr <TLSSession> session, shared_ptr <socket> sok) -{ - return make_shared <TLSSocket_OpenSSL> - (dynamicCast <TLSSession_OpenSSL>(session), sok); +shared_ptr <TLSSocket> TLSSocket::wrap( + const shared_ptr <TLSSession>& session, + const shared_ptr <socket>& sok +) { + + return make_shared <TLSSocket_OpenSSL>(dynamicCast <TLSSession_OpenSSL>(session), sok); } -TLSSocket_OpenSSL::TLSSocket_OpenSSL(shared_ptr <TLSSession_OpenSSL> session, shared_ptr <socket> sok) - : m_session(session), m_wrapped(sok), m_connected(false), m_ssl(0), m_status(0), m_ex() -{ +TLSSocket_OpenSSL::TLSSocket_OpenSSL( + const shared_ptr <TLSSession_OpenSSL>& session, + const shared_ptr <socket>& sok +) + : m_session(session), + m_wrapped(sok), + m_connected(false), + m_ssl(0), + m_status(0), + m_ex() { + } -TLSSocket_OpenSSL::~TLSSocket_OpenSSL() -{ - try - { +TLSSocket_OpenSSL::~TLSSocket_OpenSSL() { + + try { disconnect(); - } - catch (...) - { + } catch (...) { // Don't throw in destructor } } -void TLSSocket_OpenSSL::createSSLHandle() -{ - if (m_wrapped->isConnected()) - { +void TLSSocket_OpenSSL::createSSLHandle() { + + if (m_wrapped->isConnected()) { + +#if OPENSSL_VERSION_NUMBER < 0x10100000L + BIO* sockBio = BIO_new(&sm_customBIOMethod); sockBio->ptr = this; sockBio->init = 1; +#else + + BIO_METHOD* bioMeth = BIO_meth_new(BIO_TYPE_SOURCE_SINK | BIO_get_new_index(), "vmime::socket glue"); + + if (!bioMeth) { + BIO_meth_free(bioMeth); + throw exceptions::tls_exception("BIO_meth_new() failed"); + } + + BIO_meth_set_write(bioMeth, TLSSocket_OpenSSL::bio_write); + BIO_meth_set_read(bioMeth, TLSSocket_OpenSSL::bio_read); + BIO_meth_set_puts(bioMeth, TLSSocket_OpenSSL::bio_puts); + BIO_meth_set_ctrl(bioMeth, TLSSocket_OpenSSL::bio_ctrl); + BIO_meth_set_create(bioMeth, TLSSocket_OpenSSL::bio_create); + BIO_meth_set_destroy(bioMeth, TLSSocket_OpenSSL::bio_destroy); + + BIO* sockBio = BIO_new(bioMeth); + BIO_set_data(sockBio, this); + BIO_set_init(sockBio, 1); + +#endif + + if (!sockBio) { + throw exceptions::tls_exception("BIO_new() failed"); + } + m_ssl = SSL_new(m_session->getContext()); - if (!m_ssl) - { + if (!m_ssl) { BIO_free(sockBio); throw exceptions::tls_exception("Cannot create SSL object"); } @@ -114,156 +165,156 @@ void TLSSocket_OpenSSL::createSSLHandle() SSL_set_bio(m_ssl, sockBio, sockBio); SSL_set_connect_state(m_ssl); SSL_set_mode(m_ssl, SSL_MODE_AUTO_RETRY | SSL_MODE_ENABLE_PARTIAL_WRITE | SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER); - } - else - { + + } else { + throw exceptions::tls_exception("Unconnected socket error"); } } -void TLSSocket_OpenSSL::connect(const string& address, const port_t port) -{ - try - { +void TLSSocket_OpenSSL::connect(const string& address, const port_t port) { + + try { + m_wrapped->connect(address, port); createSSLHandle(); handshake(); - } - catch (...) - { + + } catch (...) { + disconnect(); throw; } } -void TLSSocket_OpenSSL::disconnect() -{ - if (m_ssl) - { +void TLSSocket_OpenSSL::disconnect() { + + if (m_ssl) { + // Don't shut down the socket more than once. int shutdownState = SSL_get_shutdown(m_ssl); bool shutdownSent = (shutdownState & SSL_SENT_SHUTDOWN) == SSL_SENT_SHUTDOWN; - if (!shutdownSent) + if (!shutdownSent) { SSL_shutdown(m_ssl); + } SSL_free(m_ssl); m_ssl = 0; } - if (m_connected) - { + if (m_connected) { m_connected = false; m_wrapped->disconnect(); } } -bool TLSSocket_OpenSSL::isConnected() const -{ +bool TLSSocket_OpenSSL::isConnected() const { + return m_wrapped->isConnected() && m_connected; } -size_t TLSSocket_OpenSSL::getBlockSize() const -{ +size_t TLSSocket_OpenSSL::getBlockSize() const { + return 16384; // 16 KB } -const string TLSSocket_OpenSSL::getPeerName() const -{ +const string TLSSocket_OpenSSL::getPeerName() const { + return m_wrapped->getPeerName(); } -const string TLSSocket_OpenSSL::getPeerAddress() const -{ +const string TLSSocket_OpenSSL::getPeerAddress() const { + return m_wrapped->getPeerAddress(); } -shared_ptr <timeoutHandler> TLSSocket_OpenSSL::getTimeoutHandler() -{ +shared_ptr <timeoutHandler> TLSSocket_OpenSSL::getTimeoutHandler() { + return m_wrapped->getTimeoutHandler(); } -void TLSSocket_OpenSSL::setTracer(shared_ptr <net::tracer> tracer) -{ +void TLSSocket_OpenSSL::setTracer(const shared_ptr <net::tracer>& tracer) { + m_wrapped->setTracer(tracer); } -shared_ptr <net::tracer> TLSSocket_OpenSSL::getTracer() -{ +shared_ptr <net::tracer> TLSSocket_OpenSSL::getTracer() { + return m_wrapped->getTracer(); } -bool TLSSocket_OpenSSL::waitForRead(const int msecs) -{ +bool TLSSocket_OpenSSL::waitForRead(const int msecs) { + return m_wrapped->waitForRead(msecs); } -bool TLSSocket_OpenSSL::waitForWrite(const int msecs) -{ +bool TLSSocket_OpenSSL::waitForWrite(const int msecs) { + return m_wrapped->waitForWrite(msecs); } -void TLSSocket_OpenSSL::receive(string& buffer) -{ +void TLSSocket_OpenSSL::receive(string& buffer) { + const size_t size = receiveRaw(m_buffer, sizeof(m_buffer)); - if (size != 0) + if (size != 0) { buffer = utility::stringUtils::makeStringFromBytes(m_buffer, size); - else + } else { buffer.clear(); + } } -void TLSSocket_OpenSSL::send(const string& buffer) -{ +void TLSSocket_OpenSSL::send(const string& buffer) { + sendRaw(reinterpret_cast <const byte_t*>(buffer.data()), buffer.length()); } -void TLSSocket_OpenSSL::send(const char* str) -{ +void TLSSocket_OpenSSL::send(const char* str) { + sendRaw(reinterpret_cast <const byte_t*>(str), ::strlen(str)); } -size_t TLSSocket_OpenSSL::receiveRaw(byte_t* buffer, const size_t count) -{ - if (!m_ssl) +size_t TLSSocket_OpenSSL::receiveRaw(byte_t* buffer, const size_t count) { + + if (!m_ssl) { throw exceptions::socket_not_connected_exception(); + } m_status &= ~(STATUS_WANT_WRITE | STATUS_WANT_READ); ERR_clear_error(); int rc = SSL_read(m_ssl, buffer, static_cast <int>(count)); - if (m_ex.get()) + if (m_ex.get()) { internalThrow(); + } + + if (rc <= 0) { - if (rc <= 0) - { int error = SSL_get_error(m_ssl, rc); - if (error == SSL_ERROR_WANT_WRITE) - { + if (error == SSL_ERROR_WANT_WRITE) { m_status |= STATUS_WANT_WRITE; return 0; - } - else if (error == SSL_ERROR_WANT_READ) - { + } else if (error == SSL_ERROR_WANT_READ) { m_status |= STATUS_WANT_READ; return 0; } @@ -275,37 +326,35 @@ size_t TLSSocket_OpenSSL::receiveRaw(byte_t* buffer, const size_t count) } -void TLSSocket_OpenSSL::sendRaw(const byte_t* buffer, const size_t count) -{ - if (!m_ssl) +void TLSSocket_OpenSSL::sendRaw(const byte_t* buffer, const size_t count) { + + if (!m_ssl) { throw exceptions::socket_not_connected_exception(); + } m_status &= ~(STATUS_WANT_WRITE | STATUS_WANT_READ); - for (size_t size = count ; size > 0 ; ) - { + for (size_t size = count ; size > 0 ; ) { + ERR_clear_error(); int rc = SSL_write(m_ssl, buffer, static_cast <int>(size)); - if (rc <= 0) - { + if (rc <= 0) { + int error = SSL_get_error(m_ssl, rc); - if (error == SSL_ERROR_WANT_READ) - { + if (error == SSL_ERROR_WANT_READ) { m_wrapped->waitForRead(); continue; - } - else if (error == SSL_ERROR_WANT_WRITE) - { + } else if (error == SSL_ERROR_WANT_WRITE) { m_wrapped->waitForWrite(); continue; } handleError(rc); - } - else - { + + } else { + buffer += rc; size -= rc; } @@ -313,30 +362,29 @@ void TLSSocket_OpenSSL::sendRaw(const byte_t* buffer, const size_t count) } -size_t TLSSocket_OpenSSL::sendRawNonBlocking(const byte_t* buffer, const size_t count) -{ - if (!m_ssl) +size_t TLSSocket_OpenSSL::sendRawNonBlocking(const byte_t* buffer, const size_t count) { + + if (!m_ssl) { throw exceptions::socket_not_connected_exception(); + } m_status &= ~(STATUS_WANT_WRITE | STATUS_WANT_READ); ERR_clear_error(); int rc = SSL_write(m_ssl, buffer, static_cast <int>(count)); - if (m_ex.get()) + if (m_ex.get()) { internalThrow(); + } + + if (rc <= 0) { - if (rc <= 0) - { int error = SSL_get_error(m_ssl, rc); - if (error == SSL_ERROR_WANT_WRITE) - { + if (error == SSL_ERROR_WANT_WRITE) { m_status |= STATUS_WANT_WRITE; return 0; - } - else if (error == SSL_ERROR_WANT_READ) - { + } else if (error == SSL_ERROR_WANT_READ) { m_status |= STATUS_WANT_READ; return 0; } @@ -348,59 +396,65 @@ size_t TLSSocket_OpenSSL::sendRawNonBlocking(const byte_t* buffer, const size_t } -void TLSSocket_OpenSSL::handshake() -{ +void TLSSocket_OpenSSL::handshake() { + shared_ptr <timeoutHandler> toHandler = m_wrapped->getTimeoutHandler(); - if (toHandler) + if (toHandler) { toHandler->resetTimeOut(); + } - if (getTracer()) + if (getTracer()) { getTracer()->traceSend("Beginning SSL/TLS handshake"); + } // Start handshaking process - if (!m_ssl) + if (!m_ssl) { createSSLHandle(); + } + + try { - try - { int rc; ERR_clear_error(); - while ((rc = SSL_do_handshake(m_ssl)) <= 0) - { + while ((rc = SSL_do_handshake(m_ssl)) <= 0) { + const int err = SSL_get_error(m_ssl, rc); - if (err == SSL_ERROR_WANT_READ) + if (err == SSL_ERROR_WANT_READ) { m_wrapped->waitForRead(); - else if (err == SSL_ERROR_WANT_WRITE) + } else if (err == SSL_ERROR_WANT_WRITE) { m_wrapped->waitForWrite(); - else + } else { handleError(rc); + } // Check whether the time-out delay is elapsed - if (toHandler && toHandler->isTimeOut()) - { - if (!toHandler->handleTimeOut()) + if (toHandler && toHandler->isTimeOut()) { + + if (!toHandler->handleTimeOut()) { throw exceptions::operation_timed_out(); + } toHandler->resetTimeOut(); } ERR_clear_error(); } - } - catch (...) - { + + } catch (...) { + throw; } // Verify server's certificate(s) shared_ptr <security::cert::certificateChain> certs = getPeerCertificates(); - if (certs == NULL) + if (!certs) { throw exceptions::tls_exception("No peer certificate."); + } m_session->getCertificateVerifier()->verify(certs, getPeerName()); @@ -408,121 +462,130 @@ void TLSSocket_OpenSSL::handshake() } -shared_ptr <security::cert::certificateChain> TLSSocket_OpenSSL::getPeerCertificates() -{ - if (getTracer()) +shared_ptr <security::cert::certificateChain> TLSSocket_OpenSSL::getPeerCertificates() { + + if (getTracer()) { getTracer()->traceSend("Getting peer certificates"); + } STACK_OF(X509)* chain = SSL_get_peer_cert_chain(m_ssl); - if (chain == NULL) + if (chain == NULL) { return null; + } int certCount = sk_X509_num(chain); - if (certCount == 0) + if (certCount == 0) { return null; + } bool error = false; std::vector <shared_ptr <security::cert::certificate> > certs; - for (int i = 0; i < certCount && !error; i++) - { + for (int i = 0; i < certCount && !error; i++) { + shared_ptr <vmime::security::cert::X509Certificate> cert = vmime::security::cert::X509Certificate_OpenSSL::importInternal(sk_X509_value(chain, i)); - if (cert) + if (cert) { certs.push_back(cert); - else + } else { error = true; + } } - if (error) + if (error) { return null; + } return make_shared <security::cert::certificateChain>(certs); } -void TLSSocket_OpenSSL::internalThrow() -{ - if (m_ex.get()) +void TLSSocket_OpenSSL::internalThrow() { + + if (m_ex.get()) { throw *m_ex; + } } -void TLSSocket_OpenSSL::handleError(int rc) -{ - if (rc > 0) return; +void TLSSocket_OpenSSL::handleError(int rc) { + + if (rc > 0) { + return; + } internalThrow(); int sslError = SSL_get_error(m_ssl, rc); long lastError = ERR_get_error(); - switch (sslError) - { - case SSL_ERROR_ZERO_RETURN: + switch (sslError) { - disconnect(); - return; + case SSL_ERROR_ZERO_RETURN: - case SSL_ERROR_SYSCALL: - { - if (lastError == 0) - { - if (rc == 0) - { - throw exceptions::tls_exception("SSL connection unexpectedly closed"); - } - else - { - std::ostringstream oss; - oss << "The BIO reported an error: " << rc; - oss.flush(); - throw exceptions::tls_exception(oss.str()); + disconnect(); + return; + + case SSL_ERROR_SYSCALL: { + + if (lastError == 0) { + + if (rc == 0) { + + throw exceptions::tls_exception("SSL connection unexpectedly closed"); + + } else { + + std::ostringstream oss; + oss << "The BIO reported an error: " << rc; + oss.flush(); + throw exceptions::tls_exception(oss.str()); + } } + + break; } - break; - } - case SSL_ERROR_WANT_READ: + case SSL_ERROR_WANT_READ: - BIO_set_retry_read(SSL_get_rbio(m_ssl)); - break; + BIO_set_retry_read(SSL_get_rbio(m_ssl)); + break; - case SSL_ERROR_WANT_WRITE: + case SSL_ERROR_WANT_WRITE: - BIO_set_retry_write(SSL_get_wbio(m_ssl)); - break; + BIO_set_retry_write(SSL_get_wbio(m_ssl)); + break; - // This happens only for BIOs of type BIO_s_connect() or BIO_s_accept() - case SSL_ERROR_WANT_CONNECT: - case SSL_ERROR_WANT_ACCEPT: - // SSL_CTX_set_client_cert_cb related, not used - case SSL_ERROR_WANT_X509_LOOKUP: - case SSL_ERROR_SSL: - default: + // This happens only for BIOs of type BIO_s_connect() or BIO_s_accept() + case SSL_ERROR_WANT_CONNECT: + case SSL_ERROR_WANT_ACCEPT: + // SSL_CTX_set_client_cert_cb related, not used + case SSL_ERROR_WANT_X509_LOOKUP: + case SSL_ERROR_SSL: + default: - if (lastError == 0) - { - throw exceptions::tls_exception("Unexpected SSL IO error"); - } - else - { - char buffer[256]; - ERR_error_string_n(lastError, buffer, sizeof(buffer)); - vmime::string msg(buffer); - throw exceptions::tls_exception(msg); - } + if (lastError == 0) { + + throw exceptions::tls_exception("Unexpected SSL IO error"); + + } else { - break; + char buffer[256]; + ERR_error_string_n(lastError, buffer, sizeof(buffer)); + vmime::string msg(buffer); + throw exceptions::tls_exception(msg); + } + + break; } } -unsigned int TLSSocket_OpenSSL::getStatus() const -{ +unsigned int TLSSocket_OpenSSL::getStatus() const { + return m_status; } @@ -531,33 +594,35 @@ unsigned int TLSSocket_OpenSSL::getStatus() const // static -int TLSSocket_OpenSSL::bio_write(BIO* bio, const char* buf, int len) -{ +int TLSSocket_OpenSSL::bio_write(BIO* bio, const char* buf, int len) { + BIO_clear_retry_flags(bio); - if (buf == NULL || len <= 0) + if (buf == NULL || len <= 0) { return -1; + } - TLSSocket_OpenSSL *sok = reinterpret_cast <TLSSocket_OpenSSL*>(bio->ptr); + TLSSocket_OpenSSL *sok = reinterpret_cast <TLSSocket_OpenSSL*>(BIO_get_data(bio)); - if (!bio->init || !sok) + if (!BIO_get_init(bio) || !sok) { return -1; + } - try - { - const size_t n = sok->m_wrapped->sendRawNonBlocking - (reinterpret_cast <const byte_t*>(buf), len); + try { - if (n == 0 && sok->m_wrapped->getStatus() & socket::STATUS_WOULDBLOCK) - { + const size_t n = sok->m_wrapped->sendRawNonBlocking( + reinterpret_cast <const byte_t*>(buf), len + ); + + if (n == 0 && sok->m_wrapped->getStatus() & socket::STATUS_WOULDBLOCK) { BIO_set_retry_write(bio); return -1; } return static_cast <int>(n); - } - catch (exception& e) - { + + } catch (exception& e) { + // Workaround for passing C++ exceptions from C BIO functions sok->m_ex.reset(e.clone()); return -1; @@ -566,33 +631,35 @@ int TLSSocket_OpenSSL::bio_write(BIO* bio, const char* buf, int len) // static -int TLSSocket_OpenSSL::bio_read(BIO* bio, char* buf, int len) -{ +int TLSSocket_OpenSSL::bio_read(BIO* bio, char* buf, int len) { + BIO_clear_retry_flags(bio); - if (buf == NULL || len <= 0) + if (buf == NULL || len <= 0) { return -1; + } - TLSSocket_OpenSSL *sok = reinterpret_cast <TLSSocket_OpenSSL*>(bio->ptr); + TLSSocket_OpenSSL *sok = reinterpret_cast <TLSSocket_OpenSSL*>(BIO_get_data(bio)); - if (!bio->init || !sok) + if (!BIO_get_init(bio) || !sok) { return -1; + } + + try { - try - { - const size_t n = sok->m_wrapped->receiveRaw - (reinterpret_cast <byte_t*>(buf), len); + const size_t n = sok->m_wrapped->receiveRaw( + reinterpret_cast <byte_t*>(buf), len + ); - if (n == 0 || sok->m_wrapped->getStatus() & socket::STATUS_WOULDBLOCK) - { + if (n == 0 || sok->m_wrapped->getStatus() & socket::STATUS_WOULDBLOCK) { BIO_set_retry_read(bio); return -1; } return static_cast <int>(n); - } - catch (exception& e) - { + + } catch (exception& e) { + // Workaround for passing C++ exceptions from C BIO functions sok->m_ex.reset(e.clone()); return -1; @@ -601,50 +668,50 @@ int TLSSocket_OpenSSL::bio_read(BIO* bio, char* buf, int len) // static -int TLSSocket_OpenSSL::bio_puts(BIO* bio, const char* str) -{ +int TLSSocket_OpenSSL::bio_puts(BIO* bio, const char* str) { + return bio_write(bio, str, static_cast <int>(strlen(str))); } // static -long TLSSocket_OpenSSL::bio_ctrl(BIO* bio, int cmd, long num, void* /* ptr */) -{ +long TLSSocket_OpenSSL::bio_ctrl(BIO* bio, int cmd, long num, void* /* ptr */) { + long ret = 1; - switch (cmd) - { - case BIO_CTRL_INFO: + switch (cmd) { + + case BIO_CTRL_INFO: - ret = 0; - break; + ret = 0; + break; - case BIO_CTRL_GET_CLOSE: + case BIO_CTRL_GET_CLOSE: - ret = bio->shutdown; - break; + ret = BIO_get_shutdown(bio); + break; - case BIO_CTRL_SET_CLOSE: + case BIO_CTRL_SET_CLOSE: - bio->shutdown = static_cast <int>(num); - break; + BIO_set_shutdown(bio, static_cast <int>(num)); + break; - case BIO_CTRL_PENDING: - case BIO_CTRL_WPENDING: + case BIO_CTRL_PENDING: + case BIO_CTRL_WPENDING: - ret = 0; - break; + ret = 0; + break; - case BIO_CTRL_DUP: - case BIO_CTRL_FLUSH: + case BIO_CTRL_DUP: + case BIO_CTRL_FLUSH: - ret = 1; - break; + ret = 1; + break; - default: + default: - ret = 0; - break; + ret = 0; + break; } return ret; @@ -652,28 +719,28 @@ long TLSSocket_OpenSSL::bio_ctrl(BIO* bio, int cmd, long num, void* /* ptr */) // static -int TLSSocket_OpenSSL::bio_create(BIO* bio) -{ - bio->init = 0; - bio->num = 0; - bio->ptr = NULL; - bio->flags = 0; +int TLSSocket_OpenSSL::bio_create(BIO* bio) { + + BIO_set_init(bio, 0); + BIO_set_num(bio, 0); + BIO_set_data(bio, NULL); + BIO_set_flags(bio, 0); return 1; } // static -int TLSSocket_OpenSSL::bio_destroy(BIO* bio) -{ - if (bio == NULL) +int TLSSocket_OpenSSL::bio_destroy(BIO* bio) { + + if (!bio) { return 0; + } - if (bio->shutdown) - { - bio->ptr = NULL; - bio->init = 0; - bio->flags = 0; + if (BIO_get_shutdown(bio)) { + BIO_set_data(bio, NULL); + BIO_set_init(bio, 0); + BIO_set_flags(bio, 0); } return 1; diff --git a/src/vmime/net/tls/openssl/TLSSocket_OpenSSL.hpp b/src/vmime/net/tls/openssl/TLSSocket_OpenSSL.hpp index 34324b8c..e30df680 100644 --- a/src/vmime/net/tls/openssl/TLSSocket_OpenSSL.hpp +++ b/src/vmime/net/tls/openssl/TLSSocket_OpenSSL.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard <[email protected]> +// Copyright (C) 2002 Vincent Richard <[email protected]> // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License as @@ -50,11 +50,15 @@ class TLSSession; class TLSSession_OpenSSL; -class TLSSocket_OpenSSL : public TLSSocket -{ +class TLSSocket_OpenSSL : public TLSSocket { + public: - TLSSocket_OpenSSL(shared_ptr <TLSSession_OpenSSL> session, shared_ptr <socket> sok); + TLSSocket_OpenSSL( + const shared_ptr <TLSSession_OpenSSL>& session, + const shared_ptr <socket>& sok + ); + ~TLSSocket_OpenSSL(); @@ -87,7 +91,7 @@ public: shared_ptr <timeoutHandler> getTimeoutHandler(); - void setTracer(shared_ptr <net::tracer> tracer); + void setTracer(const shared_ptr <net::tracer>& tracer); shared_ptr <net::tracer> getTracer(); private: diff --git a/src/vmime/net/tracer.cpp b/src/vmime/net/tracer.cpp index b3610cdd..66afb360 100644 --- a/src/vmime/net/tracer.cpp +++ b/src/vmime/net/tracer.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2014 Vincent Richard <[email protected]> +// Copyright (C) 2002 Vincent Richard <[email protected]> // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License as @@ -37,13 +37,14 @@ namespace vmime { namespace net { -void tracer::traceReceiveBytes(const size_t count, const string& state) -{ +void tracer::traceReceiveBytes(const size_t count, const string& state) { + std::ostringstream oss; oss << "{..."; - if (!state.empty()) + if (!state.empty()) { oss << state << ": "; + } oss << count << " bytes of data...}"; @@ -51,13 +52,14 @@ void tracer::traceReceiveBytes(const size_t count, const string& state) } -void tracer::traceSendBytes(const size_t count, const string& state) -{ +void tracer::traceSendBytes(const size_t count, const string& state) { + std::ostringstream oss; oss << "{..."; - if (!state.empty()) + if (!state.empty()) { oss << state << ": "; + } oss << count << " bytes of data...}"; diff --git a/src/vmime/net/tracer.hpp b/src/vmime/net/tracer.hpp index e30c823c..74724630 100644 --- a/src/vmime/net/tracer.hpp +++ b/src/vmime/net/tracer.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2014 Vincent Richard <[email protected]> +// Copyright (C) 2002 Vincent Richard <[email protected]> // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License as @@ -44,12 +44,13 @@ class service; /** Base class for an object used to trace network communication * between the client and the server. */ +class VMIME_EXPORT tracer : public object { -class VMIME_EXPORT tracer : public object -{ public: - virtual ~tracer() { } + virtual ~tracer() { + + } /** Trace raw bytes which have been received. * @@ -79,15 +80,15 @@ public: }; - /** A class to create 'tracer' objects. */ +class VMIME_EXPORT tracerFactory : public object { -class VMIME_EXPORT tracerFactory : public object -{ public: - virtual ~tracerFactory() { } + virtual ~tracerFactory() { + + } /** Creates a tracer for the specified service. * @@ -96,7 +97,7 @@ public: * different connections used by a service * @return a new tracer */ - virtual shared_ptr <tracer> create(shared_ptr <service> serv, const int connectionId) = 0; + virtual shared_ptr <tracer> create(const shared_ptr <service>& serv, const int connectionId) = 0; }; diff --git a/src/vmime/net/transport.cpp b/src/vmime/net/transport.cpp index dd7281d0..f87648a3 100644 --- a/src/vmime/net/transport.cpp +++ b/src/vmime/net/transport.cpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard <[email protected]> +// Copyright (C) 2002 Vincent Richard <[email protected]> // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License as @@ -43,30 +43,34 @@ namespace vmime { namespace net { -transport::transport(shared_ptr <session> sess, const serviceInfos& infos, shared_ptr <security::authenticator> auth) - : service(sess, infos, auth) -{ +transport::transport( + const shared_ptr <session>& sess, + const serviceInfos& infos, + const shared_ptr <security::authenticator>& auth +) + : service(sess, infos, auth) { + } -shared_ptr <headerField> transport::processHeaderField(shared_ptr <headerField> field) -{ - if (utility::stringUtils::isStringEqualNoCase(field->getName(), fields::BCC)) - { +shared_ptr <headerField> transport::processHeaderField(const shared_ptr <headerField>& field) { + + if (utility::stringUtils::isStringEqualNoCase(field->getName(), fields::BCC)) { + // Remove Bcc headers from the message, as required by the RFC. // Some SMTP server automatically strip this header (Postfix, qmail), // and others have an option for this (Exim). return null; - } - else if (utility::stringUtils::isStringEqualNoCase(field->getName(), fields::RETURN_PATH)) - { + + } else if (utility::stringUtils::isStringEqualNoCase(field->getName(), fields::RETURN_PATH)) { + // RFC-2821: Return-Path header is added by the final transport system // that delivers the message to its recipient. Then, it should not be // transmitted to MSA. return null; - } - else if (utility::stringUtils::isStringEqualNoCase(field->getName(), fields::ORIGINAL_RECIPIENT)) - { + + } else if (utility::stringUtils::isStringEqualNoCase(field->getName(), fields::ORIGINAL_RECIPIENT)) { + // RFC-2298: Delivering MTA may add the Original-Recipient header and // discard existing one; so, no need to send it. return null; @@ -77,59 +81,71 @@ shared_ptr <headerField> transport::processHeaderField(shared_ptr <headerField> } -void transport::processHeader(shared_ptr <header> header) -{ - if (header->getFieldCount() == 0) +void transport::processHeader(const shared_ptr <header>& header) { + + if (header->getFieldCount() == 0) { return; + } // Remove/replace fields - for (size_t idx = header->getFieldCount() ; idx != 0 ; --idx) - { + for (size_t idx = header->getFieldCount() ; idx != 0 ; --idx) { + shared_ptr <headerField> field = header->getFieldAt(idx - 1); shared_ptr <headerField> newField = processHeaderField(field); - if (newField == NULL) + if (newField == NULL) { header->removeField(field); - else if (newField != field) + } else if (newField != field) { header->replaceField(field, newField); + } } // Add missing header fields // -- Date - if (!header->hasField(fields::DATE)) + if (!header->hasField(fields::DATE)) { header->Date()->setValue(datetime::now()); + } // -- Mime-Version - if (!header->hasField(fields::MIME_VERSION)) + if (!header->hasField(fields::MIME_VERSION)) { header->MimeVersion()->setValue(string(SUPPORTED_MIME_VERSION)); + } // -- Message-Id - if (!header->hasField(fields::MESSAGE_ID)) + if (!header->hasField(fields::MESSAGE_ID)) { header->MessageId()->setValue(messageId::generateId()); + } } -static void extractMailboxes - (mailboxList& recipients, const addressList& list) -{ - for (size_t i = 0 ; i < list.getAddressCount() ; ++i) - { +static void extractMailboxes( + mailboxList& recipients, + const addressList& list +) { + + for (size_t i = 0 ; i < list.getAddressCount() ; ++i) { + shared_ptr <mailbox> mbox = dynamicCast <mailbox>(list.getAddressAt(i)->clone()); - if (mbox != NULL) + if (mbox) { recipients.appendMailbox(mbox); + } } } -void transport::send(shared_ptr <vmime::message> msg, utility::progressListener* progress) -{ +void transport::send( + const shared_ptr <vmime::message>& msg, + utility::progressListener* progress +) { + // Extract expeditor shared_ptr <mailbox> fromMbox = msg->getHeader()->findFieldValue <mailbox>(fields::FROM); - if (!fromMbox) + if (!fromMbox) { throw exceptions::no_expeditor(); + } mailbox expeditor = *fromMbox; @@ -139,10 +155,11 @@ void transport::send(shared_ptr <vmime::message> msg, utility::progressListener* mailbox sender; - if (!senderMbox) + if (!senderMbox) { sender = expeditor; - else + } else { sender = *senderMbox; + } // Extract recipients mailboxList recipients; @@ -151,22 +168,23 @@ void transport::send(shared_ptr <vmime::message> msg, utility::progressListener* shared_ptr <addressList> addresses = msg->getHeader()->findFieldValue <addressList>(fields::TO); - if (addresses) + if (addresses) { extractMailboxes(recipients, *addresses); + } // -- "Cc" field - addresses = - msg->getHeader()->findFieldValue <addressList>(fields::CC); + addresses = msg->getHeader()->findFieldValue <addressList>(fields::CC); - if (addresses) + if (addresses) { extractMailboxes(recipients, *addresses); + } // -- "Bcc" field - addresses = - msg->getHeader()->findFieldValue <addressList>(fields::BCC); + addresses = msg->getHeader()->findFieldValue <addressList>(fields::BCC); - if (addresses) + if (addresses) { extractMailboxes(recipients, *addresses); + } // Process message header by removing fields that should be removed // before transmitting the message to MSA, and adding missing fields @@ -177,18 +195,21 @@ void transport::send(shared_ptr <vmime::message> msg, utility::progressListener* // To avoid cloning message body (too much overhead), use processed // header during the time we are generating the message to a stream. // Revert it back to original header after. - struct XChangeMsgHeader - { - XChangeMsgHeader(shared_ptr <vmime::message> _msg, - shared_ptr <vmime::header> _hdr) - : msg(_msg), hdr(msg->getHeader()) - { + struct XChangeMsgHeader { + + XChangeMsgHeader( + const shared_ptr <vmime::message>& _msg, + const shared_ptr <vmime::header>& _hdr + ) + : msg(_msg), + hdr(msg->getHeader()) { + // Set new header msg->setHeader(_hdr); } - ~XChangeMsgHeader() - { + ~XChangeMsgHeader() { + // Revert original header msg->setHeader(hdr); } @@ -197,16 +218,21 @@ void transport::send(shared_ptr <vmime::message> msg, utility::progressListener* shared_ptr <vmime::message> msg; shared_ptr <vmime::header> hdr; + } headerExchanger(msg, hdr); send(msg, expeditor, recipients, progress, sender); } -void transport::send - (shared_ptr <vmime::message> msg, const mailbox& expeditor, const mailboxList& recipients, - utility::progressListener* progress, const mailbox& sender) -{ +void transport::send( + const shared_ptr <vmime::message>& msg, + const mailbox& expeditor, + const mailboxList& recipients, + utility::progressListener* progress, + const mailbox& sender +) { + // Generate the message, "stream" it and delegate the sending // to the generic send() function. std::ostringstream oss; @@ -222,9 +248,9 @@ void transport::send } -transport::Type transport::getType() const -{ - return (TYPE_TRANSPORT); +transport::Type transport::getType() const { + + return TYPE_TRANSPORT; } diff --git a/src/vmime/net/transport.hpp b/src/vmime/net/transport.hpp index 6c405cbb..2f9878d0 100644 --- a/src/vmime/net/transport.hpp +++ b/src/vmime/net/transport.hpp @@ -1,6 +1,6 @@ // // VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard <[email protected]> +// Copyright (C) 2002 Vincent Richard <[email protected]> // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License as @@ -51,12 +51,15 @@ namespace net { /** A transport service. * Encapsulate protocols that can send messages. */ +class VMIME_EXPORT transport : public service { -class VMIME_EXPORT transport : public service -{ protected: - transport(shared_ptr <session> sess, const serviceInfos& infos, shared_ptr <security::authenticator> auth); + transport( + const shared_ptr <session>& sess, + const serviceInfos& infos, + const shared_ptr <security::authenticator>& auth + ); public: @@ -67,7 +70,10 @@ public: * @param msg message to send * @param progress progress listener, or NULL if not used */ - virtual void send(shared_ptr <vmime::message> msg, utility::progressListener* progress = NULL); + virtual void send( + const shared_ptr <vmime::message>& msg, + utility::progressListener* progress = NULL + ); /** Send a message over this transport service. * @@ -78,13 +84,14 @@ public: * @param progress progress listener, or NULL if not used * @param sender envelope sender (if empty, expeditor will be used) */ - virtual void send - (const mailbox& expeditor, - const mailboxList& recipients, - utility::inputStream& is, - const size_t size, - utility::progressListener* progress = NULL, - const mailbox& sender = mailbox()) = 0; + virtual void send( + const mailbox& expeditor, + const mailboxList& recipients, + utility::inputStream& is, + const size_t size, + utility::progressListener* progress = NULL, + const mailbox& sender = mailbox() + ) = 0; /** Send a message over this transport service. * The default implementation simply generates the whole message into @@ -96,12 +103,13 @@ public: * @param progress progress listener, or NULL if not used * @param sender envelope sender (if empty, expeditor will be used) */ - virtual void send - (shared_ptr <vmime::message> msg, - const mailbox& expeditor, - const mailboxList& recipients, - utility::progressListener* progress = NULL, - const mailbox& sender = mailbox()); + virtual void send( + const shared_ptr <vmime::message>& msg, + const mailbox& expeditor, + const mailboxList& recipients, + utility::progressListener* progress = NULL, + const mailbox& sender = mailbox() + ); Type getType() const; @@ -115,7 +123,7 @@ protected: * if the field is to be replaced, or a reference to the same headerField * that was passed if the field should be left as is */ - shared_ptr <headerField> processHeaderField(shared_ptr <headerField> field); + shared_ptr <headerField> processHeaderField(const shared_ptr <headerField>& field); /** Prepares the header before transmitting the message. * Removes headers that should not be present (eg. "Bcc", "Return-Path"), @@ -124,7 +132,7 @@ protected: * * @param header headers to process */ - void processHeader(shared_ptr <header> header); + void processHeader(const shared_ptr <header>& header); }; |