aboutsummaryrefslogtreecommitdiffstats
path: root/src/net/imap
diff options
context:
space:
mode:
authorVincent Richard <[email protected]>2013-12-29 10:02:12 +0100
committerVincent Richard <[email protected]>2013-12-29 10:02:12 +0100
commit152c6bed75598a6ca5efb7914701157270155833 (patch)
tree8faced1d75a45c819630323da256248415992ed0 /src/net/imap
parentMerge branch 'master' of https://github.com/kisli/vmime (diff)
downloadvmime-152c6bed75598a6ca5efb7914701157270155833.tar.gz
vmime-152c6bed75598a6ca5efb7914701157270155833.zip
Merged source and header files in directory structure. Got rid of SConstruct build.
Diffstat (limited to 'src/net/imap')
-rw-r--r--src/net/imap/IMAPConnection.cpp814
-rw-r--r--src/net/imap/IMAPFolder.cpp1511
-rw-r--r--src/net/imap/IMAPFolderStatus.cpp307
-rw-r--r--src/net/imap/IMAPMessage.cpp649
-rw-r--r--src/net/imap/IMAPMessagePart.cpp161
-rw-r--r--src/net/imap/IMAPMessagePartContentHandler.cpp216
-rw-r--r--src/net/imap/IMAPMessageStructure.cpp94
-rw-r--r--src/net/imap/IMAPSStore.cpp79
-rw-r--r--src/net/imap/IMAPServiceInfos.cpp137
-rw-r--r--src/net/imap/IMAPStore.cpp267
-rw-r--r--src/net/imap/IMAPTag.cpp122
-rw-r--r--src/net/imap/IMAPUtils.cpp758
12 files changed, 0 insertions, 5115 deletions
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 <[email protected]>
-//
-// This program is free software; you can redistribute it and/or
-// modify it under the terms of the GNU General Public License as
-// published by the Free Software Foundation; either version 3 of
-// the License, or (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-// General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License along
-// with this program; if not, write to the Free Software Foundation, Inc.,
-// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
-//
-// Linking this library statically or dynamically with other modules is making
-// a combined work based on this library. Thus, the terms and conditions of
-// the GNU General Public License cover the whole combination.
-//
-
-#include "vmime/config.hpp"
-
-
-#if VMIME_HAVE_MESSAGING_FEATURES && 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 <sstream>
-
-
-// Helpers for service properties
-#define GET_PROPERTY(type, prop) \
- (m_store.lock()->getInfos().getPropertyValue <type>(getSession(), \
- dynamic_cast <const IMAPServiceInfos&>(m_store.lock()->getInfos()).getProperties().prop))
-#define HAS_PROPERTY(prop) \
- (m_store.lock()->getInfos().hasProperty(getSession(), \
- dynamic_cast <const IMAPServiceInfos&>(m_store.lock()->getInfos()).getProperties().prop))
-
-
-namespace vmime {
-namespace net {
-namespace imap {
-
-
-IMAPConnection::IMAPConnection(shared_ptr <IMAPStore> store, shared_ptr <security::authenticator> auth)
- : m_store(store), m_auth(auth), m_socket(null), m_parser(null), m_tag(null),
- m_hierarchySeparator('\0'), m_state(STATE_NONE), m_timeoutHandler(null),
- m_secured(false), m_firstTag(true), m_capabilitiesFetched(false), m_noModSeq(false)
-{
-}
-
-
-IMAPConnection::~IMAPConnection()
-{
- 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 <IMAPStore> 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 <tls::TLSSession> tlsSession = tls::TLSSession::create
- (store->getCertificateVerifier(),
- store->getSession()->getTLSProperties());
-
- shared_ptr <tls::TLSSocket> tlsSocket =
- tlsSession->getSocket(m_socket);
-
- m_socket = tlsSocket;
-
- m_secured = true;
- m_cntInfos = make_shared <tls::TLSSecuredConnectionInfos>(address, port, tlsSession, tlsSocket);
- }
- else
-#endif // VMIME_HAVE_TLS_SUPPORT
- {
- m_cntInfos = make_shared <defaultConnectionInfos>(address, port);
- }
-
- m_socket->connect(address, port);
-
-
- m_tag = make_shared <IMAPTag>();
- m_parser = make_shared <IMAPParser>(m_tag, m_socket, m_timeoutHandler);
-
-
- setState(STATE_NON_AUTHENTICATED);
-
-
- // Connection greeting
- //
- // eg: C: <connection to server>
- // --- S: * OK mydomain.org IMAP4rev1 v12.256 server ready
-
- std::auto_ptr <IMAPParser::greeting> 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 <IMAPParser::response> 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 <security::sasl::SASLAuthenticator>(getAuthenticator()))
- throw exceptions::authentication_error("No SASL authenticator available.");
-
- const std::vector <string> capa = getCapabilities();
- std::vector <string> saslMechs;
-
- for (unsigned int i = 0 ; i < capa.size() ; ++i)
- {
- 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 <shared_ptr <security::sasl::SASLMechanism> > mechList;
-
- shared_ptr <security::sasl::SASLContext> saslContext =
- make_shared <security::sasl::SASLContext>();
-
- 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 <security::sasl::SASLMechanism> 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 <security::sasl::SASLAuthenticator>(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 <security::sasl::SASLMechanism> mech = mechList[i];
-
- shared_ptr <security::sasl::SASLSession> saslSession =
- saslContext->createSession("imap", getAuthenticator(), mech);
-
- saslSession->init();
-
- send(true, "AUTHENTICATE " + mech->getName(), true);
-
- for (bool cont = true ; cont ; )
- {
- std::auto_ptr <IMAPParser::response> resp(m_parser->readResponse());
-
- if (resp->response_done() &&
- resp->response_done()->response_tagged() &&
- resp->response_done()->response_tagged()->resp_cond_state()->
- status() == IMAPParser::resp_cond_state::OK)
- {
- m_socket = saslSession->getSecuredSocket(m_socket);
- return;
- }
- else
- {
- std::vector <IMAPParser::continue_req_or_response_data*>
- respDataList = resp->continue_req_or_response_data();
-
- string response;
- bool hasResponse = false;
-
- for (unsigned int i = 0 ; i < respDataList.size() ; ++i)
- {
- if (respDataList[i]->continue_req())
- {
- 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 <IMAPParser::response> resp(m_parser->readResponse());
-
- if (resp->isBad() || resp->response_done()->response_tagged()->
- resp_cond_state()->status() != IMAPParser::resp_cond_state::OK)
- {
- throw exceptions::command_error
- ("STARTTLS", resp->getErrorLog(), "bad response");
- }
-
- shared_ptr <tls::TLSSession> tlsSession = tls::TLSSession::create
- (m_store.lock()->getCertificateVerifier(),
- m_store.lock()->getSession()->getTLSProperties());
-
- shared_ptr <tls::TLSSocket> tlsSocket =
- tlsSession->getSocket(m_socket);
-
- tlsSocket->handshake(m_timeoutHandler);
-
- m_socket = tlsSocket;
- m_parser->setSocket(m_socket);
-
- m_secured = true;
- m_cntInfos = make_shared <tls::TLSSecuredConnectionInfos>
- (m_cntInfos->getHost(), m_cntInfos->getPort(), tlsSession, tlsSocket);
-
- // " Once TLS has been started, the client MUST discard cached
- // information about server capabilities and SHOULD re-issue the
- // 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 <string> 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 <IMAPParser::response> 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 <IMAPParser::continue_req_or_response_data*>& respDataList =
- resp->continue_req_or_response_data();
-
- for (size_t i = 0 ; i < respDataList.size() ; ++i)
- {
- if (respDataList[i]->response_data() == NULL)
- 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 <string> res;
-
- std::vector <IMAPParser::capability*> 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 <security::authenticator> IMAPConnection::getAuthenticator()
-{
- return m_auth;
-}
-
-
-bool IMAPConnection::isConnected() const
-{
- return (m_socket && m_socket->isConnected() &&
- (m_state == STATE_AUTHENTICATED || m_state == STATE_SELECTED));
-}
-
-
-bool IMAPConnection::isSecuredConnection() const
-{
- return m_secured;
-}
-
-
-shared_ptr <connectionInfos> 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 <IMAPParser::response> 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 <IMAPParser::continue_req_or_response_data*>& 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 <const IMAPParser::response_data*>
- (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 <const IMAPStore> IMAPConnection::getStore() const
-{
- return m_store.lock();
-}
-
-
-shared_ptr <IMAPStore> IMAPConnection::getStore()
-{
- return m_store.lock();
-}
-
-
-shared_ptr <session> IMAPConnection::getSession()
-{
- return m_store.lock()->getSession();
-}
-
-
-shared_ptr <const socket> 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 <[email protected]>
-//
-// This program is free software; you can redistribute it and/or
-// modify it under the terms of the GNU General Public License as
-// published by the Free Software Foundation; either version 3 of
-// the License, or (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-// General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License along
-// with this program; if not, write to the Free Software Foundation, Inc.,
-// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
-//
-// Linking this library statically or dynamically with other modules is making
-// a combined work based on this library. Thus, the terms and conditions of
-// the GNU General Public License cover the whole combination.
-//
-
-#include "vmime/config.hpp"
-
-
-#if VMIME_HAVE_MESSAGING_FEATURES && 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 <algorithm>
-#include <sstream>
-
-
-namespace vmime {
-namespace net {
-namespace imap {
-
-
-IMAPFolder::IMAPFolder(const folder::path& path, shared_ptr <IMAPStore> 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 <IMAPFolderStatus>();
-}
-
-
-IMAPFolder::~IMAPFolder()
-{
- shared_ptr <IMAPStore> 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 <IMAPStore> 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 <IMAPFolder*>::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 <IMAPConnection> connection =
- make_shared <IMAPConnection>(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 <IMAPParser::response> resp(connection->readResponse());
-
- if (resp->isBad() || resp->response_done()->response_tagged()->
- resp_cond_state()->status() != IMAPParser::resp_cond_state::OK)
- {
- throw exceptions::command_error("SELECT",
- resp->getErrorLog(), "bad response");
- }
-
- const std::vector <IMAPParser::continue_req_or_response_data*>& respDataList =
- resp->continue_req_or_response_data();
-
- for (std::vector <IMAPParser::continue_req_or_response_data*>::const_iterator
- it = respDataList.begin() ; it != respDataList.end() ; ++it)
- {
- if ((*it)->response_data() == NULL)
- {
- throw exceptions::command_error("SELECT",
- resp->getErrorLog(), "invalid response");
- }
-
- 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 <IMAPStore> store = m_store.lock();
-
- if (!store)
- throw exceptions::illegal_state("Store disconnected");
-
- if (!isOpen())
- throw exceptions::illegal_state("Folder not open");
-
- shared_ptr <IMAPConnection> oldConnection = m_connection;
-
- // Emit the "CLOSE" command to expunge messages marked
- // as deleted (this is fastest than "EXPUNGE")
- if (expunge)
- {
- if (m_mode == MODE_READ_ONLY)
- 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 <IMAPFolderStatus>();
-
- onClose();
-}
-
-
-void IMAPFolder::onClose()
-{
- for (std::vector <IMAPMessage*>::iterator it = m_messages.begin() ;
- it != m_messages.end() ; ++it)
- {
- (*it)->onFolderClosed();
- }
-
- m_messages.clear();
-}
-
-
-void IMAPFolder::create(const int type)
-{
- shared_ptr <IMAPStore> 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 <IMAPParser::response> resp(m_connection->readResponse());
-
- if (resp->isBad() || resp->response_done()->response_tagged()->
- resp_cond_state()->status() != IMAPParser::resp_cond_state::OK)
- {
- throw exceptions::command_error("CREATE",
- resp->getErrorLog(), "bad response");
- }
-
- // Notify folder created
- shared_ptr <events::folderEvent> event =
- make_shared <events::folderEvent>
- (dynamicCast <folder>(shared_from_this()),
- events::folderEvent::TYPE_CREATED, m_path, m_path);
-
- notifyFolder(event);
-}
-
-
-void IMAPFolder::destroy()
-{
- shared_ptr <IMAPStore> 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 <IMAPParser::response> resp(m_connection->readResponse());
-
- if (resp->isBad() || resp->response_done()->response_tagged()->
- resp_cond_state()->status() != IMAPParser::resp_cond_state::OK)
- {
- throw exceptions::command_error("DELETE",
- resp->getErrorLog(), "bad response");
- }
-
- // Notify folder deleted
- shared_ptr <events::folderEvent> event =
- make_shared <events::folderEvent>
- (dynamicCast <folder>(shared_from_this()),
- events::folderEvent::TYPE_DELETED, m_path, m_path);
-
- notifyFolder(event);
-}
-
-
-bool IMAPFolder::exists()
-{
- shared_ptr <IMAPStore> 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 <IMAPParser::response> resp(m_connection->readResponse());
-
- if (resp->isBad() || resp->response_done()->response_tagged()->
- resp_cond_state()->status() != IMAPParser::resp_cond_state::OK)
- {
- throw exceptions::command_error("LIST",
- resp->getErrorLog(), "bad response");
- }
-
- // Check whether the result mailbox list contains this folder
- const std::vector <IMAPParser::continue_req_or_response_data*>& respDataList =
- resp->continue_req_or_response_data();
-
- for (std::vector <IMAPParser::continue_req_or_response_data*>::const_iterator
- it = respDataList.begin() ; it != respDataList.end() ; ++it)
- {
- if ((*it)->response_data() == NULL)
- {
- throw exceptions::command_error("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 <message> 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 <IMAPMessage>(dynamicCast <IMAPFolder>(shared_from_this()), num);
-}
-
-
-std::vector <shared_ptr <message> > IMAPFolder::getMessages(const messageSet& msgs)
-{
- if (!isOpen())
- throw exceptions::illegal_state("Folder not open");
-
- if (msgs.isEmpty())
- return std::vector <shared_ptr <message> >();
-
- std::vector <shared_ptr <message> > messages;
-
- if (msgs.isNumberSet())
- {
- const std::vector <int> numbers = IMAPUtils::messageSetToNumberList(msgs);
-
- shared_ptr <IMAPFolder> thisFolder = dynamicCast <IMAPFolder>(shared_from_this());
-
- for (std::vector <int>::const_iterator it = numbers.begin() ; it != numbers.end() ; ++it)
- messages.push_back(make_shared <IMAPMessage>(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 <IMAPParser::response> resp(m_connection->readResponse());
-
- if (resp->isBad() || resp->response_done()->response_tagged()->
- resp_cond_state()->status() != IMAPParser::resp_cond_state::OK)
- {
- throw exceptions::command_error("UID FETCH ... UID", resp->getErrorLog(), "bad response");
- }
-
- // Process the response
- const std::vector <IMAPParser::continue_req_or_response_data*>& respDataList =
- resp->continue_req_or_response_data();
-
- for (std::vector <IMAPParser::continue_req_or_response_data*>::const_iterator
- it = respDataList.begin() ; it != respDataList.end() ; ++it)
- {
- if ((*it)->response_data() == NULL)
- {
- throw exceptions::command_error("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 <int>(messageData->number());
- message::uid msgUID;
-
- // Find UID in message attributes
- const std::vector <IMAPParser::msg_att_item*> atts = messageData->msg_att()->items();
-
- for (std::vector <IMAPParser::msg_att_item*>::const_iterator
- it = atts.begin() ; it != atts.end() ; ++it)
- {
- if ((*it)->type() == IMAPParser::msg_att_item::UID)
- {
- msgUID = (*it)->unique_id()->value();
- break;
- }
- }
-
- if (!msgUID.empty())
- {
- shared_ptr <IMAPFolder> thisFolder = dynamicCast <IMAPFolder>(shared_from_this());
- messages.push_back(make_shared <IMAPMessage>(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 <folder> IMAPFolder::getFolder(const folder::path::component& name)
-{
- shared_ptr <IMAPStore> store = m_store.lock();
-
- if (!store)
- throw exceptions::illegal_state("Store disconnected");
-
- return make_shared <IMAPFolder>(m_path / name, store);
-}
-
-
-std::vector <shared_ptr <folder> > IMAPFolder::getFolders(const bool recursive)
-{
- shared_ptr <IMAPStore> 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 <IMAPParser::response> resp(m_connection->readResponse());
-
- if (resp->isBad() || resp->response_done()->response_tagged()->
- resp_cond_state()->status() != IMAPParser::resp_cond_state::OK)
- {
- throw exceptions::command_error("LIST", resp->getErrorLog(), "bad response");
- }
-
- const std::vector <IMAPParser::continue_req_or_response_data*>& respDataList =
- resp->continue_req_or_response_data();
-
-
- std::vector <shared_ptr <folder> > v;
-
- for (std::vector <IMAPParser::continue_req_or_response_data*>::const_iterator
- it = respDataList.begin() ; it != respDataList.end() ; ++it)
- {
- if ((*it)->response_data() == NULL)
- {
- throw exceptions::command_error("LIST",
- resp->getErrorLog(), "invalid response");
- }
-
- 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 <IMAPFolder>(path, store,
- IMAPUtils::folderTypeFromFlags(mailbox_flag_list),
- IMAPUtils::folderFlagsFromFlags(mailbox_flag_list)));
- }
- }
-
- return (v);
-}
-
-
-void IMAPFolder::fetchMessages(std::vector <shared_ptr <message> >& msg, const fetchAttributes& options,
- utility::progressListener* progress)
-{
- shared_ptr <IMAPStore> 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 <int> list;
- list.reserve(msg.size());
-
- std::map <int, shared_ptr <IMAPMessage> > numberToMsg;
-
- for (std::vector <shared_ptr <message> >::iterator it = msg.begin() ; it != msg.end() ; ++it)
- {
- list.push_back((*it)->getNumber());
- numberToMsg[(*it)->getNumber()] = dynamicCast <IMAPMessage>(*it);
- }
-
- // Send the request
- const string command = IMAPUtils::buildFetchRequest
- (m_connection, messageSet::byNumber(list), options);
-
- m_connection->send(true, command, true);
-
- // Get the response
- std::auto_ptr <IMAPParser::response> resp(m_connection->readResponse());
-
- if (resp->isBad() || resp->response_done()->response_tagged()->
- resp_cond_state()->status() != IMAPParser::resp_cond_state::OK)
- {
- throw exceptions::command_error("FETCH",
- resp->getErrorLog(), "bad response");
- }
-
- const std::vector <IMAPParser::continue_req_or_response_data*>& 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 <IMAPParser::continue_req_or_response_data*>::const_iterator
- it = respDataList.begin() ; it != respDataList.end() ; ++it)
- {
- if ((*it)->response_data() == NULL)
- {
- throw exceptions::command_error("FETCH",
- resp->getErrorLog(), "invalid response");
- }
-
- 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 <int>(messageData->number());
-
- std::map <int, shared_ptr <IMAPMessage> >::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 <message> msg, const fetchAttributes& options)
-{
- std::vector <shared_ptr <message> > 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 <folder> IMAPFolder::getParent()
-{
- if (m_path.isEmpty())
- return null;
- else
- return make_shared <IMAPFolder>(m_path.getParent(), m_store.lock());
-}
-
-
-shared_ptr <const store> IMAPFolder::getStore() const
-{
- return m_store.lock();
-}
-
-
-shared_ptr <store> IMAPFolder::getStore()
-{
- return m_store.lock();
-}
-
-
-void IMAPFolder::registerMessage(IMAPMessage* msg)
-{
- m_messages.push_back(msg);
-}
-
-
-void IMAPFolder::unregisterMessage(IMAPMessage* msg)
-{
- std::vector <IMAPMessage*>::iterator it =
- std::find(m_messages.begin(), m_messages.end(), msg);
-
- if (it != m_messages.end())
- m_messages.erase(it);
-}
-
-
-void IMAPFolder::onStoreDisconnected()
-{
- m_store.reset();
-}
-
-
-void IMAPFolder::deleteMessages(const messageSet& msgs)
-{
- shared_ptr <IMAPStore> 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 <IMAPParser::response> resp(m_connection->readResponse());
-
- if (resp->isBad() || resp->response_done()->response_tagged()->
- resp_cond_state()->status() != IMAPParser::resp_cond_state::OK)
- {
- throw exceptions::command_error("STORE",
- resp->getErrorLog(), "bad response");
- }
-
- 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 <IMAPParser::response> resp(m_connection->readResponse());
-
- if (resp->isBad() || resp->response_done()->response_tagged()->
- resp_cond_state()->status() != IMAPParser::resp_cond_state::OK)
- {
- throw exceptions::command_error("STORE",
- resp->getErrorLog(), "bad response");
- }
-
- processStatusUpdate(resp.get());
- }
-}
-
-
-void IMAPFolder::addMessage(shared_ptr <vmime::message> 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 <IMAPStore> 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 <IMAPParser::response> resp(m_connection->readResponse());
-
- bool ok = false;
- const std::vector <IMAPParser::continue_req_or_response_data*>& respList
- = resp->continue_req_or_response_data();
-
- for (std::vector <IMAPParser::continue_req_or_response_data*>::const_iterator
- it = respList.begin() ; !ok && (it != respList.end()) ; ++it)
- {
- if ((*it)->continue_req())
- 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 <size_t>(m_connection->getSocket()->getBlockSize()));
-
- std::vector <byte_t> 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 <IMAPParser::response> finalResp(m_connection->readResponse());
-
- if (finalResp->isBad() || finalResp->response_done()->response_tagged()->
- resp_cond_state()->status() != IMAPParser::resp_cond_state::OK)
- {
- throw exceptions::command_error("APPEND",
- resp->getErrorLog(), "bad response");
- }
-
- processStatusUpdate(resp.get());
-}
-
-
-void IMAPFolder::expunge()
-{
- shared_ptr <IMAPStore> 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 <IMAPParser::response> resp(m_connection->readResponse());
-
- if (resp->isBad() || resp->response_done()->response_tagged()->
- resp_cond_state()->status() != IMAPParser::resp_cond_state::OK)
- {
- throw exceptions::command_error("EXPUNGE",
- resp->getErrorLog(), "bad response");
- }
-
- processStatusUpdate(resp.get());
-}
-
-
-void IMAPFolder::rename(const folder::path& newPath)
-{
- shared_ptr <IMAPStore> 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 <IMAPParser::response> resp(m_connection->readResponse());
-
- if (resp->isBad() || resp->response_done()->response_tagged()->
- resp_cond_state()->status() != IMAPParser::resp_cond_state::OK)
- {
- throw exceptions::command_error("RENAME",
- resp->getErrorLog(), "bad response");
- }
-
- // Notify folder renamed
- folder::path oldPath(m_path);
-
- m_path = newPath;
- m_name = newPath.getLastComponent();
-
- shared_ptr <events::folderEvent> event =
- make_shared <events::folderEvent>
- (dynamicCast <folder>(shared_from_this()),
- events::folderEvent::TYPE_RENAMED, oldPath, newPath);
-
- notifyFolder(event);
-
- // Notify sub-folders
- for (std::list <IMAPFolder*>::iterator it = store->m_folders.begin() ;
- it != store->m_folders.end() ; ++it)
- {
- if ((*it) != this && oldPath.isParentOf((*it)->getFullPath()))
- {
- folder::path oldPath((*it)->m_path);
-
- (*it)->m_path.renameParent(oldPath, newPath);
-
- shared_ptr <events::folderEvent> event =
- make_shared <events::folderEvent>
- (dynamicCast <folder>((*it)->shared_from_this()),
- events::folderEvent::TYPE_RENAMED, oldPath, (*it)->m_path);
-
- (*it)->notifyFolder(event);
- }
- }
-
- processStatusUpdate(resp.get());
-}
-
-
-void IMAPFolder::copyMessages(const folder::path& dest, const messageSet& set)
-{
- shared_ptr <IMAPStore> 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 <IMAPParser::response> resp(m_connection->readResponse());
-
- if (resp->isBad() || resp->response_done()->response_tagged()->
- resp_cond_state()->status() != IMAPParser::resp_cond_state::OK)
- {
- throw exceptions::command_error("COPY",
- resp->getErrorLog(), "bad response");
- }
-
- processStatusUpdate(resp.get());
-}
-
-
-void IMAPFolder::status(int& count, int& unseen)
-{
- count = 0;
- unseen = 0;
-
- shared_ptr <folderStatus> status = getStatus();
-
- count = status->getMessageCount();
- unseen = status->getUnseenCount();
-}
-
-
-shared_ptr <folderStatus> IMAPFolder::getStatus()
-{
- shared_ptr <IMAPStore> 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 <IMAPParser::response> resp(m_connection->readResponse());
-
- if (resp->isBad() || resp->response_done()->response_tagged()->
- resp_cond_state()->status() != IMAPParser::resp_cond_state::OK)
- {
- throw exceptions::command_error("STATUS",
- resp->getErrorLog(), "bad response");
- }
-
- const std::vector <IMAPParser::continue_req_or_response_data*>& respDataList =
- resp->continue_req_or_response_data();
-
- for (std::vector <IMAPParser::continue_req_or_response_data*>::const_iterator
- it = respDataList.begin() ; it != respDataList.end() ; ++it)
- {
- if ((*it)->response_data() != NULL)
- {
- const IMAPParser::response_data* responseData = (*it)->response_data();
-
- if (responseData->mailbox_data() &&
- responseData->mailbox_data()->type() == IMAPParser::mailbox_data::STATUS)
- {
- shared_ptr <IMAPFolderStatus> status = make_shared <IMAPFolderStatus>();
- 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 <IMAPStore> store = m_store.lock();
-
- if (!store)
- throw exceptions::illegal_state("Store disconnected");
-
- m_connection->send(true, "NOOP", true);
-
- std::auto_ptr <IMAPParser::response> resp(m_connection->readResponse());
-
- if (resp->isBad() || resp->response_done()->response_tagged()->
- resp_cond_state()->status() != IMAPParser::resp_cond_state::OK)
- {
- throw exceptions::command_error("NOOP", resp->getErrorLog());
- }
-
- processStatusUpdate(resp.get());
-}
-
-
-std::vector <int> IMAPFolder::getMessageNumbersStartingOnUID(const message::uid& uid)
-{
- std::vector<int> 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 <IMAPParser::response> resp(m_connection->readResponse());
-
- if (resp->isBad() ||
- resp->response_done()->response_tagged()->resp_cond_state()->status() != IMAPParser::resp_cond_state::OK)
- {
- throw exceptions::command_error("SEARCH",
- resp->getErrorLog(), "bad response");
- }
-
- const std::vector <IMAPParser::continue_req_or_response_data*>& respDataList = resp->continue_req_or_response_data();
-
- for (std::vector <IMAPParser::continue_req_or_response_data*>::const_iterator
- it = respDataList.begin() ; it != respDataList.end() ; ++it)
- {
- if ((*it)->response_data() == NULL)
- {
- throw exceptions::command_error("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 <IMAPParser::nz_number*>::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 <shared_ptr <events::event> > events;
-
- shared_ptr <IMAPFolderStatus> 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 <IMAPParser::continue_req_or_response_data*>::const_iterator
- it = resp->continue_req_or_response_data().begin() ;
- it != resp->continue_req_or_response_data().end() ; ++it)
- {
- 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 <IMAPMessage*>::iterator mit =
- m_messages.begin() ; mit != m_messages.end() ; ++mit)
- {
- if ((*mit)->getNumber() == msgNumber)
- (*mit)->processFetchResponse(/* options */ 0, msgData);
- }
-
- events.push_back(make_shared <events::messageChangedEvent>
- (dynamicCast <folder>(shared_from_this()),
- events::messageChangedEvent::TYPE_FLAGS,
- std::vector <int>(1, msgNumber)));
- }
- else if ((*it)->response_data()->message_data()->type() == IMAPParser::message_data::EXPUNGE)
- {
- // A message has been expunged, renumber messages
- for (std::vector <IMAPMessage*>::iterator jt =
- m_messages.begin() ; jt != m_messages.end() ; ++jt)
- {
- if ((*jt)->getNumber() == msgNumber)
- (*jt)->setExpunged();
- else if ((*jt)->getNumber() > msgNumber)
- (*jt)->renumber((*jt)->getNumber() - 1);
- }
-
- events.push_back(make_shared <events::messageCountEvent>
- (dynamicCast <folder>(shared_from_this()),
- events::messageCountEvent::TYPE_REMOVED,
- std::vector <int>(1, msgNumber)));
-
- expungedMessageCount++;
- }
- }
- }
-
- // New messages arrived
- if (m_status->getMessageCount() > oldStatus->getMessageCount() - expungedMessageCount)
- {
- std::vector <int> newMessageNumbers;
-
- for (int msgNumber = oldStatus->getMessageCount() - expungedMessageCount ;
- msgNumber <= m_status->getMessageCount() ; ++msgNumber)
- {
- newMessageNumbers.push_back(msgNumber);
- }
-
- events.push_back(make_shared <events::messageCountEvent>
- (dynamicCast <folder>(shared_from_this()),
- events::messageCountEvent::TYPE_ADDED,
- newMessageNumbers));
- }
-
- // Dispatch notifications
- for (std::vector <shared_ptr <events::event> >::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 <[email protected]>
-//
-// This program is free software; you can redistribute it and/or
-// modify it under the terms of the GNU General Public License as
-// published by the Free Software Foundation; either version 3 of
-// the License, or (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-// General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License along
-// with this program; if not, write to the Free Software Foundation, Inc.,
-// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
-//
-// Linking this library statically or dynamically with other modules is making
-// a combined work based on this library. Thus, the terms and conditions of
-// the GNU General Public License cover the whole combination.
-//
-
-#include "vmime/config.hpp"
-
-
-#if VMIME_HAVE_MESSAGING_FEATURES && 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 <folderStatus> IMAPFolderStatus::clone() const
-{
- return make_shared <IMAPFolderStatus>(*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 <IMAPParser::status_att_val*>::const_iterator
- jt = statusAttList->values().begin() ; jt != statusAttList->values().end() ; ++jt)
- {
- switch ((*jt)->type())
- {
- case IMAPParser::status_att_val::MESSAGES:
- {
- const unsigned int count =
- static_cast <unsigned int>((*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 <unsigned int>((*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 <unsigned int>((*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 <vmime_uint32>((*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 <vmime_uint32>((*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 <vmime_uint64>((*jt)->value_as_mod_sequence_value()->value());
-
- if (m_highestModSeq != highestModSeq)
- {
- m_highestModSeq = highestModSeq;
- changed = true;
- }
-
- break;
- }
-
- }
- }
- }
- else if (resp->type() == IMAPParser::mailbox_data::EXISTS)
- {
- const unsigned int count =
- static_cast <unsigned int>(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 <unsigned int>(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 <vmime_uint32>(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 <vmime_uint32>(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 <unsigned int>(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 <vmime_uint64>(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 <[email protected]>
-//
-// This program is free software; you can redistribute it and/or
-// modify it under the terms of the GNU General Public License as
-// published by the Free Software Foundation; either version 3 of
-// the License, or (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-// General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License along
-// with this program; if not, write to the Free Software Foundation, Inc.,
-// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
-//
-// Linking this library statically or dynamically with other modules is making
-// a combined work based on this library. Thus, the terms and conditions of
-// the GNU General Public License cover the whole combination.
-//
-
-#include "vmime/config.hpp"
-
-
-#if VMIME_HAVE_MESSAGING_FEATURES && 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 <sstream>
-#include <iterator>
-#include <typeinfo>
-
-
-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
- <const IMAPParser::msg_att_item&>(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 <IMAPFolder> 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 <IMAPFolder> 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 <IMAPFolder> 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 <const messageStructure> IMAPMessage::getStructure() const
-{
- if (m_structure == NULL)
- throw exceptions::unfetched_object();
-
- return m_structure;
-}
-
-
-shared_ptr <messageStructure> IMAPMessage::getStructure()
-{
- if (m_structure == NULL)
- throw exceptions::unfetched_object();
-
- return m_structure;
-}
-
-
-shared_ptr <const header> 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 <const IMAPFolder> 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 <const messagePart> p,
- utility::outputStream& os,
- utility::progressListener* progress,
- const size_t start, const size_t length,
- const bool peek) const
-{
- shared_ptr <const IMAPFolder> folder = m_folder.lock();
-
- if (!folder)
- throw exceptions::folder_not_found();
-
- extractImpl(p, os, progress, start, length,
- EXTRACT_HEADER | EXTRACT_BODY | (peek ? EXTRACT_PEEK : 0));
-}
-
-
-void IMAPMessage::fetchPartHeader(shared_ptr <messagePart> p)
-{
- shared_ptr <IMAPFolder> 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 <IMAPMessagePart>(p)->getOrCreateHeader().parse(oss.str());
-}
-
-
-void IMAPMessage::fetchPartHeaderForStructure(shared_ptr <messageStructure> str)
-{
- for (size_t i = 0, n = str->getPartCount() ; i < n ; ++i)
- {
- shared_ptr <messagePart> part = str->getPartAt(i);
-
- // Fetch header of current part
- fetchPartHeader(part);
-
- // Fetch header of sub-parts
- fetchPartHeaderForStructure(part->getStructure());
- }
-}
-
-
-void IMAPMessage::extractImpl
- (shared_ptr <const messagePart> p,
- utility::outputStream& os,
- utility::progressListener* progress,
- const size_t start, const size_t length,
- const int extractFlags) const
-{
- shared_ptr <const IMAPFolder> 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 <const IMAPMessagePart> currentPart = dynamicCast <const IMAPMessagePart>(p);
- std::vector <int> 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 <int>::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 <size_t>(-1))
- command << "<" << start << "." << length << ">";
-
- // Send the request
- constCast <IMAPFolder>(folder)->m_connection->send(true, command.str(), true);
-
- // Get the response
- std::auto_ptr <IMAPParser::response> resp
- (constCast <IMAPFolder>(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 <IMAPFolder> folder = m_folder.lock();
-
- // Get message attributes
- const std::vector <IMAPParser::msg_att_item*> atts = msgData->msg_att()->items();
- int changes = 0;
-
- for (std::vector <IMAPParser::msg_att_item*>::const_iterator
- it = atts.begin() ; it != atts.end() ; ++it)
- {
- switch ((*it)->type())
- {
- case IMAPParser::msg_att_item::FLAGS:
- {
- int flags = IMAPUtils::messageFlagsFromFlags((*it)->flag_list());
-
- if (m_flags != flags)
- {
- m_flags = flags;
- changes |= events::messageChangedEvent::TYPE_FLAGS;
- }
-
- break;
- }
- case IMAPParser::msg_att_item::UID:
- {
- m_uid = (*it)->unique_id()->value();
- break;
- }
- case IMAPParser::msg_att_item::MODSEQ:
- {
- m_modseq = (*it)->mod_sequence_value()->value();
- break;
- }
- case IMAPParser::msg_att_item::ENVELOPE:
- {
- if (!options.has(fetchAttributes::FULL_HEADER))
- {
- const IMAPParser::envelope* env = (*it)->envelope();
- shared_ptr <vmime::header> hdr = getOrCreateHeader();
-
- // 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 <IMAPMessageStructure>((*it)->body());
- break;
- }
- case IMAPParser::msg_att_item::RFC822_HEADER:
- {
- getOrCreateHeader()->parse((*it)->nstring()->value());
- break;
- }
- case IMAPParser::msg_att_item::RFC822_SIZE:
- {
- m_size = static_cast <size_t>((*it)->number()->value());
- break;
- }
- case IMAPParser::msg_att_item::BODY_SECTION:
- {
- if (!options.has(fetchAttributes::FULL_HEADER))
- {
- if ((*it)->section()->section_text1() &&
- (*it)->section()->section_text1()->type()
- == IMAPParser::section_text::HEADER_FIELDS)
- {
- header tempHeader;
- tempHeader.parse((*it)->nstring()->value());
-
- vmime::header& hdr = *getOrCreateHeader();
- std::vector <shared_ptr <headerField> > fields = tempHeader.getFieldList();
-
- for (std::vector <shared_ptr <headerField> >::const_iterator jt = fields.begin() ;
- jt != fields.end() ; ++jt)
- {
- hdr.appendField(vmime::clone(*jt));
- }
- }
- }
-
- break;
- }
- case IMAPParser::msg_att_item::INTERNALDATE:
- case IMAPParser::msg_att_item::RFC822:
- case IMAPParser::msg_att_item::RFC822_TEXT:
- case IMAPParser::msg_att_item::BODY:
- {
- break;
- }
-
- }
- }
-
- return changes;
-}
-
-
-shared_ptr <header> IMAPMessage::getOrCreateHeader()
-{
- if (m_header != NULL)
- return (m_header);
- else
- return (m_header = make_shared <header>());
-}
-
-
-void IMAPMessage::setFlags(const int flags, const int mode)
-{
- shared_ptr <IMAPFolder> 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 <bodyPart> parentPart, shared_ptr <messageStructure> str, int level)
-{
- if (level == 0)
- {
- shared_ptr <messagePart> part = str->getPartAt(0);
-
- // Copy header
- shared_ptr <const header> hdr = part->getHeader();
- parentPart->getHeader()->copyFrom(*hdr);
-
- // Initialize body
- parentPart->getBody()->setContents
- (make_shared <IMAPMessagePartContentHandler>
- (dynamicCast <IMAPMessage>(shared_from_this()),
- part, parentPart->getBody()->getEncoding()));
-
- constructParsedMessage(parentPart, part->getStructure(), 1);
- }
- else
- {
- for (size_t i = 0, n = str->getPartCount() ; i < n ; ++i)
- {
- shared_ptr <messagePart> part = str->getPartAt(i);
-
- shared_ptr <bodyPart> childPart = make_shared <bodyPart>();
-
- // Copy header
- shared_ptr <const header> hdr = part->getHeader();
- childPart->getHeader()->copyFrom(*hdr);
-
- // Initialize body
- childPart->getBody()->setContents
- (make_shared <IMAPMessagePartContentHandler>
- (dynamicCast <IMAPMessage>(shared_from_this()),
- part, childPart->getBody()->getEncoding()));
-
- // Add child part
- parentPart->getBody()->appendPart(childPart);
-
- // Construct sub parts
- constructParsedMessage(childPart, part->getStructure(), ++level);
- }
- }
-}
-
-
-shared_ptr <vmime::message> IMAPMessage::getParsedMessage()
-{
- // Fetch structure
- shared_ptr <messageStructure> structure;
-
- try
- {
- structure = getStructure();
- }
- catch (exceptions::unfetched_object&)
- {
- std::vector <shared_ptr <message> > msgs;
- msgs.push_back(dynamicCast <IMAPMessage>(shared_from_this()));
-
- m_folder.lock()->fetchMessages
- (msgs, fetchAttributes(fetchAttributes::STRUCTURE), /* progress */ NULL);
-
- structure = getStructure();
- }
-
- // Fetch header for each part
- fetchPartHeaderForStructure(structure);
-
- // Construct message from structure
- shared_ptr <vmime::message> msg = make_shared <vmime::message>();
-
- 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 <[email protected]>
-//
-// This program is free software; you can redistribute it and/or
-// modify it under the terms of the GNU General Public License as
-// published by the Free Software Foundation; either version 3 of
-// the License, or (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-// General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License along
-// with this program; if not, write to the Free Software Foundation, Inc.,
-// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
-//
-// Linking this library statically or dynamically with other modules is making
-// a combined work based on this library. Thus, the terms and conditions of
-// the GNU General Public License cover the whole combination.
-//
-
-#include "vmime/config.hpp"
-
-
-#if VMIME_HAVE_MESSAGING_FEATURES && 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 <IMAPMessagePart> 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 <IMAPMessagePart> 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 <const messageStructure> IMAPMessagePart::getStructure() const
-{
- if (m_structure != NULL)
- return m_structure;
- else
- return IMAPMessageStructure::emptyStructure();
-}
-
-
-shared_ptr <messageStructure> IMAPMessagePart::getStructure()
-{
- if (m_structure != NULL)
- return m_structure;
- else
- return IMAPMessageStructure::emptyStructure();
-}
-
-
-shared_ptr <const IMAPMessagePart> 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 <const header> IMAPMessagePart::getHeader() const
-{
- if (m_header == NULL)
- throw exceptions::unfetched_object();
- else
- return m_header;
-}
-
-
-// static
-shared_ptr <IMAPMessagePart> IMAPMessagePart::create
- (shared_ptr <IMAPMessagePart> parent, const int number, const IMAPParser::body* body)
-{
- if (body->body_type_mpart())
- {
- shared_ptr <IMAPMessagePart> part = make_shared <IMAPMessagePart>(parent, number, body->body_type_mpart());
- part->m_structure = make_shared <IMAPMessageStructure>(part, body->body_type_mpart()->list());
-
- return part;
- }
- else
- {
- return make_shared <IMAPMessagePart>(parent, number, body->body_type_1part());
- }
-}
-
-
-header& IMAPMessagePart::getOrCreateHeader()
-{
- if (m_header != NULL)
- return *m_header;
- else
- return *(m_header = make_shared <header>());
-}
-
-
-} // 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 <[email protected]>
-//
-// This program is free software; you can redistribute it and/or
-// modify it under the terms of the GNU General Public License as
-// published by the Free Software Foundation; either version 3 of
-// the License, or (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-// General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License along
-// with this program; if not, write to the Free Software Foundation, Inc.,
-// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
-//
-// Linking this library statically or dynamically with other modules is making
-// a combined work based on this library. Thus, the terms and conditions of
-// the GNU General Public License cover the whole combination.
-//
-
-#include "vmime/config.hpp"
-
-
-#if VMIME_HAVE_MESSAGING_FEATURES && 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 <IMAPMessage> msg, shared_ptr <messagePart> part, const vmime::encoding& encoding)
- : m_message(msg), m_part(part), m_encoding(encoding)
-{
-}
-
-
-shared_ptr <contentHandler> IMAPMessagePartContentHandler::clone() const
-{
- return make_shared <IMAPMessagePartContentHandler>
- (constCast <IMAPMessage>(m_message.lock()),
- constCast <messagePart>(m_part.lock()),
- m_encoding);
-}
-
-
-void IMAPMessagePartContentHandler::generate
- (utility::outputStream& os, const vmime::encoding& enc, const size_t maxLineLength) const
-{
- shared_ptr <IMAPMessage> msg = constCast <IMAPMessage>(m_message.lock());
- shared_ptr <messagePart> part = constCast <messagePart>(m_part.lock());
-
- // 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 <utility::encoder::encoder> theDecoder = m_encoding.getEncoder();
- theDecoder->decode(in, tmp2);
-
- // Reencode to output stream
- string str = oss2.str();
- utility::inputStreamStringAdapter tempIn(str);
-
- shared_ptr <utility::encoder::encoder> 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 <utility::encoder::encoder> 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 <IMAPMessage> msg = constCast <IMAPMessage>(m_message.lock());
- shared_ptr <messagePart> part = constCast <messagePart>(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 <utility::encoder::encoder> theDecoder = m_encoding.getEncoder();
- theDecoder->decode(is, os, &plsa);
- }
-}
-
-
-void IMAPMessagePartContentHandler::extractRaw
- (utility::outputStream& os, utility::progressListener* progress) const
-{
- shared_ptr <IMAPMessage> msg = constCast <IMAPMessage>(m_message.lock());
- shared_ptr <messagePart> part = constCast <messagePart>(m_part.lock());
-
- 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 <[email protected]>
-//
-// This program is free software; you can redistribute it and/or
-// modify it under the terms of the GNU General Public License as
-// published by the Free Software Foundation; either version 3 of
-// the License, or (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-// General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License along
-// with this program; if not, write to the Free Software Foundation, Inc.,
-// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
-//
-// Linking this library statically or dynamically with other modules is making
-// a combined work based on this library. Thus, the terms and conditions of
-// the GNU General Public License cover the whole combination.
-//
-
-#include "vmime/config.hpp"
-
-
-#if VMIME_HAVE_MESSAGING_FEATURES && 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 <IMAPMessagePart> parent, const std::vector <IMAPParser::body*>& list)
-{
- int number = 0;
-
- for (std::vector <IMAPParser::body*>::const_iterator
- it = list.begin() ; it != list.end() ; ++it, ++number)
- {
- m_parts.push_back(IMAPMessagePart::create(parent, number, *it));
- }
-}
-
-
-shared_ptr <const messagePart> IMAPMessageStructure::getPartAt(const size_t x) const
-{
- return m_parts[x];
-}
-
-
-shared_ptr <messagePart> IMAPMessageStructure::getPartAt(const size_t x)
-{
- return m_parts[x];
-}
-
-
-size_t IMAPMessageStructure::getPartCount() const
-{
- return m_parts.size();
-}
-
-
-// static
-shared_ptr <IMAPMessageStructure> IMAPMessageStructure::emptyStructure()
-{
- static shared_ptr <IMAPMessageStructure> emptyStructure = make_shared <IMAPMessageStructure>();
- 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 <[email protected]>
-//
-// This program is free software; you can redistribute it and/or
-// modify it under the terms of the GNU General Public License as
-// published by the Free Software Foundation; either version 3 of
-// the License, or (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-// General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License along
-// with this program; if not, write to the Free Software Foundation, Inc.,
-// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
-//
-// Linking this library statically or dynamically with other modules is making
-// a combined work based on this library. Thus, the terms and conditions of
-// the GNU General Public License cover the whole combination.
-//
-
-#include "vmime/config.hpp"
-
-
-#if VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_IMAP
-
-
-#include "vmime/net/imap/IMAPSStore.hpp"
-
-
-namespace vmime {
-namespace net {
-namespace imap {
-
-
-IMAPSStore::IMAPSStore(shared_ptr <session> sess, shared_ptr <security::authenticator> 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 <[email protected]>
-//
-// This program is free software; you can redistribute it and/or
-// modify it under the terms of the GNU General Public License as
-// published by the Free Software Foundation; either version 3 of
-// the License, or (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-// General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License along
-// with this program; if not, write to the Free Software Foundation, Inc.,
-// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
-//
-// Linking this library statically or dynamically with other modules is making
-// a combined work based on this library. Thus, the terms and conditions of
-// the GNU General Public License cover the whole combination.
-//
-
-#include "vmime/config.hpp"
-
-
-#if VMIME_HAVE_MESSAGING_FEATURES && 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 <serviceInfos::property> IMAPServiceInfos::getAvailableProperties() const
-{
- std::vector <property> 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 <[email protected]>
-//
-// This program is free software; you can redistribute it and/or
-// modify it under the terms of the GNU General Public License as
-// published by the Free Software Foundation; either version 3 of
-// the License, or (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-// General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License along
-// with this program; if not, write to the Free Software Foundation, Inc.,
-// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
-//
-// Linking this library statically or dynamically with other modules is making
-// a combined work based on this library. Thus, the terms and conditions of
-// the GNU General Public License cover the whole combination.
-//
-
-#include "vmime/config.hpp"
-
-
-#if VMIME_HAVE_MESSAGING_FEATURES && 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 <map>
-
-
-namespace vmime {
-namespace net {
-namespace imap {
-
-
-IMAPStore::IMAPStore(shared_ptr <session> sess, shared_ptr <security::authenticator> auth, const bool secured)
- : store(sess, getInfosInstance(), auth), m_connection(null), m_isIMAPS(secured)
-{
-}
-
-
-IMAPStore::~IMAPStore()
-{
- try
- {
- if (isConnected())
- disconnect();
- }
- catch (vmime::exception&)
- {
- // Ignore
- }
-}
-
-
-const string IMAPStore::getProtocolName() const
-{
- return "imap";
-}
-
-
-shared_ptr <folder> IMAPStore::getRootFolder()
-{
- if (!isConnected())
- throw exceptions::illegal_state("Not connected");
-
- return make_shared <IMAPFolder>
- (folder::path(),
- dynamicCast <IMAPStore>(shared_from_this()));
-}
-
-
-shared_ptr <folder> IMAPStore::getDefaultFolder()
-{
- if (!isConnected())
- throw exceptions::illegal_state("Not connected");
-
- return make_shared <IMAPFolder>
- (folder::path::component("INBOX"),
- dynamicCast <IMAPStore>(shared_from_this()));
-}
-
-
-shared_ptr <folder> IMAPStore::getFolder(const folder::path& path)
-{
- if (!isConnected())
- throw exceptions::illegal_state("Not connected");
-
- return make_shared <IMAPFolder>
- (path, dynamicCast <IMAPStore>(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 <IMAPConnection>
- (dynamicCast <IMAPStore>(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 <connectionInfos> IMAPStore::getConnectionInfos() const
-{
- if (m_connection == NULL)
- return null;
-
- return m_connection->getConnectionInfos();
-}
-
-
-shared_ptr <IMAPConnection> IMAPStore::getConnection()
-{
- return m_connection;
-}
-
-
-void IMAPStore::disconnect()
-{
- if (!isConnected())
- throw exceptions::not_connected();
-
- for (std::list <IMAPFolder*>::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 <IMAPParser::response> resp(m_connection->readResponse());
-
- if (resp->isBad() || resp->response_done()->response_tagged()->
- resp_cond_state()->status() != IMAPParser::resp_cond_state::OK)
- {
- throw exceptions::command_error("NOOP", resp->getErrorLog());
- }
-
-
- for (std::list <IMAPFolder*>::iterator it = m_folders.begin() ;
- it != m_folders.end() ; ++it)
- {
- if ((*it)->isOpen())
- (*it)->noop();
- }
-}
-
-
-shared_ptr <IMAPConnection> IMAPStore::connection()
-{
- return (m_connection);
-}
-
-
-void IMAPStore::registerFolder(IMAPFolder* folder)
-{
- m_folders.push_back(folder);
-}
-
-
-void IMAPStore::unregisterFolder(IMAPFolder* folder)
-{
- std::list <IMAPFolder*>::iterator it = std::find(m_folders.begin(), m_folders.end(), folder);
- if (it != m_folders.end()) m_folders.erase(it);
-}
-
-
-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 <[email protected]>
-//
-// This program is free software; you can redistribute it and/or
-// modify it under the terms of the GNU General Public License as
-// published by the Free Software Foundation; either version 3 of
-// the License, or (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-// General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License along
-// with this program; if not, write to the Free Software Foundation, Inc.,
-// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
-//
-// Linking this library statically or dynamically with other modules is making
-// a combined work based on this library. Thus, the terms and conditions of
-// the GNU General Public License cover the whole combination.
-//
-
-#include "vmime/config.hpp"
-
-
-#if VMIME_HAVE_MESSAGING_FEATURES && 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 <char>('0' + (m_number % 1000) / 100);
- m_tag[2] = static_cast <char>('0' + (m_number % 100) / 10);
- m_tag[3] = static_cast <char>('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 <[email protected]>
-//
-// This program is free software; you can redistribute it and/or
-// modify it under the terms of the GNU General Public License as
-// published by the Free Software Foundation; either version 3 of
-// the License, or (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-// General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License along
-// with this program; if not, write to the Free Software Foundation, Inc.,
-// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
-//
-// Linking this library statically or dynamically with other modules is making
-// a combined work based on this library. Thus, the terms and conditions of
-// the GNU General Public License cover the whole combination.
-//
-
-#include "vmime/config.hpp"
-
-
-#if VMIME_HAVE_MESSAGING_FEATURES && 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 <sstream>
-#include <iterator>
-#include <algorithm>
-
-
-namespace vmime {
-namespace net {
-namespace imap {
-
-
-// static
-const string IMAPUtils::quoteString(const string& text)
-{
- //
- // ATOM_CHAR ::= <any CHAR except atom_specials>
- //
- // atom_specials ::= "(" / ")" / "{" / SPACE / CTL /
- // list_wildcards / quoted_specials
- //
- // list_wildcards ::= "%" / "*"
- //
- // quoted_specials ::= <"> / "\"
- //
- // CHAR ::= <any 7-bit US-ASCII character except NUL,
- // 0x01 - 0x7f>
- //
- // CTL ::= <any ASCII control character and DEL,
- // 0x00 - 0x1f, 0x7f>
- //
-
- 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 <unsigned int>(static_cast <unsigned char>(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 <[email protected]>
-
- // 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 <char>(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 <IMAPParser::mailbox_flag*>& flags = list->flags();
-
- for (std::vector <IMAPParser::mailbox_flag*>::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 <IMAPParser::mailbox_flag*>& flags = list->flags();
-
- for (std::vector <IMAPParser::mailbox_flag*>::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 <IMAPParser::flag*>& flagList = list->flags();
- int flags = 0;
-
- for (std::vector <IMAPParser::flag*>::const_iterator
- it = flagList.begin() ; it != flagList.end() ; ++it)
- {
- switch ((*it)->type())
- {
- case IMAPParser::flag::ANSWERED:
- flags |= message::FLAG_REPLIED;
- break;
- case IMAPParser::flag::FLAGGED:
- flags |= message::FLAG_MARKED;
- break;
- case IMAPParser::flag::DELETED:
- flags |= message::FLAG_DELETED;
- break;
- case IMAPParser::flag::SEEN:
- flags |= message::FLAG_SEEN;
- break;
- case IMAPParser::flag::DRAFT:
- flags |= message::FLAG_DRAFT;
- break;
-
- default:
- //case IMAPParser::flag::UNKNOWN:
- break;
- }
- }
-
- return (flags);
-}
-
-
-const string IMAPUtils::messageFlagList(const int flags)
-{
- std::vector <string> 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 <string>(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 <IMAPConnection> 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 <string> 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 <string> 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 <string> customHeaderFields = options.getHeaderFields();
- std::copy(customHeaderFields.begin(), customHeaderFields.end(), std::back_inserter(headerFields));
-
- if (!headerFields.empty())
- {
- string list;
-
- for (std::vector <string>::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 <string>::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 <IMAPParser::address*>::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 <mailbox>(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 <int>& list() const
- {
- return m_list;
- }
-
-public:
-
- std::vector <int> m_list;
-};
-
-
-
-// static
-const string IMAPUtils::messageSetToSequenceSet(const messageSet& msgs)
-{
- IMAPUIDMessageSetEnumerator en;
- msgs.enumerate(en);
-
- return en.str();
-}
-
-
-// static
-const std::vector <int> 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
-