\documentclass{article}
\usepackage{ulem}
\usepackage{graphicx}
\usepackage{hyperref}
\pagestyle{headings}
\begin{document}
\textbf{This information is valid for Horde 5 and later only. See <a href="https://wiki.horde.org/AltQuotaH4">AltQuotaH4</a> for Horde 4 or <a href="https://wiki.horde.org/AltQuotaH3">AltQuotaH3</a> for Horde 3.}

\subsection{Notes}
\textbf{IMP 6, Horde 5}<br />
\textbf{Modifies basic and dynamic views to display quotas}.

This describes modifications to IMP 6 (Horde 5) quota \textbackslash\{\}<br />
to use two different partitions (file systems) with quota enabled. \textbackslash\{\}<br />
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 modified quota Imap driver and related Imp files.

Tested on Debian 7 (wheezy, stable) with Dovecot (wheezy distribution), Horde 5.1.5-IMP 6.1.6


\noindent\rule{\textwidth}{1pt}
\subsection{Modifications}
<table class="horde-table">File & Variables, Function(s) \\
\hline
imp/config/backends.local.php & quota \\
\hline
imp/lib/Quota/Imap.php & getQuota \\
\hline
imp/lib/Quota/Ui.php & quota \\
\hline
imp/lib/Quota.php & construct \\
\hline
imp/lib/Ajax/Queue.php & m, p, l, add \\
\hline
imp/lib/View/Subinfo.php & construct \\
\hline
imp/js/dimpbase.js & r.m, r.l, quotaCallback \\
\hline
imp/templates/basic/subinfo.html.php & quotaClass, quotaText \\
\hline
imp/templates/dynamic/mailbox\_subinfo.html.php & quota-text \\
\hline
\textit{Last updated 2014-01-01} &  \\
\hline
</table>

\noindent\rule{\textwidth}{1pt}
\subsection{Image of IMP showing quotas and 90\% warning}

\noindent\rule{\textwidth}{1pt}
\section{\includegraphics{Qfolders90.png}}
\subsection{Descriptions}

