diff --git a/DOCUMENTS/DOVECOT.txt b/DOCUMENTS/DOVECOT.txt index 2fe5d675..cba5f12e 100644 --- a/DOCUMENTS/DOVECOT.txt +++ b/DOCUMENTS/DOVECOT.txt @@ -117,16 +117,15 @@ username_field = username Create database in Mysql: - -create table quota ( - username varchar(255) /*!40100 CHARACTER SET latin1 */ not null, - path varchar(100) /*!40100 CHARACTER SET latin1 */ not null, - current integer, - primary key (username, path) -) TYPE=MyISAM ; - +(This is automatically done by postfixadmin's setup.php) Enable quota support in Postfixadmin config.inc.php: $CONF['used_quotas'] = 'YES'; $CONF['quota'] = 'YES'; + +Note: The above text describes the configuration for dovecot 1.0 & 1.1 quota table format. + +If you use dovecot 1.2 or newer, +- use the 'quota2' table (also created by setup.php) +- set $CONF['new_quota_table'] = 'YES' diff --git a/config.inc.php b/config.inc.php index c16d099a..54184ee6 100644 --- a/config.inc.php +++ b/config.inc.php @@ -74,6 +74,7 @@ $CONF['database_tables'] = array ( 'vacation' => 'vacation', 'vacation_notification' => 'vacation_notification', 'quota' => 'quota', + 'quota2' => 'quota2', ); // Site Admin @@ -362,7 +363,11 @@ $CONF['create_mailbox_subdirs_prefix']='INBOX.'; // See: DOCUMENTATION/DOVECOT.txt // http://wiki.dovecot.org/Quota/Dict // -// $CONF['used_quotas'] = 'YES'; +$CONF['used_quotas'] = 'NO'; + +// if you use dovecot >= 1.2, set this to yes. +// Note about dovecot config: table "quota" is for 1.0 & 1.1, table "quota2" is for dovecot 1.2 and newer +$CONF['new_quota_table'] = 'NO'; // // Normally, the TCP port number does not have to be specified. diff --git a/functions.inc.php b/functions.inc.php index ca29adc9..cd702c93 100644 --- a/functions.inc.php +++ b/functions.inc.php @@ -2352,4 +2352,5 @@ $table_mailbox = table_by_key ('mailbox'); $table_vacation = table_by_key ('vacation'); $table_vacation_notification = table_by_key('vacation_notification'); $table_quota = table_by_key ('quota'); +$table_quota2 = table_by_key ('quota2'); /* vim: set expandtab softtabstop=4 tabstop=4 shiftwidth=4: */ diff --git a/list-virtual.php b/list-virtual.php index f5f1cfb1..9a66ed43 100644 --- a/list-virtual.php +++ b/list-virtual.php @@ -158,29 +158,60 @@ if ($result['rows'] > 0) } } +# 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')) - $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' - ORDER BY $table_mailbox.username LIMIT $page_size OFFSET $fDisplay"; -// AND $table_quota.path='quota/storage' - else + { + if (boolconf('new_quota_table')) + { + $query = "SELECT $table_mailbox.*, $table_vacation.active AS v_active, $table_quota2.bytes 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"; -} -else -{ - - $query = "SELECT * FROM $table_mailbox WHERE domain='$fDomain' ORDER BY username LIMIT $fDisplay, $page_size"; - if ('pgsql'==$CONF['database_type']) - { - $query = "SELECT *,extract(epoch from created) as uts_created,extract(epoch from modified) as uts_modified FROM $table_mailbox WHERE domain='$fDomain' ORDER BY username LIMIT $page_size OFFSET $fDisplay"; } - +} +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"; + } } $result = db_query ($query); if ($result['rows'] > 0) diff --git a/upgrade.php b/upgrade.php index 0615d1bf..695f2fac 100644 --- a/upgrade.php +++ b/upgrade.php @@ -171,6 +171,7 @@ function db_query_parsed($sql, $ignore_errors = 0, $attach_mysql = "") { '{RENAME_COLUMN}' => 'CHANGE COLUMN', '{MYISAM}' => 'ENGINE=MyISAM', '{INNODB}' => 'ENGINE=InnoDB', + '{BIGINT}' => 'bigint', ); $sql = "$sql $attach_mysql"; @@ -187,6 +188,7 @@ function db_query_parsed($sql, $ignore_errors = 0, $attach_mysql = "") { '{RENAME_COLUMN}' => 'ALTER COLUMN', # PgSQL : ALTER TABLE x RENAME x TO y '{MYISAM}' => '', '{INNODB}' => '', + '{BIGINT}' => 'bigint', 'int(1)' => 'int', 'int(10)' => 'int', 'int(11)' => 'int', @@ -1086,3 +1088,94 @@ function upgrade_655() { db_query_parsed(_add_index('mailbox', 'domain', 'domain')); db_query_parsed(_add_index('alias', 'domain', 'domain')); } + +function upgrade_729() { + $table_quota = table_by_key('quota'); + $table_quota2 = table_by_key('quota2'); + + # table for dovecot v1.0 & 1.1 + db_query_parsed(" + CREATE TABLE {IF_NOT_EXISTS} $table_quota ( + username VARCHAR(255) {LATIN1} NOT NULL, + path VARCHAR(100) {LATIN1} NOT NULL, + current {BIGINT}, + PRIMARY KEY (username, path) + ) {MYISAM} ; + "); + + # table for dovecot >= 1.2 + db_query_parsed(" + CREATE TABLE {IF_NOT_EXISTS} $table_quota2 ( + username VARCHAR(100) {LATIN1} NOT NULL, + bytes {BIGINT} NOT NULL DEFAULT 0, + messages integer NOT NULL DEFAULT 0, + PRIMARY KEY (username) + ) {MYISAM} ; + "); +} + +function upgrade_730_pgsql() { + $table_quota = table_by_key('quota'); + $table_quota2 = table_by_key('quota2'); + + # trigger for dovecot v1.0 & 1.1 quota table + # taken from http://wiki.dovecot.org/Quota/Dict + db_query_parsed(" + CREATE OR REPLACE FUNCTION merge_quota() RETURNS TRIGGER AS \$merge_quota\$ + BEGIN + UPDATE $table_quota SET current = NEW.current + current WHERE username = NEW.username AND path = NEW.path; + IF found THEN + RETURN NULL; + ELSE + RETURN NEW; + END IF; + END; + \$merge_quota\$ LANGUAGE plpgsql; + "); + db_query_parsed(" + CREATE TRIGGER mergequota BEFORE INSERT ON $table_quota FOR EACH ROW EXECUTE PROCEDURE merge_quota(); + "); + + # trigger for dovecot >= 1.2 quota table + # taken from http://wiki.dovecot.org/Quota/Dict, table/trigger name changed to quota2 naming + db_query_parsed(" + CREATE OR REPLACE FUNCTION merge_quota2() RETURNS TRIGGER AS \$\$ + BEGIN + IF NEW.messages < 0 OR NEW.messages IS NULL THEN + -- ugly kludge: we came here from this function, really do try to insert + IF NEW.messages IS NULL THEN + NEW.messages = 0; + ELSE + NEW.messages = -NEW.messages; + END IF; + return NEW; + END IF; + + LOOP + UPDATE $table_quota2 SET bytes = bytes + NEW.bytes, + messages = messages + NEW.messages + WHERE username = NEW.username; + IF found THEN + RETURN NULL; + END IF; + + BEGIN + IF NEW.messages = 0 THEN + INSERT INTO $table_quota2 (bytes, messages, username) VALUES (NEW.bytes, NULL, NEW.username); + ELSE + INSERT INTO $table_quota2 (bytes, messages, username) VALUES (NEW.bytes, -NEW.messages, NEW.username); + END IF; + return NULL; + EXCEPTION WHEN unique_violation THEN + -- someone just inserted the record, update it + END; + END LOOP; + END; + \$\$ LANGUAGE plpgsql; +"); + + db_query_parsed(" + CREATE TRIGGER mergequota2 BEFORE INSERT ON $table_quota2 + FOR EACH ROW EXECUTE PROCEDURE merge_quota2(); + "); +}