mirror of
https://github.com/postfixadmin/postfixadmin.git
synced 2024-09-19 19:22:14 +02:00
Merge remote-tracking branch 'svnexport/master'
This commit is contained in:
commit
491df198cc
@ -9,6 +9,15 @@
|
||||
# Last update:
|
||||
# $Id$
|
||||
|
||||
Changes since the 3.0.1 release
|
||||
-------------------------------------------------
|
||||
|
||||
- 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'
|
||||
|
||||
Version 3.0.1 - 2016/09/19 - SVN r1870
|
||||
-------------------------------------------------
|
||||
|
||||
|
@ -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.
|
||||
|
@ -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.
|
||||
|
@ -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);
|
||||
@ -1686,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)) {
|
||||
@ -1703,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();
|
||||
|
||||
@ -1724,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 {
|
||||
|
@ -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();
|
||||
|
||||
|
||||
|
@ -42,13 +42,9 @@ class AliasHandler extends PFAHandler {
|
||||
/*options*/ '',
|
||||
/*not_in_db*/ 0,
|
||||
/*dont_write_to_db*/ 1,
|
||||
/*select*/ 'coalesce(__is_mailbox,0) as is_mailbox, __mailbox_username',
|
||||
# __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 ' .
|
||||
' ) 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*/ '',
|
||||
/*not_in_db*/ 1 ), # read_from_db_postprocess() sets the value
|
||||
@ -64,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';
|
||||
@ -303,22 +328,34 @@ 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);
|
||||
$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()) {
|
||||
# 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);
|
||||
$this->set_is_mailbox_extrafrom($condition, $searchmode);
|
||||
$result = parent::getPagebrowser($condition, $searchmode);
|
||||
$this->set_is_mailbox_extrafrom(); # reset to default
|
||||
return $result;
|
||||
}
|
||||
|
||||
|
||||
|
@ -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')) . "')";
|
||||
|
@ -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?
|
||||
|
@ -64,6 +64,7 @@
|
||||
{if $tCanAddMailbox}
|
||||
<br /><a href="{#url_create_mailbox#}&domain={$fDomain|escape:"url"}" class="button">{$PALANG.add_mailbox}</a><br />
|
||||
{/if}
|
||||
<br /><br /><a href="list.php?table=mailbox&output=csv">{$PALANG.download_csv}</a>
|
||||
{/if}
|
||||
{if $CONF.show_status===YES && $CONF.show_status_key===YES}
|
||||
<br/><br/>
|
||||
|
@ -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');
|
||||
|
Loading…
Reference in New Issue
Block a user