\noindent\rule{\textwidth}{1pt}
\subsubsection{Configuration example (imp/config/backends.local.php)}
<pre><code class="language-php">
\$servers['imap'] = array(
    ...

    'quota' => array(
        'driver' => 'imap',
        'params' => array(
            'hide\_when\_unlimited' => false,
            'unit' => 'GB'
        )

    ...
);
</code></pre>

\noindent\rule{\textwidth}{1pt}
\subsubsection{imp/lib/Quota/Imap.php}
\begin{itemize}
\item Function getQuota


\end{itemize}
\begin{quote}
\$quotavar, usagevar, limitvar.<br />
\$quotahome, usagehome, limithome.


\end{quote}
Backup your original imp/lib/Quota/Imap.php and create a new Imap.php with the following code:

<pre><code class="language-php">
<?php
/**
 * Copyright 2002-2013 Horde LLC (http://www.horde.org/)
 *
 * See the enclosed file COPYING for license information (GPL). If you
 * did not receive this file, see http://www.horde.org/licenses/gpl.
 *
 * @category  Horde
 * @copyright 2002-2013 Horde LLC
 * @license   http://www.horde.org/licenses/gpl GPL
 * @package   IMP
 * Modified by Mauricio Jose T. Tecles <mtecles@biof.ufrj.br>
 * Updated 2013 December 18
 */

/**
 * Quota driver for IMAP servers.
 *
 * @author    Mike Cochrane <mike@graftonhall.co.nz>
 * @category  Horde
 * @copyright 2002-2013 Horde LLC
 * @license   http://www.horde.org/licenses/gpl GPL
 * @package   IMP
 */
class IMP\_Quota\_Imap extends IMP\_Quota
\{
    /**
     * Constructor.
     *
     * @param array \$params  Parameters:
     *   - imap\_ob: (Horde\_Imap\_Client\_Base) IMAP client object [REQUIRED].
     */
    public function \_\_construct(array \$params = array())
    \{
        if (!isset(\$params['imap\_ob'])) \{
            throw new InvalidArgumentException('Missing imap\_ob parameter');
        \}

        parent::\_\_construct(\$params);
    \}

    /**
     */
    public function getQuota(\$mailbox = null)
    \{
        try \{
            \$quotavar = \$this->\_params['imap\_ob']->getQuotaRoot('INBOX');
            \$quotahome = \$this->\_params['imap\_ob']->getQuotaRoot('');
        \} catch (IMP\_Imap\_Exception \$e) \{
            throw new IMP\_Exception(\_("Unable to retrieve quota"));
        \}

        \$quota\_var\_val = reset(\$quotavar);
        \$quota\_home\_val = reset(\$quotahome);

        if (isset(\$quota\_var\_val['storage'])) \{
                  \$quota\_val['limitvar'] = \$quota\_var\_val['storage']['limit'] * 1024;
                  \$quota\_val['usagevar'] = \$quota\_var\_val['storage']['usage'] * 1024;
        \} else \{
                \$quota\_val['limitvar'] = 0;
                \$quota\_val['usagevar'] = 0;
        \}

        if (isset(\$quota\_home\_val['storage'])) \{
                  \$quota\_val['limithome'] = \$quota\_home\_val['storage']['limit'] * 1024;
                  \$quota\_val['usagehome'] = \$quota\_home\_val['storage']['usage'] * 1024;
        \} else \{
                \$quota\_val['limithome'] = 0;
                \$quota\_val['usagehome'] = 0;
        \}

        return \$quota\_val;

    \}

\}
</code></pre>

\noindent\rule{\textwidth}{1pt}
\subsubsection{imp/lib/Quota/Ui.php}
\begin{itemize}
\item Function quota:


\end{itemize}
\begin{quote}
limitvar, usagevar, percentvar, messagevar.<br />
limithome, usagehome, percenthome, messagehome.


\end{quote}
Backup your original imp/lib/Quota/Ui.php and create a new Ui.php with the following code:

<pre><code class="language-php">
<?php
/**
 * Copyright 2012-2013 Horde LLC (http://www.horde.org/)
 *
 * See the enclosed file COPYING for license information (GPL). If you
 * did not receive this file, see http://www.horde.org/licenses/gpl.
 *
 * @category  Horde
 * @copyright 2012-2013 Horde LLC
 * @license   http://www.horde.org/licenses/gpl GPL
 * @package   IMP
 * Modified by Mauricio Jose T. Tecles <mtecles@biof.ufrj.br>
 * Updated 2013 December 18
 */

/**
 * Common code dealing with quota UI display.
 *
 * @author    Michael Slusarz <slusarz@horde.org>
 * @category  Horde
 * @copyright 2012-2013 Horde LLC
 * @license   http://www.horde.org/licenses/gpl GPL
 * @package   IMP
 */
class IMP\_Quota\_Ui
\{
    /**
     * Returns data needed to output quota.
     *
     * @param string \$mailbox  Mailbox to query.
     *
     * @return array  Array with these keys: class, message, percent.
     */
    public function quota(\$mailbox = null)
    \{
        global \$injector;

        if (!\$injector->getInstance('IMP\_Imap')->config->quota) \{
            return false;
        \}

        if (!is\_null(\$mailbox)) \{
            \$mailbox = IMP\_Mailbox::get(\$mailbox);
            if (\$mailbox->nonimap) \{
                return false;
            \}
        \}

        try \{
            \$quotaDriver = \$injector->getInstance('IMP\_Quota');
            \$quota = \$quotaDriver->getQuota(\$mailbox);
        \} catch (IMP\_Exception \$e) \{
            Horde::log(\$e, 'ERR');
            return false;
        \}

        if (empty(\$quota)) \{
            return false;
        \}

        \$strings = \$quotaDriver->getMessages();
        list(\$calc, \$unit) = \$quotaDriver->getUnit();
        \$ret = array(
            'classvar' => '',
            'percentvar' => 0,
            'classhome' => '',
            'percenthome' => 0
        );

        /* Quota for dev\_fldrs */
        unset(\$ret['messagehome']);
        if (\$quota['limithome'] != 0) \{
            \$quota['usagehome'] = \$quota['usagehome'] / \$calc;
            \$quota['limithome'] = \$quota['limithome'] / \$calc;
            \$ret['percenthome'] = (\$quota['usagehome'] * 100) / \$quota['limithome'];
 
            if (\$ret['percenthome'] >= 100) \{
                \$ret['classhome'] = 'quotaalert';
            \} elseif (\$ret['percenthome'] >= 90) \{
                \$ret['classhome'] = 'quotawarn';
            \}
 
            if (\$quota['usagevar'] != 0) \{
                \$ret['messagehome'] = sprintf(\$strings['shorth'], \$ret['percenthome'], \$quota['limithome'], \$unit);
                \$ret['percenthome'] = sprintf("\%.2f", \$ret['percenthome']);
            \} else \{
                \$ret['messagehome'] = sprintf(\$strings['sshorth'], \$ret['percenthome'], \$quota['limithome'], \$unit);
                \$ret['percenthome'] = sprintf("\%.2f", \$ret['percenthome']);
            \}
 
        \} else \{
            if (\$quota['usagehome'] != 0) \{
                if (\$quota['usagevar'] != 0) \{
                    \$quota['usagehome'] = \$quota['usagehome'] / \$calc;
                    \$ret['messagehome'] = sprintf(\$strings['nolimit\_shorth'], \$quota['usagehome'], \$unit);
                \} else \{
                    \$quota['usagehome'] = \$quota['usagehome'] / \$calc;
                    \$ret['messagehome'] = sprintf(\$strings['nolimit\_sshorth'], \$quota['usagehome'], \$unit);
                \}
            \} else \{
                \$ret['messagehome'] = \_(" ");
            \}
        \}
 
        /* Quota for dev\_inbx */
        if (\$quota['limitvar'] != 0) \{
            \$quota['usagevar'] = \$quota['usagevar'] / \$calc;
            \$quota['limitvar'] = \$quota['limitvar'] / \$calc;
            \$ret['percentvar'] = (\$quota['usagevar'] * 100) / \$quota['limitvar'];
 
            if (\$ret['percentvar'] >= 100) \{
                \$ret['classvar'] = 'quotaalert';
            \} elseif (\$ret['percentvar'] >= 90) \{
                \$ret['classvar'] = 'quotawarn';
            \}
 
            \$ret['messagevar'] = sprintf(\$strings['shortv'], \$ret['percentvar'], \$quota['limitvar'], \$unit);
            \$ret['percentvar'] = sprintf("\%.2f", \$ret['percentvar']);
        \} else \{
            if (\$quota['usagevar'] != 0) \{
                \$quota['usagevar'] = \$quota['usagevar'] / \$calc;
 
                \$ret['messagevar'] = sprintf(\$strings['nolimit\_shortv'], \$quota['usagevar'], \$unit);
            \} else \{
                \$ret['messagevar'] = \_(" ");
            \}
        \}

        return \$ret;
    \}

\}
</code></pre>

\noindent\rule{\textwidth}{1pt}
\subsubsection{imp/lib/Quota.php}
\begin{itemize}
\item Only short formats.


\end{itemize}
Backup your original imp/lib/Quota.php and replace function construct with the following code:

<pre><code class="language-php">
    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']
                : \_("Inbox: \%.0f\%\% of \%.1f \%s"),
            'shorth' => isset(\$this->\_params['format']['shorth'])
                ? \$this->\_params['format']['shorth']
                : \_(" - Folders: \%.0f\%\% of \%.1f \%s"),
            'sshorth' => isset(\$this->\_params['format']['sshorth'])
                ? \$this->\_params['format']['sshorth']
                : \_("Folders: \%.0f\%\% of \%.1f \%s"),
            'nolimit\_shortv' => isset(\$this->\_params['format']['nolimit\_short'])
                ? \$this->\_params['format']['nolimit\_short']
                : \_("Inbox: \%.1f \%s"),
            'nolimit\_shorth' => isset(\$this->\_params['format']['nolimit\_shorth'])
                ? \$this->\_params['format']['nolimit\_shorth']
                : \_(" - Folders: \%.1f \%s"),
            'nolimit\_sshorth' => isset(\$this->\_params['format']['nolimit\_sshorth'])
                ? \$this->\_params['format']['nolimit\_sshorth']
                : \_("Folders: \%.1f \%s"),
        );
    \}
