diff options
author | Patrick Ohly <patrick.ohly@intel.com> | 2014-05-06 12:13:19 +0200 |
---|---|---|
committer | Patrick Ohly <patrick.ohly@intel.com> | 2014-05-06 12:13:19 +0200 |
commit | 8a7356c1518aca405eb29ddf12a2d1052375da68 (patch) | |
tree | 2f13d347adcdc133d9adf3be4f26539186601a46 /src | |
parent | ab9ee87347c3efeb98cfb2b46549272a070f04d3 (diff) |
MIME parser + encoder: no backslash quoting in parameter values
RFC 2425 (MIME DIR) and RFC 6350 (vCard) do not describe backslash
escaping for special characters in parameter values. Only the more
limited quoted-string (double quotes at start and end, no line breaks,
no double quotes inside value) is specified.
The following two examples both contain a literal backslash:
URL;X-ABLabel="Custom-label6 Backslash \":http://custom.com
X-ABRELATEDNAMES;X-ABLabel="custom-label5 Umlaut รค Semicolon ; Backslash \ end of label":custom relationship
This commit limits backslash escaping to parsing and generating
property values. Backslashs in parameters are stored literally during
parsing. A quoted string parameter value is used for every value that
is more complex than alphanumeric plus underscore and hyphen.
In particular spaces (while allowed in unquoted values) are only
generated as part of quoted strings because the Evolution Data Server
parser had problems with them (fixed in EDS 3.10).
Diffstat (limited to 'src')
-rw-r--r-- | src/sysync/mimedirprofile.cpp | 60 |
1 files changed, 42 insertions, 18 deletions
diff --git a/src/sysync/mimedirprofile.cpp b/src/sysync/mimedirprofile.cpp index a1f88b8..83acbca 100644 --- a/src/sysync/mimedirprofile.cpp +++ b/src/sysync/mimedirprofile.cpp @@ -2359,6 +2359,34 @@ sInt16 TMimeDirProfileHandler::generateValue( } // - val is now translated enum (or original value if value does not match any enum text) valsiz+=val.size(); + // We have two choices for parameter values: + // - quoted string in double quotes + // - a simple string without + // + // Line breaks and control characters are not supported + // either way; the backslash escape mechanism is not used + // unless explicitly specified otherwise for specific + // parameters (like TYPE). + // + // We pick the simple string option only if the value + // contains only alphanumeric characters plus hyphen and + // underscore. Spaces are allowed by the RFC, but are + // known to cause issues in other parsers (EDS before + // 3.10) unless used in a quoted string, therefore we + // are more conservative than the RFC. + bool quotedstring = false; + if (aParamValue) { + for (const char *p=val.c_str();(c=*p)!=0;p++) { + if (!(isalnum(c) || + c == '-' || + c == '_')) { + quotedstring = true; + outval+='"'; + break; + } + } + } + // perform escaping and determine need for encoding bool spaceonly = true; bool firstchar = true; @@ -2380,24 +2408,26 @@ sInt16 TMimeDirProfileHandler::generateValue( // escape reserved chars switch (c) { case '"': - if (firstchar && aParamValue && aMimeMode==mimo_standard) goto do_escape; // if param value starts with a double quote, we need to escape it because param value can be in double-quote-enclosed form + if (aParamValue) { c = '\''; goto add_char; } // replace double quotes with single quotes + // if (firstchar && aParamValue && aMimeMode==mimo_standard) goto do_escape; // if param value starts with a double quote, we need to escape it because param value can be in double-quote-enclosed form goto add_char; // otherwise, just add case ',': // in MIME-DIR, always escape commas, in pre-MIME-DIR only if usage in value list requires it - if (!aCommaEscape && aMimeMode==mimo_old) goto add_char; + if ((!aCommaEscape && aMimeMode==mimo_old) || quotedstring) goto add_char; goto do_escape; case ':': // always escape colon in parameters - if (!aParamValue) goto add_char; + if (!aParamValue || quotedstring) goto add_char; goto do_escape; case '\\': + if (quotedstring) goto add_char; // Backslash must always be escaped // - for MIMO-old: at least Nokia 9210 does it this way // - for MIME-DIR: specified in the standard goto do_escape; case ';': // in MIME-DIR, always escape semicolons, in pre-MIME-DIR only in parameters and structured values - if (!aParamValue && !aStructured && aMimeMode==mimo_old) goto add_char; + if ((!aParamValue && !aStructured && aMimeMode==mimo_old) || quotedstring) goto add_char; do_escape: if (!aEscapeOnlyLF) { // escape chars with backslash @@ -2408,6 +2438,7 @@ sInt16 TMimeDirProfileHandler::generateValue( // ignore returns break; case '\n': + if (quotedstring) { c = ' '; goto add_char; } // quote linefeeds if (aMimeMode==mimo_old) { if (aEncoding==enc_none) { @@ -2435,6 +2466,12 @@ sInt16 TMimeDirProfileHandler::generateValue( break; } } // for all chars in val item + + // terminate quoted string parameter value + if (quotedstring) { + outval+='"'; + } + // go to next item in the val list (if any) if (*lp!=0) { // more items in the list @@ -3710,7 +3747,7 @@ bool TMimeDirProfileHandler::parseValue( break; } // check for escaped chars - if (c=='\\') { + if (!aParamValue && c=='\\') { p++; c=*p; if (!c) break; // half escape sequence, ignore @@ -3914,19 +3951,6 @@ bool TMimeDirProfileHandler::parseProperty( else { // not within double quoted value if (c==':' || c==';') break; // end of value - // check escaped characters - if (c=='\\') { - // escape char, do not check next char for end-of-value (but DO NOT expand \-escaped chars here!!) - vp=nextunfolded(vp,aMimeMode); - c=*vp; // get next - if (c) { - val+='\\'; // keep the escaped sequence for later when value is actually processed! - } - else { - // half-finished escape at end of value, ignore - break; - } - } } val+=c; // cancel QP softbreaks if encoding is already switched to QP at this point |