From bbec3e9f0e7eeb846410316170bae28236814aa4 Mon Sep 17 00:00:00 2001 From: Christian Boltz Date: Thu, 20 Oct 2016 20:15:15 +0000 Subject: [PATCH 01/10] pacrypt(): allow switching between dovecot:* password schemes Dovecot password hashes include a {SCHEME} prefix, so it's possible to switch the scheme while still accepting passwords hashed using the previous dovecot:* scheme. This patch adds the code needed to find out the used hashing scheme from the hash and ensures it gets used to validate the password. Patch by Aaron Lindsay (sent to the ML) git-svn-id: https://svn.code.sf.net/p/postfixadmin/code/trunk@1875 a1433add-5e2c-0410-b055-b7f2511e0802 --- CHANGELOG.TXT | 7 +++++++ functions.inc.php | 4 +++- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.TXT b/CHANGELOG.TXT index 60df8eac..1c7820ab 100644 --- a/CHANGELOG.TXT +++ b/CHANGELOG.TXT @@ -9,6 +9,13 @@ # Last update: # $Id$ +Changes since the 3.0.1 release +------------------------------------------------- + + - allow switching between dovecot:* password schemes while still accepting + passwords hashed using the previous dovecot:* scheme + - FetchmailHandler: use a valid date as default for 'date' + Version 3.0.1 - 2016/09/19 - SVN r1870 ------------------------------------------------- diff --git a/functions.inc.php b/functions.inc.php index c06dba6c..5ff4ab32 100644 --- a/functions.inc.php +++ b/functions.inc.php @@ -933,7 +933,9 @@ function pacrypt ($pw, $pw_db="") { elseif (preg_match("/^dovecot:/", $CONF['encrypt'])) { $split_method = preg_split ('/:/', $CONF['encrypt']); - $method = strtoupper($split_method[1]); # TODO: if $pw_db starts with {method}, change $method accordingly + $method = strtoupper($split_method[1]); + # If $pw_db starts with {method}, change $method accordingly + if (!empty($pw_db) && preg_match('/^\{([A-Z0-9.-]+)\}.+/', $pw_db, $method_matches)) { $method = $method_matches[1]; } if (! preg_match("/^[A-Z0-9.-]+$/", $method)) { die("invalid dovecot encryption method"); } # TODO: check against a fixed list? # if (strtolower($method) == 'md5-crypt') die("\$CONF['encrypt'] = 'dovecot:md5-crypt' will not work because dovecotpw generates a random salt each time. Please use \$CONF['encrypt'] = 'md5crypt' instead."); # $crypt_method = preg_match ("/.*-CRYPT$/", $method); From 4c2ff84d528cd0171c768afb9d2cd5471872b258 Mon Sep 17 00:00:00 2001 From: Christian Boltz Date: Thu, 20 Oct 2016 21:26:13 +0000 Subject: [PATCH 02/10] upate wiki links mediawiki -> SF wiki git-svn-id: https://svn.code.sf.net/p/postfixadmin/code/trunk@1876 a1433add-5e2c-0410-b055-b7f2511e0802 --- INSTALL.TXT | 2 +- config.inc.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/INSTALL.TXT b/INSTALL.TXT index 5f12e5ae..fa7bc361 100644 --- a/INSTALL.TXT +++ b/INSTALL.TXT @@ -22,7 +22,7 @@ If you need to setup Postfix to be able to handle Virtual Domains and Virtual Users check out: - the PostfixAdmin documentation in the DOCUMENTS/ directory - - our wiki at http://sourceforge.net/apps/mediawiki/postfixadmin/ + - our wiki at https://sourceforge.net/p/postfixadmin/wiki/ There are also lots of HOWTOs around the web. Be warned that many of them (even those listed below) may be outdated or incomplete. diff --git a/config.inc.php b/config.inc.php index 91b52a53..11639295 100644 --- a/config.inc.php +++ b/config.inc.php @@ -262,7 +262,7 @@ function maildir_name_hook($domain, $user) { PostfixAdmin, but it does not create it in the database. You have to do that yourself. Please follow the naming policy for custom database fields and tables on - http://sourceforge.net/apps/mediawiki/postfixadmin/index.php?title=Custom_fields + https://sourceforge.net/p/postfixadmin/wiki/Custom_fields/ to avoid clashes with future versions of PostfixAdmin. See initStruct() in the *Handler class for the default $struct. From bd28fcb19481f0fc520b821f14c660235922ec2b Mon Sep 17 00:00:00 2001 From: Christian Boltz Date: Mon, 31 Oct 2016 20:15:31 +0000 Subject: [PATCH 03/10] AliasHandler: restrict __is_mailbox subquery to allowed domains This improves performance on setups with lots of mailboxes. Well, except for superadmins because restricting to "all domains" doesn't really help ;-) Thanks to gygy for reporting this on IRC, and for testing the patch. git-svn-id: https://svn.code.sf.net/p/postfixadmin/code/trunk@1877 a1433add-5e2c-0410-b055-b7f2511e0802 --- CHANGELOG.TXT | 2 ++ model/AliasHandler.php | 1 + 2 files changed, 3 insertions(+) diff --git a/CHANGELOG.TXT b/CHANGELOG.TXT index 1c7820ab..b5e10cba 100644 --- a/CHANGELOG.TXT +++ b/CHANGELOG.TXT @@ -12,6 +12,8 @@ Changes since the 3.0.1 release ------------------------------------------------- + - AliasHandler: restrict mailbox subquery to allowed domains to improve + performance (except for superadmins ;-) on setups with lots of mailboxes - allow switching between dovecot:* password schemes while still accepting passwords hashed using the previous dovecot:* scheme - FetchmailHandler: use a valid date as default for 'date' diff --git a/model/AliasHandler.php b/model/AliasHandler.php index 23e08234..b6b0e4c8 100644 --- a/model/AliasHandler.php +++ b/model/AliasHandler.php @@ -48,6 +48,7 @@ class AliasHandler extends PFAHandler { ' SELECT 1 as __is_mailbox, username as __mailbox_username ' . ' FROM ' . table_by_key('mailbox') . ' WHERE username IS NOT NULL ' . + ' AND ' . db_in_clause($this->domain_field, $this->allowed_domains) . ' ) AS __mailbox ON __mailbox_username = address' ), 'goto_mailbox' => pacol( $mbgoto, $mbgoto,$mbgoto,'bool', 'pEdit_alias_forward_and_store' , '' , 0, /*options*/ '', From 16e14076213d1b4cf5e9a0d6c31a0ac0f6b80967 Mon Sep 17 00:00:00 2001 From: Christian Boltz Date: Tue, 1 Nov 2016 15:45:45 +0000 Subject: [PATCH 04/10] db_where_clause(): allow NULL and NOTNULL searchmodes git-svn-id: https://svn.code.sf.net/p/postfixadmin/code/trunk@1878 a1433add-5e2c-0410-b055-b7f2511e0802 --- functions.inc.php | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/functions.inc.php b/functions.inc.php index 5ff4ab32..e60a853a 100644 --- a/functions.inc.php +++ b/functions.inc.php @@ -1688,11 +1688,13 @@ function db_in_clause($field, $values) { * db_where_clause * Action: builds and returns a WHERE clause for database queries. All given conditions will be AND'ed. * Call: db_where_clause (array $conditions, array $struct) - * param array $conditios: array('field' => 'value', 'field2' => 'value2, ...) + * param array $condition: array('field' => 'value', 'field2' => 'value2, ...) * param array $struct - field structure, used for automatic bool conversion * param string $additional_raw_where - raw sniplet to include in the WHERE part - typically needs to start with AND * param array $searchmode - operators to use (=, <, > etc.) - defaults to = if not specified for a field (see * $allowed_operators for available operators) + * Note: the $searchmode operator will only be used if a $condition for that field is set. + * This also means you'll need to set a (dummy) condition for NULL and NOTNULL. */ function db_where_clause($condition, $struct, $additional_raw_where = '', $searchmode = array()) { if (!is_array($condition)) { @@ -1705,7 +1707,7 @@ function db_where_clause($condition, $struct, $additional_raw_where = '', $searc die('db_where_cond: parameter $struct is not an array!'); } - $allowed_operators = explode(' ', '< > >= <= = != <> CONT LIKE'); + $allowed_operators = explode(' ', '< > >= <= = != <> CONT LIKE NULL NOTNULL'); $where_parts = array(); $having_parts = array(); @@ -1726,7 +1728,15 @@ function db_where_clause($condition, $struct, $additional_raw_where = '', $searc die('db_where_clause: Invalid searchmode for ' . $field); } } - $querypart = $field . $operator . "'" . escape_string($value) . "'"; + + if ($operator == "NULL") { + $querypart = $field . ' IS NULL'; + } elseif ($operator == "NOTNULL") { + $querypart = $field . ' IS NOT NULL'; + } else { + $querypart = $field . $operator . "'" . escape_string($value) . "'"; + } + if($struct[$field]['select'] != '') { $having_parts[$field] = $querypart; } else { From 40b4fdf61c97639e506dcc0007bb27c2b91cc7f0 Mon Sep 17 00:00:00 2001 From: Christian Boltz Date: Tue, 1 Nov 2016 17:43:32 +0000 Subject: [PATCH 05/10] beautify alias list search parameters AliasHandler: - initStruct(): handle __mailbox_username as separate field (needed to make it searchable) - split off a condition_ignore_mailboxes() function (used in getList() and getPagebrowser()) to add '__mailbox_username IS NULL' to the search condition array. Also, make sure $condition can be an array (preferred) or a string with a raw query list-virtual.php: - hand over a search array instead of a raw query git-svn-id: https://svn.code.sf.net/p/postfixadmin/code/trunk@1879 a1433add-5e2c-0410-b055-b7f2511e0802 --- list-virtual.php | 9 ++++----- model/AliasHandler.php | 31 +++++++++++++++++++------------ 2 files changed, 23 insertions(+), 17 deletions(-) diff --git a/list-virtual.php b/list-virtual.php index 89bd432f..0087999c 100644 --- a/list-virtual.php +++ b/list-virtual.php @@ -136,10 +136,9 @@ $table_alias = table_by_key('alias'); $table_mailbox = table_by_key('mailbox'); if (count($search) == 0 || !isset($search['_'])) { - $list_param = "domain='$fDomain'"; + $search_alias = array('domain' => $fDomain); } else { - $searchterm = escape_string($search['_']); - $list_param = "(address LIKE '%$searchterm%' OR goto LIKE '%$searchterm%')"; + $search_alias = array('_' => $search['_']); } $handler = new AliasHandler(0, $admin_username); @@ -153,8 +152,8 @@ $alias_data['struct']['goto_mailbox']['display_in_list'] = 0; # not useful/defin $alias_data['struct']['on_vacation']['display_in_list'] = 0; $alias_data['msg']['show_simple_search'] = False; # hide search box -$handler->getList($list_param, array(), $page_size, $fDisplay); -$pagebrowser_alias = $handler->getPagebrowser($list_param, array()); +$handler->getList($search_alias, array(), $page_size, $fDisplay); +$pagebrowser_alias = $handler->getPagebrowser($search_alias, array()); $tAlias = $handler->result(); diff --git a/model/AliasHandler.php b/model/AliasHandler.php index b6b0e4c8..ac7b04a7 100644 --- a/model/AliasHandler.php +++ b/model/AliasHandler.php @@ -42,7 +42,7 @@ class AliasHandler extends PFAHandler { /*options*/ '', /*not_in_db*/ 0, /*dont_write_to_db*/ 1, - /*select*/ 'coalesce(__is_mailbox,0) as is_mailbox, __mailbox_username', + /*select*/ 'coalesce(__is_mailbox,0) as is_mailbox', # __mailbox_username is unused, but needed as workaround for a MariaDB bug /*extrafrom*/ 'LEFT JOIN ( ' . ' SELECT 1 as __is_mailbox, username as __mailbox_username ' . @@ -50,6 +50,7 @@ class AliasHandler extends PFAHandler { ' WHERE username IS NOT NULL ' . ' AND ' . db_in_clause($this->domain_field, $this->allowed_domains) . ' ) AS __mailbox ON __mailbox_username = address' ), + '__mailbox_username' => pacol( 0, 0, 1, 'vtxt', '' , '' , 0), # filled via is_mailbox 'goto_mailbox' => pacol( $mbgoto, $mbgoto,$mbgoto,'bool', 'pEdit_alias_forward_and_store' , '' , 0, /*options*/ '', /*not_in_db*/ 1 ), # read_from_db_postprocess() sets the value @@ -304,22 +305,28 @@ class AliasHandler extends PFAHandler { return $db_result; } - public function getList($condition, $searchmode = array(), $limit=-1, $offset=-1) { + private function condition_ignore_mailboxes($condition, $searchmode) { # only list aliases that do not belong to mailboxes - # TODO: breaks if $condition is an array - if ($condition != '') { - $condition = " AND ( $condition ) "; + if (is_array($condition)) { + $condition['__mailbox_username'] = 1; + $searchmode['__mailbox_username'] = 'NULL'; + } else { + if ($condition != '') { + $condition = " ( $condition ) AND "; + } + $condition = " $condition __mailbox_username IS NULL "; } - return parent::getList( "__mailbox_username IS NULL $condition", $searchmode, $limit, $offset); + return array($condition, $searchmode); + } + + public function getList($condition, $searchmode = array(), $limit=-1, $offset=-1) { + list($condition, $searchmode) = $this->condition_ignore_mailboxes($condition, $searchmode); + return parent::getList($condition, $searchmode, $limit, $offset); } public function getPagebrowser($condition, $searchmode = array()) { - # only list aliases that do not belong to mailboxes - # TODO: breaks if $condition is an array - if ($condition != '') { - $condition = " AND ( $condition ) "; - } - return parent::getPagebrowser( "__mailbox_username IS NULL $condition", $searchmode); + list($condition, $searchmode) = $this->condition_ignore_mailboxes($condition, $searchmode); + return parent::getPagebrowser($condition, $searchmode); } From 74130b478ce27fd875d96256b66e4616039d557f Mon Sep 17 00:00:00 2001 From: Christian Boltz Date: Tue, 1 Nov 2016 19:31:41 +0000 Subject: [PATCH 06/10] list-virtual.tpl: add missing "download as CSV" for mailboxes Reported by Dan in https://sourceforge.net/p/postfixadmin/patches/135/ Note that I'm using a completely different patch to fix it. git-svn-id: https://svn.code.sf.net/p/postfixadmin/code/trunk@1880 a1433add-5e2c-0410-b055-b7f2511e0802 --- templates/list-virtual.tpl | 1 + 1 file changed, 1 insertion(+) diff --git a/templates/list-virtual.tpl b/templates/list-virtual.tpl index cb04c2da..8218e738 100644 --- a/templates/list-virtual.tpl +++ b/templates/list-virtual.tpl @@ -64,6 +64,7 @@ {if $tCanAddMailbox}
{$PALANG.add_mailbox}
{/if} +

