<?php
/** @const INGO_BLACKLIST_MARKER String that can't be a valid folder name used to mark blacklisted email as deleted. */
define('INGO_BLACKLIST_MARKER', '++DELETE++');

/**
 * Ingo base class.
 *
 * $Horde: ingo/lib/Ingo.php,v 1.69 2004/11/23 22:00:54 chuck Exp $
 *
 * See the enclosed file LICENSE for license information. If you
 * did not receive this file, see http://www.horde.org/licenses.
 *
 * @author  Mike Cochrane <mike@graftonhall.co.nz>
 * @version $Revision: 1.69 $
 * @since   Ingo 1.0
 * @package Ingo
 */
class Ingo {

    /**
     * Generates a folder widget.
     * If an application is available that provides a folderlist method
     * then a &lt;select&gt; input is created else a simple text field
     * is returned.
     *
     * @access public
     *
     * @param optional string $value    The current value for the field.
     * @param optional string $form     The form name for the newFolderName()
     *                                  call.
     * @param optional string $tagname  The label for the select tag.
     *
     * @return string  The HTML to render the field.
     */
    function flistSelect($value = null, $form = null, $tagname = 'actionvalue')
    {
        global $conf, $registry;

        if (!empty($conf['rules']['usefolderapi']) &&
            $registry->hasMethod('mail/folderlist')) {
            $mailboxes = $registry->call('mail/folderlist');
            if (!is_a($mailboxes, 'PEAR_Error')) {
                $createfolder = $registry->hasMethod('mail/createFolder');

                $text = '<select name="' . $tagname . '"';
                if ($createfolder) {
                    $text .= ' onchange="newFolderName(\'' . $form . '\');"';
                }
                $text .= ">\n";
                $text .= '<option value="">' . _("Select target folder") . "</option>\n";

                if ($registry->hasMethod('mail/createFolder')) {
                    $text .= '<option value="">' . _("Create new folder") . "</option>\n";
                }

                require_once 'Horde/Text.php';

                foreach ($mailboxes as $mbox) {
                    $sel = ($mbox['val'] && ($mbox['val'] === $value)) ? ' selected="selected"' : '';
                    $val = htmlspecialchars($mbox['val']);
                    $label = $mbox['abbrev'];
                    $text .= sprintf('<option value="%s"%s>%s</option>%s', $val, $sel, Text::htmlSpaces($label), "\n");
                }

                $text .= '</select>';
                return $text;
            }
        }

        return '<input name="' . $tagname . '" size="40" value="' . $value . '" />';
    }

    /**
     * Creates a new IMAP folder via an api call.
     *
     * @access public
     *
     * @param string $folder  The name of the folder to create.
     *
     * @return boolean  True on success.
     */
    function createFolder($folder)
    {
        global $registry;

        if ($registry->hasMethod('mail/createFolder')) {
             $result = $registry->call('mail/createFolder', array('folder' => $folder));
        }

        return $result;
    }

    /**
     * Connects to the backend and uploads the script and sets it
     * active.
     *
     * @access public
     *
     * @param string $script                The script to set active.
     * @param optional boolean $deactivate  If true, notification will
     *                                      identify the script as
     *                                      deactivated instead of activated.
     *
     * @return boolean  True on success, false on failure.
     */
    function activateScript($script, $deactivate = false)
    {
        global $notification;

        require_once INGO_BASE . '/lib/Driver.php';

        // Set authentication parameters.
        if (!empty($_SESSION['ingo']['backend']['hordeauth'])) {
            $username = ($_SESSION['ingo']['backend']['hordeauth'] === 'full')
                        ? Auth::getAuth() : Auth::getBareAuth();
            $password = Auth::getCredential('password');
        } else if (isset($_SESSION['ingo']['backend']['params']['username']) && isset($_SESSION['ingo']['backend']['params']['password'])) {
            $username = $_SESSION['ingo']['backend']['params']['username'];
            $password = $_SESSION['ingo']['backend']['params']['password'];
        } else {
            $username = Auth::getBareAuth();
            $password = Auth::getCredential('password');
        }

        $driver = &Ingo_Driver::singleton($_SESSION['ingo']['backend']['driver'], $_SESSION['ingo']['backend']['params']);
        $res = $driver->setScriptActive($script, $username, $password);
        if (is_a($res, 'PEAR_Error')) {
            $msg = ($deactivate)
              ? _("There was an error deactivating the script.")
              : _("There was an error activating the script.");
            $notification->push($msg . ' ' . _("The driver said: ") . $res->getMessage(), 'horde.error');
            return false;
        } elseif ($res === true) {
            $msg = ($deactivate)
              ? _("Script successfully deactivated.")
              : _("Script successfully activated.");
            $notification->push($msg, 'horde.success');
            return true;
        }

        return false;
    }

    /**
     * Connects to the backend and returns the currently active script.
     *
     * @access public
     *
     * @return string  The currently active script.
     */
    function getScript()
    {
        require_once INGO_BASE . '/lib/Driver.php';

        $uid = ($_SESSION['ingo']['backend']['hordeauth'] === 'full')
               ? Auth::getAuth() : Auth::getBareAuth();

        $driver = &Ingo_Driver::singleton($_SESSION['ingo']['backend']['driver'], $_SESSION['ingo']['backend']['params']);
        return $driver->getScript($uid, Auth::getCredential('password'));
    }

