diff options
Diffstat (limited to 'vmime-master/src/vmime/net/smtp/SMTPResponse.cpp')
-rw-r--r-- | vmime-master/src/vmime/net/smtp/SMTPResponse.cpp | 366 |
1 files changed, 366 insertions, 0 deletions
diff --git a/vmime-master/src/vmime/net/smtp/SMTPResponse.cpp b/vmime-master/src/vmime/net/smtp/SMTPResponse.cpp new file mode 100644 index 0000000..2234705 --- /dev/null +++ b/vmime-master/src/vmime/net/smtp/SMTPResponse.cpp @@ -0,0 +1,366 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002 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 && VMIME_HAVE_MESSAGING_PROTO_SMTP + + +#include "vmime/net/smtp/SMTPResponse.hpp" + +#include "vmime/platform.hpp" +#include "vmime/utility/stringUtils.hpp" + +#include "vmime/net/socket.hpp" +#include "vmime/net/timeoutHandler.hpp" +#include "vmime/net/tracer.hpp" + +#include <cctype> + + +namespace vmime { +namespace net { +namespace smtp { + + +SMTPResponse::SMTPResponse( + const shared_ptr <tracer>& tr, + const shared_ptr <socket>& sok, + const shared_ptr <timeoutHandler>& toh, + const state& st +) + : m_socket(sok), + m_timeoutHandler(toh), + m_tracer(tr), + m_responseBuffer(st.responseBuffer), + m_responseContinues(false) { + +} + + +SMTPResponse::SMTPResponse(const SMTPResponse&) + : vmime::object() { + + // Not used +} + + +int SMTPResponse::getCode() const { + + const int firstCode = m_lines[0].getCode(); + + for (unsigned int i = 1 ; i < m_lines.size() ; ++i) { + + // All response codes returned must be equal + // or else this in an error... + if (m_lines[i].getCode() != firstCode) { + return 0; + } + } + + return firstCode; +} + + +const SMTPResponse::enhancedStatusCode SMTPResponse::getEnhancedCode() const { + + return m_lines[m_lines.size() - 1].getEnhancedCode(); +} + + +const string SMTPResponse::getText() const { + + string text = m_lines[0].getText(); + + for (unsigned int i = 1 ; i < m_lines.size() ; ++i) { + + text += '\n'; + text += m_lines[i].getText(); + } + + return text; +} + + +// static +shared_ptr <SMTPResponse> SMTPResponse::readResponse( + const shared_ptr <tracer>& tr, + const shared_ptr <socket>& sok, + const shared_ptr <timeoutHandler>& toh, + const state& st +) { + + shared_ptr <SMTPResponse> resp = + shared_ptr <SMTPResponse>(new SMTPResponse(tr, sok, toh, st)); + + resp->readResponse(); + + return resp; +} + + +void SMTPResponse::readResponse() { + + responseLine line = getNextResponse(); + m_lines.push_back(line); + + while (m_responseContinues) { + line = getNextResponse(); + m_lines.push_back(line); + } +} + + +const string SMTPResponse::readResponseLine() { + + string currentBuffer = m_responseBuffer; + + if (m_timeoutHandler) { + m_timeoutHandler->resetTimeOut(); + } + + while (true) { + + // Get a line from the response buffer + const size_t lineEnd = currentBuffer.find_first_of('\n'); + + if (lineEnd != string::npos) { + + size_t actualLineEnd = lineEnd; + + if (actualLineEnd != 0 && currentBuffer[actualLineEnd - 1] == '\r') { // CRLF case + actualLineEnd--; + } + + const string line(currentBuffer.begin(), currentBuffer.begin() + actualLineEnd); + + currentBuffer.erase(currentBuffer.begin(), currentBuffer.begin() + lineEnd + 1); + m_responseBuffer = currentBuffer; + + if (m_tracer) { + m_tracer->traceReceive(line); + } + + return line; + } + + // Check whether the time-out delay is elapsed + if (m_timeoutHandler && m_timeoutHandler->isTimeOut()) { + + if (!m_timeoutHandler->handleTimeOut()) { + throw exceptions::operation_timed_out(); + } + + m_timeoutHandler->resetTimeOut(); + } + + // Receive data from the socket + string receiveBuffer; + m_socket->receive(receiveBuffer); + + if (receiveBuffer.empty()) { // buffer is empty + m_socket->waitForRead(); + continue; + } + + currentBuffer += receiveBuffer; + } +} + + +const SMTPResponse::responseLine SMTPResponse::getNextResponse() { + + string line = readResponseLine(); + + const int code = extractResponseCode(line); + string text; + + m_responseContinues = (line.length() >= 4 && line[3] == '-'); + + if (line.length() > 4) { + text = utility::stringUtils::trim(line.substr(4)); + } else { + text = ""; + } + + return responseLine(code, text, extractEnhancedCode(text)); +} + + +// static +int SMTPResponse::extractResponseCode(const string& response) { + + int code = 0; + + if (response.length() >= 3) { + + code = (response[0] - '0') * 100 + + (response[1] - '0') * 10 + + (response[2] - '0'); + } + + return code; +} + + +// static +const SMTPResponse::enhancedStatusCode SMTPResponse::extractEnhancedCode(const string& responseText) { + + enhancedStatusCode enhCode; + + std::istringstream iss(responseText); + iss.imbue(std::locale::classic()); + + if (std::isdigit(iss.peek())) { + + iss >> enhCode.klass; + + if (iss.get() == '.' && std::isdigit(iss.peek())) { + + iss >> enhCode.subject; + + if (iss.get() == '.' && std::isdigit(iss.peek())) { + + iss >> enhCode.detail; + return enhCode; + } + } + } + + return enhancedStatusCode(); // no enhanced code found +} + + +const SMTPResponse::responseLine SMTPResponse::getLineAt(const size_t pos) const { + + return m_lines[pos]; +} + + +size_t SMTPResponse::getLineCount() const { + + return m_lines.size(); +} + + +const SMTPResponse::responseLine SMTPResponse::getLastLine() const { + + return m_lines[m_lines.size() - 1]; +} + + +const SMTPResponse::state SMTPResponse::getCurrentState() const { + + state st; + st.responseBuffer = m_responseBuffer; + + return st; +} + + + +// SMTPResponse::responseLine + +SMTPResponse::responseLine::responseLine( + const int code, + const string& text, + const enhancedStatusCode& enhCode +) + : m_code(code), + m_text(text), + m_enhCode(enhCode) { + +} + + +void SMTPResponse::responseLine::setCode(const int code) { + + m_code = code; +} + + +int SMTPResponse::responseLine::getCode() const { + + return m_code; +} + + +void SMTPResponse::responseLine::setEnhancedCode(const enhancedStatusCode& enhCode) { + + m_enhCode = enhCode; +} + + +const SMTPResponse::enhancedStatusCode SMTPResponse::responseLine::getEnhancedCode() const { + + return m_enhCode; +} + + +void SMTPResponse::responseLine::setText(const string& text) { + + m_text = text; +} + + +const string SMTPResponse::responseLine::getText() const { + + return m_text; +} + + + +// SMTPResponse::enhancedStatusCode + + +SMTPResponse::enhancedStatusCode::enhancedStatusCode() + : klass(0), + subject(0), + detail(0) { + +} + + +SMTPResponse::enhancedStatusCode::enhancedStatusCode(const enhancedStatusCode& enhCode) + : klass(enhCode.klass), + subject(enhCode.subject), + detail(enhCode.detail) { + +} + + +std::ostream& operator<<(std::ostream& os, const SMTPResponse::enhancedStatusCode& code) { + + os << code.klass << '.' << code.subject << '.' << code.detail; + return os; +} + + +} // smtp +} // net +} // vmime + + +#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_SMTP + |