Connection trace facility.
This commit is contained in:
parent
cfe9c6b1e7
commit
84e570bbbb
@ -31,178 +31,17 @@
|
||||
#include "vmime/vmime.hpp"
|
||||
#include "vmime/platforms/posix/posixHandler.hpp"
|
||||
|
||||
#include "example6_tracer.hpp"
|
||||
#include "example6_authenticator.hpp"
|
||||
#include "example6_certificateVerifier.hpp"
|
||||
#include "example6_timeoutHandler.hpp"
|
||||
|
||||
|
||||
// Global session object
|
||||
static vmime::shared_ptr <vmime::net::session> g_session
|
||||
= vmime::make_shared <vmime::net::session>();
|
||||
|
||||
|
||||
#if VMIME_HAVE_SASL_SUPPORT
|
||||
|
||||
// SASL authentication handler
|
||||
class interactiveAuthenticator : public vmime::security::sasl::defaultSASLAuthenticator
|
||||
{
|
||||
const std::vector <vmime::shared_ptr <vmime::security::sasl::SASLMechanism> > getAcceptableMechanisms
|
||||
(const std::vector <vmime::shared_ptr <vmime::security::sasl::SASLMechanism> >& available,
|
||||
vmime::shared_ptr <vmime::security::sasl::SASLMechanism> suggested) const
|
||||
{
|
||||
std::cout << std::endl << "Available SASL mechanisms:" << std::endl;
|
||||
|
||||
for (unsigned int i = 0 ; i < available.size() ; ++i)
|
||||
{
|
||||
std::cout << " " << available[i]->getName();
|
||||
|
||||
if (suggested && available[i]->getName() == suggested->getName())
|
||||
std::cout << "(suggested)";
|
||||
}
|
||||
|
||||
std::cout << std::endl << std::endl;
|
||||
|
||||
return defaultSASLAuthenticator::getAcceptableMechanisms(available, suggested);
|
||||
}
|
||||
|
||||
void setSASLMechanism(vmime::shared_ptr <vmime::security::sasl::SASLMechanism> mech)
|
||||
{
|
||||
std::cout << "Trying '" << mech->getName() << "' authentication mechanism" << std::endl;
|
||||
|
||||
defaultSASLAuthenticator::setSASLMechanism(mech);
|
||||
}
|
||||
|
||||
const vmime::string getUsername() const
|
||||
{
|
||||
if (m_username.empty())
|
||||
m_username = getUserInput("Username");
|
||||
|
||||
return m_username;
|
||||
}
|
||||
|
||||
const vmime::string getPassword() const
|
||||
{
|
||||
if (m_password.empty())
|
||||
m_password = getUserInput("Password");
|
||||
|
||||
return m_password;
|
||||
}
|
||||
|
||||
static const vmime::string getUserInput(const std::string& prompt)
|
||||
{
|
||||
std::cout << prompt << ": ";
|
||||
std::cout.flush();
|
||||
|
||||
vmime::string res;
|
||||
std::getline(std::cin, res);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
mutable vmime::string m_username;
|
||||
mutable vmime::string m_password;
|
||||
};
|
||||
|
||||
#else // !VMIME_HAVE_SASL_SUPPORT
|
||||
|
||||
// Simple authentication handler
|
||||
class interactiveAuthenticator : public vmime::security::defaultAuthenticator
|
||||
{
|
||||
const vmime::string getUsername() const
|
||||
{
|
||||
if (m_username.empty())
|
||||
m_username = getUserInput("Username");
|
||||
|
||||
return m_username;
|
||||
}
|
||||
|
||||
const vmime::string getPassword() const
|
||||
{
|
||||
if (m_password.empty())
|
||||
m_password = getUserInput("Password");
|
||||
|
||||
return m_password;
|
||||
}
|
||||
|
||||
static const vmime::string getUserInput(const std::string& prompt)
|
||||
{
|
||||
std::cout << prompt << ": ";
|
||||
std::cout.flush();
|
||||
|
||||
vmime::string res;
|
||||
std::getline(std::cin, res);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
mutable vmime::string m_username;
|
||||
mutable vmime::string m_password;
|
||||
};
|
||||
|
||||
#endif // VMIME_HAVE_SASL_SUPPORT
|
||||
|
||||
|
||||
#if VMIME_HAVE_TLS_SUPPORT
|
||||
|
||||
// Certificate verifier (TLS/SSL)
|
||||
class interactiveCertificateVerifier : public vmime::security::cert::defaultCertificateVerifier
|
||||
{
|
||||
public:
|
||||
|
||||
void verify(vmime::shared_ptr <vmime::security::cert::certificateChain> chain, const vmime::string& hostname)
|
||||
{
|
||||
try
|
||||
{
|
||||
setX509TrustedCerts(m_trustedCerts);
|
||||
|
||||
defaultCertificateVerifier::verify(chain, hostname);
|
||||
}
|
||||
catch (vmime::exceptions::certificate_verification_exception&)
|
||||
{
|
||||
// Obtain subject's certificate
|
||||
vmime::shared_ptr <vmime::security::cert::certificate> cert = chain->getAt(0);
|
||||
|
||||
std::cout << std::endl;
|
||||
std::cout << "Server sent a '" << cert->getType() << "'" << " certificate." << std::endl;
|
||||
std::cout << "Do you want to accept this certificate? (Y/n) ";
|
||||
std::cout.flush();
|
||||
|
||||
std::string answer;
|
||||
std::getline(std::cin, answer);
|
||||
|
||||
if (answer.length() != 0 &&
|
||||
(answer[0] == 'Y' || answer[0] == 'y'))
|
||||
{
|
||||
// Accept it, and remember user's choice for later
|
||||
if (cert->getType() == "X.509")
|
||||
{
|
||||
m_trustedCerts.push_back(vmime::dynamicCast
|
||||
<vmime::security::cert::X509Certificate>(cert));
|
||||
|
||||
setX509TrustedCerts(m_trustedCerts);
|
||||
defaultCertificateVerifier::verify(chain, hostname);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
throw vmime::exceptions::certificate_verification_exception
|
||||
("User did not accept the certificate.");
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
static std::vector <vmime::shared_ptr <vmime::security::cert::X509Certificate> > m_trustedCerts;
|
||||
};
|
||||
|
||||
|
||||
std::vector <vmime::shared_ptr <vmime::security::cert::X509Certificate> >
|
||||
interactiveCertificateVerifier::m_trustedCerts;
|
||||
|
||||
#endif // VMIME_HAVE_TLS_SUPPORT
|
||||
|
||||
|
||||
/** Returns the messaging protocols supported by VMime.
|
||||
*
|
||||
* @param type service type (vmime::net::service::TYPE_STORE or
|
||||
@ -290,53 +129,6 @@ static std::ostream& operator<<(std::ostream& os, const vmime::exception& e)
|
||||
}
|
||||
|
||||
|
||||
/** Time out handler.
|
||||
* Used to stop the current operation after too much time, or if the user
|
||||
* requested cancellation.
|
||||
*/
|
||||
class timeoutHandler : public vmime::net::timeoutHandler
|
||||
{
|
||||
public:
|
||||
|
||||
bool isTimeOut()
|
||||
{
|
||||
// This is a cancellation point: return true if you want to cancel
|
||||
// the current operation. If you return true, handleTimeOut() will
|
||||
// be called just after this, and before actually cancelling the
|
||||
// operation
|
||||
return false;
|
||||
}
|
||||
|
||||
void resetTimeOut()
|
||||
{
|
||||
// Called at the beginning of an operation (eg. connecting,
|
||||
// a read() or a write() on a socket...)
|
||||
}
|
||||
|
||||
bool handleTimeOut()
|
||||
{
|
||||
// If isTimeOut() returned true, this function will be called. This
|
||||
// allows you to interact with the user, ie. display a prompt to
|
||||
// know whether he wants to cancel the operation.
|
||||
|
||||
// If you return true here, the operation will be actually cancelled.
|
||||
// If not, the time out is reset and the operation continues.
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
class timeoutHandlerFactory : public vmime::net::timeoutHandlerFactory
|
||||
{
|
||||
public:
|
||||
|
||||
vmime::shared_ptr <vmime::net::timeoutHandler> create()
|
||||
{
|
||||
return vmime::make_shared <timeoutHandler>();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/** Print the MIME structure of a message on the standard output.
|
||||
*
|
||||
* @param s structure object
|
||||
@ -445,8 +237,12 @@ static void sendMessage()
|
||||
|
||||
vmime::utility::url url(urlString);
|
||||
|
||||
vmime::shared_ptr <vmime::net::transport> tr =
|
||||
g_session->getTransport(url, vmime::make_shared <interactiveAuthenticator>());
|
||||
vmime::shared_ptr <vmime::net::transport> tr;
|
||||
|
||||
if (url.getUsername().empty() || url.getPassword().empty())
|
||||
tr = g_session->getTransport(url, vmime::make_shared <interactiveAuthenticator>());
|
||||
else
|
||||
tr = g_session->getTransport(url);
|
||||
|
||||
#if VMIME_HAVE_TLS_SUPPORT
|
||||
|
||||
@ -465,7 +261,12 @@ static void sendMessage()
|
||||
|
||||
// You can also set some properties (see example7 to know the properties
|
||||
// available for each service). For example, for SMTP:
|
||||
// tr->setProperty("options.need-authentication", true);
|
||||
if (!url.getUsername().empty() || !url.getPassword().empty())
|
||||
tr->setProperty("options.need-authentication", true);
|
||||
|
||||
// Trace communication between client and server
|
||||
vmime::shared_ptr <std::ostringstream> traceStream = vmime::make_shared <std::ostringstream>();
|
||||
tr->setTracerFactory(vmime::make_shared <myTracerFactory>(traceStream));
|
||||
|
||||
// Information about the mail
|
||||
std::cout << "Enter email of the expeditor (eg. me@somewhere.com): ";
|
||||
@ -520,6 +321,12 @@ static void sendMessage()
|
||||
// ...
|
||||
// tr->send(&msg);
|
||||
|
||||
// Display connection log
|
||||
std::cout << std::endl;
|
||||
std::cout << "Connection Trace:" << std::endl;
|
||||
std::cout << "=================" << std::endl;
|
||||
std::cout << traceStream->str();
|
||||
|
||||
tr->disconnect();
|
||||
}
|
||||
catch (vmime::exception& e)
|
||||
@ -580,6 +387,10 @@ static void connectStore()
|
||||
|
||||
#endif // VMIME_HAVE_TLS_SUPPORT
|
||||
|
||||
// Trace communication between client and server
|
||||
vmime::shared_ptr <std::ostringstream> traceStream = vmime::make_shared <std::ostringstream>();
|
||||
st->setTracerFactory(vmime::make_shared <myTracerFactory>(traceStream));
|
||||
|
||||
// Connect to the mail store
|
||||
st->connect();
|
||||
|
||||
@ -621,6 +432,7 @@ static void connectStore()
|
||||
choices.push_back("Change folder");
|
||||
choices.push_back("Add message (to the current folder)");
|
||||
choices.push_back("Copy message (into the current folder)");
|
||||
choices.push_back("Display trace output");
|
||||
choices.push_back("Return to main menu");
|
||||
|
||||
const int choice = printMenu(choices);
|
||||
@ -928,9 +740,18 @@ static void connectStore()
|
||||
|
||||
break;
|
||||
}
|
||||
// Main menu
|
||||
// Display trace output
|
||||
case 12:
|
||||
|
||||
std::cout << std::endl;
|
||||
std::cout << "Connection Trace:" << std::endl;
|
||||
std::cout << "=================" << std::endl;
|
||||
std::cout << traceStream->str();
|
||||
break;
|
||||
|
||||
// Main menu
|
||||
case 13:
|
||||
|
||||
f->close(true); // 'true' to expunge deleted messages
|
||||
cont = false;
|
||||
break;
|
||||
@ -979,7 +800,9 @@ static void connectStore()
|
||||
std::cerr << std::endl;
|
||||
std::cerr << "std::exception: " << e.what() << std::endl;
|
||||
}
|
||||
}
|
||||
} // for(cont)
|
||||
|
||||
st->disconnect();
|
||||
}
|
||||
catch (vmime::exception& e)
|
||||
{
|
||||
|
106
examples/example6_authenticator.hpp
Normal file
106
examples/example6_authenticator.hpp
Normal file
@ -0,0 +1,106 @@
|
||||
|
||||
|
||||
#if VMIME_HAVE_SASL_SUPPORT
|
||||
|
||||
// SASL authentication handler
|
||||
class interactiveAuthenticator : public vmime::security::sasl::defaultSASLAuthenticator
|
||||
{
|
||||
const std::vector <vmime::shared_ptr <vmime::security::sasl::SASLMechanism> > getAcceptableMechanisms
|
||||
(const std::vector <vmime::shared_ptr <vmime::security::sasl::SASLMechanism> >& available,
|
||||
vmime::shared_ptr <vmime::security::sasl::SASLMechanism> suggested) const
|
||||
{
|
||||
std::cout << std::endl << "Available SASL mechanisms:" << std::endl;
|
||||
|
||||
for (unsigned int i = 0 ; i < available.size() ; ++i)
|
||||
{
|
||||
std::cout << " " << available[i]->getName();
|
||||
|
||||
if (suggested && available[i]->getName() == suggested->getName())
|
||||
std::cout << "(suggested)";
|
||||
}
|
||||
|
||||
std::cout << std::endl << std::endl;
|
||||
|
||||
return defaultSASLAuthenticator::getAcceptableMechanisms(available, suggested);
|
||||
}
|
||||
|
||||
void setSASLMechanism(vmime::shared_ptr <vmime::security::sasl::SASLMechanism> mech)
|
||||
{
|
||||
std::cout << "Trying '" << mech->getName() << "' authentication mechanism" << std::endl;
|
||||
|
||||
defaultSASLAuthenticator::setSASLMechanism(mech);
|
||||
}
|
||||
|
||||
const vmime::string getUsername() const
|
||||
{
|
||||
if (m_username.empty())
|
||||
m_username = getUserInput("Username");
|
||||
|
||||
return m_username;
|
||||
}
|
||||
|
||||
const vmime::string getPassword() const
|
||||
{
|
||||
if (m_password.empty())
|
||||
m_password = getUserInput("Password");
|
||||
|
||||
return m_password;
|
||||
}
|
||||
|
||||
static const vmime::string getUserInput(const std::string& prompt)
|
||||
{
|
||||
std::cout << prompt << ": ";
|
||||
std::cout.flush();
|
||||
|
||||
vmime::string res;
|
||||
std::getline(std::cin, res);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
mutable vmime::string m_username;
|
||||
mutable vmime::string m_password;
|
||||
};
|
||||
|
||||
#else // !VMIME_HAVE_SASL_SUPPORT
|
||||
|
||||
// Simple authentication handler
|
||||
class interactiveAuthenticator : public vmime::security::defaultAuthenticator
|
||||
{
|
||||
const vmime::string getUsername() const
|
||||
{
|
||||
if (m_username.empty())
|
||||
m_username = getUserInput("Username");
|
||||
|
||||
return m_username;
|
||||
}
|
||||
|
||||
const vmime::string getPassword() const
|
||||
{
|
||||
if (m_password.empty())
|
||||
m_password = getUserInput("Password");
|
||||
|
||||
return m_password;
|
||||
}
|
||||
|
||||
static const vmime::string getUserInput(const std::string& prompt)
|
||||
{
|
||||
std::cout << prompt << ": ";
|
||||
std::cout.flush();
|
||||
|
||||
vmime::string res;
|
||||
std::getline(std::cin, res);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
mutable vmime::string m_username;
|
||||
mutable vmime::string m_password;
|
||||
};
|
||||
|
||||
#endif // VMIME_HAVE_SASL_SUPPORT
|
||||
|
62
examples/example6_certificateVerifier.hpp
Normal file
62
examples/example6_certificateVerifier.hpp
Normal file
@ -0,0 +1,62 @@
|
||||
|
||||
|
||||
#if VMIME_HAVE_TLS_SUPPORT
|
||||
|
||||
// Certificate verifier (TLS/SSL)
|
||||
class interactiveCertificateVerifier : public vmime::security::cert::defaultCertificateVerifier
|
||||
{
|
||||
public:
|
||||
|
||||
void verify(vmime::shared_ptr <vmime::security::cert::certificateChain> chain, const vmime::string& hostname)
|
||||
{
|
||||
try
|
||||
{
|
||||
setX509TrustedCerts(m_trustedCerts);
|
||||
|
||||
defaultCertificateVerifier::verify(chain, hostname);
|
||||
}
|
||||
catch (vmime::exceptions::certificate_verification_exception&)
|
||||
{
|
||||
// Obtain subject's certificate
|
||||
vmime::shared_ptr <vmime::security::cert::certificate> cert = chain->getAt(0);
|
||||
|
||||
std::cout << std::endl;
|
||||
std::cout << "Server sent a '" << cert->getType() << "'" << " certificate." << std::endl;
|
||||
std::cout << "Do you want to accept this certificate? (Y/n) ";
|
||||
std::cout.flush();
|
||||
|
||||
std::string answer;
|
||||
std::getline(std::cin, answer);
|
||||
|
||||
if (answer.length() != 0 &&
|
||||
(answer[0] == 'Y' || answer[0] == 'y'))
|
||||
{
|
||||
// Accept it, and remember user's choice for later
|
||||
if (cert->getType() == "X.509")
|
||||
{
|
||||
m_trustedCerts.push_back(vmime::dynamicCast
|
||||
<vmime::security::cert::X509Certificate>(cert));
|
||||
|
||||
setX509TrustedCerts(m_trustedCerts);
|
||||
defaultCertificateVerifier::verify(chain, hostname);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
throw vmime::exceptions::certificate_verification_exception
|
||||
("User did not accept the certificate.");
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
static std::vector <vmime::shared_ptr <vmime::security::cert::X509Certificate> > m_trustedCerts;
|
||||
};
|
||||
|
||||
|
||||
std::vector <vmime::shared_ptr <vmime::security::cert::X509Certificate> >
|
||||
interactiveCertificateVerifier::m_trustedCerts;
|
||||
|
||||
#endif // VMIME_HAVE_TLS_SUPPORT
|
||||
|
48
examples/example6_timeoutHandler.hpp
Normal file
48
examples/example6_timeoutHandler.hpp
Normal file
@ -0,0 +1,48 @@
|
||||
|
||||
|
||||
/** Time out handler.
|
||||
* Used to stop the current operation after too much time, or if the user
|
||||
* requested cancellation.
|
||||
*/
|
||||
class timeoutHandler : public vmime::net::timeoutHandler
|
||||
{
|
||||
public:
|
||||
|
||||
bool isTimeOut()
|
||||
{
|
||||
// This is a cancellation point: return true if you want to cancel
|
||||
// the current operation. If you return true, handleTimeOut() will
|
||||
// be called just after this, and before actually cancelling the
|
||||
// operation
|
||||
return false;
|
||||
}
|
||||
|
||||
void resetTimeOut()
|
||||
{
|
||||
// Called at the beginning of an operation (eg. connecting,
|
||||
// a read() or a write() on a socket...)
|
||||
}
|
||||
|
||||
bool handleTimeOut()
|
||||
{
|
||||
// If isTimeOut() returned true, this function will be called. This
|
||||
// allows you to interact with the user, ie. display a prompt to
|
||||
// know whether he wants to cancel the operation.
|
||||
|
||||
// If you return true here, the operation will be actually cancelled.
|
||||
// If not, the time out is reset and the operation continues.
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
class timeoutHandlerFactory : public vmime::net::timeoutHandlerFactory
|
||||
{
|
||||
public:
|
||||
|
||||
vmime::shared_ptr <vmime::net::timeoutHandler> create()
|
||||
{
|
||||
return vmime::make_shared <timeoutHandler>();
|
||||
}
|
||||
};
|
||||
|
53
examples/example6_tracer.hpp
Normal file
53
examples/example6_tracer.hpp
Normal file
@ -0,0 +1,53 @@
|
||||
|
||||
/** Tracer used to demonstrate logging communication between client and server.
|
||||
*/
|
||||
|
||||
class myTracer : public vmime::net::tracer
|
||||
{
|
||||
public:
|
||||
|
||||
myTracer(vmime::shared_ptr <std::ostringstream> stream,
|
||||
vmime::shared_ptr <vmime::net::service> serv, const int connectionId)
|
||||
: m_stream(stream), m_service(serv), m_connectionId(connectionId)
|
||||
{
|
||||
}
|
||||
|
||||
void traceSend(const vmime::string& line)
|
||||
{
|
||||
*m_stream << "[" << m_service->getProtocolName() << ":" << m_connectionId
|
||||
<< "] C: " << line << std::endl;
|
||||
}
|
||||
|
||||
void traceReceive(const vmime::string& line)
|
||||
{
|
||||
*m_stream << "[" << m_service->getProtocolName() << ":" << m_connectionId
|
||||
<< "] S: " << line << std::endl;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
vmime::shared_ptr <std::ostringstream> m_stream;
|
||||
vmime::shared_ptr <vmime::net::service> m_service;
|
||||
const int m_connectionId;
|
||||
};
|
||||
|
||||
class myTracerFactory : public vmime::net::tracerFactory
|
||||
{
|
||||
public:
|
||||
|
||||
myTracerFactory(vmime::shared_ptr <std::ostringstream> stream)
|
||||
: m_stream(stream)
|
||||
{
|
||||
}
|
||||
|
||||
vmime::shared_ptr <vmime::net::tracer> create
|
||||
(vmime::shared_ptr <vmime::net::service> serv, const int connectionId)
|
||||
{
|
||||
return vmime::make_shared <myTracer>(m_stream, serv, connectionId);
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
vmime::shared_ptr <std::ostringstream> m_stream;
|
||||
};
|
||||
|
@ -56,7 +56,7 @@ shared_ptr <IMAPCommand> IMAPCommand::LOGIN(const string& username, const string
|
||||
|
||||
std::ostringstream trace;
|
||||
trace.imbue(std::locale::classic());
|
||||
trace << "LOGIN <username> <password>";
|
||||
trace << "LOGIN {username} {password}";
|
||||
|
||||
return createCommand(cmd.str(), trace.str());
|
||||
}
|
||||
|
@ -98,7 +98,7 @@ public:
|
||||
/** Returns the full text of the command, suitable for outputing
|
||||
* to the tracer.
|
||||
*
|
||||
* @return trace text (eg. "LOGIN myusername ***")
|
||||
* @return trace text (eg. "LOGIN {username} {password}")
|
||||
*/
|
||||
virtual const string getTraceText() const;
|
||||
|
||||
|
@ -71,10 +71,16 @@ IMAPConnection::IMAPConnection(shared_ptr <IMAPStore> store, shared_ptr <securit
|
||||
m_hierarchySeparator('\0'), m_state(STATE_NONE), m_timeoutHandler(null),
|
||||
m_secured(false), m_firstTag(true), m_capabilitiesFetched(false), m_noModSeq(false)
|
||||
{
|
||||
static int connectionId = 0;
|
||||
|
||||
m_tag = make_shared <IMAPTag>();
|
||||
|
||||
if (store->getTracerFactory())
|
||||
m_tracer = store->getTracerFactory()->create(store, ++connectionId);
|
||||
|
||||
m_parser = make_shared <IMAPParser>();
|
||||
m_parser->setTag(m_tag);
|
||||
m_parser->setTracer(m_tracer);
|
||||
}
|
||||
|
||||
|
||||
@ -439,6 +445,9 @@ void IMAPConnection::authenticateSASL()
|
||||
const string respB64 = saslContext->encodeB64(resp, respLen) + "\r\n";
|
||||
sendRaw(utility::stringUtils::bytesFromString(respB64), respB64.length());
|
||||
|
||||
if (m_tracer)
|
||||
m_tracer->traceSendBytes(respB64.length() - 2, "SASL exchange");
|
||||
|
||||
// Server capabilities may change when logged in
|
||||
invalidateCapabilities();
|
||||
}
|
||||
@ -458,6 +467,9 @@ void IMAPConnection::authenticateSASL()
|
||||
|
||||
// Cancel SASL exchange
|
||||
sendRaw(utility::stringUtils::bytesFromString("*\r\n"), 3);
|
||||
|
||||
if (m_tracer)
|
||||
m_tracer->traceSend("*");
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
@ -752,6 +764,14 @@ void IMAPConnection::sendCommand(shared_ptr <IMAPCommand> cmd)
|
||||
m_socket->send("\r\n");
|
||||
|
||||
m_firstTag = false;
|
||||
|
||||
if (m_tracer)
|
||||
{
|
||||
std::ostringstream oss;
|
||||
oss << string(*m_tag) << " " << cmd->getText();
|
||||
|
||||
m_tracer->traceSend(oss.str());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -816,6 +836,12 @@ void IMAPConnection::setSocket(shared_ptr <socket> sok)
|
||||
}
|
||||
|
||||
|
||||
shared_ptr <tracer> IMAPConnection::getTracer()
|
||||
{
|
||||
return m_tracer;
|
||||
}
|
||||
|
||||
|
||||
shared_ptr <IMAPTag> IMAPConnection::getTag()
|
||||
{
|
||||
return m_tag;
|
||||
|
@ -33,6 +33,7 @@
|
||||
|
||||
#include "vmime/net/socket.hpp"
|
||||
#include "vmime/net/timeoutHandler.hpp"
|
||||
#include "vmime/net/tracer.hpp"
|
||||
#include "vmime/net/session.hpp"
|
||||
#include "vmime/net/connectionInfos.hpp"
|
||||
|
||||
@ -105,6 +106,8 @@ public:
|
||||
shared_ptr <const socket> getSocket() const;
|
||||
void setSocket(shared_ptr <socket> sok);
|
||||
|
||||
shared_ptr <tracer> getTracer();
|
||||
|
||||
shared_ptr <IMAPTag> getTag();
|
||||
|
||||
bool isMODSEQDisabled() const;
|
||||
@ -151,6 +154,8 @@ private:
|
||||
|
||||
bool m_noModSeq;
|
||||
|
||||
shared_ptr <tracer> m_tracer;
|
||||
|
||||
|
||||
void internalDisconnect();
|
||||
|
||||
|
@ -1124,6 +1124,9 @@ messageSet IMAPFolder::addMessage
|
||||
|
||||
m_connection->sendRaw(utility::stringUtils::bytesFromString("\r\n"), 2);
|
||||
|
||||
if (m_connection->getTracer())
|
||||
m_connection->getTracer()->traceSendBytes(current);
|
||||
|
||||
if (progress)
|
||||
progress->stop(total);
|
||||
|
||||
|
@ -49,6 +49,7 @@
|
||||
|
||||
#include "vmime/net/timeoutHandler.hpp"
|
||||
#include "vmime/net/socket.hpp"
|
||||
#include "vmime/net/tracer.hpp"
|
||||
|
||||
#include "vmime/net/imap/IMAPTag.hpp"
|
||||
|
||||
@ -281,6 +282,15 @@ public:
|
||||
m_timeoutHandler = toh;
|
||||
}
|
||||
|
||||
/** Set the tracer currently used by this parser.
|
||||
*
|
||||
* @param tr tracer
|
||||
*/
|
||||
void setTracer(shared_ptr <tracer> tr)
|
||||
{
|
||||
m_tracer = tr;
|
||||
}
|
||||
|
||||
/** Set whether we operate in strict mode (this may not work
|
||||
* with some servers which are not fully standard-compliant).
|
||||
*
|
||||
@ -5687,6 +5697,7 @@ private:
|
||||
|
||||
weak_ptr <IMAPTag> m_tag;
|
||||
weak_ptr <socket> m_socket;
|
||||
shared_ptr <tracer> m_tracer;
|
||||
|
||||
utility::progressListener* m_progress;
|
||||
|
||||
@ -5731,6 +5742,13 @@ public:
|
||||
std::cout << std::endl << "Read line:" << std::endl << line << std::endl;
|
||||
#endif
|
||||
|
||||
if (m_tracer)
|
||||
{
|
||||
string::size_type len = line.length();
|
||||
while (len != 0 && (line[len - 1] == '\r' || line[len - 1] == '\n')) --len;
|
||||
m_tracer->traceReceive(line.substr(0, len));
|
||||
}
|
||||
|
||||
return (line);
|
||||
}
|
||||
|
||||
@ -5860,6 +5878,9 @@ public:
|
||||
m_progress->progress(len, count);
|
||||
}
|
||||
|
||||
if (m_tracer)
|
||||
m_tracer->traceReceiveBytes(count);
|
||||
|
||||
if (m_progress)
|
||||
m_progress->stop(count);
|
||||
}
|
||||
|
@ -42,8 +42,8 @@ namespace net {
|
||||
namespace pop3 {
|
||||
|
||||
|
||||
POP3Command::POP3Command(const string& text)
|
||||
: m_text(text)
|
||||
POP3Command::POP3Command(const string& text, const string& traceText)
|
||||
: m_text(text), m_traceText(traceText)
|
||||
{
|
||||
}
|
||||
|
||||
@ -109,7 +109,11 @@ shared_ptr <POP3Command> POP3Command::USER(const string& username)
|
||||
cmd.imbue(std::locale::classic());
|
||||
cmd << "USER " << username;
|
||||
|
||||
return createCommand(cmd.str());
|
||||
std::ostringstream trace;
|
||||
trace.imbue(std::locale::classic());
|
||||
trace << "USER {username}";
|
||||
|
||||
return createCommand(cmd.str(), trace.str());
|
||||
}
|
||||
|
||||
|
||||
@ -120,7 +124,11 @@ shared_ptr <POP3Command> POP3Command::PASS(const string& password)
|
||||
cmd.imbue(std::locale::classic());
|
||||
cmd << "PASS " << password;
|
||||
|
||||
return createCommand(cmd.str());
|
||||
std::ostringstream trace;
|
||||
trace.imbue(std::locale::classic());
|
||||
trace << "PASS {password}";
|
||||
|
||||
return createCommand(cmd.str(), trace.str());
|
||||
}
|
||||
|
||||
|
||||
@ -215,9 +223,13 @@ shared_ptr <POP3Command> POP3Command::QUIT()
|
||||
|
||||
|
||||
// static
|
||||
shared_ptr <POP3Command> POP3Command::createCommand(const string& text)
|
||||
shared_ptr <POP3Command> POP3Command::createCommand
|
||||
(const string& text, const string& traceText)
|
||||
{
|
||||
return shared_ptr <POP3Command>(new POP3Command(text));
|
||||
if (traceText.empty())
|
||||
return shared_ptr <POP3Command>(new POP3Command(text, text));
|
||||
else
|
||||
return shared_ptr <POP3Command>(new POP3Command(text, traceText));
|
||||
}
|
||||
|
||||
|
||||
@ -227,9 +239,18 @@ const string POP3Command::getText() const
|
||||
}
|
||||
|
||||
|
||||
const string POP3Command::getTraceText() const
|
||||
{
|
||||
return m_traceText;
|
||||
}
|
||||
|
||||
|
||||
void POP3Command::send(shared_ptr <POP3Connection> conn)
|
||||
{
|
||||
conn->getSocket()->send(m_text + "\r\n");
|
||||
|
||||
if (conn->getTracer())
|
||||
conn->getTracer()->traceSend(m_traceText);
|
||||
}
|
||||
|
||||
|
||||
|
@ -76,9 +76,10 @@ public:
|
||||
/** 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 <POP3Command> createCommand(const string& text);
|
||||
static shared_ptr <POP3Command> createCommand(const string& text, const string& traceText = "");
|
||||
|
||||
/** Sends this command over the specified connection.
|
||||
*
|
||||
@ -93,14 +94,22 @@ public:
|
||||
*/
|
||||
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);
|
||||
POP3Command(const string& text, const string& traceText);
|
||||
POP3Command(const POP3Command&);
|
||||
|
||||
private:
|
||||
|
||||
string m_text;
|
||||
string m_traceText;
|
||||
};
|
||||
|
||||
|
||||
|
@ -67,6 +67,10 @@ POP3Connection::POP3Connection(shared_ptr <POP3Store> store, shared_ptr <securit
|
||||
: 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);
|
||||
}
|
||||
|
||||
|
||||
@ -500,7 +504,11 @@ void POP3Connection::authenticateSASL()
|
||||
(challenge, challengeLen, &resp, &respLen);
|
||||
|
||||
// Send response
|
||||
m_socket->send(saslContext->encodeB64(resp, respLen) + "\r\n");
|
||||
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)
|
||||
{
|
||||
@ -518,6 +526,9 @@ void POP3Connection::authenticateSASL()
|
||||
|
||||
// Cancel SASL exchange
|
||||
m_socket->send("*\r\n");
|
||||
|
||||
if (m_tracer)
|
||||
m_tracer->traceSend("*");
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
@ -677,6 +688,12 @@ shared_ptr <socket> POP3Connection::getSocket()
|
||||
}
|
||||
|
||||
|
||||
shared_ptr <tracer> POP3Connection::getTracer()
|
||||
{
|
||||
return m_tracer;
|
||||
}
|
||||
|
||||
|
||||
shared_ptr <timeoutHandler> POP3Connection::getTimeoutHandler()
|
||||
{
|
||||
return m_timeoutHandler;
|
||||
|
@ -37,6 +37,7 @@
|
||||
#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"
|
||||
@ -80,6 +81,7 @@ public:
|
||||
virtual shared_ptr <timeoutHandler> getTimeoutHandler();
|
||||
virtual shared_ptr <security::authenticator> getAuthenticator();
|
||||
virtual shared_ptr <session> getSession();
|
||||
virtual shared_ptr <tracer> getTracer();
|
||||
|
||||
private:
|
||||
|
||||
@ -104,6 +106,7 @@ private:
|
||||
shared_ptr <security::authenticator> m_auth;
|
||||
shared_ptr <socket> m_socket;
|
||||
shared_ptr <timeoutHandler> m_timeoutHandler;
|
||||
shared_ptr <tracer> m_tracer;
|
||||
|
||||
bool m_authenticated;
|
||||
bool m_secured;
|
||||
|
@ -149,7 +149,7 @@ void POP3Message::extract
|
||||
try
|
||||
{
|
||||
POP3Response::readLargeResponse
|
||||
(store->getConnection(), os, progress, m_size);
|
||||
(store->getConnection(), os, progress, m_size == -1 ? 0 : m_size);
|
||||
}
|
||||
catch (exceptions::command_error& e)
|
||||
{
|
||||
|
@ -46,8 +46,8 @@ namespace net {
|
||||
namespace pop3 {
|
||||
|
||||
|
||||
POP3Response::POP3Response(shared_ptr <socket> sok, shared_ptr <timeoutHandler> toh)
|
||||
: m_socket(sok), m_timeoutHandler(toh)
|
||||
POP3Response::POP3Response(shared_ptr <socket> sok, shared_ptr <timeoutHandler> toh, shared_ptr <tracer> tracer)
|
||||
: m_socket(sok), m_timeoutHandler(toh), m_tracer(tracer)
|
||||
{
|
||||
}
|
||||
|
||||
@ -56,7 +56,7 @@ POP3Response::POP3Response(shared_ptr <socket> sok, shared_ptr <timeoutHandler>
|
||||
shared_ptr <POP3Response> POP3Response::readResponse(shared_ptr <POP3Connection> conn)
|
||||
{
|
||||
shared_ptr <POP3Response> resp = shared_ptr <POP3Response>
|
||||
(new POP3Response(conn->getSocket(), conn->getTimeoutHandler()));
|
||||
(new POP3Response(conn->getSocket(), conn->getTimeoutHandler(), conn->getTracer()));
|
||||
|
||||
string buffer;
|
||||
resp->readResponseImpl(buffer, /* multiLine */ false);
|
||||
@ -65,6 +65,9 @@ shared_ptr <POP3Response> POP3Response::readResponse(shared_ptr <POP3Connection>
|
||||
resp->m_code = getResponseCode(buffer);
|
||||
stripResponseCode(buffer, resp->m_text);
|
||||
|
||||
if (resp->m_tracer)
|
||||
resp->m_tracer->traceReceive(buffer);
|
||||
|
||||
return resp;
|
||||
}
|
||||
|
||||
@ -73,7 +76,7 @@ shared_ptr <POP3Response> POP3Response::readResponse(shared_ptr <POP3Connection>
|
||||
shared_ptr <POP3Response> POP3Response::readMultilineResponse(shared_ptr <POP3Connection> conn)
|
||||
{
|
||||
shared_ptr <POP3Response> resp = shared_ptr <POP3Response>
|
||||
(new POP3Response(conn->getSocket(), conn->getTimeoutHandler()));
|
||||
(new POP3Response(conn->getSocket(), conn->getTimeoutHandler(), conn->getTracer()));
|
||||
|
||||
string buffer;
|
||||
resp->readResponseImpl(buffer, /* multiLine */ true);
|
||||
@ -88,8 +91,20 @@ shared_ptr <POP3Response> POP3Response::readMultilineResponse(shared_ptr <POP3Co
|
||||
std::istringstream iss(nextLines);
|
||||
string line;
|
||||
|
||||
if (resp->m_tracer)
|
||||
resp->m_tracer->traceReceive(firstLine);
|
||||
|
||||
while (std::getline(iss, line, '\n'))
|
||||
resp->m_lines.push_back(utility::stringUtils::trim(line));
|
||||
{
|
||||
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;
|
||||
}
|
||||
@ -101,15 +116,22 @@ shared_ptr <POP3Response> POP3Response::readLargeResponse
|
||||
utility::progressListener* progress, const size_t predictedSize)
|
||||
{
|
||||
shared_ptr <POP3Response> resp = shared_ptr <POP3Response>
|
||||
(new POP3Response(conn->getSocket(), conn->getTimeoutHandler()));
|
||||
(new POP3Response(conn->getSocket(), conn->getTimeoutHandler(), conn->getTracer()));
|
||||
|
||||
string firstLine;
|
||||
resp->readResponseImpl(firstLine, os, progress, predictedSize);
|
||||
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;
|
||||
}
|
||||
|
||||
@ -230,7 +252,7 @@ void POP3Response::readResponseImpl(string& buffer, const bool multiLine)
|
||||
}
|
||||
|
||||
|
||||
void POP3Response::readResponseImpl
|
||||
size_t POP3Response::readResponseImpl
|
||||
(string& firstLine, utility::outputStream& os,
|
||||
utility::progressListener* progress, const size_t predictedSize)
|
||||
{
|
||||
@ -327,6 +349,8 @@ void POP3Response::readResponseImpl
|
||||
|
||||
if (progress)
|
||||
progress->stop(total);
|
||||
|
||||
return current;
|
||||
}
|
||||
|
||||
|
||||
|
@ -38,6 +38,7 @@
|
||||
#include "vmime/utility/progressListener.hpp"
|
||||
|
||||
#include "vmime/net/socket.hpp"
|
||||
#include "vmime/net/tracer.hpp"
|
||||
|
||||
|
||||
namespace vmime {
|
||||
@ -143,10 +144,10 @@ public:
|
||||
|
||||
private:
|
||||
|
||||
POP3Response(shared_ptr <socket> sok, shared_ptr <timeoutHandler> toh);
|
||||
POP3Response(shared_ptr <socket> sok, shared_ptr <timeoutHandler> toh, shared_ptr <tracer> tracer);
|
||||
|
||||
void readResponseImpl(string& buffer, const bool multiLine);
|
||||
void readResponseImpl
|
||||
size_t readResponseImpl
|
||||
(string& firstLine, utility::outputStream& os,
|
||||
utility::progressListener* progress, const size_t predictedSize);
|
||||
|
||||
@ -163,6 +164,7 @@ private:
|
||||
|
||||
shared_ptr <socket> m_socket;
|
||||
shared_ptr <timeoutHandler> m_timeoutHandler;
|
||||
shared_ptr <tracer> m_tracer;
|
||||
|
||||
string m_firstLine;
|
||||
ResponseCode m_code;
|
||||
|
@ -136,6 +136,18 @@ shared_ptr <socketFactory> service::getSocketFactory()
|
||||
}
|
||||
|
||||
|
||||
void service::setTracerFactory(shared_ptr <tracerFactory> tf)
|
||||
{
|
||||
m_tracerFactory = tf;
|
||||
}
|
||||
|
||||
|
||||
shared_ptr <tracerFactory> service::getTracerFactory()
|
||||
{
|
||||
return m_tracerFactory;
|
||||
}
|
||||
|
||||
|
||||
void service::setTimeoutHandlerFactory(shared_ptr <timeoutHandlerFactory> thf)
|
||||
{
|
||||
m_toHandlerFactory = thf;
|
||||
|
@ -40,6 +40,7 @@
|
||||
|
||||
#include "vmime/net/socket.hpp"
|
||||
#include "vmime/net/timeoutHandler.hpp"
|
||||
#include "vmime/net/tracer.hpp"
|
||||
|
||||
#if VMIME_HAVE_TLS_SUPPORT
|
||||
#include "vmime/security/cert/certificateVerifier.hpp"
|
||||
@ -183,6 +184,11 @@ public:
|
||||
*/
|
||||
shared_ptr <timeoutHandlerFactory> getTimeoutHandlerFactory();
|
||||
|
||||
|
||||
void setTracerFactory(shared_ptr <tracerFactory> tf);
|
||||
|
||||
shared_ptr <tracerFactory> getTracerFactory();
|
||||
|
||||
/** Set a property for this service (service prefix is added automatically).
|
||||
*
|
||||
* WARNING: this sets the property on the session object, so all service
|
||||
@ -219,8 +225,8 @@ private:
|
||||
#endif // VMIME_HAVE_TLS_SUPPORT
|
||||
|
||||
shared_ptr <socketFactory> m_socketFactory;
|
||||
|
||||
shared_ptr <timeoutHandlerFactory> m_toHandlerFactory;
|
||||
shared_ptr <tracerFactory> m_tracerFactory;
|
||||
};
|
||||
|
||||
|
||||
|
@ -73,6 +73,9 @@ void SMTPChunkingOutputStreamAdapter::sendChunk
|
||||
m_progress->progress(m_totalSent, m_totalSize);
|
||||
}
|
||||
|
||||
if (m_connection->getTracer())
|
||||
m_connection->getTracer()->traceSendBytes(count);
|
||||
|
||||
// If PIPELINING is not supported, read one response for this BDAT command
|
||||
if (!m_connection->hasExtension("PIPELINING"))
|
||||
{
|
||||
@ -143,6 +146,9 @@ void SMTPChunkingOutputStreamAdapter::flush()
|
||||
|
||||
if (m_progress)
|
||||
m_progress->stop(m_totalSize);
|
||||
|
||||
if (m_connection->getTracer())
|
||||
m_connection->getTracer()->traceSendBytes(m_bufferSize);
|
||||
}
|
||||
|
||||
|
||||
|
@ -30,6 +30,7 @@
|
||||
#include "vmime/net/smtp/SMTPCommand.hpp"
|
||||
|
||||
#include "vmime/net/socket.hpp"
|
||||
#include "vmime/net/tracer.hpp"
|
||||
|
||||
#include "vmime/mailbox.hpp"
|
||||
#include "vmime/utility/outputStreamAdapter.hpp"
|
||||
@ -40,8 +41,8 @@ namespace net {
|
||||
namespace smtp {
|
||||
|
||||
|
||||
SMTPCommand::SMTPCommand(const string& text)
|
||||
: m_text(text)
|
||||
SMTPCommand::SMTPCommand(const string& text, const string& traceText)
|
||||
: m_text(text), m_traceText(traceText)
|
||||
{
|
||||
}
|
||||
|
||||
@ -199,9 +200,12 @@ shared_ptr <SMTPCommand> SMTPCommand::QUIT()
|
||||
|
||||
|
||||
// static
|
||||
shared_ptr <SMTPCommand> SMTPCommand::createCommand(const string& text)
|
||||
shared_ptr <SMTPCommand> SMTPCommand::createCommand(const string& text, const string& traceText)
|
||||
{
|
||||
return shared_ptr <SMTPCommand>(new SMTPCommand(text));
|
||||
if (traceText.empty())
|
||||
return shared_ptr <SMTPCommand>(new SMTPCommand(text, text));
|
||||
else
|
||||
return shared_ptr <SMTPCommand>(new SMTPCommand(text, traceText));
|
||||
}
|
||||
|
||||
|
||||
@ -211,9 +215,18 @@ const string SMTPCommand::getText() const
|
||||
}
|
||||
|
||||
|
||||
void SMTPCommand::writeToSocket(shared_ptr <socket> sok)
|
||||
const string SMTPCommand::getTraceText() const
|
||||
{
|
||||
return m_traceText;
|
||||
}
|
||||
|
||||
|
||||
void SMTPCommand::writeToSocket(shared_ptr <socket> sok, shared_ptr <tracer> tr)
|
||||
{
|
||||
sok->send(m_text + "\r\n");
|
||||
|
||||
if (tr)
|
||||
tr->traceSend(m_traceText);
|
||||
}
|
||||
|
||||
|
||||
|
@ -46,6 +46,7 @@ namespace net {
|
||||
|
||||
class socket;
|
||||
class timeoutHandler;
|
||||
class tracer;
|
||||
|
||||
|
||||
namespace smtp {
|
||||
@ -76,13 +77,14 @@ public:
|
||||
* @param text command text
|
||||
* @return a new SMTPCommand object
|
||||
*/
|
||||
static shared_ptr <SMTPCommand> createCommand(const string& text);
|
||||
static shared_ptr <SMTPCommand> createCommand(const string& text, const string& traceText = "");
|
||||
|
||||
/** Sends this command to the specified socket.
|
||||
*
|
||||
* @param sok socket to which the command will be written
|
||||
* @param tr tracer
|
||||
*/
|
||||
virtual void writeToSocket(shared_ptr <socket> sok);
|
||||
virtual void writeToSocket(shared_ptr <socket> sok, shared_ptr <tracer> tr);
|
||||
|
||||
/** Returns the full text of the command, including command name
|
||||
* and parameters (if any).
|
||||
@ -91,14 +93,22 @@ public:
|
||||
*/
|
||||
virtual const string getText() const;
|
||||
|
||||
/** Returns the full text of the command, suitable for outputing
|
||||
* to the tracer.
|
||||
*
|
||||
* @return trace text (eg. "LOGIN myusername ***")
|
||||
*/
|
||||
virtual const string getTraceText() const;
|
||||
|
||||
protected:
|
||||
|
||||
SMTPCommand(const string& text);
|
||||
SMTPCommand(const string& text, const string& traceText);
|
||||
SMTPCommand(const SMTPCommand&);
|
||||
|
||||
private:
|
||||
|
||||
string m_text;
|
||||
string m_traceText;
|
||||
};
|
||||
|
||||
|
||||
|
@ -42,7 +42,7 @@ namespace smtp {
|
||||
|
||||
|
||||
SMTPCommandSet::SMTPCommandSet(const bool pipeline)
|
||||
: SMTPCommand(""), m_pipeline(pipeline),
|
||||
: SMTPCommand("", ""), m_pipeline(pipeline),
|
||||
m_started(false), m_lastCommandSent()
|
||||
{
|
||||
}
|
||||
@ -67,7 +67,7 @@ void SMTPCommandSet::addCommand(shared_ptr <SMTPCommand> cmd)
|
||||
}
|
||||
|
||||
|
||||
void SMTPCommandSet::writeToSocket(shared_ptr <socket> sok)
|
||||
void SMTPCommandSet::writeToSocket(shared_ptr <socket> sok, shared_ptr <tracer> tr)
|
||||
{
|
||||
if (m_pipeline)
|
||||
{
|
||||
@ -78,7 +78,7 @@ void SMTPCommandSet::writeToSocket(shared_ptr <socket> sok)
|
||||
it != m_commands.end() ; ++it)
|
||||
{
|
||||
shared_ptr <SMTPCommand> cmd = *it;
|
||||
cmd->writeToSocket(sok);
|
||||
cmd->writeToSocket(sok, tr);
|
||||
}
|
||||
}
|
||||
|
||||
@ -99,7 +99,7 @@ void SMTPCommandSet::writeToSocket(shared_ptr <socket> sok)
|
||||
shared_ptr <SMTPCommand> cmd = m_commands.front();
|
||||
m_commands.pop_front();
|
||||
|
||||
cmd->writeToSocket(sok);
|
||||
cmd->writeToSocket(sok, tr);
|
||||
|
||||
m_lastCommandSent = cmd;
|
||||
}
|
||||
@ -124,6 +124,21 @@ const string SMTPCommandSet::getText() const
|
||||
}
|
||||
|
||||
|
||||
const string SMTPCommandSet::getTraceText() const
|
||||
{
|
||||
std::ostringstream cmd;
|
||||
cmd.imbue(std::locale::classic());
|
||||
|
||||
for (std::list <shared_ptr <SMTPCommand> >::const_iterator it = m_commands.begin() ;
|
||||
it != m_commands.end() ; ++it)
|
||||
{
|
||||
cmd << (*it)->getTraceText() << "\r\n";
|
||||
}
|
||||
|
||||
return cmd.str();
|
||||
}
|
||||
|
||||
|
||||
bool SMTPCommandSet::isFinished() const
|
||||
{
|
||||
return (m_pipeline && m_started) || (m_commands.size() == 0 && m_started);
|
||||
|
@ -78,9 +78,10 @@ public:
|
||||
shared_ptr <SMTPCommand> getLastCommandSent() const;
|
||||
|
||||
|
||||
void writeToSocket(shared_ptr <socket> sok);
|
||||
void writeToSocket(shared_ptr <socket> sok, shared_ptr <tracer> tr);
|
||||
|
||||
const string getText() const;
|
||||
const string getTraceText() const;
|
||||
|
||||
private:
|
||||
|
||||
|
@ -68,6 +68,10 @@ SMTPConnection::SMTPConnection(shared_ptr <SMTPTransport> transport, shared_ptr
|
||||
: m_transport(transport), m_auth(auth), m_socket(null), m_timeoutHandler(null),
|
||||
m_authenticated(false), m_secured(false), m_extendedSMTP(false)
|
||||
{
|
||||
static int connectionId = 0;
|
||||
|
||||
if (transport->getTracerFactory())
|
||||
m_tracer = transport->getTracerFactory()->create(transport, ++connectionId);
|
||||
}
|
||||
|
||||
|
||||
@ -416,7 +420,11 @@ void SMTPConnection::authenticateSASL()
|
||||
(challenge, challengeLen, &resp, &respLen);
|
||||
|
||||
// Send response
|
||||
m_socket->send(saslContext->encodeB64(resp, respLen) + "\r\n");
|
||||
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)
|
||||
{
|
||||
@ -434,6 +442,9 @@ void SMTPConnection::authenticateSASL()
|
||||
|
||||
// Cancel SASL exchange
|
||||
m_socket->send("*\r\n");
|
||||
|
||||
if (m_tracer)
|
||||
m_tracer->traceSend("*");
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
@ -557,14 +568,14 @@ void SMTPConnection::internalDisconnect()
|
||||
|
||||
void SMTPConnection::sendRequest(shared_ptr <SMTPCommand> cmd)
|
||||
{
|
||||
cmd->writeToSocket(m_socket);
|
||||
cmd->writeToSocket(m_socket, m_tracer);
|
||||
}
|
||||
|
||||
|
||||
shared_ptr <SMTPResponse> SMTPConnection::readResponse()
|
||||
{
|
||||
shared_ptr <SMTPResponse> resp = SMTPResponse::readResponse
|
||||
(m_socket, m_timeoutHandler, m_responseState);
|
||||
(m_tracer, m_socket, m_timeoutHandler, m_responseState);
|
||||
|
||||
m_responseState = resp->getCurrentState();
|
||||
|
||||
@ -608,6 +619,12 @@ shared_ptr <socket> SMTPConnection::getSocket()
|
||||
}
|
||||
|
||||
|
||||
shared_ptr <tracer> SMTPConnection::getTracer()
|
||||
{
|
||||
return m_tracer;
|
||||
}
|
||||
|
||||
|
||||
shared_ptr <timeoutHandler> SMTPConnection::getTimeoutHandler()
|
||||
{
|
||||
return m_timeoutHandler;
|
||||
|
@ -37,6 +37,7 @@
|
||||
#include "vmime/net/timeoutHandler.hpp"
|
||||
#include "vmime/net/session.hpp"
|
||||
#include "vmime/net/connectionInfos.hpp"
|
||||
#include "vmime/net/tracer.hpp"
|
||||
|
||||
#include "vmime/net/smtp/SMTPCommand.hpp"
|
||||
#include "vmime/net/smtp/SMTPResponse.hpp"
|
||||
@ -80,6 +81,7 @@ public:
|
||||
virtual shared_ptr <timeoutHandler> getTimeoutHandler();
|
||||
virtual shared_ptr <security::authenticator> getAuthenticator();
|
||||
virtual shared_ptr <session> getSession();
|
||||
virtual shared_ptr <tracer> getTracer();
|
||||
|
||||
void sendRequest(shared_ptr <SMTPCommand> cmd);
|
||||
shared_ptr <SMTPResponse> readResponse();
|
||||
@ -106,6 +108,7 @@ private:
|
||||
shared_ptr <security::authenticator> m_auth;
|
||||
shared_ptr <socket> m_socket;
|
||||
shared_ptr <timeoutHandler> m_timeoutHandler;
|
||||
shared_ptr <tracer> m_tracer;
|
||||
|
||||
SMTPResponse::state m_responseState;
|
||||
|
||||
|
@ -34,6 +34,7 @@
|
||||
|
||||
#include "vmime/net/socket.hpp"
|
||||
#include "vmime/net/timeoutHandler.hpp"
|
||||
#include "vmime/net/tracer.hpp"
|
||||
|
||||
#include <cctype>
|
||||
|
||||
@ -43,8 +44,10 @@ namespace net {
|
||||
namespace smtp {
|
||||
|
||||
|
||||
SMTPResponse::SMTPResponse(shared_ptr <socket> sok, shared_ptr <timeoutHandler> toh, const state& st)
|
||||
: m_socket(sok), m_timeoutHandler(toh),
|
||||
SMTPResponse::SMTPResponse
|
||||
(shared_ptr <tracer> tr, shared_ptr <socket> sok,
|
||||
shared_ptr <timeoutHandler> toh, const state& st)
|
||||
: m_socket(sok), m_timeoutHandler(toh), m_tracer(tr),
|
||||
m_responseBuffer(st.responseBuffer), m_responseContinues(false)
|
||||
{
|
||||
}
|
||||
@ -95,9 +98,11 @@ const string SMTPResponse::getText() const
|
||||
|
||||
// static
|
||||
shared_ptr <SMTPResponse> SMTPResponse::readResponse
|
||||
(shared_ptr <socket> sok, shared_ptr <timeoutHandler> toh, const state& st)
|
||||
(shared_ptr <tracer> tr, shared_ptr <socket> sok,
|
||||
shared_ptr <timeoutHandler> toh, const state& st)
|
||||
{
|
||||
shared_ptr <SMTPResponse> resp = shared_ptr <SMTPResponse>(new SMTPResponse(sok, toh, st));
|
||||
shared_ptr <SMTPResponse> resp =
|
||||
shared_ptr <SMTPResponse>(new SMTPResponse(tr, sok, toh, st));
|
||||
|
||||
resp->readResponse();
|
||||
|
||||
@ -142,6 +147,9 @@ const string SMTPResponse::readResponseLine()
|
||||
currentBuffer.erase(currentBuffer.begin(), currentBuffer.begin() + lineEnd + 1);
|
||||
m_responseBuffer = currentBuffer;
|
||||
|
||||
if (m_tracer)
|
||||
m_tracer->traceReceive(line);
|
||||
|
||||
return line;
|
||||
}
|
||||
|
||||
|
@ -41,6 +41,7 @@ namespace net {
|
||||
|
||||
class socket;
|
||||
class timeoutHandler;
|
||||
class tracer;
|
||||
|
||||
|
||||
namespace smtp {
|
||||
@ -95,6 +96,7 @@ public:
|
||||
/** Receive and parse a new SMTP response from the
|
||||
* specified socket.
|
||||
*
|
||||
* @param tr tracer
|
||||
* @param sok socket from which to read
|
||||
* @param toh time-out handler
|
||||
* @param st previous state of response parser for the specified socket
|
||||
@ -102,7 +104,9 @@ public:
|
||||
* @throws exceptions::operation_timed_out if no data
|
||||
* has been received within the granted time
|
||||
*/
|
||||
static shared_ptr <SMTPResponse> readResponse(shared_ptr <socket> sok, shared_ptr <timeoutHandler> toh, const state& st);
|
||||
static shared_ptr <SMTPResponse> readResponse
|
||||
(shared_ptr <tracer> tr, shared_ptr <socket> sok,
|
||||
shared_ptr <timeoutHandler> toh, const state& st);
|
||||
|
||||
/** Return the SMTP response code.
|
||||
*
|
||||
@ -150,7 +154,7 @@ public:
|
||||
|
||||
private:
|
||||
|
||||
SMTPResponse(shared_ptr <socket> sok, shared_ptr <timeoutHandler> toh, const state& st);
|
||||
SMTPResponse(shared_ptr <tracer> tr, shared_ptr <socket> sok, shared_ptr <timeoutHandler> toh, const state& st);
|
||||
SMTPResponse(const SMTPResponse&);
|
||||
|
||||
void readResponse();
|
||||
@ -166,6 +170,7 @@ private:
|
||||
|
||||
shared_ptr <socket> m_socket;
|
||||
shared_ptr <timeoutHandler> m_timeoutHandler;
|
||||
shared_ptr <tracer> m_tracer;
|
||||
|
||||
string m_responseBuffer;
|
||||
bool m_responseContinues;
|
||||
|
@ -210,7 +210,7 @@ void SMTPTransport::sendEnvelope
|
||||
// Read response for "RSET" command
|
||||
if (needReset)
|
||||
{
|
||||
commands->writeToSocket(m_connection->getSocket());
|
||||
commands->writeToSocket(m_connection->getSocket(), m_connection->getTracer());
|
||||
|
||||
resp = m_connection->readResponse();
|
||||
|
||||
@ -227,7 +227,7 @@ void SMTPTransport::sendEnvelope
|
||||
}
|
||||
|
||||
// Read response for "MAIL" command
|
||||
commands->writeToSocket(m_connection->getSocket());
|
||||
commands->writeToSocket(m_connection->getSocket(), m_connection->getTracer());
|
||||
|
||||
if ((resp = m_connection->readResponse())->getCode() != 250)
|
||||
{
|
||||
@ -257,7 +257,7 @@ void SMTPTransport::sendEnvelope
|
||||
// Read responses for "RCPT TO" commands
|
||||
for (size_t i = 0 ; i < recipients.getMailboxCount() ; ++i)
|
||||
{
|
||||
commands->writeToSocket(m_connection->getSocket());
|
||||
commands->writeToSocket(m_connection->getSocket(), m_connection->getTracer());
|
||||
|
||||
resp = m_connection->readResponse();
|
||||
|
||||
@ -291,7 +291,7 @@ void SMTPTransport::sendEnvelope
|
||||
// Read response for "DATA" command
|
||||
if (sendDATACommand)
|
||||
{
|
||||
commands->writeToSocket(m_connection->getSocket());
|
||||
commands->writeToSocket(m_connection->getSocket(), m_connection->getTracer());
|
||||
|
||||
if ((resp = m_connection->readResponse())->getCode() != 354)
|
||||
{
|
||||
@ -326,6 +326,12 @@ void SMTPTransport::send
|
||||
// Send end-of-data delimiter
|
||||
m_connection->getSocket()->send("\r\n.\r\n");
|
||||
|
||||
if (m_connection->getTracer())
|
||||
{
|
||||
m_connection->getTracer()->traceSendBytes(size);
|
||||
m_connection->getTracer()->traceSend(".");
|
||||
}
|
||||
|
||||
shared_ptr <SMTPResponse> resp;
|
||||
|
||||
if ((resp = m_connection->readResponse())->getCode() != 250)
|
||||
|
72
src/vmime/net/tracer.cpp
Normal file
72
src/vmime/net/tracer.cpp
Normal file
@ -0,0 +1,72 @@
|
||||
//
|
||||
// VMime library (http://www.vmime.org)
|
||||
// Copyright (C) 2002-2014 Vincent Richard <vincent@vmime.org>
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License as
|
||||
// published by the Free Software Foundation; either version 3 of
|
||||
// the License, or (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License along
|
||||
// with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
//
|
||||
// Linking this library statically or dynamically with other modules is making
|
||||
// a combined work based on this library. Thus, the terms and conditions of
|
||||
// the GNU General Public License cover the whole combination.
|
||||
//
|
||||
|
||||
#include "vmime/config.hpp"
|
||||
|
||||
|
||||
#if VMIME_HAVE_MESSAGING_FEATURES
|
||||
|
||||
|
||||
#include "tracer.hpp"
|
||||
|
||||
|
||||
#include <sstream>
|
||||
|
||||
|
||||
namespace vmime {
|
||||
namespace net {
|
||||
|
||||
|
||||
void tracer::traceReceiveBytes(const size_t count, const string& state)
|
||||
{
|
||||
std::ostringstream oss;
|
||||
oss << "{...";
|
||||
|
||||
if (!state.empty())
|
||||
oss << state << ": ";
|
||||
|
||||
oss << count << " bytes of data...}";
|
||||
|
||||
traceReceive(oss.str());
|
||||
}
|
||||
|
||||
|
||||
void tracer::traceSendBytes(const size_t count, const string& state)
|
||||
{
|
||||
std::ostringstream oss;
|
||||
oss << "{...";
|
||||
|
||||
if (!state.empty())
|
||||
oss << state << ": ";
|
||||
|
||||
oss << count << " bytes of data...}";
|
||||
|
||||
traceSend(oss.str());
|
||||
}
|
||||
|
||||
|
||||
} // net
|
||||
} // vmime
|
||||
|
||||
|
||||
#endif // VMIME_HAVE_MESSAGING_FEATURES
|
109
src/vmime/net/tracer.hpp
Normal file
109
src/vmime/net/tracer.hpp
Normal file
@ -0,0 +1,109 @@
|
||||
//
|
||||
// VMime library (http://www.vmime.org)
|
||||
// Copyright (C) 2002-2014 Vincent Richard <vincent@vmime.org>
|
||||
//
|
||||
// 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_TRACER_HPP_INCLUDED
|
||||
#define VMIME_NET_TRACER_HPP_INCLUDED
|
||||
|
||||
|
||||
#include "vmime/config.hpp"
|
||||
|
||||
|
||||
#if VMIME_HAVE_MESSAGING_FEATURES
|
||||
|
||||
|
||||
#include "vmime/base.hpp"
|
||||
|
||||
|
||||
namespace vmime {
|
||||
namespace net {
|
||||
|
||||
|
||||
class service;
|
||||
|
||||
|
||||
/** Base class for an object used to trace network communication
|
||||
* between the client and the server.
|
||||
*/
|
||||
|
||||
class VMIME_EXPORT tracer : public object
|
||||
{
|
||||
public:
|
||||
|
||||
virtual ~tracer() { }
|
||||
|
||||
/** Trace raw bytes which have been received.
|
||||
*
|
||||
* @param count number of bytes
|
||||
* @param state protocol state (eg. "SASL exchange"), or empty
|
||||
*/
|
||||
virtual void traceReceiveBytes(const size_t count, const string& state = "");
|
||||
|
||||
/** Trace raw bytes which have been sent.
|
||||
*
|
||||
* @param count number of bytes
|
||||
* @param state protocol state (eg. "SASL exchange"), or empty
|
||||
*/
|
||||
virtual void traceSendBytes(const size_t count, const string& state = "");
|
||||
|
||||
/** Trace a command line which has been sent.
|
||||
*
|
||||
* @param line command line
|
||||
*/
|
||||
virtual void traceSend(const string& line) = 0;
|
||||
|
||||
/** Trace a response line which has been received.
|
||||
*
|
||||
* @param line response line
|
||||
*/
|
||||
virtual void traceReceive(const string& line) = 0;
|
||||
};
|
||||
|
||||
|
||||
|
||||
/** A class to create 'tracer' objects.
|
||||
*/
|
||||
|
||||
class VMIME_EXPORT tracerFactory : public object
|
||||
{
|
||||
public:
|
||||
|
||||
virtual ~tracerFactory() { }
|
||||
|
||||
/** Creates a tracer for the specified service.
|
||||
*
|
||||
* @param serv messaging service
|
||||
* @param connectionId an identifier for the connection to distinguate between
|
||||
* different connections used by a service
|
||||
* @return a new tracer
|
||||
*/
|
||||
virtual shared_ptr <tracer> create(shared_ptr <service> serv, const int connectionId) = 0;
|
||||
};
|
||||
|
||||
|
||||
} // net
|
||||
} // vmime
|
||||
|
||||
|
||||
#endif // VMIME_HAVE_MESSAGING_FEATURES
|
||||
|
||||
#endif // VMIME_NET_TRACER_HPP_INCLUDED
|
@ -69,15 +69,16 @@ VMIME_TEST_SUITE_BEGIN(SMTPCommandSetTest)
|
||||
VASSERT_NO_THROW("No throw 2", cset->addCommand(SMTPCommand::createCommand("MY_COMMAND2")));
|
||||
VASSERT_EQ("Text", "MY_COMMAND1\r\nMY_COMMAND2\r\n", cset->getText());
|
||||
|
||||
vmime::shared_ptr <vmime::net::tracer> tracer;
|
||||
vmime::shared_ptr <testSocket> sok = vmime::make_shared <testSocket>();
|
||||
|
||||
cset->writeToSocket(sok);
|
||||
cset->writeToSocket(sok, tracer);
|
||||
VASSERT_FALSE("Finished", cset->isFinished());
|
||||
|
||||
// Can't add commands when writing to socket has started
|
||||
VASSERT_THROW("Throw", cset->addCommand(SMTPCommand::createCommand("MY_COMMAND3")), std::runtime_error);
|
||||
|
||||
cset->writeToSocket(sok);
|
||||
cset->writeToSocket(sok, tracer);
|
||||
VASSERT_TRUE("Finished", cset->isFinished());
|
||||
}
|
||||
|
||||
@ -90,10 +91,11 @@ VMIME_TEST_SUITE_BEGIN(SMTPCommandSetTest)
|
||||
VASSERT_NO_THROW("No throw 2", cset->addCommand(SMTPCommand::createCommand("MY_COMMAND2")));
|
||||
VASSERT_EQ("Text", "MY_COMMAND1\r\nMY_COMMAND2\r\n", cset->getText());
|
||||
|
||||
vmime::shared_ptr <vmime::net::tracer> tracer;
|
||||
vmime::shared_ptr <testSocket> sok = vmime::make_shared <testSocket>();
|
||||
vmime::string response;
|
||||
|
||||
cset->writeToSocket(sok);
|
||||
cset->writeToSocket(sok, tracer);
|
||||
VASSERT_TRUE("Finished", cset->isFinished());
|
||||
|
||||
sok->localReceive(response);
|
||||
@ -110,15 +112,16 @@ VMIME_TEST_SUITE_BEGIN(SMTPCommandSetTest)
|
||||
cset->addCommand(SMTPCommand::createCommand("MY_COMMAND1"));
|
||||
cset->addCommand(SMTPCommand::createCommand("MY_COMMAND2"));
|
||||
|
||||
vmime::shared_ptr <vmime::net::tracer> tracer;
|
||||
vmime::shared_ptr <testSocket> sok = vmime::make_shared <testSocket>();
|
||||
vmime::string response;
|
||||
|
||||
cset->writeToSocket(sok);
|
||||
cset->writeToSocket(sok, tracer);
|
||||
|
||||
sok->localReceive(response);
|
||||
VASSERT_EQ("Receive cmd 1", "MY_COMMAND1\r\n", response);
|
||||
|
||||
cset->writeToSocket(sok);
|
||||
cset->writeToSocket(sok, tracer);
|
||||
|
||||
sok->localReceive(response);
|
||||
VASSERT_EQ("Receive cmd 2", "MY_COMMAND2\r\n", response);
|
||||
@ -131,10 +134,11 @@ VMIME_TEST_SUITE_BEGIN(SMTPCommandSetTest)
|
||||
cset->addCommand(SMTPCommand::createCommand("MY_COMMAND1"));
|
||||
cset->addCommand(SMTPCommand::createCommand("MY_COMMAND2"));
|
||||
|
||||
vmime::shared_ptr <vmime::net::tracer> tracer;
|
||||
vmime::shared_ptr <testSocket> sok = vmime::make_shared <testSocket>();
|
||||
vmime::string response;
|
||||
|
||||
cset->writeToSocket(sok);
|
||||
cset->writeToSocket(sok, tracer);
|
||||
|
||||
sok->localReceive(response);
|
||||
VASSERT_EQ("Receive cmds", "MY_COMMAND1\r\nMY_COMMAND2\r\n", response);
|
||||
@ -147,12 +151,13 @@ VMIME_TEST_SUITE_BEGIN(SMTPCommandSetTest)
|
||||
cset->addCommand(SMTPCommand::createCommand("MY_COMMAND1"));
|
||||
cset->addCommand(SMTPCommand::createCommand("MY_COMMAND2"));
|
||||
|
||||
vmime::shared_ptr <vmime::net::tracer> tracer;
|
||||
vmime::shared_ptr <testSocket> sok = vmime::make_shared <testSocket>();
|
||||
|
||||
cset->writeToSocket(sok);
|
||||
cset->writeToSocket(sok, tracer);
|
||||
VASSERT_EQ("Cmd 1", "MY_COMMAND1", cset->getLastCommandSent()->getText());
|
||||
|
||||
cset->writeToSocket(sok);
|
||||
cset->writeToSocket(sok, tracer);
|
||||
VASSERT_EQ("Cmd 2", "MY_COMMAND2", cset->getLastCommandSent()->getText());
|
||||
}
|
||||
|
||||
@ -163,12 +168,13 @@ VMIME_TEST_SUITE_BEGIN(SMTPCommandSetTest)
|
||||
cset->addCommand(SMTPCommand::createCommand("MY_COMMAND1"));
|
||||
cset->addCommand(SMTPCommand::createCommand("MY_COMMAND2"));
|
||||
|
||||
vmime::shared_ptr <vmime::net::tracer> tracer;
|
||||
vmime::shared_ptr <testSocket> sok = vmime::make_shared <testSocket>();
|
||||
|
||||
cset->writeToSocket(sok);
|
||||
cset->writeToSocket(sok, tracer);
|
||||
VASSERT_EQ("Cmd 1", "MY_COMMAND1", cset->getLastCommandSent()->getText());
|
||||
|
||||
cset->writeToSocket(sok);
|
||||
cset->writeToSocket(sok, tracer);
|
||||
VASSERT_EQ("Cmd 2", "MY_COMMAND2", cset->getLastCommandSent()->getText());
|
||||
}
|
||||
|
||||
|
@ -231,8 +231,10 @@ VMIME_TEST_SUITE_BEGIN(SMTPCommandTest)
|
||||
{
|
||||
vmime::shared_ptr <SMTPCommand> cmd = SMTPCommand::createCommand("MY_COMMAND param1 param2");
|
||||
|
||||
vmime::shared_ptr <vmime::net::tracer> tracer;
|
||||
vmime::shared_ptr <testSocket> sok = vmime::make_shared <testSocket>();
|
||||
cmd->writeToSocket(sok);
|
||||
|
||||
cmd->writeToSocket(sok, tracer);
|
||||
|
||||
vmime::string response;
|
||||
sok->localReceive(response);
|
||||
|
@ -43,6 +43,7 @@ VMIME_TEST_SUITE_BEGIN(SMTPResponseTest)
|
||||
|
||||
void testSingleLineResponse()
|
||||
{
|
||||
vmime::shared_ptr <vmime::net::tracer> tracer;
|
||||
vmime::shared_ptr <testSocket> socket = vmime::make_shared <testSocket>();
|
||||
vmime::shared_ptr <vmime::net::timeoutHandler> toh =
|
||||
vmime::make_shared <testTimeoutHandler>();
|
||||
@ -52,7 +53,7 @@ VMIME_TEST_SUITE_BEGIN(SMTPResponseTest)
|
||||
vmime::net::smtp::SMTPResponse::state responseState;
|
||||
|
||||
vmime::shared_ptr <vmime::net::smtp::SMTPResponse> resp =
|
||||
vmime::net::smtp::SMTPResponse::readResponse(socket, toh, responseState);
|
||||
vmime::net::smtp::SMTPResponse::readResponse(tracer, socket, toh, responseState);
|
||||
|
||||
VASSERT_EQ("Code", 123, resp->getCode());
|
||||
VASSERT_EQ("Lines", 1, resp->getLineCount());
|
||||
@ -61,6 +62,7 @@ VMIME_TEST_SUITE_BEGIN(SMTPResponseTest)
|
||||
|
||||
void testSingleLineResponseLF()
|
||||
{
|
||||
vmime::shared_ptr <vmime::net::tracer> tracer;
|
||||
vmime::shared_ptr <testSocket> socket = vmime::make_shared <testSocket>();
|
||||
vmime::shared_ptr <vmime::net::timeoutHandler> toh =
|
||||
vmime::make_shared <testTimeoutHandler>();
|
||||
@ -70,7 +72,7 @@ VMIME_TEST_SUITE_BEGIN(SMTPResponseTest)
|
||||
vmime::net::smtp::SMTPResponse::state responseState;
|
||||
|
||||
vmime::shared_ptr <vmime::net::smtp::SMTPResponse> resp =
|
||||
vmime::net::smtp::SMTPResponse::readResponse(socket, toh, responseState);
|
||||
vmime::net::smtp::SMTPResponse::readResponse(tracer, socket, toh, responseState);
|
||||
|
||||
VASSERT_EQ("Code", 123, resp->getCode());
|
||||
VASSERT_EQ("Lines", 1, resp->getLineCount());
|
||||
@ -79,6 +81,7 @@ VMIME_TEST_SUITE_BEGIN(SMTPResponseTest)
|
||||
|
||||
void testMultiLineResponse()
|
||||
{
|
||||
vmime::shared_ptr <vmime::net::tracer> tracer;
|
||||
vmime::shared_ptr <testSocket> socket = vmime::make_shared <testSocket>();
|
||||
vmime::shared_ptr <vmime::net::timeoutHandler> toh =
|
||||
vmime::make_shared <testTimeoutHandler>();
|
||||
@ -92,7 +95,7 @@ VMIME_TEST_SUITE_BEGIN(SMTPResponseTest)
|
||||
vmime::net::smtp::SMTPResponse::state responseState;
|
||||
|
||||
vmime::shared_ptr <vmime::net::smtp::SMTPResponse> resp =
|
||||
vmime::net::smtp::SMTPResponse::readResponse(socket, toh, responseState);
|
||||
vmime::net::smtp::SMTPResponse::readResponse(tracer, socket, toh, responseState);
|
||||
|
||||
VASSERT_EQ("Code", 123, resp->getCode());
|
||||
VASSERT_EQ("Lines", 2, resp->getLineCount());
|
||||
@ -107,6 +110,7 @@ VMIME_TEST_SUITE_BEGIN(SMTPResponseTest)
|
||||
|
||||
void testMultiLineResponseDifferentCode()
|
||||
{
|
||||
vmime::shared_ptr <vmime::net::tracer> tracer;
|
||||
vmime::shared_ptr <testSocket> socket = vmime::make_shared <testSocket>();
|
||||
vmime::shared_ptr <vmime::net::timeoutHandler> toh =
|
||||
vmime::make_shared <testTimeoutHandler>();
|
||||
@ -120,7 +124,7 @@ VMIME_TEST_SUITE_BEGIN(SMTPResponseTest)
|
||||
vmime::net::smtp::SMTPResponse::state responseState;
|
||||
|
||||
vmime::shared_ptr <vmime::net::smtp::SMTPResponse> resp =
|
||||
vmime::net::smtp::SMTPResponse::readResponse(socket, toh, responseState);
|
||||
vmime::net::smtp::SMTPResponse::readResponse(tracer, socket, toh, responseState);
|
||||
|
||||
VASSERT_EQ("Code", 0, resp->getCode());
|
||||
VASSERT_EQ("Lines", 2, resp->getLineCount());
|
||||
@ -135,6 +139,7 @@ VMIME_TEST_SUITE_BEGIN(SMTPResponseTest)
|
||||
|
||||
void testIncompleteMultiLineResponse()
|
||||
{
|
||||
vmime::shared_ptr <vmime::net::tracer> tracer;
|
||||
vmime::shared_ptr <testSocket> socket = vmime::make_shared <testSocket>();
|
||||
vmime::shared_ptr <vmime::net::timeoutHandler> toh =
|
||||
vmime::make_shared <testTimeoutHandler>(1);
|
||||
@ -149,12 +154,13 @@ VMIME_TEST_SUITE_BEGIN(SMTPResponseTest)
|
||||
vmime::net::smtp::SMTPResponse::state responseState;
|
||||
|
||||
VASSERT_THROW("Incomplete response",
|
||||
vmime::net::smtp::SMTPResponse::readResponse(socket, toh, responseState),
|
||||
vmime::net::smtp::SMTPResponse::readResponse(tracer, socket, toh, responseState),
|
||||
vmime::exceptions::operation_timed_out);
|
||||
}
|
||||
|
||||
void testNoResponseText()
|
||||
{
|
||||
vmime::shared_ptr <vmime::net::tracer> tracer;
|
||||
vmime::shared_ptr <testSocket> socket = vmime::make_shared <testSocket>();
|
||||
vmime::shared_ptr <vmime::net::timeoutHandler> toh =
|
||||
vmime::make_shared <testTimeoutHandler>(1);
|
||||
@ -167,7 +173,7 @@ VMIME_TEST_SUITE_BEGIN(SMTPResponseTest)
|
||||
vmime::net::smtp::SMTPResponse::state responseState;
|
||||
|
||||
vmime::shared_ptr <vmime::net::smtp::SMTPResponse> resp =
|
||||
vmime::net::smtp::SMTPResponse::readResponse(socket, toh, responseState);
|
||||
vmime::net::smtp::SMTPResponse::readResponse(tracer, socket, toh, responseState);
|
||||
|
||||
VASSERT_EQ("Code", 250, resp->getCode());
|
||||
VASSERT_EQ("Lines", 1, resp->getLineCount());
|
||||
@ -176,6 +182,7 @@ VMIME_TEST_SUITE_BEGIN(SMTPResponseTest)
|
||||
|
||||
void testEnhancedStatusCode()
|
||||
{
|
||||
vmime::shared_ptr <vmime::net::tracer> tracer;
|
||||
vmime::shared_ptr <testSocket> socket = vmime::make_shared <testSocket>();
|
||||
vmime::shared_ptr <vmime::net::timeoutHandler> toh =
|
||||
vmime::make_shared <testTimeoutHandler>();
|
||||
@ -185,7 +192,7 @@ VMIME_TEST_SUITE_BEGIN(SMTPResponseTest)
|
||||
vmime::net::smtp::SMTPResponse::state responseState;
|
||||
|
||||
vmime::shared_ptr <vmime::net::smtp::SMTPResponse> resp =
|
||||
vmime::net::smtp::SMTPResponse::readResponse(socket, toh, responseState);
|
||||
vmime::net::smtp::SMTPResponse::readResponse(tracer, socket, toh, responseState);
|
||||
|
||||
VASSERT_EQ("Code", 250, resp->getCode());
|
||||
VASSERT_EQ("Lines", 1, resp->getLineCount());
|
||||
@ -197,6 +204,7 @@ VMIME_TEST_SUITE_BEGIN(SMTPResponseTest)
|
||||
|
||||
void testNoEnhancedStatusCode()
|
||||
{
|
||||
vmime::shared_ptr <vmime::net::tracer> tracer;
|
||||
vmime::shared_ptr <testSocket> socket = vmime::make_shared <testSocket>();
|
||||
vmime::shared_ptr <vmime::net::timeoutHandler> toh =
|
||||
vmime::make_shared <testTimeoutHandler>();
|
||||
@ -206,7 +214,7 @@ VMIME_TEST_SUITE_BEGIN(SMTPResponseTest)
|
||||
vmime::net::smtp::SMTPResponse::state responseState;
|
||||
|
||||
vmime::shared_ptr <vmime::net::smtp::SMTPResponse> resp =
|
||||
vmime::net::smtp::SMTPResponse::readResponse(socket, toh, responseState);
|
||||
vmime::net::smtp::SMTPResponse::readResponse(tracer, socket, toh, responseState);
|
||||
|
||||
VASSERT_EQ("Code", 354, resp->getCode());
|
||||
VASSERT_EQ("Lines", 1, resp->getLineCount());
|
||||
@ -218,6 +226,7 @@ VMIME_TEST_SUITE_BEGIN(SMTPResponseTest)
|
||||
|
||||
void testInvalidEnhancedStatusCode()
|
||||
{
|
||||
vmime::shared_ptr <vmime::net::tracer> tracer;
|
||||
vmime::shared_ptr <testSocket> socket = vmime::make_shared <testSocket>();
|
||||
vmime::shared_ptr <vmime::net::timeoutHandler> toh =
|
||||
vmime::make_shared <testTimeoutHandler>();
|
||||
@ -227,7 +236,7 @@ VMIME_TEST_SUITE_BEGIN(SMTPResponseTest)
|
||||
vmime::net::smtp::SMTPResponse::state responseState;
|
||||
|
||||
vmime::shared_ptr <vmime::net::smtp::SMTPResponse> resp =
|
||||
vmime::net::smtp::SMTPResponse::readResponse(socket, toh, responseState);
|
||||
vmime::net::smtp::SMTPResponse::readResponse(tracer, socket, toh, responseState);
|
||||
|
||||
VASSERT_EQ("Code", 250, resp->getCode());
|
||||
VASSERT_EQ("Lines", 1, resp->getLineCount());
|
||||
|
Loading…
Reference in New Issue
Block a user