Skip to content

Commit c887eb4

Browse files
committed
Merge branch 'prime'
2 parents 1cf4012 + 948fdc0 commit c887eb4

File tree

9 files changed

+62
-15
lines changed

9 files changed

+62
-15
lines changed

configure.ac

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
AC_INIT([gromox], [2.39])
1+
AC_INIT([gromox], [2.40])
22
AC_CONFIG_AUX_DIR([build-aux])
33
AC_CONFIG_MACRO_DIR([build-aux])
44
AC_PREFIX_DEFAULT([/usr])

doc/changelog.rst

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,20 @@
1+
Gromox 2.40 (2025-01-28)
2+
========================
3+
4+
Fixes:
5+
6+
* zcore: avoid unwrapping Content-Transfer-Encoding twice for
7+
clearsigned S/MIME
8+
* ews: calculate timezone offsets for local time only
9+
* ews: deserialize no-content XML tags as empty strings rather than as absence
10+
of the element
11+
12+
Enhancements:
13+
14+
* imap, pop3: multi-server capability, replacing direct disk I/O by network
15+
RPCs to the exmdb storage backend
16+
17+
118
Gromox 2.39 (2025-01-21)
219
========================
320

exch/emsmdb/message_object.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -313,7 +313,7 @@ static ec_error_t message_object_save2(message_object *pmessage, bool b_fai,
313313
pmessage->instance_id, pmsgctnt))
314314
return ecRpcFailed;
315315
uint32_t tmp_status = *mstatus | MSGSTATUS_IN_CONFLICT;
316-
const TAGGED_PROPVAL propbuff[] = {PR_MSG_STATUS, &tmp_status};
316+
const TAGGED_PROPVAL propbuff[] = {{PR_MSG_STATUS, &tmp_status}};
317317
const TPROPVAL_ARRAY tmp_propvals = {std::size(propbuff), deconst(propbuff)};
318318
PROBLEM_ARRAY tmp_problems;
319319
if (!message_object_set_properties_internal(pmessage,
@@ -324,7 +324,7 @@ static ec_error_t message_object_save2(message_object *pmessage, bool b_fai,
324324
pbin_pcl = common_util_pcl_merge(pbin_pcl, pbin_pcl1);
325325
if (pbin_pcl == nullptr)
326326
return ecRpcFailed;
327-
const TAGGED_PROPVAL propbuff[] = {PR_PREDECESSOR_CHANGE_LIST, pbin_pcl};
327+
const TAGGED_PROPVAL propbuff[] = {{PR_PREDECESSOR_CHANGE_LIST, pbin_pcl}};
328328
const TPROPVAL_ARRAY tmp_propvals = {std::size(propbuff), deconst(propbuff)};
329329
PROBLEM_ARRAY tmp_problems;
330330
if (!message_object_set_properties_internal(pmessage,

exch/emsmdb/oxcmsg.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -639,7 +639,7 @@ ec_error_t rop_setreadflags(uint8_t want_asynchronous, uint8_t read_flags,
639639
read_flags & rfClearReadFlag ? RELOP_NE : RELOP_EQ,
640640
PR_READ, {PR_READ, deconst(&fake_false)}
641641
};
642-
const RESTRICTION res_top = {RES_PROPERTY, deconst(&res_prop)};
642+
const RESTRICTION res_top = {RES_PROPERTY, {deconst(&res_prop)}};
643643
uint32_t table_id = 0, row_count = 0;
644644
auto username = plogon->readstate_user();
645645
if (!exmdb_client::load_content_table(plogon->dir, CP_ACP,

exch/ews/context.cpp

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1813,13 +1813,16 @@ void EWSContext::toContent(const std::string& dir, tCalendarItem& item, sShape&
18131813
shape.write(TAGGED_PROPVAL{PR_MESSAGE_CLASS, deconst("IPM.Appointment")});
18141814
int64_t startOffset = 0, endOffset = 0;
18151815
time_t startTime = 0, endTime = 0;
1816+
bool calcStartOffset, calcEndOffset = false;
18161817
if(item.Start) {
18171818
startTime = clock::to_time_t(item.Start.value().time);
18181819
startOffset = std::chrono::duration_cast<std::chrono::minutes>(item.Start.value().offset).count();
1820+
calcStartOffset = item.Start.value().needCalcOffset();
18191821
}
18201822
if(item.End) {
18211823
endTime = clock::to_time_t(item.End.value().time);
18221824
endOffset = std::chrono::duration_cast<std::chrono::minutes>(item.Start.value().offset).count();
1825+
calcEndOffset = item.Start.value().needCalcOffset();
18231826
}
18241827
// TODO handle no start and/or end times
18251828

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

2038-
// If the offsets of start or end times are not set, probably
2039-
// the client didn't send the offset information in date tags.
2040-
// Try to get the offset from the timezone definition.
2041-
if(startOffset == 0 || endOffset == 0)
2041+
// If the offsets of start or end times are 0 and
2042+
// the client didn't send the offset information in date tags,
2043+
// try to get the offset from the timezone definition.
2044+
if((startOffset == 0 && calcStartOffset) || (endOffset == 0 && calcEndOffset))
20422045
{
20432046
EXT_PULL ext_pull;
20442047
TIMEZONEDEFINITION tzdef;
20452048
ext_pull.init(buf->data(), buf->size(), alloc, EXT_FLAG_UTF16);
20462049
if(ext_pull.g_tzdef(&tzdef) != EXT_ERR_SUCCESS)
20472050
throw EWS::DispatchError(E3294);
2048-
startOffset = endOffset = offset_from_tz(&tzdef, startTime);
2051+
if(calcStartOffset)
2052+
startOffset = offset_from_tz(&tzdef, startTime);
2053+
if(calcEndOffset)
2054+
endOffset = offset_from_tz(&tzdef, endTime);
20492055
}
20502056
item.Start.value().offset = std::chrono::minutes(startOffset);
20512057
item.End.value().offset = std::chrono::minutes(endOffset);

exch/ews/serialization.hpp

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -131,9 +131,7 @@ struct ExplicitConvert<std::string>
131131
static tinyxml2::XMLError deserialize(const tinyxml2::XMLElement *xml, std::string &value)
132132
{
133133
const char* data = xml->GetText();
134-
if(!data)
135-
return tinyxml2::XML_NO_TEXT_NODE;
136-
value = data;
134+
value = data ? data : std::string("");
137135
return tinyxml2::XML_SUCCESS;
138136
}
139137

exch/ews/structures.cpp

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1194,6 +1194,24 @@ sTimePoint::sTimePoint(time_point tp, const tSerializableTimeZone& tz) :
11941194
/**
11951195
* @brief Create time point from date-time string
11961196
*
1197+
* As of 2025-01-27 we have identified 3 different datetime formats sent by
1198+
* the clients.
1199+
* Zulu time (UTC), no DST, no offset:
1200+
* `<t:Start>2024-04-29T19:30:00Z</t:Start>`
1201+
* With the offset information in datetime, additionally a timezone tag:
1202+
* `<t:Start>2024-11-27T13:00:00+01:00</t:Start>`
1203+
* `<t:StartTimeZone Id="W. Europe Standard Time"/>`
1204+
* `<t:EndTimeZone Id="W. Europe Standard Time"/>`
1205+
* Local time with a timezone tag, it's necessary to calculate the offset:
1206+
* `<t:Start>2024-09-25T09:00:00</t:Start>`
1207+
* ```
1208+
* <t:ExtendedProperty>
1209+
* <t:ExtendedFieldURI PropertyName="CalendarTimeZone" PropertySetId="A7B529B5-4B75-47A7-A24F-20743D6C55CD" PropertyType="String"/>
1210+
* <t:Value>Europe/Vienna</t:Value>
1211+
* </t:ExtendedProperty>
1212+
* ```
1213+
* `<t:MeetingTimeZone TimeZoneName="W. Europe Standard Time"/>`
1214+
*
11971215
* @throw DeserializationError Conversion failed
11981216
*
11991217
* @param Date-time string
@@ -1217,7 +1235,9 @@ sTimePoint::sTimePoint(const char* dtstr)
12171235
throw EWSError::ValueOutOfRange(E3152);
12181236
time = clock::from_time_t(timestamp);
12191237
time += std::chrono::duration_cast<time_point::duration>(std::chrono::duration<double>(seconds));
1220-
offset = std::chrono::minutes(60*tz_hour+(tz_hour < 0? -tz_min : tz_min));
1238+
offset = std::chrono::minutes(60 * (-tz_hour) + (tz_hour > 0 ? -tz_min : tz_min));
1239+
if(strlen(dtstr) == 19)
1240+
calcOffset = true;
12211241
}
12221242

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

1255+
/**
1256+
* @brief Whether it's necessary to calculate the offset from timezone
1257+
*/
1258+
bool sTimePoint::needCalcOffset() const
1259+
{return calcOffset;}
1260+
12351261
///////////////////////////////////////////////////////////////////////////////////////////////////
12361262
// Types implementation
12371263

exch/ews/structures.hpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -452,9 +452,11 @@ struct sTimePoint
452452

453453
static sTimePoint fromNT(uint64_t);
454454
uint64_t toNT() const;
455+
bool needCalcOffset() const;
455456

456457
time_point time{};
457458
std::chrono::minutes offset = std::chrono::minutes(0);
459+
bool calcOffset = false;
458460
};
459461

460462
///////////////////////////////////////////////////////////////////////////////////////////////////

mra/midb_agent.cpp

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -82,8 +82,6 @@ static void *midbag_scanwork(void *);
8282
static ssize_t read_line(int sockd, char *buff, size_t length);
8383
static int connect_midb(const char *host, uint16_t port);
8484

85-
static constexpr unsigned int POLLIN_SET =
86-
POLLRDNORM | POLLRDBAND | POLLIN | POLLHUP | POLLERR | POLLNVAL;
8785
std::atomic<size_t> g_midb_command_buffer_size{256 * 1024};
8886
static int g_conn_num;
8987
static gromox::atomic_bool g_notify_stop;

0 commit comments

Comments
 (0)