summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPatrick Ohly <patrick.ohly@intel.com>2010-09-29 18:12:58 +0200
committerPatrick Ohly <patrick.ohly@intel.com>2010-09-29 18:12:58 +0200
commitc3a18d8e0bc97fc663f5da4f45228ff7a85f0039 (patch)
treed40096bad206e09f3abc8a4ae150e7f266bb7181
parent24ca8ce6c102b2bc5e657a7d336f7dfcac266e3b (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.cpp67
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)