</code></pre>

\noindent\rule{\textwidth}{1pt}
\subsubsection{imp/lib/Ajax/Queue.php}
\begin{itemize}
\item mv, pv, lv: quota message, percentage and class for Inbox.


\item mh, ph, lh: quota message, percentage and class for folders.


\item merrov, mvclasse, merroh, mhclasse: Message when usage > 90\%.


\end{itemize}
Backup your original imp/lib/Ajax/Queue.php and replace function add with the following code:

<pre><code class="language-php">
    public function add(IMP\_Ajax\_Application \$ajax)
    \{
        global \$injector, \$registry;

        /* Add compose attachment information. */
        if (!empty(\$this->\_atc)) \{
            \$ajax->addTask('compose-atc', \$this->\_atc);
            \$this->\_atc = array();
        \}

        /* Add compose information. */
        if (!is\_null(\$this->\_compose)) \{
            \$compose = new stdClass;
            if (!\$this->\_compose->additionalAttachmentsAllowed()) \{
                \$compose->atclimit = 1;
            \}
            \$compose->cacheid = \$this->\_compose->getCacheId();

            \$ajax->addTask('compose', \$compose);
            \$this->\_compose = null;
        \}

        /* Add flag information. */
        if (!empty(\$this->\_flag)) \{
            \$ajax->addTask('flag', \$this->\_flag);
            \$this->\_flag = array();
        \}

        /* Add flag configuration. */
        if (\$this->\_flagconfig) \{
            \$flags = array();

            foreach (\$injector->getInstance('IMP\_Flags')->getList() as \$val) \{
                \$flags[] = array\_filter(array(
                    'a' => \$val->canset,
                    'b' => \$val->bgdefault ? null : \$val->bgcolor,
                    'c' => \$val->css,
                    'f' => \$val->fgcolor,
                    'i' => \$val->css ? null : \$val->cssicon,
                    'id' => \$val->id,
                    'l' => \$val->label,
                    's' => intval(\$val instanceof IMP\_Flag\_Imap),
                    'u' => intval(\$val instanceof IMP\_Flag\_User)
                ));
            \}

            \$ajax->addTask('flag-config', \$flags);
        \}

        /* Add folder tree information. */
        \$imptree = \$injector->getInstance('IMP\_Imap\_Tree');
        \$imptree->setIteratorFilter(
            (\$registry->getView() == \$registry::VIEW\_DYNAMIC)
                ? \$imptree::FLIST\_NOSPECIALMBOXES
                : 0
        );
        \$out = \$imptree->getAjaxResponse();
        if (!empty(\$out)) \{
            \$ajax->addTask('mailbox', array\_merge(\$out, \$this->\_mailboxOpts));
        \}

        /* Add mail log information. */
        if (!empty(\$this->\_maillog)) \{
            \$imp\_maillog = \$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->buid = intval(\$val['buid']);
                    \$log\_ob->log = \$tmp;
                    \$log\_ob->mbox = \$val['mailbox']->form\_to;
                    \$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;
        \}

        if (count(\$poll\_list)) \{
            \$imap\_ob = \$injector->getInstance('IMP\_Imap');
            if (\$imap\_ob->init) \{
                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 !== false) \&\&
            (\$quotadata = \$injector->getInstance('IMP\_Quota\_Ui')->quota(\$this->\_quota))) \{
            /* Quota for dev\_inbx */
            \$merrov = null;
            if (round(\$quotadata['percentvar']) >= 100) \{
                \$mvclasse = 'horde.error';
                \$merrov = sprintf("Inbox above limit.");
             \} 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';
                \$merroh = sprintf("Folders above limit.");
            \} 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;
        \}
	\}
</code></pre>

\noindent\rule{\textwidth}{1pt}
\subsubsection{imp/lib/View/Subinfo.php}
\begin{itemize}
\item function \_\_construct: quotaClassV, quotaTextV, quotaClassH, quotaTextH.


\end{itemize}
Backup your original imp/lib/View/Subinfo.php and replace function construct with the following code:

<pre><code class="language-php">
    public function \_\_construct(array \$config = array())
    \{
        \$config['templatePath'] = IMP\_TEMPLATES . '/basic';
        parent::\_\_construct(\$config);

        \$quotadata = \$GLOBALS['injector']->getInstance('IMP\_Quota\_Ui')->quota(isset(\$config['mailbox']) ? \$config['mailbox'] : null);
        if (!empty(\$quotadata)) \{
            \$this->quotaClassV = \$quotadata['classvar'];
            \$this->quotaTextV = \$quotadata['messagevar'];
            \$this->quotaClassH = \$quotadata['classhome'];
            \$this->quotaTextH = \$quotadata['messagehome'];
			\}
    \}
</code></pre>

\noindent\rule{\textwidth}{1pt}
\subsubsection{imp/js/dimpbase.js}
\begin{itemize}
\item quotaCallback


\end{itemize}
\begin{quote}
quotaV, mv, lv.<br />
quotaH, mh, lh.


