Skip to content

Commit

Permalink
Revert "oxcical: emit VTIMEZONE for events without PidLidAppointmentT…
Browse files Browse the repository at this point in the history
…imeZoneDefinitionStartDisplay"

This reverts commit 1cf586b, but
makes sure to keep the tzdesc fallback. Another testcase is added.

+--------------+--------------------+--------------------+
|              | Look at props for  | Look at props for  |
|              | recurring series   | single event       |
+==============+====================+====================+
| Before 1cf   | 1. tzdesc,tzstruct | 1. tzdefstart      |
|              | 2. tzdefrecur      |                    |
+--------------+--------------------+--------------------+
| After 1cf    | 1. tzdefrecur      | 1. tzdesc,tzstruct |
+--------------+--------------------+--------------------+
| OXCICAL says | 1. tzdefrecur      | 1. tzdefstart      |
|              | 2. tzdesc,tzstruct |                    |
+--------------+--------------------+--------------------+
| New          | 1. tzdefrecur      | 1. tzdefstart      |
|              | 2. tzdesc,tzstruct | 2. tzdesc,tzstruct |
+--------------+--------------------+--------------------+

Fixes: gromox-2.29-20-g1cf586b4b
References: DESK-2104, GXF-1766, GXF-1807, GXF-1819
  • Loading branch information
jengelh committed Sep 30, 2024
1 parent 1dc60a3 commit 31980f4
Show file tree
Hide file tree
Showing 3 changed files with 74 additions and 30 deletions.
15 changes: 8 additions & 7 deletions include/gromox/mapitags.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -1117,12 +1117,6 @@ using proptag_t = decltype(PR_NULL);
}

