summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorPatrick Ohly <patrick.ohly@intel.com>2014-05-06 12:13:19 +0200
committerPatrick Ohly <patrick.ohly@intel.com>2014-05-06 12:13:19 +0200
commit8a7356c1518aca405eb29ddf12a2d1052375da68 (patch)
tree2f13d347adcdc133d9adf3be4f26539186601a46 /src
parentab9ee87347c3efeb98cfb2b46549272a070f04d3 (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.cpp60
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