diff options
author | Vincent Richard <[email protected]> | 2004-10-05 10:28:21 +0000 |
---|---|---|
committer | Vincent Richard <[email protected]> | 2004-10-05 10:28:21 +0000 |
commit | a3229a051381e8f6b6df0fd423186166d20c898f (patch) | |
tree | 29dab66e608651e50a9b6f4bf9ce28f2ee897c87 /src/parameterizedHeaderField.cpp | |
download | vmime-a3229a051381e8f6b6df0fd423186166d20c898f.tar.gz vmime-a3229a051381e8f6b6df0fd423186166d20c898f.zip |
Initial import.
Diffstat (limited to 'src/parameterizedHeaderField.cpp')
-rw-r--r-- | src/parameterizedHeaderField.cpp | 335 |
1 files changed, 335 insertions, 0 deletions
diff --git a/src/parameterizedHeaderField.cpp b/src/parameterizedHeaderField.cpp new file mode 100644 index 00000000..ee00cd32 --- /dev/null +++ b/src/parameterizedHeaderField.cpp @@ -0,0 +1,335 @@ +// +// VMime library (http://vmime.sourceforge.net) +// Copyright (C) 2002-2004 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 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 "parameterizedHeaderField.hpp" +#include "parameterFactory.hpp" +#include "text.hpp" +#include "parserHelpers.hpp" + + +namespace vmime +{ + + +parameterizedHeaderField::parameterizedHeaderField() +{ +} + + +/* + This class handles field contents of the following form: + Field: VALUE; PARAM1="VALUE1"; PARAM2="VALUE2"... + + eg. RFC-1521 + + content := "Content-Type" ":" type "/" subtype *(";" parameter) + + parameter := attribute "=" value + + attribute := token ; case-insensitive + + value := token / quoted-string + + token := 1*<any (ASCII) CHAR except SPACE, CTLs, or tspecials> + + tspecials := "(" / ")" / "<" / ">" / "@" + / "," / ";" / ":" / "\" / <"> + / "/" / "[" / "]" / "?" / "=" + ; Must be in quoted-string, + ; to use within parameter values +*/ + +void parameterizedHeaderField::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 = pstart; + + const string::size_type start = position; + + while (p < pend && *p != ';') ++p; + + parseValue(buffer, start, position + (p - pstart)); + + // If there is one or more parameters following... + if (p < pend) + { + while (*p == ';') + { + // Skip ';' + ++p; + + while (p < pend && isspace(*p)) ++p; + + const string::size_type attrStart = position + (p - pstart); + + while (p < pend && !(*p == ';' || *p == '=')) + ++p; + + if (p >= pend || *p == ';') + { + // Hmmmm... we didn't found an '=' sign. + // This parameter may not be valid so try to advance + // to the next one, if there is one. + while (p < pend && *p != ';') + ++p; + } + else + { + // Extract the attribute name + string::size_type attrEnd = position + (p - pstart); + + while (attrEnd != attrStart && isspace(buffer[attrEnd - 1])) + --attrEnd; + + // Skip '=' + ++p; + + // Skip white-spaces between '=' and the value + while (p < pend && isspace(*p)) ++p; + + // Extract the value + string value; + + // -- this is a quoted-string + if (*p == '"') + { + // Skip '"' + ++p; + + // Extract quoted-string + bool escape = false; + bool stop = false; + + std::ostringstream ss; + string::size_type start = position + (p - pstart); + + for ( ; p < pend && !stop ; ++p) + { + if (escape) + { + escape = false; + start = position + (p - pstart); + } + else + { + switch (*p) + { + case '"': + { + ss << string(buffer.begin() + start, + buffer.begin() + position + (p - pstart)); + + stop = true; + break; + } + case '\\': + { + ss << string(buffer.begin() + start, + buffer.begin() + position + (p - pstart)); + + escape = true; + break; + } + + } + } + } + + if (!stop) + { + ss << string(buffer.begin() + start, + buffer.begin() + position + (p - pstart)); + } + + value = ss.str(); + } + // -- the value is a simple token + else + { + const string::size_type valStart = position + (p - pstart); + + while (p < pend && *p != ';') + ++p; + + string::size_type valEnd = position + (p - pstart); + + while (valEnd != valStart && isspace(buffer[valEnd - 1])) + --valEnd; + + value = string(buffer.begin() + valStart, + buffer.begin() + valEnd); + } + + // Don't allow ill-formed parameters + if (attrStart != attrEnd && value.length()) + { + // Append this parameter to the list + parameters.m_params.push_back(parameterFactory::getInstance()-> + create(string(buffer.begin() + attrStart, + buffer.begin() + attrEnd), value)); + } + + // Skip white-spaces after this parameter + while (p < pend && isspace(*p)) ++p; + } + } + } + + if (newPosition) + *newPosition = end; +} + + +void parameterizedHeaderField::generate(utility::outputStream& os, const string::size_type maxLineLength, + const string::size_type curLinePos, string::size_type* newLinePos) const +{ + string::size_type pos = curLinePos; + + // Parent header field + headerField::generate(os, maxLineLength, pos, &pos); + + // Value + const string value = generateValue(); + + encodeAndFoldText(os, text(value), maxLineLength - 1, + pos, &pos, encodeAndFoldFlags::none); + + // Parameters + for (std::vector <parameter*>::const_iterator + it = parameters.m_params.begin() ; it != parameters.m_params.end() ; ++it) + { + const parameter& param = **it; + + os << "; "; + pos += 2; + + param.generate(os, maxLineLength, pos, &pos); + } + + if (newLinePos) + *newLinePos = pos; +} + + +void parameterizedHeaderField::copyFrom(const headerField& field) +{ + const parameterizedHeaderField& source = dynamic_cast<const parameterizedHeaderField&>(field); + + parameters.clear(); + + for (std::vector <parameter*>::const_iterator i = source.parameters.m_params.begin() ; + i != source.parameters.m_params.end() ; ++i) + { + parameters.m_params.push_back((*i)->clone()); + } + + headerField::copyFrom(field); +} + + + +////////////////////// +// Params container // +////////////////////// + + +parameterizedHeaderField::paramsContainer::~paramsContainer() +{ + clear(); +} + + +parameter& parameterizedHeaderField::paramsContainer::find(const string& name) const +{ + const string _name = toLower(name); + + std::vector <parameter*>::const_iterator pos = m_params.begin(); + const std::vector <parameter*>::const_iterator end = m_params.end(); + + for ( ; pos != end && (*pos)->name() != _name ; ++pos); + + // No parameter with this name can be found + if (pos == end) + { + throw exceptions::no_such_parameter(name); + } + // Else, return a reference to the existing parameter + else + { + return (**pos); + } +} + + +parameter& parameterizedHeaderField::paramsContainer::get(const string& name) +{ + const string _name = toLower(name); + + std::vector <parameter*>::iterator pos = m_params.begin(); + const std::vector <parameter*>::iterator end = m_params.end(); + + for ( ; pos != end && (*pos)->name() != _name ; ++pos); + + // If no parameter with this name can be found, create a new one + if (pos == end) + { + parameter* param = parameterFactory::getInstance()->create(_name); + m_params.push_back(param); + + // Return a reference to the new parameter + return (*param); + } + // Else, return a reference to the existing parameter + else + { + return (**pos); + } +} + + +// Parameter insertion +void parameterizedHeaderField::paramsContainer::append(const parameter& param) +{ + m_params.push_back(param.clone()); +} + + +void parameterizedHeaderField::paramsContainer::insert(const iterator it, const parameter& param) +{ + m_params.insert(it.m_iterator, param.clone()); +} + + +// Parameter removing +void parameterizedHeaderField::paramsContainer::remove(const iterator it) +{ + delete (*it.m_iterator); + m_params.erase(it.m_iterator); +} + + +void parameterizedHeaderField::paramsContainer::clear() +{ + free_container(m_params); +} + + +} // vmime |