SF.net SVN: postfixadmin:[828] branches/postfixadmin-2.3
Brought to you by:
christian_boltz,
gingerdog
From: <chr...@us...> - 2010-05-17 22:56:31
|
Revision: 828 http://postfixadmin.svn.sourceforge.net/postfixadmin/?rev=828&view=rev Author: christian_boltz Date: 2010-05-17 22:56:23 +0000 (Mon, 17 May 2010) Log Message: ----------- more merging: - display alias targets for mailboxes (r751 and most of r787) - r819, r826 - maildir path hook, error_log IMAP mailbox creation errors - CHANGELOG.txt update Modified Paths: -------------- branches/postfixadmin-2.3/CHANGELOG.TXT branches/postfixadmin-2.3/config.inc.php branches/postfixadmin-2.3/create-mailbox.php branches/postfixadmin-2.3/functions.inc.php branches/postfixadmin-2.3/list-virtual.php branches/postfixadmin-2.3/templates/list-virtual.php Property Changed: ---------------- branches/postfixadmin-2.3/ Property changes on: branches/postfixadmin-2.3 ___________________________________________________________________ Modified: svn:mergeinfo - /trunk:800,806,811,817,821,825 + /trunk:751,800,806,811,817,819,821,825-826 Modified: branches/postfixadmin-2.3/CHANGELOG.TXT =================================================================== --- branches/postfixadmin-2.3/CHANGELOG.TXT 2010-05-17 22:04:17 UTC (rev 827) +++ branches/postfixadmin-2.3/CHANGELOG.TXT 2010-05-17 22:56:23 UTC (rev 828) @@ -10,11 +10,15 @@ # Last update: # $Id$ -Version ***svn 2.3 branch*** - 2009/12/26 - SVN r*** ------------------------------------ +Version 2.3.1 - 2010/05/18 - SVN r*** (postfixadmin-2.3 branch) +--------------------------------------------------------------- - - NOTE: this release is based on the 2.3 branch - - NOTE: this is a bugfix-only release for Postfix Admin 2.3 + - SUMMARY: PostfixAdmin 2.3.1 is a bugfix-only release for Postfix Admin 2.3. + The only visible change is displaying the alias target for mailboxes which + was a longstanding issue/"missing feature". + The ADDITIONS directory contains some new scripts. + - display alias targets for mailboxes (if $CONF['special_alias_control'] = YES) + - add hook for custom maildir path generation - add import_users_from_csv.py script (by Simone Piccardi) - add mailbox_post* scripts for cyrus - handle dovecot passwords without any tempfile (prevents safe_mode issues) @@ -117,8 +121,8 @@ - added support for domain aliases (from lenix) (can be disabled with $CONF['alias_domain']) Important: If you update from a previous version, you'll have to adapt your postfix - configuration (see DOCUMENTS/POSTFIX_CONF.txt) - or just disable alias domain support, - your postfix configuration will continue to work + configuration (see DOCUMENTS/POSTFIX_CONF.txt) - or just disable alias domain support, + your postfix configuration will continue to work - updated postfix example configuration for domain aliases and to use the new mysql map format - vacation.pl: - add option for re-notification after definable timeout (patch from Luxten) Modified: branches/postfixadmin-2.3/config.inc.php =================================================================== --- branches/postfixadmin-2.3/config.inc.php 2010-05-17 22:04:17 UTC (rev 827) +++ branches/postfixadmin-2.3/config.inc.php 2010-05-17 22:56:23 UTC (rev 828) @@ -149,7 +149,37 @@ // NO: /usr/local/virtual/domain.tld/username // Note: If $CONF['domain_path'] is set to NO, this setting will be forced to YES. $CONF['domain_in_mailbox'] = 'YES'; +// If you want to define your own function to generate a maildir path set this to the name of the function. +// Notes: +// - this configuration directive will override both domain_path and domain_in_mailbox +// - the maildir_name_hook() function example is present below, commented out +// - if the function does not exist the program will default to the above domain_path and domain_in_mailbox settings +$CONF['maildir_name_hook'] = 'NO'; +/* + maildir_name_hook example function + + Called by create-mailbox.php if $CONF['maildir_name_hook'] == '<name_of_the_function>' + - allows for customized maildir paths determined by a custom function + - the example below will prepend a single-character directory to the + beginning of the maildir, splitting domains more or less evenly over + 36 directories for improved filesystem performance with large numbers + of domains. + + Returns: maildir path + ie. I/example.com/user/ +*/ +/* +function maildir_name_hook($domain, $user) { + $chars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; + + $dir_index = hexdec(substr(md5($domain), 28)) % strlen($chars); + $dir = substr($chars, $dir_index, 1); + return sprintf("%s/%s/%s/", $dir, $domain, $user); +} +*/ + + // Default Domain Values // Specify your default values below. Quota in MB. $CONF['aliases'] = '10'; Modified: branches/postfixadmin-2.3/create-mailbox.php =================================================================== --- branches/postfixadmin-2.3/create-mailbox.php 2010-05-17 22:04:17 UTC (rev 827) +++ branches/postfixadmin-2.3/create-mailbox.php 2010-05-17 22:56:23 UTC (rev 828) @@ -159,7 +159,11 @@ { $password = pacrypt ($fPassword); - if ($CONF['domain_path'] == "YES") + if($CONF['maildir_name_hook'] != 'NO' && function_exists($CONF['maildir_name_hook'])) { + $hook_func = $CONF['maildir_name_hook']; + $maildir = $hook_func ($fDomain, $fUsername); + } + else if ($CONF['domain_path'] == "YES") { if ($CONF['domain_in_mailbox'] == "YES") { Modified: branches/postfixadmin-2.3/functions.inc.php =================================================================== --- branches/postfixadmin-2.3/functions.inc.php 2010-05-17 22:04:17 UTC (rev 827) +++ branches/postfixadmin-2.3/functions.inc.php 2010-05-17 22:56:23 UTC (rev 828) @@ -1774,8 +1774,17 @@ } } +/** + * db_in_clause + * Action: builds and returns the "field in(x, y)" clause for database queries + * Call: db_in_clause (string field, array values) + */ +function db_in_clause($field, $values) { + return " $field IN ('" + . implode("','",escape_string(array_values($values))) + . "') "; +} - // // table_by_key // Action: Return table name for given key @@ -2099,6 +2108,7 @@ $f='{'.$s_host.'}'.$s_prefix.$f; $res=imap_createmailbox($i,$f); if (!$res) { + error_log('Could not create IMAP folder $f: '.imap_last_error()); @imap_close($i); return FALSE; } @@ -2358,8 +2368,6 @@ } } - - $table_admin = table_by_key ('admin'); $table_alias = table_by_key ('alias'); $table_alias_domain = table_by_key ('alias_domain'); Modified: branches/postfixadmin-2.3/list-virtual.php =================================================================== --- branches/postfixadmin-2.3/list-virtual.php 2010-05-17 22:04:17 UTC (rev 827) +++ branches/postfixadmin-2.3/list-virtual.php 2010-05-17 22:56:23 UTC (rev 828) @@ -53,11 +53,13 @@ { if (isset ($_GET['domain'])) $fDomain = escape_string ($_GET['domain']); if (isset ($_GET['limit'])) $fDisplay = intval ($_GET['limit']); + $search = escape_string(safeget('search')); } else { if (isset ($_POST['fDomain'])) $fDomain = escape_string ($_POST['fDomain']); if (isset ($_POST['limit'])) $fDisplay = intval ($_POST['limit']); + $search = escape_string(safepost('search')); } if (count($list_domains) == 0) { @@ -91,6 +93,11 @@ $_SESSION['list_virtual_sticky_domain'] = $fDomain; } +# +# alias domain +# + +# TODO: add search support for alias domains if (boolconf('alias_domain')) { # Alias-Domains # first try to get a list of other domains pointing @@ -136,23 +143,36 @@ } } +# +# aliases +# + +if ($search == "") { + $sql_domain = " $table_alias.domain='$fDomain' "; + $sql_where = ""; +} else { + $sql_domain = db_in_clause("$table_alias.domain", $list_domains); + $sql_where = " AND ( address LIKE '%$search%' OR goto LIKE '%$search%' ) "; +} $query = "SELECT $table_alias.address, $table_alias.goto, $table_alias.modified, $table_alias.active FROM $table_alias LEFT JOIN $table_mailbox ON $table_alias.address=$table_mailbox.username - WHERE ($table_alias.domain='$fDomain' AND $table_mailbox.maildir IS NULL) + WHERE ($sql_domain AND $table_mailbox.maildir IS NULL $sql_where) ORDER BY $table_alias.address LIMIT $fDisplay, $page_size"; if ('pgsql'==$CONF['database_type']) { + # TODO: is the different query for pgsql really needed? The mailbox query below also works with both... $query = "SELECT address, goto, extract(epoch from modified) as modified, active FROM $table_alias - WHERE domain='$fDomain' AND NOT EXISTS(SELECT 1 FROM $table_mailbox WHERE username=$table_alias.address) + WHERE $sql_domain AND NOT EXISTS(SELECT 1 FROM $table_mailbox WHERE username=$table_alias.address $sql_where) ORDER BY address LIMIT $page_size OFFSET $fDisplay"; } + $result = db_query ($query); if ($result['rows'] > 0) { @@ -170,66 +190,76 @@ } } -# TODO: reduce number of different queries by not depending on too much config options -# (it probably won't hurt to include a field in the resultset that is not displayed later) -if ($CONF['vacation_control_admin'] == 'YES') -{ - if (boolconf('used_quotas')) - { - if (boolconf('new_quota_table')) - { - $query = "SELECT $table_mailbox.*, $table_vacation.active AS v_active, $table_quota2.bytes as current FROM $table_mailbox - LEFT JOIN $table_vacation ON $table_mailbox.username=$table_vacation.email - LEFT JOIN $table_quota2 ON $table_mailbox.username=$table_quota2.username - WHERE $table_mailbox.domain='$fDomain' - ORDER BY $table_mailbox.username LIMIT $page_size OFFSET $fDisplay"; - } - else - { - $query = "SELECT $table_mailbox.*, $table_vacation.active AS v_active, $table_quota.current FROM $table_mailbox - LEFT JOIN $table_vacation ON $table_mailbox.username=$table_vacation.email - LEFT JOIN $table_quota ON $table_mailbox.username=$table_quota.username - WHERE $table_mailbox.domain='$fDomain' AND - ( $table_quota.path='quota/storage' OR $table_quota.path IS NULL ) - ORDER BY $table_mailbox.username LIMIT $page_size OFFSET $fDisplay"; - } - } - else # $CONF[used_quotas] = NO - { - $query = "SELECT $table_mailbox.*, $table_vacation.active AS v_active FROM $table_mailbox - LEFT JOIN $table_vacation ON $table_mailbox.username=$table_vacation.email - WHERE $table_mailbox.domain='$fDomain' ORDER BY $table_mailbox.username LIMIT $page_size OFFSET $fDisplay"; - } + +# +# mailboxes +# + +$display_mailbox_aliases = boolconf('special_alias_control'); # TODO: is this condition correct? - I'm slightly confused with alias_control, alias_control_admin and special_alias_control + +# build the sql query +$sql_select = " SELECT $table_mailbox.* "; +$sql_from = " FROM $table_mailbox "; +$sql_join = ""; +$sql_where = " WHERE "; +$sql_order = " ORDER BY $table_mailbox.username "; +$sql_limit = " LIMIT $page_size OFFSET $fDisplay"; + +if ($search == "") { + $sql_where .= " $table_mailbox.domain='$fDomain' "; +} else { + $sql_where .= db_in_clause("$table_mailbox.domain", $list_domains) . " "; + $sql_where .= " AND ( $table_mailbox.username LIKE '%$search%' OR $table_mailbox.name LIKE '%$search%' "; + if ($display_mailbox_aliases) { + $sql_where .= " OR $table_alias.goto LIKE '%$search%' "; + } + $sql_where .= " ) "; # $search is already escaped } -else # $CONF['vacation_control_admin'] == 'NO' -{ - if (boolconf('used_quotas')) - { - if (boolconf('new_quota_table')) - { - $query = "SELECT $table_mailbox.*, $table_quota2.bytes as current FROM $table_mailbox - LEFT JOIN $table_quota2 ON $table_mailbox.username=$table_quota2.username - WHERE $table_mailbox.domain='$fDomain' ORDER BY $table_mailbox.username LIMIT $page_size OFFSET $fDisplay"; - } - else - { - $query = "SELECT $table_mailbox.*, $table_quota.current FROM $table_mailbox - LEFT JOIN $table_quota ON $table_mailbox.username=$table_quota.username - WHERE $table_mailbox.domain='$fDomain' AND - ( $table_quota.path='quota/storage' OR $table_quota.path IS NULL ) - ORDER BY $table_mailbox.username LIMIT $page_size OFFSET $fDisplay"; - } - } - else # $CONF[used_quotas] = NO - { - $query = "SELECT * FROM $table_mailbox WHERE domain='$fDomain' ORDER BY username LIMIT $page_size OFFSET $fDisplay"; - } + +if ($display_mailbox_aliases) { + $sql_select .= ", $table_alias.goto "; + $sql_join .= " LEFT JOIN $table_alias ON $table_mailbox.username=$table_alias.address "; } + +if (boolconf('vacation_control_admin')) { + $sql_select .= ", $table_vacation.active AS v_active "; + $sql_join .= " LEFT JOIN $table_vacation ON $table_mailbox.username=$table_vacation.email "; +} + +if (boolconf('used_quotas') && boolconf('new_quota_table')) { + $sql_select .= ", $table_quota2.bytes as current "; + $sql_join .= " LEFT JOIN $table_quota2 ON $table_mailbox.username=$table_quota2.username "; +} + +if (boolconf('used_quotas') && ( ! boolconf('new_quota_table') ) ) { + $sql_select .= ", $table_quota.current "; + $sql_join .= " LEFT JOIN $table_quota ON $table_mailbox.username=$table_quota.username "; + $sql_where .= " ( $table_quota.path='quota/storage' OR $table_quota.path IS NULL ) "; +} + +$query = "$sql_select\n$sql_from\n$sql_join\n$sql_where\n$sql_order\n$sql_limit"; + $result = db_query ($query); + if ($result['rows'] > 0) { while ($row = db_array ($result['result'])) { + if ($display_mailbox_aliases) { + $goto_split = split(",", $row['goto']); + $row['goto_mailbox'] = 0; + $row['goto_other'] = array(); + + foreach ($goto_split as $goto_single) { + if ($goto_single == $row['username']) { # delivers to mailbox + $row['goto_mailbox'] = 1; + } elseif (boolconf('vacation') && strstr($goto_single, '@' . $CONF['vacation_domain']) ) { # vacation alias - TODO: check for full vacation alias + # skip the vacation alias, vacation status is detected otherwise + } else { # forwarding to other alias + $row['goto_other'][] = $goto_single; + } + } + } if ('pgsql'==$CONF['database_type']) { // XXX @@ -248,6 +278,7 @@ $tCanAddAlias = false; $tCanAddMailbox = false; +# TODO: needs reworking for $search... $limit = get_domain_properties($fDomain); if (isset ($limit)) { if ($fDisplay >= $page_size) { Modified: branches/postfixadmin-2.3/templates/list-virtual.php =================================================================== --- branches/postfixadmin-2.3/templates/list-virtual.php 2010-05-17 22:04:17 UTC (rev 827) +++ branches/postfixadmin-2.3/templates/list-virtual.php 2010-05-17 22:56:23 UTC (rev 828) @@ -6,6 +6,17 @@ $file = 'list-virtual.php'; +# search highlighting +function searchhl($text) { + global $search; + if ($search == "") { + return $text; + } else { + return str_ireplace($search, "<span class='searchresult' style='background:lightgreen'>" . $search . "</span>", $text); + # TODO: find out why .searchresult class in css file doesn't work + } +} + if ($limit['aliases'] < 0) $limit['aliases'] = $PALANG['pOverview_disabled']; if ($limit['mailboxes'] < 0) $limit['mailboxes'] = $PALANG['pOverview_disabled']; if ($limit['maxquota'] < 0) $limit['maxquota'] = $PALANG['pOverview_disabled']; @@ -94,6 +105,9 @@ print " <td><a href=\"$file?domain=" . urlencode ($tAliasDomains[$i]['alias_domain']) . "&limit=" . $current_limit . "\">" . $tAliasDomains[$i]['alias_domain'] . "</a></td>\n"; print " <td>" . $tAliasDomains[$i]['modified'] . "</td>\n"; $active = ($tAliasDomains[$i]['active'] == 1) ? $PALANG['YES'] : $PALANG['NO']; + +# TODO: change all edit-*.php scripts not to require the domain parameter (and extract it from the address). This avoids superflous problems when using search. + print " <td><a href=\"edit-active.php?alias_domain=true&domain=" . urlencode ($tAliasDomains[$i]['alias_domain']) . "&return=$file" . urlencode ( "?domain=" . $fDomain . "&limit=" . $current_limit) . "\">" . $active . "</a></td>\n"; print " <td><a href=\"delete.php?table=alias_domain&delete=" . urlencode ($tAliasDomains[$i]['alias_domain']) . "&domain=" . urlencode ($tAliasDomains[$i]['alias_domain']) @@ -153,10 +167,9 @@ { print " <td>" . gen_show_status($tAlias[$i]['address']) . "</td>\n"; } - - print " <td>" . $tAlias[$i]['address'] . "</td>\n"; + print " <td>" . searchhl($tAlias[$i]['address']) . "</td>\n"; if ($CONF['alias_goto_limit'] > 0) { - print " <td>" . preg_replace ( + print " <td>" . searchhl(preg_replace ( "/,/", "<br>", preg_replace( @@ -167,9 +180,9 @@ ), $tAlias[$i]['goto'] ) - ) . "</td>\n"; + )) . "</td>\n"; } else { - print " <td>" . preg_replace ("/,/", "<br>", $tAlias[$i]['goto']) . "</td>\n"; + print " <td>" . searchhl(preg_replace ("/,/", "<br>", $tAlias[$i]['goto'])) . "</td>\n"; } print " <td>" . $tAlias[$i]['modified'] . "</td>\n"; @@ -179,7 +192,7 @@ # superadmin code $active = ($tAlias[$i]['active'] == 1) ? $PALANG['YES'] : $PALANG['NO']; print " <td><a href=\"edit-active.php?alias=" . urlencode ($tAlias[$i]['address']) . "&domain=$fDomain&return=$file?domain=$fDomain" . urlencode ("&limit=" . $current_limit) . "\">" . $active . "</a></td>\n"; - print " <td><a href=\"edit-alias.php?address=" . urlencode ($tAlias[$i]['address']) . "&domain=$fDomain" . "\">" . $PALANG['edit'] . "</a></td>\n"; + print " <td><a href=\"edit-alias.php?address=" . urlencode ($tAlias[$i]['address']) . "\">" . $PALANG['edit'] . "</a></td>\n"; print " <td><a href=\"delete.php?table=alias" . "&delete=" . urlencode ($tAlias[$i]['address']) . "&domain=$fDomain" . "\"onclick=\"return confirm ('" . $PALANG['confirm'] . $PALANG['pOverview_get_aliases'] . ": ". $tAlias[$i]['address'] . "')\">" . $PALANG['del'] . "</a></td>\n"; } else { @@ -188,7 +201,7 @@ { $active = ($tAlias[$i]['active'] == 1) ? $PALANG['YES'] : $PALANG['NO']; print " <td><a href=\"edit-active.php?alias=" . urlencode ($tAlias[$i]['address']) . "&domain=$fDomain" . "\">" . $active . "</a></td>\n"; - print " <td><a href=\"edit-alias.php?address=" . urlencode ($tAlias[$i]['address']) . "&domain=$fDomain" . "\">" . $PALANG['edit'] . "</a></td>\n"; + print " <td><a href=\"edit-alias.php?address=" . urlencode ($tAlias[$i]['address']) . "\">" . $PALANG['edit'] . "</a></td>\n"; print " <td><a href=\"delete.php?table=alias&delete=" . urlencode ($tAlias[$i]['address']) . "&domain=$fDomain" . "\"onclick=\"return confirm ('" . $PALANG['confirm'] . $PALANG['pOverview_get_aliases'] . ": ". $tAlias[$i]['address'] . "')\">" . $PALANG['del'] . "</a></td>\n"; } else @@ -197,7 +210,7 @@ { $active = ($tAlias[$i]['active'] == 1) ? $PALANG['YES'] : $PALANG['NO']; print " <td><a href=\"edit-active.php?alias=" . urlencode ($tAlias[$i]['address']) . "&domain=$fDomain" . "\">" . $active . "</a></td>\n"; - print " <td><a href=\"edit-alias.php?address=" . urlencode ($tAlias[$i]['address']) . "&domain=$fDomain" . "\">" . $PALANG['edit'] . "</a></td>\n"; + print " <td><a href=\"edit-alias.php?address=" . urlencode ($tAlias[$i]['address']) . "\">" . $PALANG['edit'] . "</a></td>\n"; print " <td><a href=\"delete.php?table=alias&delete=" . urlencode ($tAlias[$i]['address']) . "&domain=$fDomain" . "\"onclick=\"return confirm ('" . $PALANG['confirm'] . $PALANG['pOverview_get_aliases'] . ": ". $tAlias[$i]['address'] . "')\">" . $PALANG['del'] . "</a></td>\n"; } else @@ -256,6 +269,8 @@ $colspan=8; if ($CONF['vacation_control_admin'] == 'YES') $colspan=$colspan+1; if ($CONF['alias_control_admin'] == 'YES') $colspan=$colspan+1; + if ($display_mailbox_aliases) $colspan=$colspan+1; + print "<table id=\"mailbox_table\">\n"; print " <tr>\n"; print " <td colspan=\"$colspan\"><h3>" . $PALANG['pOverview_mailbox_title'] . "</h3></td>"; @@ -263,6 +278,7 @@ print " <tr class=\"header\">\n"; if ($CONF['show_status'] == 'YES') { print "<td></td>\n"; } print " <td>" . $PALANG['pOverview_mailbox_username'] . "</td>\n"; + if ($display_mailbox_aliases) print " <td>" . $PALANG['pOverview_alias_goto'] . "</td>\n"; print " <td>" . $PALANG['pOverview_mailbox_name'] . "</td>\n"; if ($CONF['quota'] == 'YES') print " <td>" . $PALANG['pOverview_mailbox_quota'] . "</td>\n"; print " <td>" . $PALANG['pOverview_mailbox_modified'] . "</td>\n"; @@ -282,7 +298,22 @@ print " <td>" . gen_show_status($tMailbox[$i]['username']) . "</td>\n"; } - print " <td>" . $tMailbox[$i]['username'] . "</td>\n"; + print " <td>" . searchhl($tMailbox[$i]['username']) . "</td>\n"; + + if ($display_mailbox_aliases) { + # print " <td>" . searchhl($tMailbox[$i]['goto']) . "</td>\n"; + print " <td>"; + if ($tMailbox[$i]['goto_mailbox'] == 1) { + print "Mailbox"; # TODO: make translatable + } else { + print "Forward only"; # TODO: make translatable + } + if (count($tMailbox[$i]['goto_other']) > 0) print "<br>"; + print searchhl(join("<br>", $tMailbox[$i]['goto_other'])); # TODO: honor $CONF['alias_goto_limit'] + print "</td>\n"; + } + + print " <td>" . $tMailbox[$i]['name'] . "</td>\n"; if ($CONF['quota'] == 'YES') { @@ -331,7 +362,7 @@ if ($edit_aliases == 1) { - print " <td><a href=\"edit-alias.php?address=" . urlencode ($tMailbox[$i]['username']) . "&domain=$fDomain" . "\">" . $PALANG['pOverview_alias_edit'] . "</a></td>\n"; + print " <td><a href=\"edit-alias.php?address=" . urlencode ($tMailbox[$i]['username']) . "\">" . $PALANG['pOverview_alias_edit'] . "</a></td>\n"; } print " <td><a href=\"edit-mailbox.php?username=" . urlencode ($tMailbox[$i]['username']) . "&domain=$fDomain" . "\">" . $PALANG['edit'] . "</a></td>\n"; This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |