diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/vmime/exception.hpp | 1 | ||||
-rw-r--r-- | src/vmime/messageParser.cpp | 19 | ||||
-rw-r--r-- | src/vmime/net/imap/IMAPConnection.cpp | 50 | ||||
-rw-r--r-- | src/vmime/net/imap/IMAPConnection.hpp | 2 | ||||
-rw-r--r-- | src/vmime/net/imap/IMAPFolder.cpp | 21 | ||||
-rw-r--r-- | src/vmime/net/imap/IMAPMessage.cpp | 19 | ||||
-rw-r--r-- | src/vmime/net/imap/IMAPMessagePartContentHandler.cpp | 14 | ||||
-rw-r--r-- | src/vmime/net/imap/IMAPParser.hpp | 6 | ||||
-rw-r--r-- | src/vmime/net/imap/IMAPStore.cpp | 14 | ||||
-rw-r--r-- | src/vmime/net/tls/gnutls/TLSSocket_GnuTLS.cpp | 15 | ||||
-rw-r--r-- | src/vmime/net/tls/gnutls/TLSSocket_GnuTLS.hpp | 2 | ||||
-rw-r--r-- | src/vmime/net/tls/openssl/TLSSocket_OpenSSL.cpp | 14 | ||||
-rw-r--r-- | src/vmime/net/tls/openssl/TLSSocket_OpenSSL.hpp | 2 |
13 files changed, 134 insertions, 45 deletions
diff --git a/src/vmime/exception.hpp b/src/vmime/exception.hpp index da0ec246..83f6c9c0 100644 --- a/src/vmime/exception.hpp +++ b/src/vmime/exception.hpp @@ -34,6 +34,7 @@ namespace vmime { +typedef std::exception_ptr exception_ptr; /** Base class for VMime exceptions. */ diff --git a/src/vmime/messageParser.cpp b/src/vmime/messageParser.cpp index 21ac09bb..d7dd592a 100644 --- a/src/vmime/messageParser.cpp +++ b/src/vmime/messageParser.cpp @@ -82,12 +82,18 @@ void messageParser::parse(const shared_ptr <const message>& msg) { // Date shared_ptr <const headerField> recv = msg->getHeader()->findField(fields::RECEIVED); + static const datetime unsetDate; + + m_date = unsetDate; if (recv) { m_date = recv->getValue <relay>()->getDate(); - } else { + } + + // RECEIVED may in some cases contain no date at all + if (unsetDate == m_date) { shared_ptr <const headerField> date = msg->getHeader()->findField(fields::DATE); @@ -204,7 +210,16 @@ bool messageParser::findSubTextParts( } else { - // No "Content-type" field. + // No "Content-type" field. RFC2045 section 5.2 assumes this is TEXT/PLAIN + try { + shared_ptr <textPart> txtPart = textPartFactory::getInstance()->create(mediaType(mediaTypes::TEXT, mediaTypes::TEXT_PLAIN)); + txtPart->parse(msg, part, p); + + m_textParts.push_back(txtPart); + } + catch (exceptions::no_factory_available& e) { + // Content-type not recognized. + } } } diff --git a/src/vmime/net/imap/IMAPConnection.cpp b/src/vmime/net/imap/IMAPConnection.cpp index df3da1c3..0e4020f1 100644 --- a/src/vmime/net/imap/IMAPConnection.cpp +++ b/src/vmime/net/imap/IMAPConnection.cpp @@ -51,14 +51,13 @@ #include <sstream> - // Helpers for service properties #define GET_PROPERTY(type, prop) \ - (m_store.lock()->getInfos().getPropertyValue <type>(getSession(), \ - dynamic_cast <const IMAPServiceInfos&>(m_store.lock()->getInfos()).getProperties().prop)) + (getStoreOrThrow()->getInfos().getPropertyValue <type>(getSession(), \ + dynamic_cast <const IMAPServiceInfos&>(getStoreOrThrow()->getInfos()).getProperties().prop)) #define HAS_PROPERTY(prop) \ - (m_store.lock()->getInfos().hasProperty(getSession(), \ - dynamic_cast <const IMAPServiceInfos&>(m_store.lock()->getInfos()).getProperties().prop)) + (getStoreOrThrow()->getInfos().hasProperty(getSession(), \ + dynamic_cast <const IMAPServiceInfos&>(getStoreOrThrow()->getInfos()).getProperties().prop)) namespace vmime { @@ -127,6 +126,10 @@ void IMAPConnection::connect() { shared_ptr <IMAPStore> store = m_store.lock(); + if (!store) { + throw exceptions::illegal_state("Store not found"); + } + // Create the time-out handler if (store->getTimeoutHandlerFactory()) { m_timeoutHandler = store->getTimeoutHandlerFactory()->create(); @@ -244,6 +247,17 @@ void IMAPConnection::connect() { setState(STATE_AUTHENTICATED); } +shared_ptr <IMAPStore> IMAPConnection::getStoreOrThrow() { + + auto store = m_store.lock(); + + if (!store) { + throw exceptions::illegal_state("Store not found"); + } + + return store; +} + void IMAPConnection::authenticate() { @@ -529,9 +543,15 @@ void IMAPConnection::startTLS() { throw exceptions::command_error("STARTTLS", resp->getErrorLog(), "bad response"); } + auto store = m_store.lock(); + + if (!store) { + throw exceptions::illegal_state("Store not found"); + } + shared_ptr <tls::TLSSession> tlsSession = tls::TLSSession::create( - m_store.lock()->getCertificateVerifier(), - m_store.lock()->getSession()->getTLSProperties() + store->getCertificateVerifier(), + store->getSession()->getTLSProperties() ); shared_ptr <tls::TLSSocket> tlsSocket = tlsSession->getSocket(m_socket); @@ -701,11 +721,11 @@ shared_ptr <connectionInfos> IMAPConnection::getConnectionInfos() const { void IMAPConnection::disconnect() { - if (!isConnected()) { + bool wasConnected = isConnected(); + internalDisconnect(); + if (!wasConnected) { throw exceptions::not_connected(); } - - internalDisconnect(); } @@ -714,7 +734,9 @@ void IMAPConnection::internalDisconnect() { if (isConnected()) { IMAPCommand::LOGOUT()->send(dynamicCast <IMAPConnection>(shared_from_this())); + } + if (m_socket) { m_socket->disconnect(); m_socket = null; } @@ -836,7 +858,13 @@ shared_ptr <IMAPStore> IMAPConnection::getStore() { shared_ptr <session> IMAPConnection::getSession() { - return m_store.lock()->getSession(); + auto store = m_store.lock(); + + if (!store) { + throw exceptions::illegal_state("Store not found"); + } + + return store->getSession(); } diff --git a/src/vmime/net/imap/IMAPConnection.hpp b/src/vmime/net/imap/IMAPConnection.hpp index 99750d49..d229d0f7 100644 --- a/src/vmime/net/imap/IMAPConnection.hpp +++ b/src/vmime/net/imap/IMAPConnection.hpp @@ -114,6 +114,8 @@ public: private: + shared_ptr <IMAPStore> getStoreOrThrow(); + void authenticate(); #if VMIME_HAVE_SASL_SUPPORT void authenticateSASL(); diff --git a/src/vmime/net/imap/IMAPFolder.cpp b/src/vmime/net/imap/IMAPFolder.cpp index 98bc05d8..f6c02697 100644 --- a/src/vmime/net/imap/IMAPFolder.cpp +++ b/src/vmime/net/imap/IMAPFolder.cpp @@ -80,7 +80,11 @@ IMAPFolder::~IMAPFolder() { if (store) { if (m_open) { - close(false); + try { + close(false); + } catch (...) { + // Ignore exception here to make sure unregisterFolder is called + } } store->unregisterFolder(this); @@ -290,9 +294,17 @@ void IMAPFolder::close(const bool expunge) { shared_ptr <IMAPStore> store = m_store.lock(); if (!store) { + if (m_connection && m_connection->isConnected()) + m_connection->disconnect(); + m_connection = nullptr; + m_open = false; throw exceptions::illegal_state("Store disconnected"); } + if (!m_connection || !m_connection->isConnected()) { + throw exceptions::illegal_state("Folder not connected"); + } + if (!isOpen()) { throw exceptions::illegal_state("Folder not open"); } @@ -314,7 +326,7 @@ void IMAPFolder::close(const bool expunge) { oldConnection->disconnect(); // Now use default store connection - m_connection = m_store.lock()->connection(); + m_connection = store->connection(); m_open = false; m_mode = -1; @@ -546,7 +558,6 @@ bool IMAPFolder::isOpen() const { return m_open; } - shared_ptr <message> IMAPFolder::getMessage(const size_t num) { if (!isOpen()) { @@ -1421,6 +1432,10 @@ void IMAPFolder::noop() { throw exceptions::illegal_state("Store disconnected"); } + if (!m_connection || !m_connection->isConnected()) { + throw exceptions::illegal_state("Store disconnected"); + } + IMAPCommand::NOOP()->send(m_connection); scoped_ptr <IMAPParser::response> resp(m_connection->readResponse()); diff --git a/src/vmime/net/imap/IMAPMessage.cpp b/src/vmime/net/imap/IMAPMessage.cpp index f74a4a4b..534727d4 100644 --- a/src/vmime/net/imap/IMAPMessage.cpp +++ b/src/vmime/net/imap/IMAPMessage.cpp @@ -318,6 +318,14 @@ size_t IMAPMessage::extractImpl( shared_ptr <const IMAPFolder> folder = m_folder.lock(); + if (!folder) { + throw exceptions::folder_not_found(); + } + + if (!folder->isOpen()) { + throw exceptions::illegal_state("Folder not open"); + } + IMAPMessage_literalHandler literalHandler(os, progress); if (length == 0) { @@ -474,7 +482,6 @@ size_t IMAPMessage::extractImpl( return literalHandler.getTarget()->getBytesWritten(); } - int IMAPMessage::processFetchResponse( const fetchAttributes& options, const IMAPParser::message_data& msgData @@ -553,7 +560,7 @@ int IMAPMessage::processFetchResponse( IMAPUtils::convertAddressList(*(env->env_reply_to), replyTo); if (!replyTo.isEmpty()) { - hdr->ReplyTo()->setValue(*(replyTo.getMailboxAt(0))); + hdr->ReplyTo()->setValue(replyTo.toAddressList()); } // Cc @@ -717,10 +724,16 @@ shared_ptr <vmime::message> IMAPMessage::getParsedMessage() { } catch (exceptions::unfetched_object&) { + auto folder = m_folder.lock(); + + if (!folder) { + throw exceptions::folder_not_found(); + } + std::vector <shared_ptr <message> > msgs; msgs.push_back(dynamicCast <IMAPMessage>(shared_from_this())); - m_folder.lock()->fetchMessages( + folder->fetchMessages( msgs, fetchAttributes(fetchAttributes::STRUCTURE), /* progress */ NULL ); diff --git a/src/vmime/net/imap/IMAPMessagePartContentHandler.cpp b/src/vmime/net/imap/IMAPMessagePartContentHandler.cpp index 85f6cb6e..040d2ab0 100644 --- a/src/vmime/net/imap/IMAPMessagePartContentHandler.cpp +++ b/src/vmime/net/imap/IMAPMessagePartContentHandler.cpp @@ -36,7 +36,6 @@ #include "vmime/utility/outputStreamAdapter.hpp" #include "vmime/utility/inputStreamStringAdapter.hpp" - namespace vmime { namespace net { namespace imap { @@ -71,6 +70,9 @@ void IMAPMessagePartContentHandler::generate( shared_ptr <IMAPMessage> msg = m_message.lock(); shared_ptr <messagePart> part = m_part.lock(); + if (!msg || !part) + throw exceptions::message_not_found(); + // Data is already encoded if (isEncoded()) { @@ -140,6 +142,9 @@ void IMAPMessagePartContentHandler::extract( shared_ptr <IMAPMessage> msg = m_message.lock(); shared_ptr <messagePart> part = m_part.lock(); + if (!msg || !part) + throw exceptions::message_not_found(); + // No decoding to perform if (!isEncoded()) { @@ -172,12 +177,17 @@ void IMAPMessagePartContentHandler::extractRaw( shared_ptr <IMAPMessage> msg = m_message.lock(); shared_ptr <messagePart> part = m_part.lock(); + if (!msg || !part) + throw exceptions::message_not_found(); + msg->extractPart(part, os, progress); } size_t IMAPMessagePartContentHandler::getLength() const { - + shared_ptr <messagePart> part = m_part.lock(); + if (!part) + throw exceptions::message_not_found(); return m_part.lock()->getSize(); } diff --git a/src/vmime/net/imap/IMAPParser.hpp b/src/vmime/net/imap/IMAPParser.hpp index 409362da..2a37b9cd 100644 --- a/src/vmime/net/imap/IMAPParser.hpp +++ b/src/vmime/net/imap/IMAPParser.hpp @@ -4912,6 +4912,9 @@ public: shared_ptr <timeoutHandler> toh = m_timeoutHandler.lock(); shared_ptr <socket> sok = m_socket.lock(); + if (!sok) + throw exceptions::illegal_state("Store disconnected"); + if (toh) { toh->resetTimeOut(); } @@ -4957,6 +4960,9 @@ public: shared_ptr <timeoutHandler> toh = m_timeoutHandler.lock(); shared_ptr <socket> sok = m_socket.lock(); + if (!sok) + throw exceptions::illegal_state("Store disconnected"); + if (m_progress) { m_progress->start(count); } diff --git a/src/vmime/net/imap/IMAPStore.cpp b/src/vmime/net/imap/IMAPStore.cpp index eafa4442..be5c4de7 100644 --- a/src/vmime/net/imap/IMAPStore.cpp +++ b/src/vmime/net/imap/IMAPStore.cpp @@ -179,9 +179,7 @@ shared_ptr <IMAPConnection> IMAPStore::getConnection() { void IMAPStore::disconnect() { - if (!isConnected()) { - throw exceptions::not_connected(); - } + bool wasConnected = isConnected(); for (std::list <IMAPFolder*>::iterator it = m_folders.begin() ; it != m_folders.end() ; ++it) { @@ -191,10 +189,14 @@ void IMAPStore::disconnect() { m_folders.clear(); + if (m_connection) { + m_connection->disconnect(); + m_connection = null; + } - m_connection->disconnect(); - - m_connection = null; + if (!wasConnected) { + throw exceptions::not_connected(); + } } diff --git a/src/vmime/net/tls/gnutls/TLSSocket_GnuTLS.cpp b/src/vmime/net/tls/gnutls/TLSSocket_GnuTLS.cpp index 53e4eaee..97466fc5 100644 --- a/src/vmime/net/tls/gnutls/TLSSocket_GnuTLS.cpp +++ b/src/vmime/net/tls/gnutls/TLSSocket_GnuTLS.cpp @@ -66,7 +66,7 @@ TLSSocket_GnuTLS::TLSSocket_GnuTLS( : m_session(session), m_wrapped(sok), m_connected(false), - m_ex(NULL), + m_ex(nullptr), m_status(0), m_errno(0) { @@ -407,7 +407,7 @@ ssize_t TLSSocket_GnuTLS::gnutlsPushFunc( // Workaround for non-portable behaviour when throwing C++ exceptions // from C functions (GNU TLS) - sok->m_ex = e.clone(); + sok->m_ex = std::current_exception(); return -1; } } @@ -440,7 +440,7 @@ ssize_t TLSSocket_GnuTLS::gnutlsPullFunc( // Workaround for non-portable behaviour when throwing C++ exceptions // from C functions (GNU TLS) - sok->m_ex = e.clone(); + sok->m_ex = std::current_exception(); return -1; } } @@ -525,18 +525,15 @@ shared_ptr <security::cert::certificateChain> TLSSocket_GnuTLS::getPeerCertifica void TLSSocket_GnuTLS::throwException() { - if (m_ex) { - throw *m_ex; + if (!!m_ex) { + std::rethrow_exception(m_ex); } } void TLSSocket_GnuTLS::resetException() { - if (m_ex) { - delete m_ex; - m_ex = NULL; - } + m_ex = nullptr; } diff --git a/src/vmime/net/tls/gnutls/TLSSocket_GnuTLS.hpp b/src/vmime/net/tls/gnutls/TLSSocket_GnuTLS.hpp index 0ac3e700..a90379fd 100644 --- a/src/vmime/net/tls/gnutls/TLSSocket_GnuTLS.hpp +++ b/src/vmime/net/tls/gnutls/TLSSocket_GnuTLS.hpp @@ -109,7 +109,7 @@ private: byte_t m_buffer[65536]; - exception* m_ex; + exception_ptr m_ex; unsigned int m_status; int m_errno; diff --git a/src/vmime/net/tls/openssl/TLSSocket_OpenSSL.cpp b/src/vmime/net/tls/openssl/TLSSocket_OpenSSL.cpp index 978f0ca6..bbda81b3 100644 --- a/src/vmime/net/tls/openssl/TLSSocket_OpenSSL.cpp +++ b/src/vmime/net/tls/openssl/TLSSocket_OpenSSL.cpp @@ -104,7 +104,7 @@ TLSSocket_OpenSSL::TLSSocket_OpenSSL( m_connected(false), m_ssl(0), m_status(0), - m_ex() { + m_ex(nullptr) { } @@ -309,7 +309,7 @@ size_t TLSSocket_OpenSSL::receiveRaw(byte_t* buffer, const size_t count) { ERR_clear_error(); int rc = SSL_read(m_ssl, buffer, static_cast <int>(count)); - if (m_ex.get()) { + if (!!m_ex) { internalThrow(); } @@ -379,7 +379,7 @@ size_t TLSSocket_OpenSSL::sendRawNonBlocking(const byte_t* buffer, const size_t ERR_clear_error(); int rc = SSL_write(m_ssl, buffer, static_cast <int>(count)); - if (m_ex.get()) { + if (!!m_ex) { internalThrow(); } @@ -511,8 +511,8 @@ shared_ptr <security::cert::certificateChain> TLSSocket_OpenSSL::getPeerCertific void TLSSocket_OpenSSL::internalThrow() { - if (m_ex.get()) { - throw *m_ex; + if (!!m_ex) { + std::rethrow_exception(m_ex); } } @@ -630,7 +630,7 @@ int TLSSocket_OpenSSL::bio_write(BIO* bio, const char* buf, int len) { } catch (exception& e) { // Workaround for passing C++ exceptions from C BIO functions - sok->m_ex.reset(e.clone()); + sok->m_ex = std::current_exception(); return -1; } } @@ -667,7 +667,7 @@ int TLSSocket_OpenSSL::bio_read(BIO* bio, char* buf, int len) { } catch (exception& e) { // Workaround for passing C++ exceptions from C BIO functions - sok->m_ex.reset(e.clone()); + sok->m_ex = std::current_exception(); return -1; } } diff --git a/src/vmime/net/tls/openssl/TLSSocket_OpenSSL.hpp b/src/vmime/net/tls/openssl/TLSSocket_OpenSSL.hpp index e30df680..62fd5f0d 100644 --- a/src/vmime/net/tls/openssl/TLSSocket_OpenSSL.hpp +++ b/src/vmime/net/tls/openssl/TLSSocket_OpenSSL.hpp @@ -125,7 +125,7 @@ private: unsigned int m_status; // Last exception thrown from C BIO functions - scoped_ptr <exception> m_ex; + exception_ptr m_ex; }; |