2004-10-05 10:28:21 +00:00
|
|
|
//
|
2005-03-18 21:33:11 +00:00
|
|
|
// VMime library (http://www.vmime.org)
|
2009-09-06 12:02:10 +00:00
|
|
|
// Copyright (C) 2002-2009 Vincent Richard <vincent@vincent-richard.net>
|
2004-10-05 10:28:21 +00:00
|
|
|
//
|
|
|
|
// This program is free software; you can redistribute it and/or
|
|
|
|
// modify it under the terms of the GNU General Public License as
|
2009-09-06 12:02:10 +00:00
|
|
|
// published by the Free Software Foundation; either version 3 of
|
2004-10-05 10:28:21 +00:00
|
|
|
// 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.
|
|
|
|
//
|
2005-09-17 10:10:29 +00:00
|
|
|
// 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.
|
2004-10-05 10:28:21 +00:00
|
|
|
//
|
|
|
|
|
2004-12-26 20:23:29 +00:00
|
|
|
#include "vmime/parameter.hpp"
|
2005-11-04 23:21:22 +00:00
|
|
|
#include "vmime/parserHelpers.hpp"
|
|
|
|
|
|
|
|
#include "vmime/text.hpp"
|
2010-09-07 07:44:15 +00:00
|
|
|
#include "vmime/encoding.hpp"
|
2004-10-05 10:28:21 +00:00
|
|
|
|
|
|
|
|
|
|
|
namespace vmime
|
|
|
|
{
|
|
|
|
|
|
|
|
|
2005-11-04 23:21:22 +00:00
|
|
|
parameter::parameter(const string& name)
|
|
|
|
: m_name(name)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
parameter::parameter(const string& name, const word& value)
|
|
|
|
: m_name(name), m_value(value)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
parameter::parameter(const string& name, const string& value)
|
|
|
|
: m_name(name), m_value(value)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
parameter::parameter(const parameter&)
|
|
|
|
: component()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2005-07-12 22:28:02 +00:00
|
|
|
ref <component> parameter::clone() const
|
2004-10-05 10:28:21 +00:00
|
|
|
{
|
2005-11-04 23:21:22 +00:00
|
|
|
ref <parameter> p = vmime::create <parameter>(m_name);
|
2004-10-05 10:28:21 +00:00
|
|
|
p->copyFrom(*this);
|
|
|
|
|
|
|
|
return (p);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2004-10-21 15:05:47 +00:00
|
|
|
void parameter::copyFrom(const component& other)
|
2004-10-05 10:28:21 +00:00
|
|
|
{
|
2004-10-21 15:05:47 +00:00
|
|
|
const parameter& param = dynamic_cast <const parameter&>(other);
|
|
|
|
|
2004-10-05 10:28:21 +00:00
|
|
|
m_name = param.m_name;
|
2005-11-04 23:21:22 +00:00
|
|
|
m_value.copyFrom(param.m_value);
|
2004-10-21 15:05:47 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
parameter& parameter::operator=(const parameter& other)
|
|
|
|
{
|
|
|
|
copyFrom(other);
|
|
|
|
return (*this);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
const string& parameter::getName() const
|
|
|
|
{
|
2005-11-04 23:21:22 +00:00
|
|
|
return m_name;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
const word& parameter::getValue() const
|
|
|
|
{
|
|
|
|
return m_value;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void parameter::setValue(const component& value)
|
|
|
|
{
|
|
|
|
std::ostringstream oss;
|
|
|
|
utility::outputStreamAdapter vos(oss);
|
|
|
|
|
|
|
|
value.generate(vos);
|
|
|
|
|
|
|
|
setValue(word(oss.str(), vmime::charsets::US_ASCII));
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void parameter::setValue(const word& value)
|
|
|
|
{
|
|
|
|
m_value = value;
|
2004-10-21 15:05:47 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void parameter::parse(const string& buffer, const string::size_type position,
|
|
|
|
const string::size_type end, string::size_type* newPosition)
|
|
|
|
{
|
2005-11-04 23:21:22 +00:00
|
|
|
m_value.setBuffer(string(buffer.begin() + position, buffer.begin() + end));
|
|
|
|
m_value.setCharset(charset(charsets::US_ASCII));
|
2005-04-12 18:42:54 +00:00
|
|
|
|
|
|
|
if (newPosition)
|
|
|
|
*newPosition = end;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void parameter::parse(const std::vector <valueChunk>& chunks)
|
|
|
|
{
|
2005-11-04 23:21:22 +00:00
|
|
|
bool foundCharsetChunk = false;
|
|
|
|
|
|
|
|
charset ch(charsets::US_ASCII);
|
2006-11-08 18:33:18 +00:00
|
|
|
|
2005-11-04 23:21:22 +00:00
|
|
|
std::ostringstream value;
|
2006-11-08 18:33:18 +00:00
|
|
|
value.imbue(std::locale::classic());
|
2005-04-12 18:42:54 +00:00
|
|
|
|
2005-11-04 23:21:22 +00:00
|
|
|
for (std::vector <valueChunk>::size_type i = 0 ; i < chunks.size() ; ++i)
|
2005-04-12 18:42:54 +00:00
|
|
|
{
|
2005-11-04 23:21:22 +00:00
|
|
|
const valueChunk& chunk = chunks[i];
|
|
|
|
|
|
|
|
// Decode following data
|
|
|
|
if (chunk.encoded)
|
|
|
|
{
|
|
|
|
const string::size_type len = chunk.data.length();
|
|
|
|
string::size_type pos = 0;
|
|
|
|
|
|
|
|
// If this is the first encoded chunk, extract charset
|
|
|
|
// and language information
|
|
|
|
if (!foundCharsetChunk)
|
|
|
|
{
|
|
|
|
// Eg. "us-ascii'en'This%20is%20even%20more%20"
|
|
|
|
string::size_type q = chunk.data.find_first_of('\'');
|
|
|
|
|
|
|
|
if (q != string::npos)
|
|
|
|
{
|
|
|
|
const string chs = chunk.data.substr(0, q);
|
|
|
|
|
|
|
|
if (!chs.empty())
|
|
|
|
ch = charset(chs);
|
|
|
|
|
|
|
|
++q;
|
|
|
|
pos = q;
|
|
|
|
}
|
|
|
|
|
|
|
|
q = chunk.data.find_first_of('\'', pos);
|
|
|
|
|
|
|
|
if (q != string::npos)
|
|
|
|
{
|
|
|
|
// Ignore language
|
|
|
|
++q;
|
|
|
|
pos = q;
|
|
|
|
}
|
|
|
|
|
|
|
|
foundCharsetChunk = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (string::size_type i = pos ; i < len ; ++i)
|
|
|
|
{
|
|
|
|
const string::value_type c = chunk.data[i];
|
|
|
|
|
|
|
|
if (c == '%' && i + 2 < len)
|
|
|
|
{
|
2008-10-12 10:05:28 +00:00
|
|
|
unsigned int v = 0;
|
2005-11-04 23:21:22 +00:00
|
|
|
|
|
|
|
// First char
|
|
|
|
switch (chunk.data[i + 1])
|
|
|
|
{
|
|
|
|
case 'a': case 'A': v += 10; break;
|
|
|
|
case 'b': case 'B': v += 11; break;
|
|
|
|
case 'c': case 'C': v += 12; break;
|
|
|
|
case 'd': case 'D': v += 13; break;
|
|
|
|
case 'e': case 'E': v += 14; break;
|
|
|
|
case 'f': case 'F': v += 15; break;
|
|
|
|
default: // assume 0-9
|
|
|
|
|
|
|
|
v += (chunk.data[i + 1] - '0');
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
v *= 16;
|
|
|
|
|
|
|
|
// Second char
|
|
|
|
switch (chunk.data[i + 2])
|
|
|
|
{
|
|
|
|
case 'a': case 'A': v += 10; break;
|
|
|
|
case 'b': case 'B': v += 11; break;
|
|
|
|
case 'c': case 'C': v += 12; break;
|
|
|
|
case 'd': case 'D': v += 13; break;
|
|
|
|
case 'e': case 'E': v += 14; break;
|
|
|
|
case 'f': case 'F': v += 15; break;
|
|
|
|
default: // assume 0-9
|
|
|
|
|
|
|
|
v += (chunk.data[i + 2] - '0');
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2008-10-12 10:05:28 +00:00
|
|
|
value << static_cast <string::value_type>(v);
|
2005-11-04 23:21:22 +00:00
|
|
|
|
|
|
|
i += 2; // skip next 2 chars
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
value << c;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// Simply copy data, as it is not encoded
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// This syntax is non-standard (expressly prohibited
|
|
|
|
// by RFC-2047), but is used by Mozilla:
|
|
|
|
//
|
|
|
|
// Content-Type: image/png;
|
|
|
|
// name="=?us-ascii?Q?Logo_VMime=2Epng?="
|
|
|
|
|
|
|
|
// Using 'vmime::text' to parse the data is safe even
|
|
|
|
// if the data is not encoded, because it can recover
|
|
|
|
// from parsing errors.
|
|
|
|
vmime::text t;
|
|
|
|
t.parse(chunk.data);
|
|
|
|
|
|
|
|
if (t.getWordCount() != 0)
|
|
|
|
{
|
|
|
|
value << t.getWholeBuffer();
|
|
|
|
|
|
|
|
if (!foundCharsetChunk)
|
|
|
|
ch = t.getWordAt(0)->getCharset();
|
|
|
|
}
|
|
|
|
}
|
2005-04-12 18:42:54 +00:00
|
|
|
}
|
|
|
|
|
2005-11-04 23:21:22 +00:00
|
|
|
m_value.setBuffer(value.str());
|
|
|
|
m_value.setCharset(ch);
|
2004-10-21 15:05:47 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void parameter::generate(utility::outputStream& os, const string::size_type maxLineLength,
|
|
|
|
const string::size_type curLinePos, string::size_type* newLinePos) const
|
|
|
|
{
|
2005-11-04 23:21:22 +00:00
|
|
|
const string& name = m_name;
|
|
|
|
const string& value = m_value.getBuffer();
|
|
|
|
|
|
|
|
// For compatibility with implementations that do not understand RFC-2231,
|
|
|
|
// also generate a normal "7bit/us-ascii" parameter
|
2010-06-23 20:42:25 +00:00
|
|
|
|
|
|
|
// [By Eugene A. Shatokhin]
|
|
|
|
// Note that if both the normal "7bit/us-ascii" value and the extended
|
|
|
|
// value are present, the latter can be ignored by mail processing systems.
|
|
|
|
// This may lead to annoying problems, for example, with strange names of
|
|
|
|
// attachments with all but 7-bit ascii characters removed, etc. To avoid
|
|
|
|
// this, I would suggest not to create "7bit/us-ascii" value if the extended
|
|
|
|
// value is to be generated.
|
|
|
|
|
|
|
|
// A stream for a temporary storage
|
|
|
|
std::ostringstream sevenBitBuffer;
|
|
|
|
|
2004-10-21 15:05:47 +00:00
|
|
|
string::size_type pos = curLinePos;
|
|
|
|
|
2005-11-04 23:21:22 +00:00
|
|
|
if (pos + name.length() + 10 + value.length() > maxLineLength)
|
2004-10-21 15:05:47 +00:00
|
|
|
{
|
2010-06-23 20:42:25 +00:00
|
|
|
sevenBitBuffer << NEW_LINE_SEQUENCE;
|
2004-10-21 15:05:47 +00:00
|
|
|
pos = NEW_LINE_SEQUENCE_LENGTH;
|
|
|
|
}
|
|
|
|
|
2005-11-04 23:21:22 +00:00
|
|
|
bool needQuoting = false;
|
|
|
|
string::size_type valueLength = 0;
|
2004-10-21 15:05:47 +00:00
|
|
|
|
2005-11-04 23:21:22 +00:00
|
|
|
for (string::size_type i = 0 ; (i < value.length()) && (pos + valueLength < maxLineLength - 4) ; ++i, ++valueLength)
|
2004-10-21 15:05:47 +00:00
|
|
|
{
|
2005-11-04 23:21:22 +00:00
|
|
|
switch (value[i])
|
2004-10-21 15:05:47 +00:00
|
|
|
{
|
|
|
|
// Characters that need to be quoted _and_ escaped
|
|
|
|
case '"':
|
|
|
|
case '\\':
|
|
|
|
// Other characters that need quoting
|
|
|
|
case ' ':
|
|
|
|
case '\t':
|
|
|
|
case '(':
|
|
|
|
case ')':
|
|
|
|
case '<':
|
|
|
|
case '>':
|
|
|
|
case '@':
|
|
|
|
case ',':
|
|
|
|
case ';':
|
|
|
|
case ':':
|
|
|
|
case '/':
|
|
|
|
case '[':
|
|
|
|
case ']':
|
|
|
|
case '?':
|
|
|
|
case '=':
|
|
|
|
|
2005-11-04 23:21:22 +00:00
|
|
|
needQuoting = true;
|
2004-10-21 15:05:47 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2005-11-04 23:21:22 +00:00
|
|
|
const bool cutValue = (valueLength != value.length()); // has the value been cut?
|
2004-10-21 15:05:47 +00:00
|
|
|
|
2005-11-04 23:21:22 +00:00
|
|
|
if (needQuoting)
|
|
|
|
{
|
2010-06-23 20:42:25 +00:00
|
|
|
sevenBitBuffer << name << "=\"";
|
2005-11-04 23:21:22 +00:00
|
|
|
pos += name.length() + 2;
|
|
|
|
}
|
2004-10-21 15:05:47 +00:00
|
|
|
else
|
2005-11-04 23:21:22 +00:00
|
|
|
{
|
2010-06-23 20:42:25 +00:00
|
|
|
sevenBitBuffer << name << "=";
|
2005-11-04 23:21:22 +00:00
|
|
|
pos += name.length() + 1;
|
|
|
|
}
|
|
|
|
|
2010-09-07 07:44:15 +00:00
|
|
|
// Check whether there is a recommended encoding for this charset.
|
|
|
|
// If so, the whole buffer will be encoded. Else, the number of
|
|
|
|
// 7-bit (ASCII) bytes in the input will be used to determine if
|
|
|
|
// we need to encode the whole buffer.
|
|
|
|
encoding recommendedEnc;
|
|
|
|
const bool alwaysEncode = m_value.getCharset().getRecommendedEncoding(recommendedEnc);
|
|
|
|
bool extended = alwaysEncode;
|
2005-11-04 23:21:22 +00:00
|
|
|
|
|
|
|
for (string::size_type i = 0 ; (i < value.length()) && (pos < maxLineLength - 4) ; ++i)
|
|
|
|
{
|
|
|
|
const char_t c = value[i];
|
|
|
|
|
|
|
|
if (/* needQuoting && */ (c == '"' || c == '\\')) // 'needQuoting' is implicit
|
|
|
|
{
|
2010-06-23 20:42:25 +00:00
|
|
|
sevenBitBuffer << '\\' << value[i]; // escape 'x' with '\x'
|
2005-11-04 23:21:22 +00:00
|
|
|
pos += 2;
|
|
|
|
}
|
|
|
|
else if (parserHelpers::isAscii(c))
|
|
|
|
{
|
2010-06-23 20:42:25 +00:00
|
|
|
sevenBitBuffer << value[i];
|
2005-11-04 23:21:22 +00:00
|
|
|
++pos;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
extended = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (needQuoting)
|
|
|
|
{
|
2010-06-23 20:42:25 +00:00
|
|
|
sevenBitBuffer << '"';
|
2005-11-04 23:21:22 +00:00
|
|
|
++pos;
|
|
|
|
}
|
|
|
|
|
2010-06-23 20:42:25 +00:00
|
|
|
#if VMIME_ALWAYS_GENERATE_7BIT_PARAMETER
|
|
|
|
os << sevenBitBuffer;
|
|
|
|
#endif // !VMIME_ALWAYS_GENERATE_7BIT_PARAMETER
|
|
|
|
|
2005-11-04 23:21:22 +00:00
|
|
|
// Also generate an extended parameter if the value contains 8-bit characters
|
|
|
|
// or is too long for a single line
|
|
|
|
if (extended || cutValue)
|
|
|
|
{
|
2010-06-23 20:42:25 +00:00
|
|
|
|
|
|
|
#if VMIME_ALWAYS_GENERATE_7BIT_PARAMETER
|
|
|
|
|
2005-11-04 23:21:22 +00:00
|
|
|
os << ';';
|
|
|
|
++pos;
|
|
|
|
|
2010-06-23 20:42:25 +00:00
|
|
|
#else // !VMIME_ALWAYS_GENERATE_7BIT_PARAMETER
|
|
|
|
|
|
|
|
// The data output to 'sevenBitBuffer' will be discarded in this case
|
|
|
|
pos = curLinePos;
|
|
|
|
|
|
|
|
#endif // VMIME_ALWAYS_GENERATE_7BIT_PARAMETER
|
|
|
|
|
2005-11-04 23:21:22 +00:00
|
|
|
/* RFC-2231
|
|
|
|
* ========
|
|
|
|
*
|
|
|
|
* Content-Type: message/external-body; access-type=URL;
|
|
|
|
* URL*0="ftp://";
|
|
|
|
* URL*1="cs.utk.edu/pub/moore/bulk-mailer/bulk-mailer.tar"
|
|
|
|
*
|
|
|
|
* Content-Type: application/x-stuff;
|
|
|
|
* title*=us-ascii'en-us'This%20is%20%2A%2A%2Afun%2A%2A%2A
|
|
|
|
*
|
|
|
|
* Content-Type: application/x-stuff;
|
|
|
|
* title*0*=us-ascii'en'This%20is%20even%20more%20
|
|
|
|
* title*1*=%2A%2A%2Afun%2A%2A%2A%20
|
|
|
|
* title*2="isn't it!"
|
|
|
|
*/
|
|
|
|
|
|
|
|
// Check whether there is enough space for the first section:
|
|
|
|
// parameter name, section identifier, charset and separators
|
|
|
|
// + at least 5 characters for the value
|
|
|
|
const string::size_type firstSectionLength =
|
|
|
|
name.length() + 4 /* *0*= */ + 2 /* '' */
|
|
|
|
+ m_value.getCharset().getName().length();
|
|
|
|
|
|
|
|
if (pos + firstSectionLength + 5 >= maxLineLength)
|
|
|
|
{
|
|
|
|
os << NEW_LINE_SEQUENCE;
|
|
|
|
pos = NEW_LINE_SEQUENCE_LENGTH;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Split text into multiple sections that fit on one line
|
|
|
|
int sectionCount = 0;
|
|
|
|
std::vector <string> sectionText;
|
|
|
|
|
|
|
|
string currentSection;
|
|
|
|
string::size_type currentSectionLength = firstSectionLength;
|
|
|
|
|
|
|
|
for (string::size_type i = 0 ; i < value.length() ; ++i)
|
|
|
|
{
|
|
|
|
// Check whether we should start a new line (taking into
|
|
|
|
// account the next character will be encoded = worst case)
|
|
|
|
if (currentSectionLength + 3 >= maxLineLength)
|
|
|
|
{
|
|
|
|
sectionText.push_back(currentSection);
|
|
|
|
sectionCount++;
|
|
|
|
|
|
|
|
currentSection.clear();
|
|
|
|
currentSectionLength = NEW_LINE_SEQUENCE_LENGTH
|
|
|
|
+ name.length() + 6;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Output next character
|
|
|
|
const char_t c = value[i];
|
|
|
|
bool encode = false;
|
|
|
|
|
|
|
|
switch (c)
|
|
|
|
{
|
|
|
|
// special characters
|
|
|
|
case ' ':
|
|
|
|
case '\t':
|
|
|
|
case '\r':
|
|
|
|
case '\n':
|
2010-08-17 21:47:25 +00:00
|
|
|
case '%':
|
2005-11-04 23:21:22 +00:00
|
|
|
case '"':
|
|
|
|
case ';':
|
|
|
|
case ',':
|
2010-08-17 21:47:25 +00:00
|
|
|
case '(':
|
|
|
|
case ')':
|
|
|
|
case '<':
|
|
|
|
case '>':
|
|
|
|
case '@':
|
|
|
|
case ':':
|
|
|
|
case '/':
|
|
|
|
case '[':
|
|
|
|
case ']':
|
|
|
|
case '?':
|
|
|
|
case '=':
|
2005-11-04 23:21:22 +00:00
|
|
|
|
|
|
|
encode = true;
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
|
|
|
|
encode = (!parserHelpers::isPrint(c) ||
|
2010-09-07 07:44:15 +00:00
|
|
|
!parserHelpers::isAscii(c) ||
|
|
|
|
alwaysEncode);
|
2005-11-04 23:21:22 +00:00
|
|
|
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (encode) // need encoding
|
|
|
|
{
|
|
|
|
const int h1 = static_cast <unsigned char>(c) / 16;
|
|
|
|
const int h2 = static_cast <unsigned char>(c) % 16;
|
|
|
|
|
|
|
|
currentSection += '%';
|
|
|
|
currentSection += "0123456789ABCDEF"[h1];
|
|
|
|
currentSection += "0123456789ABCDEF"[h2];
|
|
|
|
|
|
|
|
pos += 3;
|
|
|
|
currentSectionLength += 3;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
currentSection += value[i];
|
|
|
|
|
|
|
|
++pos;
|
|
|
|
++currentSectionLength;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!currentSection.empty())
|
|
|
|
{
|
|
|
|
sectionText.push_back(currentSection);
|
|
|
|
sectionCount++;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Output sections
|
|
|
|
for (int sectionNumber = 0 ; sectionNumber < sectionCount ; ++sectionNumber)
|
|
|
|
{
|
|
|
|
os << name;
|
|
|
|
|
|
|
|
if (sectionCount != 1) // no section specifier when only a single one
|
|
|
|
{
|
|
|
|
os << '*';
|
|
|
|
os << sectionNumber;
|
|
|
|
}
|
|
|
|
|
|
|
|
os << "*=";
|
|
|
|
|
|
|
|
if (sectionNumber == 0)
|
|
|
|
{
|
|
|
|
os << m_value.getCharset().getName();
|
|
|
|
os << '\'' << /* No language */ '\'';
|
|
|
|
}
|
|
|
|
|
|
|
|
os << sectionText[sectionNumber];
|
|
|
|
|
|
|
|
if (sectionNumber + 1 < sectionCount)
|
|
|
|
{
|
|
|
|
os << ';';
|
|
|
|
os << NEW_LINE_SEQUENCE;
|
|
|
|
pos = NEW_LINE_SEQUENCE_LENGTH;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2010-06-23 20:42:25 +00:00
|
|
|
#if !VMIME_ALWAYS_GENERATE_7BIT_PARAMETER
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// The value does not contain 8-bit characters and
|
|
|
|
// is short enough for a single line.
|
|
|
|
// "7bit/us-ascii" will suffice in this case.
|
|
|
|
|
|
|
|
// Output what has been stored in temporary buffer so far
|
|
|
|
os << sevenBitBuffer.str();
|
|
|
|
}
|
|
|
|
#endif // !VMIME_ALWAYS_GENERATE_7BIT_PARAMETER
|
2004-10-21 15:05:47 +00:00
|
|
|
|
|
|
|
if (newLinePos)
|
2005-11-04 23:21:22 +00:00
|
|
|
*newLinePos = pos;
|
2004-10-05 10:28:21 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2005-07-12 22:28:02 +00:00
|
|
|
const std::vector <ref <const component> > parameter::getChildComponents() const
|
2004-12-20 12:33:55 +00:00
|
|
|
{
|
2005-07-12 22:28:02 +00:00
|
|
|
std::vector <ref <const component> > list;
|
2004-12-20 12:33:55 +00:00
|
|
|
|
2005-11-04 23:21:22 +00:00
|
|
|
list.push_back(ref <const component>::fromPtr(&m_value));
|
2004-12-20 12:33:55 +00:00
|
|
|
|
2005-11-04 23:21:22 +00:00
|
|
|
return list;
|
2004-12-20 12:33:55 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2004-10-05 10:28:21 +00:00
|
|
|
} // vmime
|
2005-11-04 23:21:22 +00:00
|
|
|
|