diff options
author | Patrick Ohly <patrick.ohly@intel.com> | 2010-09-29 18:12:58 +0200 |
---|---|---|
committer | Patrick Ohly <patrick.ohly@intel.com> | 2010-09-29 18:12:58 +0200 |
commit | c3a18d8e0bc97fc663f5da4f45228ff7a85f0039 (patch) | |
tree | d40096bad206e09f3abc8a4ae150e7f266bb7181 | |
parent | 24ca8ce6c102b2bc5e657a7d336f7dfcac266e3b (diff) |
vtimezone: fixed handling of TZID with special characterslibsynthesis_3.4.0.6+syncevolution-1-0-99-7
The following is a valid VCALENDAR:
BEGIN:VCALENDAR
...
BEGIN:VTIMEZONE
TZID:(UTC) Dublin\, Edinburgh\, Lisbon\, London
...
END:VTIMEZONE
BEGIN:VEVENT
...
SUMMARY;LANGUAGE=en-US:All-hands
DTSTART;TZID="(UTC) Dublin, Edinburgh, Lisbon, London":20100823T140000
DTEND;TZID="(UTC) Dublin, Edinburgh, Lisbon, London":20100823T150000
...
The parser in vtimezone.cpp did not unescape the \, when extracting
the VTIMEZONE definition. Therefore later on, the TZID in DTSTART and
DTEND could not be looked up.
RFC 2445 defines the backslash escape mechanism for all properties
with text as value, which is TZID and TZNAME. This patch implements
unescaping those, which fixes the problem above.
It also adds escaping these special characters. In practice, this is
typically not needed, because vtimezone.cpp replaces the original TZID
with a generated one that is composed of the builtin aliases for the
different offsets against GMT.
-rw-r--r-- | src/sysync/vtimezone.cpp | 67 |
1 files changed, 63 insertions, 4 deletions
diff --git a/src/sysync/vtimezone.cpp b/src/sysync/vtimezone.cpp index 60a9232..67ba156 100644 --- a/src/sysync/vtimezone.cpp +++ b/src/sysync/vtimezone.cpp @@ -92,7 +92,66 @@ const char* VTZ_OFROM = "TZOFFSETFROM"; const char* VTZ_OTO = "TZOFFSETTO"; const char* VTZ_NAME = "TZNAME"; +/*! + * escapes newline ('\n'), comma, semicolon and backslash itself with backslash, + * according to RFC 2445 "4.3.1 Text" value definition + */ +static string escapeText(const string &str) +{ + string res; + res.reserve(str.size() * 110 / 100); + + for (size_t i = 0; i < str.size(); i++) { + switch (str[i]) { + case '\n': + res += "\\n"; + break; + case '\\': + case ',': + case ';': + res += '\\'; + // no break! + default: + res += str[i]; + break; + } + } + + return res; +} + +/*! + * reverses escapeText(); in addition, accepts arbitrary characters + * after backslash and replaces them with that character + */ +static string unescapeText(const string &str) +{ + string res; + res.reserve(str.size()); + + for (size_t i = 0; i < str.size(); i++) { + switch (str[i]) { + case '\\': + i++; + if (i < str.size()) { + switch (str[i]) { + case 'n': + res += '\n'; + break; + default: + res += str[i]; + break; + } + } + break; + default: + res += str[i]; + break; + } + } + return res; +} /*! RRULE2toInternal, using RType * Converts vCalendar 2.0 RRULE string into internal recurrence representation @@ -290,7 +349,7 @@ static bool GetTZInfo( cAppCharP aText, st= VValue( a, VTZ_START ); // - start time string of= VValue( a, VTZ_OFROM ); // - tz offset from string ot= VValue( a, VTZ_OTO ); // - tz offset to - cName= VValue( a, VTZ_NAME ); // - tz name + cName= unescapeText( VValue( a, VTZ_NAME ) ); // - tz name if (ISO8601StrToTimestamp( st.c_str(), dtstart, tctx )==0) return false; if (!Get_Bias( of,ot, cBias )) return false; @@ -438,7 +497,7 @@ bool VTIMEZONEtoTZEntry( const char* aText, // VTIMEZONE string to be parsed else t.biasDST= dBias - t.bias; // t.biasDST WILL be calculated here // get TZID as found in VTIMEZONE - t.name = VValue( aText, VTZ_ID ); + t.name = unescapeText( VValue( aText, VTZ_ID ) ); return success; } // VTIMEZONEtoTZEntry @@ -607,7 +666,7 @@ static string GenerateTZInfo( tz_entry t, if (withDST) s+= Property( VTZ_RR, rTxt ); s+= FromTo ( aFrom,aTo ); if (withDST && - !aName.empty()) s+= Property( VTZ_NAME, aName ); + !aName.empty()) s+= Property( VTZ_NAME, escapeText( aName ) ); return Encapsuled( value, s ); } // GenerateTZInfo @@ -671,7 +730,7 @@ bool internalToVTIMEZONE( timecontext_t aContext, } // at least one STANDARD or DAYLIGHT info is mandatory - aText= Property ( VTZ_ID, tzn ) + + aText= Property ( VTZ_ID, escapeText( tzn ) ) + GenerateTZInfo( t, VTZ_STD, id, t.std, y_std, t_plus,t.bias, g, aLogP ); if (withDST) |