// MailHeaders.cpp // Copyright (C) 2008 ARM Research Labs, LLC. // See www.armresearch.com for the copyright terms. // // This file contains the functions to extract the mail header and // body from the string returned by SNFMilterEngine::XHeaders(). #include #include #include "MailHeaders.hpp" using namespace std; const string DefaultSMTPENDL = "\r\n"; ///< Default SMTP endline. const string DefaultLibmilterENDL = "\n "; ///< Default libmilter endline. const string DefaultPrefix = "X-"; ///< Default start of header line. MailHeaders::MailHeaders() : SMTPENDL(DefaultSMTPENDL), LibMilterENDL(DefaultLibmilterENDL) { } MailHeaders::~MailHeaders() { } void MailHeaders::loadHeaders(const string &HeaderBuffer) { Buffer = HeaderBuffer; } bool MailHeaders::getHeaderName(string *HeaderName) { if (Buffer.empty()) { // No header if the buffer is empty. return false; } string::size_type endIndex = Buffer.find(SMTPENDL); if (string::npos == endIndex) { // No SMPENDL. ostringstream Temp; Temp << "Invalid header line (no SMTP end-of-line): '" << Buffer << "'."; throw std::invalid_argument(Temp.str()); } string Line(Buffer, 0, endIndex); // First line of the header. string::size_type colonIndex = Line.find(":"); if (string::npos == colonIndex) { // No ":". ostringstream Temp; Temp << "Invalid header line (no ':'): '" << Buffer << "'."; throw std::invalid_argument(Temp.str()); } HeaderName->assign(Line, 0, colonIndex); if (0 == HeaderName->size()) { // Null header name. ostringstream Temp; Temp << "Invalid header line (no name): '" << Buffer << "'."; throw std::invalid_argument(Temp.str()); } Buffer.erase(0, colonIndex + 1); // Erase the header name and ":". return true; } bool MailHeaders::getHeaderLine(string *HeaderLine) { if (Buffer.empty()) { // No line if the buffer is empty. return false; } string::size_type EndIndex = Buffer.find(SMTPENDL); if (string::npos == EndIndex) { // No SMPENDL. ostringstream Temp; Temp << "Invalid header line (no SMTP end-of-line): '" << Buffer << "'."; throw std::invalid_argument(Temp.str()); } HeaderLine->assign(Buffer, 0, EndIndex); // Tentative line of the body. string::size_type XIndex = HeaderLine->find("X-"); if (XIndex == 0) { // Does it begin with "X-"? return false; // Yes; it's not the body line. } Buffer.erase(0, EndIndex + SMTPENDL.size()); // Erase line and SMTPENDL. return true; } bool MailHeaders::getNameBody(string *HeaderName, string *FormattedHeaderBody) { if (!getHeaderName(HeaderName)) { // Get the header. return false; // No more headers. } FormattedHeaderBody->clear(); string HeaderLine; // One line of the body. bool FirstTime = true; while (getHeaderLine(&HeaderLine)) { // While this header has lines... if (FirstTime) { *FormattedHeaderBody = HeaderLine; FirstTime = false; } else { *FormattedHeaderBody += LibMilterENDL; *FormattedHeaderBody += HeaderLine; } } return true; }