Skip to content

Commit

Permalink
Merge branch 'prime'
Browse files Browse the repository at this point in the history
  • Loading branch information
jengelh committed Jan 28, 2025
2 parents 1cf4012 + 93d9a6a commit 090568e
Show file tree
Hide file tree
Showing 4 changed files with 41 additions and 9 deletions.
16 changes: 11 additions & 5 deletions exch/ews/context.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1813,13 +1813,16 @@ void EWSContext::toContent(const std::string& dir, tCalendarItem& item, sShape&
shape.write(TAGGED_PROPVAL{PR_MESSAGE_CLASS, deconst("IPM.Appointment")});
int64_t startOffset = 0, endOffset = 0;
time_t startTime = 0, endTime = 0;
bool calcStartOffset, calcEndOffset = false;
if(item.Start) {
startTime = clock::to_time_t(item.Start.value().time);
startOffset = std::chrono::duration_cast<std::chrono::minutes>(item.Start.value().offset).count();
calcStartOffset = item.Start.value().needCalcOffset();
}
if(item.End) {
endTime = clock::to_time_t(item.End.value().time);
endOffset = std::chrono::duration_cast<std::chrono::minutes>(item.Start.value().offset).count();
calcEndOffset = item.Start.value().needCalcOffset();
}
// TODO handle no start and/or end times

Expand Down Expand Up @@ -2035,17 +2038,20 @@ void EWSContext::toContent(const std::string& dir, tCalendarItem& item, sShape&
shape.write(NtAppointmentTimeZoneDefinitionEndDisplay,
TAGGED_PROPVAL{PT_BINARY, temp_bin});

// If the offsets of start or end times are not set, probably
// the client didn't send the offset information in date tags.
// Try to get the offset from the timezone definition.
if(startOffset == 0 || endOffset == 0)
// If the offsets of start or end times are 0 and
// the client didn't send the offset information in date tags,
// try to get the offset from the timezone definition.
if((startOffset == 0 && calcStartOffset) || (endOffset == 0 && calcEndOffset))
{
EXT_PULL ext_pull;
TIMEZONEDEFINITION tzdef;
ext_pull.init(buf->data(), buf->size(), alloc, EXT_FLAG_UTF16);
if(ext_pull.g_tzdef(&tzdef) != EXT_ERR_SUCCESS)
throw EWS::DispatchError(E3294);
startOffset = endOffset = offset_from_tz(&tzdef, startTime);
if(calcStartOffset)
startOffset = offset_from_tz(&tzdef, startTime);
if(calcEndOffset)
endOffset = offset_from_tz(&tzdef, endTime);
}
item.Start.value().offset = std::chrono::minutes(startOffset);
item.End.value().offset = std::chrono::minutes(endOffset);
Expand Down
4 changes: 1 addition & 3 deletions exch/ews/serialization.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -131,9 +131,7 @@ struct ExplicitConvert<std::string>
static tinyxml2::XMLError deserialize(const tinyxml2::XMLElement *xml, std::string &value)
{
const char* data = xml->GetText();
if(!data)
return tinyxml2::XML_NO_TEXT_NODE;
value = data;
value = data ? data : std::string("");
return tinyxml2::XML_SUCCESS;
}

Expand Down
28 changes: 27 additions & 1 deletion exch/ews/structures.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1194,6 +1194,24 @@ sTimePoint::sTimePoint(time_point tp, const tSerializableTimeZone& tz) :
/**
* @brief Create time point from date-time string
*
* As of 2025-01-27 we have identified 3 different datetime formats sent by
* the clients.
* Zulu time (UTC), no DST, no offset:
* `<t:Start>2024-04-29T19:30:00Z</t:Start>`
* With the offset information in datetime, additionally a timezone tag:
* `<t:Start>2024-11-27T13:00:00+01:00</t:Start>`
* `<t:StartTimeZone Id="W. Europe Standard Time"/>`
* `<t:EndTimeZone Id="W. Europe Standard Time"/>`
* Local time with a timezone tag, it's necessary to calculate the offset:
* `<t:Start>2024-09-25T09:00:00</t:Start>`
* ```
* <t:ExtendedProperty>
* <t:ExtendedFieldURI PropertyName="CalendarTimeZone" PropertySetId="A7B529B5-4B75-47A7-A24F-20743D6C55CD" PropertyType="String"/>
* <t:Value>Europe/Vienna</t:Value>
* </t:ExtendedProperty>
* ```
* `<t:MeetingTimeZone TimeZoneName="W. Europe Standard Time"/>`
*
* @throw DeserializationError Conversion failed
*
* @param Date-time string
Expand All @@ -1217,7 +1235,9 @@ sTimePoint::sTimePoint(const char* dtstr)
throw EWSError::ValueOutOfRange(E3152);
time = clock::from_time_t(timestamp);
time += std::chrono::duration_cast<time_point::duration>(std::chrono::duration<double>(seconds));
offset = std::chrono::minutes(60*tz_hour+(tz_hour < 0? -tz_min : tz_min));
offset = std::chrono::minutes(60 * (-tz_hour) + (tz_hour > 0 ? -tz_min : tz_min));
if(strlen(dtstr) == 19)
calcOffset = true;
}

/**
Expand All @@ -1232,6 +1252,12 @@ sTimePoint sTimePoint::fromNT(uint64_t timestamp)
uint64_t sTimePoint::toNT() const
{return rop_util_unix_to_nttime(time-offset);}

/**
* @brief Whether it's necessary to calculate the offset from timezone
*/
bool sTimePoint::needCalcOffset() const
{return calcOffset;}

///////////////////////////////////////////////////////////////////////////////////////////////////
// Types implementation

Expand Down
2 changes: 2 additions & 0 deletions exch/ews/structures.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -452,9 +452,11 @@ struct sTimePoint

static sTimePoint fromNT(uint64_t);
uint64_t toNT() const;
bool needCalcOffset() const;

time_point time{};
std::chrono::minutes offset = std::chrono::minutes(0);
bool calcOffset = false;
};

///////////////////////////////////////////////////////////////////////////////////////////////////
Expand Down

0 comments on commit 090568e

Please sign in to comment.