aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/vmime/parameter.cpp8
-rw-r--r--src/vmime/word.cpp54
-rw-r--r--src/vmime/word.hpp16
-rw-r--r--src/vmime/wordEncoder.cpp7
-rw-r--r--src/vmime/wordEncoder.hpp4
5 files changed, 78 insertions, 11 deletions
diff --git a/src/vmime/parameter.cpp b/src/vmime/parameter.cpp
index 45e68ad6..8773e857 100644
--- a/src/vmime/parameter.cpp
+++ b/src/vmime/parameter.cpp
@@ -134,6 +134,7 @@ void parameter::parse(const parsingContext& ctx, const std::vector <valueChunk>&
bool foundCharsetChunk = false;
charset ch(charsets::US_ASCII);
+ string lang;
std::ostringstream value;
value.imbue(std::locale::classic());
@@ -170,7 +171,9 @@ void parameter::parse(const parsingContext& ctx, const std::vector <valueChunk>&
if (q != string::npos)
{
- // Ignore language
+ // Extract language
+ lang = chunk.data.substr(pos, q - pos);
+
++q;
pos = q;
}
@@ -268,6 +271,7 @@ void parameter::parse(const parsingContext& ctx, const std::vector <valueChunk>&
m_value->setBuffer(value.str());
m_value->setCharset(ch);
+ m_value->setLanguage(lang);
}
@@ -372,7 +376,7 @@ void parameter::generateImpl
const bool alwaysEncode = m_value->getCharset().getRecommendedEncoding(recommendedEnc);
bool extended = alwaysEncode;
- if ((needQuotedPrintable || cutValue) &&
+ if ((needQuotedPrintable || cutValue || !m_value->getLanguage().empty()) &&
genMode != generationContext::PARAMETER_VALUE_NO_ENCODING)
{
// Send the name in quoted-printable, so outlook express et.al.
diff --git a/src/vmime/word.cpp b/src/vmime/word.cpp
index 7944fc77..2229857c 100644
--- a/src/vmime/word.cpp
+++ b/src/vmime/word.cpp
@@ -48,7 +48,8 @@ word::word()
word::word(const word& w)
- : headerFieldValue(), m_buffer(w.m_buffer), m_charset(w.m_charset)
+ : headerFieldValue(), m_buffer(w.m_buffer),
+ m_charset(w.m_charset), m_lang(w.m_lang)
{
}
@@ -65,6 +66,12 @@ word::word(const string& buffer, const charset& charset)
}
+word::word(const string& buffer, const charset& charset, const string& lang)
+ : m_buffer(buffer), m_charset(charset), m_lang(lang)
+{
+}
+
+
shared_ptr <word> word::parseNext
(const parsingContext& ctx, const string& buffer, const size_t position,
const size_t end, size_t* newPosition,
@@ -296,6 +303,21 @@ void word::parseImpl
if (theEncoder)
{
+ // Extract charset and language
+ const string charsetAndLang(charsetPos, charsetEnd);
+ const string::size_type asteriskPos = charsetAndLang.find('*');
+
+ if (asteriskPos != string::npos)
+ {
+ m_charset = charset(string(charsetAndLang.begin(), charsetAndLang.begin() + asteriskPos));
+ m_lang = string(charsetAndLang.begin() + asteriskPos + 1, charsetAndLang.end());
+ }
+ else
+ {
+ m_charset = charset(charsetAndLang);
+ m_lang.clear();
+ }
+
// Decode text
string decodedBuffer;
@@ -306,7 +328,6 @@ void word::parseImpl
delete (theEncoder);
m_buffer = decodedBuffer;
- m_charset = charset(string(charsetPos, charsetEnd));
setParsedBounds(position, p - buffer.begin());
@@ -358,7 +379,7 @@ void word::generate(const generationContext& ctx, utility::outputStream& os,
else if ((flags & text::FORCE_ENCODING) != 0)
encodingNeeded = true;
else // auto-detect
- encodingNeeded = wordEncoder::isEncodingNeeded(ctx, m_buffer, m_charset);
+ encodingNeeded = wordEncoder::isEncodingNeeded(ctx, m_buffer, m_charset, m_lang);
// If text does not need to be encoded, quote the buffer (no folding is performed).
if (!encodingNeeded &&
@@ -600,8 +621,12 @@ void word::generate(const generationContext& ctx, utility::outputStream& os,
wordEncoder wordEnc(m_buffer, m_charset);
- const string wordStart("=?" + m_charset.getName() + "?" +
- (wordEnc.getEncoding() == wordEncoder::ENCODING_B64 ? 'B' : 'Q') + "?");
+ const string wordStart("=?"
+ + m_charset.getName()
+ + (m_lang.empty() ? "" : string("*") + m_lang)
+ + "?"
+ + (wordEnc.getEncoding() == wordEncoder::ENCODING_B64 ? 'B' : 'Q')
+ + "?");
const string wordEnd("?=");
const size_t minWordLength = wordStart.length() + wordEnd.length();
@@ -690,6 +715,7 @@ word& word::operator=(const word& w)
{
m_buffer = w.m_buffer;
m_charset = w.m_charset;
+ m_lang = w.m_lang;
return (*this);
}
@@ -698,6 +724,7 @@ word& word::operator=(const string& s)
{
m_buffer = s;
m_charset = charset::getLocalCharset();
+ m_lang.clear();
return (*this);
}
@@ -708,18 +735,19 @@ void word::copyFrom(const component& other)
m_buffer = w.m_buffer;
m_charset = w.m_charset;
+ m_lang = w.m_lang;
}
bool word::operator==(const word& w) const
{
- return (m_charset == w.m_charset && m_buffer == w.m_buffer);
+ return (m_charset == w.m_charset && m_buffer == w.m_buffer && m_lang == w.m_lang);
}
bool word::operator!=(const word& w) const
{
- return (m_charset != w.m_charset || m_buffer != w.m_buffer);
+ return (m_charset != w.m_charset || m_buffer != w.m_buffer || m_lang != w.m_lang);
}
@@ -769,6 +797,18 @@ void word::setCharset(const charset& ch)
}
+const string word::getLanguage() const
+{
+ return m_lang;
+}
+
+
+void word::setLanguage(const string& lang)
+{
+ m_lang = lang;
+}
+
+
const string& word::getBuffer() const
{
return (m_buffer);
diff --git a/src/vmime/word.hpp b/src/vmime/word.hpp
index 4122228d..0e60225e 100644
--- a/src/vmime/word.hpp
+++ b/src/vmime/word.hpp
@@ -48,6 +48,7 @@ public:
word(const word& w);
word(const string& buffer); // Defaults to local charset
word(const string& buffer, const charset& charset);
+ word(const string& buffer, const charset& charset, const string& lang);
/** Return the raw data for this encoded word.
*
@@ -85,6 +86,20 @@ public:
*/
void setCharset(const charset& ch);
+ /** Return the language used in this word (optional).
+ * If not specified, the value is empty.
+ *
+ * @return language tag for this word, in the format specified
+ * by RFC-1766
+ */
+ const string getLanguage() const;
+
+ /** Set the language used in this word (optional).
+ *
+ * @param lang language tag, in the format specified by RFC-1766
+ */
+ void setLanguage(const string& lang);
+
/** Returns whether two words actually represent the same text,
* regardless of their charset.
*
@@ -194,6 +209,7 @@ private:
// in the specified "m_charset".
string m_buffer;
charset m_charset;
+ string m_lang;
};
diff --git a/src/vmime/wordEncoder.cpp b/src/vmime/wordEncoder.cpp
index 421a9ecd..b40f5371 100644
--- a/src/vmime/wordEncoder.cpp
+++ b/src/vmime/wordEncoder.cpp
@@ -226,7 +226,8 @@ wordEncoder::Encoding wordEncoder::getEncoding() const
// static
bool wordEncoder::isEncodingNeeded
- (const generationContext& ctx, const string& buffer, const charset& charset)
+ (const generationContext& ctx, const string& buffer,
+ const charset& charset, const string& lang)
{
if (!ctx.getInternationalizedEmailSupport())
{
@@ -250,6 +251,10 @@ bool wordEncoder::isEncodingNeeded
if (buffer.find("=?") != string::npos || buffer.find("?=") != string::npos)
return true;
+ // If a language is specified, force encoding
+ if (!lang.empty())
+ return true;
+
return false;
}
diff --git a/src/vmime/wordEncoder.hpp b/src/vmime/wordEncoder.hpp
index 6f652fa2..8abd3d3c 100644
--- a/src/vmime/wordEncoder.hpp
+++ b/src/vmime/wordEncoder.hpp
@@ -78,9 +78,11 @@ public:
* @param ctx generation context
* @param buffer buffer to analyze
* @param charset charset of the buffer
+ * @param lang language code, in the format specified by RFC-1766
* @return true if encoding is needed, false otherwise.
*/
- static bool isEncodingNeeded(const generationContext& ctx, const string& buffer, const charset& charset);
+ static bool isEncodingNeeded(const generationContext& ctx, const string& buffer,
+ const charset& charset, const string& lang);
/** Guess the best RFC-2047 encoding to use for the specified buffer.
*