aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--examples/example6.cpp259
-rw-r--r--examples/example6_authenticator.hpp106
-rw-r--r--examples/example6_certificateVerifier.hpp62
-rw-r--r--examples/example6_timeoutHandler.hpp48
-rw-r--r--examples/example6_tracer.hpp53
-rw-r--r--src/vmime/net/imap/IMAPCommand.cpp2
-rw-r--r--src/vmime/net/imap/IMAPCommand.hpp2
-rw-r--r--src/vmime/net/imap/IMAPConnection.cpp26
-rw-r--r--src/vmime/net/imap/IMAPConnection.hpp5
-rw-r--r--src/vmime/net/imap/IMAPFolder.cpp3
-rw-r--r--src/vmime/net/imap/IMAPParser.hpp21
-rw-r--r--src/vmime/net/pop3/POP3Command.cpp33
-rw-r--r--src/vmime/net/pop3/POP3Command.hpp13
-rw-r--r--src/vmime/net/pop3/POP3Connection.cpp19
-rw-r--r--src/vmime/net/pop3/POP3Connection.hpp3
-rw-r--r--src/vmime/net/pop3/POP3Message.cpp2
-rw-r--r--src/vmime/net/pop3/POP3Response.cpp40
-rw-r--r--src/vmime/net/pop3/POP3Response.hpp6
-rw-r--r--src/vmime/net/service.cpp12
-rw-r--r--src/vmime/net/service.hpp8
-rw-r--r--src/vmime/net/smtp/SMTPChunkingOutputStreamAdapter.cpp6
-rw-r--r--src/vmime/net/smtp/SMTPCommand.cpp23
-rw-r--r--src/vmime/net/smtp/SMTPCommand.hpp16
-rw-r--r--src/vmime/net/smtp/SMTPCommandSet.cpp23
-rw-r--r--src/vmime/net/smtp/SMTPCommandSet.hpp3
-rw-r--r--src/vmime/net/smtp/SMTPConnection.cpp23
-rw-r--r--src/vmime/net/smtp/SMTPConnection.hpp3
-rw-r--r--src/vmime/net/smtp/SMTPResponse.cpp16
-rw-r--r--src/vmime/net/smtp/SMTPResponse.hpp9
-rw-r--r--src/vmime/net/smtp/SMTPTransport.cpp14
-rw-r--r--src/vmime/net/tracer.cpp72
-rw-r--r--src/vmime/net/tracer.hpp109
-rw-r--r--tests/net/smtp/SMTPCommandSetTest.cpp26
-rw-r--r--tests/net/smtp/SMTPCommandTest.cpp4
-rw-r--r--tests/net/smtp/SMTPResponseTest.cpp27
35 files changed, 810 insertions, 287 deletions
diff --git a/examples/example6.cpp b/examples/example6.cpp
index 95019c03..5d8c7e64 100644
--- a/examples/example6.cpp
+++ b/examples/example6.cpp
@@ -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. [email protected]): ";
@@ -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)
{
diff --git a/examples/example6_authenticator.hpp b/examples/example6_authenticator.hpp
new file mode 100644
index 00000000..b46f8ebd
--- /dev/null
+++ b/examples/example6_authenticator.hpp
@@ -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
+
diff --git a/examples/example6_certificateVerifier.hpp b/examples/example6_certificateVerifier.hpp
new file mode 100644
index 00000000..65f0f4ad
--- /dev/null
+++ b/examples/example6_certificateVerifier.hpp
@@ -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
+
diff --git a/examples/example6_timeoutHandler.hpp b/examples/example6_timeoutHandler.hpp
new file mode 100644
index 00000000..7c2eb0e2
--- /dev/null
+++ b/examples/example6_timeoutHandler.hpp
@@ -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>();
+ }
+};
+
diff --git a/examples/example6_tracer.hpp b/examples/example6_tracer.hpp
new file mode 100644
index 00000000..19d0f040
--- /dev/null
+++ b/examples/example6_tracer.hpp
@@ -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;
+};
+
diff --git a/src/vmime/net/imap/IMAPCommand.cpp b/src/vmime/net/imap/IMAPCommand.cpp
index 19c3b723..b1840d8d 100644
--- a/src/vmime/net/imap/IMAPCommand.cpp
+++ b/src/vmime/net/imap/IMAPCommand.cpp
@@ -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());
}
diff --git a/src/vmime/net/imap/IMAPCommand.hpp b/src/vmime/net/imap/IMAPCommand.hpp
index c0a0d9b1..6003c227 100644
--- a/src/vmime/net/imap/IMAPCommand.hpp
+++ b/src/vmime/net/imap/IMAPCommand.hpp
@@ -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;
diff --git a/src/vmime/net/imap/IMAPConnection.cpp b/src/vmime/net/imap/IMAPConnection.cpp
index 57f2ff5e..28a71662 100644
--- a/src/vmime/net/imap/IMAPConnection.cpp
+++ b/src/vmime/net/imap/IMAPConnection.cpp
@@ -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;
diff --git a/src/vmime/net/imap/IMAPConnection.hpp b/src/vmime/net/imap/IMAPConnection.hpp
index da1b9ba4..b863ce33 100644
--- a/src/vmime/net/imap/IMAPConnection.hpp
+++ b/src/vmime/net/imap/IMAPConnection.hpp
@@ -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();
diff --git a/src/vmime/net/imap/IMAPFolder.cpp b/src/vmime/net/imap/IMAPFolder.cpp
index e602ea6e..00fee93c 100644
--- a/src/vmime/net/imap/IMAPFolder.cpp
+++ b/src/vmime/net/imap/IMAPFolder.cpp
@@ -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);
diff --git a/src/vmime/net/imap/IMAPParser.hpp b/src/vmime/net/imap/IMAPParser.hpp
index ba0ea195..d38ac14a 100644
--- a/src/vmime/net/imap/IMAPParser.hpp
+++ b/src/vmime/net/imap/IMAPParser.hpp
@@ -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);
}
diff --git a/src/vmime/net/pop3/POP3Command.cpp b/src/vmime/net/pop3/POP3Command.cpp
index 3c544fc0..9dfaf17a 100644
--- a/src/vmime/net/pop3/POP3Command.cpp
+++ b/src/vmime/net/pop3/POP3Command.cpp
@@ -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);
}
diff --git a/src/vmime/net/pop3/POP3Command.hpp b/src/vmime/net/pop3/POP3Command.hpp
index e34e4e2b..45aff661 100644
--- a/src/vmime/net/pop3/POP3Command.hpp
+++ b/src/vmime/net/pop3/POP3Command.hpp
@@ -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;
};
diff --git a/src/vmime/net/pop3/POP3Connection.cpp b/src/vmime/net/pop3/POP3Connection.cpp
index 45c668f5..0fd7e7ee 100644
--- a/src/vmime/net/pop3/POP3Connection.cpp
+++ b/src/vmime/net/pop3/POP3Connection.cpp
@@ -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;
diff --git a/src/vmime/net/pop3/POP3Connection.hpp b/src/vmime/net/pop3/POP3Connection.hpp
index 3622f745..f40f9562 100644
--- a/src/vmime/net/pop3/POP3Connection.hpp
+++ b/src/vmime/net/pop3/POP3Connection.hpp
@@ -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;
diff --git a/src/vmime/net/pop3/POP3Message.cpp b/src/vmime/net/pop3/POP3Message.cpp
index ff1aa88f..0b7e6d37 100644
--- a/src/vmime/net/pop3/POP3Message.cpp
+++ b/src/vmime/net/pop3/POP3Message.cpp
@@ -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)
{
diff --git a/src/vmime/net/pop3/POP3Response.cpp b/src/vmime/net/pop3/POP3Response.cpp
index bdbfb23c..de3c2cf3 100644
--- a/src/vmime/net/pop3/POP3Response.cpp
+++ b/src/vmime/net/pop3/POP3Response.cpp
@@ -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;
}
diff --git a/src/vmime/net/pop3/POP3Response.hpp b/src/vmime/net/pop3/POP3Response.hpp
index 20477b5e..d85b5405 100644
--- a/src/vmime/net/pop3/POP3Response.hpp
+++ b/src/vmime/net/pop3/POP3Response.hpp
@@ -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;
diff --git a/src/vmime/net/service.cpp b/src/vmime/net/service.cpp
index 482b141c..3cf94d5e 100644
--- a/src/vmime/net/service.cpp
+++ b/src/vmime/net/service.cpp
@@ -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;
diff --git a/src/vmime/net/service.hpp b/src/vmime/net/service.hpp
index 59352dea..b00d15ac 100644
--- a/src/vmime/net/service.hpp
+++ b/src/vmime/net/service.hpp
@@ -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;
};
diff --git a/src/vmime/net/smtp/SMTPChunkingOutputStreamAdapter.cpp b/src/vmime/net/smtp/SMTPChunkingOutputStreamAdapter.cpp
index 35ff4e0d..15e24cf1 100644
--- a/src/vmime/net/smtp/SMTPChunkingOutputStreamAdapter.cpp
+++ b/src/vmime/net/smtp/SMTPChunkingOutputStreamAdapter.cpp
@@ -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);
}
diff --git a/src/vmime/net/smtp/SMTPCommand.cpp b/src/vmime/net/smtp/SMTPCommand.cpp
index 2120caf5..27c8ec1b 100644
--- a/src/vmime/net/smtp/SMTPCommand.cpp
+++ b/src/vmime/net/smtp/SMTPCommand.cpp
@@ -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);
}
diff --git a/src/vmime/net/smtp/SMTPCommand.hpp b/src/vmime/net/smtp/SMTPCommand.hpp
index a5b8cca5..7c00d156 100644
--- a/src/vmime/net/smtp/SMTPCommand.hpp
+++ b/src/vmime/net/smtp/SMTPCommand.hpp
@@ -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;
};
diff --git a/src/vmime/net/smtp/SMTPCommandSet.cpp b/src/vmime/net/smtp/SMTPCommandSet.cpp
index 3e03427c..85f58fed 100644
--- a/src/vmime/net/smtp/SMTPCommandSet.cpp
+++ b/src/vmime/net/smtp/SMTPCommandSet.cpp
@@ -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);
diff --git a/src/vmime/net/smtp/SMTPCommandSet.hpp b/src/vmime/net/smtp/SMTPCommandSet.hpp
index 8e744c2b..83c7fe46 100644
--- a/src/vmime/net/smtp/SMTPCommandSet.hpp
+++ b/src/vmime/net/smtp/SMTPCommandSet.hpp
@@ -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:
diff --git a/src/vmime/net/smtp/SMTPConnection.cpp b/src/vmime/net/smtp/SMTPConnection.cpp
index 4985b563..99a8e8f5 100644
--- a/src/vmime/net/smtp/SMTPConnection.cpp
+++ b/src/vmime/net/smtp/SMTPConnection.cpp
@@ -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;
diff --git a/src/vmime/net/smtp/SMTPConnection.hpp b/src/vmime/net/smtp/SMTPConnection.hpp
index cc59ef34..c7614920 100644
--- a/src/vmime/net/smtp/SMTPConnection.hpp
+++ b/src/vmime/net/smtp/SMTPConnection.hpp
@@ -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;
diff --git a/src/vmime/net/smtp/SMTPResponse.cpp b/src/vmime/net/smtp/SMTPResponse.cpp
index 3d8bf15c..75dbbf6b 100644
--- a/src/vmime/net/smtp/SMTPResponse.cpp
+++ b/src/vmime/net/smtp/SMTPResponse.cpp
@@ -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;
}
diff --git a/src/vmime/net/smtp/SMTPResponse.hpp b/src/vmime/net/smtp/SMTPResponse.hpp
index 000448ac..4d88b6b5 100644
--- a/src/vmime/net/smtp/SMTPResponse.hpp
+++ b/src/vmime/net/smtp/SMTPResponse.hpp
@@ -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;
diff --git a/src/vmime/net/smtp/SMTPTransport.cpp b/src/vmime/net/smtp/SMTPTransport.cpp
index 56adfa21..ed775442 100644
--- a/src/vmime/net/smtp/SMTPTransport.cpp
+++ b/src/vmime/net/smtp/SMTPTransport.cpp
@@ -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)
diff --git a/src/vmime/net/tracer.cpp b/src/vmime/net/tracer.cpp
new file mode 100644
index 00000000..b3610cdd
--- /dev/null
+++ b/src/vmime/net/tracer.cpp
@@ -0,0 +1,72 @@
+//
+// VMime library (http://www.vmime.org)
+// Copyright (C) 2002-2014 Vincent Richard <[email protected]>
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License as
+// published by the Free Software Foundation; either version 3 of
+// the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+//
+// Linking this library statically or dynamically with other modules is making
+// a combined work based on this library. Thus, the terms and conditions of
+// the GNU General Public License cover the whole combination.
+//
+
+#include "vmime/config.hpp"
+
+
+#if VMIME_HAVE_MESSAGING_FEATURES
+
+
+#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
diff --git a/src/vmime/net/tracer.hpp b/src/vmime/net/tracer.hpp
new file mode 100644
index 00000000..e30c823c
--- /dev/null
+++ b/src/vmime/net/tracer.hpp
@@ -0,0 +1,109 @@
+//
+// VMime library (http://www.vmime.org)
+// Copyright (C) 2002-2014 Vincent Richard <[email protected]>
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License as
+// published by the Free Software Foundation; either version 3 of
+// the License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+//
+// Linking this library statically or dynamically with other modules is making
+// a combined work based on this library. Thus, the terms and conditions of
+// the GNU General Public License cover the whole combination.
+//
+
+#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
diff --git a/tests/net/smtp/SMTPCommandSetTest.cpp b/tests/net/smtp/SMTPCommandSetTest.cpp
index af250078..f419eb40 100644
--- a/tests/net/smtp/SMTPCommandSetTest.cpp
+++ b/tests/net/smtp/SMTPCommandSetTest.cpp
@@ -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());
}
diff --git a/tests/net/smtp/SMTPCommandTest.cpp b/tests/net/smtp/SMTPCommandTest.cpp
index 9480948c..9b3daa73 100644
--- a/tests/net/smtp/SMTPCommandTest.cpp
+++ b/tests/net/smtp/SMTPCommandTest.cpp
@@ -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);
diff --git a/tests/net/smtp/SMTPResponseTest.cpp b/tests/net/smtp/SMTPResponseTest.cpp
index 352f46c2..d47e31e9 100644
--- a/tests/net/smtp/SMTPResponseTest.cpp
+++ b/tests/net/smtp/SMTPResponseTest.cpp
@@ -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());