Skip to content

Commit

Permalink
tests: add testcase for DESK-2104
Browse files Browse the repository at this point in the history
References: DESK-2104, GXF-1819
  • Loading branch information
jengelh committed Sep 30, 2024
1 parent 5ccb750 commit 1dc60a3
Show file tree
Hide file tree
Showing 2 changed files with 78 additions and 1 deletion.
9 changes: 8 additions & 1 deletion include/gromox/mapitags.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -1170,27 +1170,32 @@ enum {
PidLidTaskFRecurring = 0x8126,

/* PSETID_Appointment */
PidLidSendMeetingAsIcal = 0x8200,
PidLidAppointmentSequence = 0x8201,
PidLidBusyStatus = 0x8205,
PidLidLocation = 0x8208,
PidLidAppointmentReplyTime = 0x8220,
PidLidAppointmentStartWhole = 0x820D,
PidLidAppointmentEndWhole = 0x820E,
PidLidAppointmentDuration = 0x8213,
PidLidAppointmentSubType = 0x8215,
PidLidAppointmentRecur = 0x8216,
PidLidAppointmentStateFlags = 0x8217,
PidLidResponseStatus = 0x8218,
PidLidAppointmentReplyTime = 0x8220,
PidLidRecurring = 0x8223, /* this object is a recurring series */
PidLidIntendedBusyStatus = 0x8224,
PidLidExceptionReplaceTime = 0x8228,
PidLidFInvited = 0x8229,
PidLidAppointmentReplyName = 0x8230,
PidLidRecurrenceType = 0x8231,
PidLidRecurrencePattern = 0x8232,
PidLidTimeZoneStruct = 0x8233,
PidLidTimeZoneDescription = 0x8234,
PidLidClipStart = 0x8235,
PidLidClipEnd = 0x8236,
PidLidAllAttendeesString = 0x8238,
PidLidToAttendeesString = 0x823B,
PidLidCcAttendeesString = 0x823C,
PidLidAppointmentProposedStartWhole = 0x8250,
PidLidAppointmentProposedEndWhole = 0x8251,
PidLidAppointmentCounterProposal = 0x8257,
Expand All @@ -1211,9 +1216,11 @@ enum {
PidLidReminderTime = 0x8502,
PidLidReminderSet = 0x8503,
PidLidPrivate = 0x8506,
PidLidSideEffects = 0x8510,
PidLidSmartNoAttach = 0x8514,
PidLidCommonStart = 0x8516,
PidLidCommonEnd = 0x8517,
PidLidTaskMode = 0x8518,
PidLidFlagRequest = 0x8530,
PidLidMileage = 0x8534, // not in ms-oxprops
PidLidBilling = 0x8535,
Expand Down
70 changes: 70 additions & 0 deletions tests/oxcmail_ie.cpp
Original file line number Diff line number Diff line change
@@ -1,16 +1,25 @@
// SPDX-License-Identifier: AGPL-3.0-or-later
// SPDX-FileCopyrightText: 2024 grommunio GmbH
// This file is part of Gromox.
#include <algorithm>
#include <cassert>
#include <cstdlib>
#include <libHX/string.h>
#include <gromox/element_data.hpp>
#include <gromox/ical.hpp>
#include <gromox/oxcmail.hpp>
#include <gromox/util.hpp>
#include "../tools/staticnpmap.cpp"
#undef assert
#define assert(x) do { if (!(x)) { printf("%s failed\n", #x); return EXIT_FAILURE; } } while (false)

namespace {
struct ie_name_entry {
uint16_t proptag;
PROPERTY_NAME pn;
};
}

using namespace gromox;
using namespace gi_dump;
using mptr = std::unique_ptr<message_content, mc_delete>;
Expand Down Expand Up @@ -137,6 +146,19 @@ static char data_5[] =
"///2\r\n"
"--0--\r\n";

static BOOL ie_get_propids(const ie_name_entry *map, size_t mapsize,
const PROPNAME_ARRAY *pna, PROPID_ARRAY *idp)
{
auto &id = *idp;
id.resize(pna->size());
for (size_t i = 0; i < pna->size(); ++i) {
auto row = std::find_if(&map[0], &map[mapsize],
[&](const auto &r) -> bool { return r.pn == (*pna)[i]; });
id[i] = row != &map[mapsize] ? row->proptag : 0;
}
return TRUE;
}

static int select_parts_1()
{
/*
Expand Down Expand Up @@ -309,6 +331,53 @@ static int select_parts_5()
return 0;
}

static void ical_export_1()
{
/*
* DESK-2104: Old Zarafa imports (which lack some TZ fields) shifted by
* one day in some MUA, attributed to DTSTART not containing any TZID
* but just UTC.
*/
const ie_name_entry ie_map[] = {
{0x809d, {MNID_ID, PSETID_Appointment, PidLidAppointmentStartWhole}},
{0x809e, {MNID_ID, PSETID_Appointment, PidLidAppointmentEndWhole}},
{0x80b8, {MNID_ID, PSETID_Appointment, PidLidTimeZoneStruct}},
{0x80b9, {MNID_ID, PSETID_Appointment, PidLidTimeZoneDescription}},
};
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_time = 0x1dabd02f773da00;
const BINARY bin_48{48, {reinterpret_cast<uint8_t *>(deconst("\304\377\377\377\0\0\0\0\304\377\377\377\0\0\0\0\n\0\0\0\5\0\3\0\0\0\0\0\0\0\0\0\0\0\3\0\0\0\5\0\2\0\0\0\0\0\0\0"))}};
const TAGGED_PROPVAL props[] = {
{PR_MESSAGE_CLASS, deconst("IPM.Appointment")},
{PR_START_DATE, deconst(&v_time)},
{PR_END_DATE, deconst(&v_time)},
{0x809d0040, deconst(&v_time)},
{0x809e0040, deconst(&v_time)},
{0x80b80102, deconst(&bin_48)},
{0x80b9001f, deconst("Europe/Vienna")},
};
const MESSAGE_CONTENT msgctnt = {{std::size(props), deconst(props)}};
ical icalout;
fprintf(stderr, "=== ical_export_1\n");
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;
}
constexpr char needle[] = "DTSTART;TZID=Europe/Vienna:20240612T215900";
auto ptr = strstr(icstr.c_str(), needle);
if (ptr == nullptr) {
printf("%s\n", icstr.c_str());
fprintf(stderr, "FAILED. Substrings Europe/215900 not found.\n");
}
}

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

0 comments on commit 1dc60a3

Please sign in to comment.