{$PALANG.download_csv} {/if} {if $CONF.show_status===YES && $CONF.show_status_key===YES}

From 516f1c68f408b3e713aed9203ff8238d72e3a9fb Mon Sep 17 00:00:00 2001 From: Christian Boltz Date: Tue, 1 Nov 2016 20:31:52 +0000 Subject: [PATCH 07/10] upgrade_1835_mysql: fix defaults for both date fields at once Doing it in two steps fails, see comment by Gabor 'Morc' KORMOS on https://sourceforge.net/p/postfixadmin/bugs/5/ Note: This is an exception from the "never change an existing upgrade_*() function" rule because a) the result doesn't change for people where it worked and b) it will continue here anyway for people who had upgrade problems git-svn-id: https://svn.code.sf.net/p/postfixadmin/code/trunk@1881 a1433add-5e2c-0410-b055-b7f2511e0802 --- upgrade.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/upgrade.php b/upgrade.php index 95e52eee..dd9a84a1 100644 --- a/upgrade.php +++ b/upgrade.php @@ -1619,14 +1619,14 @@ function upgrade_1824_sqlite() { function upgrade_1835_mysql() { # change default values for existing datetime fields with a 0000-00-00 default to {DATETIME} - foreach (array('admin', 'alias', 'alias_domain', 'domain', 'mailbox', 'domain_admins', 'vacation') as $table_to_change) { + foreach (array('domain_admins', 'vacation') as $table_to_change) { $table = table_by_key($table_to_change); db_query_parsed("ALTER TABLE `$table` CHANGE `created` `created` {DATETIME}"); } foreach (array('admin', 'alias', 'alias_domain', 'domain', 'mailbox') as $table_to_change) { $table = table_by_key($table_to_change); - db_query_parsed("ALTER TABLE `$table` CHANGE `modified` `modified` {DATETIME}"); + db_query_parsed("ALTER TABLE `$table` CHANGE `created` `created` {DATETIME}, CHANGE `modified` `modified` {DATETIME}"); } $table = table_by_key('log'); From 9ba7118d7b4dae81b29abe8b037b44c0a573a970 Mon Sep 17 00:00:00 2001 From: Christian Boltz Date: Wed, 9 Nov 2016 20:41:24 +0000 Subject: [PATCH 08/10] AliasHandler: restrict mailbox subquery to requested domains set_is_mailbox_extrafrom() restricts the domain list to the domain that needs to be checked (in normal list-virtual listing one domain), and is then used to restore the default extrafrom. This improves the performance for most usecases even for superadmins. Note: Search mode might still be slow because by default it searches in all domains available to the admin. git-svn-id: https://svn.code.sf.net/p/postfixadmin/code/trunk@1882 a1433add-5e2c-0410-b055-b7f2511e0802 --- CHANGELOG.TXT | 4 ++-- model/AliasHandler.php | 49 +++++++++++++++++++++++++++++++++--------- 2 files changed, 41 insertions(+), 12 deletions(-) diff --git a/CHANGELOG.TXT b/CHANGELOG.TXT index b5e10cba..db796b90 100644 --- a/CHANGELOG.TXT +++ b/CHANGELOG.TXT @@ -12,8 +12,8 @@ Changes since the 3.0.1 release ------------------------------------------------- - - AliasHandler: restrict mailbox subquery to allowed domains to improve - performance (except for superadmins ;-) on setups with lots of mailboxes + - AliasHandler: restrict mailbox subquery to allowed and specified domains + to improve performance on setups with lots of mailboxes - allow switching between dovecot:* password schemes while still accepting passwords hashed using the previous dovecot:* scheme - FetchmailHandler: use a valid date as default for 'date' diff --git a/model/AliasHandler.php b/model/AliasHandler.php index ac7b04a7..4d446f86 100644 --- a/model/AliasHandler.php +++ b/model/AliasHandler.php @@ -42,14 +42,8 @@ class AliasHandler extends PFAHandler { /*options*/ '', /*not_in_db*/ 0, /*dont_write_to_db*/ 1, - /*select*/ 'coalesce(__is_mailbox,0) as is_mailbox', - # __mailbox_username is unused, but needed as workaround for a MariaDB bug - /*extrafrom*/ 'LEFT JOIN ( ' . - ' SELECT 1 as __is_mailbox, username as __mailbox_username ' . - ' FROM ' . table_by_key('mailbox') . - ' WHERE username IS NOT NULL ' . - ' AND ' . db_in_clause($this->domain_field, $this->allowed_domains) . - ' ) AS __mailbox ON __mailbox_username = address' ), + /*select*/ 'coalesce(__is_mailbox,0) as is_mailbox' ), + /*extrafrom set via set_is_mailbox_extrafrom() */ '__mailbox_username' => pacol( 0, 0, 1, 'vtxt', '' , '' , 0), # filled via is_mailbox 'goto_mailbox' => pacol( $mbgoto, $mbgoto,$mbgoto,'bool', 'pEdit_alias_forward_and_store' , '' , 0, /*options*/ '', @@ -66,8 +60,37 @@ class AliasHandler extends PFAHandler { array('select' => '1 as _can_delete') ), # read_from_db_postprocess() updates the value # aliases listed in $CONF[default_aliases] are read-only for domain admins if $CONF[special_alias_control] is NO. ); + + $this->set_is_mailbox_extrafrom(); } + /* + * set $this->struct['is_mailbox']['extrafrom'] based on the search conditions. + * If a listing for a specific domain is requested, optimize the subquery to only return mailboxes from that domain. + * This doesn't change the result of the main query, but improves the performance a lot on setups with lots of mailboxes. + * When using this function to optimize the is_mailbox extrafrom, don't forget to reset it to the default value + * (all domains for this admin) afterwards. + */ + private function set_is_mailbox_extrafrom($condition=array(), $searchmode=array()) { + $extrafrom = 'LEFT JOIN ( ' . + ' SELECT 1 as __is_mailbox, username as __mailbox_username ' . + ' FROM ' . table_by_key('mailbox') . + ' WHERE username IS NOT NULL '; + + if(isset($condition['domain']) && !isset($searchmode['domain']) && in_array($condition['domain'], $this->allowed_domains)) { + # listing for a specific domain, so restrict subquery to that domain + $extrafrom .= ' AND ' . db_in_clause($this->domain_field, array($condition['domain'])); + } else { + # restrict subquery to all domains accessible to this admin + $extrafrom .= ' AND ' . db_in_clause($this->domain_field, $this->allowed_domains); + } + + $extrafrom .= ' ) AS __mailbox ON __mailbox_username = address'; + + $this->struct['is_mailbox']['extrafrom'] = $extrafrom; + } + + protected function initMsg() { $this->msg['error_already_exists'] = 'email_address_already_exists'; $this->msg['error_does_not_exist'] = 'alias_does_not_exist'; @@ -321,12 +344,18 @@ class AliasHandler extends PFAHandler { public function getList($condition, $searchmode = array(), $limit=-1, $offset=-1) { list($condition, $searchmode) = $this->condition_ignore_mailboxes($condition, $searchmode); - return parent::getList($condition, $searchmode, $limit, $offset); + $this->set_is_mailbox_extrafrom($condition, $searchmode); + $result = parent::getList($condition, $searchmode, $limit, $offset); + $this->set_is_mailbox_extrafrom(); # reset to default + return $result; } public function getPagebrowser($condition, $searchmode = array()) { list($condition, $searchmode) = $this->condition_ignore_mailboxes($condition, $searchmode); - return parent::getPagebrowser($condition, $searchmode); + $this->set_is_mailbox_extrafrom($condition, $searchmode); + $result = parent::getPagebrowser($condition, $searchmode); + $this->set_is_mailbox_extrafrom(); # reset to default + return $result; } From bd8e0e3ae31826184dbad1854bf2175454e06781 Mon Sep 17 00:00:00 2001 From: David Goodwin Date: Tue, 20 Dec 2016 08:39:18 +0000 Subject: [PATCH 09/10] apparently dead columns - thanks to uz@musoftware.de git-svn-id: https://svn.code.sf.net/p/postfixadmin/code/trunk@1883 a1433add-5e2c-0410-b055-b7f2511e0802 --- model/VacationHandler.php | 2 -- 1 file changed, 2 deletions(-) diff --git a/model/VacationHandler.php b/model/VacationHandler.php index 61394bcf..27081d82 100644 --- a/model/VacationHandler.php +++ b/model/VacationHandler.php @@ -21,7 +21,6 @@ class VacationHandler extends PFAHandler { 'body' => pacol( 1, 1, 0, 'text', 'pUsersVacation_body' , '' , '' ), 'activefrom' => pacol( 1, 1, 1, 'text', 'pUsersVacation_activefrom' , '' , '' ), 'activeuntil' => pacol( 1, 1, 1, 'text', 'pUsersVacation_activeuntil' , '' , '' ), - 'cache' => pacol( 0, 0, 0, 'text', '' , '' , '' ), # leftover from 2.2 'active' => pacol( 1, 1, 1, 'bool', 'active' , '' , 1 ), 'created' => pacol( 0, 0, 1, 'ts', 'created' , '' ), 'modified' => pacol( 0, 0, 1, 'ts', 'last_modified' , '' ), @@ -180,7 +179,6 @@ class VacationHandler extends PFAHandler { 'active' => db_get_boolean(true), 'activefrom' => $activeFrom, 'activeuntil' => $activeUntil, - 'cache' => '', ); // is there an entry in the vacaton table for the user, or do we need to insert? From 2f2db5949a8349d5df09a8f10c24a2568f424fdc Mon Sep 17 00:00:00 2001 From: David Goodwin Date: Wed, 21 Dec 2016 10:25:58 +0000 Subject: [PATCH 10/10] fix date formatting in non-english languages, thanks to uz@musoftware.de git-svn-id: https://svn.code.sf.net/p/postfixadmin/code/trunk@1884 a1433add-5e2c-0410-b055-b7f2511e0802 --- model/PFAHandler.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/model/PFAHandler.php b/model/PFAHandler.php index 0a47b466..8e1c5a46 100644 --- a/model/PFAHandler.php +++ b/model/PFAHandler.php @@ -565,7 +565,7 @@ abstract class PFAHandler { $no = escape_string(Config::lang('NO')); if (db_pgsql()) { - $formatted_date = "TO_DATE(text(###KEY###), '" . escape_string(Config::Lang('dateformat_pgsql')) . "')"; + $formatted_date = "TO_CHAR(###KEY###, '" . escape_string(Config::Lang('dateformat_pgsql')) . "')"; # $base64_decode = "DECODE(###KEY###, 'base64')"; } elseif (db_sqlite()) { $formatted_date = "strftime(###KEY###, '" . escape_string(Config::Lang('dateformat_mysql')) . "')";