Fixed wrong encoding of line breaks in QP-encoded text (issue #7).
This commit is contained in:
parent
ec715e6058
commit
0633a49b04
@ -34,19 +34,28 @@ namespace vmime
|
|||||||
|
|
||||||
|
|
||||||
encoding::encoding()
|
encoding::encoding()
|
||||||
: m_name(encodingTypes::SEVEN_BIT)
|
: m_name(encodingTypes::SEVEN_BIT),
|
||||||
|
m_usage(USAGE_UNKNOWN)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
encoding::encoding(const string& name)
|
encoding::encoding(const string& name)
|
||||||
: m_name(utility::stringUtils::toLower(name))
|
: m_name(utility::stringUtils::toLower(name)),
|
||||||
|
m_usage(USAGE_UNKNOWN)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
encoding::encoding(const string& name, const EncodingUsage usage)
|
||||||
|
: m_name(utility::stringUtils::toLower(name)),
|
||||||
|
m_usage(usage)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
encoding::encoding(const encoding& enc)
|
encoding::encoding(const encoding& enc)
|
||||||
: headerFieldValue(), m_name(enc.m_name)
|
: headerFieldValue(), m_name(enc.m_name), m_usage(enc.m_usage)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -54,6 +63,8 @@ encoding::encoding(const encoding& enc)
|
|||||||
void encoding::parse(const string& buffer, const string::size_type position,
|
void encoding::parse(const string& buffer, const string::size_type position,
|
||||||
const string::size_type end, string::size_type* newPosition)
|
const string::size_type end, string::size_type* newPosition)
|
||||||
{
|
{
|
||||||
|
m_usage = USAGE_UNKNOWN;
|
||||||
|
|
||||||
m_name = utility::stringUtils::toLower(utility::stringUtils::trim
|
m_name = utility::stringUtils::toLower(utility::stringUtils::trim
|
||||||
(utility::stringUtils::unquote(utility::stringUtils::trim
|
(utility::stringUtils::unquote(utility::stringUtils::trim
|
||||||
(string(buffer.begin() + position, buffer.begin() + end)))));
|
(string(buffer.begin() + position, buffer.begin() + end)))));
|
||||||
@ -80,7 +91,14 @@ void encoding::generate(utility::outputStream& os, const string::size_type /* ma
|
|||||||
|
|
||||||
ref <utility::encoder::encoder> encoding::getEncoder() const
|
ref <utility::encoder::encoder> encoding::getEncoder() const
|
||||||
{
|
{
|
||||||
return (utility::encoder::encoderFactory::getInstance()->create(generate()));
|
ref <utility::encoder::encoder> encoder =
|
||||||
|
utility::encoder::encoderFactory::getInstance()->create(generate());
|
||||||
|
|
||||||
|
// FIXME: this should not be here (move me into QP encoder instead?)
|
||||||
|
if (m_usage == USAGE_TEXT && m_name == encodingTypes::QUOTED_PRINTABLE)
|
||||||
|
encoder->getProperties()["text"] = true;
|
||||||
|
|
||||||
|
return encoder;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -94,6 +112,7 @@ encoding& encoding::operator=(const encoding& other)
|
|||||||
encoding& encoding::operator=(const string& name)
|
encoding& encoding::operator=(const string& name)
|
||||||
{
|
{
|
||||||
m_name = utility::stringUtils::toLower(name);
|
m_name = utility::stringUtils::toLower(name);
|
||||||
|
m_usage = USAGE_UNKNOWN;
|
||||||
return (*this);
|
return (*this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -167,6 +186,8 @@ const encoding encoding::decideImpl
|
|||||||
const encoding encoding::decide
|
const encoding encoding::decide
|
||||||
(ref <const contentHandler> data, const EncodingUsage usage)
|
(ref <const contentHandler> data, const EncodingUsage usage)
|
||||||
{
|
{
|
||||||
|
encoding enc;
|
||||||
|
|
||||||
if (usage == USAGE_TEXT && data->isBuffered() &&
|
if (usage == USAGE_TEXT && data->isBuffered() &&
|
||||||
data->getLength() > 0 && data->getLength() < 32768)
|
data->getLength() > 0 && data->getLength() < 32768)
|
||||||
{
|
{
|
||||||
@ -177,12 +198,16 @@ const encoding encoding::decide
|
|||||||
data->extract(os);
|
data->extract(os);
|
||||||
os.flush();
|
os.flush();
|
||||||
|
|
||||||
return decideImpl(buffer.begin(), buffer.end());
|
enc = decideImpl(buffer.begin(), buffer.end());
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
return encoding(encodingTypes::BASE64);
|
enc = encoding(encodingTypes::BASE64);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
enc.setUsage(usage);
|
||||||
|
|
||||||
|
return enc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -194,8 +219,11 @@ const encoding encoding::decide(ref <const contentHandler> data,
|
|||||||
encoding recEncoding;
|
encoding recEncoding;
|
||||||
|
|
||||||
if (chset.getRecommendedEncoding(recEncoding))
|
if (chset.getRecommendedEncoding(recEncoding))
|
||||||
|
{
|
||||||
|
recEncoding.setUsage(usage);
|
||||||
return recEncoding;
|
return recEncoding;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return decide(data, usage);
|
return decide(data, usage);
|
||||||
}
|
}
|
||||||
@ -227,6 +255,18 @@ void encoding::setName(const string& name)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
encoding::EncodingUsage encoding::getUsage() const
|
||||||
|
{
|
||||||
|
return m_usage;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void encoding::setUsage(const EncodingUsage usage)
|
||||||
|
{
|
||||||
|
m_usage = usage;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
const std::vector <ref <const component> > encoding::getChildComponents() const
|
const std::vector <ref <const component> > encoding::getChildComponents() const
|
||||||
{
|
{
|
||||||
return std::vector <ref <const component> >();
|
return std::vector <ref <const component> >();
|
||||||
|
@ -292,14 +292,15 @@ utility::stream::size_type qpEncoder::encode(utility::inputStream& in,
|
|||||||
case 13: // CR
|
case 13: // CR
|
||||||
case 10: // LF
|
case 10: // LF
|
||||||
{
|
{
|
||||||
// Text mode (where using CRLF or LF or ... does not
|
// RFC-2045/6.7(4)
|
||||||
// care for a new line...)
|
|
||||||
if (text)
|
// Text data
|
||||||
|
if (text && !rfc2047)
|
||||||
{
|
{
|
||||||
outBuffer[outBufferPos++] = c;
|
outBuffer[outBufferPos++] = c;
|
||||||
++curCol;
|
++curCol;
|
||||||
}
|
}
|
||||||
// Binary mode (where CR and LF bytes are important!)
|
// Binary data
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
QP_ENCODE_HEX(c);
|
QP_ENCODE_HEX(c);
|
||||||
|
@ -38,6 +38,7 @@ VMIME_TEST_SUITE_BEGIN
|
|||||||
VMIME_TEST(testPrologEncoding)
|
VMIME_TEST(testPrologEncoding)
|
||||||
VMIME_TEST(testSuccessiveBoundaries)
|
VMIME_TEST(testSuccessiveBoundaries)
|
||||||
VMIME_TEST(testGenerate7bit)
|
VMIME_TEST(testGenerate7bit)
|
||||||
|
VMIME_TEST(testTextUsageForQPEncoding)
|
||||||
VMIME_TEST_LIST_END
|
VMIME_TEST_LIST_END
|
||||||
|
|
||||||
|
|
||||||
@ -214,5 +215,28 @@ VMIME_TEST_SUITE_BEGIN
|
|||||||
VASSERT_EQ("1", "7bit", header1->ContentTransferEncoding()->getValue()->generate());
|
VASSERT_EQ("1", "7bit", header1->ContentTransferEncoding()->getValue()->generate());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void testTextUsageForQPEncoding()
|
||||||
|
{
|
||||||
|
vmime::ref <vmime::plainTextPart> part = vmime::create <vmime::plainTextPart>();
|
||||||
|
part->setText(vmime::create <vmime::stringContentHandler>("Part1-line1\r\nPart1-line2\r\n\x89"));
|
||||||
|
|
||||||
|
vmime::ref <vmime::message> msg = vmime::create <vmime::message>();
|
||||||
|
part->generateIn(msg, msg);
|
||||||
|
|
||||||
|
vmime::ref <vmime::body> body = msg->getBody()->getPartAt(0)->getBody();
|
||||||
|
vmime::ref <vmime::header> header = msg->getBody()->getPartAt(0)->getHeader();
|
||||||
|
|
||||||
|
std::ostringstream oss;
|
||||||
|
vmime::utility::outputStreamAdapter os(oss);
|
||||||
|
body->generate(os, 80);
|
||||||
|
|
||||||
|
VASSERT_EQ("1", "quoted-printable", header->ContentTransferEncoding()->getValue()->generate());
|
||||||
|
|
||||||
|
// This should *NOT* be:
|
||||||
|
// Part1-line1=0D=0APart1-line2=0D=0A=89
|
||||||
|
VASSERT_EQ("2", "Part1-line1\r\nPart1-line2\r\n=89", oss.str());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
VMIME_TEST_SUITE_END
|
VMIME_TEST_SUITE_END
|
||||||
|
|
||||||
|
@ -47,6 +47,7 @@ public:
|
|||||||
|
|
||||||
enum EncodingUsage
|
enum EncodingUsage
|
||||||
{
|
{
|
||||||
|
USAGE_UNKNOWN,
|
||||||
USAGE_TEXT, /**< Use for body text. */
|
USAGE_TEXT, /**< Use for body text. */
|
||||||
USAGE_BINARY_DATA /**< Use for attachment, image... */
|
USAGE_BINARY_DATA /**< Use for attachment, image... */
|
||||||
};
|
};
|
||||||
@ -54,6 +55,7 @@ public:
|
|||||||
|
|
||||||
encoding();
|
encoding();
|
||||||
explicit encoding(const string& name);
|
explicit encoding(const string& name);
|
||||||
|
encoding(const string& name, const EncodingUsage usage);
|
||||||
encoding(const encoding& enc);
|
encoding(const encoding& enc);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
@ -72,6 +74,19 @@ public:
|
|||||||
*/
|
*/
|
||||||
void setName(const string& name);
|
void setName(const string& name);
|
||||||
|
|
||||||
|
/** Return the type of contents this encoding is used for.
|
||||||
|
* See the EncodingUsage enum.
|
||||||
|
*/
|
||||||
|
EncodingUsage getUsage() const;
|
||||||
|
|
||||||
|
/** Set the type of contents this encoding is used for.
|
||||||
|
* See the EncodingUsage enum.
|
||||||
|
*
|
||||||
|
* @param usage type of contents
|
||||||
|
*/
|
||||||
|
void setUsage(const EncodingUsage usage);
|
||||||
|
|
||||||
|
|
||||||
encoding& operator=(const encoding& other);
|
encoding& operator=(const encoding& other);
|
||||||
encoding& operator=(const string& name);
|
encoding& operator=(const string& name);
|
||||||
|
|
||||||
@ -113,6 +128,7 @@ public:
|
|||||||
private:
|
private:
|
||||||
|
|
||||||
string m_name;
|
string m_name;
|
||||||
|
EncodingUsage m_usage;
|
||||||
|
|
||||||
/** Decide which encoding to use based on the specified data.
|
/** Decide which encoding to use based on the specified data.
|
||||||
*
|
*
|
||||||
|
Loading…
Reference in New Issue
Block a user