enum {
PidLidAttendeeCriticalChange = 0x0001,
PidLidGlobalObjectId = 0x0003, /* a.k.a. LID_GLOBAL_OBJID */
PidLidIsException = 0x000A,
PidLidStartRecurrenceTime = 0x000E,
PidLidOwnerCriticalChange = 0x001A,
PidLidCleanGlobalObjectId = 0x0023,
PidLidCategories = 0x2328,

/* PSETID_Address */
Expand Down Expand Up @@ -1205,10 +1199,17 @@ enum {
PidLidAppointmentTimeZoneDefinitionRecur = 0x8260,

/* PSETID_Meeting */
PidLidAttendeeCriticalChange = 0x0001,
PidLidWhere = 0x0002,
PidLidGlobalObjectId = 0x0003, /* a.k.a. LID_GLOBAL_OBJID */
PidLidIsSilent = 0x0004,
PidLidIsRecurring = 0x0005, /* object is associated with a recurring series object */
PidLidTimeZone = 0x000c,
PidLidIsException = 0x000A,
PidLidTimeZone = 0x000C,
PidLidStartRecurrenceTime = 0x000E,
PidLidMonthOfYearMask = 0x0017,
PidLidOwnerCriticalChange = 0x001A,
PidLidCleanGlobalObjectId = 0x0023,
PidLidMeetingType = 0x0026,

/* PSETID_Common */
Expand Down
45 changes: 22 additions & 23 deletions lib/mapi/oxcical.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3411,7 +3411,6 @@ static std::string oxcical_export_internal(const char *method, const char *tzid,
if (!get_propids(&pna, &propids) || propids.size() != pna.size())
return E_2201;

/* Cf. MS-OXCICAL v20240416 §2.1.3.1.1.1, "property: METHOD". */
auto num = pmsg->proplist.get<const uint32_t>(PR_MESSAGE_LOCALE_ID);
auto planguage = num != nullptr ? lcid_to_ltag(*num) : nullptr;
auto str = pmsg->proplist.get<const char>(PR_MESSAGE_CLASS);
Expand Down Expand Up @@ -3459,15 +3458,6 @@ static std::string oxcical_export_internal(const char *method, const char *tzid,
return fmt::format("W-2060: oxcical_export does not handle message class \"{}\"", str);
}
}

/*
* Cf. MS-OXCICAL v20240416: If the METHOD property of the VCALENDAR
* component is set to "COUNTER", then apptProposedStartWhole should be
* exported as a new DTSTART property. For other values of METHOD, the
* apptStartWhole of a Calendar object should be exported as DTSTART.
*
* NOTE: b_proposal is correctly set on COUNTER (see above).
*/
auto lnum = pmsg->proplist.get<const uint64_t>(PROP_TAG(PT_SYSTIME,
propids[b_proposal ? l_proposedstartwhole : l_startwhole]));
bool has_start_time = false;
Expand Down Expand Up @@ -3525,18 +3515,7 @@ static std::string oxcical_export_internal(const char *method, const char *tzid,
if (has_start_time && gmtime_r(&start_time, &tmp_tm) != nullptr)
year = tmp_tm.tm_year + 1900;

/*
* Cf. [MS-OXCICAL] v20240416 §2.1.3.1.1.19.1 "property: TZID":
* If the tzdefRecur, tzdefStartDisplay, or tzdefEndDisplay
* property is being exported as a VTIMEZONE, then the value of
* TZID must be derived from the KeyName field of the
* tzdefRecur structure.
*
* Note: There is no need to check tzdefStartDisplay or
* tzdefEndDisplay, as it is a MUST to use the KeyName of
* tzdefRecur.
*/
tzid = nullptr;
tzid = NULL;
if (b_recurrence) {
bin = pmsg->proplist.get<BINARY>(PROP_TAG(PT_BINARY, propids[l_tzdefrecur]));
if (bin != nullptr) {
Expand All @@ -3555,6 +3534,26 @@ static std::string oxcical_export_internal(const char *method, const char *tzid,
return "E-2208: export_timezone returned an unspecified error";
}
} else {
bin = pmsg->proplist.get<BINARY>(PROP_TAG(PT_BINARY, propids[l_tzdefstart]));
if (bin != nullptr)
bin = pmsg->proplist.get<BINARY>(PROP_TAG(PT_BINARY, propids[l_tzdefend]));
if (bin != nullptr) {
EXT_PULL ext_pull;
TIMEZONEDEFINITION tz_definition;
TIMEZONESTRUCT tz_struct;

ext_pull.init(bin->pb, bin->cb, alloc, 0);
if (ext_pull.g_tzdef(&tz_definition) != EXT_ERR_SUCCESS)
return "E-2209: PidLidAppointmentTimeZoneDefinitionEndDisplay contents not recognized";
tzid = tz_definition.keyname;
oxcical_convert_to_tzstruct(&tz_definition, &tz_struct);
ptz_component = oxcical_export_timezone(
pical, year - 1, tzid, &tz_struct);
if (ptz_component == nullptr)
return "E-2210: export_timezone returned an unspecified error";
}
}
if (ptz_component == nullptr) {
bin = pmsg->proplist.get<BINARY>(PROP_TAG(PT_BINARY, propids[l_tzstruct]));
tzid = pmsg->proplist.get<char>(PROP_TAG(PT_UNICODE, propids[l_tzdesc]));
if (bin != nullptr && tzid != nullptr) {
Expand All @@ -3567,7 +3566,7 @@ static std::string oxcical_export_internal(const char *method, const char *tzid,
ptz_component = oxcical_export_timezone(
pical, year - 1, tzid, &tz_struct);
if (ptz_component == nullptr)
return "E-2210: export_timezone returned an unspecified error";
return "E-2206: export_timezone returned an unspecified error";
}
}
}
Expand Down
44 changes: 44 additions & 0 deletions tests/oxcmail_ie.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -378,6 +378,49 @@ static void ical_export_1()
}
}

static void ical_export_2()
{
/* GXF-1819 */
const ie_name_entry ie_map[] = {
{0x809d, {MNID_ID, PSETID_Appointment, PidLidAppointmentStartWhole}},
{0x809e, {MNID_ID, PSETID_Appointment, PidLidAppointmentEndWhole}},
{0x80a5, {MNID_ID, PSETID_Appointment, PidLidAppointmentSubType}},
{0x80d2, {MNID_ID, PSETID_Appointment, PidLidAppointmentTimeZoneDefinitionStartDisplay}},
{0x80d3, {MNID_ID, PSETID_Appointment, PidLidAppointmentTimeZoneDefinitionEndDisplay}},
};
auto get_propids = [&](const PROPNAME_ARRAY *a, PROPID_ARRAY *i) {
return ie_get_propids(ie_map, std::size(ie_map), a, i);
};
static constexpr uint64_t v_start = 0x1db0f96441fb000, v_end = 0x1db105f6e897000;
static constexpr bool v_true = 1;
static const BINARY v_122 = {122, {reinterpret_cast<uint8_t *>(deconst("\x02\x01\x34\x00\x02\x00\x17\x00\x57\x00\x2e\x00\x20\x00\x45\x00\x75\x00\x72\x00\x6f\x00\x70\x00\x65\x00\x20\x00\x53\x00\x74\x00\x61\x00\x6e\x00\x64\x00\x61\x00\x72\x00\x64\x00\x20\x00\x54\x00\x69\x00\x6d\x00\x65\x00\x01\x00\x02\x01\x3e\x00\x02\x00\x41\x06\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\xc4\xff\xff\xff\x00\x00\x00\x00\xc4\xff\xff\xff\x00\x00\x0a\x00\x00\x00\x05\x00\x03\x00\x00\x00\x00\x00\x00\x00\x00\x00\x03\x00\x00\x00\x05\x00\x02\x00\x00\x00\x00\x00\x00\x00"))}};
const TAGGED_PROPVAL props[] = {
{PR_MESSAGE_CLASS, deconst("IPM.Appointment")},
{0x809d0040, deconst(&v_start)},
{0x809e0040, deconst(&v_end)},
{0x80a5000b, deconst(&v_true)},
{0x80d20102, deconst(&v_122)},
{0x80d30102, deconst(&v_122)},
};
fprintf(stderr, "=== ical_export_2\n");
const MESSAGE_CONTENT msgctnt = {{std::size(props), deconst(props)}};
ical icalout;
if (!oxcical_export(&msgctnt, icalout, "x500org", malloc, get_propids, nullptr)) {
fprintf(stderr, "oxcical_export failed\n");
return;
}
std::string icstr;
if (icalout.serialize(icstr) != ecSuccess) {
fprintf(stderr, "ical_serialize failed\n");
return;
}
if (strstr(icstr.c_str(), "DTSTART;VALUE=DATE;TZID=W. Europe Standard Time:20240926") == nullptr ||
strstr(icstr.c_str(), "DTEND;VALUE=DATE;TZID=W. Europe Standard Time:20240927") == nullptr) {
printf("%s\n", icstr.c_str());
fprintf(stderr, "FAILED. Substrings DTSTART/20240926 and DTEND/20240927 not found.\n");
}
}

int main()
{
auto ee_get_user_ids = [](const char *, unsigned int *, unsigned int *, enum display_type *) -> BOOL { return false; };
Expand All @@ -394,5 +437,6 @@ int main()
select_parts_4();
select_parts_5();
ical_export_1();
ical_export_2();
return EXIT_SUCCESS;
}

0 comments on commit 31980f4

Please sign in to comment.