Skip to content

Commit 936751f

Browse files
committed
oxcical: try to handle ICS files with missing VTIMEZONE blocks
References: GXH-149
1 parent 5d19470 commit 936751f

File tree

1 file changed

+46
-22
lines changed

1 file changed

+46
-22
lines changed

lib/mapi/oxcical.cpp

Lines changed: 46 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -164,7 +164,7 @@ static bool oxcical_parse_vtsubcomponent(const ical_component &sub,
164164
return true;
165165
}
166166

167-
static bool oxcical_parse_tzdefinition(const ical_component &vt,
167+
static bool oxcical_tzcom_to_def(const ical_component &vt,
168168
TIMEZONEDEFINITION *ptz_definition)
169169
{
170170
int i;
@@ -281,8 +281,7 @@ static void oxcical_convert_to_tzstruct(
281281
ptz_struct->daylightyear = ptz_struct->daylightdate.year;
282282
}
283283

284-
static bool oxcical_tzdefinition_to_binary(
285-
TIMEZONEDEFINITION *ptz_definition,
284+
static bool oxcical_tzdefinition_to_binary(const TIMEZONEDEFINITION *ptz_definition,
286285
uint16_t tzrule_flags, BINARY *pbin)
287286
{
288287
EXT_PUSH ext_push;
@@ -637,16 +636,30 @@ static const ical_component *oxcical_find_vtimezone(const ical &pical, const cha
637636
return nullptr;
638637
}
639638

639+
static bool oxcical_take_tzbin(bool b_dtstart, const BINARY &tmp_bin,
640+
namemap &phash, uint16_t *plast_propid, MESSAGE_CONTENT *pmsg)
641+
{
642+
PROPERTY_NAME propname = {MNID_ID, PSETID_Appointment, b_dtstart ?
643+
PidLidAppointmentTimeZoneDefinitionStartDisplay :
644+
PidLidAppointmentTimeZoneDefinitionEndDisplay};
645+
if (namemap_add(phash, *plast_propid, std::move(propname)) != 0)
646+
return false;
647+
if (pmsg->proplist.set(PROP_TAG(PT_BINARY, *plast_propid), &tmp_bin) != ecSuccess)
648+
return false;
649+
(*plast_propid) ++;
650+
return true;
651+
}
652+
640653
static bool oxcical_parse_tzdisplay(bool b_dtstart, const ical_component &tzcom,
641654
namemap &phash, uint16_t *plast_propid, MESSAGE_CONTENT *pmsg)
642655
{
643-
BINARY tmp_bin;
644-
TIMEZONEDEFINITION tz_definition;
645656
TZRULE rules_buff[MAX_TZRULE_NUMBER];
657+
TIMEZONEDEFINITION tz_definition;
658+
BINARY tmp_bin;
646659
uint8_t bin_buff[MAX_TZDEFINITION_LENGTH];
647660

648661
tz_definition.prules = rules_buff;
649-
if (!oxcical_parse_tzdefinition(tzcom, &tz_definition))
662+
if (!oxcical_tzcom_to_def(tzcom, &tz_definition))
650663
return false;
651664
if (tz_definition.crules == 0) {
652665
mlog(LV_DEBUG, "Rejecting conversion of iCal to MAPI object: no sensible TZ rules found (e.g. RFC 5545 §3.6.5 VTIMEZONE without STANDARD/DAYLIGHT not permitted)");
@@ -657,15 +670,7 @@ static bool oxcical_parse_tzdisplay(bool b_dtstart, const ical_component &tzcom,
657670
if (!oxcical_tzdefinition_to_binary(&tz_definition,
658671
TZRULE_FLAG_EFFECTIVE_TZREG, &tmp_bin))
659672
return false;
660-
PROPERTY_NAME propname = {MNID_ID, PSETID_Appointment, b_dtstart ?
661-
PidLidAppointmentTimeZoneDefinitionStartDisplay :
662-
PidLidAppointmentTimeZoneDefinitionEndDisplay};
663-
if (namemap_add(phash, *plast_propid, std::move(propname)) != 0)
664-
return false;
665-
if (pmsg->proplist.set(PROP_TAG(PT_BINARY, *plast_propid), &tmp_bin) != ecSuccess)
666-
return false;
667-
(*plast_propid) ++;
668-
return true;
673+
return oxcical_take_tzbin(b_dtstart, tmp_bin, phash, plast_propid, pmsg);
669674
}
670675

671676
static bool oxcical_parse_recurring_timezone(const ical_component &tzcom,
@@ -679,7 +684,7 @@ static bool oxcical_parse_recurring_timezone(const ical_component &tzcom,
679684
uint8_t bin_buff[MAX_TZDEFINITION_LENGTH];
680685

681686
tz_definition.prules = rules_buff;
682-
if (!oxcical_parse_tzdefinition(tzcom, &tz_definition))
687+
if (!oxcical_tzcom_to_def(tzcom, &tz_definition))
683688
return false;
684689
auto piline = tzcom.get_line("TZID");
685690
if (piline == nullptr)
@@ -2054,13 +2059,32 @@ static const char *oxcical_import_internal(const char *str_zone, const char *met
20542059
const ical_component *ptz_component = nullptr;
20552060
if (ptzid != nullptr) {
20562061
ptz_component = oxcical_find_vtimezone(pical, ptzid);
2057-
if (ptz_component == nullptr) {
2058-
mlog(LV_ERR, "E-2070: %s: timezone \"%s\" not found", __func__, znul(ptzid));
2059-
return "Used timezone was not declared";
2062+
if (ptz_component != nullptr) {
2063+
if (!oxcical_parse_tzdisplay(true, *ptz_component, phash,
2064+
&last_propid, pmsg))
2065+
return "E-2195: oxcical_parse_tzdisplay returned an unspecified error";
2066+
} else {
2067+
/*
2068+
* As per RFC 5545 §3.2.19, """An individual "VTIMEZONE" calendar
2069+
* component MUST be specified for each unique "TZID" parameter
2070+
* value""".
2071+
*/
2072+
2073+
/* Some final heroic efforts */
2074+
auto def = ianatz_to_tzdef(ptzid);
2075+
if (def == nullptr)
2076+
def = wintz_to_tzdef(ptzid);
2077+
if (def == nullptr) {
2078+
mlog(LV_ERR, "E-2070: %s: timezone \"%s\" not found", __func__, ptzid);
2079+
return "Used timezone was not declared";
2080+
}
2081+
mlog(LV_DEBUG, "D-5324: synthesized data for TZID \"%s\" from internal db", ptzid);
2082+
BINARY bin;
2083+
bin.cb = def->size();
2084+
bin.pc = deconst(def->data());
2085+
if (!oxcical_take_tzbin(true, bin, phash, &last_propid, pmsg))
2086+
return "E-5323: oxcical_parse_tzdef returned an unspecified error";
20602087
}
2061-
if (!oxcical_parse_tzdisplay(true, *ptz_component, phash,
2062-
&last_propid, pmsg))
2063-
return "E-2195: oxcical_parse_tzdisplay returned an unspecified error";
20642088
}
20652089

20662090
time_t start_time = 0, end_time = 0;

0 commit comments

Comments
 (0)