[[toc]]
+++ Notes
IMP 6, Horde 5
Modifies traditional and dynamic views to display quotas.
This describes modifications to IMP 6 (Horde 5) quota
to use two different partitions (file systems) with quota enabled.
One is used for INBOX and the other is used for IMAP folders.
This allows different quota values for INBOX and IMAP folders.
It uses system quota command.
Tested on Debian 6.0 (squeeze), Horde 5.0.3-IMP 6.0.3, Horde 5.0.4-IMP 6.0.4
+++ Modifications
||~ File ||~ Variables, Function(s) ||
|| imp/config/backends.php || quota ||
|| imp/lib/Quota/Command.php || getQuota ||
|| imp/lib/Quota.php || construct ||
|| imp/lib/View/Subinfo.php || construct ||
|| imp/templates/basic/subinfo.html.php || quotaClassV, quotaClassH ||
|| imp/templates/dynamic/mailbox_subinfo.html.php || quota-text ||
|| imp/lib/Ui/Quota.php || quota ||
|| imp/lib/Ajax/Queue.php || m, p, l, add ||
|| imp/js/dimpbase.js (IMP 6.0.3) || quotaV, quotaH, quotaCallback ||
|| imp/js/dimpbase.js (IMP 6.0.4) || quotaV, quotaH, quotaCallback ||
++++ Configuration example (imp/config/backends.php)
See Comand.php bellow for parameters.
Quota command must support "w" (do not wrap).
$servers['imap'] = array(
...
'quota' => array(
'driver' => 'command',
'params' => array(
'quota_path' => '/usr/bin/quota',
'dev_inbx' => '/dev/disk/by-uuid/734e96a4-af8f-4c83-a12c-4ab11b139a13',
'dev_fldrs' => '/dev/sdb2',
'unit' => 'GB',
)
),
...
);
++++ imp/lib/Quota/Command.php
'dev_inbx' (string) [REQUIRED] User´s INBOX file system device.
Usually maps to /var/mail, /var/spool/mail.
Examples: '/dev/hda6', '/dev/sdb2', '/dev/md2', '/dev/disk/by-uuid/097a934f-8fb1-4c9d-a330-817194b6e8a8'.
'dev_fldrs' (string) [REQUIRED] User´s home file system device.
Used for IMAP folders. Usually maps to /home.
Examples: '/dev/hda7', '/dev/sda3', '/dev/md1', '/dev/mapper/VOL2-Home'.
Obsolete parameters: grep_path, partition
Function now takes care of exceeded quotas and quota not defined for that user.
Backup your original imp/lib/Quota/Command.php and create a new Command.php with the following code:
public function __construct(array $params = array())
{
$this->_params = array_merge($this->_params, $params);
$this->_params['format'] = array(
'shortv' => isset($this->_params['format']['short'])
? $this->_params['format']['short']
: _("Entrada: %.0f%% of %.1f %s"),
'shorth' => isset($this->_params['format']['shorth'])
? $this->_params['format']['shorth']
: _(" - Pastas: %.0f%% de %.1f %s"),
'sshorth' => isset($this->_params['format']['sshorth'])
? $this->_params['format']['sshorth']
: _("Pastas: %.0f%% de %.1f %s"),
'nolimit_shortv' => isset($this->_params['format']['nolimit_short'])
? $this->_params['format']['nolimit_short']
: _("Entrada: %.1f %s"),
'nolimit_shorth' => isset($this->_params['format']['nolimit_shorth'])
? $this->_params['format']['nolimit_shorth']
: _(" - Pastas: %.1f %s"),
'nolimit_sshorth' => isset($this->_params['format']['nolimit_sshorth'])
? $this->_params['format']['nolimit_sshorth']
: _("Pastas: %.1f %s"),
);
}
----
++++ imp/lib/View/Subinfo.php
Backup your original imp/lib/View/Subinfo.php and replace function construct with the following code:
public function __construct($config = array())
{
$config['templatePath'] = IMP_TEMPLATES . '/basic';
parent::__construct($config);
$quotadata = $GLOBALS['injector']->getInstance('IMP_Ui_Quota')->quota();
if (!empty($quotadata)) {
$this->quotaClassV = $quotadata['classvar'];
$this->quotaTextV = $quotadata['messagevar'];
$this->quotaClassH = $quotadata['classhome'];
$this->quotaTextH = $quotadata['messagehome'];
}
}
----
++++ imp/templates/basic/subinfo.html.php
Backup your original imp/templates/basic/subinfo.html.php and replace the following code:
From:
quotaText): ?>
quotaText ?>
To:
quotaTextV): ?>
quotaTextV ?>
quotaTextV): ?>
quotaTextH ?>
----
++++ imp/templates/dynamic/mailbox_subinfo.html.php
++++ imp/lib/Ui/Quota.php
Backup your original imp/lib/Ui/Quota.php and create a new Quota.php with the following code:
public function add(IMP_Ajax_Application $ajax)
{
/* Add flag information. */
if (!empty($this->_flag)) {
$ajax->addTask('flag', $this->_flag);
$this->_flag = array();
}
/* Add folder tree information. */
$imptree = $GLOBALS['injector']->getInstance('IMP_Imap_Tree');
$imptree->setIteratorFilter(IMP_Imap_Tree::FLIST_NOSPECIALMBOXES);
$out = $imptree->getAjaxResponse();
if (!empty($out)) {
$ajax->addTask('mailbox', array_merge($out, $this->_mailboxOpts));
}
/* Add mail log information. */
if (!empty($this->_maillog)) {
$imp_maillog = $GLOBALS['injector']->getInstance('IMP_Maillog');
$maillog = array();
foreach ($this->_maillog as $val) {
if ($tmp = $imp_maillog->getLogObs($val['msg_id'])) {
$log_ob = new stdClass;
$log_ob->log = $tmp;
$log_ob->mbox = $val['mailbox']->form_to;
$log_ob->uid = $val['uid'];
$maillog[] = $log_ob;
}
}
if (!empty($maillog)) {
$ajax->addTask('maillog', $maillog);
}
}
/* Add message information. */
if (!empty($this->_messages)) {
$ajax->addTask('message', $this->_messages);
$this->_messages = array();
}
/* Add poll information. */
$poll = $poll_list = array();
foreach ($this->_poll as $val) {
$poll_list[strval($val)] = 1;
}
$imap_ob = $GLOBALS['injector']->getInstance('IMP_Factory_Imap')->create();
if ($imap_ob->ob) {
foreach ($imap_ob->statusMultiple(array_keys($poll_list), Horde_Imap_Client::STATUS_UNSEEN) as $key => $val) {
$poll[IMP_Mailbox::formTo($key)] = intval($val['unseen']);
}
}
if (!empty($poll)) {
$ajax->addTask('poll', $poll);
$this->_poll = array();
}
/* Add quota information. */
if ($this->_quota &&
($quotadata = $GLOBALS['injector']->getInstance('IMP_Ui_Quota')->quota())) {
/* Quota for dev_inbx */
$merrov = null;
if (round($quotadata['percentvar']) >= 100) {
$mvclasse = 'horde.error';
if (ereg("none", $quotadata['gracevar'])) {
$merrov = sprintf("Inbox above limit. Grace time expired.");
} else {
$merrov = sprintf("Inbox above limit. Solve in %s day(s)", $quotadata['gracevar']);
}
} else if ($quotadata['percentvar'] >= 90) {
$merrov = sprintf("Inbox above 90%%.");
$mvclasse = 'horde.warning';
}
/* Quota for dev_fldrs */
$merroh = null;
if (round($quotadata['percenthome'] >= 100)) {
$mhclasse = 'horde.error';
if (ereg("none", $quotadata['gracehome'])) {
$merroh = sprintf("Folders above limit. Grace time expired.");
} else {
$merroh = sprintf("Folders above limit. Solve in %s day(s)", $quotadata['gracehome']);
}
} elseif ($quotadata['percenthome'] >= 90) {
$merroh = sprintf("Folders above 90%%.");
$mhclasse = 'horde.warning';
}
if (!empty($merrov)) {
$GLOBALS['notification']->push($merrov, $mvclasse);
}
if (!empty($merroh)) {
$GLOBALS['notification']->push($merroh, $mhclasse);
}
$ajax->addTask('quota', array(
'mv' => $quotadata['messagevar'],
'pv' => round($quotadata['percentvar']),
'lv' => $quotadata['percentvar'] >= 100
? 'alert'
: ($quotadata['percentvar'] >= 90 ? 'warn' : 'control'),
'mh' => $quotadata['messagehome'],
'ph' => round($quotadata['percenthome']),
'lh' => $quotadata['percenthome'] >= 100
? 'alert'
: ($quotadata['percenthome'] >= 90 ? 'warn' : 'control')
));
$this->_quota = false;
}
}
----
++++ imp/js/dimpbase.js (IMP 6.0.3)
* quotaCallback
> quotaV, mv, lv
> quotaH, mh, lh
Backup your original imp/js/dimpbase.js. Edit dimpbase.js and replace function quotaCallback with the following code:
quotaCallback: function(r)
{
var quotaV = $('quota-textV');
var quotaH = $('quota-textH');
quotaV.setText(r.mv);
switch (r.lv) {
case 'alert':
quotaV.removeClassName('quotawarn');
quotaV.addClassName('quotaalert');
break;
case 'warn':
quotaV.removeClassName('quotaalert');
quotaV.addClassName('quotawarn');
break;
case 'control':
quotaV.removeClassName('quotawarn');
quotaV.removeClassName('quotaalert');
break;
}
quotaH.setText(r.mh);
switch (r.lh) {
case 'alert':
quotaH.removeClassName('quotawarn');
quotaH.addClassName('quotaalert');
break;
case 'warn':
quotaH.removeClassName('quotaalert');
quotaH.addClassName('quotawarn');
break;
case 'control':
quotaH.removeClassName('quotawarn');
quotaH.removeClassName('quotaalert');
break;
}
},
----
++++ imp/js/dimpbase.js (IMP 6.0.4)
* quotaCallback
> quotaV, mv, lv
> quotaH, mh, lh
Backup your original imp/js/dimpbase.js. Edit dimpbase.js and replace function quotaCallback with the following code:
quotaCallback: function(r)
{
var quotaV = $('quota-textV');
var quotaH = $('quota-textH');
quotaV.removeClassName('quotaalert').
removeClassName('quotawarn').
setText(r.mv);
quotaH.removeClassName('quotaalert').
removeClassName('quotawarn').
setText(r.mh);
switch (r.lv) {
case 'alert':
case 'warn':
quotaV.addClassName('quota' + r.lv);
break;
}
switch (r.lh) {
case 'alert':
case 'warn':
quotaH.addClassName('quota' + r.lh);
break;
}
},