\end{quote}
Backup your original imp/js/dimpbase.js. Edit dimpbase.js and replace quotaCallback with the following code:

<pre><code class="language-php">
    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;
        \}
    \},
</code></pre>

\noindent\rule{\textwidth}{1pt}
\subsubsection{imp/templates/basic/subinfo.html.php}
\begin{itemize}
\item quotaTextV, quotaClassV, quotaTextH, quotaClassH.


\end{itemize}
Backup your original imp/templates/basic/subinfo.html.php and replace the following code:<br />
From:

<pre><code class="language-php">
<?php if (\$this->quotaText): ?>
<span class="<?php echo \$this->quotaClass ?>"><?php echo \$this->quotaText ?></span>
<?php endif ?>
</code></pre>
To:

<pre><code class="language-php">
<?php if (\$this->quotaTextV): ?>
<span class="<?php echo \$this->quotaClassV ?>"><?php echo \$this->quotaTextV ?></span>
<?php endif ?>
<?php if (\$this->quotaTextH): ?>
<span class="<?php echo \$this->quotaClassH ?>"><?php echo \$this->quotaTextH ?></span>
<?php endif ?>
</code></pre>

\noindent\rule{\textwidth}{1pt}
\subsubsection{imp/templates/dynamic/mailbox\_subinfo.html.php}
\begin{itemize}
\item quota-textV, quota-textH.


\end{itemize}
Backup your original imp/templates/dynamic/mailbox\_subinfo.html.php and replace the following code:<br />
From:

<pre><code class="language-php">
<?php if (\$this->quota): ?>
<span id="quota-text"></span>
<?php endif ?>
</code></pre>
To:

<pre><code class="language-php">
<?php if (\$this->quota): ?>
<span id="quota-textV"></span><span id="quota-textH"></span>
<?php endif ?>
</code></pre>
\end{document}
