Skip to content

Commit 446ef67

Browse files
committed
Zipdownload: Fix message date time zone in mbox export (#10147)
Also fix anytodatetime() so it does not change the timezone of the returned object.
1 parent c20f653 commit 446ef67

5 files changed

Lines changed: 18 additions & 22 deletions

File tree

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ This file includes only changes we consider noteworthy for users, admins and plu
1010
- Stricter recognition of an Ajax request (#10118)
1111
- Allow cidr (subnets) in proxy_whitelist (#7103)
1212
- Password: Added Stalwart driver (#10114)
13+
- Zipdownload: Fix message date time zone in mbox export (#10147)
1314
- Fix regression where some data url images could get ignored/lost (#10128)
1415
- Fix SVG Animate FUNCIRI Attribute Bypass — Remote Image Loading via fill/filter/stroke [CVE-2026-35545]
1516

plugins/zipdownload/composer.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
"type": "roundcube-plugin",
44
"description": "Adds an option to download all attachments to a message in one zip file, when a message has multiple attachments. Also allows the download of a selection of messages in one zip file. Supports mbox and maildir format.",
55
"license": "GPL-3.0-or-later",
6-
"version": "3.5",
6+
"version": "3.6",
77
"authors": [
88
{
99
"name": "Thomas Bruederli",

plugins/zipdownload/zipdownload.php

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -258,16 +258,15 @@ private function _download_messages($messageset)
258258
$from = preg_replace('/\s/', '-', $from);
259259

260260
// Received (internal) date
261-
$date = rcube_utils::anytodatetime($headers->internaldate, $timezone);
261+
$date = rcube_utils::anytodatetime($headers->internaldate);
262262
if ($date) {
263-
$date = $date->format(self::MBOX_DATE_FORMAT);
263+
$date = $date->setTimezone($timezone)->format(self::MBOX_DATE_FORMAT);
264+
} else {
265+
$date = new \DateTime('now', $timezone);
264266
}
265267

266268
// Mbox format header (RFC4155)
267-
$header = sprintf("From %s %s\r\n",
268-
$from ?: 'MAILER-DAEMON',
269-
$date ?: ''
270-
);
269+
$header = sprintf("From %s %s\r\n", $from ?: 'MAILER-DAEMON', $date);
271270

272271
$messages[$uid . ':' . $mbox] = $header;
273272
} else { // maildir

program/lib/Roundcube/rcube_utils.php

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1176,7 +1176,7 @@ public static function strtotime($date, $timezone = null)
11761176
* Date parsing function that turns the given value into a DateTime object
11771177
*
11781178
* @param \DateTime|string $date A date
1179-
* @param \DateTimeZone $timezone Timezone to use for DateTime object
1179+
* @param \DateTimeZone $timezone A timezone to use for the result, if not included in the input
11801180
*
11811181
* @return \DateTime|false DateTime object or False on failure
11821182
*/
@@ -1202,10 +1202,7 @@ public static function anytodatetime($date, $timezone = null)
12021202
// try our advanced strtotime() method
12031203
if (!$dt && ($timestamp = self::strtotime($date, $timezone))) {
12041204
try {
1205-
$dt = new \DateTime('@' . $timestamp);
1206-
if ($timezone) {
1207-
$dt->setTimezone($timezone);
1208-
}
1205+
$dt = $timezone ? new \DateTime('@' . $timestamp, $timezone) : new \DateTime('@' . $timestamp);
12091206
} catch (\Exception $e) {
12101207
// ignore
12111208
}

tests/Framework/UtilsTest.php

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -799,22 +799,21 @@ public function test_anytodatetime()
799799
*/
800800
public function test_anytodatetime_timezone()
801801
{
802+
date_default_timezone_set('America/New_York');
803+
802804
$tz = new \DateTimeZone('Europe/Helsinki');
803805
$test = [
804-
'Jan 1st 2014 +0800' => '2013-12-31 18:00', // result in target timezone
805-
'Jan 1st 14 45:42' => '2014-01-01 00:00', // force fallback to rcube_utils::strtotime()
806-
'Jan 1st 2014 UK' => '2014-01-01 00:00',
807-
'1520587800' => '2018-03-09 11:30', // unix timestamp conversion
806+
'Jan 1st 2014 +0800' => '2014-01-01 00:00 +08:00',
807+
'Jan 1st 14 45:42' => '2013-12-31 22:00 +00:00', // force fallback to rcube_utils::strtotime()
808+
'Jan 1st 2014 UK' => '2013-12-31 22:00 +00:00',
809+
'2026-05-12 13:14:15.000000 Europe/Warsaw' => '2026-05-12 13:14 Europe/Warsaw',
810+
'1520587800' => '2018-03-09 09:30 +00:00', // unix timestamp conversion
808811
'Invalid date' => false,
809812
];
810813

811-
foreach ($test as $datetime => $ts) {
814+
foreach ($test as $datetime => $expected) {
812815
$result = \rcube_utils::anytodatetime($datetime, $tz);
813-
if ($result) {
814-
// move to target timezone for comparison
815-
$result->setTimezone($tz);
816-
}
817-
$this->assertSame($ts, $result ? $result->format('Y-m-d H:i') : false, "Error parsing date: {$datetime}");
816+
$this->assertSame($expected, $result ? $result->format('Y-m-d H:i e') : false, "Error parsing date: {$datetime}");
818817
}
819818
}
820819

0 commit comments

Comments
 (0)