    /**
     * Determine the backend to use.
     *
     * This decision is based on the global 'SERVER_NAME' and 'HTTP_HOST'
     * server variables and the contents of the 'preferred' either field
     * in the backend's definition.  The 'preferred' field may take a
     * single value or an array of multiple values.
     *
     * @access public
     *
     * @return array  The backend entry.
     *                Calls Horde::fatal() on error.
     */
    function getBackend()
    {
        include INGO_BASE . '/config/backends.php';
        if (!isset($backends) || !is_array($backends)) {
            Horde::fatal(PEAR::raiseError(_("No backends configured in backends.php")), __FILE__, __LINE__);
        }

        foreach ($backends as $temp) {
            if (!isset($backend)) {
                $backend = $temp;
            } elseif (!empty($temp['preferred'])) {
                if (is_array($temp['preferred'])) {
                    foreach ($temp['preferred'] as $val) {
                        if (($val == $_SERVER['SERVER_NAME']) ||
                            ($val == $_SERVER['HTTP_HOST'])) {
                            $backend = $temp;
                        }
                    }
                } elseif (($temp['preferred'] == $_SERVER['SERVER_NAME']) ||
                          ($temp['preferred'] == $_SERVER['HTTP_HOST'])) {
                    $backend = $temp;
                }
            }
        }

        /* Check for valid backend configuration. */
        if (!isset($backend)) {
            Horde::fatal(PEAR::raiseError(_("No backend configured for this host")), __FILE__, __LINE__);
        } elseif (empty($backend['script'])) {
            Horde::fatal(PEAR::raiseError(sprintf(_("No '%s' element found in backend configuration."), 'script')), __FILE__, __LINE__);
        } elseif (empty($backend['driver'])) {
            Horde::fatal(PEAR::raiseError(sprintf(_("No '%s' element found in backend configuration."), 'driver')), __FILE__, __LINE__);
        }

        /* Make sure the 'params' entry exists. */
        if (!isset($backend['params'])) {
            $backend['params'] = array();
        }

        return $backend;
    }

    /**
     * Does all the work in updating the script on the server.
     *
     * @access public
     */
    function updateScript()
    {
        global $notification;

        if ($_SESSION['ingo']['script_generate']) {
            $ingo_script = &Ingo::loadIngoScript();
            if (!$ingo_script) {
                $notification->push(_("Script not updated."), 'horde.error');
            } else {
                /* Generate and activate the script. */
                $script = $ingo_script->generate();
                Ingo::activateScript($script);
            }
        }
    }

    /**
     * Loads a Ingo_Script:: backend and checks for errors.
     *
     * @access public
     *
     * @return mixed  Ingo_Script:: object on success, false on failure.
     */
    function &loadIngoScript()
    {
        global $notification;

        require_once INGO_BASE . '/lib/Script.php';
        $ingo_script = &Ingo_Script::singleton($_SESSION['ingo']['backend']['script'], isset($_SESSION['ingo']['backend']['scriptparams']) ? $_SESSION['ingo']['backend']['scriptparams'] : array());
        if (is_a($ingo_script, 'PEAR_Error')) {
            $notification->push($ingo_script->getMessage(), 'horde.error');
            return false;
        }

        return $ingo_script;
    }

    /**
     * Build Ingo's list of menu items.
     *
     * @access public
     */
    function getMenu($returnType = 'object')
    {
        require_once 'Horde/Menu.php';

        $menu = &new Menu();
        $menu->add(Horde::applicationUrl('filters.php'), _("Filter _Rules"), 'ingo.png', null, null, null, basename($_SERVER['PHP_SELF']) == 'index.php' ? 'current' : null);
        if (!is_a($whitelist_url = $GLOBALS['registry']->link('mail/showWhitelist'), 'PEAR_Error')) {
            $menu->add(Horde::url($whitelist_url), _("_Whitelist"), 'whitelist.png');
        }
        if (!is_a($blacklist_url = $GLOBALS['registry']->link('mail/showBlacklist'), 'PEAR_Error')) {
            $menu->add(Horde::url($blacklist_url), _("_Blacklist"), 'blacklist.png');
        }
        if (in_array(INGO_STORAGE_ACTION_VACATION, $_SESSION['ingo']['script_categories'])) {
            $menu->add(Horde::applicationUrl('vacation.php'), _("_Vacation"), 'vacation.png');
        }
        if (in_array(INGO_STORAGE_ACTION_FORWARD, $_SESSION['ingo']['script_categories'])) {
            $menu->add(Horde::applicationUrl('forward.php'), _("_Forward"), 'forward.png');
        }
        if ($_SESSION['ingo']['script_generate']) {
            $menu->add(Horde::applicationUrl('script.php'), _("_Script"), 'script.png');
        }

        if ($returnType == 'object') {
            return $menu;
        } else {
            return $menu->render();
        }
    }

}
