// // VMime library (http://www.vmime.org) // Copyright (C) 2002-2005 Vincent Richard // // 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 "vmime/header.hpp" #include "vmime/parserHelpers.hpp" namespace vmime { header::header() { } header::~header() { removeAllFields(); } /* RFC #822: 3.2. HEADER FIELD DEFINITIONS field = field-name ":" [ field-body ] CRLF field-name = 1* field-body = field-body-contents [CRLF LWSP-char field-body] field-body-contents = */ void header::parse(const string& buffer, const string::size_type position, const string::size_type end, string::size_type* newPosition) { string::size_type pos = position; removeAllFields(); while (pos < end) { headerField* field = headerField::parseNext(buffer, pos, end, &pos); if (field == NULL) break; m_fields.push_back(field); } setParsedBounds(position, pos); if (newPosition) *newPosition = pos; } void header::generate(utility::outputStream& os, const string::size_type maxLineLength, const string::size_type /* curLinePos */, string::size_type* newLinePos) const { // Generate the fields for (std::vector ::const_iterator it = m_fields.begin() ; it != m_fields.end() ; ++it) { (*it)->generate(os, maxLineLength); os << CRLF; } if (newLinePos) *newLinePos = 0; } header* header::clone() const { header* hdr = new header(); try { hdr->m_fields.reserve(m_fields.size()); for (std::vector ::const_iterator it = m_fields.begin() ; it != m_fields.end() ; ++it) { hdr->m_fields.push_back((*it)->clone()); } } catch (std::exception&) { free_container(hdr->m_fields); delete (hdr); throw; } return (hdr); } void header::copyFrom(const component& other) { const header& h = dynamic_cast (other); std::vector fields; try { fields.reserve(h.m_fields.size()); for (std::vector ::const_iterator it = h.m_fields.begin() ; it != h.m_fields.end() ; ++it) { fields.push_back((*it)->clone()); } free_container(m_fields); m_fields.resize(fields.size()); std::copy(fields.begin(), fields.end(), m_fields.begin()); } catch (std::exception&) { free_container(fields); throw; } } header& header::operator=(const header& other) { copyFrom(other); return (*this); } const bool header::hasField(const string& fieldName) const { const string name = utility::stringUtils::toLower(fieldName); std::vector ::const_iterator pos = m_fields.begin(); const std::vector ::const_iterator end = m_fields.end(); for ( ; pos != end && utility::stringUtils::toLower((*pos)->getName()) != name ; ++pos); return (pos != end); } headerField* header::findField(const string& fieldName) const { const string name = utility::stringUtils::toLower(fieldName); // Find the first field that matches the specified name std::vector ::const_iterator pos = m_fields.begin(); const std::vector ::const_iterator end = m_fields.end(); for ( ; pos != end && utility::stringUtils::toLower((*pos)->getName()) != name ; ++pos); // No field with this name can be found if (pos == end) { throw exceptions::no_such_field(); } // Else, return a reference to the existing field else { return (*pos); } } std::vector header::findAllFields(const string& fieldName) { const string name = utility::stringUtils::toLower(fieldName); std::vector result; std::vector ::const_iterator pos = m_fields.begin(); const std::vector ::const_iterator end = m_fields.end(); for ( ; pos != end ; ++pos) { // Add the header if it matches the specified type if (utility::stringUtils::toLower((*pos)->getName()) == name) { result.push_back(*pos); } } return result; } headerField* header::getField(const string& fieldName) { const string name = utility::stringUtils::toLower(fieldName); // Find the first field that matches the specified name std::vector ::const_iterator pos = m_fields.begin(); const std::vector ::const_iterator end = m_fields.end(); for ( ; pos != end && utility::stringUtils::toLower((*pos)->getName()) != name ; ++pos); // If no field with this name can be found, create a new one if (pos == end) { headerField* field = headerFieldFactory::getInstance()->create(fieldName); try { appendField(field); } catch (std::exception&) { delete (field); throw; } // Return a reference to the new field return (field); } // Else, return a reference to the existing field else { return (*pos); } } void header::appendField(headerField* field) { m_fields.push_back(field); } void header::insertFieldBefore(headerField* beforeField, headerField* field) { const std::vector ::iterator it = std::find (m_fields.begin(), m_fields.end(), beforeField); if (it == m_fields.end()) throw exceptions::no_such_field(); m_fields.insert(it, field); } void header::insertFieldBefore(const int pos, headerField* field) { m_fields.insert(m_fields.begin() + pos, field); } void header::insertFieldAfter(headerField* afterField, headerField* field) { const std::vector ::iterator it = std::find (m_fields.begin(), m_fields.end(), afterField); if (it == m_fields.end()) throw exceptions::no_such_field(); m_fields.insert(it + 1, field); } void header::insertFieldAfter(const int pos, headerField* field) { m_fields.insert(m_fields.begin() + pos + 1, field); } void header::removeField(headerField* field) { const std::vector ::iterator it = std::find (m_fields.begin(), m_fields.end(), field); if (it == m_fields.end()) throw exceptions::no_such_field(); delete (*it); m_fields.erase(it); } void header::removeField(const int pos) { const std::vector ::iterator it = m_fields.begin() + pos; delete (*it); m_fields.erase(it); } void header::removeAllFields() { free_container(m_fields); } const int header::getFieldCount() const { return (m_fields.size()); } const bool header::isEmpty() const { return (m_fields.empty()); } headerField* header::getFieldAt(const int pos) { return (m_fields[pos]); } const headerField* header::getFieldAt(const int pos) const { return (m_fields[pos]); } const std::vector header::getFieldList() const { std::vector list; list.reserve(m_fields.size()); for (std::vector ::const_iterator it = m_fields.begin() ; it != m_fields.end() ; ++it) { list.push_back(*it); } return (list); } const std::vector header::getFieldList() { return (m_fields); } const std::vector header::getChildComponents() const { std::vector list; copy_vector(m_fields, list); return (list); } } // vmime