From aa4d426b4d3527d7e166df1a05058c9a4a0f6683 Mon Sep 17 00:00:00 2001 From: Wojtek Kosior Date: Fri, 30 Apr 2021 00:33:56 +0200 Subject: initial/final commit --- vmime-master/src/vmime/net/pop3/POP3Command.cpp | 267 +++++++ vmime-master/src/vmime/net/pop3/POP3Command.hpp | 123 +++ vmime-master/src/vmime/net/pop3/POP3Connection.cpp | 737 ++++++++++++++++++ vmime-master/src/vmime/net/pop3/POP3Connection.hpp | 132 ++++ vmime-master/src/vmime/net/pop3/POP3Folder.cpp | 822 +++++++++++++++++++++ vmime-master/src/vmime/net/pop3/POP3Folder.hpp | 179 +++++ .../src/vmime/net/pop3/POP3FolderStatus.cpp | 88 +++ .../src/vmime/net/pop3/POP3FolderStatus.hpp | 75 ++ vmime-master/src/vmime/net/pop3/POP3Message.cpp | 283 +++++++ vmime-master/src/vmime/net/pop3/POP3Message.hpp | 124 ++++ vmime-master/src/vmime/net/pop3/POP3Response.cpp | 504 +++++++++++++ vmime-master/src/vmime/net/pop3/POP3Response.hpp | 194 +++++ vmime-master/src/vmime/net/pop3/POP3SStore.cpp | 82 ++ vmime-master/src/vmime/net/pop3/POP3SStore.hpp | 74 ++ .../src/vmime/net/pop3/POP3ServiceInfos.cpp | 142 ++++ .../src/vmime/net/pop3/POP3ServiceInfos.hpp | 91 +++ vmime-master/src/vmime/net/pop3/POP3Store.cpp | 262 +++++++ vmime-master/src/vmime/net/pop3/POP3Store.hpp | 120 +++ vmime-master/src/vmime/net/pop3/POP3Utils.cpp | 135 ++++ vmime-master/src/vmime/net/pop3/POP3Utils.hpp | 92 +++ vmime-master/src/vmime/net/pop3/pop3.hpp | 35 + 21 files changed, 4561 insertions(+) create mode 100644 vmime-master/src/vmime/net/pop3/POP3Command.cpp create mode 100644 vmime-master/src/vmime/net/pop3/POP3Command.hpp create mode 100644 vmime-master/src/vmime/net/pop3/POP3Connection.cpp create mode 100644 vmime-master/src/vmime/net/pop3/POP3Connection.hpp create mode 100644 vmime-master/src/vmime/net/pop3/POP3Folder.cpp create mode 100644 vmime-master/src/vmime/net/pop3/POP3Folder.hpp create mode 100644 vmime-master/src/vmime/net/pop3/POP3FolderStatus.cpp create mode 100644 vmime-master/src/vmime/net/pop3/POP3FolderStatus.hpp create mode 100644 vmime-master/src/vmime/net/pop3/POP3Message.cpp create mode 100644 vmime-master/src/vmime/net/pop3/POP3Message.hpp create mode 100644 vmime-master/src/vmime/net/pop3/POP3Response.cpp create mode 100644 vmime-master/src/vmime/net/pop3/POP3Response.hpp create mode 100644 vmime-master/src/vmime/net/pop3/POP3SStore.cpp create mode 100644 vmime-master/src/vmime/net/pop3/POP3SStore.hpp create mode 100644 vmime-master/src/vmime/net/pop3/POP3ServiceInfos.cpp create mode 100644 vmime-master/src/vmime/net/pop3/POP3ServiceInfos.hpp create mode 100644 vmime-master/src/vmime/net/pop3/POP3Store.cpp create mode 100644 vmime-master/src/vmime/net/pop3/POP3Store.hpp create mode 100644 vmime-master/src/vmime/net/pop3/POP3Utils.cpp create mode 100644 vmime-master/src/vmime/net/pop3/POP3Utils.hpp create mode 100644 vmime-master/src/vmime/net/pop3/pop3.hpp (limited to 'vmime-master/src/vmime/net/pop3') diff --git a/vmime-master/src/vmime/net/pop3/POP3Command.cpp b/vmime-master/src/vmime/net/pop3/POP3Command.cpp new file mode 100644 index 0000000..0e79888 --- /dev/null +++ b/vmime-master/src/vmime/net/pop3/POP3Command.cpp @@ -0,0 +1,267 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules is making +// a combined work based on this library. Thus, the terms and conditions of +// the GNU General Public License cover the whole combination. +// + +#include "vmime/config.hpp" + + +#if VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_POP3 + + +#include "vmime/net/pop3/POP3Command.hpp" +#include "vmime/net/pop3/POP3Connection.hpp" +#include "vmime/net/pop3/POP3Store.hpp" + +#include "vmime/net/socket.hpp" + +#include "vmime/mailbox.hpp" +#include "vmime/utility/outputStreamAdapter.hpp" + + +namespace vmime { +namespace net { +namespace pop3 { + + +POP3Command::POP3Command(const string& text, const string& traceText) + : m_text(text), + m_traceText(traceText) { + +} + + +// static +shared_ptr POP3Command::CAPA() { + + return createCommand("CAPA"); +} + + +// static +shared_ptr POP3Command::NOOP() { + + return createCommand("NOOP"); +} + + +// static +shared_ptr POP3Command::AUTH(const string& mechName) { + + std::ostringstream cmd; + cmd.imbue(std::locale::classic()); + cmd << "AUTH " << mechName; + + return createCommand(cmd.str()); +} + + +// static +shared_ptr POP3Command::AUTH(const string& mechName, const string& initialResponse) { + + std::ostringstream cmd; + cmd.imbue(std::locale::classic()); + cmd << "AUTH " << mechName << " " << initialResponse; + + return createCommand(cmd.str()); +} + + +// static +shared_ptr POP3Command::STLS() { + + return createCommand("STLS"); +} + + +// static +shared_ptr POP3Command::APOP(const string& username, const string& digest) { + + std::ostringstream cmd; + cmd.imbue(std::locale::classic()); + cmd << "APOP " << username << " " << digest; + + return createCommand(cmd.str()); +} + + +// static +shared_ptr POP3Command::USER(const string& username) { + + std::ostringstream cmd; + cmd.imbue(std::locale::classic()); + cmd << "USER " << username; + + std::ostringstream trace; + trace.imbue(std::locale::classic()); + trace << "USER {username}"; + + return createCommand(cmd.str(), trace.str()); +} + + +// static +shared_ptr POP3Command::PASS(const string& password) { + + std::ostringstream cmd; + cmd.imbue(std::locale::classic()); + cmd << "PASS " << password; + + std::ostringstream trace; + trace.imbue(std::locale::classic()); + trace << "PASS {password}"; + + return createCommand(cmd.str(), trace.str()); +} + + +// static +shared_ptr POP3Command::STAT() { + + return createCommand("STAT"); +} + + +// static +shared_ptr POP3Command::LIST() { + + return createCommand("LIST"); +} + + +// static +shared_ptr POP3Command::LIST(const unsigned long msg) { + + std::ostringstream cmd; + cmd.imbue(std::locale::classic()); + cmd << "LIST " << msg; + + return createCommand(cmd.str()); +} + + +// static +shared_ptr POP3Command::UIDL() { + + return createCommand("UIDL"); +} + + +// static +shared_ptr POP3Command::UIDL(const unsigned long msg) { + + std::ostringstream cmd; + cmd.imbue(std::locale::classic()); + cmd << "UIDL " << msg; + + return createCommand(cmd.str()); +} + + +// static +shared_ptr POP3Command::DELE(const unsigned long msg) { + + std::ostringstream cmd; + cmd.imbue(std::locale::classic()); + cmd << "DELE " << msg; + + return createCommand(cmd.str()); +} + + +// static +shared_ptr POP3Command::RETR(const unsigned long msg) { + + std::ostringstream cmd; + cmd.imbue(std::locale::classic()); + cmd << "RETR " << msg; + + return createCommand(cmd.str()); +} + + +// static +shared_ptr POP3Command::TOP(const unsigned long msg, const unsigned long lines) { + + std::ostringstream cmd; + cmd.imbue(std::locale::classic()); + cmd << "TOP " << msg << " " << lines; + + return createCommand(cmd.str()); +} + + +// static +shared_ptr POP3Command::RSET() { + + return createCommand("RSET"); +} + + +// static +shared_ptr POP3Command::QUIT() { + + return createCommand("QUIT"); +} + + +// static +shared_ptr POP3Command::createCommand( + const string& text, + const string& traceText +) { + + if (traceText.empty()) { + return shared_ptr (new POP3Command(text, text)); + } else { + return shared_ptr (new POP3Command(text, traceText)); + } +} + + +const string POP3Command::getText() const { + + return m_text; +} + + +const string POP3Command::getTraceText() const { + + return m_traceText; +} + + +void POP3Command::send(const shared_ptr & conn) { + + conn->getSocket()->send(m_text + "\r\n"); + + if (conn->getTracer()) { + conn->getTracer()->traceSend(m_traceText); + } +} + + +} // pop3 +} // net +} // vmime + + +#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_POP3 diff --git a/vmime-master/src/vmime/net/pop3/POP3Command.hpp b/vmime-master/src/vmime/net/pop3/POP3Command.hpp new file mode 100644 index 0000000..06a61b9 --- /dev/null +++ b/vmime-master/src/vmime/net/pop3/POP3Command.hpp @@ -0,0 +1,123 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules is making +// a combined work based on this library. Thus, the terms and conditions of +// the GNU General Public License cover the whole combination. +// + +#ifndef VMIME_NET_POP3_POP3COMMAND_HPP_INCLUDED +#define VMIME_NET_POP3_POP3COMMAND_HPP_INCLUDED + + +#include "vmime/config.hpp" + + +#if VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_POP3 + + +#include "vmime/object.hpp" +#include "vmime/base.hpp" + + +namespace vmime { + + +class mailbox; + + +namespace net { +namespace pop3 { + + +class POP3Connection; + + +/** A POP3 command that will be sent to the server. + */ +class VMIME_EXPORT POP3Command : public object { + +public: + + static shared_ptr CAPA(); + static shared_ptr NOOP(); + static shared_ptr AUTH(const string& mechName); + static shared_ptr AUTH(const string& mechName, const string& initialResponse); + static shared_ptr STLS(); + static shared_ptr APOP(const string& username, const string& digest); + static shared_ptr USER(const string& username); + static shared_ptr PASS(const string& password); + static shared_ptr STAT(); + static shared_ptr LIST(); + static shared_ptr LIST(const unsigned long msg); + static shared_ptr UIDL(); + static shared_ptr UIDL(const unsigned long msg); + static shared_ptr DELE(const unsigned long msg); + static shared_ptr RETR(const unsigned long msg); + static shared_ptr TOP(const unsigned long msg, const unsigned long lines); + static shared_ptr RSET(); + static shared_ptr QUIT(); + + /** Creates a new POP3 command with the specified text. + * + * @param text command text + * @param traceText trace text (if empty, command text is used) + * @return a new POP3Command object + */ + static shared_ptr createCommand(const string& text, const string& traceText = ""); + + /** Sends this command over the specified connection. + * + * @param conn connection onto which the command will be sent + */ + virtual void send(const shared_ptr & conn); + + /** Returns the full text of the command, including command name + * and parameters (if any). + * + * @return command text (eg. "LIST 42") + */ + virtual const string getText() const; + + /** Returns the full text of the command, suitable for outputing + * to the tracer. + * + * @return trace text (eg. "USER myusername") + */ + virtual const string getTraceText() const; + +protected: + + POP3Command(const string& text, const string& traceText); + POP3Command(const POP3Command&); + +private: + + string m_text; + string m_traceText; +}; + + +} // pop3 +} // net +} // vmime + + +#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_POP3 + +#endif // VMIME_NET_POP3_POP3COMMAND_HPP_INCLUDED diff --git a/vmime-master/src/vmime/net/pop3/POP3Connection.cpp b/vmime-master/src/vmime/net/pop3/POP3Connection.cpp new file mode 100644 index 0000000..749f7ef --- /dev/null +++ b/vmime-master/src/vmime/net/pop3/POP3Connection.cpp @@ -0,0 +1,737 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules is making +// a combined work based on this library. Thus, the terms and conditions of +// the GNU General Public License cover the whole combination. +// + +#include "vmime/config.hpp" + + +#if VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_POP3 + + +#include "vmime/net/pop3/POP3Connection.hpp" +#include "vmime/net/pop3/POP3Store.hpp" + +#include "vmime/exception.hpp" +#include "vmime/platform.hpp" + +#include "vmime/security/digest/messageDigestFactory.hpp" + +#include "vmime/net/defaultConnectionInfos.hpp" + +#if VMIME_HAVE_SASL_SUPPORT + #include "vmime/security/sasl/SASLContext.hpp" +#endif // VMIME_HAVE_SASL_SUPPORT + +#if VMIME_HAVE_TLS_SUPPORT + #include "vmime/net/tls/TLSSession.hpp" + #include "vmime/net/tls/TLSSecuredConnectionInfos.hpp" +#endif // VMIME_HAVE_TLS_SUPPORT + + + +// Helpers for service properties +#define GET_PROPERTY(type, prop) \ + (m_store.lock()->getInfos().getPropertyValue (getSession(), \ + dynamic_cast (m_store.lock()->getInfos()).getProperties().prop)) +#define HAS_PROPERTY(prop) \ + (m_store.lock()->getInfos().hasProperty(getSession(), \ + dynamic_cast (m_store.lock()->getInfos()).getProperties().prop)) + + +namespace vmime { +namespace net { +namespace pop3 { + + + +POP3Connection::POP3Connection( + const shared_ptr & store, + const shared_ptr & auth +) + : m_store(store), + m_auth(auth), + m_socket(null), + m_timeoutHandler(null), + m_authenticated(false), + m_secured(false), + m_capabilitiesFetched(false) { + + static int connectionId = 0; + + if (store->getTracerFactory()) { + m_tracer = store->getTracerFactory()->create(store, ++connectionId); + } +} + + +POP3Connection::~POP3Connection() { + + try { + + if (isConnected()) { + disconnect(); + } else if (m_socket) { + internalDisconnect(); + } + + } catch (...) { + + // Don't throw in destructor + } +} + + +void POP3Connection::connect() { + + if (isConnected()) { + throw exceptions::already_connected(); + } + + const string address = GET_PROPERTY(string, PROPERTY_SERVER_ADDRESS); + const port_t port = GET_PROPERTY(port_t, PROPERTY_SERVER_PORT); + + shared_ptr store = m_store.lock(); + + // Create the time-out handler + if (store->getTimeoutHandlerFactory()) { + m_timeoutHandler = store->getTimeoutHandlerFactory()->create(); + } + + // Create and connect the socket + m_socket = store->getSocketFactory()->create(m_timeoutHandler); + m_socket->setTracer(m_tracer); + +#if VMIME_HAVE_TLS_SUPPORT + if (store->isPOP3S()) { // dedicated port/POP3S + + shared_ptr tlsSession = tls::TLSSession::create + (store->getCertificateVerifier(), + store->getSession()->getTLSProperties()); + + shared_ptr tlsSocket = + tlsSession->getSocket(m_socket); + + m_socket = tlsSocket; + + m_secured = true; + m_cntInfos = make_shared (address, port, tlsSession, tlsSocket); + } else +#endif // VMIME_HAVE_TLS_SUPPORT + { + m_cntInfos = make_shared (address, port); + } + + m_socket->connect(address, port); + + // Connection + // + // eg: C: + // --- S: +OK MailSite POP3 Server 5.3.4.0 Ready <36938848.1056800841.634@somewhere.com> + + shared_ptr response = POP3Response::readResponse( + dynamicCast (shared_from_this()) + ); + + if (!response->isSuccess()) { + + internalDisconnect(); + throw exceptions::connection_greeting_error(response->getFirstLine()); + } + +#if VMIME_HAVE_TLS_SUPPORT + // Setup secured connection, if requested + const bool tls = HAS_PROPERTY(PROPERTY_CONNECTION_TLS) + && GET_PROPERTY(bool, PROPERTY_CONNECTION_TLS); + const bool tlsRequired = HAS_PROPERTY(PROPERTY_CONNECTION_TLS_REQUIRED) + && GET_PROPERTY(bool, PROPERTY_CONNECTION_TLS_REQUIRED); + + if (!store->isPOP3S() && tls) { // only if not POP3S + + try { + + startTLS(); + + // Non-fatal error + } catch (exceptions::command_error&) { + + if (tlsRequired) { + throw; + } else { + // TLS is not required, so don't bother + } + + // Fatal error + } catch (...) { + throw; + } + } +#endif // VMIME_HAVE_TLS_SUPPORT + + // Start authentication process + authenticate(messageId(response->getText())); +} + + +void POP3Connection::disconnect() { + + if (!isConnected()) { + throw exceptions::not_connected(); + } + + internalDisconnect(); +} + + +void POP3Connection::internalDisconnect() { + + if (m_socket) { + + if (m_socket->isConnected()) { + + try { + + POP3Command::QUIT()->send(dynamicCast (shared_from_this())); + POP3Response::readResponse(dynamicCast (shared_from_this())); + + } catch (exception&) { + + // Not important + } + + m_socket->disconnect(); + } + + m_socket = null; + } + + m_timeoutHandler = null; + + m_authenticated = false; + m_secured = false; + + m_cntInfos = null; +} + + +void POP3Connection::authenticate(const messageId& randomMID) { + + getAuthenticator()->setService(m_store.lock()); + +#if VMIME_HAVE_SASL_SUPPORT + // First, try SASL authentication + if (GET_PROPERTY(bool, PROPERTY_OPTIONS_SASL)) { + + try { + + authenticateSASL(); + + m_authenticated = true; + return; + + } catch (exceptions::authentication_error&) { + + if (!GET_PROPERTY(bool, PROPERTY_OPTIONS_SASL_FALLBACK)) { + + // Can't fallback on APOP/normal authentication + internalDisconnect(); + throw; + + } else { + + // Ignore, will try APOP/normal authentication + } + + } catch (exception&) { + + internalDisconnect(); + throw; + } + } +#endif // VMIME_HAVE_SASL_SUPPORT + + // Secured authentication with APOP (if requested and if available) + // + // eg: C: APOP vincent + // --- S: +OK vincent is a valid mailbox + + const string username = getAuthenticator()->getUsername(); + const string password = getAuthenticator()->getPassword(); + + shared_ptr conn = dynamicCast (shared_from_this()); + shared_ptr response; + + if (GET_PROPERTY(bool, PROPERTY_OPTIONS_APOP)) { + + if (randomMID.getLeft().length() != 0 && + randomMID.getRight().length() != 0) { + + // is the result of MD5 applied to "password" + shared_ptr md5 = + security::digest::messageDigestFactory::getInstance()->create("md5"); + + md5->update(randomMID.generate() + password); + md5->finalize(); + + POP3Command::APOP(username, md5->getHexDigest())->send(conn); + response = POP3Response::readResponse(conn); + + if (response->isSuccess()) { + + m_authenticated = true; + return; + + } else { + + // Some servers close the connection after an unsuccessful APOP + // command, so the fallback may not always work... + // + // S: +OK Qpopper (version 4.0.5) at xxx starting. <30396.1126730747@xxx> + // C: APOP plop c5e0a87d088ec71d60e32692d4c5bdf4 + // S: -ERR [AUTH] Password supplied for "plop" is incorrect. + // S: +OK Pop server at xxx signing off. + // [Connection closed by foreign host.] + + if (!GET_PROPERTY(bool, PROPERTY_OPTIONS_APOP_FALLBACK)) { + + // Can't fallback on basic authentication + internalDisconnect(); + throw exceptions::authentication_error(response->getFirstLine()); + } + + // Ensure connection is valid (cf. note above) + try { + + POP3Command::NOOP()->send(conn); + POP3Response::readResponse(conn); + + } catch (exceptions::socket_exception&) { + + internalDisconnect(); + throw exceptions::authentication_error(response->getFirstLine()); + } + } + + } else { + + // APOP not supported + if (!GET_PROPERTY(bool, PROPERTY_OPTIONS_APOP_FALLBACK)) { + + // Can't fallback on basic authentication + internalDisconnect(); + throw exceptions::authentication_error("APOP not supported"); + } + } + } + + // Basic authentication + // + // eg: C: USER vincent + // --- S: +OK vincent is a valid mailbox + // + // C: PASS couic + // S: +OK vincent's maildrop has 2 messages (320 octets) + POP3Command::USER(username)->send(conn); + response = POP3Response::readResponse(conn); + + if (!response->isSuccess()) { + + internalDisconnect(); + throw exceptions::authentication_error(response->getFirstLine()); + } + + POP3Command::PASS(password)->send(conn); + response = POP3Response::readResponse(conn); + + if (!response->isSuccess()) { + + internalDisconnect(); + throw exceptions::authentication_error(response->getFirstLine()); + } + + m_authenticated = true; +} + + +#if VMIME_HAVE_SASL_SUPPORT + +void POP3Connection::authenticateSASL() { + + if (!dynamicCast (getAuthenticator())) { + throw exceptions::authentication_error("No SASL authenticator available."); + } + + std::vector capa = getCapabilities(); + std::vector saslMechs; + + for (unsigned int i = 0 ; i < capa.size() ; ++i) { + + const string& x = capa[i]; + + // C: CAPA + // S: +OK List of capabilities follows + // S: LOGIN-DELAY 0 + // S: PIPELINING + // S: UIDL + // S: ... + // S: SASL DIGEST-MD5 CRAM-MD5 <----- + // S: EXPIRE NEVER + // S: ... + + if (x.length() > 5 && + (x[0] == 'S' || x[0] == 's') && + (x[1] == 'A' || x[1] == 'a') && + (x[2] == 'S' || x[2] == 's') && + (x[3] == 'L' || x[3] == 'l') && + (x[4] == ' ' || x[4] == '\t')) { + + const string list(x.begin() + 5, x.end()); + + std::istringstream iss(list); + iss.imbue(std::locale::classic()); + + string mech; + + while (iss >> mech) { + saslMechs.push_back(mech); + } + } + } + + if (saslMechs.empty()) { + throw exceptions::authentication_error("No SASL mechanism available."); + } + + std::vector > mechList; + + shared_ptr saslContext = + security::sasl::SASLContext::create(); + + for (unsigned int i = 0 ; i < saslMechs.size() ; ++i) { + + try { + mechList.push_back(saslContext->createMechanism(saslMechs[i])); + } catch (exceptions::no_such_mechanism&) { + // Ignore mechanism + } + } + + if (mechList.empty()) { + throw exceptions::authentication_error("No SASL mechanism available."); + } + + // Try to suggest a mechanism among all those supported + shared_ptr suggestedMech = + saslContext->suggestMechanism(mechList); + + if (!suggestedMech) { + throw exceptions::authentication_error("Unable to suggest SASL mechanism."); + } + + // Allow application to choose which mechanisms to use + mechList = dynamicCast (getAuthenticator())-> + getAcceptableMechanisms(mechList, suggestedMech); + + if (mechList.empty()) { + throw exceptions::authentication_error("No SASL mechanism available."); + } + + // Try each mechanism in the list in turn + for (unsigned int i = 0 ; i < mechList.size() ; ++i) { + + shared_ptr mech = mechList[i]; + + shared_ptr saslSession = + saslContext->createSession("pop3", getAuthenticator(), mech); + + saslSession->init(); + + shared_ptr authCmd; + + if (saslSession->getMechanism()->hasInitialResponse()) { + + byte_t* initialResp = 0; + size_t initialRespLen = 0; + + saslSession->evaluateChallenge(NULL, 0, &initialResp, &initialRespLen); + + string encodedInitialResp(saslContext->encodeB64(initialResp, initialRespLen)); + delete [] initialResp; + + if (encodedInitialResp.empty()) { + authCmd = POP3Command::AUTH(mech->getName(), "="); + } else { + authCmd = POP3Command::AUTH(mech->getName(), encodedInitialResp); + } + + } else { + + authCmd = POP3Command::AUTH(mech->getName()); + } + + authCmd->send(dynamicCast (shared_from_this())); + + for (bool cont = true ; cont ; ) { + + shared_ptr response = + POP3Response::readResponse(dynamicCast (shared_from_this())); + + switch (response->getCode()) { + + case POP3Response::CODE_OK: { + + m_socket = saslSession->getSecuredSocket(m_socket); + return; + } + + case POP3Response::CODE_READY: { + + byte_t* challenge = 0; + size_t challengeLen = 0; + + byte_t* resp = 0; + size_t respLen = 0; + + try { + + // Extract challenge + saslContext->decodeB64(response->getText(), &challenge, &challengeLen); + + // Prepare response + saslSession->evaluateChallenge(challenge, challengeLen, &resp, &respLen); + + // Send response + const string respB64 = saslContext->encodeB64(resp, respLen) + "\r\n"; + m_socket->sendRaw(utility::stringUtils::bytesFromString(respB64), respB64.length()); + + if (m_tracer) { + m_tracer->traceSendBytes(respB64.length() - 2, "SASL exchange"); + } + + } catch (exceptions::sasl_exception& e) { + + if (challenge) { + delete [] challenge; + challenge = NULL; + } + + if (resp) { + delete [] resp; + resp = NULL; + } + + // Cancel SASL exchange + m_socket->send("*\r\n"); + + if (m_tracer) { + m_tracer->traceSend("*"); + } + + } catch (...) { + + if (challenge) { + delete [] challenge; + } + + if (resp) { + delete [] resp; + } + + throw; + } + + if (challenge) { + delete [] challenge; + } + + if (resp) { + delete [] resp; + } + + break; + } + + default: + + cont = false; + break; + } + } + } + + throw exceptions::authentication_error("Could not authenticate using SASL: all mechanisms failed."); +} + +#endif // VMIME_HAVE_SASL_SUPPORT + + +#if VMIME_HAVE_TLS_SUPPORT + +void POP3Connection::startTLS() { + + try { + + POP3Command::STLS()->send(dynamicCast (shared_from_this())); + + shared_ptr response = + POP3Response::readResponse(dynamicCast (shared_from_this())); + + if (!response->isSuccess()) { + throw exceptions::command_error("STLS", response->getFirstLine()); + } + + shared_ptr tlsSession = tls::TLSSession::create( + m_store.lock()->getCertificateVerifier(), + m_store.lock()->getSession()->getTLSProperties() + ); + + shared_ptr tlsSocket = tlsSession->getSocket(m_socket); + + tlsSocket->handshake(); + + m_socket = tlsSocket; + + m_secured = true; + m_cntInfos = make_shared ( + m_cntInfos->getHost(), m_cntInfos->getPort(), tlsSession, tlsSocket + ); + + // " Once TLS has been started, the client MUST discard cached + // information about server capabilities and SHOULD re-issue + // the CAPA command. This is necessary to protect against + // man-in-the-middle attacks which alter the capabilities list + // prior to STLS. " (RFC-2595) + invalidateCapabilities(); + + } catch (exceptions::command_error&) { + + // Non-fatal error + throw; + + } catch (exception&) { + + // Fatal error + internalDisconnect(); + throw; + } +} + +#endif // VMIME_HAVE_TLS_SUPPORT + + +const std::vector POP3Connection::getCapabilities() { + + if (!m_capabilitiesFetched) { + fetchCapabilities(); + } + + return m_capabilities; +} + + +void POP3Connection::invalidateCapabilities() { + + m_capabilities.clear(); + m_capabilitiesFetched = false; +} + + +void POP3Connection::fetchCapabilities() { + + POP3Command::CAPA()->send(dynamicCast (shared_from_this())); + + shared_ptr response = + POP3Response::readMultilineResponse(dynamicCast (shared_from_this())); + + std::vector res; + + if (response->isSuccess()) { + + for (size_t i = 0, n = response->getLineCount() ; i < n ; ++i) { + res.push_back(response->getLineAt(i)); + } + } + + m_capabilities = res; + m_capabilitiesFetched = true; +} + + +bool POP3Connection::isConnected() const { + + return m_socket && m_socket->isConnected() && m_authenticated; +} + + +bool POP3Connection::isSecuredConnection() const { + + return m_secured; +} + + +shared_ptr POP3Connection::getConnectionInfos() const { + + return m_cntInfos; +} + + +shared_ptr POP3Connection::getStore() { + + return m_store.lock(); +} + + +shared_ptr POP3Connection::getSession() { + + return m_store.lock()->getSession(); +} + + +shared_ptr POP3Connection::getSocket() { + + return m_socket; +} + + +shared_ptr POP3Connection::getTracer() { + + return m_tracer; +} + + +shared_ptr POP3Connection::getTimeoutHandler() { + + return m_timeoutHandler; +} + + +shared_ptr POP3Connection::getAuthenticator() { + + return m_auth; +} + + +} // pop3 +} // net +} // vmime + + +#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_POP3 diff --git a/vmime-master/src/vmime/net/pop3/POP3Connection.hpp b/vmime-master/src/vmime/net/pop3/POP3Connection.hpp new file mode 100644 index 0000000..26b3f3c --- /dev/null +++ b/vmime-master/src/vmime/net/pop3/POP3Connection.hpp @@ -0,0 +1,132 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules is making +// a combined work based on this library. Thus, the terms and conditions of +// the GNU General Public License cover the whole combination. +// + +#ifndef VMIME_NET_POP3_POP3CONNECTION_HPP_INCLUDED +#define VMIME_NET_POP3_POP3CONNECTION_HPP_INCLUDED + + +#include "vmime/config.hpp" + + +#if VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_POP3 + + +#include "vmime/messageId.hpp" + +#include "vmime/net/socket.hpp" +#include "vmime/net/timeoutHandler.hpp" +#include "vmime/net/session.hpp" +#include "vmime/net/connectionInfos.hpp" +#include "vmime/net/tracer.hpp" + +#include "vmime/net/pop3/POP3Command.hpp" +#include "vmime/net/pop3/POP3Response.hpp" + +#include "vmime/security/authenticator.hpp" + + +namespace vmime { +namespace net { + + +class socket; +class timeoutHandler; + + +namespace pop3 { + + +class POP3Store; + + +/** Manage connection to a POP3 server. + */ +class VMIME_EXPORT POP3Connection : public object, public enable_shared_from_this { + +public: + + POP3Connection( + const shared_ptr & store, + const shared_ptr & auth + ); + + virtual ~POP3Connection(); + + + virtual void connect(); + virtual bool isConnected() const; + virtual void disconnect(); + + bool isSecuredConnection() const; + shared_ptr getConnectionInfos() const; + + virtual shared_ptr getStore(); + virtual shared_ptr getSocket(); + virtual shared_ptr getTimeoutHandler(); + virtual shared_ptr getAuthenticator(); + virtual shared_ptr getSession(); + virtual shared_ptr getTracer(); + +private: + + void authenticate(const messageId& randomMID); +#if VMIME_HAVE_SASL_SUPPORT + void authenticateSASL(); +#endif // VMIME_HAVE_SASL_SUPPORT + +#if VMIME_HAVE_TLS_SUPPORT + void startTLS(); +#endif // VMIME_HAVE_TLS_SUPPORT + + void fetchCapabilities(); + void invalidateCapabilities(); + const std::vector getCapabilities(); + + void internalDisconnect(); + + + weak_ptr m_store; + + shared_ptr m_auth; + shared_ptr m_socket; + shared_ptr m_timeoutHandler; + shared_ptr m_tracer; + + bool m_authenticated; + bool m_secured; + + shared_ptr m_cntInfos; + + std::vector m_capabilities; + bool m_capabilitiesFetched; +}; + + +} // pop3 +} // net +} // vmime + + +#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_POP3 + +#endif // VMIME_NET_POP3_POP3CONNECTION_HPP_INCLUDED diff --git a/vmime-master/src/vmime/net/pop3/POP3Folder.cpp b/vmime-master/src/vmime/net/pop3/POP3Folder.cpp new file mode 100644 index 0000000..b69a483 --- /dev/null +++ b/vmime-master/src/vmime/net/pop3/POP3Folder.cpp @@ -0,0 +1,822 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules is making +// a combined work based on this library. Thus, the terms and conditions of +// the GNU General Public License cover the whole combination. +// + +#include "vmime/config.hpp" + + +#if VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_POP3 + + +#include "vmime/net/pop3/POP3Folder.hpp" + +#include "vmime/net/pop3/POP3Store.hpp" +#include "vmime/net/pop3/POP3Message.hpp" +#include "vmime/net/pop3/POP3Command.hpp" +#include "vmime/net/pop3/POP3Response.hpp" +#include "vmime/net/pop3/POP3FolderStatus.hpp" + +#include "vmime/net/pop3/POP3Utils.hpp" + +#include "vmime/exception.hpp" + + +namespace vmime { +namespace net { +namespace pop3 { + + +POP3Folder::POP3Folder( + const folder::path& path, + const shared_ptr & store +) + : m_store(store), + m_path(path), + m_name(path.isEmpty() ? folder::path::component("") : path.getLastComponent()), + m_mode(-1), + m_open(false) { + + store->registerFolder(this); +} + + +POP3Folder::~POP3Folder() { + + try { + + shared_ptr store = m_store.lock(); + + if (store) { + + if (m_open) { + close(false); + } + + store->unregisterFolder(this); + + } else if (m_open) { + + onClose(); + } + + } catch (...) { + + // Don't throw in destructor + } +} + + +int POP3Folder::getMode() const { + + if (!isOpen()) { + throw exceptions::illegal_state("Folder not open"); + } + + return m_mode; +} + + +const folderAttributes POP3Folder::getAttributes() { + + folderAttributes attribs; + + if (m_path.isEmpty()) { + attribs.setType(folderAttributes::TYPE_CONTAINS_FOLDERS); + } else if (m_path.getSize() == 1 && m_path[0].getBuffer() == "INBOX") { + attribs.setType(folderAttributes::TYPE_CONTAINS_MESSAGES); + attribs.setSpecialUse(folderAttributes::SPECIALUSE_INBOX); + } else { + throw exceptions::folder_not_found(); + } + + attribs.setFlags(0); + + return attribs; +} + + +const folder::path::component POP3Folder::getName() const { + + return m_name; +} + + +const folder::path POP3Folder::getFullPath() const { + + return m_path; +} + + +void POP3Folder::open(const int mode, bool failIfModeIsNotAvailable) { + + shared_ptr store = m_store.lock(); + + if (!store) { + throw exceptions::illegal_state("Store disconnected"); + } + + if (m_path.isEmpty()) { + + if (mode != MODE_READ_ONLY && failIfModeIsNotAvailable) { + throw exceptions::operation_not_supported(); + } + + m_open = true; + m_mode = mode; + + m_messageCount = 0; + + } else if (m_path.getSize() == 1 && m_path[0].getBuffer() == "INBOX") { + + POP3Command::STAT()->send(store->getConnection()); + + shared_ptr response = POP3Response::readResponse(store->getConnection()); + + if (!response->isSuccess()) { + throw exceptions::command_error("STAT", response->getFirstLine()); + } + + std::istringstream iss(response->getText()); + iss.imbue(std::locale::classic()); + iss >> m_messageCount; + + if (iss.fail()) { + throw exceptions::invalid_response("STAT", response->getFirstLine()); + } + + m_open = true; + m_mode = mode; + + } else { + + throw exceptions::folder_not_found(); + } +} + + +void POP3Folder::close(const bool expunge) { + + shared_ptr store = m_store.lock(); + + if (!store) { + throw exceptions::illegal_state("Store disconnected"); + } + + if (!isOpen()) { + throw exceptions::illegal_state("Folder not open"); + } + + if (!expunge) { + POP3Command::RSET()->send(store->getConnection()); + POP3Response::readResponse(store->getConnection()); + } + + m_open = false; + m_mode = -1; + + onClose(); +} + + +void POP3Folder::onClose() { + + for (MessageMap::iterator it = m_messages.begin() ; it != m_messages.end() ; ++it) { + (*it).first->onFolderClosed(); + } + + m_messages.clear(); +} + + +void POP3Folder::create(const folderAttributes& /* attribs */) { + + throw exceptions::operation_not_supported(); +} + + +void POP3Folder::destroy() { + + throw exceptions::operation_not_supported(); +} + + +bool POP3Folder::exists() { + + shared_ptr store = m_store.lock(); + + if (!store) { + throw exceptions::illegal_state("Store disconnected"); + } + + return m_path.isEmpty() || (m_path.getSize() == 1 && m_path[0].getBuffer() == "INBOX"); +} + + +bool POP3Folder::isOpen() const { + + return m_open; +} + + +shared_ptr POP3Folder::getMessage(const size_t num) { + + shared_ptr store = m_store.lock(); + + if (!store) { + throw exceptions::illegal_state("Store disconnected"); + } else if (!isOpen()) { + throw exceptions::illegal_state("Folder not open"); + } else if (num < 1 || num > m_messageCount) { + throw exceptions::message_not_found(); + } + + return make_shared (dynamicCast (shared_from_this()), num); +} + + +std::vector > POP3Folder::getMessages(const messageSet& msgs) { + + shared_ptr store = m_store.lock(); + + if (!store) { + throw exceptions::illegal_state("Store disconnected"); + } else if (!isOpen()) { + throw exceptions::illegal_state("Folder not open"); + } + + if (msgs.isNumberSet()) { + + const std::vector numbers = POP3Utils::messageSetToNumberList(msgs, m_messageCount); + + std::vector > messages; + shared_ptr thisFolder(dynamicCast (shared_from_this())); + + for (std::vector ::const_iterator it = numbers.begin() ; it != numbers.end() ; ++it) { + + if (*it < 1|| *it > m_messageCount) { + throw exceptions::message_not_found(); + } + + messages.push_back(make_shared (thisFolder, *it)); + } + + return messages; + + } else { + + throw exceptions::operation_not_supported(); + } +} + + +size_t POP3Folder::getMessageCount() { + + shared_ptr store = m_store.lock(); + + if (!store) { + throw exceptions::illegal_state("Store disconnected"); + } else if (!isOpen()) { + throw exceptions::illegal_state("Folder not open"); + } + + return m_messageCount; +} + + +shared_ptr POP3Folder::getFolder(const folder::path::component& name) { + + shared_ptr store = m_store.lock(); + + if (!store) { + throw exceptions::illegal_state("Store disconnected"); + } + + return shared_ptr (new POP3Folder(m_path / name, store)); +} + + +std::vector > POP3Folder::getFolders(const bool /* recursive */) { + + shared_ptr store = m_store.lock(); + + if (!store) { + throw exceptions::illegal_state("Store disconnected"); + } + + if (m_path.isEmpty()) { + + std::vector > v; + v.push_back(shared_ptr (new POP3Folder(folder::path::component("INBOX"), store))); + return v; + + } else { + + std::vector > v; + return v; + } +} + + +void POP3Folder::fetchMessages( + std::vector >& msg, + const fetchAttributes& options, + utility::progressListener* progress +) { + + shared_ptr store = m_store.lock(); + + if (!store) { + throw exceptions::illegal_state("Store disconnected"); + } else if (!isOpen()) { + throw exceptions::illegal_state("Folder not open"); + } + + if (msg.empty()) { + return; + } + + const size_t total = msg.size(); + size_t current = 0; + + if (progress) { + progress->start(total); + } + + for (std::vector >::iterator it = msg.begin() ; + it != msg.end() ; ++it) { + + dynamicCast (*it)->fetch( + dynamicCast (shared_from_this()), + options + ); + + if (progress) { + progress->progress(++current, total); + } + } + + if (options.has(fetchAttributes::SIZE)) { + + // Send the "LIST" command + POP3Command::LIST()->send(store->getConnection()); + + // Get the response + shared_ptr response = + POP3Response::readMultilineResponse(store->getConnection()); + + if (response->isSuccess()) { + + // C: LIST + // S: +OK + // S: 1 47548 + // S: 2 12653 + // S: . + std::map result; + POP3Utils::parseMultiListOrUidlResponse(response, result); + + for (std::vector >::iterator it = msg.begin() ; + it != msg.end() ; ++it) { + + shared_ptr m = dynamicCast (*it); + + std::map ::const_iterator x = result.find(m->m_num); + + if (x != result.end()) { + + size_t size = 0; + + std::istringstream iss((*x).second); + iss.imbue(std::locale::classic()); + iss >> size; + + m->m_size = size; + } + } + } + } + + if (options.has(fetchAttributes::UID)) { + + // Send the "UIDL" command + POP3Command::UIDL()->send(store->getConnection()); + + // Get the response + shared_ptr response = + POP3Response::readMultilineResponse(store->getConnection()); + + if (response->isSuccess()) { + + // C: UIDL + // S: +OK + // S: 1 whqtswO00WBw418f9t5JxYwZ + // S: 2 QhdPYR:00WBw1Ph7x7 + // S: . + std::map result; + POP3Utils::parseMultiListOrUidlResponse(response, result); + + for (std::vector >::iterator it = msg.begin() ; + it != msg.end() ; ++it) { + + shared_ptr m = dynamicCast (*it); + + std::map ::const_iterator x = result.find(m->m_num); + + if (x != result.end()) { + m->m_uid = (*x).second; + } + } + } + } + + if (progress) { + progress->stop(total); + } +} + + +void POP3Folder::fetchMessage(const shared_ptr & msg, const fetchAttributes& options) { + + shared_ptr store = m_store.lock(); + + if (!store) { + throw exceptions::illegal_state("Store disconnected"); + } else if (!isOpen()) { + throw exceptions::illegal_state("Folder not open"); + } + + dynamicCast (msg)->fetch( + dynamicCast (shared_from_this()), + options + ); + + if (options.has(fetchAttributes::SIZE)) { + + // Send the "LIST" command + POP3Command::LIST(msg->getNumber())->send(store->getConnection()); + + // Get the response + shared_ptr response = + POP3Response::readResponse(store->getConnection()); + + if (response->isSuccess()) { + + string responseText = response->getText(); + + // C: LIST 2 + // S: +OK 2 4242 + string::iterator it = responseText.begin(); + + while (it != responseText.end() && (*it == ' ' || *it == '\t')) ++it; + while (it != responseText.end() && !(*it == ' ' || *it == '\t')) ++it; + while (it != responseText.end() && (*it == ' ' || *it == '\t')) ++it; + + if (it != responseText.end()) { + + size_t size = 0; + + std::istringstream iss(string(it, responseText.end())); + iss.imbue(std::locale::classic()); + iss >> size; + + dynamicCast (msg)->m_size = size; + } + } + } + + if (options.has(fetchAttributes::UID)) { + + // Send the "UIDL" command + POP3Command::UIDL(msg->getNumber())->send(store->getConnection()); + + // Get the response + shared_ptr response = + POP3Response::readResponse(store->getConnection()); + + if (response->isSuccess()) { + + string responseText = response->getText(); + + // C: UIDL 2 + // S: +OK 2 QhdPYR:00WBw1Ph7x7 + string::iterator it = responseText.begin(); + + while (it != responseText.end() && (*it == ' ' || *it == '\t')) ++it; + while (it != responseText.end() && !(*it == ' ' || *it == '\t')) ++it; + while (it != responseText.end() && (*it == ' ' || *it == '\t')) ++it; + + if (it != responseText.end()) { + dynamicCast (msg)->m_uid = string(it, responseText.end()); + } + } + } +} + + +std::vector > POP3Folder::getAndFetchMessages( + const messageSet& msgs, + const fetchAttributes& attribs +) { + + if (msgs.isEmpty()) { + return std::vector >(); + } + + std::vector > messages = getMessages(msgs); + fetchMessages(messages, attribs); + + return messages; +} + + +int POP3Folder::getFetchCapabilities() const { + + return fetchAttributes::ENVELOPE | + fetchAttributes::CONTENT_INFO | + fetchAttributes::SIZE | + fetchAttributes::FULL_HEADER | + fetchAttributes::UID | + fetchAttributes::IMPORTANCE; +} + + +shared_ptr POP3Folder::getParent() { + + if (m_path.isEmpty()) { + return null; + } else { + return shared_ptr (new POP3Folder(m_path.getParent(), m_store.lock())); + } +} + + +shared_ptr POP3Folder::getStore() const { + + return m_store.lock(); +} + + +shared_ptr POP3Folder::getStore() { + + return m_store.lock(); +} + + +void POP3Folder::registerMessage(POP3Message* msg) { + + m_messages.insert(MessageMap::value_type(msg, msg->getNumber())); +} + + +void POP3Folder::unregisterMessage(POP3Message* msg) { + + m_messages.erase(msg); +} + + +void POP3Folder::onStoreDisconnected() { + + m_store.reset(); +} + + +void POP3Folder::deleteMessages(const messageSet& msgs) { + + shared_ptr store = m_store.lock(); + + const std::vector nums = POP3Utils::messageSetToNumberList(msgs, m_messageCount); + + if (nums.empty()) { + throw exceptions::invalid_argument(); + } + + if (!store) { + throw exceptions::illegal_state("Store disconnected"); + } else if (!isOpen()) { + throw exceptions::illegal_state("Folder not open"); + } + + for (std::vector ::const_iterator + it = nums.begin() ; it != nums.end() ; ++it) { + + POP3Command::DELE(*it)->send(store->getConnection()); + + shared_ptr response = + POP3Response::readResponse(store->getConnection()); + + if (!response->isSuccess()) { + throw exceptions::command_error("DELE", response->getFirstLine()); + } + } + + // Sort message list + std::vector list; + + list.resize(nums.size()); + std::copy(nums.begin(), nums.end(), list.begin()); + + std::sort(list.begin(), list.end()); + + // Update local flags + for (std::map ::iterator it = + m_messages.begin() ; it != m_messages.end() ; ++it) { + + POP3Message* msg = (*it).first; + + if (std::binary_search(list.begin(), list.end(), msg->getNumber())) { + msg->m_deleted = true; + } + } + + // Notify message flags changed + shared_ptr event = + make_shared ( + dynamicCast (shared_from_this()), + events::messageChangedEvent::TYPE_FLAGS, + list + ); + + notifyMessageChanged(event); +} + + +void POP3Folder::setMessageFlags( + const messageSet& /* msgs */, + const int /* flags */, + const int /* mode */ +) { + + throw exceptions::operation_not_supported(); +} + + +void POP3Folder::rename(const folder::path& /* newPath */) { + + throw exceptions::operation_not_supported(); +} + + +messageSet POP3Folder::addMessage( + const shared_ptr & /* msg */, + const int /* flags */, + vmime::datetime* /* date */, + utility::progressListener* /* progress */ +) { + + throw exceptions::operation_not_supported(); +} + + +messageSet POP3Folder::addMessage( + utility::inputStream& /* is */, + const size_t /* size */, + const int /* flags */, + vmime::datetime* /* date */, + utility::progressListener* /* progress */ +) { + + throw exceptions::operation_not_supported(); +} + + +messageSet POP3Folder::copyMessages( + const folder::path& /* dest */, + const messageSet& /* msgs */ +) { + + throw exceptions::operation_not_supported(); +} + + +void POP3Folder::status(size_t& count, size_t& unseen) { + + count = 0; + unseen = 0; + + shared_ptr status = getStatus(); + + count = status->getMessageCount(); + unseen = status->getUnseenCount(); + + m_messageCount = count; +} + + +shared_ptr POP3Folder::getStatus() { + + shared_ptr store = m_store.lock(); + + if (!store) { + throw exceptions::illegal_state("Store disconnected"); + } + + POP3Command::STAT()->send(store->getConnection()); + + shared_ptr response = + POP3Response::readResponse(store->getConnection()); + + if (!response->isSuccess()) { + throw exceptions::command_error("STAT", response->getFirstLine()); + } + + + size_t count = 0; + + std::istringstream iss(response->getText()); + iss.imbue(std::locale::classic()); + iss >> count; + + shared_ptr status = make_shared (); + + status->setMessageCount(count); + status->setUnseenCount(count); + + // Update local message count + if (m_messageCount != count) { + + const size_t oldCount = m_messageCount; + + m_messageCount = count; + + if (count > oldCount) { + + std::vector nums; + nums.resize(count - oldCount); + + for (size_t i = oldCount + 1, j = 0 ; i <= count ; ++i, ++j) { + nums[j] = i; + } + + // Notify message count changed + shared_ptr event = + make_shared ( + dynamicCast (shared_from_this()), + events::messageCountEvent::TYPE_ADDED, + nums + ); + + notifyMessageCount(event); + + // Notify folders with the same path + for (std::list ::iterator it = store->m_folders.begin() ; + it != store->m_folders.end() ; ++it) { + + if ((*it) != this && (*it)->getFullPath() == m_path) { + + (*it)->m_messageCount = count; + + shared_ptr event = + make_shared ( + dynamicCast ((*it)->shared_from_this()), + events::messageCountEvent::TYPE_ADDED, + nums + ); + + (*it)->notifyMessageCount(event); + } + } + } + } + + return status; +} + + +void POP3Folder::expunge() { + + // Not supported by POP3 protocol (deleted messages are automatically + // expunged at the end of the session...). +} + + +std::vector POP3Folder::getMessageNumbersStartingOnUID(const message::uid& /* uid */) { + + throw exceptions::operation_not_supported(); +} + + +} // pop3 +} // net +} // vmime + + +#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_POP3 + diff --git a/vmime-master/src/vmime/net/pop3/POP3Folder.hpp b/vmime-master/src/vmime/net/pop3/POP3Folder.hpp new file mode 100644 index 0000000..73e29f9 --- /dev/null +++ b/vmime-master/src/vmime/net/pop3/POP3Folder.hpp @@ -0,0 +1,179 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules is making +// a combined work based on this library. Thus, the terms and conditions of +// the GNU General Public License cover the whole combination. +// + +#ifndef VMIME_NET_POP3_POP3FOLDER_HPP_INCLUDED +#define VMIME_NET_POP3_POP3FOLDER_HPP_INCLUDED + + +#include "vmime/config.hpp" + + +#if VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_POP3 + + +#include +#include + +#include "vmime/types.hpp" + +#include "vmime/net/folder.hpp" + + +namespace vmime { +namespace net { +namespace pop3 { + + +class POP3Store; +class POP3Message; + + +/** POP3 folder implementation. + */ +class VMIME_EXPORT POP3Folder : public folder { + +private: + + friend class POP3Store; + friend class POP3Message; + + POP3Folder(const POP3Folder&); + POP3Folder(const folder::path& path, const shared_ptr & store); + +public: + + ~POP3Folder(); + + int getMode() const; + + const folderAttributes getAttributes(); + + const folder::path::component getName() const; + const folder::path getFullPath() const; + + void open(const int mode, bool failIfModeIsNotAvailable = false); + void close(const bool expunge); + void create(const folderAttributes& attribs); + + bool exists(); + + void destroy(); + + bool isOpen() const; + + shared_ptr getMessage(const size_t num); + std::vector > getMessages(const messageSet& msgs); + + size_t getMessageCount(); + + shared_ptr getFolder(const folder::path::component& name); + std::vector > getFolders(const bool recursive = false); + + void rename(const folder::path& newPath); + + void deleteMessages(const messageSet& msgs); + + void setMessageFlags( + const messageSet& msgs, + const int flags, + const int mode = message::FLAG_MODE_SET + ); + + messageSet addMessage( + const shared_ptr & msg, + const int flags = -1, + vmime::datetime* date = NULL, + utility::progressListener* progress = NULL + ); + + messageSet addMessage( + utility::inputStream& is, + const size_t size, + const int flags = -1, + vmime::datetime* date = NULL, + utility::progressListener* progress = NULL + ); + + messageSet copyMessages(const folder::path& dest, const messageSet& msgs); + + void status(size_t& count, size_t& unseen); + shared_ptr getStatus(); + + void expunge(); + + shared_ptr getParent(); + + shared_ptr getStore() const; + shared_ptr getStore(); + + + void fetchMessages( + std::vector >& msg, + const fetchAttributes& options, + utility::progressListener* progress = NULL + ); + + void fetchMessage(const shared_ptr & msg, const fetchAttributes& options); + + std::vector > getAndFetchMessages( + const messageSet& msgs, + const fetchAttributes& attribs + ); + + int getFetchCapabilities() const; + + std::vector getMessageNumbersStartingOnUID(const message::uid& uid); + +private: + + void registerMessage(POP3Message* msg); + void unregisterMessage(POP3Message* msg); + + void onStoreDisconnected(); + + void onClose(); + + + weak_ptr m_store; + + folder::path m_path; + folder::path::component m_name; + + int m_mode; + bool m_open; + + size_t m_messageCount; + + typedef std::map MessageMap; + MessageMap m_messages; +}; + + +} // pop3 +} // net +} // vmime + + +#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_POP3 + +#endif // VMIME_NET_POP3_POP3FOLDER_HPP_INCLUDED diff --git a/vmime-master/src/vmime/net/pop3/POP3FolderStatus.cpp b/vmime-master/src/vmime/net/pop3/POP3FolderStatus.cpp new file mode 100644 index 0000000..9f2c49f --- /dev/null +++ b/vmime-master/src/vmime/net/pop3/POP3FolderStatus.cpp @@ -0,0 +1,88 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules is making +// a combined work based on this library. Thus, the terms and conditions of +// the GNU General Public License cover the whole combination. +// + +#include "vmime/config.hpp" + + +#if VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_POP3 + + +#include "vmime/net/pop3/POP3FolderStatus.hpp" + + +namespace vmime { +namespace net { +namespace pop3 { + + +POP3FolderStatus::POP3FolderStatus() + : m_count(0), + m_unseen(0) { + +} + + +POP3FolderStatus::POP3FolderStatus(const POP3FolderStatus& other) + : folderStatus(), + m_count(other.m_count), + m_unseen(other.m_unseen) { + +} + + +size_t POP3FolderStatus::getMessageCount() const { + + return m_count; +} + + +size_t POP3FolderStatus::getUnseenCount() const { + + return m_unseen; +} + + +void POP3FolderStatus::setMessageCount(const size_t count) { + + m_count = count; +} + + +void POP3FolderStatus::setUnseenCount(const size_t unseen) { + + m_unseen = unseen; +} + + +shared_ptr POP3FolderStatus::clone() const { + + return make_shared (*this); +} + + +} // pop3 +} // net +} // vmime + + +#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_POP3 diff --git a/vmime-master/src/vmime/net/pop3/POP3FolderStatus.hpp b/vmime-master/src/vmime/net/pop3/POP3FolderStatus.hpp new file mode 100644 index 0000000..0ce413e --- /dev/null +++ b/vmime-master/src/vmime/net/pop3/POP3FolderStatus.hpp @@ -0,0 +1,75 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules is making +// a combined work based on this library. Thus, the terms and conditions of +// the GNU General Public License cover the whole combination. +// + +#ifndef VMIME_NET_POP3_POP3FOLDERSTATUS_HPP_INCLUDED +#define VMIME_NET_POP3_POP3FOLDERSTATUS_HPP_INCLUDED + + +#include "vmime/config.hpp" + + +#if VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_POP3 + + +#include "vmime/net/folderStatus.hpp" + + +namespace vmime { +namespace net { +namespace pop3 { + + +/** Holds the status of a POP3 folder. + */ +class VMIME_EXPORT POP3FolderStatus : public folderStatus { + +public: + + POP3FolderStatus(); + POP3FolderStatus(const POP3FolderStatus& other); + + // Inherited from folderStatus + size_t getMessageCount() const; + size_t getUnseenCount() const; + + shared_ptr clone() const; + + + void setMessageCount(const size_t count); + void setUnseenCount(const size_t unseen); + +private: + + size_t m_count; + size_t m_unseen; +}; + + +} // pop3 +} // net +} // vmime + + +#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_POP3 + +#endif // VMIME_NET_POP3_POP3FOLDERSTATUS_HPP_INCLUDED diff --git a/vmime-master/src/vmime/net/pop3/POP3Message.cpp b/vmime-master/src/vmime/net/pop3/POP3Message.cpp new file mode 100644 index 0000000..8d6b7f5 --- /dev/null +++ b/vmime-master/src/vmime/net/pop3/POP3Message.cpp @@ -0,0 +1,283 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules is making +// a combined work based on this library. Thus, the terms and conditions of +// the GNU General Public License cover the whole combination. +// + +#include "vmime/config.hpp" + + +#if VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_POP3 + + +#include "vmime/net/pop3/POP3Message.hpp" +#include "vmime/net/pop3/POP3Command.hpp" +#include "vmime/net/pop3/POP3Response.hpp" +#include "vmime/net/pop3/POP3Folder.hpp" +#include "vmime/net/pop3/POP3Store.hpp" + +#include "vmime/utility/outputStreamAdapter.hpp" +#include "vmime/utility/outputStreamStringAdapter.hpp" + +#include + + +namespace vmime { +namespace net { +namespace pop3 { + + +POP3Message::POP3Message( + const shared_ptr & folder, + const size_t num +) + : m_folder(folder), + m_num(num), + m_size(-1), + m_deleted(false) { + + folder->registerMessage(this); +} + + +POP3Message::~POP3Message() { + + try { + + shared_ptr folder = m_folder.lock(); + + if (folder) { + folder->unregisterMessage(this); + } + + } catch (...) { + + // Don't throw in destructor + } +} + + +void POP3Message::onFolderClosed() { + + m_folder.reset(); +} + + +size_t POP3Message::getNumber() const { + + return m_num; +} + + +const message::uid POP3Message::getUID() const { + + return m_uid; +} + + +size_t POP3Message::getSize() const { + + if (m_size == static_cast (-1)) { + throw exceptions::unfetched_object(); + } + + return m_size; +} + + +bool POP3Message::isExpunged() const { + + return false; +} + + +int POP3Message::getFlags() const { + + int flags = 0; + + if (m_deleted) { + flags |= FLAG_DELETED; + } + + return flags; +} + + +shared_ptr POP3Message::getStructure() const { + + throw exceptions::operation_not_supported(); +} + + +shared_ptr POP3Message::getStructure() { + + throw exceptions::operation_not_supported(); +} + + +shared_ptr POP3Message::getHeader() const { + + if (!m_header) { + throw exceptions::unfetched_object(); + } + + return m_header; +} + + +void POP3Message::extract( + utility::outputStream& os, + utility::progressListener* progress, + const size_t start, + const size_t length, + const bool /* peek */ +) const { + + shared_ptr folder = m_folder.lock(); + + if (!folder) { + throw exceptions::illegal_state("Folder closed"); + } else if (!folder->getStore()) { + throw exceptions::illegal_state("Store disconnected"); + } + + if (start != 0 && length != static_cast (-1)) { + throw exceptions::partial_fetch_not_supported(); + } + + // Emit the "RETR" command + shared_ptr store = folder->m_store.lock(); + + POP3Command::RETR(m_num)->send(store->getConnection()); + + try { + + POP3Response::readLargeResponse( + store->getConnection(), os, progress, + m_size == static_cast (-1) ? 0 : m_size + ); + + } catch (exceptions::command_error& e) { + + throw exceptions::command_error("RETR", e.response()); + } +} + + +void POP3Message::extractPart( + const shared_ptr & /* p */, + utility::outputStream& /* os */, + utility::progressListener* /* progress */, + const size_t /* start */, + const size_t /* length */, + const bool /* peek */ +) const { + + throw exceptions::operation_not_supported(); +} + + +void POP3Message::fetchPartHeader(const shared_ptr & /* p */) { + + throw exceptions::operation_not_supported(); +} + + +void POP3Message::fetch( + const shared_ptr & msgFolder, + const fetchAttributes& options +) { + + shared_ptr folder = m_folder.lock(); + + if (folder != msgFolder) { + throw exceptions::folder_not_found(); + } + + // STRUCTURE and FLAGS attributes are not supported by POP3 + if (options.has(fetchAttributes::STRUCTURE | fetchAttributes::FLAGS)) { + throw exceptions::operation_not_supported(); + } + + // Check for the real need to fetch the full header + static const int optionsRequiringHeader = + fetchAttributes::ENVELOPE | fetchAttributes::CONTENT_INFO | + fetchAttributes::FULL_HEADER | fetchAttributes::IMPORTANCE; + + if (!options.has(optionsRequiringHeader)) { + return; + } + + // No need to differenciate between ENVELOPE, CONTENT_INFO, ... + // since POP3 only permits to retrieve the whole header and not + // fields in particular. + + // Emit the "TOP" command + shared_ptr store = folder->m_store.lock(); + + POP3Command::TOP(m_num, 0)->send(store->getConnection()); + + try { + + string buffer; + utility::outputStreamStringAdapter bufferStream(buffer); + + POP3Response::readLargeResponse( + store->getConnection(), + bufferStream, /* progress */ NULL, /* predictedSize */ 0 + ); + + m_header = make_shared
(); + m_header->parse(buffer); + + } catch (exceptions::command_error& e) { + + throw exceptions::command_error("TOP", e.response()); + } +} + + +void POP3Message::setFlags(const int /* flags */, const int /* mode */) { + + throw exceptions::operation_not_supported(); +} + + +shared_ptr POP3Message::getParsedMessage() { + + std::ostringstream oss; + utility::outputStreamAdapter os(oss); + + extract(os); + + shared_ptr msg = make_shared (); + msg->parse(oss.str()); + + return msg; +} + + +} // pop3 +} // net +} // vmime + + +#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_POP3 + diff --git a/vmime-master/src/vmime/net/pop3/POP3Message.hpp b/vmime-master/src/vmime/net/pop3/POP3Message.hpp new file mode 100644 index 0000000..3d6dc92 --- /dev/null +++ b/vmime-master/src/vmime/net/pop3/POP3Message.hpp @@ -0,0 +1,124 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules is making +// a combined work based on this library. Thus, the terms and conditions of +// the GNU General Public License cover the whole combination. +// + +#ifndef VMIME_NET_POP3_POP3MESSAGE_HPP_INCLUDED +#define VMIME_NET_POP3_POP3MESSAGE_HPP_INCLUDED + + +#include "vmime/config.hpp" + + +#if VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_POP3 + + +#include "vmime/net/message.hpp" +#include "vmime/net/folder.hpp" + + +namespace vmime { +namespace net { +namespace pop3 { + + +class POP3Folder; + + +/** POP3 message implementation. + */ +class VMIME_EXPORT POP3Message : public message { + +private: + + friend class POP3Folder; + + POP3Message(const POP3Message&); + +public: + + POP3Message(const shared_ptr & folder, const size_t num); + + ~POP3Message(); + + + size_t getNumber() const; + + const uid getUID() const; + + size_t getSize() const; + + bool isExpunged() const; + + shared_ptr getStructure() const; + shared_ptr getStructure(); + + shared_ptr getHeader() const; + + int getFlags() const; + void setFlags(const int flags, const int mode = FLAG_MODE_SET); + + void extract( + utility::outputStream& os, + utility::progressListener* progress = NULL, + const size_t start = 0, + const size_t length = -1, + const bool peek = false + ) const; + + void extractPart( + const shared_ptr & p, + utility::outputStream& os, + utility::progressListener* progress = NULL, + const size_t start = 0, + const size_t length = -1, + const bool peek = false + ) const; + + void fetchPartHeader(const shared_ptr & p); + + shared_ptr getParsedMessage(); + +private: + + void fetch(const shared_ptr & folder, const fetchAttributes& options); + + void onFolderClosed(); + + weak_ptr m_folder; + size_t m_num; + uid m_uid; + size_t m_size; + + bool m_deleted; + + shared_ptr
m_header; +}; + + +} // pop3 +} // net +} // vmime + + +#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_POP3 + +#endif // VMIME_NET_POP3_POP3MESSAGE_HPP_INCLUDED diff --git a/vmime-master/src/vmime/net/pop3/POP3Response.cpp b/vmime-master/src/vmime/net/pop3/POP3Response.cpp new file mode 100644 index 0000000..725841e --- /dev/null +++ b/vmime-master/src/vmime/net/pop3/POP3Response.cpp @@ -0,0 +1,504 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules is making +// a combined work based on this library. Thus, the terms and conditions of +// the GNU General Public License cover the whole combination. +// + +#include "vmime/config.hpp" + + +#if VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_POP3 + + +#include "vmime/net/pop3/POP3Response.hpp" +#include "vmime/net/pop3/POP3Connection.hpp" + +#include "vmime/platform.hpp" + +#include "vmime/utility/stringUtils.hpp" +#include "vmime/utility/filteredStream.hpp" +#include "vmime/utility/stringUtils.hpp" +#include "vmime/utility/inputStreamSocketAdapter.hpp" + +#include "vmime/net/socket.hpp" +#include "vmime/net/timeoutHandler.hpp" + + +namespace vmime { +namespace net { +namespace pop3 { + + +POP3Response::POP3Response( + const shared_ptr & sok, + const shared_ptr & toh, + const shared_ptr & tracer +) + : m_socket(sok), + m_timeoutHandler(toh), + m_tracer(tracer) { + +} + + +// static +shared_ptr POP3Response::readResponse( + const shared_ptr & conn +) { + + shared_ptr resp = shared_ptr ( + new POP3Response(conn->getSocket(), conn->getTimeoutHandler(), conn->getTracer()) + ); + + string buffer; + resp->readResponseImpl(buffer, /* multiLine */ false); + + resp->m_firstLine = buffer; + resp->m_code = getResponseCode(buffer); + stripResponseCode(buffer, resp->m_text); + + if (resp->m_tracer) { + resp->m_tracer->traceReceive(buffer); + } + + return resp; +} + + +// static +shared_ptr POP3Response::readMultilineResponse( + const shared_ptr & conn +) { + + shared_ptr resp = shared_ptr ( + new POP3Response(conn->getSocket(), conn->getTimeoutHandler(), conn->getTracer()) + ); + + string buffer; + resp->readResponseImpl(buffer, /* multiLine */ true); + + string firstLine, nextLines; + stripFirstLine(buffer, nextLines, &firstLine); + + resp->m_firstLine = firstLine; + resp->m_code = getResponseCode(firstLine); + stripResponseCode(firstLine, resp->m_text); + + std::istringstream iss(nextLines); + string line; + + if (resp->m_tracer) { + resp->m_tracer->traceReceive(firstLine); + } + + while (std::getline(iss, line, '\n')) { + + line = utility::stringUtils::trim(line); + resp->m_lines.push_back(line); + + if (resp->m_tracer) { + resp->m_tracer->traceReceive(line); + } + } + + if (resp->m_tracer) { + resp->m_tracer->traceReceive("."); + } + + return resp; +} + + +// static +shared_ptr POP3Response::readLargeResponse( + const shared_ptr & conn, + utility::outputStream& os, + utility::progressListener* progress, + const size_t predictedSize +) { + + shared_ptr resp = shared_ptr ( + new POP3Response(conn->getSocket(), conn->getTimeoutHandler(), conn->getTracer()) + ); + + string firstLine; + const size_t length = resp->readResponseImpl(firstLine, os, progress, predictedSize); + + resp->m_firstLine = firstLine; + resp->m_code = getResponseCode(firstLine); + stripResponseCode(firstLine, resp->m_text); + + if (resp->m_tracer) { + resp->m_tracer->traceReceive(firstLine); + resp->m_tracer->traceReceiveBytes(length - firstLine.length()); + resp->m_tracer->traceReceive("."); + } + + return resp; +} + + +bool POP3Response::isSuccess() const { + + return m_code == CODE_OK; +} + + +const string POP3Response::getFirstLine() const { + + return m_firstLine; +} + + +POP3Response::ResponseCode POP3Response::getCode() const { + + return m_code; +} + + +const string POP3Response::getText() const { + + return m_text; +} + + +const string POP3Response::getLineAt(const size_t pos) const { + + return m_lines[pos]; +} + + +size_t POP3Response::getLineCount() const { + + return m_lines.size(); +} + + +void POP3Response::readResponseImpl(string& buffer, const bool multiLine) { + + bool foundTerminator = false; + + if (m_timeoutHandler) { + m_timeoutHandler->resetTimeOut(); + } + + buffer.clear(); + + char last1 = '\0', last2 = '\0'; + + for ( ; !foundTerminator ; ) { + + // Check whether the time-out delay is elapsed + if (m_timeoutHandler && m_timeoutHandler->isTimeOut()) { + + if (!m_timeoutHandler->handleTimeOut()) { + throw exceptions::operation_timed_out(); + } + + m_timeoutHandler->resetTimeOut(); + } + + // Receive data from the socket + string receiveBuffer; + m_socket->receive(receiveBuffer); + + if (receiveBuffer.empty()) { // buffer is empty + + if (m_socket->getStatus() & socket::STATUS_WANT_WRITE) { + m_socket->waitForWrite(); + } else { + m_socket->waitForRead(); + } + + continue; + } + + // We have received data: reset the time-out counter + if (m_timeoutHandler) { + m_timeoutHandler->resetTimeOut(); + } + + // Check for transparent characters: '\n..' becomes '\n.' + const char first = receiveBuffer[0]; + + if (first == '.' && last2 == '\n' && last1 == '.') { + + receiveBuffer.erase(receiveBuffer.begin()); + + } else if (receiveBuffer.length() >= 2 && first == '.' && + receiveBuffer[1] == '.' && last1 == '\n') { + + receiveBuffer.erase(receiveBuffer.begin()); + } + + for (size_t trans ; + string::npos != (trans = receiveBuffer.find("\n..")) ; ) { + + receiveBuffer.replace(trans, 3, "\n."); + } + + last1 = receiveBuffer[receiveBuffer.length() - 1]; + last2 = static_cast ((receiveBuffer.length() >= 2) ? receiveBuffer[receiveBuffer.length() - 2] : 0); + + // Append the data to the response buffer + buffer += receiveBuffer; + + // Check for terminator string (and strip it if present) + foundTerminator = checkTerminator(buffer, multiLine); + + // If there is an error (-ERR) when executing a command that + // requires a multi-line response, the error response will + // include only one line, so we stop waiting for a multi-line + // terminator and check for a "normal" one. + if (multiLine && + !foundTerminator && + buffer.length() >= 4 && buffer[0] == '-') { + + foundTerminator = checkTerminator(buffer, false); + } + } +} + + +size_t POP3Response::readResponseImpl( + string& firstLine, + utility::outputStream& os, + utility::progressListener* progress, + const size_t predictedSize +) { + + size_t current = 0, total = predictedSize; + + string temp; + bool codeDone = false; + + if (progress) { + progress->start(total); + } + + if (m_timeoutHandler) { + m_timeoutHandler->resetTimeOut(); + } + + utility::inputStreamSocketAdapter sis(*m_socket); + utility::stopSequenceFilteredInputStream <5> sfis1(sis, "\r\n.\r\n"); + utility::stopSequenceFilteredInputStream <3> sfis2(sfis1, "\n.\n"); + utility::dotFilteredInputStream dfis(sfis2); // "\n.." --> "\n." + + utility::inputStream& is = dfis; + + while (!is.eof()) { + + // Check whether the time-out delay is elapsed + if (m_timeoutHandler && m_timeoutHandler->isTimeOut()) { + + if (!m_timeoutHandler->handleTimeOut()) { + throw exceptions::operation_timed_out(); + } + } + + // Receive data from the socket + byte_t buffer[65536]; + const size_t read = is.read(buffer, sizeof(buffer)); + + if (read == 0) { // buffer is empty + + if (m_socket->getStatus() & socket::STATUS_WANT_WRITE) { + m_socket->waitForWrite(); + } else if (m_socket->getStatus() & socket::STATUS_WANT_READ) { + m_socket->waitForRead(); + } else { + // Input stream needs more bytes to continue, but there + // is enough data into socket buffer. Do not waitForRead(), + // just retry read()ing on the stream. + } + + continue; + } + + // We have received data: reset the time-out counter + if (m_timeoutHandler) { + m_timeoutHandler->resetTimeOut(); + } + + // Notify progress + current += read; + + if (progress) { + total = std::max(total, current); + progress->progress(current, total); + } + + // If we don't have extracted the response code yet + if (!codeDone) { + + vmime::utility::stringUtils::appendBytesToString(temp, buffer, read); + + string responseData; + + if (stripFirstLine(temp, responseData, &firstLine) == true) { + + if (getResponseCode(firstLine) != CODE_OK) { + throw exceptions::command_error("?", firstLine); + } + + codeDone = true; + + os.write(responseData.data(), responseData.length()); + temp.clear(); + + continue; + } + + } else { + + // Inject the data into the output stream + os.write(buffer, read); + } + } + + if (progress) { + progress->stop(total); + } + + return current; +} + + +// static +bool POP3Response::stripFirstLine( + const string& buffer, + string& result, + string* firstLine +) { + + const size_t end = buffer.find('\n'); + + if (end != string::npos) { + + if (firstLine) { + *firstLine = utility::stringUtils::trim(buffer.substr(0, end)); + } + + result = buffer.substr(end + 1); + + return true; + + } else { + + if (firstLine) { + *firstLine = utility::stringUtils::trim(buffer); + } + + result = ""; + + return false; + } +} + + +// static +POP3Response::ResponseCode POP3Response::getResponseCode(const string& buffer) { + + if (buffer.length() >= 2) { + + // +[space] + if (buffer[0] == '+' && + (buffer[1] == ' ' || buffer[1] == '\t')) { + + return CODE_READY; + } + + // +OK + if (buffer.length() >= 3) { + + if (buffer[0] == '+' && + (buffer[1] == 'O' || buffer[1] == 'o') && + (buffer[2] == 'K' || buffer[1] == 'k')) { + + return CODE_OK; + } + } + } + + // -ERR or whatever + return CODE_ERR; +} + + +// static +void POP3Response::stripResponseCode(const string& buffer, string& result) { + + const size_t pos = buffer.find_first_of(" \t"); + + if (pos != string::npos) { + result = buffer.substr(pos + 1); + } else { + result = buffer; + } +} + + +// static +bool POP3Response::checkTerminator(string& buffer, const bool multiLine) { + + // Multi-line response + if (multiLine) { + + static const string term1("\r\n.\r\n"); + static const string term2("\n.\n"); + + return checkOneTerminator(buffer, term1) || + checkOneTerminator(buffer, term2); + + // Normal response + } else { + + static const string term1("\r\n"); + static const string term2("\n"); + + return checkOneTerminator(buffer, term1) || + checkOneTerminator(buffer, term2); + } + + return false; +} + + +// static +bool POP3Response::checkOneTerminator(string& buffer, const string& term) { + + if (buffer.length() >= term.length() && + std::equal(buffer.end() - term.length(), buffer.end(), term.begin())) { + + buffer.erase(buffer.end() - term.length(), buffer.end()); + return true; + } + + return false; +} + + +} // pop3 +} // net +} // vmime + + +#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_POP3 diff --git a/vmime-master/src/vmime/net/pop3/POP3Response.hpp b/vmime-master/src/vmime/net/pop3/POP3Response.hpp new file mode 100644 index 0000000..69f8d5d --- /dev/null +++ b/vmime-master/src/vmime/net/pop3/POP3Response.hpp @@ -0,0 +1,194 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules is making +// a combined work based on this library. Thus, the terms and conditions of +// the GNU General Public License cover the whole combination. +// + +#ifndef VMIME_NET_SMTP_POP3RESPONSE_HPP_INCLUDED +#define VMIME_NET_SMTP_POP3RESPONSE_HPP_INCLUDED + + +#include "vmime/config.hpp" + + +#if VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_POP3 + + +#include "vmime/object.hpp" +#include "vmime/base.hpp" + +#include "vmime/utility/outputStream.hpp" +#include "vmime/utility/progressListener.hpp" + +#include "vmime/net/socket.hpp" +#include "vmime/net/tracer.hpp" + + +namespace vmime { +namespace net { + + +class timeoutHandler; + + +namespace pop3 { + + +class POP3Connection; + + +/** A POP3 response, as sent by the server. + */ +class VMIME_EXPORT POP3Response : public object { + +public: + + /** Possible response codes. */ + enum ResponseCode { + CODE_OK = 0, + CODE_READY, + CODE_ERR + }; + + + /** Receive and parse a POP3 response from the + * specified connection. + * + * @param conn connection from which to read + * @return POP3 response + * @throws exceptions::operation_timed_out if no data + * has been received within the granted time + */ + static shared_ptr readResponse(const shared_ptr & conn); + + /** Receive and parse a multiline POP3 response from + * the specified connection. + * + * @param conn connection from which to read + * @return POP3 response + * @throws exceptions::operation_timed_out if no data + * has been received within the granted time + */ + static shared_ptr readMultilineResponse(const shared_ptr & conn); + + /** Receive and parse a large POP3 response (eg. message data) + * from the specified connection. + * + * @param conn connection from which to read + * @param os output stream to which response data will be written + * @param progress progress listener (can be NULL) + * @param predictedSize estimated size of response data (in bytes) + * @return POP3 response + * @throws exceptions::operation_timed_out if no data + * has been received within the granted time + */ + static shared_ptr readLargeResponse( + const shared_ptr & conn, + utility::outputStream& os, + utility::progressListener* progress, + const size_t predictedSize + ); + + + /** Returns whether the response is successful ("OK"). + * + * @return true if the response if successful, false otherwise + */ + bool isSuccess() const; + + /** Return the POP3 response code. + * + * @return response code + */ + ResponseCode getCode() const; + + /** Return the POP3 response text (first line). + * + * @return response text + */ + const string getText() const; + + /** Return the first POP3 response line. + * + * @return first response line + */ + const string getFirstLine() const; + + /** Return the response line at the specified position. + * + * @param pos line index + * @return line at the specified index + */ + const string getLineAt(const size_t pos) const; + + /** Return the number of lines in the response. + * + * @return number of lines in the response + */ + size_t getLineCount() const; + +private: + + POP3Response( + const shared_ptr & sok, + const shared_ptr & toh, + const shared_ptr & tracer + ); + + void readResponseImpl(string& buffer, const bool multiLine); + + size_t readResponseImpl( + string& firstLine, + utility::outputStream& os, + utility::progressListener* progress, + const size_t predictedSize + ); + + + static bool stripFirstLine(const string& buffer, string& result, string* firstLine); + + static ResponseCode getResponseCode(const string& buffer); + + static void stripResponseCode(const string& buffer, string& result); + + static bool checkTerminator(string& buffer, const bool multiLine); + static bool checkOneTerminator(string& buffer, const string& term); + + + shared_ptr m_socket; + shared_ptr m_timeoutHandler; + shared_ptr m_tracer; + + string m_firstLine; + ResponseCode m_code; + string m_text; + + std::vector m_lines; +}; + + +} // pop3 +} // net +} // vmime + + +#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_POP3 + +#endif // VMIME_NET_SMTP_POP3RESPONSE_HPP_INCLUDED diff --git a/vmime-master/src/vmime/net/pop3/POP3SStore.cpp b/vmime-master/src/vmime/net/pop3/POP3SStore.cpp new file mode 100644 index 0000000..81a50bc --- /dev/null +++ b/vmime-master/src/vmime/net/pop3/POP3SStore.cpp @@ -0,0 +1,82 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules is making +// a combined work based on this library. Thus, the terms and conditions of +// the GNU General Public License cover the whole combination. +// + +#include "vmime/config.hpp" + + +#if VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_POP3 + + +#include "vmime/net/pop3/POP3SStore.hpp" + + +namespace vmime { +namespace net { +namespace pop3 { + + +POP3SStore::POP3SStore( + const shared_ptr & sess, + const shared_ptr & auth +) + : POP3Store(sess, auth, true) { + +} + + +POP3SStore::~POP3SStore() { + +} + + +const string POP3SStore::getProtocolName() const { + + return "pop3s"; +} + + + +// Service infos + +POP3ServiceInfos POP3SStore::sm_infos(true); + + +const serviceInfos& POP3SStore::getInfosInstance() { + + return sm_infos; +} + + +const serviceInfos& POP3SStore::getInfos() const { + + return sm_infos; +} + + +} // pop3 +} // net +} // vmime + + +#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_POP3 + diff --git a/vmime-master/src/vmime/net/pop3/POP3SStore.hpp b/vmime-master/src/vmime/net/pop3/POP3SStore.hpp new file mode 100644 index 0000000..76a6ee1 --- /dev/null +++ b/vmime-master/src/vmime/net/pop3/POP3SStore.hpp @@ -0,0 +1,74 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules is making +// a combined work based on this library. Thus, the terms and conditions of +// the GNU General Public License cover the whole combination. +// + +#ifndef VMIME_NET_POP3_POP3SSTORE_HPP_INCLUDED +#define VMIME_NET_POP3_POP3SSTORE_HPP_INCLUDED + + +#include "vmime/config.hpp" + + +#if VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_POP3 + + +#include "vmime/net/pop3/POP3Store.hpp" + + +namespace vmime { +namespace net { +namespace pop3 { + + +/** POP3S store service. + */ +class VMIME_EXPORT POP3SStore : public POP3Store { + +public: + + POP3SStore( + const shared_ptr & sess, + const shared_ptr & auth + ); + + ~POP3SStore(); + + const string getProtocolName() const; + + static const serviceInfos& getInfosInstance(); + const serviceInfos& getInfos() const; + +private: + + static POP3ServiceInfos sm_infos; +}; + + +} // pop3 +} // net +} // vmime + + +#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_POP3 + +#endif // VMIME_NET_POP3_POP3SSTORE_HPP_INCLUDED + diff --git a/vmime-master/src/vmime/net/pop3/POP3ServiceInfos.cpp b/vmime-master/src/vmime/net/pop3/POP3ServiceInfos.cpp new file mode 100644 index 0000000..4deee74 --- /dev/null +++ b/vmime-master/src/vmime/net/pop3/POP3ServiceInfos.cpp @@ -0,0 +1,142 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules is making +// a combined work based on this library. Thus, the terms and conditions of +// the GNU General Public License cover the whole combination. +// + +#include "vmime/config.hpp" + + +#if VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_POP3 + + +#include "vmime/net/pop3/POP3ServiceInfos.hpp" + + +namespace vmime { +namespace net { +namespace pop3 { + + +POP3ServiceInfos::POP3ServiceInfos(const bool pop3s) + : m_pop3s(pop3s) { + +} + + +const string POP3ServiceInfos::getPropertyPrefix() const { + + if (m_pop3s) { + return "store.pop3s."; + } else { + return "store.pop3."; + } +} + + +const POP3ServiceInfos::props& POP3ServiceInfos::getProperties() const { + + static props pop3Props = { + // POP3-specific options + property("options.apop", serviceInfos::property::TYPE_BOOLEAN, "true"), + property("options.apop.fallback", serviceInfos::property::TYPE_BOOLEAN, "true"), +#if VMIME_HAVE_SASL_SUPPORT + property("options.sasl", serviceInfos::property::TYPE_BOOLEAN, "true"), + property("options.sasl.fallback", serviceInfos::property::TYPE_BOOLEAN, "true"), +#endif // VMIME_HAVE_SASL_SUPPORT + + // Common properties + property(serviceInfos::property::AUTH_USERNAME, serviceInfos::property::FLAG_REQUIRED), + property(serviceInfos::property::AUTH_PASSWORD, serviceInfos::property::FLAG_REQUIRED), + +#if VMIME_HAVE_TLS_SUPPORT + property(serviceInfos::property::CONNECTION_TLS), + property(serviceInfos::property::CONNECTION_TLS_REQUIRED), +#endif // VMIME_HAVE_TLS_SUPPORT + + property(serviceInfos::property::SERVER_ADDRESS, serviceInfos::property::FLAG_REQUIRED), + property(serviceInfos::property::SERVER_PORT, "110"), + }; + + static props pop3sProps = { + + // POP3-specific options + property("options.apop", serviceInfos::property::TYPE_BOOLEAN, "true"), + property("options.apop.fallback", serviceInfos::property::TYPE_BOOLEAN, "true"), +#if VMIME_HAVE_SASL_SUPPORT + property("options.sasl", serviceInfos::property::TYPE_BOOLEAN, "true"), + property("options.sasl.fallback", serviceInfos::property::TYPE_BOOLEAN, "true"), +#endif // VMIME_HAVE_SASL_SUPPORT + + // Common properties + property(serviceInfos::property::AUTH_USERNAME, serviceInfos::property::FLAG_REQUIRED), + property(serviceInfos::property::AUTH_PASSWORD, serviceInfos::property::FLAG_REQUIRED), + +#if VMIME_HAVE_TLS_SUPPORT + property(serviceInfos::property::CONNECTION_TLS), + property(serviceInfos::property::CONNECTION_TLS_REQUIRED), +#endif // VMIME_HAVE_TLS_SUPPORT + + property(serviceInfos::property::SERVER_ADDRESS, serviceInfos::property::FLAG_REQUIRED), + property(serviceInfos::property::SERVER_PORT, "995"), + }; + + return m_pop3s ? pop3sProps : pop3Props; +} + + +const std::vector POP3ServiceInfos::getAvailableProperties() const { + + std::vector list; + const props& p = getProperties(); + + // POP3-specific options + list.push_back(p.PROPERTY_OPTIONS_APOP); + list.push_back(p.PROPERTY_OPTIONS_APOP_FALLBACK); +#if VMIME_HAVE_SASL_SUPPORT + list.push_back(p.PROPERTY_OPTIONS_SASL); + list.push_back(p.PROPERTY_OPTIONS_SASL_FALLBACK); +#endif // VMIME_HAVE_SASL_SUPPORT + + // Common properties + list.push_back(p.PROPERTY_AUTH_USERNAME); + list.push_back(p.PROPERTY_AUTH_PASSWORD); + +#if VMIME_HAVE_TLS_SUPPORT + if (!m_pop3s) { + list.push_back(p.PROPERTY_CONNECTION_TLS); + list.push_back(p.PROPERTY_CONNECTION_TLS_REQUIRED); + } +#endif // VMIME_HAVE_TLS_SUPPORT + + list.push_back(p.PROPERTY_SERVER_ADDRESS); + list.push_back(p.PROPERTY_SERVER_PORT); + + return list; +} + + +} // pop3 +} // net +} // vmime + + +#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_POP3 + diff --git a/vmime-master/src/vmime/net/pop3/POP3ServiceInfos.hpp b/vmime-master/src/vmime/net/pop3/POP3ServiceInfos.hpp new file mode 100644 index 0000000..590a6be --- /dev/null +++ b/vmime-master/src/vmime/net/pop3/POP3ServiceInfos.hpp @@ -0,0 +1,91 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules is making +// a combined work based on this library. Thus, the terms and conditions of +// the GNU General Public License cover the whole combination. +// + +#ifndef VMIME_NET_POP3_POP3SERVICEINFOS_HPP_INCLUDED +#define VMIME_NET_POP3_POP3SERVICEINFOS_HPP_INCLUDED + + +#include "vmime/config.hpp" + + +#if VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_POP3 + + +#include "vmime/net/serviceInfos.hpp" + + +namespace vmime { +namespace net { +namespace pop3 { + + +/** Information about POP3 service. + */ +class VMIME_EXPORT POP3ServiceInfos : public serviceInfos { + +public: + + POP3ServiceInfos(const bool pop3s); + + struct props { + // POP3-specific options + serviceInfos::property PROPERTY_OPTIONS_APOP; + serviceInfos::property PROPERTY_OPTIONS_APOP_FALLBACK; +#if VMIME_HAVE_SASL_SUPPORT + serviceInfos::property PROPERTY_OPTIONS_SASL; + serviceInfos::property PROPERTY_OPTIONS_SASL_FALLBACK; +#endif // VMIME_HAVE_SASL_SUPPORT + + // Common properties + serviceInfos::property PROPERTY_AUTH_USERNAME; + serviceInfos::property PROPERTY_AUTH_PASSWORD; + +#if VMIME_HAVE_TLS_SUPPORT + serviceInfos::property PROPERTY_CONNECTION_TLS; + serviceInfos::property PROPERTY_CONNECTION_TLS_REQUIRED; +#endif // VMIME_HAVE_TLS_SUPPORT + + serviceInfos::property PROPERTY_SERVER_ADDRESS; + serviceInfos::property PROPERTY_SERVER_PORT; + }; + + const props& getProperties() const; + + const string getPropertyPrefix() const; + const std::vector getAvailableProperties() const; + +private: + + const bool m_pop3s; +}; + + +} // pop3 +} // net +} // vmime + + +#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_POP3 + +#endif // VMIME_NET_POP3_POP3SERVICEINFOS_HPP_INCLUDED + diff --git a/vmime-master/src/vmime/net/pop3/POP3Store.cpp b/vmime-master/src/vmime/net/pop3/POP3Store.cpp new file mode 100644 index 0000000..b06640f --- /dev/null +++ b/vmime-master/src/vmime/net/pop3/POP3Store.cpp @@ -0,0 +1,262 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules is making +// a combined work based on this library. Thus, the terms and conditions of +// the GNU General Public License cover the whole combination. +// + +#include "vmime/config.hpp" + + +#if VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_POP3 + + +#include "vmime/net/pop3/POP3Store.hpp" +#include "vmime/net/pop3/POP3Folder.hpp" +#include "vmime/net/pop3/POP3Command.hpp" +#include "vmime/net/pop3/POP3Response.hpp" + +#include "vmime/exception.hpp" + +#include + + +namespace vmime { +namespace net { +namespace pop3 { + + +POP3Store::POP3Store( + const shared_ptr & sess, + const shared_ptr & auth, + const bool secured +) + : store(sess, getInfosInstance(), auth), + m_isPOP3S(secured) { + +} + + +POP3Store::~POP3Store() { + + try { + + if (isConnected()) { + disconnect(); + } + + } catch (...) { + + // Don't throw in destructor + } +} + + +const string POP3Store::getProtocolName() const { + + return "pop3"; +} + + +shared_ptr POP3Store::getDefaultFolder() { + + if (!isConnected()) { + throw exceptions::illegal_state("Not connected"); + } + + return shared_ptr ( + new POP3Folder( + folder::path(folder::path::component("INBOX")), + dynamicCast (shared_from_this()) + ) + ); +} + + +shared_ptr POP3Store::getRootFolder() { + + if (!isConnected()) { + throw exceptions::illegal_state("Not connected"); + } + + return shared_ptr ( + new POP3Folder( + folder::path(), + dynamicCast (shared_from_this()) + ) + ); +} + + +shared_ptr POP3Store::getFolder(const folder::path& path) { + + if (!isConnected()) { + throw exceptions::illegal_state("Not connected"); + } + + return shared_ptr ( + new POP3Folder( + path, + dynamicCast (shared_from_this()) + ) + ); +} + + +bool POP3Store::isValidFolderName(const folder::path::component& /* name */) const { + + return true; +} + + +void POP3Store::connect() { + + if (isConnected()) { + throw exceptions::already_connected(); + } + + m_connection = make_shared ( + dynamicCast (shared_from_this()), getAuthenticator() + ); + + m_connection->connect(); +} + + +bool POP3Store::isPOP3S() const { + + return m_isPOP3S; +} + + +bool POP3Store::isConnected() const { + + return m_connection && m_connection->isConnected(); +} + + +bool POP3Store::isSecuredConnection() const { + + if (!m_connection) { + return false; + } + + return m_connection->isSecuredConnection(); +} + + +shared_ptr POP3Store::getConnectionInfos() const { + + if (!m_connection) { + return null; + } + + return m_connection->getConnectionInfos(); +} + + +shared_ptr POP3Store::getConnection() { + + return m_connection; +} + + +void POP3Store::disconnect() { + + if (!isConnected()) { + throw exceptions::not_connected(); + } + + for (std::list ::iterator it = m_folders.begin() ; + it != m_folders.end() ; ++it) { + + (*it)->onStoreDisconnected(); + } + + m_folders.clear(); + + + m_connection->disconnect(); + m_connection = null; +} + + +void POP3Store::noop() { + + if (!m_connection) { + throw exceptions::not_connected(); + } + + POP3Command::NOOP()->send(m_connection); + + shared_ptr response = POP3Response::readResponse(m_connection); + + if (!response->isSuccess()) { + throw exceptions::command_error("NOOP", response->getFirstLine()); + } +} + + +void POP3Store::registerFolder(POP3Folder* folder) { + + m_folders.push_back(folder); +} + + +void POP3Store::unregisterFolder(POP3Folder* folder) { + + std::list ::iterator it = std::find(m_folders.begin(), m_folders.end(), folder); + + if (it != m_folders.end()) { + m_folders.erase(it); + } +} + + +int POP3Store::getCapabilities() const { + + return CAPABILITY_DELETE_MESSAGE; +} + + + +// Service infos + +POP3ServiceInfos POP3Store::sm_infos(false); + + +const serviceInfos& POP3Store::getInfosInstance() { + + return sm_infos; +} + + +const serviceInfos& POP3Store::getInfos() const { + + return sm_infos; +} + + +} // pop3 +} // net +} // vmime + + +#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_POP3 + diff --git a/vmime-master/src/vmime/net/pop3/POP3Store.hpp b/vmime-master/src/vmime/net/pop3/POP3Store.hpp new file mode 100644 index 0000000..140a1ab --- /dev/null +++ b/vmime-master/src/vmime/net/pop3/POP3Store.hpp @@ -0,0 +1,120 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules is making +// a combined work based on this library. Thus, the terms and conditions of +// the GNU General Public License cover the whole combination. +// + +#ifndef VMIME_NET_POP3_POP3STORE_HPP_INCLUDED +#define VMIME_NET_POP3_POP3STORE_HPP_INCLUDED + + +#include "vmime/config.hpp" + + +#if VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_POP3 + + +#include "vmime/net/store.hpp" + +#include "vmime/net/pop3/POP3ServiceInfos.hpp" +#include "vmime/net/pop3/POP3Connection.hpp" + +#include "vmime/utility/stream.hpp" + + +namespace vmime { +namespace net { +namespace pop3 { + + +class POP3Folder; +class POP3Command; +class POP3Response; + + +/** POP3 store service. + */ +class VMIME_EXPORT POP3Store : public store { + + friend class POP3Folder; + friend class POP3Message; + +public: + + POP3Store( + const shared_ptr & sess, + const shared_ptr & auth, + const bool secured = false + ); + + ~POP3Store(); + + const string getProtocolName() const; + + shared_ptr getDefaultFolder(); + shared_ptr getRootFolder(); + shared_ptr getFolder(const folder::path& path); + + bool isValidFolderName(const folder::path::component& name) const; + + static const serviceInfos& getInfosInstance(); + const serviceInfos& getInfos() const; + + void connect(); + bool isConnected() const; + void disconnect(); + + void noop(); + + int getCapabilities() const; + + bool isSecuredConnection() const; + shared_ptr getConnectionInfos() const; + shared_ptr getConnection(); + + bool isPOP3S() const; + +private: + + shared_ptr m_connection; + + + void registerFolder(POP3Folder* folder); + void unregisterFolder(POP3Folder* folder); + + std::list m_folders; + + + const bool m_isPOP3S; + + + // Service infos + static POP3ServiceInfos sm_infos; +}; + + +} // pop3 +} // net +} // vmime + + +#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_POP3 + +#endif // VMIME_NET_POP3_POP3STORE_HPP_INCLUDED diff --git a/vmime-master/src/vmime/net/pop3/POP3Utils.cpp b/vmime-master/src/vmime/net/pop3/POP3Utils.cpp new file mode 100644 index 0000000..b38161e --- /dev/null +++ b/vmime-master/src/vmime/net/pop3/POP3Utils.cpp @@ -0,0 +1,135 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules is making +// a combined work based on this library. Thus, the terms and conditions of +// the GNU General Public License cover the whole combination. +// + +#include "vmime/config.hpp" + + +#if VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_POP3 + + +#include "vmime/net/pop3/POP3Utils.hpp" +#include "vmime/net/pop3/POP3Response.hpp" + +#include + + +namespace vmime { +namespace net { +namespace pop3 { + + +// static +void POP3Utils::parseMultiListOrUidlResponse( + const shared_ptr & response, + std::map & result +) { + + std::map ids; + + for (size_t i = 0, n = response->getLineCount() ; i < n ; ++i) { + + string line = response->getLineAt(i); + string::iterator it = line.begin(); + + while (it != line.end() && (*it == ' ' || *it == '\t')) { + ++it; + } + + if (it != line.end()) { + + size_t number = 0; + + while (it != line.end() && (*it >= '0' && *it <= '9')) { + number = (number * 10) + (*it - '0'); + ++it; + } + + while (it != line.end() && !(*it == ' ' || *it == '\t')) ++it; + while (it != line.end() && (*it == ' ' || *it == '\t')) ++it; + + if (it != line.end()) { + result.insert(std::map ::value_type(number, string(it, line.end()))); + } + } + } +} + + + +class POP3MessageSetEnumerator : public messageSetEnumerator { + +public: + + POP3MessageSetEnumerator(const size_t msgCount) + : m_msgCount(msgCount) { + + } + + void enumerateNumberMessageRange(const vmime::net::numberMessageRange& range) { + + size_t last = range.getLast(); + + if (last == size_t(-1)) { + last = m_msgCount; + } + + for (size_t i = range.getFirst() ; i <= last ; ++i) { + list.push_back(i); + } + } + + void enumerateUIDMessageRange(const vmime::net::UIDMessageRange& /* range */) { + + // Not supported + } + +public: + + std::vector list; + +private: + + size_t m_msgCount; +}; + + +// static +const std::vector POP3Utils::messageSetToNumberList( + const messageSet& msgs, + const size_t msgCount +) { + + POP3MessageSetEnumerator en(msgCount); + msgs.enumerate(en); + + return en.list; +} + + +} // pop3 +} // net +} // vmime + + +#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_POP3 + diff --git a/vmime-master/src/vmime/net/pop3/POP3Utils.hpp b/vmime-master/src/vmime/net/pop3/POP3Utils.hpp new file mode 100644 index 0000000..09d15d5 --- /dev/null +++ b/vmime-master/src/vmime/net/pop3/POP3Utils.hpp @@ -0,0 +1,92 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules is making +// a combined work based on this library. Thus, the terms and conditions of +// the GNU General Public License cover the whole combination. +// + +#ifndef VMIME_NET_POP3_POP3UTILS_HPP_INCLUDED +#define VMIME_NET_POP3_POP3UTILS_HPP_INCLUDED + + +#include "vmime/config.hpp" + + +#if VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_POP3 + + +#include + +#include "vmime/types.hpp" + +#include "vmime/net/messageSet.hpp" + + +namespace vmime { +namespace net { +namespace pop3 { + + +class POP3Response; + + +class VMIME_EXPORT POP3Utils { + +public: + + /** Parse a response of type ([integer] [string] \n)*. + * This is used in LIST or UIDL commands: + * + * C: UIDL + * S: +OK + * S: 1 whqtswO00WBw418f9t5JxYwZ + * S: 2 QhdPYR:00WBw1Ph7x7 + * S: . + * + * @param response raw response string as returned by the server + * @param result points to an associative array which maps a message + * number to its corresponding data (either UID or size) + */ + static void parseMultiListOrUidlResponse( + const shared_ptr & response, + std::map & result + ); + + /** Returns a list of message numbers given a message set. + * + * @param msgs message set + * @param msgCount number of messages in folder + * @return list of message numbers + */ + static const std::vector messageSetToNumberList( + const messageSet& msgs, + const size_t msgCount + ); +}; + + +} // pop3 +} // net +} // vmime + + +#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_POP3 + +#endif // VMIME_NET_POP3_POP3UTILS_HPP_INCLUDED + diff --git a/vmime-master/src/vmime/net/pop3/pop3.hpp b/vmime-master/src/vmime/net/pop3/pop3.hpp new file mode 100644 index 0000000..ced3a97 --- /dev/null +++ b/vmime-master/src/vmime/net/pop3/pop3.hpp @@ -0,0 +1,35 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002 Vincent Richard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules is making +// a combined work based on this library. Thus, the terms and conditions of +// the GNU General Public License cover the whole combination. +// + +#ifndef VMIME_NET_POP3_POP3_HPP_INCLUDED +#define VMIME_NET_POP3_POP3_HPP_INCLUDED + + +#include "vmime/net/pop3/POP3Folder.hpp" +#include "vmime/net/pop3/POP3FolderStatus.hpp" +#include "vmime/net/pop3/POP3Message.hpp" +#include "vmime/net/pop3/POP3Store.hpp" +#include "vmime/net/pop3/POP3SStore.hpp" + + +#endif // VMIME_NET_POP3_POP3_HPP_INCLUDED -- cgit v1.2.3