vmime/src/relay.cpp
2004-12-15 20:28:09 +00:00

338 lines
6.8 KiB
C++

//
// VMime library (http://vmime.sourceforge.net)
// Copyright (C) 2002-2004 Vincent Richard <vincent@vincent-richard.net>
//
// 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 2 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., 675 Mass Ave, Cambridge, MA 02139, USA.
//
#include "relay.hpp"
#include "text.hpp"
#include "parserHelpers.hpp"
#include <sstream>
namespace vmime
{
relay::relay()
{
}
relay::relay(const relay& r)
: component()
{
copyFrom(r);
}
/*
RFC #2822:
received = "Received" ":" ; one per relay
["from" domain] ; sending host
["by" domain] ; receiving host
["via" atom] ; physical path
*("with" atom) ; link/mail protocol
["id" msg-id] ; receiver msg id
["for" addr-spec] ; initial form
*/
void relay::parse(const string& buffer, const string::size_type position,
const string::size_type end, string::size_type* newPosition)
{
const string::value_type* const pend = buffer.data() + end;
const string::value_type* const pstart = buffer.data() + position;
const string::value_type* p = pend - 1;
// Find the beginning of the date part
while (p >= pstart && *p != ';')
--p;
if (p >= pstart)
{
// Parse the date/time part
m_date.parse(buffer, position + (p - pstart) + 1, end);
// Parse the components
std::istringstream iss(string
(buffer.begin() + position, buffer.begin() + position + (p - pstart)));
string word;
std::vector <string> previous;
enum Parts
{
Part_None,
Part_From, // The "from" part
Part_By, // The "by" part
Part_Via, // The "via" part
Part_With, // One "with" part
Part_Id, // The "id" part
Part_For, // The "for" part
Part_End
};
Parts part = Part_None;
bool cont = true;
bool inComment = false;
while (cont)
{
Parts newPart = Part_None;
if (cont = (iss >> word))
{
// A little hack for handling comments
if (inComment)
{
string::size_type par = word.find(')');
if (par != string::npos)
{
previous.push_back(string(word.begin(), word.begin() + par + 1));
word.erase(word.begin(), word.begin() + par + 1);
inComment = false;
}
}
bool keyword = false;
if (!inComment)
{
if (stringUtils::isStringEqualNoCase(word, "from", 4))
{
newPart = Part_From;
keyword = true;
}
else if (stringUtils::isStringEqualNoCase(word, "by", 2))
{
newPart = Part_By;
keyword = true;
}
else if (stringUtils::isStringEqualNoCase(word, "via", 2))
{
newPart = Part_Via;
keyword = true;
}
else if (stringUtils::isStringEqualNoCase(word, "with", 2))
{
newPart = Part_With;
keyword = true;
}
else if (stringUtils::isStringEqualNoCase(word, "id", 2))
{
newPart = Part_Id;
keyword = true;
}
else if (stringUtils::isStringEqualNoCase(word, "for", 2))
{
newPart = Part_For;
keyword = true;
}
}
if (!keyword)
{
if (word.find('(') != string::npos)
inComment = true;
previous.push_back(word);
}
}
if (!cont || newPart != Part_None)
{
if (part != Part_None)
{
std::ostringstream value;
for (std::vector <string>::const_iterator
it = previous.begin() ; it != previous.end() ; ++it)
{
if (it != previous.begin()) value << " ";
value << *it;
}
switch (part)
{
case Part_From: m_from = value.str(); break;
case Part_By: m_by = value.str(); break;
case Part_Via: m_via = value.str(); break;
case Part_With: m_with.push_back(value.str()); break;
case Part_Id: m_id = value.str(); break;
case Part_For: m_for = value.str(); break;
default: break; // Should never happen...
}
}
previous.clear();
part = newPart;
}
}
}
setParsedBounds(position, end);
if (newPosition)
*newPosition = end;
}
void relay::generate(utility::outputStream& os, const string::size_type maxLineLength,
const string::size_type curLinePos, string::size_type* newLinePos) const
{
std::ostringstream oss;
int count = 0;
if (m_from.length()) oss << (count++ > 0 ? " " : "") << "from " << m_from;
if (m_by.length()) oss << (count++ > 0 ? " " : "") << "by " << m_by;
if (m_via.length()) oss << (count++ > 0 ? " " : "") << "via " << m_via;
for (std::vector <string>::const_iterator
it = m_with.begin() ; it != m_with.end() ; ++it)
{
oss << (count++ > 0 ? " " : "") << "with " << *it;
}
if (m_id.length()) oss << (count++ > 0 ? " " : "") << "id " << m_id;
if (m_for.length()) oss << (count++ > 0 ? " " : "") << "for " << m_for;
oss << "; " << m_date.generate();
text(oss.str()).encodeAndFold(os, maxLineLength,
curLinePos, newLinePos, text::FORCE_NO_ENCODING);
}
void relay::copyFrom(const component& other)
{
const relay& r = dynamic_cast <const relay&>(other);
m_from = r.m_from;
m_via = r.m_via;
m_by = r.m_by;
m_id = r.m_id;
m_for = r.m_for;
m_with.resize(r.m_with.size());
std::copy(r.m_with.begin(), r.m_with.end(), m_with.begin());
m_date = r.m_date;
}
relay& relay::operator=(const relay& other)
{
copyFrom(other);
return (*this);
}
relay* relay::clone() const
{
return new relay(*this);
}
const string& relay::getFrom() const
{
return (m_from);
}
void relay::setFrom(const string& from)
{
m_from = from;
}
const string& relay::getVia() const
{
return (m_via);
}
void relay::setVia(const string& via)
{
m_via = via;
}
const string& relay::getBy() const
{
return (m_by);
}
void relay::setBy(const string& by)
{
m_by = by;
}
const string& relay::getId() const
{
return (m_id);
}
void relay::setId(const string& id)
{
m_id = id;
}
const string& relay::getFor() const
{
return (m_for);
}
void relay::setFor(const string& for_)
{
m_for = for_;
}
const datetime& relay::getDate() const
{
return (m_date);
}
void relay::setDate(const datetime& date)
{
m_date = date;
}
const std::vector <string>& relay::getWithList() const
{
return (m_with);
}
std::vector <string>& relay::getWithList()
{
return (m_with);
}
} // vmime