From 152c6bed75598a6ca5efb7914701157270155833 Mon Sep 17 00:00:00 2001 From: Vincent Richard Date: Sun, 29 Dec 2013 10:02:12 +0100 Subject: Merged source and header files in directory structure. Got rid of SConstruct build. --- src/net/builtinServices.inl | 76 -- src/net/defaultConnectionInfos.cpp | 60 - src/net/events.cpp | 166 --- src/net/fetchAttributes.cpp | 95 -- src/net/folder.cpp | 127 -- src/net/imap/IMAPConnection.cpp | 814 ------------ src/net/imap/IMAPFolder.cpp | 1511 ---------------------- src/net/imap/IMAPFolderStatus.cpp | 307 ----- src/net/imap/IMAPMessage.cpp | 649 ---------- src/net/imap/IMAPMessagePart.cpp | 161 --- src/net/imap/IMAPMessagePartContentHandler.cpp | 216 ---- src/net/imap/IMAPMessageStructure.cpp | 94 -- src/net/imap/IMAPSStore.cpp | 79 -- src/net/imap/IMAPServiceInfos.cpp | 137 -- src/net/imap/IMAPStore.cpp | 267 ---- src/net/imap/IMAPTag.cpp | 122 -- src/net/imap/IMAPUtils.cpp | 758 ----------- src/net/maildir/format/courierMaildirFormat.cpp | 542 -------- src/net/maildir/format/kmailMaildirFormat.cpp | 320 ----- src/net/maildir/maildirFolder.cpp | 1254 ------------------ src/net/maildir/maildirFolderStatus.cpp | 88 -- src/net/maildir/maildirFormat.cpp | 109 -- src/net/maildir/maildirMessage.cpp | 369 ------ src/net/maildir/maildirMessagePart.cpp | 155 --- src/net/maildir/maildirMessageStructure.cpp | 98 -- src/net/maildir/maildirServiceInfos.cpp | 77 -- src/net/maildir/maildirStore.cpp | 272 ---- src/net/maildir/maildirUtils.cpp | 273 ---- src/net/message.cpp | 150 --- src/net/messageSet.cpp | 369 ------ src/net/pop3/POP3Command.cpp | 230 ---- src/net/pop3/POP3Connection.cpp | 675 ---------- src/net/pop3/POP3Folder.cpp | 729 ----------- src/net/pop3/POP3FolderStatus.cpp | 88 -- src/net/pop3/POP3Message.cpp | 250 ---- src/net/pop3/POP3Response.cpp | 428 ------ src/net/pop3/POP3SStore.cpp | 79 -- src/net/pop3/POP3ServiceInfos.cpp | 143 -- src/net/pop3/POP3Store.cpp | 240 ---- src/net/pop3/POP3Utils.cpp | 114 -- src/net/sendmail/sendmailServiceInfos.cpp | 78 -- src/net/sendmail/sendmailTransport.cpp | 230 ---- src/net/service.cpp | 152 --- src/net/serviceFactory.cpp | 145 --- src/net/serviceInfos.cpp | 167 --- src/net/serviceRegistration.inl | 98 -- src/net/session.cpp | 158 --- src/net/smtp/SMTPChunkingOutputStreamAdapter.cpp | 145 --- src/net/smtp/SMTPCommand.cpp | 214 --- src/net/smtp/SMTPCommandSet.cpp | 144 --- src/net/smtp/SMTPConnection.cpp | 618 --------- src/net/smtp/SMTPExceptions.cpp | 151 --- src/net/smtp/SMTPResponse.cpp | 334 ----- src/net/smtp/SMTPSTransport.cpp | 79 -- src/net/smtp/SMTPServiceInfos.cpp | 146 --- src/net/smtp/SMTPTransport.cpp | 420 ------ src/net/tls/TLSProperties.cpp | 44 - src/net/tls/TLSSecuredConnectionInfos.cpp | 72 -- src/net/tls/TLSSession.cpp | 48 - src/net/tls/TLSSocket.cpp | 44 - src/net/tls/gnutls/TLSProperties_GnuTLS.cpp | 113 -- src/net/tls/gnutls/TLSSession_GnuTLS.cpp | 300 ----- src/net/tls/gnutls/TLSSocket_GnuTLS.cpp | 490 ------- src/net/tls/openssl/OpenSSLInitializer.cpp | 142 -- src/net/tls/openssl/TLSProperties_OpenSSL.cpp | 112 -- src/net/tls/openssl/TLSSession_OpenSSL.cpp | 135 -- src/net/tls/openssl/TLSSocket_OpenSSL.cpp | 601 --------- src/net/transport.cpp | 236 ---- 68 files changed, 18307 deletions(-) delete mode 100644 src/net/builtinServices.inl delete mode 100644 src/net/defaultConnectionInfos.cpp delete mode 100644 src/net/events.cpp delete mode 100644 src/net/fetchAttributes.cpp delete mode 100644 src/net/folder.cpp delete mode 100644 src/net/imap/IMAPConnection.cpp delete mode 100644 src/net/imap/IMAPFolder.cpp delete mode 100644 src/net/imap/IMAPFolderStatus.cpp delete mode 100644 src/net/imap/IMAPMessage.cpp delete mode 100644 src/net/imap/IMAPMessagePart.cpp delete mode 100644 src/net/imap/IMAPMessagePartContentHandler.cpp delete mode 100644 src/net/imap/IMAPMessageStructure.cpp delete mode 100644 src/net/imap/IMAPSStore.cpp delete mode 100644 src/net/imap/IMAPServiceInfos.cpp delete mode 100644 src/net/imap/IMAPStore.cpp delete mode 100644 src/net/imap/IMAPTag.cpp delete mode 100644 src/net/imap/IMAPUtils.cpp delete mode 100644 src/net/maildir/format/courierMaildirFormat.cpp delete mode 100644 src/net/maildir/format/kmailMaildirFormat.cpp delete mode 100644 src/net/maildir/maildirFolder.cpp delete mode 100644 src/net/maildir/maildirFolderStatus.cpp delete mode 100644 src/net/maildir/maildirFormat.cpp delete mode 100644 src/net/maildir/maildirMessage.cpp delete mode 100644 src/net/maildir/maildirMessagePart.cpp delete mode 100644 src/net/maildir/maildirMessageStructure.cpp delete mode 100644 src/net/maildir/maildirServiceInfos.cpp delete mode 100644 src/net/maildir/maildirStore.cpp delete mode 100644 src/net/maildir/maildirUtils.cpp delete mode 100644 src/net/message.cpp delete mode 100644 src/net/messageSet.cpp delete mode 100644 src/net/pop3/POP3Command.cpp delete mode 100644 src/net/pop3/POP3Connection.cpp delete mode 100644 src/net/pop3/POP3Folder.cpp delete mode 100644 src/net/pop3/POP3FolderStatus.cpp delete mode 100644 src/net/pop3/POP3Message.cpp delete mode 100644 src/net/pop3/POP3Response.cpp delete mode 100644 src/net/pop3/POP3SStore.cpp delete mode 100644 src/net/pop3/POP3ServiceInfos.cpp delete mode 100644 src/net/pop3/POP3Store.cpp delete mode 100644 src/net/pop3/POP3Utils.cpp delete mode 100644 src/net/sendmail/sendmailServiceInfos.cpp delete mode 100644 src/net/sendmail/sendmailTransport.cpp delete mode 100644 src/net/service.cpp delete mode 100644 src/net/serviceFactory.cpp delete mode 100644 src/net/serviceInfos.cpp delete mode 100644 src/net/serviceRegistration.inl delete mode 100644 src/net/session.cpp delete mode 100644 src/net/smtp/SMTPChunkingOutputStreamAdapter.cpp delete mode 100644 src/net/smtp/SMTPCommand.cpp delete mode 100644 src/net/smtp/SMTPCommandSet.cpp delete mode 100644 src/net/smtp/SMTPConnection.cpp delete mode 100644 src/net/smtp/SMTPExceptions.cpp delete mode 100644 src/net/smtp/SMTPResponse.cpp delete mode 100644 src/net/smtp/SMTPSTransport.cpp delete mode 100644 src/net/smtp/SMTPServiceInfos.cpp delete mode 100644 src/net/smtp/SMTPTransport.cpp delete mode 100644 src/net/tls/TLSProperties.cpp delete mode 100644 src/net/tls/TLSSecuredConnectionInfos.cpp delete mode 100644 src/net/tls/TLSSession.cpp delete mode 100644 src/net/tls/TLSSocket.cpp delete mode 100644 src/net/tls/gnutls/TLSProperties_GnuTLS.cpp delete mode 100644 src/net/tls/gnutls/TLSSession_GnuTLS.cpp delete mode 100644 src/net/tls/gnutls/TLSSocket_GnuTLS.cpp delete mode 100644 src/net/tls/openssl/OpenSSLInitializer.cpp delete mode 100644 src/net/tls/openssl/TLSProperties_OpenSSL.cpp delete mode 100644 src/net/tls/openssl/TLSSession_OpenSSL.cpp delete mode 100644 src/net/tls/openssl/TLSSocket_OpenSSL.cpp delete mode 100644 src/net/transport.cpp (limited to 'src/net') diff --git a/src/net/builtinServices.inl b/src/net/builtinServices.inl deleted file mode 100644 index 9225ff30..00000000 --- a/src/net/builtinServices.inl +++ /dev/null @@ -1,76 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// 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 registration helpers -#include "src/net/serviceRegistration.inl" - - -#ifndef VMIME_BUILDING_DOC - - -#if VMIME_HAVE_MESSAGING_PROTO_POP3 - #include "vmime/net/pop3/POP3Store.hpp" - REGISTER_SERVICE(pop3::POP3Store, pop3, TYPE_STORE); - - #if VMIME_HAVE_TLS_SUPPORT - #include "vmime/net/pop3/POP3SStore.hpp" - REGISTER_SERVICE(pop3::POP3SStore, pop3s, TYPE_STORE); - #endif // VMIME_HAVE_TLS_SUPPORT -#endif - - -#if VMIME_HAVE_MESSAGING_PROTO_SMTP - #include "vmime/net/smtp/SMTPTransport.hpp" - REGISTER_SERVICE(smtp::SMTPTransport, smtp, TYPE_TRANSPORT); - - #if VMIME_HAVE_TLS_SUPPORT - #include "vmime/net/smtp/SMTPSTransport.hpp" - REGISTER_SERVICE(smtp::SMTPSTransport, smtps, TYPE_TRANSPORT); - #endif // VMIME_HAVE_TLS_SUPPORT -#endif - - -#if VMIME_HAVE_MESSAGING_PROTO_IMAP - #include "vmime/net/imap/IMAPStore.hpp" - REGISTER_SERVICE(imap::IMAPStore, imap, TYPE_STORE); - - #if VMIME_HAVE_TLS_SUPPORT - #include "vmime/net/imap/IMAPSStore.hpp" - REGISTER_SERVICE(imap::IMAPSStore, imaps, TYPE_STORE); - #endif // VMIME_HAVE_TLS_SUPPORT -#endif - - -#if VMIME_HAVE_MESSAGING_PROTO_MAILDIR - #include "vmime/net/maildir/maildirStore.hpp" - REGISTER_SERVICE(maildir::maildirStore, maildir, TYPE_STORE); -#endif - -#if VMIME_HAVE_MESSAGING_PROTO_SENDMAIL - #include "vmime/net/sendmail/sendmailTransport.hpp" - REGISTER_SERVICE(sendmail::sendmailTransport, sendmail, TYPE_TRANSPORT); -#endif - - -#endif // VMIME_BUILDING_DOC diff --git a/src/net/defaultConnectionInfos.cpp b/src/net/defaultConnectionInfos.cpp deleted file mode 100644 index 335e8f6f..00000000 --- a/src/net/defaultConnectionInfos.cpp +++ /dev/null @@ -1,60 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// 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/defaultConnectionInfos.hpp" - - -namespace vmime { -namespace net { - - -defaultConnectionInfos::defaultConnectionInfos(const string& host, const port_t port) - : m_host(host), m_port(port) -{ -} - - -const string defaultConnectionInfos::getHost() const -{ - return m_host; -} - - -port_t defaultConnectionInfos::getPort() const -{ - return m_port; -} - - -} // net -} // vmime - - -#endif // VMIME_HAVE_MESSAGING_FEATURES - diff --git a/src/net/events.cpp b/src/net/events.cpp deleted file mode 100644 index a19e1738..00000000 --- a/src/net/events.cpp +++ /dev/null @@ -1,166 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// 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/events.hpp" -#include "vmime/net/folder.hpp" - -#include - - -namespace vmime { -namespace net { -namespace events { - - -// -// event -// - -event::event() -{ -} - - -event::~event() -{ -} - - -// -// messageCountEvent -// - -const char* messageCountEvent::EVENT_CLASS = "messageCountEvent"; - - -messageCountEvent::messageCountEvent - (shared_ptr folder, const Types type, const std::vector & nums) - : m_folder(folder), m_type(type) -{ - m_nums.resize(nums.size()); - std::copy(nums.begin(), nums.end(), m_nums.begin()); -} - - -shared_ptr messageCountEvent::getFolder() const { return (m_folder); } -messageCountEvent::Types messageCountEvent::getType() const { return (m_type); } -const std::vector & messageCountEvent::getNumbers() const { return (m_nums); } - - -void messageCountEvent::dispatch(messageCountListener* listener) -{ - if (m_type == TYPE_ADDED) - listener->messagesAdded(dynamicCast (shared_from_this())); - else - listener->messagesRemoved(dynamicCast (shared_from_this())); -} - - -const char* messageCountEvent::getClass() const -{ - return EVENT_CLASS; -} - - -// -// messageChangedEvent -// - -const char* messageChangedEvent::EVENT_CLASS = "messageChangedEvent"; - - -messageChangedEvent::messageChangedEvent - (shared_ptr folder, const Types type, const std::vector & nums) - : m_folder(folder), m_type(type) -{ - m_nums.resize(nums.size()); - std::copy(nums.begin(), nums.end(), m_nums.begin()); -} - - -shared_ptr messageChangedEvent::getFolder() const { return (m_folder); } -messageChangedEvent::Types messageChangedEvent::getType() const { return (m_type); } -const std::vector & messageChangedEvent::getNumbers() const { return (m_nums); } - - -void messageChangedEvent::dispatch(messageChangedListener* listener) -{ - listener->messageChanged(dynamicCast (shared_from_this())); -} - - -const char* messageChangedEvent::getClass() const -{ - return EVENT_CLASS; -} - - -// -// folderEvent -// - -const char* folderEvent::EVENT_CLASS = "folderEvent"; - - -folderEvent::folderEvent - (shared_ptr folder, const Types type, - const utility::path& oldPath, const utility::path& newPath) - : m_folder(folder), m_type(type), m_oldPath(oldPath), m_newPath(newPath) -{ -} - - -shared_ptr 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 (shared_from_this())); break; - case TYPE_RENAMED: listener->folderRenamed(dynamicCast (shared_from_this())); break; - case TYPE_DELETED: listener->folderDeleted(dynamicCast (shared_from_this())); break; - } -} - - -const char* folderEvent::getClass() const -{ - return EVENT_CLASS; -} - - -} // events -} // net -} // vmime - - -#endif // VMIME_HAVE_MESSAGING_FEATURES - diff --git a/src/net/fetchAttributes.cpp b/src/net/fetchAttributes.cpp deleted file mode 100644 index 85a41b8c..00000000 --- a/src/net/fetchAttributes.cpp +++ /dev/null @@ -1,95 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// 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/fetchAttributes.hpp" - -#include "vmime/utility/stringUtils.hpp" - -#include - - -namespace vmime { -namespace net { - - -fetchAttributes::fetchAttributes() - : m_predefinedAttribs(0) -{ -} - - -fetchAttributes::fetchAttributes(const int attribs) - : m_predefinedAttribs(attribs) -{ -} - - -fetchAttributes::fetchAttributes(const fetchAttributes& attribs) - : object() -{ - m_predefinedAttribs = attribs.m_predefinedAttribs; - m_headers = attribs.m_headers; -} - - -void fetchAttributes::add(const int attribs) -{ - m_predefinedAttribs = attribs; -} - - -void fetchAttributes::add(const string& header) -{ - m_headers.push_back(utility::stringUtils::toLower(header)); -} - - -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(); -} - - -const std::vector fetchAttributes::getHeaderFields() const -{ - return m_headers; -} - - -} // net -} // vmime - - -#endif // VMIME_HAVE_MESSAGING_FEATURES diff --git a/src/net/folder.cpp b/src/net/folder.cpp deleted file mode 100644 index 1d6f3140..00000000 --- a/src/net/folder.cpp +++ /dev/null @@ -1,127 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// 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/folder.hpp" - -#include - - -namespace vmime { -namespace net { - - -void folder::addMessageChangedListener(events::messageChangedListener* l) -{ - m_messageChangedListeners.push_back(l); -} - - -void folder::removeMessageChangedListener(events::messageChangedListener* l) -{ - std::remove(m_messageChangedListeners.begin(), m_messageChangedListeners.end(), l); -} - - -void folder::notifyMessageChanged(shared_ptr event) -{ - for (std::list ::iterator - it = m_messageChangedListeners.begin() ; it != m_messageChangedListeners.end() ; ++it) - { - event->dispatch(*it); - } -} - - -void folder::addMessageCountListener(events::messageCountListener* l) -{ - m_messageCountListeners.push_back(l); -} - - -void folder::removeMessageCountListener(events::messageCountListener* l) -{ - std::remove(m_messageCountListeners.begin(), m_messageCountListeners.end(), l); -} - - -void folder::notifyMessageCount(shared_ptr event) -{ - for (std::list ::iterator - it = m_messageCountListeners.begin() ; it != m_messageCountListeners.end() ; ++it) - { - event->dispatch(*it); - } -} - - -void folder::addFolderListener(events::folderListener* l) -{ - m_folderListeners.push_back(l); -} - - -void folder::removeFolderListener(events::folderListener* l) -{ - std::remove(m_folderListeners.begin(), m_folderListeners.end(), l); -} - - -void folder::notifyFolder(shared_ptr event) -{ - for (std::list ::iterator - it = m_folderListeners.begin() ; it != m_folderListeners.end() ; ++it) - { - event->dispatch(*it); - } -} - - -void folder::notifyEvent(shared_ptr event) -{ - if (event->getClass() == events::messageCountEvent::EVENT_CLASS) - { - notifyMessageCount(dynamicCast (event)); - } - else if (event->getClass() == events::messageChangedEvent::EVENT_CLASS) - { - notifyMessageChanged(dynamicCast (event)); - } - else if (event->getClass() == events::folderEvent::EVENT_CLASS) - { - notifyFolder(dynamicCast (event)); - } -} - - -} // net -} // vmime - - -#endif // VMIME_HAVE_MESSAGING_FEATURES - diff --git a/src/net/imap/IMAPConnection.cpp b/src/net/imap/IMAPConnection.cpp deleted file mode 100644 index 234c2b6a..00000000 --- a/src/net/imap/IMAPConnection.cpp +++ /dev/null @@ -1,814 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// 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 && VMIME_HAVE_MESSAGING_PROTO_IMAP - - -#include "vmime/net/imap/IMAPTag.hpp" -#include "vmime/net/imap/IMAPConnection.hpp" -#include "vmime/net/imap/IMAPUtils.hpp" -#include "vmime/net/imap/IMAPStore.hpp" - -#include "vmime/exception.hpp" -#include "vmime/platform.hpp" - -#include "vmime/utility/stringUtils.hpp" - -#include "vmime/net/defaultConnectionInfos.hpp" - -#if VMIME_HAVE_SASL_SUPPORT - #include "vmime/security/sasl/SASLContext.hpp" -#endif // VMIME_HAVE_SASL_SUPPORT - -#if VMIME_HAVE_TLS_SUPPORT - #include "vmime/net/tls/TLSSession.hpp" - #include "vmime/net/tls/TLSSecuredConnectionInfos.hpp" -#endif // VMIME_HAVE_TLS_SUPPORT - -#include - - -// Helpers for service properties -#define GET_PROPERTY(type, prop) \ - (m_store.lock()->getInfos().getPropertyValue (getSession(), \ - dynamic_cast (m_store.lock()->getInfos()).getProperties().prop)) -#define HAS_PROPERTY(prop) \ - (m_store.lock()->getInfos().hasProperty(getSession(), \ - dynamic_cast (m_store.lock()->getInfos()).getProperties().prop)) - - -namespace vmime { -namespace net { -namespace imap { - - -IMAPConnection::IMAPConnection(shared_ptr store, shared_ptr 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() -{ - try - { - if (isConnected()) - disconnect(); - else if (m_socket) - internalDisconnect(); - } - catch (vmime::exception&) - { - // Ignore - } -} - - -void IMAPConnection::connect() -{ - if (isConnected()) - throw exceptions::already_connected(); - - m_state = STATE_NONE; - m_hierarchySeparator = '\0'; - - const string address = GET_PROPERTY(string, PROPERTY_SERVER_ADDRESS); - const port_t port = GET_PROPERTY(port_t, PROPERTY_SERVER_PORT); - - shared_ptr store = m_store.lock(); - - // Create the time-out handler - if (store->getTimeoutHandlerFactory()) - m_timeoutHandler = store->getTimeoutHandlerFactory()->create(); - - // Create and connect the socket - m_socket = store->getSocketFactory()->create(m_timeoutHandler); - -#if VMIME_HAVE_TLS_SUPPORT - if (store->isIMAPS()) // dedicated port/IMAPS - { - shared_ptr tlsSession = tls::TLSSession::create - (store->getCertificateVerifier(), - store->getSession()->getTLSProperties()); - - shared_ptr tlsSocket = - tlsSession->getSocket(m_socket); - - m_socket = tlsSocket; - - m_secured = true; - m_cntInfos = make_shared (address, port, tlsSession, tlsSocket); - } - else -#endif // VMIME_HAVE_TLS_SUPPORT - { - m_cntInfos = make_shared (address, port); - } - - m_socket->connect(address, port); - - - m_tag = make_shared (); - m_parser = make_shared (m_tag, m_socket, m_timeoutHandler); - - - setState(STATE_NON_AUTHENTICATED); - - - // Connection greeting - // - // eg: C: - // --- S: * OK mydomain.org IMAP4rev1 v12.256 server ready - - std::auto_ptr greet(m_parser->readGreeting()); - bool needAuth = false; - - 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) - { - needAuth = true; - } - - if (greet->resp_cond_auth()->resp_text()->resp_text_code() && - greet->resp_cond_auth()->resp_text()->resp_text_code()->capability_data()) - { - processCapabilityResponseData(greet->resp_cond_auth()->resp_text()->resp_text_code()->capability_data()); - } - -#if VMIME_HAVE_TLS_SUPPORT - // Setup secured connection, if requested - const bool tls = HAS_PROPERTY(PROPERTY_CONNECTION_TLS) - && GET_PROPERTY(bool, PROPERTY_CONNECTION_TLS); - 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 - { - startTLS(); - } - // Non-fatal error - catch (exceptions::command_error&) - { - if (tlsRequired) - { - m_state = STATE_NONE; - throw; - } - else - { - // TLS is not required, so don't bother - } - } - // Fatal error - catch (...) - { - m_state = STATE_NONE; - throw; - } - } -#endif // VMIME_HAVE_TLS_SUPPORT - - // Authentication - if (needAuth) - { - try - { - authenticate(); - } - catch (...) - { - m_state = STATE_NONE; - throw; - } - } - - // Get the hierarchy separator character - initHierarchySeparator(); - - // Switch to state "Authenticated" - setState(STATE_AUTHENTICATED); -} - - -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 - { - authenticateSASL(); - return; - } - catch (exceptions::authentication_error& e) - { - if (!GET_PROPERTY(bool, PROPERTY_OPTIONS_SASL_FALLBACK)) - { - // Can't fallback on normal authentication - internalDisconnect(); - throw e; - } - else - { - // Ignore, will try normal authentication - } - } - catch (exception& e) - { - internalDisconnect(); - throw e; - } - } -#endif // VMIME_HAVE_SASL_SUPPORT - - // Normal authentication - const string username = getAuthenticator()->getUsername(); - const string password = getAuthenticator()->getPassword(); - - send(true, "LOGIN " + IMAPUtils::quoteString(username) - + " " + IMAPUtils::quoteString(password), true); - - std::auto_ptr resp(m_parser->readResponse()); - - 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) - { - internalDisconnect(); - throw exceptions::authentication_error(resp->getErrorLog()); - } - - // Server capabilities may change when logged in - if (!processCapabilityResponseData(resp.get())) - invalidateCapabilities(); -} - - -#if VMIME_HAVE_SASL_SUPPORT - -void IMAPConnection::authenticateSASL() -{ - if (!dynamicCast (getAuthenticator())) - throw exceptions::authentication_error("No SASL authenticator available."); - - const std::vector capa = getCapabilities(); - std::vector saslMechs; - - for (unsigned int i = 0 ; i < capa.size() ; ++i) - { - const string& x = capa[i]; - - if (x.length() > 5 && - (x[0] == 'A' || x[0] == 'a') && - (x[1] == 'U' || x[1] == 'u') && - (x[2] == 'T' || x[2] == 't') && - (x[3] == 'H' || x[3] == 'h') && - x[4] == '=') - { - saslMechs.push_back(string(x.begin() + 5, x.end())); - } - } - - if (saslMechs.empty()) - throw exceptions::authentication_error("No SASL mechanism available."); - - std::vector > mechList; - - shared_ptr saslContext = - make_shared (); - - 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()) - throw exceptions::authentication_error("No SASL mechanism available."); - - // Try to suggest a mechanism among all those supported - shared_ptr suggestedMech = - saslContext->suggestMechanism(mechList); - - if (!suggestedMech) - throw exceptions::authentication_error("Unable to suggest SASL mechanism."); - - // Allow application to choose which mechanisms to use - mechList = dynamicCast (getAuthenticator())-> - getAcceptableMechanisms(mechList, suggestedMech); - - 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) - { - shared_ptr mech = mechList[i]; - - shared_ptr saslSession = - saslContext->createSession("imap", getAuthenticator(), mech); - - saslSession->init(); - - send(true, "AUTHENTICATE " + mech->getName(), true); - - for (bool cont = true ; cont ; ) - { - std::auto_ptr 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) - { - m_socket = saslSession->getSecuredSocket(m_socket); - return; - } - else - { - std::vector - 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()) - { - response = respDataList[i]->continue_req()->resp_text()->text(); - hasResponse = true; - break; - } - } - - if (!hasResponse) - { - cont = false; - continue; - } - - byte_t* challenge = 0; - size_t challengeLen = 0; - - byte_t* resp = 0; - size_t respLen = 0; - - try - { - // Extract challenge - saslContext->decodeB64(response, &challenge, &challengeLen); - - // Prepare response - saslSession->evaluateChallenge - (challenge, challengeLen, &resp, &respLen); - - // Send response - send(false, saslContext->encodeB64(resp, respLen), true); - - // Server capabilities may change when logged in - invalidateCapabilities(); - } - catch (exceptions::sasl_exception& e) - { - if (challenge) - { - delete [] challenge; - challenge = NULL; - } - - if (resp) - { - delete [] resp; - resp = NULL; - } - - // Cancel SASL exchange - send(false, "*", true); - } - catch (...) - { - if (challenge) - delete [] challenge; - - if (resp) - delete [] resp; - - throw; - } - - if (challenge) - delete [] challenge; - - if (resp) - delete [] resp; - } - } - } - - throw exceptions::authentication_error - ("Could not authenticate using SASL: all mechanisms failed."); -} - -#endif // VMIME_HAVE_SASL_SUPPORT - - -#if VMIME_HAVE_TLS_SUPPORT - -void IMAPConnection::startTLS() -{ - try - { - send(true, "STARTTLS", true); - - std::auto_ptr 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"); - } - - shared_ptr tlsSession = tls::TLSSession::create - (m_store.lock()->getCertificateVerifier(), - m_store.lock()->getSession()->getTLSProperties()); - - shared_ptr tlsSocket = - tlsSession->getSocket(m_socket); - - tlsSocket->handshake(m_timeoutHandler); - - m_socket = tlsSocket; - m_parser->setSocket(m_socket); - - m_secured = true; - m_cntInfos = make_shared - (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 - // CAPABILITY command. This is necessary to protect against - // man-in-the-middle attacks which alter the capabilities list prior - // to STARTTLS. " (RFC-2595) - invalidateCapabilities(); - } - catch (exceptions::command_error&) - { - // Non-fatal error - throw; - } - catch (exception&) - { - // Fatal error - internalDisconnect(); - throw; - } -} - -#endif // VMIME_HAVE_TLS_SUPPORT - - -const std::vector IMAPConnection::getCapabilities() -{ - if (!m_capabilitiesFetched) - fetchCapabilities(); - - return m_capabilities; -} - - -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) - return true; - } - - return false; -} - - -void IMAPConnection::invalidateCapabilities() -{ - m_capabilities.clear(); - m_capabilitiesFetched = false; -} - - -void IMAPConnection::fetchCapabilities() -{ - send(true, "CAPABILITY", true); - - std::auto_ptr resp(m_parser->readResponse()); - - if (resp->response_done()->response_tagged()-> - resp_cond_state()->status() == IMAPParser::resp_cond_state::OK) - { - processCapabilityResponseData(resp.get()); - } -} - - -bool IMAPConnection::processCapabilityResponseData(const IMAPParser::response* resp) -{ - const std::vector & respDataList = - resp->continue_req_or_response_data(); - - 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) - continue; - - processCapabilityResponseData(capaData); - return true; - } - - return false; -} - - -void IMAPConnection::processCapabilityResponseData(const IMAPParser::capability_data* capaData) -{ - std::vector res; - - std::vector caps = capaData->capabilities(); - - for (unsigned int j = 0 ; j < caps.size() ; ++j) - { - if (caps[j]->auth_type()) - res.push_back("AUTH=" + caps[j]->auth_type()->name()); - else - res.push_back(utility::stringUtils::toUpper(caps[j]->atom()->value())); - } - - m_capabilities = res; - m_capabilitiesFetched = true; -} - - -shared_ptr 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::isSecuredConnection() const -{ - return m_secured; -} - - -shared_ptr IMAPConnection::getConnectionInfos() const -{ - return m_cntInfos; -} - - -void IMAPConnection::disconnect() -{ - if (!isConnected()) - throw exceptions::not_connected(); - - internalDisconnect(); -} - - -void IMAPConnection::internalDisconnect() -{ - if (isConnected()) - { - send(true, "LOGOUT", true); - - m_socket->disconnect(); - m_socket = null; - } - - m_timeoutHandler = null; - - m_state = STATE_LOGOUT; - - m_secured = false; - m_cntInfos = null; -} - - -void IMAPConnection::initHierarchySeparator() -{ - send(true, "LIST \"\" \"\"", true); - - std::auto_ptr resp(m_parser->readResponse()); - - if (resp->isBad() || resp->response_done()->response_tagged()-> - resp_cond_state()->status() != IMAPParser::resp_cond_state::OK) - { - internalDisconnect(); - throw exceptions::command_error("LIST", resp->getErrorLog(), "bad response"); - } - - const std::vector & respDataList = - resp->continue_req_or_response_data(); - - bool found = false; - - for (unsigned int i = 0 ; !found && i < respDataList.size() ; ++i) - { - if (respDataList[i]->response_data() == NULL) - continue; - - const IMAPParser::mailbox_data* mailboxData = - static_cast - (respDataList[i]->response_data())->mailbox_data(); - - if (mailboxData == NULL || mailboxData->type() != IMAPParser::mailbox_data::LIST) - continue; - - if (mailboxData->mailbox_list()->quoted_char() != '\0') - { - m_hierarchySeparator = mailboxData->mailbox_list()->quoted_char(); - found = true; - } - } - - if (!found) // default - m_hierarchySeparator = '/'; -} - - -void IMAPConnection::send(bool tag, const string& what, bool end) -{ - if (tag && !m_firstTag) - ++(*m_tag); - -#if VMIME_DEBUG - std::ostringstream oss; - - if (tag) - { - oss << string(*m_tag); - oss << " "; - } - - oss << what; - - if (end) - oss << "\r\n"; - - m_socket->send(oss.str()); -#else - if (tag) - { - m_socket->send(*m_tag); - m_socket->send(" "); - } - - m_socket->send(what); - - if (end) - { - m_socket->send("\r\n"); - } -#endif - - if (tag) - m_firstTag = false; -} - - -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)); -} - - -IMAPConnection::ProtocolStates IMAPConnection::state() const -{ - return (m_state); -} - - -void IMAPConnection::setState(const ProtocolStates state) -{ - m_state = state; -} - - -char IMAPConnection::hierarchySeparator() const -{ - return (m_hierarchySeparator); -} - - -shared_ptr IMAPConnection::getStore() const -{ - return m_store.lock(); -} - - -shared_ptr IMAPConnection::getStore() -{ - return m_store.lock(); -} - - -shared_ptr IMAPConnection::getSession() -{ - return m_store.lock()->getSession(); -} - - -shared_ptr IMAPConnection::getSocket() const -{ - return m_socket; -} - - -bool IMAPConnection::isMODSEQDisabled() const -{ - return m_noModSeq; -} - - -void IMAPConnection::disableMODSEQ() -{ - m_noModSeq = true; -} - - -} // imap -} // net -} // vmime - - -#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_IMAP - diff --git a/src/net/imap/IMAPFolder.cpp b/src/net/imap/IMAPFolder.cpp deleted file mode 100644 index fb98887c..00000000 --- a/src/net/imap/IMAPFolder.cpp +++ /dev/null @@ -1,1511 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// 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 && VMIME_HAVE_MESSAGING_PROTO_IMAP - - -#include "vmime/net/imap/IMAPFolder.hpp" - -#include "vmime/net/imap/IMAPStore.hpp" -#include "vmime/net/imap/IMAPParser.hpp" -#include "vmime/net/imap/IMAPMessage.hpp" -#include "vmime/net/imap/IMAPUtils.hpp" -#include "vmime/net/imap/IMAPConnection.hpp" -#include "vmime/net/imap/IMAPFolderStatus.hpp" - -#include "vmime/message.hpp" - -#include "vmime/exception.hpp" - -#include "vmime/utility/outputStreamAdapter.hpp" - -#include -#include - - -namespace vmime { -namespace net { -namespace imap { - - -IMAPFolder::IMAPFolder(const folder::path& path, shared_ptr store, const int type, const int flags) - : 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_type(type), m_flags(flags) -{ - store->registerFolder(this); - - m_status = make_shared (); -} - - -IMAPFolder::~IMAPFolder() -{ - shared_ptr store = m_store.lock(); - - if (store) - { - if (m_open) - close(false); - - store->unregisterFolder(this); - } - else if (m_open) - { - m_connection = null; - onClose(); - } -} - - -int IMAPFolder::getMode() const -{ - if (!isOpen()) - throw exceptions::illegal_state("Folder not open"); - - return (m_mode); -} - - -int IMAPFolder::getType() -{ - if (!isOpen()) - throw exceptions::illegal_state("Folder not open"); - - // Root folder - if (m_path.isEmpty()) - { - return (TYPE_CONTAINS_FOLDERS); - } - else - { - if (m_type == TYPE_UNDEFINED) - testExistAndGetType(); - - return (m_type); - } -} - - -int IMAPFolder::getFlags() -{ - if (!isOpen()) - throw exceptions::illegal_state("Folder not open"); - - // Root folder - if (m_path.isEmpty()) - { - return (FLAG_CHILDREN | FLAG_NO_OPEN); - } - else - { - if (m_flags == FLAG_UNDEFINED) - testExistAndGetType(); - - return (m_flags); - } -} - - -const folder::path::component IMAPFolder::getName() const -{ - return (m_name); -} - - -const folder::path IMAPFolder::getFullPath() const -{ - return (m_path); -} - - -void IMAPFolder::open(const int mode, bool failIfModeIsNotAvailable) -{ - shared_ptr store = m_store.lock(); - - if (!store) - throw exceptions::illegal_state("Store disconnected"); - - // Ensure this folder is not already open in the same session - for (std::list ::iterator it = store->m_folders.begin() ; - 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 connection = - make_shared (store, store->getAuthenticator()); - - try - { - connection->connect(); - - // Emit the "SELECT" command - // - // Example: C: A142 SELECT INBOX - // S: * 172 EXISTS - // S: * 1 RECENT - // S: * OK [UNSEEN 12] Message 12 is first unseen - // S: * OK [UIDVALIDITY 3857529045] UIDs valid - // S: * FLAGS (\Answered \Flagged \Deleted \Seen \Draft) - // S: * OK [PERMANENTFLAGS (\Deleted \Seen \*)] Limited - // S: A142 OK [READ-WRITE] SELECT completed - - std::ostringstream oss; - - if (mode == MODE_READ_ONLY) - oss << "EXAMINE "; - else - oss << "SELECT "; - - oss << IMAPUtils::quoteString(IMAPUtils::pathToString - (connection->hierarchySeparator(), getFullPath())); - - if (m_connection->hasCapability("CONDSTORE")) - oss << " (CONDSTORE)"; - - connection->send(true, oss.str(), true); - - // Read the response - std::auto_ptr 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"); - } - - const std::vector & respDataList = - resp->continue_req_or_response_data(); - - for (std::vector ::const_iterator - 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()) - { - 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: - - connection->disableMODSEQ(); - break; - - default: - - break; - } - } - } - // Untagged responses: FLAGS, EXISTS, RECENT (required) - else if (responseData->mailbox_data()) - { - switch (responseData->mailbox_data()->type()) - { - default: break; - - case IMAPParser::mailbox_data::FLAGS: - { - m_type = IMAPUtils::folderTypeFromFlags - (responseData->mailbox_data()->mailbox_flag_list()); - - m_flags = IMAPUtils::folderFlagsFromFlags - (responseData->mailbox_data()->mailbox_flag_list()); - - break; - } - - } - } - } - - processStatusUpdate(resp.get()); - - // Check for access mode (read-only or read-write) - const IMAPParser::resp_text_code* respTextCode = resp->response_done()-> - response_tagged()->resp_cond_state()->resp_text()->resp_text_code(); - - if (respTextCode) - { - const int openMode = - (respTextCode->type() == IMAPParser::resp_text_code::READ_WRITE) - ? MODE_READ_WRITE : MODE_READ_ONLY; - - if (failIfModeIsNotAvailable && - 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&) - { - throw; - } -} - - -void IMAPFolder::close(const bool expunge) -{ - shared_ptr store = m_store.lock(); - - if (!store) - throw exceptions::illegal_state("Store disconnected"); - - if (!isOpen()) - throw exceptions::illegal_state("Folder not open"); - - shared_ptr 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) - throw exceptions::operation_not_supported(); - - oldConnection->send(true, "CLOSE", true); - } - - // Close this folder connection - oldConnection->disconnect(); - - // Now use default store connection - m_connection = m_store.lock()->connection(); - - m_open = false; - m_mode = -1; - - m_status = make_shared (); - - onClose(); -} - - -void IMAPFolder::onClose() -{ - for (std::vector ::iterator it = m_messages.begin() ; - it != m_messages.end() ; ++it) - { - (*it)->onFolderClosed(); - } - - m_messages.clear(); -} - - -void IMAPFolder::create(const int type) -{ - shared_ptr store = m_store.lock(); - - if (!store) - throw exceptions::illegal_state("Store disconnected"); - else if (isOpen()) - throw exceptions::illegal_state("Folder is open"); - else if (exists()) - throw exceptions::illegal_state("Folder already exists"); - else if (!store->isValidFolderName(m_name)) - throw exceptions::invalid_folder_name(); - - // Emit the "CREATE" command - // - // Example: C: A003 CREATE owatagusiam/ - // S: A003 OK CREATE completed - // C: A004 CREATE owatagusiam/blurdybloop - // S: A004 OK CREATE completed - - string mailbox = IMAPUtils::pathToString - (m_connection->hierarchySeparator(), getFullPath()); - - if (type & TYPE_CONTAINS_FOLDERS) - mailbox += m_connection->hierarchySeparator(); - - std::ostringstream oss; - oss << "CREATE " << IMAPUtils::quoteString(mailbox); - - m_connection->send(true, oss.str(), true); - - - std::auto_ptr 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"); - } - - // Notify folder created - shared_ptr event = - make_shared - (dynamicCast (shared_from_this()), - events::folderEvent::TYPE_CREATED, m_path, m_path); - - notifyFolder(event); -} - - -void IMAPFolder::destroy() -{ - shared_ptr store = m_store.lock(); - - if (!store) - throw exceptions::illegal_state("Store disconnected"); - - if (isOpen()) - throw exceptions::illegal_state("Folder is open"); - - const string mailbox = IMAPUtils::pathToString - (m_connection->hierarchySeparator(), getFullPath()); - - std::ostringstream oss; - oss << "DELETE " << IMAPUtils::quoteString(mailbox); - - m_connection->send(true, oss.str(), true); - - - std::auto_ptr 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"); - } - - // Notify folder deleted - shared_ptr event = - make_shared - (dynamicCast (shared_from_this()), - events::folderEvent::TYPE_DELETED, m_path, m_path); - - notifyFolder(event); -} - - -bool IMAPFolder::exists() -{ - shared_ptr store = m_store.lock(); - - if (!isOpen() && !store) - throw exceptions::illegal_state("Store disconnected"); - - return (testExistAndGetType() != TYPE_UNDEFINED); -} - - -int IMAPFolder::testExistAndGetType() -{ - m_type = TYPE_UNDEFINED; - - // To test whether a folder exists, we simple list it using - // the "LIST" command, and there should be one unique mailbox - // with this name... - // - // Eg. Test whether '/foo/bar' exists - // - // C: a005 list "" foo/bar - // S: * LIST (\NoSelect) "/" foo/bar - // S: a005 OK LIST completed - // - // ==> OK, exists - // - // Test whether '/foo/bar/zap' exists - // - // C: a005 list "" foo/bar/zap - // S: a005 OK LIST completed - // - // ==> NO, does not exist - - std::ostringstream oss; - oss << "LIST \"\" "; - oss << IMAPUtils::quoteString(IMAPUtils::pathToString - (m_connection->hierarchySeparator(), getFullPath())); - - m_connection->send(true, oss.str(), true); - - - std::auto_ptr 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"); - } - - // Check whether the result mailbox list contains this folder - const std::vector & respDataList = - resp->continue_req_or_response_data(); - - for (std::vector ::const_iterator - 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) - { - // Get the folder type/flags at the same time - m_type = IMAPUtils::folderTypeFromFlags - (mailboxData->mailbox_list()->mailbox_flag_list()); - - m_flags = IMAPUtils::folderFlagsFromFlags - (mailboxData->mailbox_list()->mailbox_flag_list()); - } - } - - return (m_type); -} - - -bool IMAPFolder::isOpen() const -{ - return (m_open); -} - - -shared_ptr IMAPFolder::getMessage(const int num) -{ - if (!isOpen()) - throw exceptions::illegal_state("Folder not open"); - - if (num < 1 || num > m_status->getMessageCount()) - throw exceptions::message_not_found(); - - return make_shared (dynamicCast (shared_from_this()), num); -} - - -std::vector > IMAPFolder::getMessages(const messageSet& msgs) -{ - if (!isOpen()) - throw exceptions::illegal_state("Folder not open"); - - if (msgs.isEmpty()) - return std::vector >(); - - std::vector > messages; - - if (msgs.isNumberSet()) - { - const std::vector numbers = IMAPUtils::messageSetToNumberList(msgs); - - shared_ptr thisFolder = dynamicCast (shared_from_this()); - - for (std::vector ::const_iterator it = numbers.begin() ; it != numbers.end() ; ++it) - messages.push_back(make_shared (thisFolder, *it)); - } - else if (msgs.isUIDSet()) - { - // C: . UID FETCH uuuu1,uuuu2,uuuu3 UID - // S: * nnnn1 FETCH (UID uuuu1) - // S: * nnnn2 FETCH (UID uuuu2) - // S: * nnnn3 FETCH (UID uuuu3) - // S: . OK UID FETCH completed - - // Prepare command and arguments - std::ostringstream cmd; - cmd.imbue(std::locale::classic()); - - cmd << "UID FETCH " << IMAPUtils::messageSetToSequenceSet(msgs) << " UID"; - - // Send the request - m_connection->send(true, cmd.str(), true); - - // Get the response - std::auto_ptr 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("UID FETCH ... UID", resp->getErrorLog(), "bad response"); - } - - // Process the response - const std::vector & respDataList = - resp->continue_req_or_response_data(); - - for (std::vector ::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"); - } - - 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) - continue; - - // Get Process fetch response for this message - const int msgNum = static_cast (messageData->number()); - message::uid msgUID; - - // Find UID in message attributes - const std::vector atts = messageData->msg_att()->items(); - - for (std::vector ::const_iterator - it = atts.begin() ; it != atts.end() ; ++it) - { - if ((*it)->type() == IMAPParser::msg_att_item::UID) - { - msgUID = (*it)->unique_id()->value(); - break; - } - } - - if (!msgUID.empty()) - { - shared_ptr thisFolder = dynamicCast (shared_from_this()); - messages.push_back(make_shared (thisFolder, msgNum, msgUID)); - } - } - } - - return messages; -} - - -int IMAPFolder::getMessageCount() -{ - if (!isOpen()) - throw exceptions::illegal_state("Folder not open"); - - return m_status->getMessageCount(); -} - - -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()) - throw exceptions::illegal_state("Folder not open"); - - return m_status->getHighestModSeq(); -} - - -shared_ptr IMAPFolder::getFolder(const folder::path::component& name) -{ - shared_ptr store = m_store.lock(); - - if (!store) - throw exceptions::illegal_state("Store disconnected"); - - return make_shared (m_path / name, store); -} - - -std::vector > IMAPFolder::getFolders(const bool recursive) -{ - shared_ptr store = m_store.lock(); - - if (!isOpen() && !store) - throw exceptions::illegal_state("Store disconnected"); - - // Eg. List folders in '/foo/bar' - // - // C: a005 list "foo/bar" * - // S: * LIST (\NoSelect) "/" foo/bar - // S: * LIST (\NoInferiors) "/" foo/bar/zap - // S: a005 OK LIST completed - - std::ostringstream oss; - oss << "LIST "; - - const string pathString = IMAPUtils::pathToString - (m_connection->hierarchySeparator(), getFullPath()); - - if (recursive) - { - oss << IMAPUtils::quoteString(pathString); - oss << " *"; - } - else - { - if (pathString.empty()) // don't add sep for root folder - oss << "\"\""; - else - oss << IMAPUtils::quoteString(pathString + m_connection->hierarchySeparator()); - - oss << " %"; - } - - m_connection->send(true, oss.str(), true); - - - std::auto_ptr 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"); - } - - const std::vector & respDataList = - resp->continue_req_or_response_data(); - - - std::vector > v; - - for (std::vector ::const_iterator - 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) - 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()); - - 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(); - - v.push_back(make_shared (path, store, - IMAPUtils::folderTypeFromFlags(mailbox_flag_list), - IMAPUtils::folderFlagsFromFlags(mailbox_flag_list))); - } - } - - return (v); -} - - -void IMAPFolder::fetchMessages(std::vector >& msg, const fetchAttributes& options, - utility::progressListener* progress) -{ - shared_ptr store = m_store.lock(); - - if (!store) - throw exceptions::illegal_state("Store disconnected"); - else if (!isOpen()) - throw exceptions::illegal_state("Folder not open"); - - // Build message numbers list - std::vector list; - list.reserve(msg.size()); - - std::map > numberToMsg; - - for (std::vector >::iterator it = msg.begin() ; it != msg.end() ; ++it) - { - list.push_back((*it)->getNumber()); - numberToMsg[(*it)->getNumber()] = dynamicCast (*it); - } - - // Send the request - const string command = IMAPUtils::buildFetchRequest - (m_connection, messageSet::byNumber(list), options); - - m_connection->send(true, command, true); - - // Get the response - std::auto_ptr 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"); - } - - const std::vector & respDataList = - resp->continue_req_or_response_data(); - - const size_t total = msg.size(); - size_t current = 0; - - if (progress) - progress->start(total); - - try - { - for (std::vector ::const_iterator - 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) - continue; - - // Process fetch response for this message - const int num = static_cast (messageData->number()); - - std::map >::iterator msg = numberToMsg.find(num); - - if (msg != numberToMsg.end()) - { - (*msg).second->processFetchResponse(options, messageData); - - if (progress) - progress->progress(++current, total); - } - } - } - catch (...) - { - if (progress) - progress->stop(total); - - throw; - } - - if (progress) - progress->stop(total); - - processStatusUpdate(resp.get()); -} - - -void IMAPFolder::fetchMessage(shared_ptr msg, const fetchAttributes& options) -{ - std::vector > msgs; - msgs.push_back(msg); - - fetchMessages(msgs, options, /* progress */ NULL); -} - - -int IMAPFolder::getFetchCapabilities() const -{ - return fetchAttributes::ENVELOPE | fetchAttributes::CONTENT_INFO | - fetchAttributes::STRUCTURE | fetchAttributes::FLAGS | - fetchAttributes::SIZE | fetchAttributes::FULL_HEADER | - fetchAttributes::UID | fetchAttributes::IMPORTANCE; -} - - -shared_ptr IMAPFolder::getParent() -{ - if (m_path.isEmpty()) - return null; - else - return make_shared (m_path.getParent(), m_store.lock()); -} - - -shared_ptr IMAPFolder::getStore() const -{ - return m_store.lock(); -} - - -shared_ptr IMAPFolder::getStore() -{ - return m_store.lock(); -} - - -void IMAPFolder::registerMessage(IMAPMessage* msg) -{ - m_messages.push_back(msg); -} - - -void IMAPFolder::unregisterMessage(IMAPMessage* msg) -{ - std::vector ::iterator it = - std::find(m_messages.begin(), m_messages.end(), msg); - - if (it != m_messages.end()) - m_messages.erase(it); -} - - -void IMAPFolder::onStoreDisconnected() -{ - m_store.reset(); -} - - -void IMAPFolder::deleteMessages(const messageSet& msgs) -{ - shared_ptr store = m_store.lock(); - - if (msgs.isEmpty()) - throw exceptions::invalid_argument(); - - if (!store) - throw exceptions::illegal_state("Store disconnected"); - else if (!isOpen()) - throw exceptions::illegal_state("Folder not open"); - else if (m_mode == MODE_READ_ONLY) - throw exceptions::illegal_state("Folder is read-only"); - - // Build the request text - std::ostringstream command; - command.imbue(std::locale::classic()); - - if (msgs.isUIDSet()) - command << "UID STORE " << IMAPUtils::messageSetToSequenceSet(msgs); - else - command << "STORE " << IMAPUtils::messageSetToSequenceSet(msgs); - - command << " +FLAGS (\\Deleted)"; - - // Send the request - m_connection->send(true, command.str(), true); - - // Get the response - std::auto_ptr 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"); - } - - processStatusUpdate(resp.get()); -} - - -void IMAPFolder::setMessageFlags(const messageSet& msgs, const int flags, const int mode) -{ - // Build the request text - std::ostringstream command; - command.imbue(std::locale::classic()); - - if (msgs.isUIDSet()) - command << "UID STORE " << IMAPUtils::messageSetToSequenceSet(msgs); - else - command << "STORE " << IMAPUtils::messageSetToSequenceSet(msgs); - - switch (mode) - { - case message::FLAG_MODE_ADD: command << " +FLAGS "; break; - case message::FLAG_MODE_REMOVE: command << " -FLAGS "; break; - default: - case message::FLAG_MODE_SET: command << " FLAGS "; break; - } - - const string flagList = IMAPUtils::messageFlagList(flags); - - if (!flagList.empty()) - { - command << flagList; - - // Send the request - m_connection->send(true, command.str(), true); - - // Get the response - std::auto_ptr 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"); - } - - processStatusUpdate(resp.get()); - } -} - - -void IMAPFolder::addMessage(shared_ptr msg, const int flags, - vmime::datetime* date, utility::progressListener* progress) -{ - std::ostringstream oss; - utility::outputStreamAdapter ossAdapter(oss); - - msg->generate(ossAdapter); - - const string& str = oss.str(); - utility::inputStreamStringAdapter strAdapter(str); - - addMessage(strAdapter, str.length(), flags, date, progress); -} - - -void IMAPFolder::addMessage(utility::inputStream& is, const size_t size, const int flags, - vmime::datetime* date, utility::progressListener* progress) -{ - shared_ptr store = m_store.lock(); - - if (!store) - throw exceptions::illegal_state("Store disconnected"); - else if (!isOpen()) - throw exceptions::illegal_state("Folder not open"); - else if (m_mode == MODE_READ_ONLY) - throw exceptions::illegal_state("Folder is read-only"); - - // Build the request text - std::ostringstream command; - command.imbue(std::locale::classic()); - - command << "APPEND " << IMAPUtils::quoteString(IMAPUtils::pathToString - (m_connection->hierarchySeparator(), getFullPath())) << ' '; - - const string flagList = IMAPUtils::messageFlagList(flags); - - if (flags != message::FLAG_UNDEFINED && !flagList.empty()) - { - command << flagList; - command << ' '; - } - - if (date != NULL) - { - command << IMAPUtils::dateTime(*date); - command << ' '; - } - - command << '{' << size << '}'; - - // Send the request - m_connection->send(true, command.str(), true); - - // Get the response - std::auto_ptr resp(m_connection->readResponse()); - - bool ok = false; - const std::vector & respList - = resp->continue_req_or_response_data(); - - for (std::vector ::const_iterator - 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"); - } - - // Send message data - const size_t total = size; - size_t current = 0; - - if (progress) - progress->start(total); - - const size_t blockSize = std::min(is.getBlockSize(), - static_cast (m_connection->getSocket()->getBlockSize())); - - std::vector vbuffer(blockSize); - byte_t* buffer = &vbuffer.front(); - - while (!is.eof()) - { - // Read some data from the input stream - const size_t read = is.read(buffer, sizeof(buffer)); - current += read; - - // Put read data into socket output stream - m_connection->sendRaw(buffer, read); - - // Notify progress - if (progress) - progress->progress(current, total); - } - - m_connection->send(false, "", true); - - if (progress) - progress->stop(total); - - // Get the response - std::auto_ptr 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"); - } - - processStatusUpdate(resp.get()); -} - - -void IMAPFolder::expunge() -{ - shared_ptr store = m_store.lock(); - - if (!store) - throw exceptions::illegal_state("Store disconnected"); - else if (!isOpen()) - throw exceptions::illegal_state("Folder not open"); - else if (m_mode == MODE_READ_ONLY) - throw exceptions::illegal_state("Folder is read-only"); - - // Send the request - m_connection->send(true, "EXPUNGE", true); - - // Get the response - std::auto_ptr 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"); - } - - processStatusUpdate(resp.get()); -} - - -void IMAPFolder::rename(const folder::path& newPath) -{ - shared_ptr store = m_store.lock(); - - if (!store) - throw exceptions::illegal_state("Store disconnected"); - 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") - throw exceptions::illegal_operation("Cannot rename 'INBOX' folder"); - else if (!store->isValidFolderName(newPath.getLastComponent())) - throw exceptions::invalid_folder_name(); - - // Build the request text - std::ostringstream command; - command.imbue(std::locale::classic()); - - command << "RENAME "; - command << IMAPUtils::quoteString(IMAPUtils::pathToString - (m_connection->hierarchySeparator(), getFullPath())) << " "; - command << IMAPUtils::quoteString(IMAPUtils::pathToString - (m_connection->hierarchySeparator(), newPath)); - - // Send the request - m_connection->send(true, command.str(), true); - - // Get the response - std::auto_ptr 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"); - } - - // Notify folder renamed - folder::path oldPath(m_path); - - m_path = newPath; - m_name = newPath.getLastComponent(); - - shared_ptr event = - make_shared - (dynamicCast (shared_from_this()), - events::folderEvent::TYPE_RENAMED, oldPath, newPath); - - notifyFolder(event); - - // Notify sub-folders - for (std::list ::iterator it = store->m_folders.begin() ; - 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 event = - make_shared - (dynamicCast ((*it)->shared_from_this()), - events::folderEvent::TYPE_RENAMED, oldPath, (*it)->m_path); - - (*it)->notifyFolder(event); - } - } - - processStatusUpdate(resp.get()); -} - - -void IMAPFolder::copyMessages(const folder::path& dest, const messageSet& set) -{ - shared_ptr store = m_store.lock(); - - if (!store) - throw exceptions::illegal_state("Store disconnected"); - else if (!isOpen()) - throw exceptions::illegal_state("Folder not open"); - - // Build the request text - std::ostringstream command; - command.imbue(std::locale::classic()); - - command << "COPY " << IMAPUtils::messageSetToSequenceSet(set) << " "; - command << IMAPUtils::quoteString(IMAPUtils::pathToString - (m_connection->hierarchySeparator(), dest)); - - // Send the request - m_connection->send(true, command.str(), true); - - // Get the response - std::auto_ptr 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"); - } - - processStatusUpdate(resp.get()); -} - - -void IMAPFolder::status(int& count, int& unseen) -{ - count = 0; - unseen = 0; - - shared_ptr status = getStatus(); - - count = status->getMessageCount(); - unseen = status->getUnseenCount(); -} - - -shared_ptr IMAPFolder::getStatus() -{ - shared_ptr store = m_store.lock(); - - if (!store) - throw exceptions::illegal_state("Store disconnected"); - - // Build the request text - std::ostringstream command; - command.imbue(std::locale::classic()); - - command << "STATUS "; - command << IMAPUtils::quoteString(IMAPUtils::pathToString - (m_connection->hierarchySeparator(), getFullPath())); - command << " ("; - - command << "MESSAGES" << ' ' << "UNSEEN" << ' ' << "UIDNEXT" << ' ' << "UIDVALIDITY"; - - if (m_connection->hasCapability("CONDSTORE")) - command << ' ' << "HIGHESTMODSEQ"; - - command << ")"; - - // Send the request - m_connection->send(true, command.str(), true); - - // Get the response - std::auto_ptr 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"); - } - - const std::vector & respDataList = - resp->continue_req_or_response_data(); - - for (std::vector ::const_iterator - 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) - { - shared_ptr status = make_shared (); - status->updateFromResponse(responseData->mailbox_data()); - - m_status->updateFromResponse(responseData->mailbox_data()); - - return status; - } - } - } - - throw exceptions::command_error("STATUS", - resp->getErrorLog(), "invalid response"); -} - - -void IMAPFolder::noop() -{ - shared_ptr store = m_store.lock(); - - if (!store) - throw exceptions::illegal_state("Store disconnected"); - - m_connection->send(true, "NOOP", true); - - std::auto_ptr 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("NOOP", resp->getErrorLog()); - } - - processStatusUpdate(resp.get()); -} - - -std::vector IMAPFolder::getMessageNumbersStartingOnUID(const message::uid& uid) -{ - std::vector v; - - std::ostringstream command; - command.imbue(std::locale::classic()); - - command << "SEARCH UID " << uid << ":*"; - - // Send the request - m_connection->send(true, command.str(), true); - - // Get the response - std::auto_ptr 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"); - } - - const std::vector & respDataList = resp->continue_req_or_response_data(); - - for (std::vector ::const_iterator - 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 = - (*it)->response_data()->mailbox_data(); - - // We are only interested in responses of type "SEARCH" - if (mailboxData == NULL || - mailboxData->type() != IMAPParser::mailbox_data::SEARCH) - { - continue; - } - - for (std::vector ::const_iterator - it = mailboxData->search_nz_number_list().begin() ; - it != mailboxData->search_nz_number_list().end(); - ++it) - { - v.push_back((*it)->value()); - } - } - - processStatusUpdate(resp.get()); - - return v; -} - - -void IMAPFolder::processStatusUpdate(const IMAPParser::response* resp) -{ - std::vector > events; - - shared_ptr oldStatus = vmime::clone(m_status); - int expungedMessageCount = 0; - - // 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()) - { - const IMAPParser::resp_text_code* code = - resp->response_done()->response_tagged() - ->resp_cond_state()->resp_text()->resp_text_code(); - - m_status->updateFromResponse(code); - } - - // Process untagged responses - for (std::vector ::const_iterator - it = resp->continue_req_or_response_data().begin() ; - 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()) - { - 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()) - { - m_status->updateFromResponse((*it)->response_data()->mailbox_data()); - } - else if ((*it)->response_data() && (*it)->response_data()->message_data()) - { - const IMAPParser::message_data* msgData = (*it)->response_data()->message_data(); - const int msgNumber = msgData->number(); - - if ((*it)->response_data()->message_data()->type() == IMAPParser::message_data::FETCH) - { - // Message changed - for (std::vector ::iterator mit = - m_messages.begin() ; mit != m_messages.end() ; ++mit) - { - if ((*mit)->getNumber() == msgNumber) - (*mit)->processFetchResponse(/* options */ 0, msgData); - } - - events.push_back(make_shared - (dynamicCast (shared_from_this()), - events::messageChangedEvent::TYPE_FLAGS, - std::vector (1, msgNumber))); - } - else if ((*it)->response_data()->message_data()->type() == IMAPParser::message_data::EXPUNGE) - { - // A message has been expunged, renumber messages - for (std::vector ::iterator jt = - m_messages.begin() ; jt != m_messages.end() ; ++jt) - { - if ((*jt)->getNumber() == msgNumber) - (*jt)->setExpunged(); - else if ((*jt)->getNumber() > msgNumber) - (*jt)->renumber((*jt)->getNumber() - 1); - } - - events.push_back(make_shared - (dynamicCast (shared_from_this()), - events::messageCountEvent::TYPE_REMOVED, - std::vector (1, msgNumber))); - - expungedMessageCount++; - } - } - } - - // New messages arrived - if (m_status->getMessageCount() > oldStatus->getMessageCount() - expungedMessageCount) - { - std::vector newMessageNumbers; - - for (int msgNumber = oldStatus->getMessageCount() - expungedMessageCount ; - msgNumber <= m_status->getMessageCount() ; ++msgNumber) - { - newMessageNumbers.push_back(msgNumber); - } - - events.push_back(make_shared - (dynamicCast (shared_from_this()), - events::messageCountEvent::TYPE_ADDED, - newMessageNumbers)); - } - - // Dispatch notifications - for (std::vector >::iterator evit = - events.begin() ; evit != events.end() ; ++evit) - { - notifyEvent(*evit); - } -} - - -} // imap -} // net -} // vmime - - -#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_IMAP - diff --git a/src/net/imap/IMAPFolderStatus.cpp b/src/net/imap/IMAPFolderStatus.cpp deleted file mode 100644 index c78a40f3..00000000 --- a/src/net/imap/IMAPFolderStatus.cpp +++ /dev/null @@ -1,307 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// 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 && VMIME_HAVE_MESSAGING_PROTO_IMAP - - -#include "vmime/net/imap/IMAPFolderStatus.hpp" - - -namespace vmime { -namespace net { -namespace imap { - - -IMAPFolderStatus::IMAPFolderStatus() - : m_count(0), - m_unseen(0), - m_recent(0), - m_uidValidity(0), - m_uidNext(0), - m_highestModSeq(0) -{ -} - - -IMAPFolderStatus::IMAPFolderStatus(const IMAPFolderStatus& other) - : folderStatus(), - m_count(other.m_count), - m_unseen(other.m_unseen), - m_recent(other.m_recent), - m_uidValidity(other.m_uidValidity), - m_uidNext(other.m_uidNext), - m_highestModSeq(other.m_highestModSeq) -{ -} - - -unsigned int IMAPFolderStatus::getMessageCount() const -{ - return m_count; -} - - -unsigned int IMAPFolderStatus::getUnseenCount() const -{ - return m_unseen; -} - - -unsigned int IMAPFolderStatus::getRecentCount() const -{ - return m_recent; -} - - -vmime_uint32 IMAPFolderStatus::getUIDValidity() const -{ - return m_uidValidity; -} - - -vmime_uint32 IMAPFolderStatus::getUIDNext() const -{ - return m_uidNext; -} - - -vmime_uint64 IMAPFolderStatus::getHighestModSeq() const -{ - return m_highestModSeq; -} - - -shared_ptr IMAPFolderStatus::clone() const -{ - return make_shared (*this); -} - - -bool IMAPFolderStatus::updateFromResponse(const IMAPParser::mailbox_data* resp) -{ - bool changed = false; - - if (resp->type() == IMAPParser::mailbox_data::STATUS) - { - const IMAPParser::status_att_list* statusAttList = resp->status_att_list(); - - for (std::vector ::const_iterator - jt = statusAttList->values().begin() ; jt != statusAttList->values().end() ; ++jt) - { - switch ((*jt)->type()) - { - case IMAPParser::status_att_val::MESSAGES: - { - const unsigned int count = - static_cast ((*jt)->value_as_number()->value()); - - if (m_count != count) - { - m_count = count; - changed = true; - } - - break; - } - case IMAPParser::status_att_val::UNSEEN: - { - const unsigned int unseen = - static_cast ((*jt)->value_as_number()->value()); - - if (m_unseen != unseen) - { - m_unseen = unseen; - changed = true; - } - - break; - } - case IMAPParser::status_att_val::RECENT: - { - const unsigned int recent = - static_cast ((*jt)->value_as_number()->value()); - - if (m_recent != recent) - { - m_recent = recent; - changed = true; - } - - break; - } - case IMAPParser::status_att_val::UIDNEXT: - { - const vmime_uint32 uidNext = - static_cast ((*jt)->value_as_number()->value()); - - if (m_uidNext != uidNext) - { - m_uidNext = uidNext; - changed = true; - } - - break; - } - case IMAPParser::status_att_val::UIDVALIDITY: - { - const vmime_uint32 uidValidity = - static_cast ((*jt)->value_as_number()->value()); - - if (m_uidValidity != uidValidity) - { - m_uidValidity = uidValidity; - changed = true; - } - - break; - } - case IMAPParser::status_att_val::HIGHESTMODSEQ: - { - const vmime_uint64 highestModSeq = - static_cast ((*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) - { - const unsigned int count = - static_cast (resp->number()->value()); - - if (m_count != count) - { - m_count = count; - changed = true; - } - } - else if (resp->type() == IMAPParser::mailbox_data::RECENT) - { - const unsigned int recent = - static_cast (resp->number()->value()); - - if (m_recent != recent) - { - m_recent = recent; - changed = true; - } - } - - return changed; -} - - -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 (resp->nz_number()->value()); - - if (m_uidValidity != uidValidity) - { - m_uidValidity = uidValidity; - changed = true; - } - - break; - } - case IMAPParser::resp_text_code::UIDNEXT: - { - const vmime_uint32 uidNext = - static_cast (resp->nz_number()->value()); - - if (m_uidNext != uidNext) - { - m_uidNext = uidNext; - changed = true; - } - - break; - } - case IMAPParser::resp_text_code::UNSEEN: - { - const unsigned int unseen = - static_cast (resp->nz_number()->value()); - - if (m_unseen != unseen) - { - m_unseen = unseen; - changed = true; - } - - break; - } - case IMAPParser::resp_text_code::HIGHESTMODSEQ: - { - const vmime_uint64 highestModSeq = - static_cast (resp->mod_sequence_value()->value()); - - if (m_highestModSeq != highestModSeq) - { - m_highestModSeq = highestModSeq; - changed = true; - } - - break; - } - case IMAPParser::resp_text_code::NOMODSEQ: - { - if (m_highestModSeq != 0) - { - m_highestModSeq = 0; - changed = true; - } - - break; - } - default: - - break; - } - - return changed; -} - - -} // imap -} // net -} // vmime - - -#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_IMAP diff --git a/src/net/imap/IMAPMessage.cpp b/src/net/imap/IMAPMessage.cpp deleted file mode 100644 index c11aafc2..00000000 --- a/src/net/imap/IMAPMessage.cpp +++ /dev/null @@ -1,649 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// 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 && VMIME_HAVE_MESSAGING_PROTO_IMAP - - -#include "vmime/net/imap/IMAPParser.hpp" -#include "vmime/net/imap/IMAPMessage.hpp" -#include "vmime/net/imap/IMAPFolder.hpp" -#include "vmime/net/imap/IMAPFolderStatus.hpp" -#include "vmime/net/imap/IMAPStore.hpp" -#include "vmime/net/imap/IMAPConnection.hpp" -#include "vmime/net/imap/IMAPUtils.hpp" -#include "vmime/net/imap/IMAPMessageStructure.hpp" -#include "vmime/net/imap/IMAPMessagePart.hpp" -#include "vmime/net/imap/IMAPMessagePartContentHandler.hpp" - -#include "vmime/utility/outputStreamAdapter.hpp" - -#include -#include -#include - - -namespace vmime { -namespace net { -namespace imap { - - -#ifndef VMIME_BUILDING_DOC - -// -// IMAPMessage_literalHandler -// - -class IMAPMessage_literalHandler : public IMAPParser::literalHandler -{ -public: - - IMAPMessage_literalHandler(utility::outputStream& os, utility::progressListener* progress) - : m_os(os), m_progress(progress) - { - } - - target* targetFor(const IMAPParser::component& comp, const int /* data */) - { - if (typeid(comp) == typeid(IMAPParser::msg_att_item)) - { - const int type = static_cast - (comp).type(); - - if (type == IMAPParser::msg_att_item::BODY_SECTION || - type == IMAPParser::msg_att_item::RFC822_TEXT) - { - return new targetStream(m_progress, m_os); - } - } - - return (NULL); - } - -private: - - utility::outputStream& m_os; - utility::progressListener* m_progress; -}; - -#endif // VMIME_BUILDING_DOC - - - -// -// IMAPMessage -// - - -IMAPMessage::IMAPMessage(shared_ptr folder, const int 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 folder, const int 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() -{ - shared_ptr folder = m_folder.lock(); - - if (folder) - folder->unregisterMessage(this); -} - - -void IMAPMessage::onFolderClosed() -{ - m_folder.reset(); -} - - -int IMAPMessage::getNumber() const -{ - return (m_num); -} - - -const message::uid IMAPMessage::getUID() const -{ - return m_uid; -} - - -vmime_uint64 IMAPMessage::getModSequence() const -{ - return m_modseq; -} - - -size_t IMAPMessage::getSize() const -{ - if (m_size == -1U) - throw exceptions::unfetched_object(); - - return (m_size); -} - - -bool IMAPMessage::isExpunged() const -{ - return (m_expunged); -} - - -int IMAPMessage::getFlags() const -{ - if (m_flags == FLAG_UNDEFINED) - throw exceptions::unfetched_object(); - - return (m_flags); -} - - -shared_ptr IMAPMessage::getStructure() const -{ - if (m_structure == NULL) - throw exceptions::unfetched_object(); - - return m_structure; -} - - -shared_ptr IMAPMessage::getStructure() -{ - if (m_structure == NULL) - throw exceptions::unfetched_object(); - - return m_structure; -} - - -shared_ptr IMAPMessage::getHeader() const -{ - if (m_header == NULL) - throw exceptions::unfetched_object(); - - return (m_header); -} - - -void IMAPMessage::extract - (utility::outputStream& os, - utility::progressListener* progress, - const size_t start, const size_t length, - const bool peek) const -{ - shared_ptr folder = m_folder.lock(); - - if (!folder) - throw exceptions::folder_not_found(); - - extractImpl(null, os, progress, start, length, - EXTRACT_HEADER | EXTRACT_BODY | (peek ? EXTRACT_PEEK : 0)); -} - - -void IMAPMessage::extractPart - (shared_ptr p, - utility::outputStream& os, - utility::progressListener* progress, - const size_t start, const size_t length, - const bool peek) const -{ - shared_ptr folder = m_folder.lock(); - - if (!folder) - throw exceptions::folder_not_found(); - - extractImpl(p, os, progress, start, length, - EXTRACT_HEADER | EXTRACT_BODY | (peek ? EXTRACT_PEEK : 0)); -} - - -void IMAPMessage::fetchPartHeader(shared_ptr p) -{ - shared_ptr folder = m_folder.lock(); - - if (!folder) - throw exceptions::folder_not_found(); - - std::ostringstream oss; - utility::outputStreamAdapter ossAdapter(oss); - - extractImpl(p, ossAdapter, NULL, 0, -1, EXTRACT_HEADER | EXTRACT_PEEK); - - dynamicCast (p)->getOrCreateHeader().parse(oss.str()); -} - - -void IMAPMessage::fetchPartHeaderForStructure(shared_ptr str) -{ - for (size_t i = 0, n = str->getPartCount() ; i < n ; ++i) - { - shared_ptr part = str->getPartAt(i); - - // Fetch header of current part - fetchPartHeader(part); - - // Fetch header of sub-parts - fetchPartHeaderForStructure(part->getStructure()); - } -} - - -void IMAPMessage::extractImpl - (shared_ptr p, - utility::outputStream& os, - utility::progressListener* progress, - const size_t start, const size_t length, - const int extractFlags) const -{ - shared_ptr folder = m_folder.lock(); - - IMAPMessage_literalHandler literalHandler(os, progress); - - // Construct section identifier - std::ostringstream section; - section.imbue(std::locale::classic()); - - if (p != NULL) - { - shared_ptr currentPart = dynamicCast (p); - std::vector numbers; - - numbers.push_back(currentPart->getNumber()); - currentPart = currentPart->getParent(); - - while (currentPart != NULL) - { - numbers.push_back(currentPart->getNumber()); - currentPart = currentPart->getParent(); - } - - numbers.erase(numbers.end() - 1); - - for (std::vector ::reverse_iterator it = numbers.rbegin() ; it != numbers.rend() ; ++it) - { - if (it != numbers.rbegin()) section << "."; - section << (*it + 1); - } - } - - // Build the request text - std::ostringstream command; - command.imbue(std::locale::classic()); - - if (m_uid.empty()) - command << "FETCH " << m_num << " BODY"; - else - command << "UID FETCH " << m_uid << " BODY"; - - /* - BODY[] header + body - BODY.PEEK[] header + body (peek) - BODY[HEADER] header - BODY.PEEK[HEADER] header (peek) - BODY[TEXT] body - BODY.PEEK[TEXT] body (peek) - */ - - if (extractFlags & EXTRACT_PEEK) - command << ".PEEK"; - - command << "["; - - if (section.str().empty()) - { - // header + body - if ((extractFlags & EXTRACT_HEADER) && (extractFlags & EXTRACT_BODY)) - command << ""; - // body only - else if (extractFlags & EXTRACT_BODY) - command << "TEXT"; - // header only - else if (extractFlags & EXTRACT_HEADER) - command << "HEADER"; - } - else - { - command << section.str(); - - // header + body - if ((extractFlags & EXTRACT_HEADER) && (extractFlags & EXTRACT_BODY)) - throw exceptions::operation_not_supported(); - // body only - else if (extractFlags & EXTRACT_BODY) - command << ".TEXT"; - // header only - else if (extractFlags & EXTRACT_HEADER) - command << ".MIME"; // "MIME" not "HEADER" for parts - } - - command << "]"; - - if (start != 0 || length != static_cast (-1)) - command << "<" << start << "." << length << ">"; - - // Send the request - constCast (folder)->m_connection->send(true, command.str(), true); - - // Get the response - std::auto_ptr resp - (constCast (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"); - } - - - if (extractFlags & EXTRACT_BODY) - { - // TODO: update the flags (eg. flag "\Seen" may have been set) - } -} - - -int IMAPMessage::processFetchResponse - (const fetchAttributes& options, const IMAPParser::message_data* msgData) -{ - shared_ptr folder = m_folder.lock(); - - // Get message attributes - const std::vector atts = msgData->msg_att()->items(); - int changes = 0; - - for (std::vector ::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; - } - - 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 hdr = getOrCreateHeader(); - - // Date - hdr->Date()->setValue(env->env_date()->value()); - - // Subject - text subject; - text::decodeAndUnfold(env->env_subject()->value(), &subject); - - hdr->Subject()->setValue(subject); - - // From - mailboxList from; - IMAPUtils::convertAddressList(*(env->env_from()), from); - - if (!from.isEmpty()) - hdr->From()->setValue(*(from.getMailboxAt(0))); - - // To - mailboxList to; - IMAPUtils::convertAddressList(*(env->env_to()), to); - - hdr->To()->setValue(to.toAddressList()); - - // Sender - mailboxList sender; - IMAPUtils::convertAddressList(*(env->env_sender()), sender); - - if (!sender.isEmpty()) - hdr->Sender()->setValue(*(sender.getMailboxAt(0))); - - // Reply-to - mailboxList replyTo; - IMAPUtils::convertAddressList(*(env->env_reply_to()), replyTo); - - if (!replyTo.isEmpty()) - hdr->ReplyTo()->setValue(*(replyTo.getMailboxAt(0))); - - // Cc - mailboxList cc; - IMAPUtils::convertAddressList(*(env->env_cc()), cc); - - if (!cc.isEmpty()) - hdr->Cc()->setValue(cc); - - // Bcc - mailboxList bcc; - IMAPUtils::convertAddressList(*(env->env_bcc()), bcc); - - if (!bcc.isEmpty()) - hdr->Bcc()->setValue(bcc); - } - - break; - } - case IMAPParser::msg_att_item::BODY_STRUCTURE: - { - m_structure = make_shared ((*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 ((*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 > fields = tempHeader.getFieldList(); - - for (std::vector >::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; - } - - } - } - - return changes; -} - - -shared_ptr
IMAPMessage::getOrCreateHeader() -{ - if (m_header != NULL) - return (m_header); - else - return (m_header = make_shared
()); -} - - -void IMAPMessage::setFlags(const int flags, const int mode) -{ - shared_ptr folder = m_folder.lock(); - - if (!folder) - throw exceptions::folder_not_found(); - - if (!m_uid.empty()) - folder->setMessageFlags(messageSet::byUID(m_uid), flags, mode); - else - folder->setMessageFlags(messageSet::byNumber(m_num), flags, mode); -} - - -void IMAPMessage::constructParsedMessage - (shared_ptr parentPart, shared_ptr str, int level) -{ - if (level == 0) - { - shared_ptr part = str->getPartAt(0); - - // Copy header - shared_ptr hdr = part->getHeader(); - parentPart->getHeader()->copyFrom(*hdr); - - // Initialize body - parentPart->getBody()->setContents - (make_shared - (dynamicCast (shared_from_this()), - part, parentPart->getBody()->getEncoding())); - - constructParsedMessage(parentPart, part->getStructure(), 1); - } - else - { - for (size_t i = 0, n = str->getPartCount() ; i < n ; ++i) - { - shared_ptr part = str->getPartAt(i); - - shared_ptr childPart = make_shared (); - - // Copy header - shared_ptr hdr = part->getHeader(); - childPart->getHeader()->copyFrom(*hdr); - - // Initialize body - childPart->getBody()->setContents - (make_shared - (dynamicCast (shared_from_this()), - part, childPart->getBody()->getEncoding())); - - // Add child part - parentPart->getBody()->appendPart(childPart); - - // Construct sub parts - constructParsedMessage(childPart, part->getStructure(), ++level); - } - } -} - - -shared_ptr IMAPMessage::getParsedMessage() -{ - // Fetch structure - shared_ptr structure; - - try - { - structure = getStructure(); - } - catch (exceptions::unfetched_object&) - { - std::vector > msgs; - msgs.push_back(dynamicCast (shared_from_this())); - - m_folder.lock()->fetchMessages - (msgs, fetchAttributes(fetchAttributes::STRUCTURE), /* progress */ NULL); - - structure = getStructure(); - } - - // Fetch header for each part - fetchPartHeaderForStructure(structure); - - // Construct message from structure - shared_ptr msg = make_shared (); - - constructParsedMessage(msg, structure); - - return msg; -} - - -void IMAPMessage::renumber(const int number) -{ - m_num = number; -} - - -void IMAPMessage::setExpunged() -{ - m_expunged = true; -} - - -} // imap -} // net -} // vmime - - -#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_IMAP - diff --git a/src/net/imap/IMAPMessagePart.cpp b/src/net/imap/IMAPMessagePart.cpp deleted file mode 100644 index eed885dc..00000000 --- a/src/net/imap/IMAPMessagePart.cpp +++ /dev/null @@ -1,161 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// 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 && VMIME_HAVE_MESSAGING_PROTO_IMAP - - -#include "vmime/net/imap/IMAPMessagePart.hpp" -#include "vmime/net/imap/IMAPMessageStructure.hpp" - - -namespace vmime { -namespace net { -namespace imap { - - -IMAPMessagePart::IMAPMessagePart(shared_ptr parent, const int 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 parent, const int 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()); - - m_size = part->body_type_basic()->body_fields()->body_fld_octets()->value(); - } - - m_structure = null; -} - - -shared_ptr IMAPMessagePart::getStructure() const -{ - if (m_structure != NULL) - return m_structure; - else - return IMAPMessageStructure::emptyStructure(); -} - - -shared_ptr IMAPMessagePart::getStructure() -{ - if (m_structure != NULL) - return m_structure; - else - return IMAPMessageStructure::emptyStructure(); -} - - -shared_ptr IMAPMessagePart::getParent() const -{ - return m_parent.lock(); -} - - -const mediaType& IMAPMessagePart::getType() const -{ - return m_mediaType; -} - - -size_t IMAPMessagePart::getSize() const -{ - return m_size; -} - - -int IMAPMessagePart::getNumber() const -{ - return m_number; -} - - -shared_ptr IMAPMessagePart::getHeader() const -{ - if (m_header == NULL) - throw exceptions::unfetched_object(); - else - return m_header; -} - - -// static -shared_ptr IMAPMessagePart::create - (shared_ptr parent, const int number, const IMAPParser::body* body) -{ - if (body->body_type_mpart()) - { - shared_ptr part = make_shared (parent, number, body->body_type_mpart()); - part->m_structure = make_shared (part, body->body_type_mpart()->list()); - - return part; - } - else - { - return make_shared (parent, number, body->body_type_1part()); - } -} - - -header& IMAPMessagePart::getOrCreateHeader() -{ - if (m_header != NULL) - return *m_header; - else - return *(m_header = make_shared
()); -} - - -} // imap -} // net -} // vmime - - -#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_IMAP - diff --git a/src/net/imap/IMAPMessagePartContentHandler.cpp b/src/net/imap/IMAPMessagePartContentHandler.cpp deleted file mode 100644 index 1f53f082..00000000 --- a/src/net/imap/IMAPMessagePartContentHandler.cpp +++ /dev/null @@ -1,216 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// 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 && VMIME_HAVE_MESSAGING_PROTO_IMAP - - -#include "vmime/net/imap/IMAPMessagePartContentHandler.hpp" -#include "vmime/net/imap/IMAPFolder.hpp" -#include "vmime/net/imap/IMAPConnection.hpp" -#include "vmime/net/imap/IMAPFolderStatus.hpp" -#include "vmime/net/imap/IMAPStore.hpp" - -#include "vmime/utility/outputStreamAdapter.hpp" -#include "vmime/utility/inputStreamStringProxyAdapter.hpp" - - -namespace vmime { -namespace net { -namespace imap { - - -IMAPMessagePartContentHandler::IMAPMessagePartContentHandler - (shared_ptr msg, shared_ptr part, const vmime::encoding& encoding) - : m_message(msg), m_part(part), m_encoding(encoding) -{ -} - - -shared_ptr IMAPMessagePartContentHandler::clone() const -{ - return make_shared - (constCast (m_message.lock()), - constCast (m_part.lock()), - m_encoding); -} - - -void IMAPMessagePartContentHandler::generate - (utility::outputStream& os, const vmime::encoding& enc, const size_t maxLineLength) const -{ - shared_ptr msg = constCast (m_message.lock()); - shared_ptr part = constCast (m_part.lock()); - - // Data is already encoded - 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) - { - // Extract part contents to temporary buffer - std::ostringstream oss; - utility::outputStreamAdapter tmp(oss); - - msg->extractPart(part, tmp, NULL); - - // Decode to another temporary buffer - utility::inputStreamStringProxyAdapter in(oss.str()); - - std::ostringstream oss2; - utility::outputStreamAdapter tmp2(oss2); - - shared_ptr theDecoder = m_encoding.getEncoder(); - theDecoder->decode(in, tmp2); - - // Reencode to output stream - string str = oss2.str(); - utility::inputStreamStringAdapter tempIn(str); - - shared_ptr theEncoder = enc.getEncoder(); - theEncoder->getProperties()["maxlinelength"] = maxLineLength; - theEncoder->getProperties()["text"] = (m_contentType.getType() == mediaTypes::TEXT); - - theEncoder->encode(tempIn, os); - } - // No encoding to perform - else - { - msg->extractPart(part, os); - } - } - // Need to encode data before - else - { - // Extract part contents to temporary buffer - std::ostringstream oss; - utility::outputStreamAdapter tmp(oss); - - msg->extractPart(part, tmp, NULL); - - // Encode temporary buffer to output stream - shared_ptr theEncoder = enc.getEncoder(); - theEncoder->getProperties()["maxlinelength"] = maxLineLength; - theEncoder->getProperties()["text"] = (m_contentType.getType() == mediaTypes::TEXT); - - utility::inputStreamStringAdapter is(oss.str()); - - theEncoder->encode(is, os); - } -} - - -void IMAPMessagePartContentHandler::extract - (utility::outputStream& os, utility::progressListener* progress) const -{ - shared_ptr msg = constCast (m_message.lock()); - shared_ptr part = constCast (m_part.lock()); - - // No decoding to perform - if (!isEncoded()) - { - msg->extractImpl(part, os, progress, 0, -1, IMAPMessage::EXTRACT_BODY); - } - // Need to decode data - else - { - // Extract part contents to temporary buffer - std::ostringstream oss; - utility::outputStreamAdapter tmp(oss); - - msg->extractImpl(part, tmp, NULL, 0, -1, IMAPMessage::EXTRACT_BODY); - - // Encode temporary buffer to output stream - utility::inputStreamStringAdapter is(oss.str()); - utility::progressListenerSizeAdapter plsa(progress, getLength()); - - shared_ptr theDecoder = m_encoding.getEncoder(); - theDecoder->decode(is, os, &plsa); - } -} - - -void IMAPMessagePartContentHandler::extractRaw - (utility::outputStream& os, utility::progressListener* progress) const -{ - shared_ptr msg = constCast (m_message.lock()); - shared_ptr part = constCast (m_part.lock()); - - msg->extractPart(part, os, progress); -} - - -size_t IMAPMessagePartContentHandler::getLength() const -{ - return m_part.lock()->getSize(); -} - - -bool IMAPMessagePartContentHandler::isEncoded() const -{ - return m_encoding != NO_ENCODING; -} - - -const vmime::encoding& IMAPMessagePartContentHandler::getEncoding() const -{ - return m_encoding; -} - - -bool IMAPMessagePartContentHandler::isEmpty() const -{ - return getLength() == 0; -} - - -bool IMAPMessagePartContentHandler::isBuffered() const -{ - return true; -} - - -void IMAPMessagePartContentHandler::setContentTypeHint(const mediaType& type) -{ - m_contentType = type; -} - - -const mediaType IMAPMessagePartContentHandler::getContentTypeHint() const -{ - return m_contentType; -} - - -} // imap -} // net -} // vmime - - -#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_IMAP - diff --git a/src/net/imap/IMAPMessageStructure.cpp b/src/net/imap/IMAPMessageStructure.cpp deleted file mode 100644 index 8dc333e9..00000000 --- a/src/net/imap/IMAPMessageStructure.cpp +++ /dev/null @@ -1,94 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// 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 && VMIME_HAVE_MESSAGING_PROTO_IMAP - - -#include "vmime/net/imap/IMAPMessageStructure.hpp" -#include "vmime/net/imap/IMAPMessagePart.hpp" - - -namespace vmime { -namespace net { -namespace imap { - - -IMAPMessageStructure::IMAPMessageStructure() -{ -} - - -IMAPMessageStructure::IMAPMessageStructure(const IMAPParser::body* body) -{ - m_parts.push_back(IMAPMessagePart::create(null, 0, body)); -} - - -IMAPMessageStructure::IMAPMessageStructure(shared_ptr parent, const std::vector & list) -{ - int number = 0; - - for (std::vector ::const_iterator - it = list.begin() ; it != list.end() ; ++it, ++number) - { - m_parts.push_back(IMAPMessagePart::create(parent, number, *it)); - } -} - - -shared_ptr IMAPMessageStructure::getPartAt(const size_t x) const -{ - return m_parts[x]; -} - - -shared_ptr IMAPMessageStructure::getPartAt(const size_t x) -{ - return m_parts[x]; -} - - -size_t IMAPMessageStructure::getPartCount() const -{ - return m_parts.size(); -} - - -// static -shared_ptr IMAPMessageStructure::emptyStructure() -{ - static shared_ptr emptyStructure = make_shared (); - return emptyStructure; -} - - -} // imap -} // net -} // vmime - - -#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_IMAP - diff --git a/src/net/imap/IMAPSStore.cpp b/src/net/imap/IMAPSStore.cpp deleted file mode 100644 index c9e64f5b..00000000 --- a/src/net/imap/IMAPSStore.cpp +++ /dev/null @@ -1,79 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// 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 && VMIME_HAVE_MESSAGING_PROTO_IMAP - - -#include "vmime/net/imap/IMAPSStore.hpp" - - -namespace vmime { -namespace net { -namespace imap { - - -IMAPSStore::IMAPSStore(shared_ptr sess, shared_ptr auth) - : IMAPStore(sess, auth, true) -{ -} - - -IMAPSStore::~IMAPSStore() -{ -} - - -const string IMAPSStore::getProtocolName() const -{ - return "imaps"; -} - - - -// Service infos - -IMAPServiceInfos IMAPSStore::sm_infos(true); - - -const serviceInfos& IMAPSStore::getInfosInstance() -{ - return sm_infos; -} - - -const serviceInfos& IMAPSStore::getInfos() const -{ - return sm_infos; -} - - -} // imap -} // net -} // vmime - - -#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_IMAP - diff --git a/src/net/imap/IMAPServiceInfos.cpp b/src/net/imap/IMAPServiceInfos.cpp deleted file mode 100644 index 46dbc2e1..00000000 --- a/src/net/imap/IMAPServiceInfos.cpp +++ /dev/null @@ -1,137 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// 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 && VMIME_HAVE_MESSAGING_PROTO_IMAP - - -#include "vmime/net/imap/IMAPServiceInfos.hpp" - - -namespace vmime { -namespace net { -namespace imap { - - -IMAPServiceInfos::IMAPServiceInfos(const bool imaps) - : m_imaps(imaps) -{ -} - - -const string IMAPServiceInfos::getPropertyPrefix() const -{ - if (m_imaps) - return "store.imaps."; - else - return "store.imap."; -} - - -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"), - property("options.sasl.fallback", serviceInfos::property::TYPE_BOOLEAN, "true"), -#endif // VMIME_HAVE_SASL_SUPPORT - - // Common properties - property(serviceInfos::property::AUTH_USERNAME, serviceInfos::property::FLAG_REQUIRED), - property(serviceInfos::property::AUTH_PASSWORD, serviceInfos::property::FLAG_REQUIRED), - -#if VMIME_HAVE_TLS_SUPPORT - property(serviceInfos::property::CONNECTION_TLS), - property(serviceInfos::property::CONNECTION_TLS_REQUIRED), -#endif // VMIME_HAVE_TLS_SUPPORT - - property(serviceInfos::property::SERVER_ADDRESS, serviceInfos::property::FLAG_REQUIRED), - property(serviceInfos::property::SERVER_PORT, "143"), - }; - - static props imapsProps = - { - // IMAP-specific options -#if VMIME_HAVE_SASL_SUPPORT - property("options.sasl", serviceInfos::property::TYPE_BOOLEAN, "true"), - property("options.sasl.fallback", serviceInfos::property::TYPE_BOOLEAN, "true"), -#endif // VMIME_HAVE_SASL_SUPPORT - - // Common properties - property(serviceInfos::property::AUTH_USERNAME, serviceInfos::property::FLAG_REQUIRED), - property(serviceInfos::property::AUTH_PASSWORD, serviceInfos::property::FLAG_REQUIRED), - -#if VMIME_HAVE_TLS_SUPPORT - property(serviceInfos::property::CONNECTION_TLS), - property(serviceInfos::property::CONNECTION_TLS_REQUIRED), -#endif // VMIME_HAVE_TLS_SUPPORT - - property(serviceInfos::property::SERVER_ADDRESS, serviceInfos::property::FLAG_REQUIRED), - property(serviceInfos::property::SERVER_PORT, "993"), - }; - - return m_imaps ? imapsProps : imapProps; -} - - -const std::vector IMAPServiceInfos::getAvailableProperties() const -{ - std::vector list; - const props& p = getProperties(); - - // IMAP-specific options -#if VMIME_HAVE_SASL_SUPPORT - list.push_back(p.PROPERTY_OPTIONS_SASL); - list.push_back(p.PROPERTY_OPTIONS_SASL_FALLBACK); -#endif // VMIME_HAVE_SASL_SUPPORT - - // Common properties - list.push_back(p.PROPERTY_AUTH_USERNAME); - list.push_back(p.PROPERTY_AUTH_PASSWORD); - -#if VMIME_HAVE_TLS_SUPPORT - if (!m_imaps) - { - list.push_back(p.PROPERTY_CONNECTION_TLS); - list.push_back(p.PROPERTY_CONNECTION_TLS_REQUIRED); - } -#endif // VMIME_HAVE_TLS_SUPPORT - - list.push_back(p.PROPERTY_SERVER_ADDRESS); - list.push_back(p.PROPERTY_SERVER_PORT); - - return list; -} - - -} // imap -} // net -} // vmime - - -#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_IMAP - diff --git a/src/net/imap/IMAPStore.cpp b/src/net/imap/IMAPStore.cpp deleted file mode 100644 index a1a8c9ca..00000000 --- a/src/net/imap/IMAPStore.cpp +++ /dev/null @@ -1,267 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// 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 && VMIME_HAVE_MESSAGING_PROTO_IMAP - - -#include "vmime/net/imap/IMAPStore.hpp" -#include "vmime/net/imap/IMAPFolder.hpp" -#include "vmime/net/imap/IMAPConnection.hpp" -#include "vmime/net/imap/IMAPFolderStatus.hpp" - -#include "vmime/exception.hpp" -#include "vmime/platform.hpp" - -#include - - -namespace vmime { -namespace net { -namespace imap { - - -IMAPStore::IMAPStore(shared_ptr sess, shared_ptr auth, const bool secured) - : store(sess, getInfosInstance(), auth), m_connection(null), m_isIMAPS(secured) -{ -} - - -IMAPStore::~IMAPStore() -{ - try - { - if (isConnected()) - disconnect(); - } - catch (vmime::exception&) - { - // Ignore - } -} - - -const string IMAPStore::getProtocolName() const -{ - return "imap"; -} - - -shared_ptr IMAPStore::getRootFolder() -{ - if (!isConnected()) - throw exceptions::illegal_state("Not connected"); - - return make_shared - (folder::path(), - dynamicCast (shared_from_this())); -} - - -shared_ptr IMAPStore::getDefaultFolder() -{ - if (!isConnected()) - throw exceptions::illegal_state("Not connected"); - - return make_shared - (folder::path::component("INBOX"), - dynamicCast (shared_from_this())); -} - - -shared_ptr IMAPStore::getFolder(const folder::path& path) -{ - if (!isConnected()) - throw exceptions::illegal_state("Not connected"); - - return make_shared - (path, dynamicCast (shared_from_this())); -} - - -bool IMAPStore::isValidFolderName(const folder::path::component& /* name */) const -{ - return true; -} - - -void IMAPStore::connect() -{ - if (isConnected()) - throw exceptions::already_connected(); - - m_connection = make_shared - (dynamicCast (shared_from_this()), getAuthenticator()); - - try - { - m_connection->connect(); - } - catch (std::exception&) - { - m_connection = null; - throw; - } -} - - -bool IMAPStore::isConnected() const -{ - return (m_connection && m_connection->isConnected()); -} - - -bool IMAPStore::isIMAPS() const -{ - return m_isIMAPS; -} - - -bool IMAPStore::isSecuredConnection() const -{ - if (m_connection == NULL) - return false; - - return m_connection->isSecuredConnection(); -} - - -shared_ptr IMAPStore::getConnectionInfos() const -{ - if (m_connection == NULL) - return null; - - return m_connection->getConnectionInfos(); -} - - -shared_ptr IMAPStore::getConnection() -{ - return m_connection; -} - - -void IMAPStore::disconnect() -{ - if (!isConnected()) - throw exceptions::not_connected(); - - for (std::list ::iterator it = m_folders.begin() ; - it != m_folders.end() ; ++it) - { - (*it)->onStoreDisconnected(); - } - - m_folders.clear(); - - - m_connection->disconnect(); - - m_connection = null; -} - - -void IMAPStore::noop() -{ - if (!isConnected()) - throw exceptions::not_connected(); - - m_connection->send(true, "NOOP", true); - - std::auto_ptr 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("NOOP", resp->getErrorLog()); - } - - - for (std::list ::iterator it = m_folders.begin() ; - it != m_folders.end() ; ++it) - { - if ((*it)->isOpen()) - (*it)->noop(); - } -} - - -shared_ptr IMAPStore::connection() -{ - return (m_connection); -} - - -void IMAPStore::registerFolder(IMAPFolder* folder) -{ - m_folders.push_back(folder); -} - - -void IMAPStore::unregisterFolder(IMAPFolder* folder) -{ - std::list ::iterator it = std::find(m_folders.begin(), m_folders.end(), folder); - 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); -} - - - -// Service infos - -IMAPServiceInfos IMAPStore::sm_infos(false); - - -const serviceInfos& IMAPStore::getInfosInstance() -{ - return sm_infos; -} - - -const serviceInfos& IMAPStore::getInfos() const -{ - return sm_infos; -} - - -} // imap -} // net -} // vmime - - -#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_IMAP - diff --git a/src/net/imap/IMAPTag.cpp b/src/net/imap/IMAPTag.cpp deleted file mode 100644 index 14d12788..00000000 --- a/src/net/imap/IMAPTag.cpp +++ /dev/null @@ -1,122 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// 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 && VMIME_HAVE_MESSAGING_PROTO_IMAP - - -#include "vmime/net/imap/IMAPTag.hpp" - - -namespace vmime { -namespace net { -namespace imap { - - -const int IMAPTag::sm_maxNumber = 52 * 10 * 10 * 10; - - -IMAPTag::IMAPTag(const int number) - : m_number(number) -{ - m_tag.resize(4); - generate(); -} - - -IMAPTag::IMAPTag(const IMAPTag& tag) - : object(), m_number(tag.m_number) -{ - m_tag.resize(4); - generate(); -} - - -IMAPTag::IMAPTag() - : m_number(1) -{ - m_tag.resize(4); - generate(); -} - - -IMAPTag& IMAPTag::operator++() -{ - ++m_number; - - if (m_number >= sm_maxNumber) - m_number = 1; - - generate(); - - return (*this); -} - - -const IMAPTag IMAPTag::operator++(int) -{ - IMAPTag old(*this); - operator++(); - return (old); -} - - -int IMAPTag::maximumNumber() const -{ - return sm_maxNumber - 1; -} - - -int IMAPTag::number() const -{ - return (m_number); -} - - -IMAPTag::operator string() const -{ - return (m_tag); -} - - -void IMAPTag::generate() -{ - static const char prefixChars[53] = - "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"; - - m_tag[0] = prefixChars[m_number / 1000]; - m_tag[1] = static_cast ('0' + (m_number % 1000) / 100); - m_tag[2] = static_cast ('0' + (m_number % 100) / 10); - m_tag[3] = static_cast ('0' + m_number % 10); -} - - -} // imap -} // net -} // vmime - - -#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_IMAP - diff --git a/src/net/imap/IMAPUtils.cpp b/src/net/imap/IMAPUtils.cpp deleted file mode 100644 index ff81ce71..00000000 --- a/src/net/imap/IMAPUtils.cpp +++ /dev/null @@ -1,758 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// 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 && VMIME_HAVE_MESSAGING_PROTO_IMAP - - -#include "vmime/net/imap/IMAPUtils.hpp" -#include "vmime/net/imap/IMAPStore.hpp" - -#include "vmime/net/message.hpp" -#include "vmime/net/folder.hpp" - -#include -#include -#include - - -namespace vmime { -namespace net { -namespace imap { - - -// static -const string IMAPUtils::quoteString(const string& text) -{ - // - // ATOM_CHAR ::= - // - // atom_specials ::= "(" / ")" / "{" / SPACE / CTL / - // list_wildcards / quoted_specials - // - // list_wildcards ::= "%" / "*" - // - // quoted_specials ::= <"> / "\" - // - // CHAR ::= - // - // CTL ::= - // - - bool needQuoting = text.empty(); - - for (string::const_iterator it = text.begin() ; - !needQuoting && it != text.end() ; ++it) - { - const unsigned char c = *it; - - switch (c) - { - case '(': - case ')': - case '{': - case 0x20: // SPACE - case '%': - case '*': - case '"': - case '\\': - - needQuoting = true; - break; - - default: - - if (c <= 0x1f || c >= 0x7f) - needQuoting = true; - } - } - - if (needQuoting) - { - string quoted; - quoted.reserve((text.length() * 3) / 2 + 2); - - quoted += '"'; - - for (string::const_iterator it = text.begin() ; it != text.end() ; ++it) - { - const unsigned char c = *it; - - if (c == '\\' || c == '"') - quoted += '\\'; - - quoted += c; - } - - quoted += '"'; - - return (quoted); - } - else - { - return (text); - } -} - - -const string IMAPUtils::pathToString - (const char hierarchySeparator, const folder::path& path) -{ - string result; - - for (size_t i = 0 ; i < path.getSize() ; ++i) - { - if (i > 0) result += hierarchySeparator; - result += toModifiedUTF7(hierarchySeparator, path[i]); - } - - return (result); -} - - -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) - { - result /= fromModifiedUTF7(string(begin, it)); - begin = it + 1; - } - } - - if (begin != str.end()) - { - result /= fromModifiedUTF7(string(begin, str.end())); - } - - return (result); -} - - -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[] = - "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+,="; - - const unsigned int hs = static_cast (static_cast (hierarchySeparator)); - - string hsUTF7; - hsUTF7.resize(3); - - hsUTF7[0] = base64alphabet[0]; - hsUTF7[1] = base64alphabet[(hs & 0xF0) >> 4]; - hsUTF7[2] = base64alphabet[(hs & 0x0F) << 2]; - - // iconv() is buggy with UTF-8 to UTF-7 conversion, so we do it "by hand". - // This code is largely inspired from "imap/utf7.c", in mutt 1.4. - // Copyright (C) 2000 Edmund Grimley Evans - - // WARNING: This may throw "exceptions::charset_conv_error" - const string cvt = text.getConvertedText(charset(charsets::UTF_8)); - - // In the worst case we convert 2 chars to 7 chars. - // For example: "\x10&\x10&..." -> "&ABA-&-&ABA-&-...". - string out; - out.reserve((cvt.length() / 2) * 7 + 6); - - int b = 0, k = 0; - bool base64 = false; - - size_t remaining = cvt.length(); - - 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) - { - out += "&" + hsUTF7 + "-"; - - ++i; - --remaining; - continue; - } - - size_t n = 0; - int ch = 0; - - if (c < 0x80) - ch = c, n = 0; - else if (c < 0xc2) - return ""; - else if (c < 0xe0) - ch = c & 0x1f, n = 1; - else if (c < 0xf0) - ch = c & 0x0f, n = 2; - else if (c < 0xf8) - ch = c & 0x07, n = 3; - else if (c < 0xfc) - ch = c & 0x03, n = 4; - else if (c < 0xfe) - ch = c & 0x01, n = 5; - else - return ""; - - if (n > remaining) - return ""; // error - - ++i; - --remaining; - - 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))) - return ""; // error - - i += n; - remaining -= n; - - if (ch < 0x20 || ch >= 0x7f) - { - if (!base64) - { - out += '&'; - base64 = true; - b = 0; - k = 10; - } - - if (ch & ~0xffff) - ch = 0xfffe; - - out += base64alphabet[b | ch >> k]; - - k -= 6; - - for ( ; k >= 0 ; k -= 6) - out += base64alphabet[(ch >> k) & 0x3f]; - - b = (ch << (-k)) & 0x3f; - k += 16; - } - else - { - if (base64) - { - if (k > 10) - out += base64alphabet[b]; - - out += '-'; - base64 = false; - } - - out += static_cast (ch); - - if (ch == '&') - out += '-'; - } - } - - if (base64) - { - if (k > 10) - out += base64alphabet[b]; - - out += '-'; - } - - return (out); -} - - -const folder::path::component IMAPUtils::fromModifiedUTF7(const string& text) -{ - // Transcode from modified UTF-7 (RFC-2060). - string out; - out.reserve(text.length()); - - bool inB64sequence = false; - unsigned char prev = 0; - - 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 += '+'; - } - else - { - out += '&'; - } - - break; - } - // End of Base64 sequence (or "&-" --> "&") - case '-': - { - if (inB64sequence && prev == '&') - out += '&'; - else - out += '-'; - - inB64sequence = false; - break; - } - // ',' is used instead of '/' in modified Base64 - case ',': - { - out += (inB64sequence ? '/' : ','); - break; - } - default: - { - out += c; - break; - } - - } - - prev = c; - } - - // Store it as UTF-8 by default - string cvt; - charset::convert(out, cvt, - charset(charsets::UTF_7), charset(charsets::UTF_8)); - - return (folder::path::component(cvt, charset(charsets::UTF_8))); -} - - -int IMAPUtils::folderTypeFromFlags(const IMAPParser::mailbox_flag_list* list) -{ - // Get folder type - int type = folder::TYPE_CONTAINS_MESSAGES | folder::TYPE_CONTAINS_FOLDERS; - const std::vector & flags = list->flags(); - - for (std::vector ::const_iterator it = flags.begin() ; - it != flags.end() ; ++it) - { - if ((*it)->type() == IMAPParser::mailbox_flag::NOSELECT) - type &= ~folder::TYPE_CONTAINS_MESSAGES; - } - - if (type & folder::TYPE_CONTAINS_MESSAGES) - type &= ~folder::TYPE_CONTAINS_FOLDERS; - - return (type); -} - - -int IMAPUtils::folderFlagsFromFlags(const IMAPParser::mailbox_flag_list* list) -{ - // Get folder flags - int folderFlags = folder::FLAG_CHILDREN; - const std::vector & flags = list->flags(); - - for (std::vector ::const_iterator it = flags.begin() ; - it != flags.end() ; ++it) - { - if ((*it)->type() == IMAPParser::mailbox_flag::NOSELECT) - folderFlags |= folder::FLAG_NO_OPEN; - else if ((*it)->type() == IMAPParser::mailbox_flag::NOINFERIORS) - folderFlags &= ~folder::FLAG_CHILDREN; - } - - return (folderFlags); -} - - -int IMAPUtils::messageFlagsFromFlags(const IMAPParser::flag_list* list) -{ - const std::vector & flagList = list->flags(); - int flags = 0; - - for (std::vector ::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; - } - } - - return (flags); -} - - -const string IMAPUtils::messageFlagList(const int flags) -{ - std::vector flagList; - - if (flags & message::FLAG_REPLIED) flagList.push_back("\\Answered"); - if (flags & message::FLAG_MARKED) flagList.push_back("\\Flagged"); - if (flags & message::FLAG_DELETED) flagList.push_back("\\Deleted"); - if (flags & message::FLAG_SEEN) flagList.push_back("\\Seen"); - if (flags & message::FLAG_DRAFT) flagList.push_back("\\Draft"); - - if (!flagList.empty()) - { - std::ostringstream res; - res.imbue(std::locale::classic()); - - res << "("; - - if (flagList.size() >= 2) - { - std::copy(flagList.begin(), flagList.end() - 1, - std::ostream_iterator (res, " ")); - } - - res << *(flagList.end() - 1) << ")"; - - return (res.str()); - } - - return ""; -} - - -// static -const string IMAPUtils::dateTime(const vmime::datetime& date) -{ - std::ostringstream res; - res.imbue(std::locale::classic()); - - // date_time ::= <"> date_day_fixed "-" date_month "-" date_year - // SPACE time SPACE zone <"> - // - // time ::= 2digit ":" 2digit ":" 2digit - // ;; Hours minutes seconds - // zone ::= ("+" / "-") 4digit - // ;; Signed four-digit value of hhmm representing - // ;; hours and minutes west of Greenwich - res << '"'; - - // Date - if (date.getDay() < 10) res << ' '; - res << date.getDay(); - - res << '-'; - - 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)]; - - res << '-'; - - if (date.getYear() < 10) res << '0'; - if (date.getYear() < 100) res << '0'; - if (date.getYear() < 1000) res << '0'; - res << date.getYear(); - - res << ' '; - - // Time - if (date.getHour() < 10) res << '0'; - res << date.getHour() << ':'; - - if (date.getMinute() < 10) res << '0'; - res << date.getMinute() << ':'; - - if (date.getSecond() < 10) res << '0'; - res << date.getSecond(); - - res << ' '; - - // Zone - const int zs = (date.getZone() < 0 ? -1 : 1); - const int zh = (date.getZone() * zs) / 60; - const int zm = (date.getZone() * zs) % 60; - - res << (zs < 0 ? '-' : '+'); - - if (zh < 10) res << '0'; - res << zh; - - if (zm < 10) res << '0'; - res << zm; - - res << '"'; - - - return (res.str()); -} - - -// static -const string IMAPUtils::buildFetchRequest - (shared_ptr cnt, const messageSet& msgs, const fetchAttributes& options) -{ - // Example: - // C: A654 FETCH 2:4 (FLAGS BODY[HEADER.FIELDS (DATE FROM)]) - // S: * 2 FETCH .... - // S: * 3 FETCH .... - // S: * 4 FETCH .... - // S: A654 OK FETCH completed - - std::vector items; - - if (options.has(fetchAttributes::SIZE)) - items.push_back("RFC822.SIZE"); - - if (options.has(fetchAttributes::FLAGS)) - items.push_back("FLAGS"); - - if (options.has(fetchAttributes::STRUCTURE)) - items.push_back("BODYSTRUCTURE"); - - if (options.has(fetchAttributes::UID)) - { - items.push_back("UID"); - - // Also fetch MODSEQ if CONDSTORE is supported - if (cnt->hasCapability("CONDSTORE") && !cnt->isMODSEQDisabled()) - items.push_back("MODSEQ"); - } - - if (options.has(fetchAttributes::FULL_HEADER)) - items.push_back("RFC822.HEADER"); - else - { - if (options.has(fetchAttributes::ENVELOPE)) - items.push_back("ENVELOPE"); - - std::vector headerFields; - - if (options.has(fetchAttributes::CONTENT_INFO)) - headerFields.push_back("CONTENT_TYPE"); - - if (options.has(fetchAttributes::IMPORTANCE)) - { - headerFields.push_back("IMPORTANCE"); - headerFields.push_back("X-PRIORITY"); - } - - // Also add custom header fields to fetch, if any - const std::vector customHeaderFields = options.getHeaderFields(); - std::copy(customHeaderFields.begin(), customHeaderFields.end(), std::back_inserter(headerFields)); - - if (!headerFields.empty()) - { - string list; - - for (std::vector ::iterator it = headerFields.begin() ; - it != headerFields.end() ; ++it) - { - if (it != headerFields.begin()) - list += " "; - - list += *it; - } - - items.push_back("BODY[HEADER.FIELDS (" + list + ")]"); - } - } - - // Build the request text - std::ostringstream command; - command.imbue(std::locale::classic()); - - if (msgs.isUIDSet()) - command << "UID FETCH " << messageSetToSequenceSet(msgs) << " ("; - else - command << "FETCH " << messageSetToSequenceSet(msgs) << " ("; - - for (std::vector ::const_iterator it = items.begin() ; - it != items.end() ; ++it) - { - if (it != items.begin()) command << " "; - command << *it; - } - - command << ")"; - - return command.str(); -} - - -// static -void IMAPUtils::convertAddressList - (const IMAPParser::address_list& src, mailboxList& dest) -{ - for (std::vector ::const_iterator - it = src.addresses().begin() ; it != src.addresses().end() ; ++it) - { - const IMAPParser::address& addr = **it; - - text name; - text::decodeAndUnfold(addr.addr_name()->value(), &name); - - string email = addr.addr_mailbox()->value() - + "@" + addr.addr_host()->value(); - - dest.appendMailbox(make_shared (name, email)); - } -} - - - -class IMAPUIDMessageSetEnumerator : public messageSetEnumerator -{ -public: - - IMAPUIDMessageSetEnumerator() - : m_first(true) - { - } - - void enumerateNumberMessageRange(const vmime::net::numberMessageRange& range) - { - if (!m_first) - m_oss << ","; - - if (range.getFirst() == range.getLast()) - m_oss << range.getFirst(); - else - m_oss << range.getFirst() << ":" << range.getLast(); - - m_first = false; - } - - void enumerateUIDMessageRange(const vmime::net::UIDMessageRange& range) - { - if (!m_first) - m_oss << ","; - - if (range.getFirst() == range.getLast()) - m_oss << range.getFirst(); - else - m_oss << range.getFirst() << ":" << range.getLast(); - - m_first = false; - } - - const std::string str() const - { - return m_oss.str(); - } - -private: - - std::ostringstream m_oss; - bool m_first; -}; - - -class IMAPMessageSetEnumerator : public messageSetEnumerator -{ -public: - - void enumerateNumberMessageRange(const vmime::net::numberMessageRange& range) - { - for (int i = range.getFirst(), last = range.getLast() ; i <= last ; ++i) - m_list.push_back(i); - } - - void enumerateUIDMessageRange(const vmime::net::UIDMessageRange& /* range */) - { - // Not used - } - - const std::vector & list() const - { - return m_list; - } - -public: - - std::vector m_list; -}; - - - -// static -const string IMAPUtils::messageSetToSequenceSet(const messageSet& msgs) -{ - IMAPUIDMessageSetEnumerator en; - msgs.enumerate(en); - - return en.str(); -} - - -// static -const std::vector IMAPUtils::messageSetToNumberList(const messageSet& msgs) -{ - IMAPMessageSetEnumerator en; - msgs.enumerate(en); - - return en.list(); -} - - -} // imap -} // net -} // vmime - - -#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_IMAP - diff --git a/src/net/maildir/format/courierMaildirFormat.cpp b/src/net/maildir/format/courierMaildirFormat.cpp deleted file mode 100644 index 6d460d5e..00000000 --- a/src/net/maildir/format/courierMaildirFormat.cpp +++ /dev/null @@ -1,542 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// 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 && VMIME_HAVE_MESSAGING_PROTO_MAILDIR - - -#include "vmime/net/maildir/format/courierMaildirFormat.hpp" - -#include "vmime/net/maildir/maildirStore.hpp" -#include "vmime/net/maildir/maildirUtils.hpp" - -#include "vmime/platform.hpp" - - -namespace vmime { -namespace net { -namespace maildir { -namespace format { - - -courierMaildirFormat::courierMaildirFormat(shared_ptr ctx) - : maildirFormat(ctx) -{ -} - - -const string courierMaildirFormat::getName() const -{ - return "courier"; -} - - -void courierMaildirFormat::createFolder(const folder::path& path) -{ - shared_ptr fsf = platform::getHandler()->getFileSystemFactory(); - - if (!fsf->isValidPath(folderPathToFileSystemPath(path, ROOT_DIRECTORY))) - throw exceptions::invalid_folder_name(); - - shared_ptr rootDir = fsf->create - (folderPathToFileSystemPath(path, ROOT_DIRECTORY)); - - shared_ptr newDir = fsf->create - (folderPathToFileSystemPath(path, NEW_DIRECTORY)); - shared_ptr tmpDir = fsf->create - (folderPathToFileSystemPath(path, TMP_DIRECTORY)); - shared_ptr curDir = fsf->create - (folderPathToFileSystemPath(path, CUR_DIRECTORY)); - - rootDir->createDirectory(true); - - newDir->createDirectory(false); - tmpDir->createDirectory(false); - curDir->createDirectory(false); - - shared_ptr maildirFile = fsf->create - (folderPathToFileSystemPath(path, ROOT_DIRECTORY) - / utility::file::path::component("maildirfolder")); - - maildirFile->createFile(); -} - - -void courierMaildirFormat::destroyFolder(const folder::path& path) -{ - shared_ptr fsf = platform::getHandler()->getFileSystemFactory(); - - // Recursively delete directories of subfolders - const std::vector folders = listFolders(path, true); - - for (std::vector ::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))); -} - - -void courierMaildirFormat::renameFolder - (const folder::path& oldPath, const folder::path& newPath) -{ - const std::vector folders = listFolders(oldPath, true); - - for (std::vector ::size_type i = 0, n = folders.size() ; i < n ; ++i) - { - const folder::path folderOldPath = folders[i]; - - folder::path folderNewPath = folderOldPath; - folderNewPath.renameParent(oldPath, newPath); - - renameFolderImpl(folderOldPath, folderNewPath); - } - - renameFolderImpl(oldPath, newPath); -} - - -void courierMaildirFormat::renameFolderImpl - (const folder::path& oldPath, const folder::path& newPath) -{ - shared_ptr fsf = platform::getHandler()->getFileSystemFactory(); - - const utility::file::path oldFSPath = - folderPathToFileSystemPath(oldPath, ROOT_DIRECTORY); - - const utility::file::path newFSPath = - folderPathToFileSystemPath(newPath, ROOT_DIRECTORY); - - shared_ptr rootDir = fsf->create(oldFSPath); - rootDir->rename(newFSPath); -} - - -bool courierMaildirFormat::folderExists(const folder::path& path) const -{ - shared_ptr fsf = platform::getHandler()->getFileSystemFactory(); - - shared_ptr rootDir = fsf->create - (folderPathToFileSystemPath(path, ROOT_DIRECTORY)); - - shared_ptr newDir = fsf->create - (folderPathToFileSystemPath(path, NEW_DIRECTORY)); - shared_ptr tmpDir = fsf->create - (folderPathToFileSystemPath(path, TMP_DIRECTORY)); - shared_ptr curDir = fsf->create - (folderPathToFileSystemPath(path, CUR_DIRECTORY)); - - shared_ptr 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(); - - // If this is not the root folder, then a file named "maildirfolder" - // must also be present in the directory - if (!path.isRoot()) - exists = exists && maildirFile->exists() && maildirFile->isFile(); - - return exists; -} - - -bool courierMaildirFormat::folderHasSubfolders(const folder::path& path) const -{ - std::vector dirs; - return listDirectories(path, dirs, true); -} - - -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()) - { - string folderComp; - - 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: - - // Nothing to add - break; - - case NEW_DIRECTORY: - - fsPath /= NEW_DIR; - break; - - case CUR_DIRECTORY: - - fsPath /= CUR_DIR; - break; - - case TMP_DIRECTORY: - - fsPath /= TMP_DIR; - break; - - case CONTAINER_DIRECTORY: - - // Not used - break; - } - - return fsPath; -} - - -const std::vector courierMaildirFormat::listFolders - (const folder::path& root, const bool recursive) const -{ - // First, list directories - std::vector dirs; - listDirectories(root, dirs, false); - - // Then, map directories to folders - std::vector folders; - - for (std::vector ::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)) - { - const string comp = dir.substr(prev, pos - prev); - path /= fromModifiedUTF7(comp); - } - - if (recursive || path.getSize() == root.getSize() + 1) - folders.push_back(path); - } - - return folders; -} - - -bool courierMaildirFormat::listDirectories(const folder::path& root, - std::vector & dirs, const bool onlyTestForExistence) const -{ - shared_ptr fsf = platform::getHandler()->getFileSystemFactory(); - - shared_ptr rootDir = fsf->create - (getContext()->getStore()->getFileSystemPath()); - - 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) - base += "." + toModifiedUTF7(root[i]); - } - - // Enumerate directories - shared_ptr it = rootDir->getFiles(); - - while (it->hasMoreElements()) - { - shared_ptr file = it->nextElement(); - - if (isSubfolderDirectory(*file)) - { - const string dir = file->getFullPath().getLastComponent().getBuffer(); - - if (base.empty() || (dir.length() > base.length() && dir.substr(0, base.length()) == base)) - { - dirs.push_back(dir); - - if (onlyTestForExistence) - return true; - } - } - } - } - else - { - // No sub-folder - } - - std::sort(dirs.begin(), dirs.end()); - - return !dirs.empty(); -} - - -// static -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] == '.') - { - return true; - } - - return false; -} - - -// static -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 - // characters. US-ASCII characters, U+0x0020 - U+0x007F, except for the - // period, forward-slash, and ampersand characters (U+0x002E, U+0x002F, - // and U+0x0026) represent themselves. The ampersand is represented by - // the two character sequence "&-". The period, forward slash, and non - // US-ASCII Unicode characters are represented using the UTF-7 character - // set, and encoded with a modified form of base64-encoding. - // - // The "&" character starts the modified base64-encoded sequence; the - // sequence is terminated by the "-" character. The sequence of 16-bit - // Unicode characters is written in big-endian order, and encoded using - // the base64-encoding method described in section 5.2 of RFC 1521, with - // the following modifications: - // - // * The "=" padding character is omitted. When decoding, an incomplete - // 16-bit character is discarded. - // - // * The comma character, "," is used in place of the "/" character in - // the base64 alphabet. - // - // For example, the word "Resume" with both "e"s being the e-acute - // character, U+0x00e9, is encoded as "R&AOk-sum&AOk-" (so a folder of - // that name would be a maildir subdirectory called ".R&AOk-sum&AOk-"). - // - - // Transcode path component to UTF-7 charset. - // WARNING: This may throw "exceptions::charset_conv_error" - const string cvt = text.getConvertedText(charset(charsets::UTF_7)); - - // Transcode to modified UTF-7 (RFC-2060). - string out; - out.reserve((cvt.length() * 3) / 2); - - bool inB64sequence = false; - - 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 += '&'; - } - else - { - out += '+'; - } - - 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-"; - - 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 += '&'; - - break; - } - default: - { - out += c; - break; - } - - } - } - - return out; -} - - -// static -const folder::path::component courierMaildirFormat::fromModifiedUTF7(const string& text) -{ - // Transcode from modified UTF-7 - string out; - out.reserve(text.length()); - - bool inB64sequence = false; - unsigned char prev = 0; - - 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 += '+'; - } - else - { - out += '&'; - } - - break; - } - // End of Base64 sequence (or "&-" --> "&") - case '-': - { - if (inB64sequence && prev == '&') - out += '&'; - else - out += '-'; - - inB64sequence = false; - break; - } - // ',' is used instead of '/' in modified Base64 - case ',': - { - out += (inB64sequence ? '/' : ','); - break; - } - default: - { - out += c; - break; - } - - } - - prev = c; - } - - // Store it as UTF-8 by default - string cvt; - charset::convert(out, cvt, - charset(charsets::UTF_7), charset(charsets::UTF_8)); - - return (folder::path::component(cvt, charset(charsets::UTF_8))); -} - - -bool courierMaildirFormat::supports() const -{ - shared_ptr fsf = platform::getHandler()->getFileSystemFactory(); - - shared_ptr rootDir = fsf->create - (getContext()->getStore()->getFileSystemPath()); - - if (rootDir->exists()) - { - // Try to find a file named "maildirfolder", which indicates - // the Maildir is in Courier format - shared_ptr it = rootDir->getFiles(); - - while (it->hasMoreElements()) - { - shared_ptr file = it->nextElement(); - - if (isSubfolderDirectory(*file)) - { - shared_ptr folderFile = fsf->create - (file->getFullPath() / utility::file::path::component("maildirfolder")); - - if (folderFile->exists() && folderFile->isFile()) - return true; - } - } - } - - return false; -} - - -} // format -} // maildir -} // net -} // vmime - - -#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_MAILDIR - diff --git a/src/net/maildir/format/kmailMaildirFormat.cpp b/src/net/maildir/format/kmailMaildirFormat.cpp deleted file mode 100644 index 975752a5..00000000 --- a/src/net/maildir/format/kmailMaildirFormat.cpp +++ /dev/null @@ -1,320 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// 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 && VMIME_HAVE_MESSAGING_PROTO_MAILDIR - - -#include "vmime/net/maildir/format/kmailMaildirFormat.hpp" - -#include "vmime/net/maildir/maildirStore.hpp" -#include "vmime/net/maildir/maildirUtils.hpp" - -#include "vmime/platform.hpp" - - -namespace vmime { -namespace net { -namespace maildir { -namespace format { - - -kmailMaildirFormat::kmailMaildirFormat(shared_ptr ctx) - : maildirFormat(ctx) -{ -} - - -const string kmailMaildirFormat::getName() const -{ - return "kmail"; -} - - -void kmailMaildirFormat::createFolder(const folder::path& path) -{ - shared_ptr fsf = platform::getHandler()->getFileSystemFactory(); - - if (!fsf->isValidPath(folderPathToFileSystemPath(path, ROOT_DIRECTORY))) - throw exceptions::invalid_folder_name(); - - shared_ptr rootDir = fsf->create - (folderPathToFileSystemPath(path, ROOT_DIRECTORY)); - - shared_ptr newDir = fsf->create - (folderPathToFileSystemPath(path, NEW_DIRECTORY)); - shared_ptr tmpDir = fsf->create - (folderPathToFileSystemPath(path, TMP_DIRECTORY)); - shared_ptr curDir = fsf->create - (folderPathToFileSystemPath(path, CUR_DIRECTORY)); - - rootDir->createDirectory(true); - - newDir->createDirectory(false); - tmpDir->createDirectory(false); - curDir->createDirectory(false); -} - - -void kmailMaildirFormat::destroyFolder(const folder::path& path) -{ - // Delete 'folder' and '.folder.directory' directories - shared_ptr fsf = platform::getHandler()->getFileSystemFactory(); - - maildirUtils::recursiveFSDelete(fsf->create - (folderPathToFileSystemPath(path, ROOT_DIRECTORY))); // root - - maildirUtils::recursiveFSDelete(fsf->create - (folderPathToFileSystemPath(path, CONTAINER_DIRECTORY))); // container -} - - -bool kmailMaildirFormat::folderExists(const folder::path& path) const -{ - shared_ptr fsf = platform::getHandler()->getFileSystemFactory(); - - shared_ptr rootDir = fsf->create - (folderPathToFileSystemPath(path, ROOT_DIRECTORY)); - - shared_ptr newDir = fsf->create - (folderPathToFileSystemPath(path, NEW_DIRECTORY)); - shared_ptr tmpDir = fsf->create - (folderPathToFileSystemPath(path, TMP_DIRECTORY)); - shared_ptr curDir = fsf->create - (folderPathToFileSystemPath(path, CUR_DIRECTORY)); - - return rootDir->exists() && rootDir->isDirectory() && - newDir->exists() && newDir->isDirectory() && - tmpDir->exists() && tmpDir->isDirectory() && - curDir->exists() && curDir->isDirectory(); -} - - -const utility::file::path kmailMaildirFormat::folderPathToFileSystemPath - (const folder::path& path, const DirectoryType type) const -{ - // Root path - utility::file::path fsPath = getContext()->getStore()->getFileSystemPath(); - - const size_t pathSize = path.getSize(); - const size_t count = (type == CONTAINER_DIRECTORY - ? pathSize : (pathSize >= 1 ? pathSize - 1 : 0)); - - // Parent folders - for (size_t i = 0 ; i < count ; ++i) - { - utility::file::path::component comp(path[i]); - - // TODO: may not work with all encodings... - comp.setBuffer("." + comp.getBuffer() + ".directory"); - - fsPath /= comp; - } - - // Last component - if (path.getSize() != 0 && type != CONTAINER_DIRECTORY) - { - fsPath /= path.getLastComponent(); - - switch (type) - { - case ROOT_DIRECTORY: - - // Nothing to add - break; - - case NEW_DIRECTORY: - - fsPath /= NEW_DIR; - break; - - case CUR_DIRECTORY: - - fsPath /= CUR_DIR; - break; - - case TMP_DIRECTORY: - - fsPath /= TMP_DIR; - break; - - case CONTAINER_DIRECTORY: - - // Can't happen... - break; - } - } - - return fsPath; -} - - -const std::vector kmailMaildirFormat::listFolders - (const folder::path& root, const bool recursive) const -{ - std::vector list; - listFoldersImpl(list, root, recursive); - - return list; -} - - -void kmailMaildirFormat::listFoldersImpl - (std::vector & list, const folder::path& root, const bool recursive) const -{ - shared_ptr fsf = platform::getHandler()->getFileSystemFactory(); - - shared_ptr rootDir = fsf->create(folderPathToFileSystemPath(root, - root.isEmpty() ? ROOT_DIRECTORY : CONTAINER_DIRECTORY)); - - if (rootDir->exists()) - { - shared_ptr it = rootDir->getFiles(); - - while (it->hasMoreElements()) - { - shared_ptr file = it->nextElement(); - - if (isSubfolderDirectory(*file)) - { - const utility::path subPath = - root / file->getFullPath().getLastComponent(); - - list.push_back(subPath); - - if (recursive) - listFoldersImpl(list, subPath, true); - } - } - } - else - { - // No sub-folder - } -} - - -// static -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] != '.') - { - return true; - } - - return false; -} - - -void kmailMaildirFormat::renameFolder(const folder::path& oldPath, const folder::path& newPath) -{ - shared_ptr fsf = platform::getHandler()->getFileSystemFactory(); - - shared_ptr rootDir = fsf->create - (folderPathToFileSystemPath(oldPath, ROOT_DIRECTORY)); - shared_ptr contDir = fsf->create - (folderPathToFileSystemPath(oldPath, CONTAINER_DIRECTORY)); - - try - { - const utility::file::path newRootPath = - folderPathToFileSystemPath(newPath, ROOT_DIRECTORY); - const utility::file::path newContPath = - folderPathToFileSystemPath(newPath, CONTAINER_DIRECTORY); - - rootDir->rename(newRootPath); - - // Container directory may not exist, so ignore error when trying to rename it - try - { - contDir->rename(newContPath); - } - catch (exceptions::filesystem_exception& e) - { - // Ignore - } - } - 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 - { - rootDir->rename(rootPath); - contDir->rename(contPath); - } - catch (exceptions::filesystem_exception& e) - { - // Ignore (not recoverable) - } - - throw; - } -} - - -bool kmailMaildirFormat::folderHasSubfolders(const folder::path& path) const -{ - shared_ptr fsf = platform::getHandler()->getFileSystemFactory(); - - shared_ptr rootDir = fsf->create - (folderPathToFileSystemPath(path, CONTAINER_DIRECTORY)); - - shared_ptr it = rootDir->getFiles(); - - while (it->hasMoreElements()) - { - shared_ptr file = it->nextElement(); - - if (isSubfolderDirectory(*file)) - return true; - } - - return false; -} - - -bool kmailMaildirFormat::supports() const -{ - // This is the default - return true; -} - - -} // format -} // maildir -} // net -} // vmime - - -#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_MAILDIR - diff --git a/src/net/maildir/maildirFolder.cpp b/src/net/maildir/maildirFolder.cpp deleted file mode 100644 index 660178ff..00000000 --- a/src/net/maildir/maildirFolder.cpp +++ /dev/null @@ -1,1254 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// 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 && VMIME_HAVE_MESSAGING_PROTO_MAILDIR - - -#include "vmime/net/maildir/maildirFolder.hpp" - -#include "vmime/net/maildir/maildirStore.hpp" -#include "vmime/net/maildir/maildirMessage.hpp" -#include "vmime/net/maildir/maildirUtils.hpp" -#include "vmime/net/maildir/maildirFormat.hpp" -#include "vmime/net/maildir/maildirFolderStatus.hpp" - -#include "vmime/message.hpp" - -#include "vmime/exception.hpp" -#include "vmime/platform.hpp" - -#include "vmime/utility/outputStreamAdapter.hpp" -#include "vmime/utility/inputStreamStringAdapter.hpp" - - -namespace vmime { -namespace net { -namespace maildir { - - -maildirFolder::maildirFolder(const folder::path& path, shared_ptr 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) -{ - store->registerFolder(this); -} - - -maildirFolder::~maildirFolder() -{ - shared_ptr store = m_store.lock(); - - if (store) - { - if (m_open) - close(false); - - store->unregisterFolder(this); - } - else if (m_open) - { - close(false); - } -} - - -void maildirFolder::onStoreDisconnected() -{ - m_store.reset(); -} - - -int maildirFolder::getMode() const -{ - if (!isOpen()) - throw exceptions::illegal_state("Folder not open"); - - return (m_mode); -} - - -int maildirFolder::getType() -{ - if (m_path.isEmpty()) - return (TYPE_CONTAINS_FOLDERS); - else - return (TYPE_CONTAINS_FOLDERS | TYPE_CONTAINS_MESSAGES); -} - - -int maildirFolder::getFlags() -{ - int flags = 0; - - if (m_store.lock()->getFormat()->folderHasSubfolders(m_path)) - flags |= FLAG_CHILDREN; // Contains at least one sub-folder - - return (flags); -} - - -const folder::path::component maildirFolder::getName() const -{ - return (m_name); -} - - -const folder::path maildirFolder::getFullPath() const -{ - return (m_path); -} - - -void maildirFolder::open(const int mode, bool /* failIfModeIsNotAvailable */) -{ - shared_ptr store = m_store.lock(); - - if (!store) - throw exceptions::illegal_state("Store disconnected"); - else if (isOpen()) - throw exceptions::illegal_state("Folder is already open"); - else if (!exists()) - throw exceptions::illegal_state("Folder does not exist"); - - scanFolder(); - - m_open = true; - m_mode = mode; -} - - -void maildirFolder::close(const bool expunge) -{ - shared_ptr store = m_store.lock(); - - if (!store) - throw exceptions::illegal_state("Store disconnected"); - - if (!isOpen()) - throw exceptions::illegal_state("Folder not open"); - - if (expunge) - this->expunge(); - - m_open = false; - m_mode = -1; - - onClose(); -} - - -void maildirFolder::onClose() -{ - for (std::vector ::iterator it = m_messages.begin() ; - it != m_messages.end() ; ++it) - { - (*it)->onFolderClosed(); - } - - m_messages.clear(); -} - - -void maildirFolder::registerMessage(maildirMessage* msg) -{ - m_messages.push_back(msg); -} - - -void maildirFolder::unregisterMessage(maildirMessage* msg) -{ - std::vector ::iterator it = - std::find(m_messages.begin(), m_messages.end(), msg); - - if (it != m_messages.end()) - m_messages.erase(it); -} - - -void maildirFolder::create(const int /* type */) -{ - shared_ptr store = m_store.lock(); - - if (!store) - throw exceptions::illegal_state("Store disconnected"); - else if (isOpen()) - throw exceptions::illegal_state("Folder is open"); - else if (exists()) - throw exceptions::illegal_state("Folder already exists"); - else if (!store->isValidFolderName(m_name)) - throw exceptions::invalid_folder_name(); - - // Create directory on file system - try - { - store->getFormat()->createFolder(m_path); - } - catch (exceptions::filesystem_exception& e) - { - throw exceptions::command_error("CREATE", "", "File system exception", e); - } - - // Notify folder created - shared_ptr event = - make_shared - (dynamicCast (shared_from_this()), - events::folderEvent::TYPE_CREATED, m_path, m_path); - - notifyFolder(event); -} - - -void maildirFolder::destroy() -{ - shared_ptr store = m_store.lock(); - - if (!store) - throw exceptions::illegal_state("Store disconnected"); - else if (isOpen()) - throw exceptions::illegal_state("Folder is open"); - - // Delete folder - try - { - store->getFormat()->destroyFolder(m_path); - } - catch (std::exception&) - { - // Ignore exception: anyway, we can't recover from this... - } - - // Notify folder deleted - shared_ptr event = - make_shared - (dynamicCast (shared_from_this()), - events::folderEvent::TYPE_DELETED, m_path, m_path); - - notifyFolder(event); -} - - -bool maildirFolder::exists() -{ - shared_ptr store = m_store.lock(); - - return store->getFormat()->folderExists(m_path); -} - - -bool maildirFolder::isOpen() const -{ - return (m_open); -} - - -void maildirFolder::scanFolder() -{ - shared_ptr store = m_store.lock(); - - try - { - m_messageCount = 0; - m_unreadMessageCount = 0; - - shared_ptr fsf = platform::getHandler()->getFileSystemFactory(); - - utility::file::path newDirPath = store->getFormat()->folderPathToFileSystemPath - (m_path, maildirFormat::NEW_DIRECTORY); - shared_ptr newDir = fsf->create(newDirPath); - - utility::file::path curDirPath = store->getFormat()->folderPathToFileSystemPath - (m_path, maildirFormat::CUR_DIRECTORY); - shared_ptr curDir = fsf->create(curDirPath); - - // New received messages (new/) - shared_ptr nit = newDir->getFiles(); - std::vector newMessageFilenames; - - while (nit->hasMoreElements()) - { - shared_ptr file = nit->nextElement(); - - if (maildirUtils::isMessageFile(*file)) - newMessageFilenames.push_back(file->getFullPath().getLastComponent()); - } - - // Current messages (cur/) - shared_ptr cit = curDir->getFiles(); - std::vector curMessageFilenames; - - while (cit->hasMoreElements()) - { - shared_ptr file = cit->nextElement(); - - if (maildirUtils::isMessageFile(*file)) - curMessageFilenames.push_back(file->getFullPath().getLastComponent()); - } - - // Update/delete existing messages (found in previous scan) - for (unsigned int i = 0 ; i < m_messageInfos.size() ; ++i) - { - messageInfos& msgInfos = m_messageInfos[i]; - - // NOTE: the flags may have changed (eg. moving from 'new' to 'cur' - // may imply the 'S' flag) and so the filename. That's why we use - // "maildirUtils::messageIdComparator" to compare only the 'unique' - // portion of the filename... - - if (msgInfos.type == messageInfos::TYPE_CUR) - { - const std::vector ::iterator pos = - 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()) - { - msgInfos.type = messageInfos::TYPE_DELETED; - } - // Otherwise, update its information. - else - { - msgInfos.path = *pos; - curMessageFilenames.erase(pos); - } - } - } - - m_messageInfos.reserve(m_messageInfos.size() - + newMessageFilenames.size() + curMessageFilenames.size()); - - // Add new messages from 'new': we are responsible to move the files - // from the 'new' directory to the 'cur' directory, and append them - // to our message list. - for (std::vector ::const_iterator - it = newMessageFilenames.begin() ; it != newMessageFilenames.end() ; ++it) - { - const utility::file::path::component newFilename = - maildirUtils::buildFilename(maildirUtils::extractId(*it), 0); - - // Move messages from 'new' to 'cur' - shared_ptr file = fsf->create(newDirPath / *it); - file->rename(curDirPath / newFilename); - - // Append to message list - messageInfos msgInfos; - msgInfos.path = newFilename; - - if (maildirUtils::extractFlags(msgInfos.path) & message::FLAG_DELETED) - msgInfos.type = messageInfos::TYPE_DELETED; - else - msgInfos.type = messageInfos::TYPE_CUR; - - m_messageInfos.push_back(msgInfos); - } - - // 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 ::const_iterator - it = curMessageFilenames.begin() ; it != curMessageFilenames.end() ; ++it) - { - // Append to message list - messageInfos msgInfos; - msgInfos.path = *it; - - if (maildirUtils::extractFlags(msgInfos.path) & message::FLAG_DELETED) - msgInfos.type = messageInfos::TYPE_DELETED; - else - msgInfos.type = messageInfos::TYPE_CUR; - - m_messageInfos.push_back(msgInfos); - } - - // Update message count - int unreadMessageCount = 0; - - for (std::vector ::const_iterator - it = m_messageInfos.begin() ; it != m_messageInfos.end() ; ++it) - { - if ((maildirUtils::extractFlags((*it).path) & message::FLAG_SEEN) == 0) - ++unreadMessageCount; - } - - m_unreadMessageCount = unreadMessageCount; - m_messageCount = m_messageInfos.size(); - } - catch (exceptions::filesystem_exception&) - { - // Should not happen... - } -} - - -shared_ptr maildirFolder::getMessage(const int num) -{ - if (!isOpen()) - throw exceptions::illegal_state("Folder not open"); - - if (num < 1 || num > m_messageCount) - throw exceptions::message_not_found(); - - return make_shared - (dynamicCast (shared_from_this()), num); -} - - -std::vector > maildirFolder::getMessages(const messageSet& msgs) -{ - if (!isOpen()) - throw exceptions::illegal_state("Folder not open"); - - if (msgs.isNumberSet()) - { - const std::vector numbers = maildirUtils::messageSetToNumberList(msgs); - - std::vector > messages; - shared_ptr thisFolder = dynamicCast (shared_from_this()); - - for (std::vector ::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 (thisFolder, *it)); - } - - return messages; - } - else - { - throw exceptions::operation_not_supported(); - } -} - - -int maildirFolder::getMessageCount() -{ - return (m_messageCount); -} - - -shared_ptr maildirFolder::getFolder(const folder::path::component& name) -{ - shared_ptr store = m_store.lock(); - - if (!store) - throw exceptions::illegal_state("Store disconnected"); - - return make_shared (m_path / name, store); -} - - -std::vector > maildirFolder::getFolders(const bool recursive) -{ - shared_ptr store = m_store.lock(); - - if (!isOpen() && !store) - throw exceptions::illegal_state("Store disconnected"); - - std::vector > list; - - listFolders(list, recursive); - - return (list); -} - - -void maildirFolder::listFolders(std::vector >& list, const bool recursive) -{ - shared_ptr store = m_store.lock(); - - try - { - std::vector pathList = - store->getFormat()->listFolders(m_path, recursive); - - list.reserve(pathList.size()); - - for (std::vector ::size_type i = 0, n = pathList.size() ; i < n ; ++i) - { - shared_ptr subFolder = - make_shared (pathList[i], store); - - list.push_back(subFolder); - } - } - catch (exceptions::filesystem_exception& e) - { - throw exceptions::command_error("LIST", "", "", e); - } -} - - -void maildirFolder::rename(const folder::path& newPath) -{ - shared_ptr store = m_store.lock(); - - if (!store) - throw exceptions::illegal_state("Store disconnected"); - else if (m_path.isEmpty() || newPath.isEmpty()) - throw exceptions::illegal_operation("Cannot rename root folder"); - else if (!store->isValidFolderName(newPath.getLastComponent())) - throw exceptions::invalid_folder_name(); - - // Rename the directory on the file system - try - { - store->getFormat()->renameFolder(m_path, newPath); - } - catch (vmime::exception& e) - { - throw exceptions::command_error("RENAME", "", "", e); - } - - // Notify folder renamed - folder::path oldPath(m_path); - - m_path = newPath; - m_name = newPath.getLastComponent(); - - shared_ptr event = - make_shared - (dynamicCast (shared_from_this()), - events::folderEvent::TYPE_RENAMED, oldPath, newPath); - - notifyFolder(event); - - // Notify folders with the same path - for (std::list ::iterator it = store->m_folders.begin() ; - it != store->m_folders.end() ; ++it) - { - if ((*it) != this && (*it)->getFullPath() == oldPath) - { - (*it)->m_path = newPath; - (*it)->m_name = newPath.getLastComponent(); - - shared_ptr event = - make_shared - (dynamicCast ((*it)->shared_from_this()), - events::folderEvent::TYPE_RENAMED, oldPath, newPath); - - (*it)->notifyFolder(event); - } - else if ((*it) != this && oldPath.isParentOf((*it)->getFullPath())) - { - folder::path oldPath((*it)->m_path); - - (*it)->m_path.renameParent(oldPath, newPath); - - shared_ptr event = - make_shared - (dynamicCast ((*it)->shared_from_this()), - events::folderEvent::TYPE_RENAMED, oldPath, (*it)->m_path); - - (*it)->notifyFolder(event); - } - } -} - - -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) -{ - shared_ptr store = m_store.lock(); - - if (!store) - throw exceptions::illegal_state("Store disconnected"); - else if (!isOpen()) - throw exceptions::illegal_state("Folder not open"); - else if (m_mode == MODE_READ_ONLY) - throw exceptions::illegal_state("Folder is read-only"); - - if (msgs.isNumberSet()) - { - const std::vector nums = maildirUtils::messageSetToNumberList(msgs); - - // Change message flags - shared_ptr fsf = platform::getHandler()->getFileSystemFactory(); - - utility::file::path curDirPath = store->getFormat()-> - folderPathToFileSystemPath(m_path, maildirFormat::CUR_DIRECTORY); - - for (std::vector ::const_iterator it = - nums.begin() ; it != nums.end() ; ++it) - { - const int num = *it - 1; - - try - { - const utility::file::path::component path = m_messageInfos[num].path; - shared_ptr 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; - } - - const utility::file::path::component newPath = maildirUtils::buildFilename - (maildirUtils::extractId(path), newFlags); - - file->rename(curDirPath / newPath); - - if (flags & message::FLAG_DELETED) - m_messageInfos[num].type = messageInfos::TYPE_DELETED; - else - m_messageInfos[num].type = messageInfos::TYPE_CUR; - - m_messageInfos[num].path = newPath; - } - catch (exceptions::filesystem_exception& e) - { - // Ignore (not important) - } - } - - // Update local flags - switch (mode) - { - case message::FLAG_MODE_ADD: - { - for (std::vector ::iterator it = - m_messages.begin() ; it != m_messages.end() ; ++it) - { - if (std::binary_search(nums.begin(), nums.end(), (*it)->getNumber()) && - (*it)->m_flags != message::FLAG_UNDEFINED) - { - (*it)->m_flags |= flags; - } - } - - break; - } - case message::FLAG_MODE_REMOVE: - { - for (std::vector ::iterator it = - m_messages.begin() ; it != m_messages.end() ; ++it) - { - if (std::binary_search(nums.begin(), nums.end(), (*it)->getNumber()) && - (*it)->m_flags != message::FLAG_UNDEFINED) - { - (*it)->m_flags &= ~flags; - } - } - - break; - } - default: - case message::FLAG_MODE_SET: - { - for (std::vector ::iterator it = - m_messages.begin() ; it != m_messages.end() ; ++it) - { - if (std::binary_search(nums.begin(), nums.end(), (*it)->getNumber()) && - (*it)->m_flags != message::FLAG_UNDEFINED) - { - (*it)->m_flags = flags; - } - } - - break; - } - - } - - // Notify message flags changed - shared_ptr event = - make_shared - (dynamicCast (shared_from_this()), - events::messageChangedEvent::TYPE_FLAGS, nums); - - notifyMessageChanged(event); - - // TODO: notify other folders with the same path - } - else - { - throw exceptions::operation_not_supported(); - } -} - - -void maildirFolder::addMessage(shared_ptr msg, const int flags, - vmime::datetime* date, utility::progressListener* progress) -{ - std::ostringstream oss; - utility::outputStreamAdapter ossAdapter(oss); - - msg->generate(ossAdapter); - - const string& str = oss.str(); - utility::inputStreamStringAdapter strAdapter(str); - - addMessage(strAdapter, str.length(), flags, date, progress); -} - - -void maildirFolder::addMessage(utility::inputStream& is, const size_t size, - const int flags, vmime::datetime* /* date */, utility::progressListener* progress) -{ - shared_ptr store = m_store.lock(); - - if (!store) - throw exceptions::illegal_state("Store disconnected"); - else if (!isOpen()) - throw exceptions::illegal_state("Folder not open"); - else if (m_mode == MODE_READ_ONLY) - throw exceptions::illegal_state("Folder is read-only"); - - shared_ptr 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, - flags == message::FLAG_RECENT ? - maildirFormat::NEW_DIRECTORY : - maildirFormat::CUR_DIRECTORY); - - const utility::file::path::component filename = - maildirUtils::buildFilename(maildirUtils::generateId(), - ((flags == message::FLAG_UNDEFINED) ? 0 : flags)); - - try - { - shared_ptr tmpDir = fsf->create(tmpDirPath); - tmpDir->createDirectory(true); - } - catch (exceptions::filesystem_exception&) - { - // Don't throw now, it will fail later... - } - - try - { - shared_ptr curDir = fsf->create(dstDirPath); - curDir->createDirectory(true); - } - catch (exceptions::filesystem_exception&) - { - // Don't throw now, it will fail later... - } - - // Actually add the message - copyMessageImpl(tmpDirPath, dstDirPath, filename, is, size, progress); - - // Append the message to the cache list - messageInfos msgInfos; - msgInfos.path = filename; - msgInfos.type = messageInfos::TYPE_CUR; - - m_messageInfos.push_back(msgInfos); - m_messageCount++; - - if ((flags == message::FLAG_UNDEFINED) || !(flags & message::FLAG_SEEN)) - m_unreadMessageCount++; - - // Notification - std::vector nums; - nums.push_back(m_messageCount); - - shared_ptr event = - make_shared - (dynamicCast (shared_from_this()), - events::messageCountEvent::TYPE_ADDED, nums); - - notifyMessageCount(event); - - // Notify folders with the same path - for (std::list ::iterator it = store->m_folders.begin() ; - it != store->m_folders.end() ; ++it) - { - if ((*it) != this && (*it)->getFullPath() == m_path) - { - (*it)->m_messageCount = m_messageCount; - (*it)->m_unreadMessageCount = m_unreadMessageCount; - - (*it)->m_messageInfos.resize(m_messageInfos.size()); - std::copy(m_messageInfos.begin(), m_messageInfos.end(), (*it)->m_messageInfos.begin()); - - shared_ptr event = - make_shared - (dynamicCast ((*it)->shared_from_this()), - events::messageCountEvent::TYPE_ADDED, nums); - - (*it)->notifyMessageCount(event); - } - } -} - - -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) -{ - shared_ptr fsf = platform::getHandler()->getFileSystemFactory(); - - shared_ptr file = fsf->create(tmpDirPath / filename); - - if (progress) - progress->start(size); - - // First, write the message into 'tmp'... - try - { - file->createFile(); - - shared_ptr fw = file->getFileWriter(); - shared_ptr os = fw->getOutputStream(); - - byte_t buffer[65536]; - size_t total = 0; - - while (!is.eof()) - { - const size_t read = is.read(buffer, sizeof(buffer)); - - if (read != 0) - { - os->write(buffer, read); - total += read; - } - - if (progress) - progress->progress(total, size); - } - - os->flush(); - } - catch (exception& e) - { - if (progress) - progress->stop(size); - - // Delete temporary file - try - { - shared_ptr file = fsf->create(tmpDirPath / filename); - file->remove(); - } - catch (exceptions::filesystem_exception&) - { - // Ignore - } - - throw exceptions::command_error("ADD", "", "", e); - } - - // ...then, move it to 'cur' - try - { - file->rename(dstDirPath / filename); - } - catch (exception& e) - { - if (progress) - progress->stop(size); - - // Delete temporary file - try - { - file->remove(); - shared_ptr file = fsf->create(dstDirPath / filename); - file->remove(); - } - catch (exceptions::filesystem_exception&) - { - // Ignore - } - - throw exceptions::command_error("ADD", "", "", e); - } - - if (progress) - progress->stop(size); -} - - -void maildirFolder::copyMessages(const folder::path& dest, const messageSet& msgs) -{ - shared_ptr store = m_store.lock(); - - if (!store) - throw exceptions::illegal_state("Store disconnected"); - else if (!isOpen()) - throw exceptions::illegal_state("Folder not open"); - - shared_ptr fsf = platform::getHandler()->getFileSystemFactory(); - - utility::file::path curDirPath = store->getFormat()->folderPathToFileSystemPath - (m_path, maildirFormat::CUR_DIRECTORY); - - utility::file::path destCurDirPath = store->getFormat()-> - folderPathToFileSystemPath(dest, maildirFormat::CUR_DIRECTORY); - utility::file::path destTmpDirPath = store->getFormat()-> - folderPathToFileSystemPath(dest, maildirFormat::TMP_DIRECTORY); - - // Create destination directories - try - { - shared_ptr destTmpDir = fsf->create(destTmpDirPath); - destTmpDir->createDirectory(true); - } - catch (exceptions::filesystem_exception&) - { - // Don't throw now, it will fail later... - } - - try - { - shared_ptr destCurDir = fsf->create(destCurDirPath); - destCurDir->createDirectory(true); - } - catch (exceptions::filesystem_exception&) - { - // Don't throw now, it will fail later... - } - - // Copy messages - const std::vector nums = maildirUtils::messageSetToNumberList(msgs); - - try - { - for (std::vector ::const_iterator it = - nums.begin() ; it != nums.end() ; ++it) - { - const int num = *it; - const messageInfos& msg = m_messageInfos[num - 1]; - const int flags = maildirUtils::extractFlags(msg.path); - - const utility::file::path::component filename = - maildirUtils::buildFilename(maildirUtils::generateId(), flags); - - shared_ptr file = fsf->create(curDirPath / msg.path); - shared_ptr fr = file->getFileReader(); - shared_ptr is = fr->getInputStream(); - - copyMessageImpl(destTmpDirPath, destCurDirPath, - filename, *is, file->getLength(), NULL); - } - } - catch (exception& e) - { - notifyMessagesCopied(dest); - throw exceptions::command_error("COPY", "", "", e); - } - - notifyMessagesCopied(dest); -} - - -void maildirFolder::notifyMessagesCopied(const folder::path& dest) -{ - shared_ptr store = m_store.lock(); - - for (std::list ::iterator it = store->m_folders.begin() ; - 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. - int count, unseen; - (*it)->status(count, unseen); - - return; - } - } -} - - -void maildirFolder::status(int& count, int& unseen) -{ - count = 0; - unseen = 0; - - shared_ptr status = getStatus(); - - count = status->getMessageCount(); - unseen = status->getUnseenCount(); -} - - -shared_ptr maildirFolder::getStatus() -{ - shared_ptr store = m_store.lock(); - - const int oldCount = m_messageCount; - - scanFolder(); - - shared_ptr status = make_shared (); - - status->setMessageCount(m_messageCount); - status->setUnseenCount(m_unreadMessageCount); - - // Notify message count changed (new messages) - if (m_messageCount > oldCount) - { - std::vector nums; - nums.reserve(m_messageCount - oldCount); - - for (int i = oldCount + 1, j = 0 ; i <= m_messageCount ; ++i, ++j) - nums[j] = i; - - shared_ptr event = - make_shared - (dynamicCast (shared_from_this()), - events::messageCountEvent::TYPE_ADDED, nums); - - notifyMessageCount(event); - - // Notify folders with the same path - for (std::list ::iterator it = store->m_folders.begin() ; - it != store->m_folders.end() ; ++it) - { - if ((*it) != this && (*it)->getFullPath() == m_path) - { - (*it)->m_messageCount = m_messageCount; - (*it)->m_unreadMessageCount = m_unreadMessageCount; - - (*it)->m_messageInfos.resize(m_messageInfos.size()); - std::copy(m_messageInfos.begin(), m_messageInfos.end(), (*it)->m_messageInfos.begin()); - - shared_ptr event = - make_shared - (dynamicCast ((*it)->shared_from_this()), - events::messageCountEvent::TYPE_ADDED, nums); - - (*it)->notifyMessageCount(event); - } - } - } - - return status; -} - - -void maildirFolder::expunge() -{ - shared_ptr store = m_store.lock(); - - if (!store) - throw exceptions::illegal_state("Store disconnected"); - else if (!isOpen()) - throw exceptions::illegal_state("Folder not open"); - else if (m_mode == MODE_READ_ONLY) - throw exceptions::illegal_state("Folder is read-only"); - - shared_ptr fsf = platform::getHandler()->getFileSystemFactory(); - - utility::file::path curDirPath = store->getFormat()-> - folderPathToFileSystemPath(m_path, maildirFormat::CUR_DIRECTORY); - - std::vector nums; - int unreadCount = 0; - - for (int num = 1 ; num <= m_messageCount ; ++num) - { - messageInfos& infos = m_messageInfos[num - 1]; - - if (infos.type == messageInfos::TYPE_DELETED) - { - nums.push_back(num); - - for (std::vector ::iterator it = - m_messages.begin() ; it != m_messages.end() ; ++it) - { - if ((*it)->m_num == num) - (*it)->m_expunged = true; - else if ((*it)->m_num > num) - (*it)->m_num--; - } - - if (maildirUtils::extractFlags(infos.path) & message::FLAG_SEEN) - ++unreadCount; - - // Delete file from file system - try - { - shared_ptr file = fsf->create(curDirPath / infos.path); - file->remove(); - } - catch (exceptions::filesystem_exception& e) - { - // Ignore (not important) - } - } - } - - if (!nums.empty()) - { - for (std::vector ::size_type i = nums.size() ; i != 0 ; --i) - m_messageInfos.erase(m_messageInfos.begin() + (i - 1)); - } - - m_messageCount -= nums.size(); - m_unreadMessageCount -= unreadCount; - - // Notify message expunged - shared_ptr event = - make_shared - (dynamicCast (shared_from_this()), - events::messageCountEvent::TYPE_REMOVED, nums); - - notifyMessageCount(event); - - // Notify folders with the same path - for (std::list ::iterator it = store->m_folders.begin() ; - it != store->m_folders.end() ; ++it) - { - if ((*it) != this && (*it)->getFullPath() == m_path) - { - (*it)->m_messageCount = m_messageCount; - (*it)->m_unreadMessageCount = m_unreadMessageCount; - - (*it)->m_messageInfos.resize(m_messageInfos.size()); - std::copy(m_messageInfos.begin(), m_messageInfos.end(), (*it)->m_messageInfos.begin()); - - shared_ptr event = - make_shared - (dynamicCast ((*it)->shared_from_this()), - events::messageCountEvent::TYPE_REMOVED, nums); - - (*it)->notifyMessageCount(event); - } - } -} - - -shared_ptr maildirFolder::getParent() -{ - if (m_path.isEmpty()) - return null; - else - return make_shared (m_path.getParent(), m_store.lock()); -} - - -shared_ptr maildirFolder::getStore() const -{ - return m_store.lock(); -} - - -shared_ptr maildirFolder::getStore() -{ - return m_store.lock(); -} - - -void maildirFolder::fetchMessages(std::vector >& msg, - const fetchAttributes& options, utility::progressListener* progress) -{ - shared_ptr store = m_store.lock(); - - if (!store) - throw exceptions::illegal_state("Store disconnected"); - else if (!isOpen()) - throw exceptions::illegal_state("Folder not open"); - - const size_t total = msg.size(); - size_t current = 0; - - if (progress) - progress->start(total); - - shared_ptr thisFolder = dynamicCast (shared_from_this()); - - for (std::vector >::iterator it = msg.begin() ; - it != msg.end() ; ++it) - { - dynamicCast (*it)->fetch(thisFolder, options); - - if (progress) - progress->progress(++current, total); - } - - if (progress) - progress->stop(total); -} - - -void maildirFolder::fetchMessage(shared_ptr msg, const fetchAttributes& options) -{ - shared_ptr store = m_store.lock(); - - if (!store) - throw exceptions::illegal_state("Store disconnected"); - else if (!isOpen()) - throw exceptions::illegal_state("Folder not open"); - - dynamicCast (msg)->fetch - (dynamicCast (shared_from_this()), options); -} - - -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 int number) const -{ - utility::file::path curDirPath = m_store.lock()->getFormat()-> - folderPathToFileSystemPath(m_path, maildirFormat::CUR_DIRECTORY); - - return (curDirPath / m_messageInfos[number - 1].path); -} - - -std::vector maildirFolder::getMessageNumbersStartingOnUID(const message::uid& /* uid */) -{ - throw exceptions::operation_not_supported(); -} - - -} // maildir -} // net -} // vmime - - -#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_MAILDIR - diff --git a/src/net/maildir/maildirFolderStatus.cpp b/src/net/maildir/maildirFolderStatus.cpp deleted file mode 100644 index 9ee84dba..00000000 --- a/src/net/maildir/maildirFolderStatus.cpp +++ /dev/null @@ -1,88 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// 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 && VMIME_HAVE_MESSAGING_PROTO_MAILDIR - - -#include "vmime/net/maildir/maildirFolderStatus.hpp" - - -namespace vmime { -namespace net { -namespace maildir { - - -maildirFolderStatus::maildirFolderStatus() - : m_count(0), - m_unseen(0) -{ -} - - -maildirFolderStatus::maildirFolderStatus(const maildirFolderStatus& other) - : folderStatus(), - m_count(other.m_count), - m_unseen(other.m_unseen) -{ -} - - -unsigned int maildirFolderStatus::getMessageCount() const -{ - return m_count; -} - - -unsigned int maildirFolderStatus::getUnseenCount() const -{ - return m_unseen; -} - - -void maildirFolderStatus::setMessageCount(const unsigned int count) -{ - m_count = count; -} - - -void maildirFolderStatus::setUnseenCount(const unsigned int unseen) -{ - m_unseen = unseen; -} - - -shared_ptr maildirFolderStatus::clone() const -{ - return make_shared (*this); -} - - -} // maildir -} // net -} // vmime - - -#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_MAILDIR diff --git a/src/net/maildir/maildirFormat.cpp b/src/net/maildir/maildirFormat.cpp deleted file mode 100644 index f7a3c8fe..00000000 --- a/src/net/maildir/maildirFormat.cpp +++ /dev/null @@ -1,109 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// 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 && VMIME_HAVE_MESSAGING_PROTO_MAILDIR - - -#include "vmime/net/maildir/maildirFormat.hpp" -#include "vmime/net/maildir/maildirStore.hpp" - -#include "vmime/net/maildir/format/kmailMaildirFormat.hpp" -#include "vmime/net/maildir/format/courierMaildirFormat.hpp" - -#include "vmime/utility/file.hpp" - - -namespace vmime { -namespace net { -namespace maildir { - - -const utility::file::path::component maildirFormat::TMP_DIR("tmp", vmime::charset(vmime::charsets::US_ASCII)); -const utility::file::path::component maildirFormat::CUR_DIR("cur", vmime::charset(vmime::charsets::US_ASCII)); -const utility::file::path::component maildirFormat::NEW_DIR("new", vmime::charset(vmime::charsets::US_ASCII)); - - -// -// maildirFormat::context -// - -maildirFormat::context::context(shared_ptr store) - : m_store(store) -{ -} - - -shared_ptr maildirFormat::context::getStore() const -{ - return constCast (m_store.lock()); -} - - -// -// maildirFormat -// - -maildirFormat::maildirFormat(shared_ptr ctx) - : m_context(ctx) -{ -} - - -shared_ptr maildirFormat::getContext() -{ - return m_context; -} - - -shared_ptr maildirFormat::getContext() const -{ - return m_context; -} - - -// static -shared_ptr maildirFormat::detect(shared_ptr store) -{ - shared_ptr ctx = make_shared (store); - - // Try Courier format - shared_ptr fmt = make_shared (ctx); - - if (fmt->supports()) - return fmt; - - // Default is KMail format - return make_shared (ctx); -} - - -} // maildir -} // net -} // vmime - - -#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_MAILDIR - diff --git a/src/net/maildir/maildirMessage.cpp b/src/net/maildir/maildirMessage.cpp deleted file mode 100644 index a14f067e..00000000 --- a/src/net/maildir/maildirMessage.cpp +++ /dev/null @@ -1,369 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// 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 && VMIME_HAVE_MESSAGING_PROTO_MAILDIR - - -#include "vmime/net/maildir/maildirMessage.hpp" -#include "vmime/net/maildir/maildirMessagePart.hpp" -#include "vmime/net/maildir/maildirMessageStructure.hpp" -#include "vmime/net/maildir/maildirFolder.hpp" -#include "vmime/net/maildir/maildirUtils.hpp" -#include "vmime/net/maildir/maildirStore.hpp" - -#include "vmime/message.hpp" - -#include "vmime/exception.hpp" -#include "vmime/platform.hpp" - -#include "vmime/utility/outputStreamAdapter.hpp" -#include "vmime/utility/stringUtils.hpp" - - -namespace vmime { -namespace net { -namespace maildir { - - -maildirMessage::maildirMessage(shared_ptr folder, const int 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() -{ - shared_ptr folder = m_folder.lock(); - - if (folder) - folder->unregisterMessage(this); -} - - -void maildirMessage::onFolderClosed() -{ - m_folder.reset(); -} - - -int maildirMessage::getNumber() const -{ - return (m_num); -} - - -const message::uid maildirMessage::getUID() const -{ - return (m_uid); -} - - -size_t maildirMessage::getSize() const -{ - if (m_size == static_cast (-1)) - throw exceptions::unfetched_object(); - - return (m_size); -} - - -bool maildirMessage::isExpunged() const -{ - return (m_expunged); -} - - -shared_ptr maildirMessage::getStructure() const -{ - if (m_structure == NULL) - throw exceptions::unfetched_object(); - - return m_structure; -} - - -shared_ptr maildirMessage::getStructure() -{ - if (m_structure == NULL) - throw exceptions::unfetched_object(); - - return m_structure; -} - - -shared_ptr maildirMessage::getHeader() const -{ - if (m_header == NULL) - throw exceptions::unfetched_object(); - - return (m_header); -} - - -int maildirMessage::getFlags() const -{ - if (m_flags == FLAG_UNDEFINED) - throw exceptions::unfetched_object(); - - return (m_flags); -} - - -void maildirMessage::setFlags(const int flags, const int mode) -{ - shared_ptr folder = m_folder.lock(); - - 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 -{ - extractImpl(os, progress, 0, m_size, start, length, peek); -} - - -void maildirMessage::extractPart(shared_ptr p, utility::outputStream& os, - utility::progressListener* progress, const size_t start, - const size_t length, const bool peek) const -{ - shared_ptr mp = dynamicCast (p); - - 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 -{ - shared_ptr folder = m_folder.lock(); - - shared_ptr fsf = platform::getHandler()->getFileSystemFactory(); - - const utility::file::path path = folder->getMessageFSPath(m_num); - shared_ptr file = fsf->create(path); - - shared_ptr reader = file->getFileReader(); - shared_ptr is = reader->getInputStream(); - - is->skip(start + partialStart); - - byte_t buffer[8192]; - size_t remaining = (partialLength == static_cast (-1) - ? length : std::min(partialLength, length)); - - const size_t total = remaining; - size_t current = 0; - - if (progress) - progress->start(total); - - while (!is->eof() && remaining > 0) - { - const size_t read = is->read(buffer, std::min(remaining, sizeof(buffer))); - - remaining -= read; - current += read; - - os.write(buffer, read); - - if (progress) - progress->progress(current, total); - } - - if (progress) - progress->stop(total); - - // TODO: mark as read unless 'peek' is set -} - - -void maildirMessage::fetchPartHeader(shared_ptr p) -{ - shared_ptr folder = m_folder.lock(); - - shared_ptr mp = dynamicCast (p); - - shared_ptr fsf = platform::getHandler()->getFileSystemFactory(); - - const utility::file::path path = folder->getMessageFSPath(m_num); - shared_ptr file = fsf->create(path); - - shared_ptr reader = file->getFileReader(); - shared_ptr is = reader->getInputStream(); - - is->skip(mp->getHeaderParsedOffset()); - - byte_t buffer[1024]; - size_t remaining = mp->getHeaderParsedLength(); - - string contents; - contents.reserve(remaining); - - while (!is->eof() && remaining > 0) - { - const size_t read = is->read(buffer, std::min(remaining, sizeof(buffer))); - - remaining -= read; - - vmime::utility::stringUtils::appendBytesToString(contents, buffer, read); - } - - mp->getOrCreateHeader().parse(contents); -} - - -void maildirMessage::fetch(shared_ptr msgFolder, const fetchAttributes& options) -{ - shared_ptr folder = m_folder.lock(); - - if (folder != msgFolder) - throw exceptions::folder_not_found(); - - shared_ptr fsf = platform::getHandler()->getFileSystemFactory(); - - const utility::file::path path = folder->getMessageFSPath(m_num); - shared_ptr file = fsf->create(path); - - if (options.has(fetchAttributes::FLAGS)) - m_flags = maildirUtils::extractFlags(path.getLastComponent()); - - if (options.has(fetchAttributes::SIZE)) - m_size = file->getLength(); - - 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)) - { - string contents; - - shared_ptr reader = file->getFileReader(); - shared_ptr is = reader->getInputStream(); - - // Need whole message contents for structure - if (options.has(fetchAttributes::STRUCTURE)) - { - byte_t buffer[16384]; - - contents.reserve(file->getLength()); - - while (!is->eof()) - { - const size_t read = is->read(buffer, sizeof(buffer)); - vmime::utility::stringUtils::appendBytesToString(contents, buffer, read); - } - } - // Need only header - else - { - byte_t buffer[1024]; - - contents.reserve(4096); - - 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) - { - contents.erase(contents.begin() + sep1 + 4, contents.end()); - break; - } - else if (sep2 != string::npos) - { - contents.erase(contents.begin() + sep2 + 2, contents.end()); - break; - } - } - } - - vmime::message msg; - msg.parse(contents); - - // Extract structure - if (options.has(fetchAttributes::STRUCTURE)) - { - m_structure = make_shared (shared_ptr (), msg); - } - - // Extract some header fields or whole header - if (options.has(fetchAttributes::ENVELOPE | - fetchAttributes::CONTENT_INFO | - fetchAttributes::FULL_HEADER | - fetchAttributes::IMPORTANCE)) - { - getOrCreateHeader()->copyFrom(*(msg.getHeader())); - } - } -} - - -shared_ptr
maildirMessage::getOrCreateHeader() -{ - if (m_header != NULL) - return (m_header); - else - return (m_header = make_shared
()); -} - - -shared_ptr maildirMessage::getParsedMessage() -{ - std::ostringstream oss; - utility::outputStreamAdapter os(oss); - - extract(os); - - shared_ptr msg = make_shared (); - msg->parse(oss.str()); - - return msg; -} - - -} // maildir -} // net -} // vmime - - -#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_MAILDIR - diff --git a/src/net/maildir/maildirMessagePart.cpp b/src/net/maildir/maildirMessagePart.cpp deleted file mode 100644 index 6ae085c9..00000000 --- a/src/net/maildir/maildirMessagePart.cpp +++ /dev/null @@ -1,155 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// 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 && VMIME_HAVE_MESSAGING_PROTO_MAILDIR - - -#include "vmime/net/maildir/maildirMessagePart.hpp" -#include "vmime/net/maildir/maildirMessageStructure.hpp" - - -namespace vmime { -namespace net { -namespace maildir { - - -maildirMessagePart::maildirMessagePart(shared_ptr parent, const int number, const bodyPart& part) - : m_parent(parent), m_header(null), m_number(number) -{ - m_headerParsedOffset = part.getHeader()->getParsedOffset(); - m_headerParsedLength = part.getHeader()->getParsedLength(); - - m_bodyParsedOffset = part.getBody()->getParsedOffset(); - m_bodyParsedLength = part.getBody()->getParsedLength(); - - m_size = part.getBody()->getContents()->getLength(); - - m_mediaType = part.getBody()->getContentType(); -} - - -maildirMessagePart::~maildirMessagePart() -{ -} - - -void maildirMessagePart::initStructure(const bodyPart& part) -{ - if (part.getBody()->getPartList().size() == 0) - m_structure = null; - else - { - m_structure = make_shared - (dynamicCast (shared_from_this()), - part.getBody()->getPartList()); - } -} - - -shared_ptr maildirMessagePart::getStructure() const -{ - if (m_structure != NULL) - return m_structure; - else - return maildirMessageStructure::emptyStructure(); -} - - -shared_ptr maildirMessagePart::getStructure() -{ - if (m_structure != NULL) - return m_structure; - else - return maildirMessageStructure::emptyStructure(); -} - - -const mediaType& maildirMessagePart::getType() const -{ - return m_mediaType; -} - - -size_t maildirMessagePart::getSize() const -{ - return m_size; -} - - -int maildirMessagePart::getNumber() const -{ - return m_number; -} - - -shared_ptr maildirMessagePart::getHeader() const -{ - if (m_header == NULL) - throw exceptions::unfetched_object(); - else - return m_header; -} - - -header& maildirMessagePart::getOrCreateHeader() -{ - if (m_header != NULL) - return *m_header; - else - return *(m_header = make_shared
()); -} - - -size_t maildirMessagePart::getHeaderParsedOffset() const -{ - return m_headerParsedOffset; -} - - -size_t maildirMessagePart::getHeaderParsedLength() const -{ - return m_headerParsedLength; -} - - -size_t maildirMessagePart::getBodyParsedOffset() const -{ - return m_bodyParsedOffset; -} - - -size_t maildirMessagePart::getBodyParsedLength() const -{ - return m_bodyParsedLength; -} - - -} // maildir -} // net -} // vmime - - -#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_MAILDIR diff --git a/src/net/maildir/maildirMessageStructure.cpp b/src/net/maildir/maildirMessageStructure.cpp deleted file mode 100644 index f3b7cf59..00000000 --- a/src/net/maildir/maildirMessageStructure.cpp +++ /dev/null @@ -1,98 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// 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 && VMIME_HAVE_MESSAGING_PROTO_MAILDIR - - -#include "vmime/net/maildir/maildirMessageStructure.hpp" -#include "vmime/net/maildir/maildirMessagePart.hpp" - - -namespace vmime { -namespace net { -namespace maildir { - - -shared_ptr maildirMessageStructure::m_emptyStructure = make_shared (); - - -maildirMessageStructure::maildirMessageStructure() -{ -} - - -maildirMessageStructure::maildirMessageStructure(shared_ptr parent, const bodyPart& part) -{ - shared_ptr mpart = make_shared (parent, 0, part); - mpart->initStructure(part); - - m_parts.push_back(mpart); -} - - -maildirMessageStructure::maildirMessageStructure(shared_ptr parent, const std::vector >& list) -{ - for (unsigned int i = 0 ; i < list.size() ; ++i) - { - shared_ptr mpart = make_shared (parent, i, *list[i]); - mpart->initStructure(*list[i]); - - m_parts.push_back(mpart); - } -} - - -shared_ptr maildirMessageStructure::getPartAt(const size_t x) const -{ - return m_parts[x]; -} - - -shared_ptr maildirMessageStructure::getPartAt(const size_t x) -{ - return m_parts[x]; -} - - -size_t maildirMessageStructure::getPartCount() const -{ - return m_parts.size(); -} - - -// static -shared_ptr maildirMessageStructure::emptyStructure() -{ - return m_emptyStructure; -} - - -} // maildir -} // net -} // vmime - - -#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_MAILDIR diff --git a/src/net/maildir/maildirServiceInfos.cpp b/src/net/maildir/maildirServiceInfos.cpp deleted file mode 100644 index 974a0c21..00000000 --- a/src/net/maildir/maildirServiceInfos.cpp +++ /dev/null @@ -1,77 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// 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 && VMIME_HAVE_MESSAGING_PROTO_MAILDIR - - -#include "vmime/net/maildir/maildirServiceInfos.hpp" - - -namespace vmime { -namespace net { -namespace maildir { - - -maildirServiceInfos::maildirServiceInfos() -{ -} - - -const string maildirServiceInfos::getPropertyPrefix() const -{ - return "store.maildir."; -} - - -const maildirServiceInfos::props& maildirServiceInfos::getProperties() const -{ - static props maildirProps = - { - property(serviceInfos::property::SERVER_ROOTPATH, serviceInfos::property::FLAG_REQUIRED) - }; - - return maildirProps; -} - - -const std::vector maildirServiceInfos::getAvailableProperties() const -{ - std::vector list; - const props& p = getProperties(); - - list.push_back(p.PROPERTY_SERVER_ROOTPATH); - - return list; -} - - -} // maildir -} // net -} // vmime - - -#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_MAILDIR - diff --git a/src/net/maildir/maildirStore.cpp b/src/net/maildir/maildirStore.cpp deleted file mode 100644 index 87e733e2..00000000 --- a/src/net/maildir/maildirStore.cpp +++ /dev/null @@ -1,272 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// 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 && VMIME_HAVE_MESSAGING_PROTO_MAILDIR - - -#include "vmime/net/maildir/maildirStore.hpp" - -#include "vmime/net/maildir/maildirFolder.hpp" -#include "vmime/net/maildir/maildirFormat.hpp" - -#include "vmime/exception.hpp" -#include "vmime/platform.hpp" - -#include "vmime/net/defaultConnectionInfos.hpp" - - -// Helpers for service properties -#define GET_PROPERTY(type, prop) \ - (getInfos().getPropertyValue (getSession(), \ - dynamic_cast (getInfos()).getProperties().prop)) -#define HAS_PROPERTY(prop) \ - (getInfos().hasProperty(getSession(), \ - dynamic_cast (getInfos()).getProperties().prop)) - - -namespace vmime { -namespace net { -namespace maildir { - - -maildirStore::maildirStore(shared_ptr sess, shared_ptr auth) - : store(sess, getInfosInstance(), auth), m_connected(false) -{ -} - - -maildirStore::~maildirStore() -{ - try - { - if (isConnected()) - disconnect(); - } - catch (vmime::exception&) - { - // Ignore - } -} - - -const string maildirStore::getProtocolName() const -{ - return "maildir"; -} - - -shared_ptr maildirStore::getRootFolder() -{ - if (!isConnected()) - throw exceptions::illegal_state("Not connected"); - - return make_shared - (folder::path(), - dynamicCast (shared_from_this())); -} - - -shared_ptr maildirStore::getDefaultFolder() -{ - if (!isConnected()) - throw exceptions::illegal_state("Not connected"); - - return make_shared - (folder::path::component("inbox"), - dynamicCast (shared_from_this())); -} - - -shared_ptr maildirStore::getFolder(const folder::path& path) -{ - if (!isConnected()) - throw exceptions::illegal_state("Not connected"); - - return make_shared - (path, dynamicCast (shared_from_this())); -} - - -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) - return false; - - // Name cannot start with '.' - const size_t length = buf.length(); - int pos = 0; - - while ((pos < length) && (buf[pos] == '.')) - ++pos; - - return (pos == 0); -} - - -void maildirStore::connect() -{ - if (isConnected()) - throw exceptions::already_connected(); - - // Get root directory - shared_ptr fsf = platform::getHandler()->getFileSystemFactory(); - - m_fsPath = fsf->stringToPath(GET_PROPERTY(string, PROPERTY_SERVER_ROOTPATH)); - - shared_ptr rootDir = fsf->create(m_fsPath); - - // Try to create the root directory if it does not exist - if (!(rootDir->exists() && rootDir->isDirectory())) - { - try - { - rootDir->createDirectory(); - } - catch (exceptions::filesystem_exception& e) - { - throw exceptions::connection_error("Cannot create root directory.", e); - } - } - - m_format = maildirFormat::detect(dynamicCast (shared_from_this())); - - m_connected = true; -} - - -bool maildirStore::isConnected() const -{ - return (m_connected); -} - - -bool maildirStore::isSecuredConnection() const -{ - return false; -} - - -shared_ptr maildirStore::getConnectionInfos() const -{ - return make_shared ("localhost", static_cast (0)); -} - - -void maildirStore::disconnect() -{ - for (std::list ::iterator it = m_folders.begin() ; - it != m_folders.end() ; ++it) - { - (*it)->onStoreDisconnected(); - } - - m_folders.clear(); - - m_connected = false; -} - - -void maildirStore::noop() -{ - // Nothing to do. -} - - -shared_ptr maildirStore::getFormat() -{ - return m_format; -} - - -shared_ptr maildirStore::getFormat() const -{ - return m_format; -} - - -void maildirStore::registerFolder(maildirFolder* folder) -{ - m_folders.push_back(folder); -} - - -void maildirStore::unregisterFolder(maildirFolder* folder) -{ - std::list ::iterator it = std::find(m_folders.begin(), m_folders.end(), folder); - if (it != m_folders.end()) m_folders.erase(it); -} - - -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); -} - - - -// Service infos - -maildirServiceInfos maildirStore::sm_infos; - - -const serviceInfos& maildirStore::getInfosInstance() -{ - return sm_infos; -} - - -const serviceInfos& maildirStore::getInfos() const -{ - return sm_infos; -} - - -} // maildir -} // net -} // vmime - - -#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_MAILDIR - diff --git a/src/net/maildir/maildirUtils.cpp b/src/net/maildir/maildirUtils.cpp deleted file mode 100644 index 77aac715..00000000 --- a/src/net/maildir/maildirUtils.cpp +++ /dev/null @@ -1,273 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// 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 && VMIME_HAVE_MESSAGING_PROTO_MAILDIR - - -#include "vmime/net/maildir/maildirUtils.hpp" -#include "vmime/net/maildir/maildirStore.hpp" - -#include "vmime/utility/random.hpp" -#include "vmime/platform.hpp" - -#include "vmime/exception.hpp" - - -namespace vmime { -namespace net { -namespace maildir { - - -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); - } - - return (false); -} - - -// NOTE ABOUT ID/FLAGS SEPARATOR -// ----------------------------- -// In the maildir specification, the character ':' is used to separate -// the unique identifier and the message flags. -// -// On Windows (and particularly FAT file systems), ':' is not allowed -// in a filename, so we use a dash ('-') instead. This is the solution -// used by Mutt/Win32, so we also use it here. -// -// To be compatible between implementations, we check for both -// characters when reading file names. - - -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) - { - 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))); -} - - -int maildirUtils::extractFlags(const utility::file::path::component& comp) -{ - size_t sep = comp.getBuffer().rfind(':'); // try colon - - if (sep == string::npos) - { - sep = comp.getBuffer().rfind('-'); // try dash (Windows) - if (sep == string::npos) return 0; - } - - const string flagsString(comp.getBuffer().begin() + sep + 1, comp.getBuffer().end()); - const size_t count = flagsString.length(); - - 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; - } - } - - return (flags); -} - - -const utility::file::path::component maildirUtils::buildFlags(const int flags) -{ - string str; - str.reserve(8); - - str += "2,"; - - if (flags & message::FLAG_MARKED) str += "F"; - if (flags & message::FLAG_PASSED) str += "P"; - if (flags & message::FLAG_REPLIED) str += "R"; - if (flags & message::FLAG_SEEN) str += "S"; - if (flags & message::FLAG_DELETED) str += "T"; - if (flags & message::FLAG_DRAFT) str += "D"; - - 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) - return id; - 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) -{ -#if VMIME_PLATFORM_IS_WINDOWS - static const char DELIMITER[] = "-"; -#else - static const char DELIMITER[] = ":"; -#endif - - return utility::path::component(id.getBuffer() + DELIMITER + flags.getBuffer()); -} - - -const utility::file::path::component maildirUtils::generateId() -{ - std::ostringstream oss; - oss.imbue(std::locale::classic()); - - oss << utility::random::getTime(); - oss << "."; - oss << utility::random::getProcess(); - oss << "."; - oss << utility::random::getString(6); - oss << "."; - oss << platform::getHandler()->getHostName(); - - return (utility::file::path::component(oss.str())); -} - - -void maildirUtils::recursiveFSDelete(shared_ptr dir) -{ - shared_ptr files = dir->getFiles(); - - // First, delete files and subdirectories in this directory - while (files->hasMoreElements()) - { - shared_ptr file = files->nextElement(); - - if (file->isDirectory()) - { - maildirUtils::recursiveFSDelete(file); - } - else - { - try - { - file->remove(); - } - catch (exceptions::filesystem_exception&) - { - // Ignore - } - } - } - - // Then, delete this (empty) directory - try - { - dir->remove(); - } - catch (exceptions::filesystem_exception&) - { - // Ignore - } -} - - - -class maildirMessageSetEnumerator : public messageSetEnumerator -{ -public: - - void enumerateNumberMessageRange(const vmime::net::numberMessageRange& range) - { - for (int i = range.getFirst(), last = range.getLast() ; i <= last ; ++i) - list.push_back(i); - } - - void enumerateUIDMessageRange(const vmime::net::UIDMessageRange& /* range */) - { - // Not supported - } - -public: - - std::vector list; -}; - - -// static -const std::vector maildirUtils::messageSetToNumberList(const messageSet& msgs) -{ - maildirMessageSetEnumerator en; - msgs.enumerate(en); - - return en.list; -} - - - -// -// messageIdComparator -// - -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)); -} - - -} // maildir -} // net -} // vmime - - -#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_MAILDIR - diff --git a/src/net/message.cpp b/src/net/message.cpp deleted file mode 100644 index 6765e73c..00000000 --- a/src/net/message.cpp +++ /dev/null @@ -1,150 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// 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/message.hpp" - -#include - - -namespace vmime { -namespace net { - - -shared_ptr messagePart::getPartAt(const size_t pos) const -{ - return getStructure()->getPartAt(pos); -} - - -shared_ptr messagePart::getPartAt(const size_t pos) -{ - return getStructure()->getPartAt(pos); -} - - -size_t messagePart::getPartCount() const -{ - return getStructure()->getPartCount(); -} - - - -// message::uid - - -message::uid::uid() -{ -} - - -message::uid::uid(const string& uid) - : m_str(uid) -{ -} - - -message::uid::uid(const unsigned long uid) -{ - std::ostringstream oss; - oss.imbue(std::locale::classic()); - oss << uid; - - m_str = oss.str(); -} - - -message::uid::uid(const char* uid) - : m_str(uid) -{ -} - - -message::uid::uid(const uid& other) -{ - m_str = other.m_str; -} - - -message::uid& message::uid::operator=(const uid& other) -{ - m_str = other.m_str; - return *this; -} - - -message::uid& message::uid::operator=(const string& uid) -{ - m_str = uid; - return *this; -} - - -message::uid& message::uid::operator=(const unsigned long uid) -{ - std::ostringstream oss; - oss.imbue(std::locale::classic()); - oss << uid; - - m_str = oss.str(); - - return *this; -} - - -message::uid::operator string() const -{ - return m_str; -} - - -bool message::uid::empty() const -{ - return m_str.empty(); -} - - -bool message::uid::operator==(const uid& other) const -{ - return m_str == other.m_str; -} - - -std::ostream& operator<<(std::ostream& os, const message::uid& uid) -{ - os << static_cast (uid); - return os; -} - - -} // net -} // vmime - - -#endif // VMIME_HAVE_MESSAGING_FEATURES - diff --git a/src/net/messageSet.cpp b/src/net/messageSet.cpp deleted file mode 100644 index 2939042e..00000000 --- a/src/net/messageSet.cpp +++ /dev/null @@ -1,369 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// 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/net/messageSet.hpp" - -#include -#include -#include - - -namespace vmime { -namespace net { - - -// messageRange - -messageRange::messageRange() -{ -} - - -messageRange::~messageRange() -{ -} - - -// numberMessageRange - -numberMessageRange::numberMessageRange(const int number) - : m_first(number), m_last(number) -{ - if (number < 1) - throw std::invalid_argument("number"); -} - - -numberMessageRange::numberMessageRange(const int first, const int last) - : m_first(first), m_last(last) -{ - if (first < 1) - throw std::invalid_argument("first"); - else if (last != -1 && last < first) - throw std::invalid_argument("last"); -} - - -numberMessageRange::numberMessageRange(const numberMessageRange& other) - : messageRange(), m_first(other.m_first), m_last(other.m_last) -{ -} - - -int numberMessageRange::getFirst() const -{ - return m_first; -} - - -int numberMessageRange::getLast() const -{ - return m_last; -} - - -void numberMessageRange::enumerate(messageSetEnumerator& en) const -{ - en.enumerateNumberMessageRange(*this); -} - - -messageRange* numberMessageRange::clone() const -{ - return new numberMessageRange(*this); -} - - -// UIDMessageRange - -UIDMessageRange::UIDMessageRange(const message::uid& uid) - : m_first(uid), m_last(uid) -{ -} - - -UIDMessageRange::UIDMessageRange(const message::uid& first, const message::uid& last) - : m_first(first), m_last(last) -{ -} - - -UIDMessageRange::UIDMessageRange(const UIDMessageRange& other) - : messageRange(), m_first(other.m_first), m_last(other.m_last) -{ -} - - -const message::uid UIDMessageRange::getFirst() const -{ - return m_first; -} - - -const message::uid UIDMessageRange::getLast() const -{ - return m_last; -} - - -void UIDMessageRange::enumerate(messageSetEnumerator& en) const -{ - en.enumerateUIDMessageRange(*this); -} - - -messageRange* UIDMessageRange::clone() const -{ - return new UIDMessageRange(*this); -} - - -// messageSet - - -messageSet::messageSet() -{ -} - - -messageSet::messageSet(const messageSet& other) - : object() -{ - m_ranges.resize(other.m_ranges.size()); - - 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) - delete m_ranges[i]; -} - - -// static -messageSet messageSet::byNumber(const int number) -{ - messageSet set; - set.m_ranges.push_back(new numberMessageRange(number)); - - return set; -} - - -// static -messageSet messageSet::byNumber(const int first, const int last) -{ - messageSet set; - set.m_ranges.push_back(new numberMessageRange(first, last)); - - return set; -} - - -// static -messageSet messageSet::byNumber(const std::vector & numbers) -{ - // Sort a copy of the list - std::vector sortedNumbers; - - sortedNumbers.resize(numbers.size()); - - std::copy(numbers.begin(), numbers.end(), sortedNumbers.begin()); - std::sort(sortedNumbers.begin(), sortedNumbers.end()); - - // Build the set by detecting ranges of continuous numbers - int previous = -1, rangeStart = -1; - messageSet set; - - for (std::vector ::const_iterator it = sortedNumbers.begin() ; - it != sortedNumbers.end() ; ++it) - { - const int current = *it; - - if (current == previous) - continue; // skip duplicates - - if (previous == -1) - { - previous = current; - rangeStart = current; - } - else - { - if (current == previous + 1) - { - previous = current; - } - else - { - set.m_ranges.push_back(new numberMessageRange(rangeStart, previous)); - - previous = current; - rangeStart = current; - } - } - } - - set.m_ranges.push_back(new numberMessageRange(rangeStart, previous)); - - return set; -} - - -// static -messageSet messageSet::byUID(const message::uid& uid) -{ - messageSet set; - set.m_ranges.push_back(new UIDMessageRange(uid)); - - return set; -} - - -messageSet messageSet::byUID(const message::uid& first, const message::uid& last) -{ - messageSet set; - set.m_ranges.push_back(new UIDMessageRange(first, last)); - - return set; -} - - -messageSet messageSet::byUID(const std::vector & uids) -{ - std::vector numericUIDs; - - 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'); - - 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) - set.m_ranges.push_back(new UIDMessageRange(uids[i])); - - return set; - } - - numericUIDs.push_back(numericUID); - } - - // Sort a copy of the list - std::vector sortedUIDs; - - sortedUIDs.resize(numericUIDs.size()); - - std::copy(numericUIDs.begin(), numericUIDs.end(), sortedUIDs.begin()); - std::sort(sortedUIDs.begin(), sortedUIDs.end()); - - // Build the set by detecting ranges of continuous numbers - vmime_uint32 previous = -1U, rangeStart = -1U; - messageSet set; - - for (std::vector ::const_iterator it = sortedUIDs.begin() ; - it != sortedUIDs.end() ; ++it) - { - const vmime_uint32 current = *it; - - if (current == previous) - continue; // skip duplicates - - if (previous == -1U) - { - previous = current; - rangeStart = current; - } - else - { - if (current == previous + 1) - { - previous = current; - } - else - { - set.m_ranges.push_back(new UIDMessageRange - (utility::stringUtils::toString(rangeStart), - utility::stringUtils::toString(previous))); - - previous = current; - rangeStart = current; - } - } - } - - 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)) - 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) - m_ranges[i]->enumerate(en); -} - - -bool messageSet::isEmpty() const -{ - return m_ranges.empty(); -} - - -bool messageSet::isNumberSet() const -{ - return !isEmpty() && dynamic_cast (m_ranges[0]) != NULL; -} - - -bool messageSet::isUIDSet() const -{ - return !isEmpty() && dynamic_cast (m_ranges[0]) != NULL; -} - - -} // net -} // vmime diff --git a/src/net/pop3/POP3Command.cpp b/src/net/pop3/POP3Command.cpp deleted file mode 100644 index 6fe301ce..00000000 --- a/src/net/pop3/POP3Command.cpp +++ /dev/null @@ -1,230 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// 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 && VMIME_HAVE_MESSAGING_PROTO_POP3 - - -#include "vmime/net/pop3/POP3Command.hpp" -#include "vmime/net/pop3/POP3Connection.hpp" -#include "vmime/net/pop3/POP3Store.hpp" - -#include "vmime/net/socket.hpp" - -#include "vmime/mailbox.hpp" -#include "vmime/utility/outputStreamAdapter.hpp" - - -namespace vmime { -namespace net { -namespace pop3 { - - -POP3Command::POP3Command(const string& text) - : m_text(text) -{ -} - - -// static -shared_ptr POP3Command::CAPA() -{ - return createCommand("CAPA"); -} - - -// static -shared_ptr POP3Command::NOOP() -{ - return createCommand("NOOP"); -} - - -// static -shared_ptr POP3Command::AUTH(const string& mechName) -{ - std::ostringstream cmd; - cmd.imbue(std::locale::classic()); - cmd << "AUTH " << mechName; - - return createCommand(cmd.str()); -} - - -// static -shared_ptr POP3Command::STLS() -{ - return createCommand("STLS"); -} - - -// static -shared_ptr POP3Command::APOP(const string& username, const string& digest) -{ - std::ostringstream cmd; - cmd.imbue(std::locale::classic()); - cmd << "APOP " << username << " " << digest; - - return createCommand(cmd.str()); -} - - -// static -shared_ptr POP3Command::USER(const string& username) -{ - std::ostringstream cmd; - cmd.imbue(std::locale::classic()); - cmd << "USER " << username; - - return createCommand(cmd.str()); -} - - -// static -shared_ptr POP3Command::PASS(const string& password) -{ - std::ostringstream cmd; - cmd.imbue(std::locale::classic()); - cmd << "PASS " << password; - - return createCommand(cmd.str()); -} - - -// static -shared_ptr POP3Command::STAT() -{ - return createCommand("STAT"); -} - - -// static -shared_ptr POP3Command::LIST() -{ - return createCommand("LIST"); -} - - -// static -shared_ptr POP3Command::LIST(const unsigned long msg) -{ - std::ostringstream cmd; - cmd.imbue(std::locale::classic()); - cmd << "LIST " << msg; - - return createCommand(cmd.str()); -} - - -// static -shared_ptr POP3Command::UIDL() -{ - return createCommand("UIDL"); -} - - -// static -shared_ptr POP3Command::UIDL(const unsigned long msg) -{ - std::ostringstream cmd; - cmd.imbue(std::locale::classic()); - cmd << "UIDL " << msg; - - return createCommand(cmd.str()); -} - - -// static -shared_ptr POP3Command::DELE(const unsigned long msg) -{ - std::ostringstream cmd; - cmd.imbue(std::locale::classic()); - cmd << "DELE " << msg; - - return createCommand(cmd.str()); -} - - -// static -shared_ptr POP3Command::RETR(const unsigned long msg) -{ - std::ostringstream cmd; - cmd.imbue(std::locale::classic()); - cmd << "RETR " << msg; - - return createCommand(cmd.str()); -} - - -// static -shared_ptr POP3Command::TOP(const unsigned long msg, const unsigned long lines) -{ - std::ostringstream cmd; - cmd.imbue(std::locale::classic()); - cmd << "TOP " << msg << " " << lines; - - return createCommand(cmd.str()); -} - - -// static -shared_ptr POP3Command::RSET() -{ - return createCommand("RSET"); -} - - -// static -shared_ptr POP3Command::QUIT() -{ - return createCommand("QUIT"); -} - - -// static -shared_ptr POP3Command::createCommand(const string& text) -{ - return shared_ptr (new POP3Command(text)); -} - - -const string POP3Command::getText() const -{ - return m_text; -} - - -void POP3Command::send(shared_ptr conn) -{ - conn->getSocket()->send(m_text + "\r\n"); -} - - -} // pop3 -} // net -} // vmime - - -#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_POP3 diff --git a/src/net/pop3/POP3Connection.cpp b/src/net/pop3/POP3Connection.cpp deleted file mode 100644 index 5fa923f4..00000000 --- a/src/net/pop3/POP3Connection.cpp +++ /dev/null @@ -1,675 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// 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 && VMIME_HAVE_MESSAGING_PROTO_POP3 - - -#include "vmime/net/pop3/POP3Connection.hpp" -#include "vmime/net/pop3/POP3Store.hpp" - -#include "vmime/exception.hpp" -#include "vmime/platform.hpp" - -#include "vmime/security/digest/messageDigestFactory.hpp" - -#include "vmime/net/defaultConnectionInfos.hpp" - -#if VMIME_HAVE_SASL_SUPPORT - #include "vmime/security/sasl/SASLContext.hpp" -#endif // VMIME_HAVE_SASL_SUPPORT - -#if VMIME_HAVE_TLS_SUPPORT - #include "vmime/net/tls/TLSSession.hpp" - #include "vmime/net/tls/TLSSecuredConnectionInfos.hpp" -#endif // VMIME_HAVE_TLS_SUPPORT - - - -// Helpers for service properties -#define GET_PROPERTY(type, prop) \ - (m_store.lock()->getInfos().getPropertyValue (getSession(), \ - dynamic_cast (m_store.lock()->getInfos()).getProperties().prop)) -#define HAS_PROPERTY(prop) \ - (m_store.lock()->getInfos().hasProperty(getSession(), \ - dynamic_cast (m_store.lock()->getInfos()).getProperties().prop)) - - -namespace vmime { -namespace net { -namespace pop3 { - - - -POP3Connection::POP3Connection(shared_ptr store, shared_ptr auth) - : m_store(store), m_auth(auth), m_socket(null), m_timeoutHandler(null), - m_authenticated(false), m_secured(false), m_capabilitiesFetched(false) -{ -} - - -POP3Connection::~POP3Connection() -{ - try - { - if (isConnected()) - disconnect(); - else if (m_socket) - internalDisconnect(); - } - catch (vmime::exception&) - { - // Ignore - } -} - - -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); - - shared_ptr store = m_store.lock(); - - // Create the time-out handler - if (store->getTimeoutHandlerFactory()) - m_timeoutHandler = store->getTimeoutHandlerFactory()->create(); - - // Create and connect the socket - m_socket = store->getSocketFactory()->create(m_timeoutHandler); - -#if VMIME_HAVE_TLS_SUPPORT - if (store->isPOP3S()) // dedicated port/POP3S - { - shared_ptr tlsSession = tls::TLSSession::create - (store->getCertificateVerifier(), - store->getSession()->getTLSProperties()); - - shared_ptr tlsSocket = - tlsSession->getSocket(m_socket); - - m_socket = tlsSocket; - - m_secured = true; - m_cntInfos = make_shared (address, port, tlsSession, tlsSocket); - } - else -#endif // VMIME_HAVE_TLS_SUPPORT - { - m_cntInfos = make_shared (address, port); - } - - m_socket->connect(address, port); - - // Connection - // - // eg: C: - // --- S: +OK MailSite POP3 Server 5.3.4.0 Ready <36938848.1056800841.634@somewhere.com> - - shared_ptr response = POP3Response::readResponse - (dynamicCast (shared_from_this())); - - if (!response->isSuccess()) - { - internalDisconnect(); - throw exceptions::connection_greeting_error(response->getFirstLine()); - } - -#if VMIME_HAVE_TLS_SUPPORT - // Setup secured connection, if requested - const bool tls = HAS_PROPERTY(PROPERTY_CONNECTION_TLS) - && GET_PROPERTY(bool, PROPERTY_CONNECTION_TLS); - 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 - { - startTLS(); - } - // Non-fatal error - catch (exceptions::command_error&) - { - if (tlsRequired) - { - throw; - } - else - { - // TLS is not required, so don't bother - } - } - // Fatal error - catch (...) - { - throw; - } - } -#endif // VMIME_HAVE_TLS_SUPPORT - - // Start authentication process - authenticate(messageId(response->getText())); -} - - -void POP3Connection::disconnect() -{ - if (!isConnected()) - throw exceptions::not_connected(); - - internalDisconnect(); -} - - -void POP3Connection::internalDisconnect() -{ - if (m_socket) - { - if (m_socket->isConnected()) - { - try - { - POP3Command::QUIT()->send(dynamicCast (shared_from_this())); - POP3Response::readResponse(dynamicCast (shared_from_this())); - } - catch (exception&) - { - // Not important - } - - m_socket->disconnect(); - } - - m_socket = null; - } - - m_timeoutHandler = null; - - m_authenticated = false; - m_secured = false; - - m_cntInfos = null; -} - - -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 - { - authenticateSASL(); - - m_authenticated = true; - return; - } - catch (exceptions::authentication_error& e) - { - if (!GET_PROPERTY(bool, PROPERTY_OPTIONS_SASL_FALLBACK)) - { - // Can't fallback on APOP/normal authentication - internalDisconnect(); - throw e; - } - else - { - // Ignore, will try APOP/normal authentication - } - } - catch (exception& e) - { - internalDisconnect(); - throw e; - } - } -#endif // VMIME_HAVE_SASL_SUPPORT - - // Secured authentication with APOP (if requested and if available) - // - // eg: C: APOP vincent - // --- S: +OK vincent is a valid mailbox - - const string username = getAuthenticator()->getUsername(); - const string password = getAuthenticator()->getPassword(); - - shared_ptr conn = dynamicCast (shared_from_this()); - shared_ptr response; - - if (GET_PROPERTY(bool, PROPERTY_OPTIONS_APOP)) - { - if (randomMID.getLeft().length() != 0 && - randomMID.getRight().length() != 0) - { - // is the result of MD5 applied to "password" - shared_ptr md5 = - security::digest::messageDigestFactory::getInstance()->create("md5"); - - md5->update(randomMID.generate() + password); - md5->finalize(); - - POP3Command::APOP(username, md5->getHexDigest())->send(conn); - response = POP3Response::readResponse(conn); - - if (response->isSuccess()) - { - m_authenticated = true; - return; - } - else - { - // Some servers close the connection after an unsuccessful APOP - // command, so the fallback may not always work... - // - // S: +OK Qpopper (version 4.0.5) at xxx starting. <30396.1126730747@xxx> - // C: APOP plop c5e0a87d088ec71d60e32692d4c5bdf4 - // S: -ERR [AUTH] Password supplied for "plop" is incorrect. - // S: +OK Pop server at xxx signing off. - // [Connection closed by foreign host.] - - 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 - { - POP3Command::NOOP()->send(conn); - POP3Response::readResponse(conn); - } - catch (exceptions::socket_exception&) - { - internalDisconnect(); - throw exceptions::authentication_error(response->getFirstLine()); - } - } - } - else - { - // APOP not supported - if (!GET_PROPERTY(bool, PROPERTY_OPTIONS_APOP_FALLBACK)) - { - // Can't fallback on basic authentication - internalDisconnect(); - throw exceptions::authentication_error("APOP not supported"); - } - } - } - - // Basic authentication - // - // eg: C: USER vincent - // --- S: +OK vincent is a valid mailbox - // - // C: PASS couic - // S: +OK vincent's maildrop has 2 messages (320 octets) - POP3Command::USER(username)->send(conn); - response = POP3Response::readResponse(conn); - - if (!response->isSuccess()) - { - internalDisconnect(); - throw exceptions::authentication_error(response->getFirstLine()); - } - - POP3Command::PASS(password)->send(conn); - response = POP3Response::readResponse(conn); - - if (!response->isSuccess()) - { - internalDisconnect(); - throw exceptions::authentication_error(response->getFirstLine()); - } - - m_authenticated = true; -} - - -#if VMIME_HAVE_SASL_SUPPORT - -void POP3Connection::authenticateSASL() -{ - if (!dynamicCast (getAuthenticator())) - throw exceptions::authentication_error("No SASL authenticator available."); - - std::vector capa = getCapabilities(); - std::vector saslMechs; - - for (unsigned int i = 0 ; i < capa.size() ; ++i) - { - const string& x = capa[i]; - - // C: CAPA - // S: +OK List of capabilities follows - // S: LOGIN-DELAY 0 - // S: PIPELINING - // S: UIDL - // S: ... - // S: SASL DIGEST-MD5 CRAM-MD5 <----- - // S: EXPIRE NEVER - // S: ... - - if (x.length() > 5 && - (x[0] == 'S' || x[0] == 's') && - (x[1] == 'A' || x[1] == 'a') && - (x[2] == 'S' || x[2] == 's') && - (x[3] == 'L' || x[3] == 'l') && - (x[4] == ' ' || x[4] == '\t')) - { - const string list(x.begin() + 5, x.end()); - - std::istringstream iss(list); - string mech; - - while (iss >> mech) - saslMechs.push_back(mech); - } - } - - if (saslMechs.empty()) - throw exceptions::authentication_error("No SASL mechanism available."); - - std::vector > mechList; - - shared_ptr saslContext = - make_shared (); - - 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()) - throw exceptions::authentication_error("No SASL mechanism available."); - - // Try to suggest a mechanism among all those supported - shared_ptr suggestedMech = - saslContext->suggestMechanism(mechList); - - if (!suggestedMech) - throw exceptions::authentication_error("Unable to suggest SASL mechanism."); - - // Allow application to choose which mechanisms to use - mechList = dynamicCast (getAuthenticator())-> - getAcceptableMechanisms(mechList, suggestedMech); - - 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) - { - shared_ptr mech = mechList[i]; - - shared_ptr saslSession = - saslContext->createSession("pop3", getAuthenticator(), mech); - - saslSession->init(); - - POP3Command::AUTH(mech->getName())->send(dynamicCast (shared_from_this())); - - for (bool cont = true ; cont ; ) - { - shared_ptr response = - POP3Response::readResponse(dynamicCast (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; - - byte_t* resp = 0; - size_t respLen = 0; - - try - { - // Extract challenge - saslContext->decodeB64(response->getText(), &challenge, &challengeLen); - - // Prepare response - saslSession->evaluateChallenge - (challenge, challengeLen, &resp, &respLen); - - // Send response - m_socket->send(saslContext->encodeB64(resp, respLen) + "\r\n"); - } - 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"); - } - catch (...) - { - if (challenge) - delete [] challenge; - - if (resp) - delete [] resp; - - throw; - } - - if (challenge) - delete [] challenge; - - if (resp) - delete [] resp; - - break; - } - default: - - cont = false; - break; - } - } - } - - throw exceptions::authentication_error - ("Could not authenticate using SASL: all mechanisms failed."); -} - -#endif // VMIME_HAVE_SASL_SUPPORT - - -#if VMIME_HAVE_TLS_SUPPORT - -void POP3Connection::startTLS() -{ - try - { - POP3Command::STLS()->send(dynamicCast (shared_from_this())); - - shared_ptr response = - POP3Response::readResponse(dynamicCast (shared_from_this())); - - if (!response->isSuccess()) - throw exceptions::command_error("STLS", response->getFirstLine()); - - shared_ptr tlsSession = tls::TLSSession::create - (m_store.lock()->getCertificateVerifier(), - m_store.lock()->getSession()->getTLSProperties()); - - shared_ptr tlsSocket = - tlsSession->getSocket(m_socket); - - tlsSocket->handshake(m_timeoutHandler); - - m_socket = tlsSocket; - - m_secured = true; - m_cntInfos = make_shared - (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 CAPA command. This is necessary to protect against - // man-in-the-middle attacks which alter the capabilities list - // prior to STLS. " (RFC-2595) - invalidateCapabilities(); - } - catch (exceptions::command_error&) - { - // Non-fatal error - throw; - } - catch (exception&) - { - // Fatal error - internalDisconnect(); - throw; - } -} - -#endif // VMIME_HAVE_TLS_SUPPORT - - -const std::vector POP3Connection::getCapabilities() -{ - if (!m_capabilitiesFetched) - fetchCapabilities(); - - return m_capabilities; -} - - -void POP3Connection::invalidateCapabilities() -{ - m_capabilities.clear(); - m_capabilitiesFetched = false; -} - - -void POP3Connection::fetchCapabilities() -{ - POP3Command::CAPA()->send(dynamicCast (shared_from_this())); - - shared_ptr response = - POP3Response::readMultilineResponse(dynamicCast (shared_from_this())); - - std::vector res; - - if (response->isSuccess()) - { - for (size_t i = 0, n = response->getLineCount() ; i < n ; ++i) - res.push_back(response->getLineAt(i)); - } - - m_capabilities = res; - m_capabilitiesFetched = true; -} - - -bool POP3Connection::isConnected() const -{ - return m_socket && m_socket->isConnected() && m_authenticated; -} - - -bool POP3Connection::isSecuredConnection() const -{ - return m_secured; -} - - -shared_ptr POP3Connection::getConnectionInfos() const -{ - return m_cntInfos; -} - - -shared_ptr POP3Connection::getStore() -{ - return m_store.lock(); -} - - -shared_ptr POP3Connection::getSession() -{ - return m_store.lock()->getSession(); -} - - -shared_ptr POP3Connection::getSocket() -{ - return m_socket; -} - - -shared_ptr POP3Connection::getTimeoutHandler() -{ - return m_timeoutHandler; -} - - -shared_ptr POP3Connection::getAuthenticator() -{ - return m_auth; -} - - -} // pop3 -} // net -} // vmime - - -#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_POP3 diff --git a/src/net/pop3/POP3Folder.cpp b/src/net/pop3/POP3Folder.cpp deleted file mode 100644 index 096de8af..00000000 --- a/src/net/pop3/POP3Folder.cpp +++ /dev/null @@ -1,729 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// 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 && VMIME_HAVE_MESSAGING_PROTO_POP3 - - -#include "vmime/net/pop3/POP3Folder.hpp" - -#include "vmime/net/pop3/POP3Store.hpp" -#include "vmime/net/pop3/POP3Message.hpp" -#include "vmime/net/pop3/POP3Command.hpp" -#include "vmime/net/pop3/POP3Response.hpp" -#include "vmime/net/pop3/POP3FolderStatus.hpp" - -#include "vmime/net/pop3/POP3Utils.hpp" - -#include "vmime/exception.hpp" - - -namespace vmime { -namespace net { -namespace pop3 { - - -POP3Folder::POP3Folder(const folder::path& path, shared_ptr store) - : m_store(store), m_path(path), - m_name(path.isEmpty() ? folder::path::component("") : path.getLastComponent()), - m_mode(-1), m_open(false) -{ - store->registerFolder(this); -} - - -POP3Folder::~POP3Folder() -{ - shared_ptr store = m_store.lock(); - - if (store) - { - if (m_open) - close(false); - - store->unregisterFolder(this); - } - else if (m_open) - { - onClose(); - } -} - - -int POP3Folder::getMode() const -{ - if (!isOpen()) - throw exceptions::illegal_state("Folder not open"); - - return (m_mode); -} - - -int POP3Folder::getType() -{ - if (!isOpen()) - throw exceptions::illegal_state("Folder not open"); - - if (m_path.isEmpty()) - return (TYPE_CONTAINS_FOLDERS); - else if (m_path.getSize() == 1 && m_path[0].getBuffer() == "INBOX") - return (TYPE_CONTAINS_MESSAGES); - else - throw exceptions::folder_not_found(); -} - - -int POP3Folder::getFlags() -{ - return (0); -} - - -const folder::path::component POP3Folder::getName() const -{ - return (m_name); -} - - -const folder::path POP3Folder::getFullPath() const -{ - return (m_path); -} - - -void POP3Folder::open(const int mode, bool failIfModeIsNotAvailable) -{ - shared_ptr store = m_store.lock(); - - if (!store) - throw exceptions::illegal_state("Store disconnected"); - - 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") - { - POP3Command::STAT()->send(store->getConnection()); - - shared_ptr response = POP3Response::readResponse(store->getConnection()); - - if (!response->isSuccess()) - throw exceptions::command_error("STAT", response->getFirstLine()); - - std::istringstream iss(response->getText()); - iss >> m_messageCount; - - if (iss.fail()) - throw exceptions::invalid_response("STAT", response->getFirstLine()); - - m_open = true; - m_mode = mode; - } - else - { - throw exceptions::folder_not_found(); - } -} - -void POP3Folder::close(const bool expunge) -{ - shared_ptr store = m_store.lock(); - - if (!store) - throw exceptions::illegal_state("Store disconnected"); - - if (!isOpen()) - throw exceptions::illegal_state("Folder not open"); - - if (!expunge) - { - POP3Command::RSET()->send(store->getConnection()); - POP3Response::readResponse(store->getConnection()); - } - - m_open = false; - m_mode = -1; - - onClose(); -} - - -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 int /* type */) -{ - throw exceptions::operation_not_supported(); -} - - -void POP3Folder::destroy() -{ - throw exceptions::operation_not_supported(); -} - - -bool POP3Folder::exists() -{ - shared_ptr store = m_store.lock(); - - if (!store) - throw exceptions::illegal_state("Store disconnected"); - - return (m_path.isEmpty() || (m_path.getSize() == 1 && m_path[0].getBuffer() == "INBOX")); -} - - -bool POP3Folder::isOpen() const -{ - return (m_open); -} - - -shared_ptr POP3Folder::getMessage(const int num) -{ - shared_ptr store = m_store.lock(); - - if (!store) - throw exceptions::illegal_state("Store disconnected"); - else if (!isOpen()) - throw exceptions::illegal_state("Folder not open"); - else if (num < 1 || num > m_messageCount) - throw exceptions::message_not_found(); - - return make_shared (dynamicCast (shared_from_this()), num); -} - - -std::vector > POP3Folder::getMessages(const messageSet& msgs) -{ - shared_ptr store = m_store.lock(); - - if (!store) - throw exceptions::illegal_state("Store disconnected"); - else if (!isOpen()) - throw exceptions::illegal_state("Folder not open"); - - if (msgs.isNumberSet()) - { - const std::vector numbers = POP3Utils::messageSetToNumberList(msgs); - - std::vector > messages; - shared_ptr thisFolder(dynamicCast (shared_from_this())); - - for (std::vector ::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 (thisFolder, *it)); - } - - return messages; - } - else - { - throw exceptions::operation_not_supported(); - } -} - - -int POP3Folder::getMessageCount() -{ - shared_ptr store = m_store.lock(); - - if (!store) - throw exceptions::illegal_state("Store disconnected"); - else if (!isOpen()) - throw exceptions::illegal_state("Folder not open"); - - return (m_messageCount); -} - - -shared_ptr POP3Folder::getFolder(const folder::path::component& name) -{ - shared_ptr store = m_store.lock(); - - if (!store) - throw exceptions::illegal_state("Store disconnected"); - - return make_shared (m_path / name, store); -} - - -std::vector > POP3Folder::getFolders(const bool /* recursive */) -{ - shared_ptr store = m_store.lock(); - - if (!store) - throw exceptions::illegal_state("Store disconnected"); - - if (m_path.isEmpty()) - { - std::vector > v; - v.push_back(make_shared (folder::path::component("INBOX"), store)); - return (v); - } - else - { - std::vector > v; - return (v); - } -} - - -void POP3Folder::fetchMessages(std::vector >& msg, const fetchAttributes& options, - utility::progressListener* progress) -{ - shared_ptr store = m_store.lock(); - - if (!store) - throw exceptions::illegal_state("Store disconnected"); - else if (!isOpen()) - throw exceptions::illegal_state("Folder not open"); - - const size_t total = msg.size(); - size_t current = 0; - - if (progress) - progress->start(total); - - for (std::vector >::iterator it = msg.begin() ; - it != msg.end() ; ++it) - { - dynamicCast (*it)->fetch - (dynamicCast (shared_from_this()), options); - - if (progress) - progress->progress(++current, total); - } - - if (options.has(fetchAttributes::SIZE)) - { - // Send the "LIST" command - POP3Command::LIST()->send(store->getConnection()); - - // Get the response - shared_ptr response = - POP3Response::readMultilineResponse(store->getConnection()); - - if (response->isSuccess()) - { - // C: LIST - // S: +OK - // S: 1 47548 - // S: 2 12653 - // S: . - std::map result; - POP3Utils::parseMultiListOrUidlResponse(response, result); - - for (std::vector >::iterator it = msg.begin() ; - it != msg.end() ; ++it) - { - shared_ptr m = dynamicCast (*it); - - std::map ::const_iterator x = result.find(m->m_num); - - if (x != result.end()) - { - size_t size = 0; - - std::istringstream iss((*x).second); - iss >> size; - - m->m_size = size; - } - } - } - - } - - if (options.has(fetchAttributes::UID)) - { - // Send the "UIDL" command - POP3Command::UIDL()->send(store->getConnection()); - - // Get the response - shared_ptr response = - POP3Response::readMultilineResponse(store->getConnection()); - - if (response->isSuccess()) - { - // C: UIDL - // S: +OK - // S: 1 whqtswO00WBw418f9t5JxYwZ - // S: 2 QhdPYR:00WBw1Ph7x7 - // S: . - std::map result; - POP3Utils::parseMultiListOrUidlResponse(response, result); - - for (std::vector >::iterator it = msg.begin() ; - it != msg.end() ; ++it) - { - shared_ptr m = dynamicCast (*it); - - std::map ::const_iterator x = result.find(m->m_num); - - if (x != result.end()) - m->m_uid = (*x).second; - } - } - } - - if (progress) - progress->stop(total); -} - - -void POP3Folder::fetchMessage(shared_ptr msg, const fetchAttributes& options) -{ - shared_ptr store = m_store.lock(); - - if (!store) - throw exceptions::illegal_state("Store disconnected"); - else if (!isOpen()) - throw exceptions::illegal_state("Folder not open"); - - dynamicCast (msg)->fetch - (dynamicCast (shared_from_this()), options); - - if (options.has(fetchAttributes::SIZE)) - { - // Send the "LIST" command - POP3Command::LIST(msg->getNumber())->send(store->getConnection()); - - // Get the response - shared_ptr response = - POP3Response::readResponse(store->getConnection()); - - if (response->isSuccess()) - { - string responseText = response->getText(); - - // C: LIST 2 - // S: +OK 2 4242 - string::iterator it = responseText.begin(); - - while (it != responseText.end() && (*it == ' ' || *it == '\t')) ++it; - while (it != responseText.end() && !(*it == ' ' || *it == '\t')) ++it; - while (it != responseText.end() && (*it == ' ' || *it == '\t')) ++it; - - if (it != responseText.end()) - { - size_t size = 0; - - std::istringstream iss(string(it, responseText.end())); - iss >> size; - - dynamicCast (msg)->m_size = size; - } - } - } - - if (options.has(fetchAttributes::UID)) - { - // Send the "UIDL" command - POP3Command::UIDL(msg->getNumber())->send(store->getConnection()); - - // Get the response - shared_ptr response = - POP3Response::readResponse(store->getConnection()); - - if (response->isSuccess()) - { - string responseText = response->getText(); - - // C: UIDL 2 - // S: +OK 2 QhdPYR:00WBw1Ph7x7 - string::iterator it = responseText.begin(); - - while (it != responseText.end() && (*it == ' ' || *it == '\t')) ++it; - while (it != responseText.end() && !(*it == ' ' || *it == '\t')) ++it; - while (it != responseText.end() && (*it == ' ' || *it == '\t')) ++it; - - if (it != responseText.end()) - { - dynamicCast (msg)->m_uid = - string(it, responseText.end()); - } - } - } -} - - -int POP3Folder::getFetchCapabilities() const -{ - return fetchAttributes::ENVELOPE | fetchAttributes::CONTENT_INFO | - fetchAttributes::SIZE | fetchAttributes::FULL_HEADER | - fetchAttributes::UID | fetchAttributes::IMPORTANCE; -} - - -shared_ptr POP3Folder::getParent() -{ - if (m_path.isEmpty()) - return null; - else - return make_shared (m_path.getParent(), m_store.lock()); -} - - -shared_ptr POP3Folder::getStore() const -{ - return m_store.lock(); -} - - -shared_ptr POP3Folder::getStore() -{ - return m_store.lock(); -} - - -void POP3Folder::registerMessage(POP3Message* msg) -{ - m_messages.insert(MessageMap::value_type(msg, msg->getNumber())); -} - - -void POP3Folder::unregisterMessage(POP3Message* msg) -{ - m_messages.erase(msg); -} - - -void POP3Folder::onStoreDisconnected() -{ - m_store.reset(); -} - - -void POP3Folder::deleteMessages(const messageSet& msgs) -{ - shared_ptr store = m_store.lock(); - - const std::vector nums = POP3Utils::messageSetToNumberList(msgs); - - if (nums.empty()) - throw exceptions::invalid_argument(); - - if (!store) - throw exceptions::illegal_state("Store disconnected"); - else if (!isOpen()) - throw exceptions::illegal_state("Folder not open"); - - for (std::vector ::const_iterator - it = nums.begin() ; it != nums.end() ; ++it) - { - POP3Command::DELE(*it)->send(store->getConnection()); - - shared_ptr response = - POP3Response::readResponse(store->getConnection()); - - if (!response->isSuccess()) - throw exceptions::command_error("DELE", response->getFirstLine()); - } - - // Sort message list - std::vector list; - - list.resize(nums.size()); - std::copy(nums.begin(), nums.end(), list.begin()); - - std::sort(list.begin(), list.end()); - - // Update local flags - for (std::map ::iterator it = - m_messages.begin() ; it != m_messages.end() ; ++it) - { - POP3Message* msg = (*it).first; - - if (std::binary_search(list.begin(), list.end(), msg->getNumber())) - msg->m_deleted = true; - } - - // Notify message flags changed - shared_ptr event = - make_shared - (dynamicCast (shared_from_this()), - events::messageChangedEvent::TYPE_FLAGS, list); - - notifyMessageChanged(event); -} - - -void POP3Folder::setMessageFlags(const messageSet& /* msgs */, - const int /* flags */, const int /* mode */) -{ - throw exceptions::operation_not_supported(); -} - - -void POP3Folder::rename(const folder::path& /* newPath */) -{ - throw exceptions::operation_not_supported(); -} - - -void POP3Folder::addMessage - (shared_ptr /* msg */, const int /* flags */, - vmime::datetime* /* date */, utility::progressListener* /* progress */) -{ - throw exceptions::operation_not_supported(); -} - - -void POP3Folder::addMessage - (utility::inputStream& /* is */, const size_t /* size */, const int /* flags */, - vmime::datetime* /* date */, utility::progressListener* /* progress */) -{ - throw exceptions::operation_not_supported(); -} - - -void POP3Folder::copyMessages(const folder::path& /* dest */, const messageSet& /* msgs */) -{ - throw exceptions::operation_not_supported(); -} - - -void POP3Folder::status(int& count, int& unseen) -{ - count = 0; - unseen = 0; - - shared_ptr status = getStatus(); - - count = status->getMessageCount(); - unseen = status->getUnseenCount(); -} - - -shared_ptr POP3Folder::getStatus() -{ - shared_ptr store = m_store.lock(); - - if (!store) - throw exceptions::illegal_state("Store disconnected"); - - POP3Command::STAT()->send(store->getConnection()); - - shared_ptr response = - POP3Response::readResponse(store->getConnection()); - - if (!response->isSuccess()) - throw exceptions::command_error("STAT", response->getFirstLine()); - - - unsigned int count = 0; - - std::istringstream iss(response->getText()); - iss >> count; - - shared_ptr status = make_shared (); - - status->setMessageCount(count); - status->setUnseenCount(count); - - // Update local message count - if (m_messageCount != count) - { - const int oldCount = m_messageCount; - - m_messageCount = count; - - if (count > oldCount) - { - std::vector nums; - nums.reserve(count - oldCount); - - for (int i = oldCount + 1, j = 0 ; i <= count ; ++i, ++j) - nums[j] = i; - - // Notify message count changed - shared_ptr event = - make_shared - (dynamicCast (shared_from_this()), - events::messageCountEvent::TYPE_ADDED, nums); - - notifyMessageCount(event); - - // Notify folders with the same path - for (std::list ::iterator it = store->m_folders.begin() ; - it != store->m_folders.end() ; ++it) - { - if ((*it) != this && (*it)->getFullPath() == m_path) - { - (*it)->m_messageCount = count; - - shared_ptr event = - make_shared - (dynamicCast ((*it)->shared_from_this()), - events::messageCountEvent::TYPE_ADDED, nums); - - (*it)->notifyMessageCount(event); - } - } - } - } - - return status; -} - - -void POP3Folder::expunge() -{ - // Not supported by POP3 protocol (deleted messages are automatically - // expunged at the end of the session...). -} - - -std::vector POP3Folder::getMessageNumbersStartingOnUID(const message::uid& /* uid */) -{ - throw exceptions::operation_not_supported(); -} - - -} // pop3 -} // net -} // vmime - - -#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_POP3 - diff --git a/src/net/pop3/POP3FolderStatus.cpp b/src/net/pop3/POP3FolderStatus.cpp deleted file mode 100644 index 944379ac..00000000 --- a/src/net/pop3/POP3FolderStatus.cpp +++ /dev/null @@ -1,88 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// 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 && VMIME_HAVE_MESSAGING_PROTO_POP3 - - -#include "vmime/net/pop3/POP3FolderStatus.hpp" - - -namespace vmime { -namespace net { -namespace pop3 { - - -POP3FolderStatus::POP3FolderStatus() - : m_count(0), - m_unseen(0) -{ -} - - -POP3FolderStatus::POP3FolderStatus(const POP3FolderStatus& other) - : folderStatus(), - m_count(other.m_count), - m_unseen(other.m_unseen) -{ -} - - -unsigned int POP3FolderStatus::getMessageCount() const -{ - return m_count; -} - - -unsigned int POP3FolderStatus::getUnseenCount() const -{ - return m_unseen; -} - - -void POP3FolderStatus::setMessageCount(const unsigned int count) -{ - m_count = count; -} - - -void POP3FolderStatus::setUnseenCount(const unsigned int unseen) -{ - m_unseen = unseen; -} - - -shared_ptr POP3FolderStatus::clone() const -{ - return make_shared (*this); -} - - -} // pop3 -} // net -} // vmime - - -#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_POP3 diff --git a/src/net/pop3/POP3Message.cpp b/src/net/pop3/POP3Message.cpp deleted file mode 100644 index 08523611..00000000 --- a/src/net/pop3/POP3Message.cpp +++ /dev/null @@ -1,250 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// 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 && VMIME_HAVE_MESSAGING_PROTO_POP3 - - -#include "vmime/net/pop3/POP3Message.hpp" -#include "vmime/net/pop3/POP3Command.hpp" -#include "vmime/net/pop3/POP3Response.hpp" -#include "vmime/net/pop3/POP3Folder.hpp" -#include "vmime/net/pop3/POP3Store.hpp" - -#include "vmime/utility/outputStreamAdapter.hpp" -#include "vmime/utility/outputStreamStringAdapter.hpp" - -#include - - -namespace vmime { -namespace net { -namespace pop3 { - - -POP3Message::POP3Message(shared_ptr folder, const int num) - : m_folder(folder), m_num(num), m_size(-1), m_deleted(false) -{ - folder->registerMessage(this); -} - - -POP3Message::~POP3Message() -{ - shared_ptr folder = m_folder.lock(); - - if (folder) - folder->unregisterMessage(this); -} - - -void POP3Message::onFolderClosed() -{ - m_folder.reset(); -} - - -int POP3Message::getNumber() const -{ - return (m_num); -} - - -const message::uid POP3Message::getUID() const -{ - return (m_uid); -} - - -size_t POP3Message::getSize() const -{ - if (m_size == static_cast (-1)) - throw exceptions::unfetched_object(); - - return (m_size); -} - - -bool POP3Message::isExpunged() const -{ - return (false); -} - - -int POP3Message::getFlags() const -{ - int flags = FLAG_RECENT; - - if (m_deleted) - flags |= FLAG_DELETED; - - return (flags); -} - - -shared_ptr POP3Message::getStructure() const -{ - throw exceptions::operation_not_supported(); -} - - -shared_ptr POP3Message::getStructure() -{ - throw exceptions::operation_not_supported(); -} - - -shared_ptr POP3Message::getHeader() const -{ - if (m_header == NULL) - throw exceptions::unfetched_object(); - - return (m_header); -} - - -void POP3Message::extract - (utility::outputStream& os, - utility::progressListener* progress, - const size_t start, const size_t length, - const bool /* peek */) const -{ - shared_ptr folder = m_folder.lock(); - - if (!folder) - throw exceptions::illegal_state("Folder closed"); - else if (!folder->getStore()) - throw exceptions::illegal_state("Store disconnected"); - - if (start != 0 && length != static_cast (-1)) - throw exceptions::partial_fetch_not_supported(); - - // Emit the "RETR" command - shared_ptr store = constCast (folder)->m_store.lock(); - - POP3Command::RETR(m_num)->send(store->getConnection()); - - try - { - POP3Response::readLargeResponse - (store->getConnection(), os, progress, m_size); - } - catch (exceptions::command_error& e) - { - throw exceptions::command_error("RETR", e.response()); - } -} - - -void POP3Message::extractPart - (shared_ptr /* 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 /* p */) -{ - throw exceptions::operation_not_supported(); -} - - -void POP3Message::fetch(shared_ptr msgFolder, const fetchAttributes& options) -{ - shared_ptr folder = m_folder.lock(); - - if (folder != msgFolder) - throw exceptions::folder_not_found(); - - // STRUCTURE and FLAGS attributes are not supported by POP3 - 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)) - return; - - // No need to differenciate between ENVELOPE, CONTENT_INFO, ... - // since POP3 only permits to retrieve the whole header and not - // fields in particular. - - // Emit the "TOP" command - shared_ptr store = folder->m_store.lock(); - - POP3Command::TOP(m_num, 0)->send(store->getConnection()); - - try - { - string buffer; - utility::outputStreamStringAdapter bufferStream(buffer); - - POP3Response::readLargeResponse(store->getConnection(), - bufferStream, /* progress */ NULL, /* predictedSize */ 0); - - m_header = make_shared
(); - m_header->parse(buffer); - } - catch (exceptions::command_error& e) - { - throw exceptions::command_error("TOP", e.response()); - } -} - - -void POP3Message::setFlags(const int /* flags */, const int /* mode */) -{ - throw exceptions::operation_not_supported(); -} - - -shared_ptr POP3Message::getParsedMessage() -{ - std::ostringstream oss; - utility::outputStreamAdapter os(oss); - - extract(os); - - shared_ptr msg = make_shared (); - msg->parse(oss.str()); - - return msg; -} - - -} // pop3 -} // net -} // vmime - - -#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_POP3 - diff --git a/src/net/pop3/POP3Response.cpp b/src/net/pop3/POP3Response.cpp deleted file mode 100644 index 1dc5ee76..00000000 --- a/src/net/pop3/POP3Response.cpp +++ /dev/null @@ -1,428 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// 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 && VMIME_HAVE_MESSAGING_PROTO_POP3 - - -#include "vmime/net/pop3/POP3Response.hpp" -#include "vmime/net/pop3/POP3Connection.hpp" - -#include "vmime/platform.hpp" - -#include "vmime/utility/stringUtils.hpp" -#include "vmime/utility/filteredStream.hpp" -#include "vmime/utility/stringUtils.hpp" -#include "vmime/utility/inputStreamSocketAdapter.hpp" - -#include "vmime/net/socket.hpp" -#include "vmime/net/timeoutHandler.hpp" - - -namespace vmime { -namespace net { -namespace pop3 { - - -POP3Response::POP3Response(shared_ptr sok, shared_ptr toh) - : m_socket(sok), m_timeoutHandler(toh) -{ -} - - -// static -shared_ptr POP3Response::readResponse(shared_ptr conn) -{ - shared_ptr resp = shared_ptr - (new POP3Response(conn->getSocket(), conn->getTimeoutHandler())); - - string buffer; - resp->readResponseImpl(buffer, /* multiLine */ false); - - resp->m_firstLine = buffer; - resp->m_code = getResponseCode(buffer); - stripResponseCode(buffer, resp->m_text); - - return resp; -} - - -// static -shared_ptr POP3Response::readMultilineResponse(shared_ptr conn) -{ - shared_ptr resp = shared_ptr - (new POP3Response(conn->getSocket(), conn->getTimeoutHandler())); - - string buffer; - resp->readResponseImpl(buffer, /* multiLine */ true); - - string firstLine, nextLines; - stripFirstLine(buffer, nextLines, &firstLine); - - resp->m_firstLine = firstLine; - resp->m_code = getResponseCode(firstLine); - stripResponseCode(firstLine, resp->m_text); - - std::istringstream iss(nextLines); - string line; - - while (std::getline(iss, line, '\n')) - resp->m_lines.push_back(utility::stringUtils::trim(line)); - - return resp; -} - - -// static -shared_ptr POP3Response::readLargeResponse - (shared_ptr conn, utility::outputStream& os, - utility::progressListener* progress, const size_t predictedSize) -{ - shared_ptr resp = shared_ptr - (new POP3Response(conn->getSocket(), conn->getTimeoutHandler())); - - string firstLine; - resp->readResponseImpl(firstLine, os, progress, predictedSize); - - resp->m_firstLine = firstLine; - resp->m_code = getResponseCode(firstLine); - stripResponseCode(firstLine, resp->m_text); - - return resp; -} - - -bool POP3Response::isSuccess() const -{ - return m_code == CODE_OK; -} - - -const string POP3Response::getFirstLine() const -{ - return m_firstLine; -} - - -POP3Response::ResponseCode POP3Response::getCode() const -{ - return m_code; -} - - -const string POP3Response::getText() const -{ - return m_text; -} - - -const string POP3Response::getLineAt(const size_t pos) const -{ - return m_lines[pos]; -} - - -size_t POP3Response::getLineCount() const -{ - return m_lines.size(); -} - - -void POP3Response::readResponseImpl(string& buffer, const bool multiLine) -{ - bool foundTerminator = false; - - if (m_timeoutHandler) - m_timeoutHandler->resetTimeOut(); - - buffer.clear(); - - char last1 = '\0', last2 = '\0'; - - for ( ; !foundTerminator ; ) - { - // Check whether the time-out delay is elapsed - if (m_timeoutHandler && m_timeoutHandler->isTimeOut()) - { - if (!m_timeoutHandler->handleTimeOut()) - throw exceptions::operation_timed_out(); - - m_timeoutHandler->resetTimeOut(); - } - - // Receive data from the socket - string receiveBuffer; - m_socket->receive(receiveBuffer); - - if (receiveBuffer.empty()) // buffer is empty - { - platform::getHandler()->wait(); - continue; - } - - // We have received data: reset the time-out counter - if (m_timeoutHandler) - m_timeoutHandler->resetTimeOut(); - - // Check for transparent characters: '\n..' becomes '\n.' - const char first = receiveBuffer[0]; - - if (first == '.' && last2 == '\n' && last1 == '.') - { - receiveBuffer.erase(receiveBuffer.begin()); - } - else if (receiveBuffer.length() >= 2 && first == '.' && - receiveBuffer[1] == '.' && last1 == '\n') - { - receiveBuffer.erase(receiveBuffer.begin()); - } - - for (size_t trans ; - string::npos != (trans = receiveBuffer.find("\n..")) ; ) - { - receiveBuffer.replace(trans, 3, "\n."); - } - - last1 = receiveBuffer[receiveBuffer.length() - 1]; - last2 = static_cast ((receiveBuffer.length() >= 2) ? receiveBuffer[receiveBuffer.length() - 2] : 0); - - // Append the data to the response buffer - buffer += receiveBuffer; - - // Check for terminator string (and strip it if present) - foundTerminator = checkTerminator(buffer, multiLine); - - // If there is an error (-ERR) when executing a command that - // 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] == '-') - { - foundTerminator = checkTerminator(buffer, false); - } - } -} - - -void 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) - progress->start(total); - - if (m_timeoutHandler) - m_timeoutHandler->resetTimeOut(); - - utility::inputStreamSocketAdapter sis(*m_socket); - utility::stopSequenceFilteredInputStream <5> sfis1(sis, "\r\n.\r\n"); - utility::stopSequenceFilteredInputStream <3> sfis2(sfis1, "\n.\n"); - utility::dotFilteredInputStream dfis(sfis2); // "\n.." --> "\n." - - utility::inputStream& is = dfis; - - while (!is.eof()) - { -#if 0 // not supported - // Check for possible cancellation - if (progress && progress->cancel()) - throw exceptions::operation_cancelled(); -#endif - - // Check whether the time-out delay is elapsed - 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 - { - platform::getHandler()->wait(); - continue; - } - - // We have received data: reset the time-out counter - if (m_timeoutHandler) - m_timeoutHandler->resetTimeOut(); - - // Notify progress - current += read; - - if (progress) - { - total = std::max(total, current); - progress->progress(current, total); - } - - // If we don't have extracted the response code yet - if (!codeDone) - { - vmime::utility::stringUtils::appendBytesToString(temp, buffer, read); - - string responseData; - - if (stripFirstLine(temp, responseData, &firstLine) == true) - { - if (getResponseCode(firstLine) != CODE_OK) - throw exceptions::command_error("?", firstLine); - - codeDone = true; - - os.write(responseData.data(), responseData.length()); - temp.clear(); - - continue; - } - } - else - { - // Inject the data into the output stream - os.write(buffer, read); - } - } - - if (progress) - progress->stop(total); -} - - -// static -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)); - result = buffer.substr(end + 1); - return true; - } - else - { - if (firstLine) *firstLine = utility::stringUtils::trim(buffer); - result = ""; - return false; - } -} - - -// static -POP3Response::ResponseCode POP3Response::getResponseCode(const string& buffer) -{ - if (buffer.length() >= 2) - { - // +[space] - if (buffer[0] == '+' && - (buffer[1] == ' ' || buffer[1] == '\t')) - { - return CODE_READY; - } - - // +OK - if (buffer.length() >= 3) - { - if (buffer[0] == '+' && - (buffer[1] == 'O' || buffer[1] == 'o') && - (buffer[2] == 'K' || buffer[1] == 'k')) - { - return CODE_OK; - } - } - } - - // -ERR or whatever - return CODE_ERR; -} - - -// static -void POP3Response::stripResponseCode(const string& buffer, string& result) -{ - const size_t pos = buffer.find_first_of(" \t"); - - if (pos != string::npos) - result = buffer.substr(pos + 1); - else - result = buffer; -} - - -// static -bool POP3Response::checkTerminator(string& buffer, const bool multiLine) -{ - // Multi-line response - if (multiLine) - { - static const string term1("\r\n.\r\n"); - static const string term2("\n.\n"); - - return (checkOneTerminator(buffer, term1) || - checkOneTerminator(buffer, term2)); - } - // Normal response - else - { - static const string term1("\r\n"); - static const string term2("\n"); - - return (checkOneTerminator(buffer, term1) || - checkOneTerminator(buffer, term2)); - } - - return false; -} - - -// static -bool POP3Response::checkOneTerminator(string& buffer, const string& term) -{ - if (buffer.length() >= term.length() && - std::equal(buffer.end() - term.length(), buffer.end(), term.begin())) - { - buffer.erase(buffer.end() - term.length(), buffer.end()); - return true; - } - - return false; -} - - -} // pop3 -} // net -} // vmime - - -#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_POP3 diff --git a/src/net/pop3/POP3SStore.cpp b/src/net/pop3/POP3SStore.cpp deleted file mode 100644 index f1c3da74..00000000 --- a/src/net/pop3/POP3SStore.cpp +++ /dev/null @@ -1,79 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// 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 && VMIME_HAVE_MESSAGING_PROTO_POP3 - - -#include "vmime/net/pop3/POP3SStore.hpp" - - -namespace vmime { -namespace net { -namespace pop3 { - - -POP3SStore::POP3SStore(shared_ptr sess, shared_ptr auth) - : POP3Store(sess, auth, true) -{ -} - - -POP3SStore::~POP3SStore() -{ -} - - -const string POP3SStore::getProtocolName() const -{ - return "pop3s"; -} - - - -// Service infos - -POP3ServiceInfos POP3SStore::sm_infos(true); - - -const serviceInfos& POP3SStore::getInfosInstance() -{ - return sm_infos; -} - - -const serviceInfos& POP3SStore::getInfos() const -{ - return sm_infos; -} - - -} // pop3 -} // net -} // vmime - - -#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_POP3 - diff --git a/src/net/pop3/POP3ServiceInfos.cpp b/src/net/pop3/POP3ServiceInfos.cpp deleted file mode 100644 index 4760d4f2..00000000 --- a/src/net/pop3/POP3ServiceInfos.cpp +++ /dev/null @@ -1,143 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// 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 && VMIME_HAVE_MESSAGING_PROTO_POP3 - - -#include "vmime/net/pop3/POP3ServiceInfos.hpp" - - -namespace vmime { -namespace net { -namespace pop3 { - - -POP3ServiceInfos::POP3ServiceInfos(const bool pop3s) - : m_pop3s(pop3s) -{ -} - - -const string POP3ServiceInfos::getPropertyPrefix() const -{ - if (m_pop3s) - return "store.pop3s."; - else - return "store.pop3."; -} - - -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"), -#if VMIME_HAVE_SASL_SUPPORT - property("options.sasl", serviceInfos::property::TYPE_BOOLEAN, "true"), - property("options.sasl.fallback", serviceInfos::property::TYPE_BOOLEAN, "true"), -#endif // VMIME_HAVE_SASL_SUPPORT - - // Common properties - property(serviceInfos::property::AUTH_USERNAME, serviceInfos::property::FLAG_REQUIRED), - property(serviceInfos::property::AUTH_PASSWORD, serviceInfos::property::FLAG_REQUIRED), - -#if VMIME_HAVE_TLS_SUPPORT - property(serviceInfos::property::CONNECTION_TLS), - property(serviceInfos::property::CONNECTION_TLS_REQUIRED), -#endif // VMIME_HAVE_TLS_SUPPORT - - property(serviceInfos::property::SERVER_ADDRESS, serviceInfos::property::FLAG_REQUIRED), - property(serviceInfos::property::SERVER_PORT, "110"), - }; - - static props pop3sProps = - { - // POP3-specific options - property("options.apop", serviceInfos::property::TYPE_BOOLEAN, "true"), - property("options.apop.fallback", serviceInfos::property::TYPE_BOOLEAN, "true"), -#if VMIME_HAVE_SASL_SUPPORT - property("options.sasl", serviceInfos::property::TYPE_BOOLEAN, "true"), - property("options.sasl.fallback", serviceInfos::property::TYPE_BOOLEAN, "true"), -#endif // VMIME_HAVE_SASL_SUPPORT - - // Common properties - property(serviceInfos::property::AUTH_USERNAME, serviceInfos::property::FLAG_REQUIRED), - property(serviceInfos::property::AUTH_PASSWORD, serviceInfos::property::FLAG_REQUIRED), - -#if VMIME_HAVE_TLS_SUPPORT - property(serviceInfos::property::CONNECTION_TLS), - property(serviceInfos::property::CONNECTION_TLS_REQUIRED), -#endif // VMIME_HAVE_TLS_SUPPORT - - property(serviceInfos::property::SERVER_ADDRESS, serviceInfos::property::FLAG_REQUIRED), - property(serviceInfos::property::SERVER_PORT, "995"), - }; - - return m_pop3s ? pop3sProps : pop3Props; -} - - -const std::vector POP3ServiceInfos::getAvailableProperties() const -{ - std::vector list; - const props& p = getProperties(); - - // POP3-specific options - list.push_back(p.PROPERTY_OPTIONS_APOP); - list.push_back(p.PROPERTY_OPTIONS_APOP_FALLBACK); -#if VMIME_HAVE_SASL_SUPPORT - list.push_back(p.PROPERTY_OPTIONS_SASL); - list.push_back(p.PROPERTY_OPTIONS_SASL_FALLBACK); -#endif // VMIME_HAVE_SASL_SUPPORT - - // Common properties - list.push_back(p.PROPERTY_AUTH_USERNAME); - list.push_back(p.PROPERTY_AUTH_PASSWORD); - -#if VMIME_HAVE_TLS_SUPPORT - if (!m_pop3s) - { - list.push_back(p.PROPERTY_CONNECTION_TLS); - list.push_back(p.PROPERTY_CONNECTION_TLS_REQUIRED); - } -#endif // VMIME_HAVE_TLS_SUPPORT - - list.push_back(p.PROPERTY_SERVER_ADDRESS); - list.push_back(p.PROPERTY_SERVER_PORT); - - return list; -} - - -} // pop3 -} // net -} // vmime - - -#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_POP3 - diff --git a/src/net/pop3/POP3Store.cpp b/src/net/pop3/POP3Store.cpp deleted file mode 100644 index e6e95b1b..00000000 --- a/src/net/pop3/POP3Store.cpp +++ /dev/null @@ -1,240 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// 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 && VMIME_HAVE_MESSAGING_PROTO_POP3 - - -#include "vmime/net/pop3/POP3Store.hpp" -#include "vmime/net/pop3/POP3Folder.hpp" -#include "vmime/net/pop3/POP3Command.hpp" -#include "vmime/net/pop3/POP3Response.hpp" - -#include "vmime/exception.hpp" - -#include - - -namespace vmime { -namespace net { -namespace pop3 { - - -POP3Store::POP3Store(shared_ptr sess, shared_ptr auth, const bool secured) - : store(sess, getInfosInstance(), auth), m_isPOP3S(secured) -{ -} - - -POP3Store::~POP3Store() -{ - try - { - if (isConnected()) - disconnect(); - } - catch (vmime::exception&) - { - // Ignore - } -} - - -const string POP3Store::getProtocolName() const -{ - return "pop3"; -} - - -shared_ptr POP3Store::getDefaultFolder() -{ - if (!isConnected()) - throw exceptions::illegal_state("Not connected"); - - return make_shared - (folder::path(folder::path::component("INBOX")), - dynamicCast (shared_from_this())); -} - - -shared_ptr POP3Store::getRootFolder() -{ - if (!isConnected()) - throw exceptions::illegal_state("Not connected"); - - return make_shared - (folder::path(), dynamicCast (shared_from_this())); -} - - -shared_ptr POP3Store::getFolder(const folder::path& path) -{ - if (!isConnected()) - throw exceptions::illegal_state("Not connected"); - - return make_shared - (path, dynamicCast (shared_from_this())); -} - - -bool POP3Store::isValidFolderName(const folder::path::component& /* name */) const -{ - return true; -} - - -void POP3Store::connect() -{ - if (isConnected()) - throw exceptions::already_connected(); - - m_connection = make_shared - (dynamicCast (shared_from_this()), getAuthenticator()); - - try - { - m_connection->connect(); - } - catch (std::exception&) - { - m_connection = null; - throw; - } -} - - -bool POP3Store::isPOP3S() const -{ - return m_isPOP3S; -} - - -bool POP3Store::isConnected() const -{ - return m_connection && m_connection->isConnected(); -} - - -bool POP3Store::isSecuredConnection() const -{ - if (m_connection == NULL) - return false; - - return m_connection->isSecuredConnection(); -} - - -shared_ptr POP3Store::getConnectionInfos() const -{ - if (m_connection == NULL) - return null; - - return m_connection->getConnectionInfos(); -} - - -shared_ptr POP3Store::getConnection() -{ - return m_connection; -} - - -void POP3Store::disconnect() -{ - if (!isConnected()) - throw exceptions::not_connected(); - - for (std::list ::iterator it = m_folders.begin() ; - it != m_folders.end() ; ++it) - { - (*it)->onStoreDisconnected(); - } - - m_folders.clear(); - - - m_connection->disconnect(); - m_connection = null; -} - - -void POP3Store::noop() -{ - if (!m_connection) - throw exceptions::not_connected(); - - POP3Command::NOOP()->send(m_connection); - - shared_ptr response = POP3Response::readResponse(m_connection); - - if (!response->isSuccess()) - throw exceptions::command_error("NOOP", response->getFirstLine()); -} - - -void POP3Store::registerFolder(POP3Folder* folder) -{ - m_folders.push_back(folder); -} - - -void POP3Store::unregisterFolder(POP3Folder* folder) -{ - std::list ::iterator it = std::find(m_folders.begin(), m_folders.end(), folder); - if (it != m_folders.end()) m_folders.erase(it); -} - - -int POP3Store::getCapabilities() const -{ - return (CAPABILITY_DELETE_MESSAGE); -} - - - -// Service infos - -POP3ServiceInfos POP3Store::sm_infos(false); - - -const serviceInfos& POP3Store::getInfosInstance() -{ - return sm_infos; -} - - -const serviceInfos& POP3Store::getInfos() const -{ - return sm_infos; -} - - -} // pop3 -} // net -} // vmime - - -#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_POP3 - diff --git a/src/net/pop3/POP3Utils.cpp b/src/net/pop3/POP3Utils.cpp deleted file mode 100644 index 7ba65fff..00000000 --- a/src/net/pop3/POP3Utils.cpp +++ /dev/null @@ -1,114 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// 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 && VMIME_HAVE_MESSAGING_PROTO_POP3 - - -#include "vmime/net/pop3/POP3Utils.hpp" -#include "vmime/net/pop3/POP3Response.hpp" - -#include - - -namespace vmime { -namespace net { -namespace pop3 { - - -// static -void POP3Utils::parseMultiListOrUidlResponse(shared_ptr response, std::map & result) -{ - std::map ids; - - 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')) - ++it; - - if (it != line.end()) - { - int number = 0; - - while (it != line.end() && (*it >= '0' && *it <= '9')) - { - number = (number * 10) + (*it - '0'); - ++it; - } - - while (it != line.end() && !(*it == ' ' || *it == '\t')) ++it; - while (it != line.end() && (*it == ' ' || *it == '\t')) ++it; - - if (it != line.end()) - { - result.insert(std::map ::value_type(number, string(it, line.end()))); - } - } - } -} - - - -class POP3MessageSetEnumerator : public messageSetEnumerator -{ -public: - - void enumerateNumberMessageRange(const vmime::net::numberMessageRange& range) - { - for (int i = range.getFirst(), last = range.getLast() ; i <= last ; ++i) - list.push_back(i); - } - - void enumerateUIDMessageRange(const vmime::net::UIDMessageRange& /* range */) - { - // Not supported - } - -public: - - std::vector list; -}; - - -// static -const std::vector POP3Utils::messageSetToNumberList(const messageSet& msgs) -{ - POP3MessageSetEnumerator en; - msgs.enumerate(en); - - return en.list; -} - - -} // pop3 -} // net -} // vmime - - -#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_POP3 - diff --git a/src/net/sendmail/sendmailServiceInfos.cpp b/src/net/sendmail/sendmailServiceInfos.cpp deleted file mode 100644 index 21cac00c..00000000 --- a/src/net/sendmail/sendmailServiceInfos.cpp +++ /dev/null @@ -1,78 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// 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 && VMIME_HAVE_MESSAGING_PROTO_SENDMAIL - - -#include "vmime/net/sendmail/sendmailServiceInfos.hpp" - - -namespace vmime { -namespace net { -namespace sendmail { - - -sendmailServiceInfos::sendmailServiceInfos() -{ -} - - -const string sendmailServiceInfos::getPropertyPrefix() const -{ - return "transport.sendmail."; -} - - -const sendmailServiceInfos::props& sendmailServiceInfos::getProperties() const -{ - static props sendmailProps = - { - // Path to sendmail (override default) - property("binpath", serviceInfos::property::TYPE_STRING, string(VMIME_SENDMAIL_PATH)) - }; - - return sendmailProps; -} - - -const std::vector sendmailServiceInfos::getAvailableProperties() const -{ - std::vector list; - const props& p = getProperties(); - - list.push_back(p.PROPERTY_BINPATH); - - return list; -} - - -} // sendmail -} // net -} // vmime - - -#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_SENDMAIL - diff --git a/src/net/sendmail/sendmailTransport.cpp b/src/net/sendmail/sendmailTransport.cpp deleted file mode 100644 index 8ef18e3b..00000000 --- a/src/net/sendmail/sendmailTransport.cpp +++ /dev/null @@ -1,230 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// 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 && VMIME_HAVE_MESSAGING_PROTO_SENDMAIL - - -#include "vmime/net/sendmail/sendmailTransport.hpp" - -#include "vmime/exception.hpp" -#include "vmime/platform.hpp" -#include "vmime/message.hpp" -#include "vmime/mailboxList.hpp" - -#include "vmime/utility/filteredStream.hpp" -#include "vmime/utility/childProcess.hpp" - -#include "vmime/utility/streamUtils.hpp" - -#include "vmime/net/defaultConnectionInfos.hpp" - -#include "vmime/config.hpp" - - -// Helpers for service properties -#define GET_PROPERTY(type, prop) \ - (getInfos().getPropertyValue (getSession(), \ - dynamic_cast (getInfos()).getProperties().prop)) -#define HAS_PROPERTY(prop) \ - (getInfos().hasProperty(getSession(), \ - dynamic_cast (getInfos()).getProperties().prop)) - - -namespace vmime { -namespace net { -namespace sendmail { - - -sendmailTransport::sendmailTransport(shared_ptr sess, shared_ptr auth) - : transport(sess, getInfosInstance(), auth), m_connected(false) -{ -} - - -sendmailTransport::~sendmailTransport() -{ - try - { - if (isConnected()) - disconnect(); - } - catch (vmime::exception&) - { - // Ignore - } -} - - -const string sendmailTransport::getProtocolName() const -{ - return "sendmail"; -} - - -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); - - m_connected = true; -} - - -bool sendmailTransport::isConnected() const -{ - return (m_connected); -} - - -bool sendmailTransport::isSecuredConnection() const -{ - return false; -} - - -shared_ptr sendmailTransport::getConnectionInfos() const -{ - return make_shared ("localhost", static_cast (0)); -} - - -void sendmailTransport::disconnect() -{ - if (!isConnected()) - throw exceptions::not_connected(); - - internalDisconnect(); -} - - -void sendmailTransport::internalDisconnect() -{ - m_connected = false; -} - - -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) -{ - // If no recipient/expeditor was found, throw an exception - if (recipients.isEmpty()) - throw exceptions::no_recipient(); - else if (expeditor.isEmpty()) - throw exceptions::no_expeditor(); - - // Construct the argument list - std::vector args; - - args.push_back("-i"); - args.push_back("-f"); - - if (!sender.isEmpty()) - args.push_back(expeditor.getEmail().generate()); - else - args.push_back(sender.getEmail().generate()); - - args.push_back("--"); - - for (size_t i = 0 ; i < recipients.getMailboxCount() ; ++i) - args.push_back(recipients.getMailboxAt(i)->getEmail().generate()); - - // Call sendmail - try - { - internalSend(args, is, size, progress); - } - catch (vmime::exception& e) - { - throw exceptions::command_error("SEND", "", "sendmail failed", e); - } -} - - -void sendmailTransport::internalSend - (const std::vector 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 proc = - vmime::platform::getHandler()-> - getChildProcessFactory()->create(path); - - proc->start(args, utility::childProcess::FLAG_REDIRECT_STDIN); - - // Copy message data from input stream to output pipe - utility::outputStream& os = *(proc->getStdIn()); - - // Workaround for lame sendmail implementations that - // can't handle CRLF eoln sequences: we transform CRLF - // sequences into LF characters. - utility::CRLFToLFFilteredOutputStream fos(os); - - // TODO: remove 'Bcc:' field from message header - - utility::bufferedStreamCopy(is, fos, size, progress); - - // Wait for sendmail to exit - proc->waitForFinish(); -} - - -// Service infos - -sendmailServiceInfos sendmailTransport::sm_infos; - - -const serviceInfos& sendmailTransport::getInfosInstance() -{ - return sm_infos; -} - - -const serviceInfos& sendmailTransport::getInfos() const -{ - return sm_infos; -} - - -} // sendmail -} // net -} // vmime - - -#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_SENDMAIL - diff --git a/src/net/service.cpp b/src/net/service.cpp deleted file mode 100644 index c52ba592..00000000 --- a/src/net/service.cpp +++ /dev/null @@ -1,152 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// 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/service.hpp" - -#include "vmime/platform.hpp" - -#if VMIME_HAVE_SASL_SUPPORT - #include "vmime/security/sasl/defaultSASLAuthenticator.hpp" -#else - #include "vmime/security/defaultAuthenticator.hpp" -#endif // VMIME_HAVE_SASL_SUPPORT - -#if VMIME_HAVE_TLS_SUPPORT - #include "vmime/security/cert/defaultCertificateVerifier.hpp" -#endif // VMIME_HAVE_TLS_SUPPORT - - -namespace vmime { -namespace net { - - -service::service(shared_ptr sess, const serviceInfos& /* infos */, - shared_ptr auth) - : m_session(sess), m_auth(auth) -{ - if (!auth) - { -#if VMIME_HAVE_SASL_SUPPORT - m_auth = make_shared - (); -#else - m_auth = make_shared - (); -#endif // VMIME_HAVE_SASL_SUPPORT - } - -#if VMIME_HAVE_TLS_SUPPORT - m_certVerifier = make_shared (); -#endif // VMIME_HAVE_TLS_SUPPORT - - m_socketFactory = platform::getHandler()->getSocketFactory(); -} - - -service::~service() -{ -} - - -shared_ptr service::getSession() const -{ - return (m_session); -} - - -shared_ptr service::getSession() -{ - return (m_session); -} - - -shared_ptr service::getAuthenticator() const -{ - return (m_auth); -} - - -shared_ptr service::getAuthenticator() -{ - return (m_auth); -} - - -void service::setAuthenticator(shared_ptr auth) -{ - m_auth = auth; -} - - -#if VMIME_HAVE_TLS_SUPPORT - -void service::setCertificateVerifier(shared_ptr cv) -{ - m_certVerifier = cv; -} - - -shared_ptr service::getCertificateVerifier() -{ - return m_certVerifier; -} - -#endif // VMIME_HAVE_TLS_SUPPORT - - -void service::setSocketFactory(shared_ptr sf) -{ - m_socketFactory = sf; -} - - -shared_ptr service::getSocketFactory() -{ - return m_socketFactory; -} - - -void service::setTimeoutHandlerFactory(shared_ptr thf) -{ - m_toHandlerFactory = thf; -} - - -shared_ptr service::getTimeoutHandlerFactory() -{ - return m_toHandlerFactory; -} - - -} // net -} // vmime - - -#endif // VMIME_HAVE_MESSAGING_FEATURES - diff --git a/src/net/serviceFactory.cpp b/src/net/serviceFactory.cpp deleted file mode 100644 index 98aee646..00000000 --- a/src/net/serviceFactory.cpp +++ /dev/null @@ -1,145 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// 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/serviceFactory.hpp" -#include "vmime/net/service.hpp" - -#include "vmime/exception.hpp" - -#include "src/net/builtinServices.inl" - - -namespace vmime { -namespace net { - - -serviceFactory::serviceFactory() -{ -} - - -serviceFactory::~serviceFactory() -{ -} - - -shared_ptr serviceFactory::getInstance() -{ - static serviceFactory instance; - return shared_ptr (&instance, noop_shared_ptr_deleter ()); -} - - -shared_ptr serviceFactory::create - (shared_ptr sess, const string& protocol, - shared_ptr auth) -{ - return (getServiceByProtocol(protocol)->create(sess, auth)); -} - - -shared_ptr serviceFactory::create - (shared_ptr sess, const utility::url& u, - shared_ptr auth) -{ - shared_ptr serv = create(sess, u.getProtocol(), auth); - - sess->getProperties()[serv->getInfos().getPropertyPrefix() + "server.address"] = u.getHost(); - - 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()) - sess->getProperties()[serv->getInfos().getPropertyPrefix() + "server.rootpath"] = u.getPath(); - - if (!u.getUsername().empty()) - { - sess->getProperties()[serv->getInfos().getPropertyPrefix() + "auth.username"] = u.getUsername(); - sess->getProperties()[serv->getInfos().getPropertyPrefix() + "auth.password"] = u.getPassword(); - } - - return (serv); -} - - -shared_ptr serviceFactory::getServiceByProtocol(const string& protocol) const -{ - const string name(utility::stringUtils::toLower(protocol)); - - for (std::vector >::const_iterator it = m_services.begin() ; - it != m_services.end() ; ++it) - { - if ((*it)->getName() == name) - return (*it); - } - - return null; -} - - -size_t serviceFactory::getServiceCount() const -{ - return (m_services.size()); -} - - -shared_ptr serviceFactory::getServiceAt(const size_t pos) const -{ - return (m_services[pos]); -} - - -const std::vector > serviceFactory::getServiceList() const -{ - std::vector > res; - - for (std::vector >::const_iterator it = m_services.begin() ; - it != m_services.end() ; ++it) - { - res.push_back(*it); - } - - return (res); -} - - -void serviceFactory::registerService(shared_ptr reg) -{ - m_services.push_back(reg); -} - - -} // net -} // vmime - - -#endif // VMIME_HAVE_MESSAGING_FEATURES - diff --git a/src/net/serviceInfos.cpp b/src/net/serviceInfos.cpp deleted file mode 100644 index 8de0529e..00000000 --- a/src/net/serviceInfos.cpp +++ /dev/null @@ -1,167 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// 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/serviceInfos.hpp" - - -namespace vmime { -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); - -#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_REQUIRED - ("connection.tls.required", serviceInfos::property::TYPE_BOOLEAN, "false"); - -#endif // VMIME_HAVE_TLS_SUPPORT - - - -// serviceInfos - -serviceInfos::serviceInfos() -{ -} - - -serviceInfos::serviceInfos(const serviceInfos&) -{ -} - - -serviceInfos& serviceInfos::operator=(const serviceInfos&) -{ - return (*this); -} - - -serviceInfos::~serviceInfos() -{ -} - - -bool serviceInfos::hasProperty(shared_ptr s, const property& p) const -{ - return s->getProperties().hasProperty(getPropertyPrefix() + p.getName()); -} - - - -// 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 property& p, const int addFlags, const int removeFlags) -{ - m_name = p.m_name; - m_type = p.m_type; - m_defaultValue = p.m_defaultValue; - m_flags = (p.m_flags | addFlags) & ~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; - m_flags = (p.m_flags | addFlags) & ~removeFlags; -} - - -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); -} - - -const string& serviceInfos::property::getName() const -{ - return (m_name); -} - - -const string& serviceInfos::property::getDefaultValue() const -{ - return (m_defaultValue); -} - - -serviceInfos::property::Types serviceInfos::property::getType() const -{ - return (m_type); -} - - -int serviceInfos::property::getFlags() const -{ - return (m_flags); -} - - -} // net -} // vmime - - -#endif // VMIME_HAVE_MESSAGING_FEATURES - diff --git a/src/net/serviceRegistration.inl b/src/net/serviceRegistration.inl deleted file mode 100644 index 2366fe01..00000000 --- a/src/net/serviceRegistration.inl +++ /dev/null @@ -1,98 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// 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/net/serviceFactory.hpp" - - -#ifndef VMIME_BUILDING_DOC - - -namespace vmime { -namespace net { - - -template -class registeredServiceImpl : public serviceFactory::registeredService -{ -public: - - registeredServiceImpl(const string& name, const int type) - : m_type(type), m_name(name), m_servInfos(S::getInfosInstance()) - { - } - - shared_ptr create - (shared_ptr sess, - shared_ptr auth) const - { - return make_shared (sess, auth); - } - - const serviceInfos& getInfos() const - { - return (m_servInfos); - } - - const string& getName() const - { - return (m_name); - } - - int getType() const - { - return (m_type); - } - -private: - - const int m_type; - const string m_name; - const serviceInfos& m_servInfos; -}; - - -// Basic service registerer -template -class serviceRegisterer -{ -public: - - serviceRegisterer(const string& protocol, const service::Type type) - { - serviceFactory::getInstance()->registerService - (make_shared >(protocol, type)); - } -}; - - -} // net -} // vmime - - -#define REGISTER_SERVICE(p_class, p_name, p_type) \ - vmime::net::serviceRegisterer \ - p_name(#p_name, vmime::net::service::p_type) - - -#endif // VMIME_BUILDING_DOC - diff --git a/src/net/session.cpp b/src/net/session.cpp deleted file mode 100644 index 36b9f2c3..00000000 --- a/src/net/session.cpp +++ /dev/null @@ -1,158 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// 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/session.hpp" -#include "vmime/net/serviceFactory.hpp" - -#include "vmime/net/store.hpp" -#include "vmime/net/transport.hpp" - - -namespace vmime { -namespace net { - - -session::session() - : m_tlsProps(make_shared ()) -{ -} - - -session::session(const session& sess) - : object(), m_props(sess.m_props), - m_tlsProps(make_shared (*sess.m_tlsProps)) -{ -} - - -session::session(const propertySet& props) - : m_props(props), m_tlsProps(make_shared ()) -{ -} - - -session::~session() -{ -} - - -shared_ptr session::getTransport(shared_ptr auth) -{ - return (getTransport(m_props["transport.protocol"], auth)); -} - - -shared_ptr session::getTransport - (const string& protocol, shared_ptr auth) -{ - shared_ptr sess(dynamicCast (shared_from_this())); - shared_ptr sv = serviceFactory::getInstance()->create(sess, protocol, auth); - - if (!sv || sv->getType() != service::TYPE_TRANSPORT) - return null; - - return dynamicCast (sv); -} - - -shared_ptr session::getTransport - (const utility::url& url, shared_ptr auth) -{ - shared_ptr sess(dynamicCast (shared_from_this())); - shared_ptr sv = serviceFactory::getInstance()->create(sess, url, auth); - - if (!sv || sv->getType() != service::TYPE_TRANSPORT) - return null; - - return dynamicCast (sv); -} - - -shared_ptr session::getStore(shared_ptr auth) -{ - return (getStore(m_props["store.protocol"], auth)); -} - - -shared_ptr session::getStore - (const string& protocol, shared_ptr auth) -{ - shared_ptr sess(dynamicCast (shared_from_this())); - shared_ptr sv = serviceFactory::getInstance()->create(sess, protocol, auth); - - if (!sv || sv->getType() != service::TYPE_STORE) - return null; - - return dynamicCast (sv); -} - - -shared_ptr session::getStore - (const utility::url& url, shared_ptr auth) -{ - shared_ptr sess(dynamicCast (shared_from_this())); - shared_ptr sv = serviceFactory::getInstance()->create(sess, url, auth); - - if (!sv || sv->getType() != service::TYPE_STORE) - return null; - - return dynamicCast (sv); -} - - -const propertySet& session::getProperties() const -{ - return (m_props); -} - - -propertySet& session::getProperties() -{ - return (m_props); -} - - -void session::setTLSProperties(shared_ptr tlsProps) -{ - m_tlsProps = make_shared (*tlsProps); -} - - -shared_ptr session::getTLSProperties() const -{ - return m_tlsProps; -} - - -} // net -} // vmime - - -#endif // VMIME_HAVE_MESSAGING_FEATURES - diff --git a/src/net/smtp/SMTPChunkingOutputStreamAdapter.cpp b/src/net/smtp/SMTPChunkingOutputStreamAdapter.cpp deleted file mode 100644 index 69f63bc9..00000000 --- a/src/net/smtp/SMTPChunkingOutputStreamAdapter.cpp +++ /dev/null @@ -1,145 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// 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 && VMIME_HAVE_MESSAGING_PROTO_SMTP - - -#include "vmime/net/smtp/SMTPChunkingOutputStreamAdapter.hpp" - -#include "vmime/net/smtp/SMTPConnection.hpp" -#include "vmime/net/smtp/SMTPTransport.hpp" - -#include - - -namespace vmime { -namespace net { -namespace smtp { - - -SMTPChunkingOutputStreamAdapter::SMTPChunkingOutputStreamAdapter(shared_ptr conn) - : m_connection(conn), m_bufferSize(0), m_chunkCount(0) -{ -} - - -void SMTPChunkingOutputStreamAdapter::sendChunk - (const byte_t* const data, const size_t count, const bool last) -{ - if (count == 0 && !last) - { - // Nothing to send - return; - } - - // Send this chunk - m_connection->sendRequest(SMTPCommand::BDAT(count, last)); - m_connection->getSocket()->sendRaw(data, count); - - ++m_chunkCount; - - // If PIPELINING is not supported, read one response for this BDAT command - if (!m_connection->hasExtension("PIPELINING")) - { - shared_ptr resp = m_connection->readResponse(); - - 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) - { - bool invalidReply = false; - shared_ptr resp; - - for (unsigned int i = 0 ; i < m_chunkCount ; ++i) - { - resp = m_connection->readResponse(); - - if (resp->getCode() != 250) - invalidReply = true; - } - - if (invalidReply) - { - m_connection->getTransport()->disconnect(); - throw exceptions::command_error("BDAT", resp->getText()); - } - } -} - - -void SMTPChunkingOutputStreamAdapter::writeImpl - (const byte_t* const data, const size_t count) -{ - const byte_t* curData = data; - size_t curCount = count; - - while (curCount != 0) - { - // Fill the buffer - const size_t remaining = sizeof(m_buffer) - m_bufferSize; - const size_t bytesToCopy = std::min(remaining, curCount); - - std::copy(data, data + bytesToCopy, m_buffer + m_bufferSize); - - m_bufferSize += bytesToCopy; - curData += bytesToCopy; - curCount -= bytesToCopy; - - // If the buffer is full, send this chunk - if (m_bufferSize >= sizeof(m_buffer)) - { - sendChunk(m_buffer, m_bufferSize, /* last */ false); - m_bufferSize = 0; - } - } -} - - -void SMTPChunkingOutputStreamAdapter::flush() -{ - sendChunk(m_buffer, m_bufferSize, /* last */ true); - m_bufferSize = 0; -} - - -size_t SMTPChunkingOutputStreamAdapter::getBlockSize() -{ - return sizeof(m_buffer); -} - - -} // smtp -} // net -} // vmime - - -#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_SMTP diff --git a/src/net/smtp/SMTPCommand.cpp b/src/net/smtp/SMTPCommand.cpp deleted file mode 100644 index 949ab0c1..00000000 --- a/src/net/smtp/SMTPCommand.cpp +++ /dev/null @@ -1,214 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// 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 && VMIME_HAVE_MESSAGING_PROTO_SMTP - - -#include "vmime/net/smtp/SMTPCommand.hpp" - -#include "vmime/net/socket.hpp" - -#include "vmime/mailbox.hpp" -#include "vmime/utility/outputStreamAdapter.hpp" - - -namespace vmime { -namespace net { -namespace smtp { - - -SMTPCommand::SMTPCommand(const string& text) - : m_text(text) -{ -} - - -// static -shared_ptr SMTPCommand::EHLO(const string& hostname) -{ - std::ostringstream cmd; - cmd.imbue(std::locale::classic()); - cmd << "EHLO " << hostname; - - return createCommand(cmd.str()); -} - - -// static -shared_ptr SMTPCommand::HELO(const string& hostname) -{ - std::ostringstream cmd; - cmd.imbue(std::locale::classic()); - cmd << "HELO " << hostname; - - return createCommand(cmd.str()); -} - - -// static -shared_ptr SMTPCommand::AUTH(const string& mechName) -{ - std::ostringstream cmd; - cmd.imbue(std::locale::classic()); - cmd << "AUTH " << mechName; - - return createCommand(cmd.str()); -} - - -// static -shared_ptr SMTPCommand::STARTTLS() -{ - return createCommand("STARTTLS"); -} - - -// static -shared_ptr SMTPCommand::MAIL(const mailbox& mbox, const bool utf8) -{ - return MAIL(mbox, utf8, 0); -} - - -// static -shared_ptr 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) - { - cmd << mbox.getEmail().toText().getConvertedText(vmime::charsets::UTF_8); - } - else - { - vmime::utility::outputStreamAdapter cmd2(cmd); - mbox.getEmail().generate(cmd2); - } - - cmd << ">"; - - if (utf8) - cmd << " SMTPUTF8"; - - if (size != 0) - cmd << " SIZE=" << size; - - return createCommand(cmd.str()); -} - - -// static -shared_ptr SMTPCommand::RCPT(const mailbox& mbox, const bool utf8) -{ - std::ostringstream cmd; - cmd.imbue(std::locale::classic()); - cmd << "RCPT TO:<"; - - if (utf8) - { - cmd << mbox.getEmail().toText().getConvertedText(vmime::charsets::UTF_8); - } - else - { - vmime::utility::outputStreamAdapter cmd2(cmd); - mbox.getEmail().generate(cmd2); - } - - cmd << ">"; - - return createCommand(cmd.str()); -} - - -// static -shared_ptr SMTPCommand::RSET() -{ - return createCommand("RSET"); -} - - -// static -shared_ptr SMTPCommand::DATA() -{ - return createCommand("DATA"); -} - - -// static -shared_ptr SMTPCommand::BDAT(const size_t chunkSize, const bool last) -{ - std::ostringstream cmd; - cmd.imbue(std::locale::classic()); - cmd << "BDAT " << chunkSize; - - if (last) - cmd << " LAST"; - - return createCommand(cmd.str()); -} - - -// static -shared_ptr SMTPCommand::NOOP() -{ - return createCommand("NOOP"); -} - - -// static -shared_ptr SMTPCommand::QUIT() -{ - return createCommand("QUIT"); -} - - -// static -shared_ptr SMTPCommand::createCommand(const string& text) -{ - return shared_ptr (new SMTPCommand(text)); -} - - -const string SMTPCommand::getText() const -{ - return m_text; -} - - -void SMTPCommand::writeToSocket(shared_ptr sok) -{ - sok->send(m_text + "\r\n"); -} - - -} // smtp -} // net -} // vmime - - -#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_SMTP diff --git a/src/net/smtp/SMTPCommandSet.cpp b/src/net/smtp/SMTPCommandSet.cpp deleted file mode 100644 index 3e03427c..00000000 --- a/src/net/smtp/SMTPCommandSet.cpp +++ /dev/null @@ -1,144 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// 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 && VMIME_HAVE_MESSAGING_PROTO_SMTP - - -#include "vmime/net/smtp/SMTPCommandSet.hpp" - -#include "vmime/net/socket.hpp" - -#include "vmime/mailbox.hpp" - -#include - - -namespace vmime { -namespace net { -namespace smtp { - - -SMTPCommandSet::SMTPCommandSet(const bool pipeline) - : SMTPCommand(""), m_pipeline(pipeline), - m_started(false), m_lastCommandSent() -{ -} - - -// static -shared_ptr SMTPCommandSet::create(const bool pipeline) -{ - return shared_ptr (new SMTPCommandSet(pipeline)); -} - - -void SMTPCommandSet::addCommand(shared_ptr 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."); - } - - m_commands.push_back(cmd); -} - - -void SMTPCommandSet::writeToSocket(shared_ptr sok) -{ - if (m_pipeline) - { - if (!m_started) - { - // Send all commands at once - for (std::list >::const_iterator it = m_commands.begin() ; - it != m_commands.end() ; ++it) - { - shared_ptr cmd = *it; - cmd->writeToSocket(sok); - } - } - - if (!m_commands.empty()) - { - // Advance the pointer to last command sent - shared_ptr cmd = m_commands.front(); - m_commands.pop_front(); - - m_lastCommandSent = cmd; - } - } - else - { - if (!m_commands.empty()) - { - // Send only one command - shared_ptr cmd = m_commands.front(); - m_commands.pop_front(); - - cmd->writeToSocket(sok); - - m_lastCommandSent = cmd; - } - } - - m_started = true; -} - - -const string SMTPCommandSet::getText() const -{ - std::ostringstream cmd; - cmd.imbue(std::locale::classic()); - - for (std::list >::const_iterator it = m_commands.begin() ; - it != m_commands.end() ; ++it) - { - cmd << (*it)->getText() << "\r\n"; - } - - return cmd.str(); -} - - -bool SMTPCommandSet::isFinished() const -{ - return (m_pipeline && m_started) || (m_commands.size() == 0 && m_started); -} - - -shared_ptr SMTPCommandSet::getLastCommandSent() const -{ - return m_lastCommandSent; -} - - -} // smtp -} // net -} // vmime - - -#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_SMTP diff --git a/src/net/smtp/SMTPConnection.cpp b/src/net/smtp/SMTPConnection.cpp deleted file mode 100644 index 26be25db..00000000 --- a/src/net/smtp/SMTPConnection.cpp +++ /dev/null @@ -1,618 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// 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 && VMIME_HAVE_MESSAGING_PROTO_SMTP - - -#include "vmime/net/smtp/SMTPConnection.hpp" -#include "vmime/net/smtp/SMTPTransport.hpp" -#include "vmime/net/smtp/SMTPExceptions.hpp" - -#include "vmime/exception.hpp" -#include "vmime/platform.hpp" - -#include "vmime/security/digest/messageDigestFactory.hpp" - -#include "vmime/net/defaultConnectionInfos.hpp" - -#if VMIME_HAVE_SASL_SUPPORT - #include "vmime/security/sasl/SASLContext.hpp" -#endif // VMIME_HAVE_SASL_SUPPORT - -#if VMIME_HAVE_TLS_SUPPORT - #include "vmime/net/tls/TLSSession.hpp" - #include "vmime/net/tls/TLSSecuredConnectionInfos.hpp" -#endif // VMIME_HAVE_TLS_SUPPORT - - - -// Helpers for service properties -#define GET_PROPERTY(type, prop) \ - (m_transport.lock()->getInfos().getPropertyValue (getSession(), \ - dynamic_cast (m_transport.lock()->getInfos()).getProperties().prop)) -#define HAS_PROPERTY(prop) \ - (m_transport.lock()->getInfos().hasProperty(getSession(), \ - dynamic_cast (m_transport.lock()->getInfos()).getProperties().prop)) - - -namespace vmime { -namespace net { -namespace smtp { - - - -SMTPConnection::SMTPConnection(shared_ptr transport, shared_ptr auth) - : m_transport(transport), m_auth(auth), m_socket(null), m_timeoutHandler(null), - m_authenticated(false), m_secured(false), m_extendedSMTP(false) -{ -} - - -SMTPConnection::~SMTPConnection() -{ - try - { - if (isConnected()) - disconnect(); - else if (m_socket) - internalDisconnect(); - } - catch (vmime::exception&) - { - // Ignore - } -} - - -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); - - shared_ptr transport = m_transport.lock(); - - // Create the time-out handler - if (transport->getTimeoutHandlerFactory()) - m_timeoutHandler = transport->getTimeoutHandlerFactory()->create(); - - // Create and connect the socket - m_socket = transport->getSocketFactory()->create(m_timeoutHandler); - -#if VMIME_HAVE_TLS_SUPPORT - if (transport->isSMTPS()) // dedicated port/SMTPS - { - shared_ptr tlsSession = tls::TLSSession::create - (transport->getCertificateVerifier(), - transport->getSession()->getTLSProperties()); - - shared_ptr tlsSocket = - tlsSession->getSocket(m_socket); - - m_socket = tlsSocket; - - m_secured = true; - m_cntInfos = make_shared (address, port, tlsSession, tlsSocket); - } - else -#endif // VMIME_HAVE_TLS_SUPPORT - { - m_cntInfos = make_shared (address, port); - } - - m_socket->connect(address, port); - - // Connection - // - // eg: C: - // --- S: 220 smtp.domain.com Service ready - - shared_ptr resp; - - if ((resp = readResponse())->getCode() != 220) - { - internalDisconnect(); - throw exceptions::connection_greeting_error(resp->getText()); - } - - // Identification - helo(); - -#if VMIME_HAVE_TLS_SUPPORT - // Setup secured connection, if requested - const bool tls = HAS_PROPERTY(PROPERTY_CONNECTION_TLS) - && GET_PROPERTY(bool, PROPERTY_CONNECTION_TLS); - 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 - { - startTLS(); - } - // Non-fatal error - catch (exceptions::command_error&) - { - if (tlsRequired) - { - throw; - } - else - { - // TLS is not required, so don't bother - } - } - // Fatal error - catch (...) - { - throw; - } - - // Must reissue a EHLO command [RFC-2487, 5.2] - helo(); - } -#endif // VMIME_HAVE_TLS_SUPPORT - - // Authentication - if (GET_PROPERTY(bool, PROPERTY_OPTIONS_NEEDAUTH)) - authenticate(); - else - m_authenticated = true; -} - - -void SMTPConnection::helo() -{ - // First, try Extended SMTP (ESMTP) - // - // eg: C: EHLO thismachine.ourdomain.com - // S: 250-smtp.theserver.com - // S: 250-AUTH CRAM-MD5 DIGEST-MD5 - // S: 250-PIPELINING - // S: 250 SIZE 2555555555 - - sendRequest(SMTPCommand::EHLO(platform::getHandler()->getHostName())); - - shared_ptr resp; - - if ((resp = readResponse())->getCode() != 250) - { - // Next, try "Basic" SMTP - // - // eg: C: HELO thismachine.ourdomain.com - // S: 250 OK - - sendRequest(SMTPCommand::HELO(platform::getHandler()->getHostName())); - - if ((resp = readResponse())->getCode() != 250) - { - internalDisconnect(); - throw exceptions::connection_greeting_error(resp->getLastLine().getText()); - } - - m_extendedSMTP = false; - m_extensions.clear(); - } - 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) - { - const string line = resp->getLineAt(i).getText(); - std::istringstream iss(line); - - string ext; - iss >> ext; - - std::vector params; - string param; - - // Special case: some servers send "AUTH=MECH [MECH MECH...]" - 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) - params.push_back(utility::stringUtils::toUpper(param)); - - m_extensions[ext] = params; - } - } -} - - -bool SMTPConnection::hasExtension - (const std::string& extName, std::vector * params) const -{ - std::map >::const_iterator - it = m_extensions.find(extName); - - if (it != m_extensions.end()) - { - if (params) - *params = (*it).second; - - return true; - } - else - { - return false; - } -} - - -void SMTPConnection::authenticate() -{ - if (!m_extendedSMTP) - { - internalDisconnect(); - throw exceptions::command_error("AUTH", "ESMTP not supported."); - } - - getAuthenticator()->setService(m_transport.lock()); - -#if VMIME_HAVE_SASL_SUPPORT - // First, try SASL authentication - if (GET_PROPERTY(bool, PROPERTY_OPTIONS_SASL)) - { - try - { - authenticateSASL(); - - m_authenticated = true; - return; - } - catch (exceptions::authentication_error& e) - { - if (!GET_PROPERTY(bool, PROPERTY_OPTIONS_SASL_FALLBACK)) - { - // Can't fallback on normal authentication - internalDisconnect(); - throw e; - } - else - { - // Ignore, will try normal authentication - } - } - catch (exception& e) - { - internalDisconnect(); - throw e; - } - } -#endif // VMIME_HAVE_SASL_SUPPORT - - // No other authentication method is possible - throw exceptions::authentication_error("All authentication methods failed"); -} - - - -#if VMIME_HAVE_SASL_SUPPORT - -void SMTPConnection::authenticateSASL() -{ - if (!dynamicCast (getAuthenticator())) - throw exceptions::authentication_error("No SASL authenticator available."); - - // Obtain SASL mechanisms supported by server from ESMTP extensions - std::vector saslMechs; - hasExtension("AUTH", &saslMechs); - - if (saslMechs.empty()) - throw exceptions::authentication_error("No SASL mechanism available."); - - std::vector > mechList; - - shared_ptr saslContext = - make_shared (); - - 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()) - throw exceptions::authentication_error("No SASL mechanism available."); - - // Try to suggest a mechanism among all those supported - shared_ptr suggestedMech = - saslContext->suggestMechanism(mechList); - - if (!suggestedMech) - throw exceptions::authentication_error("Unable to suggest SASL mechanism."); - - // Allow application to choose which mechanisms to use - mechList = dynamicCast (getAuthenticator())-> - getAcceptableMechanisms(mechList, suggestedMech); - - 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) - { - shared_ptr mech = mechList[i]; - - shared_ptr saslSession = - saslContext->createSession("smtp", getAuthenticator(), mech); - - saslSession->init(); - - sendRequest(SMTPCommand::AUTH(mech->getName())); - - for (bool cont = true ; cont ; ) - { - shared_ptr response = readResponse(); - - switch (response->getCode()) - { - case 235: - { - m_socket = saslSession->getSecuredSocket(m_socket); - return; - } - case 334: - { - byte_t* challenge = 0; - size_t challengeLen = 0; - - byte_t* resp = 0; - size_t respLen = 0; - - try - { - // Extract challenge - saslContext->decodeB64(response->getText(), &challenge, &challengeLen); - - // Prepare response - saslSession->evaluateChallenge - (challenge, challengeLen, &resp, &respLen); - - // Send response - m_socket->send(saslContext->encodeB64(resp, respLen) + "\r\n"); - } - 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"); - } - catch (...) - { - if (challenge) - delete [] challenge; - - if (resp) - delete [] resp; - - throw; - } - - if (challenge) - delete [] challenge; - - if (resp) - delete [] resp; - - break; - } - default: - - cont = false; - break; - } - } - } - - throw exceptions::authentication_error - ("Could not authenticate using SASL: all mechanisms failed."); -} - -#endif // VMIME_HAVE_SASL_SUPPORT - - -#if VMIME_HAVE_TLS_SUPPORT - -void SMTPConnection::startTLS() -{ - try - { - sendRequest(SMTPCommand::STARTTLS()); - - shared_ptr resp = readResponse(); - - if (resp->getCode() != 220) - { - throw SMTPCommandError("STARTTLS", resp->getText(), - resp->getCode(), resp->getEnhancedCode()); - } - - shared_ptr tlsSession = tls::TLSSession::create - (getTransport()->getCertificateVerifier(), - getTransport()->getSession()->getTLSProperties()); - - shared_ptr tlsSocket = - tlsSession->getSocket(m_socket); - - tlsSocket->handshake(m_timeoutHandler); - - m_socket = tlsSocket; - - m_secured = true; - m_cntInfos = make_shared - (m_cntInfos->getHost(), m_cntInfos->getPort(), tlsSession, tlsSocket); - } - catch (exceptions::command_error&) - { - // Non-fatal error - throw; - } - catch (exception&) - { - // Fatal error - internalDisconnect(); - throw; - } -} - -#endif // VMIME_HAVE_TLS_SUPPORT - - -void SMTPConnection::disconnect() -{ - if (!isConnected()) - throw exceptions::not_connected(); - - internalDisconnect(); -} - - -void SMTPConnection::internalDisconnect() -{ - try - { - sendRequest(SMTPCommand::QUIT()); - readResponse(); - } - catch (exception&) - { - // Not important - } - - m_socket->disconnect(); - m_socket = null; - - m_timeoutHandler = null; - - m_authenticated = false; - m_extendedSMTP = false; - - m_secured = false; - m_cntInfos = null; -} - - -void SMTPConnection::sendRequest(shared_ptr cmd) -{ - cmd->writeToSocket(m_socket); -} - - -shared_ptr SMTPConnection::readResponse() -{ - shared_ptr resp = SMTPResponse::readResponse - (m_socket, m_timeoutHandler, m_responseState); - - m_responseState = resp->getCurrentState(); - - return resp; -} - - -bool SMTPConnection::isConnected() const -{ - return m_socket && m_socket->isConnected() && m_authenticated; -} - - -bool SMTPConnection::isSecuredConnection() const -{ - return m_secured; -} - - -shared_ptr SMTPConnection::getConnectionInfos() const -{ - return m_cntInfos; -} - - -shared_ptr SMTPConnection::getTransport() -{ - return m_transport.lock(); -} - - -shared_ptr SMTPConnection::getSession() -{ - return m_transport.lock()->getSession(); -} - - -shared_ptr SMTPConnection::getSocket() -{ - return m_socket; -} - - -shared_ptr SMTPConnection::getTimeoutHandler() -{ - return m_timeoutHandler; -} - - -shared_ptr SMTPConnection::getAuthenticator() -{ - return m_auth; -} - - -} // smtp -} // net -} // vmime - - -#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_SMTP diff --git a/src/net/smtp/SMTPExceptions.cpp b/src/net/smtp/SMTPExceptions.cpp deleted file mode 100644 index 0c3112c0..00000000 --- a/src/net/smtp/SMTPExceptions.cpp +++ /dev/null @@ -1,151 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// 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 && VMIME_HAVE_MESSAGING_PROTO_SMTP - - -#include "vmime/net/smtp/SMTPExceptions.hpp" - - -namespace vmime { -namespace net { -namespace smtp { - - -// -// SMTPCommandError -// - -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) -{ -} - - -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) -{ -} - - -SMTPCommandError::~SMTPCommandError() throw() -{ -} - - -int SMTPCommandError::statusCode() const -{ - return m_status; -} - - -const SMTPResponse::enhancedStatusCode SMTPCommandError::extendedStatusCode() const -{ - return m_exStatus; -} - - -exception* SMTPCommandError::clone() const -{ - return new SMTPCommandError(*this); -} - - -const char* SMTPCommandError::name() const throw() -{ - return "SMTPCommandError"; -} - - -// -// SMTPMessageSizeExceedsMaxLimitsException -// - -SMTPMessageSizeExceedsMaxLimitsException::SMTPMessageSizeExceedsMaxLimitsException(const exception& other) - : net_exception("Message size exceeds maximum server limits (permanent error).", other) -{ -} - - -SMTPMessageSizeExceedsMaxLimitsException::~SMTPMessageSizeExceedsMaxLimitsException() throw() -{ -} - - -exception* SMTPMessageSizeExceedsMaxLimitsException::clone() const -{ - return new SMTPMessageSizeExceedsMaxLimitsException(*this); -} - - -const char* SMTPMessageSizeExceedsMaxLimitsException::name() const throw() -{ - return "SMTPMessageSizeExceedsMaxLimitsException"; -} - - -// -// SMTPMessageSizeExceedsCurLimitsException -// - -SMTPMessageSizeExceedsCurLimitsException::SMTPMessageSizeExceedsCurLimitsException(const exception& other) - : net_exception("Message size exceeds current server limits (temporary storage error).", other) -{ -} - - -SMTPMessageSizeExceedsCurLimitsException::~SMTPMessageSizeExceedsCurLimitsException() throw() -{ -} - - -exception* SMTPMessageSizeExceedsCurLimitsException::clone() const -{ - return new SMTPMessageSizeExceedsCurLimitsException(*this); -} - - -const char* SMTPMessageSizeExceedsCurLimitsException::name() const throw() -{ - return "SMTPMessageSizeExceedsCurLimitsException"; -} - - -} // smtp -} // net -} // vmime - - -#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_SMTP diff --git a/src/net/smtp/SMTPResponse.cpp b/src/net/smtp/SMTPResponse.cpp deleted file mode 100644 index f7980351..00000000 --- a/src/net/smtp/SMTPResponse.cpp +++ /dev/null @@ -1,334 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// 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 && VMIME_HAVE_MESSAGING_PROTO_SMTP - - -#include "vmime/net/smtp/SMTPResponse.hpp" - -#include "vmime/platform.hpp" -#include "vmime/utility/stringUtils.hpp" - -#include "vmime/net/socket.hpp" -#include "vmime/net/timeoutHandler.hpp" - -#include - - -namespace vmime { -namespace net { -namespace smtp { - - -SMTPResponse::SMTPResponse(shared_ptr sok, shared_ptr toh, const state& st) - : m_socket(sok), m_timeoutHandler(toh), - m_responseBuffer(st.responseBuffer), m_responseContinues(false) -{ -} - - -SMTPResponse::SMTPResponse(const SMTPResponse&) - : vmime::object() -{ - // Not used -} - - -int SMTPResponse::getCode() const -{ - const int firstCode = m_lines[0].getCode(); - - 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) - return 0; - } - - return firstCode; -} - - -const SMTPResponse::enhancedStatusCode SMTPResponse::getEnhancedCode() const -{ - return m_lines[m_lines.size() - 1].getEnhancedCode(); -} - - -const string SMTPResponse::getText() const -{ - string text = m_lines[0].getText(); - - for (unsigned int i = 1 ; i < m_lines.size() ; ++i) - { - text += '\n'; - text += m_lines[i].getText(); - } - - return text; -} - - -// static -shared_ptr SMTPResponse::readResponse - (shared_ptr sok, shared_ptr toh, const state& st) -{ - shared_ptr resp = shared_ptr (new SMTPResponse(sok, toh, st)); - - resp->readResponse(); - - return resp; -} - - -void SMTPResponse::readResponse() -{ - responseLine line = getNextResponse(); - m_lines.push_back(line); - - while (m_responseContinues) - { - line = getNextResponse(); - m_lines.push_back(line); - } -} - - -const string SMTPResponse::readResponseLine() -{ - string currentBuffer = m_responseBuffer; - - if (m_timeoutHandler) - m_timeoutHandler->resetTimeOut(); - - while (true) - { - // Get a line from the response buffer - const size_t lineEnd = currentBuffer.find_first_of('\n'); - - if (lineEnd != string::npos) - { - size_t actualLineEnd = lineEnd; - - 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; - - return line; - } - - // Check whether the time-out delay is elapsed - if (m_timeoutHandler && m_timeoutHandler->isTimeOut()) - { - if (!m_timeoutHandler->handleTimeOut()) - throw exceptions::operation_timed_out(); - - m_timeoutHandler->resetTimeOut(); - } - - // Receive data from the socket - string receiveBuffer; - m_socket->receive(receiveBuffer); - - if (receiveBuffer.empty()) // buffer is empty - { - platform::getHandler()->wait(); - continue; - } - - currentBuffer += receiveBuffer; - } -} - - -const SMTPResponse::responseLine SMTPResponse::getNextResponse() -{ - string line = readResponseLine(); - - const int code = extractResponseCode(line); - string text; - - m_responseContinues = (line.length() >= 4 && line[3] == '-'); - - if (line.length() > 4) - text = utility::stringUtils::trim(line.substr(4)); - else - text = ""; - - return responseLine(code, text, extractEnhancedCode(text)); -} - - -// static -int SMTPResponse::extractResponseCode(const string& response) -{ - int code = 0; - - if (response.length() >= 3) - { - code = (response[0] - '0') * 100 - + (response[1] - '0') * 10 - + (response[2] - '0'); - } - - return code; -} - - -// static -const SMTPResponse::enhancedStatusCode SMTPResponse::extractEnhancedCode(const string& responseText) -{ - enhancedStatusCode enhCode; - - std::istringstream iss(responseText); - - if (std::isdigit(iss.peek())) - { - iss >> enhCode.klass; - - if (iss.get() == '.' && std::isdigit(iss.peek())) - { - iss >> enhCode.subject; - - if (iss.get() == '.' && std::isdigit(iss.peek())) - { - iss >> enhCode.detail; - return enhCode; - } - } - } - - return enhancedStatusCode(); // no enhanced code found -} - - -const SMTPResponse::responseLine SMTPResponse::getLineAt(const size_t pos) const -{ - return m_lines[pos]; -} - - -size_t SMTPResponse::getLineCount() const -{ - return m_lines.size(); -} - - -const SMTPResponse::responseLine SMTPResponse::getLastLine() const -{ - return m_lines[m_lines.size() - 1]; -} - - -const SMTPResponse::state SMTPResponse::getCurrentState() const -{ - state st; - st.responseBuffer = m_responseBuffer; - - return st; -} - - - -// SMTPResponse::responseLine - -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) -{ - m_code = code; -} - - -int SMTPResponse::responseLine::getCode() const -{ - return m_code; -} - - -void SMTPResponse::responseLine::setEnhancedCode(const enhancedStatusCode& enhCode) -{ - m_enhCode = enhCode; -} - - -const SMTPResponse::enhancedStatusCode SMTPResponse::responseLine::getEnhancedCode() const -{ - return m_enhCode; -} - - -void SMTPResponse::responseLine::setText(const string& text) -{ - m_text = text; -} - - -const string SMTPResponse::responseLine::getText() const -{ - return m_text; -} - - - -// SMTPResponse::enhancedStatusCode - - -SMTPResponse::enhancedStatusCode::enhancedStatusCode() - : klass(0), subject(0), detail(0) -{ -} - - -SMTPResponse::enhancedStatusCode::enhancedStatusCode(const enhancedStatusCode& enhCode) - : klass(enhCode.klass), subject(enhCode.subject), detail(enhCode.detail) -{ -} - - -std::ostream& operator<<(std::ostream& os, const SMTPResponse::enhancedStatusCode& code) -{ - os << code.klass << '.' << code.subject << '.' << code.detail; - return os; -} - - -} // smtp -} // net -} // vmime - - -#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_SMTP - diff --git a/src/net/smtp/SMTPSTransport.cpp b/src/net/smtp/SMTPSTransport.cpp deleted file mode 100644 index ab64d49d..00000000 --- a/src/net/smtp/SMTPSTransport.cpp +++ /dev/null @@ -1,79 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// 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 && VMIME_HAVE_MESSAGING_PROTO_SMTP - - -#include "vmime/net/smtp/SMTPSTransport.hpp" - - -namespace vmime { -namespace net { -namespace smtp { - - -SMTPSTransport::SMTPSTransport(shared_ptr sess, shared_ptr auth) - : SMTPTransport(sess, auth, true) -{ -} - - -SMTPSTransport::~SMTPSTransport() -{ -} - - -const string SMTPSTransport::getProtocolName() const -{ - return "smtps"; -} - - - -// Service infos - -SMTPServiceInfos SMTPSTransport::sm_infos(true); - - -const serviceInfos& SMTPSTransport::getInfosInstance() -{ - return sm_infos; -} - - -const serviceInfos& SMTPSTransport::getInfos() const -{ - return sm_infos; -} - - -} // smtp -} // net -} // vmime - - -#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_SMTP - diff --git a/src/net/smtp/SMTPServiceInfos.cpp b/src/net/smtp/SMTPServiceInfos.cpp deleted file mode 100644 index 532bb8b8..00000000 --- a/src/net/smtp/SMTPServiceInfos.cpp +++ /dev/null @@ -1,146 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// 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 && VMIME_HAVE_MESSAGING_PROTO_SMTP - - -#include "vmime/net/smtp/SMTPServiceInfos.hpp" - - -namespace vmime { -namespace net { -namespace smtp { - - -SMTPServiceInfos::SMTPServiceInfos(const bool smtps) - : m_smtps(smtps) -{ -} - - -const string SMTPServiceInfos::getPropertyPrefix() const -{ - if (m_smtps) - return "transport.smtps."; - else - return "transport.smtp."; -} - - -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 - property("options.sasl", serviceInfos::property::TYPE_BOOLEAN, "true"), - property("options.sasl.fallback", serviceInfos::property::TYPE_BOOLEAN, "false"), -#endif // VMIME_HAVE_SASL_SUPPORT - - property("options.pipelining", serviceInfos::property::TYPE_BOOLEAN, "true"), - property("options.chunking", serviceInfos::property::TYPE_BOOLEAN, "true"), - - // Common properties - property(serviceInfos::property::AUTH_USERNAME, serviceInfos::property::FLAG_REQUIRED), - property(serviceInfos::property::AUTH_PASSWORD, serviceInfos::property::FLAG_REQUIRED), - -#if VMIME_HAVE_TLS_SUPPORT - property(serviceInfos::property::CONNECTION_TLS), - property(serviceInfos::property::CONNECTION_TLS_REQUIRED), -#endif // VMIME_HAVE_TLS_SUPPORT - - property(serviceInfos::property::SERVER_ADDRESS, serviceInfos::property::FLAG_REQUIRED), - property(serviceInfos::property::SERVER_PORT, "25"), - }; - - static props smtpsProps = - { - // SMTP-specific options - property("options.need-authentication", serviceInfos::property::TYPE_BOOLEAN, "false"), -#if VMIME_HAVE_SASL_SUPPORT - property("options.sasl", serviceInfos::property::TYPE_BOOLEAN, "true"), - property("options.sasl.fallback", serviceInfos::property::TYPE_BOOLEAN, "false"), -#endif // VMIME_HAVE_SASL_SUPPORT - - property("options.pipelining", serviceInfos::property::TYPE_BOOLEAN, "true"), - property("options.chunking", serviceInfos::property::TYPE_BOOLEAN, "true"), - - // Common properties - property(serviceInfos::property::AUTH_USERNAME, serviceInfos::property::FLAG_REQUIRED), - property(serviceInfos::property::AUTH_PASSWORD, serviceInfos::property::FLAG_REQUIRED), - -#if VMIME_HAVE_TLS_SUPPORT - property(serviceInfos::property::CONNECTION_TLS), - property(serviceInfos::property::CONNECTION_TLS_REQUIRED), -#endif // VMIME_HAVE_TLS_SUPPORT - - property(serviceInfos::property::SERVER_ADDRESS, serviceInfos::property::FLAG_REQUIRED), - property(serviceInfos::property::SERVER_PORT, "465"), - }; - - return m_smtps ? smtpsProps : smtpProps; -} - - -const std::vector SMTPServiceInfos::getAvailableProperties() const -{ - std::vector list; - const props& p = getProperties(); - - // SMTP-specific options - list.push_back(p.PROPERTY_OPTIONS_NEEDAUTH); -#if VMIME_HAVE_SASL_SUPPORT - list.push_back(p.PROPERTY_OPTIONS_SASL); - list.push_back(p.PROPERTY_OPTIONS_SASL_FALLBACK); -#endif // VMIME_HAVE_SASL_SUPPORT - - // Common properties - list.push_back(p.PROPERTY_AUTH_USERNAME); - list.push_back(p.PROPERTY_AUTH_PASSWORD); - -#if VMIME_HAVE_TLS_SUPPORT - if (!m_smtps) - { - list.push_back(p.PROPERTY_CONNECTION_TLS); - list.push_back(p.PROPERTY_CONNECTION_TLS_REQUIRED); - } -#endif // VMIME_HAVE_TLS_SUPPORT - - list.push_back(p.PROPERTY_SERVER_ADDRESS); - list.push_back(p.PROPERTY_SERVER_PORT); - - return list; -} - - -} // smtp -} // net -} // vmime - - -#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_SMTP - diff --git a/src/net/smtp/SMTPTransport.cpp b/src/net/smtp/SMTPTransport.cpp deleted file mode 100644 index 0020d010..00000000 --- a/src/net/smtp/SMTPTransport.cpp +++ /dev/null @@ -1,420 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// 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 && VMIME_HAVE_MESSAGING_PROTO_SMTP - - -#include "vmime/net/smtp/SMTPTransport.hpp" -#include "vmime/net/smtp/SMTPResponse.hpp" -#include "vmime/net/smtp/SMTPCommand.hpp" -#include "vmime/net/smtp/SMTPCommandSet.hpp" -#include "vmime/net/smtp/SMTPChunkingOutputStreamAdapter.hpp" -#include "vmime/net/smtp/SMTPExceptions.hpp" - -#include "vmime/exception.hpp" -#include "vmime/mailboxList.hpp" -#include "vmime/message.hpp" - -#include "vmime/utility/filteredStream.hpp" -#include "vmime/utility/stringUtils.hpp" -#include "vmime/utility/outputStreamSocketAdapter.hpp" -#include "vmime/utility/streamUtils.hpp" -#include "vmime/utility/outputStreamAdapter.hpp" -#include "vmime/utility/inputStreamStringAdapter.hpp" - - -namespace vmime { -namespace net { -namespace smtp { - - -SMTPTransport::SMTPTransport(shared_ptr sess, shared_ptr auth, const bool secured) - : transport(sess, getInfosInstance(), auth), m_isSMTPS(secured), m_needReset(false) -{ -} - - -SMTPTransport::~SMTPTransport() -{ - try - { - if (isConnected()) - disconnect(); - } - catch (vmime::exception&) - { - // Ignore - } -} - - -const string SMTPTransport::getProtocolName() const -{ - return "smtp"; -} - - -bool SMTPTransport::isSMTPS() const -{ - return m_isSMTPS; -} - - -void SMTPTransport::connect() -{ - if (isConnected()) - throw exceptions::already_connected(); - - m_connection = make_shared - (dynamicCast (shared_from_this()), getAuthenticator()); - - try - { - m_connection->connect(); - } - catch (std::exception&) - { - m_connection = null; - throw; - } -} - - -bool SMTPTransport::isConnected() const -{ - return m_connection && m_connection->isConnected(); -} - - -bool SMTPTransport::isSecuredConnection() const -{ - if (m_connection == NULL) - return false; - - return m_connection->isSecuredConnection(); -} - - -shared_ptr SMTPTransport::getConnectionInfos() const -{ - if (m_connection == NULL) - return null; - - return m_connection->getConnectionInfos(); -} - - -shared_ptr SMTPTransport::getConnection() -{ - return m_connection; -} - - -void SMTPTransport::disconnect() -{ - if (!isConnected()) - throw exceptions::not_connected(); - - m_connection->disconnect(); - m_connection = null; -} - - -void SMTPTransport::noop() -{ - if (!isConnected()) - throw exceptions::not_connected(); - - m_connection->sendRequest(SMTPCommand::NOOP()); - - shared_ptr resp = m_connection->readResponse(); - - if (resp->getCode() != 250) - { - throw SMTPCommandError - ("NOOP", resp->getText(), resp->getCode(), resp->getEnhancedCode()); - } -} - - -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()) - throw exceptions::no_recipient(); - else if (expeditor.isEmpty()) - throw exceptions::no_expeditor(); - - - const bool needReset = m_needReset; - const bool hasPipelining = m_connection->hasExtension("PIPELINING") && - getInfos().getPropertyValue (getSession(), - dynamic_cast (getInfos()).getProperties().PROPERTY_OPTIONS_PIPELINING); - - shared_ptr resp; - shared_ptr commands = SMTPCommandSet::create(hasPipelining); - - // Emit a "RSET" command if we previously sent a message on this connection - if (needReset) - commands->addCommand(SMTPCommand::RSET()); - - // Emit the "MAIL" command - const bool hasSMTPUTF8 = m_connection->hasExtension("SMTPUTF8"); - 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)); - - // 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) - { - const mailbox& mbox = *recipients.getMailboxAt(i); - commands->addCommand(SMTPCommand::RCPT(mbox, hasSMTPUTF8)); - } - - // Prepare sending of message data - if (sendDATACommand) - commands->addCommand(SMTPCommand::DATA()); - - // Read response for "RSET" command - if (needReset) - { - commands->writeToSocket(m_connection->getSocket()); - - if ((resp = m_connection->readResponse())->getCode() != 250) - { - disconnect(); - - throw SMTPCommandError - (commands->getLastCommandSent()->getText(), resp->getText(), - resp->getCode(), resp->getEnhancedCode()); - } - } - - // Read response for "MAIL" command - commands->writeToSocket(m_connection->getSocket()); - - if ((resp = m_connection->readResponse())->getCode() != 250) - { - // SIZE extension: insufficient system storage - if (resp->getCode() == 452) - { - disconnect(); - - 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) - { - disconnect(); - - throw SMTPMessageSizeExceedsMaxLimitsException - (SMTPCommandError(commands->getLastCommandSent()->getText(), resp->getText(), - resp->getCode(), resp->getEnhancedCode())); - } - // Other error - else - { - disconnect(); - - 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) - { - commands->writeToSocket(m_connection->getSocket()); - - resp = m_connection->readResponse(); - - if (resp->getCode() != 250 && - resp->getCode() != 251) - { - // SIZE extension: insufficient system storage - if (resp->getCode() == 452) - { - disconnect(); - - 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) - { - disconnect(); - - throw SMTPMessageSizeExceedsMaxLimitsException - (SMTPCommandError(commands->getLastCommandSent()->getText(), resp->getText(), - resp->getCode(), resp->getEnhancedCode())); - } - // Other error - else - { - disconnect(); - - throw SMTPCommandError - (commands->getLastCommandSent()->getText(), resp->getText(), - resp->getCode(), resp->getEnhancedCode()); - } - } - } - - // Read response for "DATA" command - if (sendDATACommand) - { - commands->writeToSocket(m_connection->getSocket()); - - if ((resp = m_connection->readResponse())->getCode() != 354) - { - disconnect(); - - 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()) - throw exceptions::not_connected(); - - // Send message envelope - sendEnvelope(expeditor, recipients, sender, /* sendDATACommand */ true, size); - - // Send the message data - // Stream copy with "\n." to "\n.." transformation - utility::outputStreamSocketAdapter sos(*m_connection->getSocket()); - utility::dotFilteredOutputStream fos(sos); - - utility::bufferedStreamCopy(is, fos, size, progress); - - fos.flush(); - - // Send end-of-data delimiter - m_connection->getSocket()->send("\r\n.\r\n"); - - shared_ptr resp; - - if ((resp = m_connection->readResponse())->getCode() != 250) - { - disconnect(); - - throw SMTPCommandError - ("DATA", resp->getText(), resp->getCode(), resp->getEnhancedCode()); - } -} - - -void SMTPTransport::send - (shared_ptr 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 - generationContext ctx(generationContext::getDefaultContext()); - ctx.setInternationalizedEmailSupport(m_connection->hasExtension("SMTPUTF8")); - - // If CHUNKING is not supported, generate the message to a temporary - // buffer then use the send() method which takes an inputStream - if (!m_connection->hasExtension("CHUNKING") || - !getInfos().getPropertyValue (getSession(), - dynamic_cast (getInfos()).getProperties().PROPERTY_OPTIONS_CHUNKING)) - - { - std::ostringstream oss; - utility::outputStreamAdapter ossAdapter(oss); - - msg->generate(ctx, ossAdapter); - - const string& str(oss.str()); - - utility::inputStreamStringAdapter isAdapter(str); - - send(expeditor, recipients, isAdapter, str.length(), progress, sender); - return; - } - - // Send message envelope - sendEnvelope(expeditor, recipients, sender, - /* sendDATACommand */ false, msg->getGeneratedSize(ctx)); - - // Send the message by chunks - SMTPChunkingOutputStreamAdapter chunkStream(m_connection); - - msg->generate(ctx, chunkStream); - - chunkStream.flush(); -} - - - -// Service infos - -SMTPServiceInfos SMTPTransport::sm_infos(false); - - -const serviceInfos& SMTPTransport::getInfosInstance() -{ - return sm_infos; -} - - -const serviceInfos& SMTPTransport::getInfos() const -{ - return sm_infos; -} - - -} // smtp -} // net -} // vmime - - -#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_SMTP - diff --git a/src/net/tls/TLSProperties.cpp b/src/net/tls/TLSProperties.cpp deleted file mode 100644 index 1986db79..00000000 --- a/src/net/tls/TLSProperties.cpp +++ /dev/null @@ -1,44 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// 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 && VMIME_HAVE_TLS_SUPPORT - - -#include "vmime/net/tls/TLSProperties.hpp" - - -namespace vmime { -namespace net { -namespace tls { - - -} // tls -} // net -} // vmime - - -#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_TLS_SUPPORT - diff --git a/src/net/tls/TLSSecuredConnectionInfos.cpp b/src/net/tls/TLSSecuredConnectionInfos.cpp deleted file mode 100644 index 4856e9af..00000000 --- a/src/net/tls/TLSSecuredConnectionInfos.cpp +++ /dev/null @@ -1,72 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// 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 && VMIME_HAVE_TLS_SUPPORT - - -#include "vmime/net/tls/TLSSecuredConnectionInfos.hpp" -#include "vmime/net/tls/TLSSession.hpp" - - -namespace vmime { -namespace net { -namespace tls { - - -TLSSecuredConnectionInfos::TLSSecuredConnectionInfos - (const string& host, const port_t port, - shared_ptr tlsSession, shared_ptr tlsSocket) - : m_host(host), m_port(port), - m_tlsSession(tlsSession), m_tlsSocket(tlsSocket) -{ -} - - -const string TLSSecuredConnectionInfos::getHost() const -{ - return m_host; -} - - -port_t TLSSecuredConnectionInfos::getPort() const -{ - return m_port; -} - - -shared_ptr TLSSecuredConnectionInfos::getPeerCertificates() const -{ - return m_tlsSocket->getPeerCertificates(); -} - - -} // tls -} // net -} // vmime - - -#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_TLS_SUPPORT - diff --git a/src/net/tls/TLSSession.cpp b/src/net/tls/TLSSession.cpp deleted file mode 100644 index a46f07ca..00000000 --- a/src/net/tls/TLSSession.cpp +++ /dev/null @@ -1,48 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// 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 && VMIME_HAVE_TLS_SUPPORT - - -#include "vmime/net/tls/TLSSession.hpp" - - -namespace vmime { -namespace net { -namespace tls { - - -TLSSession::TLSSession() -{ -} - - -} // tls -} // net -} // vmime - - -#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_TLS_SUPPORT diff --git a/src/net/tls/TLSSocket.cpp b/src/net/tls/TLSSocket.cpp deleted file mode 100644 index 0419a571..00000000 --- a/src/net/tls/TLSSocket.cpp +++ /dev/null @@ -1,44 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// 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 && VMIME_HAVE_TLS_SUPPORT - - -#include "vmime/net/tls/TLSSocket.hpp" - - -namespace vmime { -namespace net { -namespace tls { - - -} // tls -} // net -} // vmime - - -#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_TLS_SUPPORT - diff --git a/src/net/tls/gnutls/TLSProperties_GnuTLS.cpp b/src/net/tls/gnutls/TLSProperties_GnuTLS.cpp deleted file mode 100644 index 36ab7d7a..00000000 --- a/src/net/tls/gnutls/TLSProperties_GnuTLS.cpp +++ /dev/null @@ -1,113 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// 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 && VMIME_HAVE_TLS_SUPPORT && VMIME_TLS_SUPPORT_LIB_IS_GNUTLS - - -#include "vmime/base.hpp" -#include "vmime/net/tls/gnutls/TLSProperties_GnuTLS.hpp" - -#include -#if GNUTLS_VERSION_NUMBER < 0x030000 -#include -#endif - - -namespace vmime { -namespace net { -namespace tls { - - -TLSProperties::TLSProperties() - : m_data(make_shared ()) -{ - setCipherSuite(CIPHERSUITE_DEFAULT); -} - - -TLSProperties::TLSProperties(const TLSProperties& props) - : object(), - m_data(make_shared ()) -{ - *dynamicCast (m_data) = *dynamicCast (props.m_data); -} - - -void TLSProperties::setCipherSuite(const GenericCipherSuite cipherSuite) -{ - switch (cipherSuite) - { - case CIPHERSUITE_HIGH: - - setCipherSuite("SECURE256:%SSL3_RECORD_VERSION"); - break; - - case CIPHERSUITE_MEDIUM: - - setCipherSuite("SECURE128:%SSL3_RECORD_VERSION"); - break; - - case CIPHERSUITE_LOW: - - setCipherSuite("NORMAL:%SSL3_RECORD_VERSION"); - break; - - default: - case CIPHERSUITE_DEFAULT: - - setCipherSuite("NORMAL:%SSL3_RECORD_VERSION"); - break; - } -} - - -void TLSProperties::setCipherSuite(const string& cipherSuite) -{ - dynamicCast (m_data)->cipherSuite = cipherSuite; -} - - -const string TLSProperties::getCipherSuite() const -{ - return dynamicCast (m_data)->cipherSuite; -} - - - -TLSProperties_GnuTLS& TLSProperties_GnuTLS::operator=(const TLSProperties_GnuTLS& other) -{ - cipherSuite = other.cipherSuite; - - return *this; -} - - -} // tls -} // net -} // vmime - - -#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_TLS_SUPPORT && VMIME_TLS_SUPPORT_LIB_IS_GNUTLS diff --git a/src/net/tls/gnutls/TLSSession_GnuTLS.cpp b/src/net/tls/gnutls/TLSSession_GnuTLS.cpp deleted file mode 100644 index 1c520ed1..00000000 --- a/src/net/tls/gnutls/TLSSession_GnuTLS.cpp +++ /dev/null @@ -1,300 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// 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 && VMIME_HAVE_TLS_SUPPORT && VMIME_TLS_SUPPORT_LIB_IS_GNUTLS - - -#include -#if GNUTLS_VERSION_NUMBER < 0x030000 -#include -#endif - - -// Dependency on gcrypt is not needed since GNU TLS version 2.12. -// See here: http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=638651 -#if GNUTLS_VERSION_NUMBER <= 0x020b00 -# define VMIME_GNUTLS_NEEDS_GCRYPT 1 -#endif - -#if VMIME_HAVE_PTHREAD -# include -# if VMIME_GNUTLS_NEEDS_GCRYPT -# include -# endif -# include -#endif // VMIME_HAVE_PTHREAD - -#include "vmime/net/tls/gnutls/TLSSession_GnuTLS.hpp" -#include "vmime/net/tls/gnutls/TLSSocket_GnuTLS.hpp" -#include "vmime/net/tls/gnutls/TLSProperties_GnuTLS.hpp" - -#include "vmime/exception.hpp" - - -// Enable GnuTLS debugging by defining GNUTLS_DEBUG -//#define GNUTLS_DEBUG 1 - - -#include -#include - -#if VMIME_DEBUG && GNUTLS_DEBUG - #include -#endif // VMIME_DEBUG && GNUTLS_DEBUG - - -#if VMIME_HAVE_PTHREAD && VMIME_GNUTLS_NEEDS_GCRYPT && defined(GCRY_THREAD_OPTION_PTHREAD_IMPL) -extern "C" -{ - GCRY_THREAD_OPTION_PTHREAD_IMPL; -} -#endif // VMIME_HAVE_PTHREAD && defined(GCRY_THREAD_OPTION_PTHREAD_IMPL - - -namespace vmime { -namespace net { -namespace tls { - - -#ifndef VMIME_BUILDING_DOC - -// Initialize GNU TLS library -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); - #endif // VMIME_GNUTLS_NEEDS_GCRYPT -#endif // VMIME_HAVE_PTHREAD && defined(GCRY_THREAD_OPTION_PTHREAD_IMPL - - gnutls_global_init(); - //gnutls_global_init_extra(); - -#if VMIME_DEBUG && GNUTLS_DEBUG - gnutls_global_set_log_function(TLSLogFunc); - gnutls_global_set_log_level(10); -#endif // VMIME_DEBUG && GNUTLS_DEBUG - - gnutls_anon_allocate_client_credentials(&anonCred); - gnutls_certificate_allocate_credentials(&certCred); - } - - ~TLSGlobal() - { - gnutls_anon_free_client_credentials(anonCred); - gnutls_certificate_free_credentials(certCred); - - gnutls_global_deinit(); - } - -#if VMIME_DEBUG && GNUTLS_DEBUG - - static void TLSLogFunc(int level, const char *str) - { - std::cerr << "GNUTLS: [" << level << "] " << str << std::endl; - } - -#endif // VMIME_DEBUG && GNUTLS_DEBUG - - - gnutls_anon_client_credentials anonCred; - gnutls_certificate_credentials certCred; -}; - -static TLSGlobal g_gnutlsGlobal; - - -#endif // VMIME_BUILDING_DOC - - - -// static -shared_ptr TLSSession::create(shared_ptr cv, shared_ptr props) -{ - return make_shared (cv, props); -} - - -TLSSession_GnuTLS::TLSSession_GnuTLS(shared_ptr cv, shared_ptr props) - : m_certVerifier(cv), m_props(props) -{ - int res; - - m_gnutlsSession = new gnutls_session; - - 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. -#ifdef VMIME_HAVE_GNUTLS_PRIORITY_FUNCS - gnutls_dh_set_prime_bits(*m_gnutlsSession, 128); - - if ((res = gnutls_priority_set_direct - (*m_gnutlsSession, m_props->getCipherSuite().c_str(), NULL)) != 0) - { - throwTLSException("gnutls_priority_set_direct", res); - } - -#else // !VMIME_HAVE_GNUTLS_PRIORITY_FUNCS - - gnutls_set_default_priority(*m_gnutlsSession); - - // Sets the priority on the certificate types supported by gnutls. - // Priority is higher for types specified before others. After - // 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); - - if (res < 0) - { - throwTLSException - ("gnutls_certificate_type_set_priority", res); - } - - // Sets the priority on the protocol types - const int protoPriority[] = { GNUTLS_TLS1, GNUTLS_SSL3, 0 }; - - res = gnutls_protocol_set_priority(*m_gnutlsSession, protoPriority); - - if (res < 0) - { - throwTLSException - ("gnutls_certificate_type_set_priority", res); - } - - // Priority on the ciphers - const int cipherPriority[] = - { - GNUTLS_CIPHER_ARCFOUR_128, - GNUTLS_CIPHER_3DES_CBC, - GNUTLS_CIPHER_AES_128_CBC, - GNUTLS_CIPHER_AES_256_CBC, - GNUTLS_CIPHER_ARCFOUR_40, - GNUTLS_CIPHER_RC2_40_CBC, - GNUTLS_CIPHER_DES_CBC, - 0 - }; - - gnutls_cipher_set_priority(*m_gnutlsSession, cipherPriority); - - // Priority on MACs - 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[] = - { - GNUTLS_KX_RSA, - GNUTLS_KX_DHE_DSS, - GNUTLS_KX_DHE_RSA, - GNUTLS_KX_ANON_DH, - GNUTLS_KX_SRP, - GNUTLS_KX_RSA_EXPORT, - GNUTLS_KX_SRP_RSA, - GNUTLS_KX_SRP_DSS, - 0 - }; - - gnutls_kx_set_priority(*m_gnutlsSession, kxPriority); - - // Priority on compression methods - const int compressionPriority[] = - { - GNUTLS_COMP_ZLIB, - //GNUTLS_COMP_LZO, - GNUTLS_COMP_NULL, - 0 - }; - - gnutls_compression_set_priority(*m_gnutlsSession, compressionPriority); - -#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_CERTIFICATE, g_gnutlsGlobal.certCred); -} - - -TLSSession_GnuTLS::TLSSession_GnuTLS(const TLSSession_GnuTLS&) - : TLSSession() -{ - // Not used -} - - -TLSSession_GnuTLS::~TLSSession_GnuTLS() -{ - if (m_gnutlsSession) - { - gnutls_deinit(*m_gnutlsSession); - - delete m_gnutlsSession; - m_gnutlsSession = NULL; - } -} - - -shared_ptr TLSSession_GnuTLS::getSocket(shared_ptr sok) -{ - return TLSSocket::wrap(dynamicCast (shared_from_this()), sok); -} - - -shared_ptr TLSSession_GnuTLS::getCertificateVerifier() -{ - return m_certVerifier; -} - - -void TLSSession_GnuTLS::throwTLSException(const string& fname, const int code) -{ - std::ostringstream msg; - - msg << fname + "() returned code "; - msg << std::hex << code; - msg << ": "; - msg << gnutls_strerror(code); - - throw exceptions::tls_exception(msg.str()); -} - - -} // tls -} // net -} // vmime - - -#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_TLS_SUPPORT && VMIME_TLS_SUPPORT_LIB_IS_GNUTLS diff --git a/src/net/tls/gnutls/TLSSocket_GnuTLS.cpp b/src/net/tls/gnutls/TLSSocket_GnuTLS.cpp deleted file mode 100644 index 5a90565b..00000000 --- a/src/net/tls/gnutls/TLSSocket_GnuTLS.cpp +++ /dev/null @@ -1,490 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// 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 && VMIME_HAVE_TLS_SUPPORT && VMIME_TLS_SUPPORT_LIB_IS_GNUTLS - - -#include -#include - -#include "vmime/net/tls/gnutls/TLSSocket_GnuTLS.hpp" -#include "vmime/net/tls/gnutls/TLSSession_GnuTLS.hpp" - -#include "vmime/platform.hpp" - -#include "vmime/security/cert/X509Certificate.hpp" - -#include "vmime/utility/stringUtils.hpp" - -#include - - -namespace vmime { -namespace net { -namespace tls { - - -// static -shared_ptr TLSSocket::wrap(shared_ptr session, shared_ptr sok) -{ - return make_shared - (dynamicCast (session), sok); -} - - -TLSSocket_GnuTLS::TLSSocket_GnuTLS(shared_ptr session, shared_ptr sok) - : m_session(session), m_wrapped(sok), m_connected(false), - m_handshaking(false), m_ex(NULL), m_status(0) -{ - gnutls_transport_set_ptr(*m_session->m_gnutlsSession, this); - - gnutls_transport_set_push_function(*m_session->m_gnutlsSession, gnutlsPushFunc); - gnutls_transport_set_pull_function(*m_session->m_gnutlsSession, gnutlsPullFunc); -} - - -TLSSocket_GnuTLS::~TLSSocket_GnuTLS() -{ - if (m_ex) - { - delete m_ex; - m_ex = NULL; - } - - try - { - disconnect(); - } - catch (...) - { - // Don't throw exception in destructor - } -} - - -void TLSSocket_GnuTLS::connect(const string& address, const port_t port) -{ - m_wrapped->connect(address, port); - - handshake(null); - - m_connected = true; -} - - -void TLSSocket_GnuTLS::disconnect() -{ - if (m_connected) - { - gnutls_bye(*m_session->m_gnutlsSession, GNUTLS_SHUT_RDWR); - - m_wrapped->disconnect(); - - m_connected = false; - } -} - - -bool TLSSocket_GnuTLS::isConnected() const -{ - return m_wrapped->isConnected() && m_connected; -} - - -size_t TLSSocket_GnuTLS::getBlockSize() const -{ - return 16384; // 16 KB -} - - -const string TLSSocket_GnuTLS::getPeerName() const -{ - return m_wrapped->getPeerName(); -} - - -const string TLSSocket_GnuTLS::getPeerAddress() const -{ - return m_wrapped->getPeerAddress(); -} - - -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) -{ - sendRaw(reinterpret_cast (buffer.data()), buffer.length()); -} - - -void TLSSocket_GnuTLS::send(const char* str) -{ - sendRaw(reinterpret_cast (str), ::strlen(str)); -} - - -size_t TLSSocket_GnuTLS::receiveRaw(byte_t* buffer, const size_t count) -{ - m_status &= ~STATUS_WOULDBLOCK; - - const ssize_t ret = gnutls_record_recv - (*m_session->m_gnutlsSession, - buffer, static_cast (count)); - - if (m_ex) - internalThrow(); - - if (ret < 0) - { - if (ret == GNUTLS_E_AGAIN) - { - m_status |= STATUS_WOULDBLOCK; - return 0; - } - - TLSSession_GnuTLS::throwTLSException("gnutls_record_recv", static_cast (ret)); - } - - return static_cast (ret); -} - - -void TLSSocket_GnuTLS::sendRaw(const byte_t* buffer, const size_t count) -{ - ssize_t ret = gnutls_record_send - (*m_session->m_gnutlsSession, - buffer, static_cast (count)); - - if (m_ex) - internalThrow(); - - if (ret < 0) - { - if (ret == GNUTLS_E_AGAIN) - { - m_status |= STATUS_WOULDBLOCK; - return; - } - - TLSSession_GnuTLS::throwTLSException("gnutls_record_send", static_cast (ret)); - } -} - - -size_t TLSSocket_GnuTLS::sendRawNonBlocking(const byte_t* buffer, const size_t count) -{ - ssize_t ret = gnutls_record_send - (*m_session->m_gnutlsSession, - buffer, static_cast (count)); - - if (m_ex) - internalThrow(); - - if (ret < 0) - { - if (ret == GNUTLS_E_AGAIN) - { - m_status |= STATUS_WOULDBLOCK; - return 0; - } - - TLSSession_GnuTLS::throwTLSException("gnutls_record_send", static_cast (ret)); - } - - return static_cast (ret); -} - - -unsigned int TLSSocket_GnuTLS::getStatus() const -{ - return m_status | m_wrapped->getStatus(); -} - - -void TLSSocket_GnuTLS::handshake(shared_ptr toHandler) -{ - if (toHandler) - toHandler->resetTimeOut(); - - // Start handshaking process - m_handshaking = true; - m_toHandler = toHandler; - - try - { - while (true) - { - const int ret = gnutls_handshake(*m_session->m_gnutlsSession); - - if (m_ex) - internalThrow(); - - if (ret < 0) - { - if (ret == GNUTLS_E_AGAIN || - ret == GNUTLS_E_INTERRUPTED) - { - // Non-fatal error - platform::getHandler()->wait(); - } - else - { - TLSSession_GnuTLS::throwTLSException("gnutls_handshake", ret); - } - } - else - { - // Successful handshake - break; - } - } - } - catch (...) - { - m_handshaking = false; - m_toHandler = null; - - throw; - } - - m_handshaking = false; - m_toHandler = null; - - // Verify server's certificate(s) - shared_ptr certs = getPeerCertificates(); - - if (certs == NULL) - throw exceptions::tls_exception("No peer certificate."); - - m_session->getCertificateVerifier()->verify(certs, getPeerName()); - - m_connected = true; -} - - -ssize_t TLSSocket_GnuTLS::gnutlsPushFunc - (gnutls_transport_ptr trspt, const void* data, size_t len) -{ - TLSSocket_GnuTLS* sok = reinterpret_cast (trspt); - - try - { - sok->m_wrapped->sendRaw - (reinterpret_cast (data), len); - } - catch (exception& e) - { - // Workaround for bad behaviour when throwing C++ exceptions - // from C functions (GNU TLS) - sok->m_ex = e.clone(); - return -1; - } - - return len; -} - - -ssize_t TLSSocket_GnuTLS::gnutlsPullFunc - (gnutls_transport_ptr trspt, void* data, size_t len) -{ - TLSSocket_GnuTLS* sok = reinterpret_cast (trspt); - - try - { - // Workaround for cross-platform asynchronous handshaking: - // gnutls_handshake() only returns GNUTLS_E_AGAIN if recv() - // returns -1 and errno is set to EGAIN... - if (sok->m_handshaking) - { - while (true) - { - const ssize_t ret = static_cast - (sok->m_wrapped->receiveRaw - (reinterpret_cast (data), len)); - - if (ret == 0) - { - // No data available yet - platform::getHandler()->wait(); - } - else - { - return ret; - } - - // Check whether the time-out delay is elapsed - if (sok->m_toHandler && sok->m_toHandler->isTimeOut()) - { - if (!sok->m_toHandler->handleTimeOut()) - throw exceptions::operation_timed_out(); - - sok->m_toHandler->resetTimeOut(); - } - } - } - else - { - const ssize_t n = static_cast - (sok->m_wrapped->receiveRaw - (reinterpret_cast (data), len)); - - if (n == 0 && sok->m_wrapped->getStatus() & socket::STATUS_WOULDBLOCK) - return GNUTLS_E_AGAIN; - - return n; - } - } - catch (exception& e) - { - // Workaround for bad behaviour when throwing C++ exceptions - // from C functions (GNU TLS) - sok->m_ex = e.clone(); - return -1; - } -} - - -shared_ptr TLSSocket_GnuTLS::getPeerCertificates() const -{ - unsigned int certCount = 0; - const gnutls_datum* rawData = gnutls_certificate_get_peers - (*m_session->m_gnutlsSession, &certCount); - - if (rawData == NULL) - return null; - - // Try X.509 - gnutls_x509_crt* x509Certs = new gnutls_x509_crt[certCount]; - - 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); - - if (res < 0) - { - // XXX more fine-grained error reporting? - delete [] x509Certs; - return null; - } - } - - { - std::vector > certs; - bool error = false; - - for (unsigned int i = 0 ; i < certCount ; ++i) - { - size_t dataSize = 0; - - gnutls_x509_crt_export(x509Certs[i], - GNUTLS_X509_FMT_DER, NULL, &dataSize); - - std::vector data(dataSize); - - gnutls_x509_crt_export(x509Certs[i], - GNUTLS_X509_FMT_DER, &data[0], &dataSize); - - shared_ptr cert = - security::cert::X509Certificate::import(&data[0], dataSize); - - if (cert != NULL) - certs.push_back(cert); - else - error = true; - - gnutls_x509_crt_deinit(x509Certs[i]); - } - - delete [] x509Certs; - - if (error) - return null; - - return make_shared (certs); - } - - delete [] x509Certs; - - return null; -} - - -// Following is a workaround for C++ exceptions to pass correctly between -// C and C++ calls. -// -// gnutls_record_recv() calls TLSSocket::gnutlsPullFunc, and exceptions -// thrown by the socket can not be caught. - -#ifndef VMIME_BUILDING_DOC - -class TLSSocket_DeleteExWrapper : public object -{ -public: - - TLSSocket_DeleteExWrapper(exception* ex) : m_ex(ex) { } - ~TLSSocket_DeleteExWrapper() { delete m_ex; } - -private: - - exception* m_ex; -}; - -#endif // VMIME_BUILDING_DOC - - -void TLSSocket_GnuTLS::internalThrow() -{ - static std::vector > exToDelete; - - if (m_ex) - { - // Reset the current exception pointer to prevent the same - // exception from being thrown again later - exception* ex = m_ex; - m_ex = NULL; - - // To avoid memory leaks - exToDelete.push_back(make_shared (ex)); - - throw *ex; - } -} - - -} // tls -} // net -} // vmime - - -#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_TLS_SUPPORT && VMIME_TLS_SUPPORT_LIB_IS_GNUTLS diff --git a/src/net/tls/openssl/OpenSSLInitializer.cpp b/src/net/tls/openssl/OpenSSLInitializer.cpp deleted file mode 100644 index 1bbb9ee5..00000000 --- a/src/net/tls/openssl/OpenSSLInitializer.cpp +++ /dev/null @@ -1,142 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// 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 && VMIME_HAVE_TLS_SUPPORT && VMIME_TLS_SUPPORT_LIB_IS_OPENSSL - - -#include "vmime/net/tls/openssl/OpenSSLInitializer.hpp" - -#include "vmime/utility/sync/autoLock.hpp" -#include "vmime/utility/sync/criticalSection.hpp" - -#include "vmime/platform.hpp" - -#include -#include -#include -#include - -#if OPENSSL_VERSION_NUMBER >= 0x0907000L -# include -#endif - - -namespace vmime { -namespace net { -namespace tls { - - -shared_ptr * OpenSSLInitializer::sm_mutexes; - - -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::oneTimeInitializer::oneTimeInitializer() -{ - initialize(); -} - - -OpenSSLInitializer::oneTimeInitializer::~oneTimeInitializer() -{ - uninitialize(); -} - - -// static -void OpenSSLInitializer::initialize() -{ -#if OPENSSL_VERSION_NUMBER >= 0x0907000L - OPENSSL_config(NULL); -#endif - - SSL_load_error_strings(); - SSL_library_init(); - OpenSSL_add_all_algorithms(); - - unsigned char seed[SEEDSIZE]; - vmime::platform::getHandler()->generateRandomBytes(seed, SEEDSIZE); - RAND_seed(seed, SEEDSIZE); - - int numMutexes = CRYPTO_num_locks(); - sm_mutexes = new shared_ptr [numMutexes]; - - 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); -} - - -// static -void OpenSSLInitializer::uninitialize() -{ - EVP_cleanup(); - ERR_free_strings(); - - CRYPTO_set_locking_callback(NULL); - CRYPTO_set_id_callback(NULL); - - delete [] sm_mutexes; -} - - -// static -void OpenSSLInitializer::lock(int mode, int n, const char* /* file */, int /* line */) -{ - if (mode & CRYPTO_LOCK) - sm_mutexes[n]->lock(); - else - sm_mutexes[n]->unlock(); -} - - -// static -unsigned long OpenSSLInitializer::id() -{ - return vmime::platform::getHandler()->getThreadId(); -} - - -} // tls -} // net -} // vmime - - -#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_TLS_SUPPORT && VMIME_TLS_SUPPORT_LIB_IS_OPENSSL - diff --git a/src/net/tls/openssl/TLSProperties_OpenSSL.cpp b/src/net/tls/openssl/TLSProperties_OpenSSL.cpp deleted file mode 100644 index 932477df..00000000 --- a/src/net/tls/openssl/TLSProperties_OpenSSL.cpp +++ /dev/null @@ -1,112 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// 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 && VMIME_HAVE_TLS_SUPPORT && VMIME_TLS_SUPPORT_LIB_IS_OPENSSL - - -#include "vmime/base.hpp" -#include "vmime/net/tls/openssl/TLSProperties_OpenSSL.hpp" - -#include -#include - - -namespace vmime { -namespace net { -namespace tls { - - -TLSProperties::TLSProperties() - : m_data(make_shared ()) -{ - setCipherSuite(CIPHERSUITE_DEFAULT); -} - - -TLSProperties::TLSProperties(const TLSProperties& props) - : object(), - m_data(make_shared ()) -{ - *dynamicCast (m_data) = *dynamicCast (props.m_data); -} - - -void TLSProperties::setCipherSuite(const GenericCipherSuite cipherSuite) -{ - switch (cipherSuite) - { - case CIPHERSUITE_HIGH: - - setCipherSuite("HIGH:!ADH:@STRENGTH"); - break; - - case CIPHERSUITE_MEDIUM: - - setCipherSuite("MEDIUM:!ADH:@STRENGTH"); - break; - - case CIPHERSUITE_LOW: - - setCipherSuite("LOW:!ADH:@STRENGTH"); - break; - - default: - case CIPHERSUITE_DEFAULT: - - setCipherSuite("DEFAULT:!ADH:@STRENGTH"); - break; - } -} - - -void TLSProperties::setCipherSuite(const string& cipherSuite) -{ - dynamicCast (m_data)->cipherSuite = cipherSuite; -} - - -const string TLSProperties::getCipherSuite() const -{ - return dynamicCast (m_data)->cipherSuite; -} - - - -TLSProperties_OpenSSL& TLSProperties_OpenSSL::operator=(const TLSProperties_OpenSSL& other) -{ - cipherSuite = other.cipherSuite; - - return *this; -} - - -} // tls -} // net -} // vmime - - -#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_TLS_SUPPORT && VMIME_TLS_SUPPORT_LIB_IS_OPENSSL - diff --git a/src/net/tls/openssl/TLSSession_OpenSSL.cpp b/src/net/tls/openssl/TLSSession_OpenSSL.cpp deleted file mode 100644 index cf600a63..00000000 --- a/src/net/tls/openssl/TLSSession_OpenSSL.cpp +++ /dev/null @@ -1,135 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// 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 && VMIME_HAVE_TLS_SUPPORT && VMIME_TLS_SUPPORT_LIB_IS_OPENSSL - - -#include "vmime/net/tls/openssl/TLSSession_OpenSSL.hpp" -#include "vmime/net/tls/openssl/TLSProperties_OpenSSL.hpp" -#include "vmime/net/tls/openssl/OpenSSLInitializer.hpp" - -#include "vmime/exception.hpp" - -#include -#include - - -namespace vmime { -namespace net { -namespace tls { - - -static OpenSSLInitializer::autoInitializer openSSLInitializer; - - -// static -shared_ptr TLSSession::create(shared_ptr cv, shared_ptr props) -{ - return make_shared (cv, props); -} - - -TLSSession_OpenSSL::TLSSession_OpenSSL(shared_ptr cv, shared_ptr 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); - SSL_CTX_set_cipher_list(m_sslctx, m_props->getCipherSuite().c_str()); - SSL_CTX_set_session_cache_mode(m_sslctx, SSL_SESS_CACHE_OFF); -} - - -TLSSession_OpenSSL::TLSSession_OpenSSL(const TLSSession_OpenSSL&) - : TLSSession() -{ - // Not used -} - - -TLSSession_OpenSSL::~TLSSession_OpenSSL() -{ - SSL_CTX_free(m_sslctx); -} - - -shared_ptr TLSSession_OpenSSL::getSocket(shared_ptr sok) -{ - return TLSSocket::wrap(dynamicCast (shared_from_this()), sok); -} - - -shared_ptr TLSSession_OpenSSL::getCertificateVerifier() -{ - return m_certVerifier; -} - - -void TLSSession_OpenSSL::usePrivateKeyFile(const vmime::string& keyfile) -{ - 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)); - vmime::string sslErr(buffer); - std::ostringstream oss; - oss << "Error loading private key from file " << keyfile; - oss << " - msg: " << sslErr; - throw exceptions::certificate_exception(oss.str()); - } -} - - -void TLSSession_OpenSSL::useCertificateChainFile(const vmime::string& chainFile) -{ - 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)); - vmime::string sslErr(buffer); - std::ostringstream oss; - oss << "Error loading certificate from file " << chainFile; - oss << " - msg: " << sslErr; - throw exceptions::certificate_exception(oss.str()); - } -} - - -SSL_CTX* TLSSession_OpenSSL::getContext() const -{ - return m_sslctx; -} - - -} // tls -} // net -} // vmime - - -#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_TLS_SUPPORT && VMIME_TLS_SUPPORT_LIB_IS_OPENSSL - diff --git a/src/net/tls/openssl/TLSSocket_OpenSSL.cpp b/src/net/tls/openssl/TLSSocket_OpenSSL.cpp deleted file mode 100644 index ef6647d6..00000000 --- a/src/net/tls/openssl/TLSSocket_OpenSSL.cpp +++ /dev/null @@ -1,601 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// 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 && VMIME_HAVE_TLS_SUPPORT && VMIME_TLS_SUPPORT_LIB_IS_OPENSSL - - -#include -#include - -#include "vmime/net/tls/openssl/TLSSocket_OpenSSL.hpp" -#include "vmime/net/tls/openssl/TLSSession_OpenSSL.hpp" -#include "vmime/net/tls/openssl/OpenSSLInitializer.hpp" - -#include "vmime/platform.hpp" - -#include "vmime/security/cert/openssl/X509Certificate_OpenSSL.hpp" - -#include "vmime/utility/stringUtils.hpp" - -#include -#include - - -namespace vmime { -namespace net { -namespace tls { - - -static OpenSSLInitializer::autoInitializer openSSLInitializer; - - -// static -BIO_METHOD TLSSocket_OpenSSL::sm_customBIOMethod = -{ - 100 | BIO_TYPE_SOURCE_SINK, - "vmime::socket glue", - TLSSocket_OpenSSL::bio_write, - TLSSocket_OpenSSL::bio_read, - TLSSocket_OpenSSL::bio_puts, - NULL, // gets - TLSSocket_OpenSSL::bio_ctrl, - TLSSocket_OpenSSL::bio_create, - TLSSocket_OpenSSL::bio_destroy, - 0 -}; - - -// static -shared_ptr TLSSocket::wrap(shared_ptr session, shared_ptr sok) -{ - return make_shared - (dynamicCast (session), sok); -} - - -TLSSocket_OpenSSL::TLSSocket_OpenSSL(shared_ptr session, shared_ptr sok) - : m_session(session), m_wrapped(sok), m_connected(false), m_ssl(0), m_status(0), m_ex(NULL) -{ -} - - -TLSSocket_OpenSSL::~TLSSocket_OpenSSL() -{ - try - { - disconnect(); - - if (m_ssl) - { - SSL_free(m_ssl); - m_ssl = 0; - } - } - catch (...) - { - // Don't throw in destructor - } -} - - -void TLSSocket_OpenSSL::createSSLHandle() -{ - if (m_wrapped->isConnected()) - { - BIO* sockBio = BIO_new(&sm_customBIOMethod); - sockBio->ptr = this; - sockBio->init = 1; - - m_ssl = SSL_new(m_session->getContext()); - - if (!m_ssl) - { - BIO_free(sockBio); - throw exceptions::tls_exception("Cannot create SSL object"); - } - - SSL_set_bio(m_ssl, sockBio, sockBio); - SSL_set_connect_state(m_ssl); - } - else - { - throw exceptions::tls_exception("Unconnected socket error"); - } -} - - -void TLSSocket_OpenSSL::connect(const string& address, const port_t port) -{ - m_wrapped->connect(address, port); - - createSSLHandle(); - - handshake(null); - - m_connected = true; -} - - -void TLSSocket_OpenSSL::disconnect() -{ - if (m_connected) - { - 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) - SSL_shutdown(m_ssl); - } - - m_wrapped->disconnect(); - m_connected = false; - } -} - - -bool TLSSocket_OpenSSL::isConnected() const -{ - return m_wrapped->isConnected() && m_connected; -} - - -size_t TLSSocket_OpenSSL::getBlockSize() const -{ - return 16384; // 16 KB -} - - -const string TLSSocket_OpenSSL::getPeerName() const -{ - return m_wrapped->getPeerName(); -} - - -const string TLSSocket_OpenSSL::getPeerAddress() const -{ - return m_wrapped->getPeerAddress(); -} - - -void TLSSocket_OpenSSL::receive(string& buffer) -{ - const size_t size = receiveRaw(m_buffer, sizeof(m_buffer)); - - if (size != 0) - buffer = utility::stringUtils::makeStringFromBytes(m_buffer, size); - else - buffer.clear(); -} - - -void TLSSocket_OpenSSL::send(const string& buffer) -{ - sendRaw(reinterpret_cast (buffer.data()), buffer.length()); -} - - -void TLSSocket_OpenSSL::send(const char* str) -{ - sendRaw(reinterpret_cast (str), ::strlen(str)); -} - - -size_t TLSSocket_OpenSSL::receiveRaw(byte_t* buffer, const size_t count) -{ - m_status &= ~STATUS_WOULDBLOCK; - - int rc = SSL_read(m_ssl, buffer, static_cast (count)); - - if (m_ex.get()) - internalThrow(); - - if (rc <= 0) - { - int error = SSL_get_error(m_ssl, rc); - - if (error == SSL_ERROR_WANT_WRITE || error == SSL_ERROR_WANT_READ) - { - m_status |= STATUS_WOULDBLOCK; - return 0; - } - - handleError(rc); - } - - return rc; -} - - -void TLSSocket_OpenSSL::sendRaw(const byte_t* buffer, const size_t count) -{ - sendRawNonBlocking(buffer, count); -} - - -size_t TLSSocket_OpenSSL::sendRawNonBlocking(const byte_t* buffer, const size_t count) -{ - m_status &= ~STATUS_WOULDBLOCK; - - int rc = SSL_write(m_ssl, buffer, static_cast (count)); - - if (m_ex.get()) - internalThrow(); - - if (rc <= 0) - { - int error = SSL_get_error(m_ssl, rc); - - if (error == SSL_ERROR_WANT_WRITE || error == SSL_ERROR_WANT_READ) - { - m_status |= STATUS_WOULDBLOCK; - return 0; - } - - handleError(rc); - } - - return rc; -} - - -void TLSSocket_OpenSSL::handshake(shared_ptr toHandler) -{ - if (toHandler) - toHandler->resetTimeOut(); - - // Start handshaking process - m_toHandler = toHandler; - - if (!m_ssl) - createSSLHandle(); - - try - { - int rc; - - while ((rc = SSL_do_handshake(m_ssl)) <= 0) - { - const int err = SSL_get_error(m_ssl, rc); - - if (err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE) - { - // No data available yet - platform::getHandler()->wait(); - } - else - { - handleError(rc); - } - - // Check whether the time-out delay is elapsed - if (m_toHandler && m_toHandler->isTimeOut()) - { - if (!m_toHandler->handleTimeOut()) - throw exceptions::operation_timed_out(); - - m_toHandler->resetTimeOut(); - } - } - } - catch (...) - { - SSL_free(m_ssl); - m_ssl = 0; - m_toHandler = null; - throw; - } - - m_toHandler = null; - - // Verify server's certificate(s) - shared_ptr certs = getPeerCertificates(); - - if (certs == NULL) - throw exceptions::tls_exception("No peer certificate."); - - m_session->getCertificateVerifier()->verify(certs, getPeerName()); - - m_connected = true; -} - - -shared_ptr TLSSocket_OpenSSL::getPeerCertificates() const -{ - STACK_OF(X509)* chain = SSL_get_peer_cert_chain(m_ssl); - - if (chain == NULL) - return null; - - int certCount = sk_X509_num(chain); - - if (certCount == 0) - return null; - - bool error = false; - std::vector > certs; - - for (int i = 0; i < certCount && !error; i++) - { - shared_ptr cert = - vmime::security::cert::X509Certificate_OpenSSL::importInternal(sk_X509_value(chain, i)); - - if (cert) - certs.push_back(cert); - else - error = true; - } - - if (error) - return null; - - return make_shared (certs); -} - - -void TLSSocket_OpenSSL::internalThrow() -{ - if (m_ex.get()) - throw *m_ex; -} - - -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: - return; - - case SSL_ERROR_SYSCALL: - { - if (lastError == 0) - { - if (rc == 0) - { - throw exceptions::tls_exception("SSL connection unexpectedly closed"); - } - else - { - vmime::string msg; - std::ostringstream oss(msg); - oss << "The BIO reported an error: " << rc; - oss.flush(); - throw exceptions::tls_exception(oss.str()); - } - } - break; - } - - case SSL_ERROR_WANT_READ: - - BIO_set_retry_read(SSL_get_rbio(m_ssl)); - break; - - case SSL_ERROR_WANT_WRITE: - - 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: - - 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); - } - - break; - } -} - - -unsigned int TLSSocket_OpenSSL::getStatus() const -{ - return m_status; -} - - -// Implementation of custom BIO methods - - -// static -int TLSSocket_OpenSSL::bio_write(BIO* bio, const char* buf, int len) -{ - BIO_clear_retry_flags(bio); - - if (buf == NULL || len <= 0) - return -1; - - TLSSocket_OpenSSL *sok = reinterpret_cast (bio->ptr); - - if (!bio->init || !sok) - return -1; - - try - { - const size_t n = sok->m_wrapped->sendRawNonBlocking - (reinterpret_cast (buf), len); - - if (n == 0 && sok->m_wrapped->getStatus() & socket::STATUS_WOULDBLOCK) - { - BIO_set_retry_write(bio); - return -1; - } - - return static_cast (len); - } - catch (exception& e) - { - // Workaround for passing C++ exceptions from C BIO functions - sok->m_ex.reset(e.clone()); - return -1; - } -} - - -// static -int TLSSocket_OpenSSL::bio_read(BIO* bio, char* buf, int len) -{ - BIO_clear_retry_flags(bio); - - if (buf == NULL || len <= 0) - return -1; - - TLSSocket_OpenSSL *sok = reinterpret_cast (bio->ptr); - - if (!bio->init || !sok) - return -1; - - try - { - const size_t n = sok->m_wrapped->receiveRaw - (reinterpret_cast (buf), len); - - if (n == 0 || sok->m_wrapped->getStatus() & socket::STATUS_WOULDBLOCK) - { - BIO_set_retry_read(bio); - return -1; - } - - return static_cast (n); - } - catch (exception& e) - { - // Workaround for passing C++ exceptions from C BIO functions - sok->m_ex.reset(e.clone()); - return -1; - } -} - - -// static -int TLSSocket_OpenSSL::bio_puts(BIO* bio, const char* str) -{ - return bio_write(bio, str, static_cast (strlen(str))); -} - - -// static -long TLSSocket_OpenSSL::bio_ctrl(BIO* bio, int cmd, long num, void* ptr) -{ - long ret = 1; - - switch (cmd) - { - case BIO_CTRL_INFO: - - ret = 0; - break; - - case BIO_CTRL_GET_CLOSE: - - ret = bio->shutdown; - break; - - case BIO_CTRL_SET_CLOSE: - - bio->shutdown = static_cast (num); - break; - - case BIO_CTRL_PENDING: - case BIO_CTRL_WPENDING: - - ret = 0; - break; - - case BIO_CTRL_DUP: - case BIO_CTRL_FLUSH: - - ret = 1; - break; - - default: - - ret = 0; - break; - } - - return ret; -} - - -// static -int TLSSocket_OpenSSL::bio_create(BIO* bio) -{ - bio->init = 0; - bio->num = 0; - bio->ptr = NULL; - bio->flags = 0; - - return 1; -} - - -// static -int TLSSocket_OpenSSL::bio_destroy(BIO* bio) -{ - if (bio == NULL) - return 0; - - if (bio->shutdown) - { - bio->ptr = NULL; - bio->init = 0; - bio->flags = 0; - } - - return 1; -} - - -} // tls -} // net -} // vmime - - -#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_TLS_SUPPORT && VMIME_TLS_SUPPORT_LIB_IS_OPENSSL diff --git a/src/net/transport.cpp b/src/net/transport.cpp deleted file mode 100644 index dd7281d0..00000000 --- a/src/net/transport.cpp +++ /dev/null @@ -1,236 +0,0 @@ -// -// VMime library (http://www.vmime.org) -// Copyright (C) 2002-2013 Vincent Richard -// -// 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/transport.hpp" - -#include "vmime/utility/stream.hpp" -#include "vmime/mailboxList.hpp" -#include "vmime/message.hpp" -#include "vmime/dateTime.hpp" -#include "vmime/messageId.hpp" - -#include "vmime/utility/outputStreamAdapter.hpp" -#include "vmime/utility/inputStreamStringAdapter.hpp" - - -namespace vmime { -namespace net { - - -transport::transport(shared_ptr sess, const serviceInfos& infos, shared_ptr auth) - : service(sess, infos, auth) -{ -} - - -shared_ptr transport::processHeaderField(shared_ptr 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)) - { - // 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)) - { - // RFC-2298: Delivering MTA may add the Original-Recipient header and - // discard existing one; so, no need to send it. - return null; - } - - // Leave the header field as is - return field; -} - - -void transport::processHeader(shared_ptr
header) -{ - if (header->getFieldCount() == 0) - return; - - // Remove/replace fields - for (size_t idx = header->getFieldCount() ; idx != 0 ; --idx) - { - shared_ptr field = header->getFieldAt(idx - 1); - shared_ptr newField = processHeaderField(field); - - if (newField == NULL) - header->removeField(field); - else if (newField != field) - header->replaceField(field, newField); - } - - // Add missing header fields - // -- Date - if (!header->hasField(fields::DATE)) - header->Date()->setValue(datetime::now()); - - // -- Mime-Version - if (!header->hasField(fields::MIME_VERSION)) - header->MimeVersion()->setValue(string(SUPPORTED_MIME_VERSION)); - - // -- 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) - { - shared_ptr mbox = dynamicCast (list.getAddressAt(i)->clone()); - - if (mbox != NULL) - recipients.appendMailbox(mbox); - } -} - - -void transport::send(shared_ptr msg, utility::progressListener* progress) -{ - // Extract expeditor - shared_ptr fromMbox = - msg->getHeader()->findFieldValue (fields::FROM); - - if (!fromMbox) - throw exceptions::no_expeditor(); - - mailbox expeditor = *fromMbox; - - // Extract sender - shared_ptr senderMbox = - msg->getHeader()->findFieldValue (fields::SENDER); - - mailbox sender; - - if (!senderMbox) - sender = expeditor; - else - sender = *senderMbox; - - // Extract recipients - mailboxList recipients; - - // -- "To" field - shared_ptr addresses = - msg->getHeader()->findFieldValue (fields::TO); - - if (addresses) - extractMailboxes(recipients, *addresses); - - // -- "Cc" field - addresses = - msg->getHeader()->findFieldValue (fields::CC); - - if (addresses) - extractMailboxes(recipients, *addresses); - - // -- "Bcc" field - addresses = - msg->getHeader()->findFieldValue (fields::BCC); - - 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 - // which are required/recommended by the RFCs. - shared_ptr
hdr = vmime::clone(msg->getHeader()); - processHeader(hdr); - - // 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 _msg, - shared_ptr _hdr) - : msg(_msg), hdr(msg->getHeader()) - { - // Set new header - msg->setHeader(_hdr); - } - - ~XChangeMsgHeader() - { - // Revert original header - msg->setHeader(hdr); - } - - private: - - shared_ptr msg; - shared_ptr hdr; - } headerExchanger(msg, hdr); - - send(msg, expeditor, recipients, progress, sender); -} - - -void transport::send - (shared_ptr 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; - utility::outputStreamAdapter ossAdapter(oss); - - msg->generate(ossAdapter); - - const string& str(oss.str()); - - utility::inputStreamStringAdapter isAdapter(str); - - send(expeditor, recipients, isAdapter, str.length(), progress, sender); -} - - -transport::Type transport::getType() const -{ - return (TYPE_TRANSPORT); -} - - -} // net -} // vmime - - -#endif // VMIME_HAVE_MESSAGING_FEATURES - -- cgit