From e160e48069f9d1409f1f2977edc86ae3c2c611c7 Mon Sep 17 00:00:00 2001 From: Aleksander Machniak Date: Mon, 3 Apr 2017 12:06:23 +0200 Subject: [PATCH] Fix undesired effects when postgres database uses different timezone than PHP host (#5708) Allow passing DateTime variables as query arguments. Their value will be converted to date/time input string in format specific to the database type (with timezone on postgres). --- CHANGELOG | 1 + program/lib/Roundcube/rcube_db.php | 9 ++++++++- program/lib/Roundcube/rcube_db_oracle.php | 4 ++++ program/lib/Roundcube/rcube_db_pgsql.php | 15 +++++++++++++++ program/lib/Roundcube/rcube_user.php | 4 ++-- 5 files changed, 30 insertions(+), 3 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index 7112ace19..93c768953 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -27,6 +27,7 @@ CHANGELOG Roundcube Webmail - Fix XSS issue in handling of a style tag inside of an svg element [CVE-2017-6820] - Fix bug where settings/upload.inc could not be used by plugins (#5694) - Fix regression in LDAP fuzzy search where it always used prefix search instead (#5713) +- Fix undesired effects when postgres database uses different timezone than PHP host (#5708) RELEASE 1.3-beta ---------------- diff --git a/program/lib/Roundcube/rcube_db.php b/program/lib/Roundcube/rcube_db.php index 9cfdcaee8..2e4d01fdf 100644 --- a/program/lib/Roundcube/rcube_db.php +++ b/program/lib/Roundcube/rcube_db.php @@ -47,6 +47,8 @@ class rcube_db // column/table quotes 'identifier_start' => '"', 'identifier_end' => '"', + // date/time input format + 'datetime_format' => 'Y-m-d H:i:s', ); const DEBUG_LINE_LENGTH = 4096; @@ -818,6 +820,10 @@ class rcube_db return 'NULL'; } + if ($input instanceof DateTime) { + return $this->quote($input->format($this->options['datetime_format'])); + } + if ($type == 'ident') { return $this->quote_identifier($input); } @@ -970,10 +976,11 @@ class rcube_db * @param int $timestamp Unix timestamp * * @return string Date string in db-specific format + * @deprecated */ public function fromunixtime($timestamp) { - return date("'Y-m-d H:i:s'", $timestamp); + return $this->quote(date($this->options['datetime_format'], $timestamp)); } /** diff --git a/program/lib/Roundcube/rcube_db_oracle.php b/program/lib/Roundcube/rcube_db_oracle.php index 846fa27fa..fb1cd2351 100644 --- a/program/lib/Roundcube/rcube_db_oracle.php +++ b/program/lib/Roundcube/rcube_db_oracle.php @@ -327,6 +327,10 @@ class rcube_db_oracle extends rcube_db return 'NULL'; } + if ($input instanceof DateTime) { + return $this->quote($input->format($this->options['datetime_format'])); + } + if ($type == 'ident') { return $this->quote_identifier($input); } diff --git a/program/lib/Roundcube/rcube_db_pgsql.php b/program/lib/Roundcube/rcube_db_pgsql.php index aa7809370..d0d707a4a 100644 --- a/program/lib/Roundcube/rcube_db_pgsql.php +++ b/program/lib/Roundcube/rcube_db_pgsql.php @@ -28,6 +28,21 @@ class rcube_db_pgsql extends rcube_db { public $db_provider = 'postgres'; + /** + * Object constructor + * + * @param string $db_dsnw DSN for read/write operations + * @param string $db_dsnr Optional DSN for read only operations + * @param bool $pconn Enables persistent connections + */ + public function __construct($db_dsnw, $db_dsnr = '', $pconn = false) + { + parent::__construct($db_dsnw, $db_dsnr, $pconn); + + // use date/time input format with timezone spec. + $this->options['datetime_format'] = 'c'; + } + /** * Driver-specific configuration of database connection * diff --git a/program/lib/Roundcube/rcube_user.php b/program/lib/Roundcube/rcube_user.php index 32679ead9..ad442436c 100644 --- a/program/lib/Roundcube/rcube_user.php +++ b/program/lib/Roundcube/rcube_user.php @@ -503,10 +503,10 @@ class rcube_user $this->db->query( "UPDATE " . $this->db->table_name('users', true) - . " SET `failed_login` = " . $this->db->fromunixtime($failed_login->format('U')) + . " SET `failed_login` = ?" . ", `failed_login_counter` = " . ($counter ?: "`failed_login_counter` + 1") . " WHERE `user_id` = ?", - $this->ID); + $failed_login, $this->ID); } }