PHP5/H4-ify
authorJan Schneider <jan@horde.org>
Fri, 10 Dec 2010 17:32:25 +0000 (18:32 +0100)
committerJan Schneider <jan@horde.org>
Fri, 10 Dec 2010 17:32:25 +0000 (18:32 +0100)
40 files changed:
vilma/config/hooks.php.dist
vilma/domains/delete.php
vilma/domains/edit.php
vilma/domains/index.php
vilma/lib/Application.php
vilma/lib/Driver.php
vilma/lib/Driver/Qmailldap.php [new file with mode: 0644]
vilma/lib/Driver/Sql.php [new file with mode: 0644]
vilma/lib/Driver/qmailldap.php [deleted file]
vilma/lib/Driver/sql.php [deleted file]
vilma/lib/Form/DeleteDomain.php [new file with mode: 0644]
vilma/lib/Form/EditAlias.php [new file with mode: 0644]
vilma/lib/Form/EditDomain.php [new file with mode: 0644]
vilma/lib/Form/EditForward.php [new file with mode: 0644]
vilma/lib/Form/EditUser.php [new file with mode: 0644]
vilma/lib/Forms/DeleteDomainForm.php [deleted file]
vilma/lib/Forms/EditAliasForm.php [deleted file]
vilma/lib/Forms/EditDomainForm.php [deleted file]
vilma/lib/Forms/EditForwardForm.php [deleted file]
vilma/lib/Forms/EditUserForm.php [deleted file]
vilma/lib/MailboxDriver.php
vilma/lib/MailboxDriver/Hooks.php [new file with mode: 0644]
vilma/lib/MailboxDriver/Imap.php [new file with mode: 0644]
vilma/lib/MailboxDriver/Maildrop.php [new file with mode: 0644]
vilma/lib/MailboxDriver/Null.php [new file with mode: 0644]
vilma/lib/MailboxDriver/hooks.php [deleted file]
vilma/lib/MailboxDriver/imap.php [deleted file]
vilma/lib/MailboxDriver/maildrop.php [deleted file]
vilma/lib/MailboxDriver/null.php [deleted file]
vilma/lib/Vilma.php
vilma/lib/tests/driver.phpt
vilma/scripts/create_mailboxes.php
vilma/users/delete.php
vilma/users/edit.php
vilma/users/editAlias.php
vilma/users/editForward.php
vilma/users/index.php
vilma/virtuals/delete.php
vilma/virtuals/edit.php
vilma/virtuals/index.php

index 927602c..062ebd1 100644 (file)
@@ -19,7 +19,7 @@
 // "control/locals" file on an interval from cron(8) using some kind of script
 // to pull a list of domains from Horde using (for example) XML-RPC.
 
-// if (!function_exists('_vilma_hook_savedomain')) {
+// if (!function_exists('_vilma_hook_saveDomain')) {
 //     function _vilma_hook_savedomain($info = null)
 //     {
 //         if ($info === null || !isset($info['domain_name'])) {
@@ -55,7 +55,7 @@
 // This hook does the opposite of the above:  Remove a domain from the
 // "control/locals" file.
 
-// if (!function_exists('_vilma_hook_deletedomain')) {
+// if (!function_exists('_vilma_hook_deleteDomain')) {
 //     function _vilma_hook_deletedomain($domain = null)
 //     {
 //         if ($domain === null) {
@@ -89,7 +89,7 @@
 
 // This function will turn an array of additional LDAP attributes that will be
 // added to the attributes created by the LDAP driver.
-//if (!function_exists('_vilma_hook_getldapattrs')) {
+//if (!function_exists('_vilma_hook_getLDAPAttrs')) {
 //    function _vilma_hook_getldapattrs($attrs)
 //    {
 //        $attrs['deliverymode'] = 'nolocal';
index 838298a..2a0b66d 100644 (file)
 require_once dirname(__FILE__) . '/../lib/Application.php';
 $vilma = Horde_Registry::appInit('vilma');
 
-require_once VILMA_BASE . '/lib/Forms/DeleteDomainForm.php';
-
 /* Only admin should be using this. */
 if (!Vilma::hasPermission($domain)) {
-    $registry->authenticateFailure('vilma', $e);
+    $registry->authenticateFailure('vilma');
 }
 
 $vars = Horde_Variables::getDefaultVariables();
-$form = new DeleteDomainForm($vars);
+try {
+    $form = new Vilma_Form_DeleteDomain($vars);
+} catch (Exception $e) {
+    $notification->push($e);
+    Horde::url('domains/index.php', true)->redirect();
+}
+
+if ($vars->get('submitbutton') == _("Do not delete")) {
+    $notification->push(_("Domain not deleted."), 'horde.message');
+    Horde::url('domains/index.php', true)->redirect();
+}
 
 if ($vars->get('submitbutton') == _("Delete")) {
     if ($form->validate($vars)) {
         $form->getInfo($vars, $info);
-        $delete = $vilma->driver->deleteDomain($info['domain_id']);
-        if (is_a($delete, 'PEAR_Error')) {
-            Horde::logMessage($delete, 'ERR');
-            $notification->push(sprintf(_("Error deleting domain. %s."), $delete->getMessage()), 'horde.error');
-        } else {
+        try {
+            $delete = $vilma->driver->deleteDomain($info['domain_id']);
             $notification->push(_("Domain deleted."), 'horde.success');
             Horde::url('domains/index.php', true)->redirect();
+        } catch (Exception $e) {
+            $notification->push(sprintf(_("Error deleting domain. %s."), $e->getMessage()), 'horde.error');
         }
     }
-} elseif ($vars->get('submitbutton') == _("Do not delete")) {
-    $notification->push(_("Domain not deleted."), 'horde.message');
-    Horde::url('domains/index.php', true)->redirect();
 }
 
 /* Render the form. */
-require_once 'Horde/Form/Renderer.php';
 $renderer = new Horde_Form_Renderer();
 
+$template = $injector->createInstance('Horde_Template');
 Horde::startBuffer();
 $form->renderActive($renderer, $vars, 'delete.php', 'post');
-$main = Horde::endBuffer();
-
-$template = $injector->createInstance('Horde_Template');
-$template->set('main', $main);
-$template->set('menu', Vilma::getMenu('string'));
-
+$template->set('main', Horde::endBuffer());
+$template->set('menu', Horde::menu());
 Horde::startBuffer();
 $notification->notify(array('listeners' => 'status'));
 $template->set('notify', Horde::endBuffer());
index ec26463..3199151 100644 (file)
 require_once dirname(__FILE__) . '/../lib/Application.php';
 $vilma = Horde_Registry::appInit('vilma');
 
-require_once VILMA_BASE . '/lib/Forms/EditDomainForm.php';
-
 /* Only admin should be using this. */
 if (!Vilma::hasPermission($domain)) {
-    $registry->authenticateFailure('vilma', $e);
+    $registry->authenticateFailure('vilma');
 }
 
-//$domain_id = Horde_Util::getFormData('domain_id');
 $vars = Horde_Variables::getDefaultVariables();
-$form = new EditDomainForm($vars);
+try {
+    $form = new Vilma_Form_EditDomain($vars);
+} catch (Exception $e) {
+    $notification->push($e);
+    Horde::url('domains/index.php', true)->redirect();
+}
 
 if ($form->validate($vars)) {
     $form->getInfo($vars, $info);
     $info['name'] = Horde_String::lower($info['name']);
-    $domain_id = $vilma->driver->saveDomain($info);
-    if (is_a($domain_id, 'PEAR_Error')) {
-        Horde::logMessage($domain_id, 'ERR');
-        $notification->push(sprintf(_("Error saving domain: %s."), $domain_id->getMessage()), 'horde.error');
-    } else {
+    try {
+        $domain_id = $vilma->driver->saveDomain($info);
         $notification->push(_("Domain saved."), 'horde.success');
         Horde::url('domains/index.php', true)->redirect();
+    } catch (Exception $e) {
+        $notification->push(sprintf(_("Error saving domain: %s."), $e->getMessage()), 'horde.error');
     }
 }
 
 /* Render the form. */
-require_once 'Horde/Form/Renderer.php';
 $renderer = new Horde_Form_Renderer();
 
+$template = $injector->createInstance('Horde_Template');
 Horde::startBuffer();
 $form->renderActive($renderer, $vars, 'edit.php', 'post');
-$main = Horde::endBuffer();
-
-$template = $injector->createInstance('Horde_Template');
-$template->set('main', $main);
-$template->set('menu', Vilma::getMenu('string'));
-
+$template->set('main', Horde::endBuffer());
+$template->set('menu', Horde::menu());
 Horde::startBuffer();
 $notification->notify(array('listeners' => 'status'));
 $template->set('notify', Horde::endBuffer());
index f7042c1..1d90ff2 100644 (file)
@@ -17,28 +17,29 @@ if (!Vilma::hasPermission()) {
 }
 
 // Having a current domain doesn't make sense on this page
-Vilma::setCurDomain(false);
+Vilma::setCurDomain();
 
-$domains = $vilma->driver->getDomains();
-if (is_a($domains, 'PEAR_Error')) {
-    $notification->push($domains, 'horde.error');
+try {
+    $domains = $vilma->driver->getDomains();
+} catch (Exception $e) {
+    $notification->push($e, 'horde.error');
     $domains = array();
 }
-foreach ($domains as $id => $domain) {
-    $url = Horde::url('domains/edit.php');
-    $domains[$id]['edit_url'] = Horde_Util::addParameter($url, 'domain_id', $domain['domain_id']);
-    $url = Horde::url('domains/delete.php');
-    $domains[$id]['del_url'] = Horde_Util::addParameter($url, 'domain_id', $domain['domain_id']);
-    $url = Horde::url('users/index.php');
-    $domains[$id]['view_url'] = Horde_Util::addParameter($url, 'domain_id', $domain['domain_id']);
+
+$editurl   = Horde::url('domains/edit.php');
+$deleteurl = Horde::url('domains/delete.php');
+$userurl   = Horde::url('users/index.php');
+foreach ($domains as &$domain) {
+    $domain['edit_url'] = $editurl->copy()->add('domain_id', $domain['domain_id']);
+    $domain['del_url']  = $deleteurl->copy()->add('domain_id', $domain['domain_id']);
+    $domain['view_url'] = $userurl->copy()->add('domain_id', $domain['domain_id']);
 }
 
 /* Set up the template fields. */
 $template = $injector->createInstance('Horde_Template');
 $template->setOption('gettext', true);
-$template->set('domains', $domains, true);
+$template->set('domains', $domains);
 $template->set('menu', Horde::menu());
-
 Horde::startBuffer();
 $notification->notify(array('listeners' => 'status'));
 $template->set('notify', Horde::endBuffer());
index 732b6d3..53fe8c5 100644 (file)
@@ -49,7 +49,7 @@ class Vilma_Application extends Horde_Registry_Application
 
     protected function _init()
     {
-        $this->driver = Vilma_Driver::singleton();
+        $this->driver = Vilma_Driver::factory();
 
         // Get the currently active domain, possibly storing a change into the
         // session.
index c904595..276cd11 100644 (file)
@@ -5,8 +5,8 @@
  * See the enclosed file LICENSE for license information (BSD). If you did not
  * did not receive this file, see http://cvs.horde.org/co.php/vilma/LICENSE.
  *
- * @author Marko Djukic <marko@oblo.com>
- * @author Daniel Collins <horde_dev@argentproductions.com>
+ * @author  Marko Djukic <marko@oblo.com>
+ * @author  Daniel Collins <horde_dev@argentproductions.com>
  * @package Vilma
  */
 abstract class Vilma_Driver
@@ -16,133 +16,218 @@ abstract class Vilma_Driver
      *
      * @var array
      */
-    var $_params = array();
+    protected $_params = array();
 
     /**
-     * Constructor
+     * Constructor.
      *
      * @param array $params  Any parameters needed for this driver.
      */
-    function Vilma_Driver($params)
+    public function __construct(array $params)
     {
         $this->_params = $params;
     }
 
     /**
-     * Returns a list of all users, aliases, or groups and forwards for a
-     * domain.
+     * Returns the list of domains from the backend.
      *
-     * @param string $domain      Domain on which to search.
-     * @param string $type        Only return a specific type. One of 'all',
-     *                            'user', 'alias','forward', or 'group'.
-     * @param string $key         Sort list by this key.
-     * @param integer $direction  Sort direction.
+     * @return array  All the domains and their data in an array.
+     */
+    abstract public function getDomains();
+
+    /**
+     * Returns the specified domain information from the backend.
      *
-     * @return array Account information for this domain
+     * @param integer $domain_id  The id of the domain to fetch.
+     *
+     * @return array  The domain's information in an array.
      */
-    public function getAddresses($domain, $type = 'all', $key = 'user_name',
-                                 $direction = 0)
-    {
-        $addresses = $this->_getAddresses($domain, $type);
-        Horde_Array::arraySort($addresses, $key, $direction, true);
-        return $addresses;
-    }
+    abstract public function getDomain($domain_id);
 
     /**
-     * Returns a list of all users, aliases, or groups and forwards for a
-     * domain.
+     * Given a domain name returns the information from the backend.
      *
-     * @param string $domain      Domain on which to search.
-     * @param string $type        Only return a specific type. One of 'all',
-     *                            'user', 'alias','forward', or 'group'.
-     * @param string $key         Sort list by this key.
-     * @param integer $direction  Sort direction.
+     * @param string $name  The name of the domain to fetch.
      *
-     * @return array Account information for this domain
+     * @return array  The domain's information in an array.
      */
-    abstract protected function _getAddresses($domain, $type = 'all');
+    abstract public function getDomainByName($domain_name);
 
     /**
-     * Returns all the users sorted by domain and as arrays of each domain.
+     * Saves a domain with the provided information.
      *
-     * @return array  An array of domains then users for each domain.
+     * @param array $info  Array of details to save the domain.
+     *
+     * @throws Vilma_Exception
      */
-    function getAllUsers()
+    public function saveDomain($info)
     {
-        /* Get all users from backend. */
-        $users = &$this->getUsers();
+        $this->_saveDomain($info);
+        Horde::callHook('saveDomain', array($info), 'vilma');
+    }
 
-        /* Determine the domain for each user and plug into array by domain. */
-        $users_by_domain = array();
+    /**
+     * Saves a domain with the provided information.
+     *
+     * @param array $info  Array of details to save the domain.
+     */
+    abstract protected function _saveDomain($info);
+
+    /**
+     * Deletes a domain and all the users and virtuals within it.
+     *
+     * @param integer $domain_id  The id of the domain to delete.
+     *
+     * @throws Vilma_Exception
+     */
+    public function deleteDomain($domain_id)
+    {
+        $domain_record = $this->getDomain($domain_id);
+        $users = $this->getUsers($domain_record['domain_name']);
         foreach ($users as $user) {
-            $domain_name = Vilma::stripDomain($user['user_name']);
-            $users_by_domain[$domain_name][] = $user;
+            $this->_deleteUser($user['user_id']);
         }
+        $this->_deleteDomain($domain_id);
+        Horde::callHook('deleteDomain', array($domain_record['domain_name']), 'vilma');
+    }
 
-        /* Sort by domain. */
-        ksort($users_by_domain);
-        /* Sort each domain's users by user name. */
-        require_once 'Horde/Array.php';
-        foreach ($users_by_domain as $key => $val) {
-            Horde_Array::arraySort($users_by_domain[$key], 'user_name');
-        }
+    /**
+     * Deletes a domain.
+     *
+     * @param integer $domain_id  The id of the domain to delete.
+     *
+     * @throws Vilma_Exception
+     */
+    abstract protected function _deleteDomain($domain_id);
 
-        return $users_by_domain;
+    /**
+     * Returns the user who is the domain administrator.
+     *
+     * @todo  This should be replaced by moving all permissions into Horde
+     *        permissions.
+     *
+     * @param string $domain_name  The name of the domain for which to
+     *                             return the administrator.
+     *
+     * @return string  The domain adminstrator.
+     * @throws Vilma_Exception
+     */
+    public function getDomainAdmin($domain_name)
+    {
+        $domain = $this->getDomainByName($domain_name);
+        return $domain['domain_admin'];
     }
 
     /**
+     * Returns the configured quota for this domain.
+     *
+     * @param string $domain_name  The name of the domain for which to
+     *                             return the quota.
+     *
+     * @return integer  The domain quota.
+     * @throws Vilma_Exception
+     */
+    public function getDomainQuota($domain_name)
+    {
+        $domain = $this->getDomainByName($domain_name);
+        return $domain['domain_quota'];
+    }
+
+    /**
+     * Returns the maximum number of users allowed for a given domain.
+     *
+     * @param string $domain_name  The name of the domain for which to
+     *                             return the maximum users.
+     *
+     * @return integer The maximum number of allowed users.
+     * @throws Vilma_Exception
+     */
+    public function getDomainMaxUsers($domain_name)
+    {
+        $domain = $this->getDomainByName($domain_name);
+        return $domain['max_users'];
+    }
+
+    /**
+     * Returns the current number of users for a domain.
+     *
+     * @param string $domain_name  The name of the domain for which to
+     *                             get the current number of users.
+     *
+     * @return integer  The current number of users.
+     */
+    abstract public function getDomainNumUsers($domain_name);
+
+    /**
      * Checks if the given domain is below the maximum allowed users.
      *
      * @param string $domain  The domain name to check.
      *
      * @return boolean  True if the domain does not have a maximum limit (0) or
      *                  current number of users is below the maximum number
-     *                  allowed. Otherwise false.
+     *                  allowed.
      */
-    function isBelowMaxUsers($domain)
+    public function isBelowMaxUsers($domain)
     {
         /* Get the maximum number of users for this domain. */
         $max_users = $this->getDomainMaxUsers($domain);
-        if ($max_users == '0') {
+        if (!$max_users) {
             /* No maximum. */
             return true;
         }
 
         /* Get the current number of users. */
-        $num_users = $this->getDomainNumUsers($domain);
-
-        return ($num_users < $max_users);
+        return $this->getDomainNumUsers($domain) < $max_users;
     }
 
     /**
-     * Gets an array of information related to the address passed in.
-     * This method may be overridden by the backend driver if there is a more
-     * efficient way to do this than a linear array search
+     * Returns all available users, if a domain name is passed then limit the
+     * list of users only to those users.
      *
-     * @param string $address  Address for which information will be pulled
-     * @param string $type     Address type to request
-     *                         One of 'user', 'alias', 'grpfwd' or 'any'
-     *                         Defaults to 'any'
+     * @param string $domain  The name of the domain for which to fetch the
+     *                        users.
      *
-     * @return mixed  Array of user information on success, empty array
-     *                if the user does not exist, PEAR_Error on failure
+     * @return array  The available users and their stored information.
+     * @throws Vilma_Exception
+     */
+    abstract public function getUsers($domain = null);
+
+    /**
+     * Returns all the users sorted by domain and as arrays of each domain.
+     *
+     * @return array  An array of domains then users for each domain.
      */
-    function getAddressInfo($address, $type = 'all')
+    public function getAllUsers()
     {
-        Horde::logMessage("Get Addresses Called for $domain with type $type and key $key", 'DEBUG');
-        $domain = Vilma::stripDomain($address);
-        $addresses = $this->getAddresses($domain, $type);
-        foreach($addresses as $addrinfo) {
-            if ($addrinfo['id'] == $address) {
-                return $addrinfo;
-            } else if ($addrinfo['address'] == $address) {
-                return $addrinfo;
-            }
+        /* Determine the domain for each user and plug into array by domain. */
+        $users = array();
+        foreach ($this->getUsers() as $user) {
+            $domain = Vilma::stripDomain($user['user_name']);
+            $users[$domain][] = $user;
         }
-        throw new Vilma_Exception(sprintf(_("No such address %s of type %s found."), $address, $type));
+
+        /* Sort by domain. */
+        ksort($users);
+
+        /* Sort each domain's users by user name. */
+        foreach ($users as $key => $val) {
+            Horde_Array::arraySort($users[$key], 'user_name');
+        }
+
+        return $users;
     }
 
     /**
+     * Returns the user information for a given user id.
+     *
+     * @param integer $user_id  The id of the user for which to fetch
+     *                          information.
+     *
+     * @return array  The user information.
+     */
+    abstract public function getUser($user_id);
+
+    /**
      * Does a series of checks for a given user to determine the status.
      *
      * @param array $user  The user's details in an array as returned by the
@@ -151,33 +236,28 @@ abstract class Vilma_Driver
      * @return array  Either an array of error messages found during the checks
      *                or an array with a single element stating that the user
      *                is ready.
+     * @throws Vilma_Exception if an error occurs looking up the user status.
      */
-    function getUserStatus($user)
+    public function getUserStatus($user)
     {
         /* Some needed vars. */
-        $no_error = true;
+        $error = false;
         $status = array();
         $domain_name = Vilma::stripDomain($user['user_name']);
         $user_name = Vilma::stripUser($user['user_name']);
 
         /* Check if user enabled. */
         if ($user['user_enabled'] !== 'active') {
-            $no_error = false;
+            $error = true;
             $err_msg = _("User disabled.");
             $status[] = Horde::img('alerts/error.png', $err_msg) . '&nbsp;' . $err_msg;
         }
 
         /* Check if mailbox exists. */
-        $mailboxes = &Vilma::getMailboxDriver();
-        if (is_a($mailboxes, 'PEAR_Error')) {
-            $no_error = false;
-            $err_msg = $mailboxes->getMessage();
-            $status[] = Horde::img('alerts/warning.png', $err_msg) . '&nbsp;' . $err_msg;
-        }
         try {
-            $mailboxes->checkMailbox($user_name, $domain_name);
+            Vilma_MailboxDriver::factory()->checkMailbox($user_name, $domain_name);
         } catch (Exception $result) {
-            $no_error = false;
+            $error = true;
             $err_msg = $result->getMessage();
             $status[] = Horde::img('alerts/warning.png', $err_msg) . '&nbsp;' . $err_msg;
         }
@@ -186,112 +266,30 @@ abstract class Vilma_Driver
 
         /* If no errors have been found output a success message for this
          * user's status. */
-        if ($no_error) {
+        if (!$error) {
             $msg = _("User ready.");
             $status = array(Horde::img('alerts/success.png', $msg) . '&nbsp;' . $msg);
         }
-        return $status;
-    }
-
-    /* Saves or creates alias records for a given user.
-     *
-     * @param array info The info used to store the information.
-     *                   Required fields are:
-     *                    'address' => The destination address (used for LDAP ID lookup)
-     *                    'alias_address'   => The alias to create or the new data for the modified entry
-     *                    'alias'  => The alias we are modifying, if we are modifying an existing one.
-     */
-    function saveAlias(&$info)
-    {
-        Horde::logMessage("saveAlias called with info: " . print_r($info, true), 'DEBUG');
-        $result = $this->_saveAlias($info);
-        if (is_a($result, 'PEAR_Error')) {
-          return $result;
-        }
-
-        return true;
-    }
-
-    /* Deletes alias records for a given user.
-     *
-     * @param array info The info used to store the information.
-     *                   Required fields are:
-     *                    'address' => The destination address (used for LDAP ID lookup)
-     *                    'alias'  => The alias we are deleting.
-     */
-    function deleteAlias(&$info)
-    {
-        Horde::logMessage("deleteAlias called with info: " . print_r($info, true), 'DEBUG');
-        $result = $this->_deleteAlias($info);
-        if (is_a($result, 'PEAR_Error')) {
-          return $result;
-        }
-
-        return true;
-    }
 
-    /* Saves or creates forward records for a given user.
-     *
-     * @param array info The info used to store the information.
-     *                   Required fields are:
-     *                    'address' => The destination address (used for LDAP ID lookup)
-     *                    'forward_address'   => The forward to create or the new data for the modified entry
-     *                    'forward'  => The forward we are modifying, if we are modifying an existing one.
-     */
-    function saveForward(&$info)
-    {
-        Horde::logMessage("saveForward called with info: " . print_r($info, true), 'DEBUG');
-        $result = $this->_saveForward($info);
-        if (is_a($result, 'PEAR_Error')) {
-          return $result;
-        }
-
-        return true;
+        return $status;
     }
 
-    /* Deletes forward records for a given user.
-     *
-     * @param array info The info used to store the information.
-     *                   Required fields are:
-     *                    'address' => The destination address (used for LDAP ID lookup)
-     *                    'forward'  => The forward we are deleting.
+    /**
+     * @throws Vilma_Exception
      */
-    function deleteForward(&$info)
+    public function saveUser($info)
     {
-        Horde::logMessage("deleteForward called with info: " . print_r($info, true), 'DEBUG');
-        $result = $this->_deleteForwrd($info);
-        if (is_a($result, 'PEAR_Error')) {
-          return $result;
-        }
-
-        return true;
-    }
-
-    function saveUser(&$info)
-    {
-        $create = false;
-        if (empty($info['user_id'])) {
-            $create = true;
-        }
-
-        $result = $this->_saveUser($info);
-        if (is_a($result, 'PEAR_Error')) {
-            return $result;
-        }
+        $create = empty($info['user_id']);
+        $info['user_id'] = $this->_saveUser($info);
 
         if ($create) {
-            $mailboxes = &Vilma::getMailboxDriver();
-            if (is_a($mailboxes, 'PEAR_Error')) {
-                $this->_deleteUser($result['user_id']);
-                return $mailboxes;
-            }
-
-            $mailbox = $mailboxes->createMailbox(Vilma::stripUser($info['user_name']), Vilma::stripDomain($info['user_name']));
-            if (is_a($mailbox, 'PEAR_Error')) {
-                //echo $mailbox->getMessage() . '<br />';
-                //No 'system_user' parameter specified to maildrop driver.
-                //$this->_deleteUser($result['user_id']);
-                return $mailbox;
+            try {
+                Vilma_MailboxDriver::factory()
+                    ->createMailbox(Vilma::stripUser($info['user_name']),
+                                    Vilma::stripDomain($info['user_name']));
+            } catch (Exception $e) {
+                $this->_deleteUser($info['user_id']);
+                throw $e;
             }
         }
 
@@ -306,232 +304,235 @@ abstract class Vilma_Driver
                 throw new Vilma_Exception(_("Error running authentication update script."));
             }
             if ($ec != 0) {
-                if (empty($msg)) {
-                    $msg = _("Unknown error running authentication update script.");
-                }
-                throw new Vilma_Exception($msg);
+                throw new Vilma_Exception(_("Unknown error running authentication update script."));
             }
         }
-
-        return true;
     }
 
-    function deleteUser($user_id)
+    /**
+     * Saves a user to the backend.
+     *
+     * @param array $info  The user information to save.
+     *
+     * @return string  The user ID.
+     * @throws Vilma_Exception
+     */
+    abstract protected function _saveUser($info);
+
+    /**
+     * Deletes a user.
+     *
+     * @param integer $user_id  The id of the user to delete.
+     *
+     * @throws Vilma_Exception
+     */
+    abstract public function deleteUser($user_id);
+
+    public function getUserFormAttributes()
     {
-        throw new Vilma_Exception(_("Vilma_Driver::deleteUser(): Method Not Implemented."));
     }
 
     /**
-     * Saves a given domain with the provided information.
+     * Returns a list of all users, aliases, or groups and forwards for a
+     * domain.
      *
-     * @param array $info  Array of details to save the domain
+     * @param string $domain      Domain on which to search.
+     * @param string $type        Only return a specific type. One of 'all',
+     *                            'user', 'alias', 'forward', or 'group'.
+     * @param string $key         Sort list by this key.
+     * @param integer $direction  Sort direction.
      *
-     * @return mixed  True on success, or PEAR_Error on failure.
+     * @return array  Account information for this domain.
      */
-    function saveDomain(&$info)
+    public function getAddresses($domain, $type = 'all', $key = 'user_name',
+                                 $direction = 0)
     {
-        $domain_id = $this->_saveDomain($info);
-        if (is_a($domain_id, 'PEAR_Error')) {
-            return $domain_id;
-        }
+        $addresses = $this->_getAddresses($domain, $type);
+        Horde_Array::arraySort($addresses, $key, $direction, true);
+        return $addresses;
+    }
 
-        $ret = Horde::callHook('_vilma_hook_savedomain', array($info), 'vilma');
-        if (!$ret) {
-            throw new Vilma_Exception(_("Domain added but an error was encountered while calling the configured hook.  Contact your administrator for futher assistance."));
-        }
+    /**
+     * Returns a list of all users, aliases, or groups and forwards for a
+     * domain.
+     *
+     * @param string $domain      Domain on which to search.
+     * @param string $type        Only return a specific type. One of 'all',
+     *                            'user', 'alias','forward', or 'group'.
+     * @param string $key         Sort list by this key.
+     * @param integer $direction  Sort direction.
+     *
+     * @return array  Account information for this domain.
+     */
+    abstract protected function _getAddresses($domain, $type = 'all');
 
-        return $domain_id;
+    /**
+     * Returns an array of information related to the address passed in.
+     *
+     * This method may be overridden by the backend driver if there is a more
+     * efficient way to do this than a linear array search.
+     *
+     * @param string $address  Address for which information will be pulled.
+     * @param string $type     Address type to request.
+     *                         One of 'all', 'user', 'alias', 'forward' or
+     *                         'group'.
+     *
+     * @return array  Array of user information on success or empty array
+     *                if the user does not exist.
+     * @throws Vilma_Exception if address of that type doesn't exist.
+     */
+    public function getAddressInfo($address, $type = 'all')
+    {
+        $domain = Vilma::stripDomain($address);
+        $addresses = $this->getAddresses($domain, $type);
+        foreach ($addresses as $addrinfo) {
+            if ($addrinfo['id'] == $address ||
+                $addrinfo['address'] == $address) {
+                return $addrinfo;
+            }
+        }
+        throw new Vilma_Exception(sprintf(_("No such address %s of type %s found."), $address, $type));
     }
 
     /**
-     * Saves the domain record.
+     * Returns available virtual emails.
      *
-     * @abstract
-     * @param array $info  Information to save the domain
+     * @param string $filter  If passed a domain then return all virtual emails
+     *                        for the domain, otherwise if passed a user name
+     *                        return all virtual emails for that user.
      *
-     * @return mixed True on success, or PEAR_Error on failure.
+     * @return array  The available virtual emails.
      */
-    function _saveDomain(&$info)
+    public function getVirtuals($filter)
     {
-        throw new Vilma_Exception(_("Not implemented."));
     }
 
     /**
-     * Deletes a given domain and all the users and virtuals under it.
+     * Returns information for a virtual id.
      *
-     * @param integer $domain_id  The id of the domain to delete.
+     * @param integer $virtual_id  The virtual id for which to return
+     *                             information.
      *
-     * @return mixed  True on success, or PEAR_Error on failure.
+     * @return array  The virtual email information.
      */
-    function deleteDomain($domain_id)
+    public function getVirtual($virtual_id)
     {
-        $domain_record = $this->getDomain($domain_id);
-        if (is_a($domain_record, 'PEAR_Error')) {
-            return $domain_record;
-        }
-
-        $users = $this->getUsers($domain_record['domain_name']);
-        if (is_a($users, 'PEAR_Error')) {
-            return $users;
-        }
-
-        foreach ($users as $user) {
-            $this->_deleteUser($user['user_id']);
-        }
-
-        $ret = $this->_deleteDomain($domain_id);
-        if (is_a($ret, 'PEAR_Error')) {
-            return $ret;
-        }
-
-        $ret = Horde::callHook('_vilma_hook_deletedomain',
-                               array($domain_record['domain_name']),
-                               'vilma');
-        if (!$ret) {
-            throw new Vilma_Exception(_("Error while calling hook to delete domain."));
-        }
     }
 
     /**
-     * Deletes the domain record.
+     * Saves virtual email address to the backend.
      *
-     * @abstract
-     * @param integer $domain_id  The ID of the domain to delete.
+     * @param array $info     The virtual email data.
+     * @param string $domain  The name of the domain for this virtual email.
      *
-     * @return mixed True on success, or PEAR_Error on failure.
+     * @throws Vilma_Exception
      */
-    function _deleteDomain($domain_id)
+    public function saveVirtual($info, $domain)
     {
-        throw new Vilma_Exception(_("Not implemented."));
     }
 
     /**
-     * Get the user who is the domain admin.
+     * Deletes a virtual email.
      *
-     * @todo  This should be replaced by moving all permissions into Horde
-     *        permissions.
+     * @param integer $virtual_id  The id of the virtual email to delete.
      */
-    function getDomainAdmin($domain_name)
+    public function deleteVirtual($virtual_id)
     {
-        $domain = $this->getDomainByName($domain_name);
-        if (is_a($domain, 'PEAR_Error')) {
-            return $domain;
-        }
-        return $domain['domain_admin'];
     }
 
     /**
-     * Returns the configured quota for this domain.
+     * Saves or creates alias records for a user.
      *
-     * @param string $domain_name  The name of the domain for which to
-     *                             return the quota.
+     * @param array $info  The info used to store the information.
+     *                     Required fields are:
+     *                     - 'address': The destination address (used for LDAP
+     *                       ID lookup).
+     *                     - 'alias_address': The alias to create or the new
+     *                       data for the modified entry.
+     *                     - 'alias': The alias we are modifying, if we are
+     *                       modifying an existing one.
      *
-     * @return integer  The domain's quota.
+     * @throws Vilma_Exception
      */
-    function getDomainQuota($domain_name)
+    public function saveAlias($info)
     {
-        $domain = $this->getDomainByName($domain_name);
-        if (is_a($domain, 'PEAR_Error')) {
-            return $domain;
-        }
-        return $domain['domain_quota'];
     }
 
     /**
-     * Returns the maximum number of users allowed for a given domain.
+     * Deletes alias records for a given user.
      *
-     * @param string $domain_name  The name of the domain for which to
-     *                             return the maximum users.
+     * @param array $info  The info used to store the information.
+     *                     Required fields are:
+     *                     - 'address': The destination address (used for LDAP
+     *                       ID lookup).
+     *                     - 'alias': The alias we are deleting.
      *
-     * @return integer The maximum number of allowed users or PEAR_Error on
-     *                 failure.
+     * @throws Vilma_Exception
      */
-    function getDomainMaxUsers($domain_name)
+    public function deleteAlias($info)
     {
-        $domain = $this->getDomainByName($domain_name);
-        if (is_a($domain, 'PEAR_Error')) {
-            return $domain;
-        }
-        return $domain['max_users'];
     }
 
-    public function getUserFormAttributes()
+    /**
+     * Saves or creates forward records for a given user.
+     *
+     * @param array $info  The info used to store the information.
+     *                     Required fields are:
+     *                     - 'address': The destination address (used for LDAP
+     *                       ID lookup).
+     *                     - 'forward_address': The forward to create or the
+     *                       new data for the modified entry.
+     *                     - 'forward': The forward we are modifying, if we are
+     *                       modifying an existing one.
+     *
+     * @throws Vilma_Exception
+     */
+    public function saveForward($info)
     {
     }
 
     /**
-     * Attempts to return a concrete Vilma_Driver instance based on $driver.
+     * Deletes forward records for a given user.
      *
-     * @param string $driver  The type of concrete Vilma_Driver subclass to
-     *                        return.
-     * @param array $params   A hash containing any additional configuration or
-     *                        connection parameters a subclass might need.
+     * @param array $info  The info used to store the information.
+     *                     Required fields are:
+     *                     - 'address': The destination address (used for LDAP
+     *                       ID lookup).
+     *                     - 'forward': The forward we are deleting.
      *
-     * @return Vilma_Driver  The newly created concrete Vilma_Driver instance,
-     *                       or false on error.
      * @throws Vilma_Exception
      */
-    function factory($driver = null, $params = null)
+    public function deleteForward($info)
     {
-        if (is_null($driver)) {
-            $driver = $GLOBALS['conf']['storage']['driver'];
-        }
-        $driver = basename($driver);
-
-        if (is_null($params)) {
-            $params = Horde::getDriverConfig('storage', $driver);
-        }
-
-        include_once dirname(__FILE__) . '/Driver/' . $driver . '.php';
-        $class = 'Vilma_Driver_' . $driver;
-        if (class_exists($class)) {
-            return new $class($params);
-        }
-
-        throw new Vilma_Exception(sprintf(_("No such backend \"%s\" found"), $driver));
     }
 
     /**
-     * Attempts to return a reference to a concrete Vilma_Driver instance
-     * based on $driver.
-     *
-     * It will only create a new instance if no Vilma_Driver instance with the
-     * same parameters currently exists.
-     *
-     * This should be used if multiple storage sources are required.
-     *
-     * This method must be invoked as: $var = &Vilma_Driver::singleton()
+     * Attempts to return a concrete Vilma_Driver instance based on $driver.
      *
      * @param string $driver  The type of concrete Vilma_Driver subclass to
      *                        return.
      * @param array $params   A hash containing any additional configuration or
      *                        connection parameters a subclass might need.
      *
-     * @return mixed  The created concrete Vilma_Driver instance, or false on
-     *                error.
+     * @return Vilma_Driver  The newly created concrete Vilma_Driver instance.
+     * @throws Vilma_Exception
      */
-    function &singleton($driver = null, $params = null)
+    static public function factory($driver = null, $params = null)
     {
-        static $instances;
-
         if (is_null($driver)) {
             $driver = $GLOBALS['conf']['storage']['driver'];
         }
+        $driver = Horde_String::ucfirst(basename($driver));
 
         if (is_null($params)) {
             $params = Horde::getDriverConfig('storage', $driver);
         }
 
-        if (!isset($instances)) {
-            $instances = array();
-        }
-
-        $signature = serialize(array($driver, $params));
-        if (!isset($instances[$signature])) {
-            $instances[$signature] = Vilma_Driver::factory($driver, $params);
+        $class = 'Vilma_Driver_' . $driver;
+        if (class_exists($class)) {
+            return new $class($params);
         }
 
-        return $instances[$signature];
+        throw new Vilma_Exception(sprintf(_("No such backend \"%s\" found"), $driver));
     }
-
 }
diff --git a/vilma/lib/Driver/Qmailldap.php b/vilma/lib/Driver/Qmailldap.php
new file mode 100644 (file)
index 0000000..9de8225
--- /dev/null
@@ -0,0 +1,1020 @@
+<?php
+/**
+ * Copyright 2006-2007 Alkaloid Networks <http://www.alkaloid.net>
+ *
+ * See the enclosed file LICENSE for license information (BSD). If you did
+ * did not receive this file, see http://cvs.horde.org/co.php/vilma/LICENSE.
+ *
+ * @author Ben Klang <bklang@alkaloid.net>
+ * @author David Cummings <davidcummings@acm.org>
+ * @package Vilma
+ * @todo - Convert to Horde_Ldap
+ */
+class Vilma_Driver_Qmailldap extends Vilma_Driver_Sql
+{
+    /**
+     * Reference to initialized LDAP driver.
+     *
+     * @var resource
+     */
+    protected $_ldap;
+
+    /**
+     * Cache for retrieved getUsers() results.
+     *
+     * @var array
+     */
+    protected $_users = array();
+
+    /**
+     * Map of internal field names to LDAP attribute names.
+     *
+     * @var array
+     */
+    protected $_fieldmap = array(
+        'address' => 'mail',
+        'user_name' => 'uid',
+        'user_crypt' => 'userpassword',
+        'user_full_name' => 'cn',
+        'user_uid' => 'qmailuid',
+        'user_gid' => 'qmailgid',
+        'user_home_dir' => 'homedirectory',
+        'user_mail_dir' => 'mailmessagestore',
+        'user_mail_quota_bytes' => 'mailquotasize',
+        'user_mail_quota_count' => 'mailquotacount',
+        'user_enabled' => 'accountstatus',
+    );
+
+    /**
+     * Constructor.
+     *
+     * @param array $params  Any parameters needed for this driver.
+     */
+    public function __construct($params)
+    {
+        $params = array_merge(
+            Horde::getDriverConfig('storage', 'sql'),
+            $params);
+        parent::__construct($params);
+        $this->_connect();
+    }
+
+    /**
+     * Deletes a domain.
+     *
+     * @todo Add logic to remove all users, aliases, and grpfwds for this
+     *       domain.
+     * @todo Use parent::_deleteDomain()
+     *
+     * @param integer $domain_id  The id of the domain to delete.
+     *
+     * @throws Vilma_Exception
+     */
+    protected function _deleteDomain($domain_id)
+    {
+        $domain_record = $this->getDomain($domain_id);
+        $domain_name = $domain_record['domain_name'];
+
+        /* Finally delete the domain. */
+        $sql = 'DELETE FROM vilma_domains WHERE domain_id=?';
+        $values = array((int)$domain_id);
+
+        Horde::logMessage($sql, 'DEBUG');
+        return $this->_db->query($sql, $values);
+    }
+
+    /**
+     * Returns the current number of users for a domain.
+     *
+     * @param string $domain_name  The name of the domain for which to
+     *                             get the current number of users.
+     *
+     * @return integer  The current number of users.
+     */
+    public function getDomainNumUsers($domain_name)
+    {
+        return count($this->_getUsers($domain_name));
+    }
+
+    /**
+     * Returns all available users, if a domain name is passed then limit the
+     * list of users only to those users.
+     *
+     * @param string $domain  The name of the domain for which to fetch the
+     *                        users.
+     *
+     * @return array  The available users and their stored information.
+     * @throws Vilma_Exception
+     */
+    public function getUsers($domain = null)
+    {
+        // Cache for multiple calls.
+        if (is_null($domain) && isset($this->_users['_all'])) {
+            return $this->_users['_all'];
+        }
+
+        if (!is_null($domain) && isset($this->_users[$domain])) {
+            return $this->_users[$domain];
+        }
+
+        $filter = '(&';
+        if (!is_null($domain)) {
+            $filter .= '(mail=*@' . $domain . ')';
+        } else {
+            $domain = '_all';
+        }
+
+        // Make sure we don't get any forwards.
+        $filter .= '(!(mailForwardingAddress=*))';
+
+        // FIXME: Check/add configured filter instead of objectclasses
+        foreach ($this->_params['ldap']['objectclass'] as $objectclass) {
+            $filter .= '(objectClass=' . $objectclass . ')';
+        }
+        $filter .= ')';
+
+        Horde::logMessage($filter, 'DEBUG');
+        $res = ldap_search($this->_ldap, $this->_params['ldap']['basedn'], $filter);
+        if ($res === false) {
+            throw new Vilma_Exception(sprintf(_("Error in LDAP search: %s"), ldap_error($this->LDAP)));
+        }
+
+        $res = ldap_get_entries($this->_ldap, $res);
+        if ($res === false) {
+            throw new Vilma_Exception(sprintf(_("Error in LDAP search: %s"), ldap_error($this->LDAP)));
+        }
+
+        $this->_users[$domain] = array();
+        // Can't use foreach because of the array format returned by LDAP driver
+        for ($i = 0; isset($res[$id]); $user = $res[$i++]) {
+            $info = array(
+                'id' => $user['dn'],
+                'address' => $user[$this->_fieldmap['address']][0],
+                'type' => 'user',
+                'user_name' => $user[$this->_fieldmap['user_name']][0]);
+
+            // We likely don't have read permission on the crypted password so
+            // avoid any warnings/errors about missing array elements.
+            if (isset($user[$this->_fieldmap['user_crypt']])) {
+                $info['user_crypt'] = $user[$this->_fieldmap['user_crypt']][0];
+            } else {
+                $info['user_crypt'] = '';
+            }
+            $info['user_full_name'] = $user[$this->_fieldmap['user_full_name']][0];
+            // Mute assignment errors on the following optional fields.
+            // These may not be present if the mail is only forwarded.
+            $info['user_uid'] = @$user[$this->_fieldmap['user_uid']][0];
+            $info['user_gid'] = @$user[$this->_fieldmap['user_gid']][0];
+            $info['user_home_dir'] = @$user[$this->_fieldmap['user_home_dir']][0];
+            $info['user_mail_dir'] = @$user[$this->_fieldmap['user_mail_dir']][0];
+            $info['user_mail_quota_bytes'] = @$user[$this->_fieldmap['user_mail_quota_bytes']][0];
+            $info['user_mail_quota_count'] = @$user[$this->_fieldmap['user_mail_quota_count']][0];
+
+            // If accountStatus is blank it's the same as active.
+            if (!isset($user[$this->_fieldmap['user_enabled']][0]) ||
+                $user[$this->_fieldmap['user_enabled']][0] == 'active') {
+                $info['user_enabled'] = 'active';
+            } else {
+                // accountStatus can also be:
+                // noaccess (receives but cannot pick up mail)
+                // disabled (bounce incoming and deny pickup)
+                // deleted (bounce incoming but allow pickup)
+                $info['user_enabled'] = $user[$this->_fieldmap['user_enabled']][0];
+            }
+
+            $this->_users[$domain][$i] = $info;
+        }
+
+        return $this->_users[$domain];
+    }
+
+    /**
+     * Returns the user information for a given user id.
+     *
+     * @param integer $user_id  The id of the user for which to fetch
+     *                          information.
+     *
+     * @return array  The user information.
+     */
+    public function getUser($user_id)
+    {
+        $user = $this->getUserStatus($user_id);
+        if (is_array($user)) {
+            return $user;
+        }
+        throw new Vilma_Exception(_("Unable to qualify address."));
+    }
+
+    /**
+     * Saves a user to the backend.
+     *
+     * @param array $info  The user information to save.
+     *
+     * @return array  The user information.
+     * @throws Vilma_Exception
+     */
+    protected function _saveUser($info)
+    {
+        switch ($info['mode']) {
+        case 'edit':
+            return $this->_updateUser($info);
+        case 'new':
+            return $this->_createUser($info);
+        }
+
+        throw new Vilma_Exception(_("Unable to save user information."));
+    }
+
+    /**
+     * Updates a user in the backend.
+     *
+     * @param array $info  The user information to save.
+     *
+     * @return array  The user information.
+     * @throws Vilma_Exception
+     */
+    protected function _updateUser($info)
+    {
+        $address = $info['address'];
+        if (empty($address)) {
+            $user_name = $info['user_name'];
+            $domain = $info['domain'];
+            if (empty($user_name)) {
+                throw new Vilma_Exception(_("Unable to acquire handle on address."));
+            }
+            $address = $info['user_name'] . $info['domain'];
+        }
+        $addrinfo = $this->getAddressInfo($address);
+        $type = $addrinfo['type'];
+        if ($type != 'user') {
+            throw new Vilma_Exception(sprintf(_("Unable to save account of type \"%s\""), $type));
+        }
+
+        $user_info = $this->_searchForUser($address);
+        if ($res['count'] === 0) {
+            throw new Vilma_Exception(_("Error reading address information from backend."));
+        }
+
+        $objectClassData = null;
+        if (isset($user_info[0]['objectclass'])) {
+            $objectClassData = $user_info[0]['objectclass'];
+        }
+
+        // Don't want to save this to LDAP.
+        unset($info['mode']);
+
+        // Special case for the password:  If it was provided, it needs
+        // to be crypted.  Otherwise, ignore it.
+        if (isset($info['password'])) {
+            if (!empty($user['password'])) {
+                // FIXME: Allow choice of hash
+                $info['user_password'] = Horde_Auth::getCryptedPassowrd($info['password'], '', 'ssha', true);
+            }
+            unset($info['password']);
+        }
+
+        $tmp['dn'] = $addrinfo['id'];
+        foreach ($info as $key => $val) {
+            $attr = $this->_fieldmap[$key];
+            $tmp[$attr] = $val;
+        }
+
+        // Bind with appropriate dn to give update access.
+        $res = ldap_bind($this->_ldap, $this->_params['ldap']['binddn'],
+                         $this->_params['ldap']['bindpw']);
+        if (!$res) {
+            throw new Vilma_Exception(_("Unable to bind to the LDAP server.  Check authentication credentials."));
+        }
+
+        // Prepare data.
+        $entry['cn'] = $info['user_full_name'];
+        // sn is not used operationally but we make an effort to be
+        // something sensical.  No guarantees, though.
+        $entry['sn'] = array_pop(explode(' ', $info['user_full_name']));
+        $entry['mail'] = $info['user_name'] . $info['domain'];
+        $entry['uid'] = $entry['mail'];
+        $entry['homeDirectory'] = '/srv/vhost/mail/' . $info['domain'] .'/' . $info['user_name'];
+        if ($type != 'group' && $type != 'forward') {
+            $entry['qmailUID'] = $entry['qmailGID'] = 8;
+        }
+        $entry['accountstatus'] = $info['user_enabled'];
+        if (isset($info['password']) && !empty($info['password'])) {
+            // FIXME: Allow choice of hash
+            $entry['userPassword'] = Horde_Auth::getCryptedPassword($info['password'], '', 'ssha', true);
+        }
+        if (isset($objectClassData)) {
+            array_shift($objectClassData);
+            $entry['objectclass'] = $objectClassData;
+        } else {
+            $entry['objectclass'] = array(
+                'top',
+                'person',
+                'organizationalPerson',
+                'inetOrgPerson',
+                'hordePerson',
+                'qmailUser');
+        }
+
+        // Stir in any site-local custom LDAP attributes.
+        $entry = Horde::callHook('getLDAPAttrs', array($entry), 'vilma');
+        $rdn = 'mail=' . $entry['mail'];
+        $dn = $rdn . ',' . $this->_params['ldap']['basedn'];
+        $res = @ldap_modify($this->_ldap, $dn, $entry);
+        if ($res === false) {
+            throw new Vilma_Exception(sprintf(_("Error modifying account: %s"), @ldap_error($this->_ldap)));
+        }
+
+        return $dn;
+    }
+
+    /**
+     * Creates a user in the backend.
+     *
+     * @param array $info  The user information to save.
+     *
+     * @return array  The user information.
+     * @throws Vilma_Exception
+     */
+    protected function _createUser($info)
+    {
+        // Bind with appropriate dn to give update access.
+        $res = ldap_bind($this->_ldap, $this->_params['ldap']['binddn'],
+                         $this->_params['ldap']['bindpw']);
+        if (!$res) {
+            throw new Vilma_Exception(_("Unable to bind to the LDAP server.  Check authentication credentials."));
+        }
+
+        // Prepare data.
+        $entry['cn'] = $info['user_full_name'];
+        // sn is not used operationally but we make an effort to be
+        // something sensical.  No guarantees, though.
+        $entry['sn'] = array_pop(explode(' ', $info['user_full_name']));
+        $entry['mail'] = $info['user_name'] . '@' . $info['domain'];
+        // uid must match mail or SMTP auth fails.
+        $entry['uid'] = $entry['mail'];
+        $entry['homeDirectory'] = '/srv/vhost/mail/' . $info['domain'] .'/' . $info['user_name'];
+        $entry['qmailUID'] = $entry['qmailGID'] = 8;
+        $entry['objectclass'] = array(
+            'top',
+            'person',
+            'organizationalPerson',
+            'inetOrgPerson',
+            'hordePerson',
+            'qmailUser');
+        $entry['accountstatus'] = $info['user_enabled'];
+        // FIXME: Allow choice of hash
+        $entry['userPassword'] = Horde_Auth::getCryptedPassword($info['password'], '', 'ssha', true);
+
+        // Stir in any site-local custom LDAP attributes.
+        $entry = Horde::callHook('getLDAPAttrs', array($entry), 'vilma');
+        $rdn = 'mail=' . $entry['mail'];
+        $dn = $rdn . ',' . $this->_params['ldap']['basedn'];
+        $res = @ldap_add($this->_ldap, $dn, $entry);
+        if ($res === false) {
+            throw new Vilma_Exception(sprintf(_("Error adding account to LDAP: %s"), @ldap_error($this->_ldap)));
+        }
+
+        return $dn;
+    }
+
+    /**
+     * Deletes a user.
+     *
+     * @param integer $user_id  The id of the user to delete.
+     *
+     * @throws Vilma_Exception
+     */
+    public function deleteUser($user_id)
+    {
+        // Get the user's DN.
+        $filter  = '(&';
+        foreach ($this->_params['ldap']['objectclass'] as $objectclass) {
+            // Add each objectClass from parameters.
+            $filter .= '(objectclass=' . $objectclass . ')';
+        }
+        $filter .= '(mail=' . $user_id . ')';
+        $filter .= ')';
+
+        Horde::logMessage($filter, 'DEBUG');
+        $res = @ldap_search($this->_ldap, $this->_params['ldap']['basedn'], $filter);
+        if ($res === false) {
+            throw new Vilma_Exception(sprintf(_("Error searching LDAP: %s"), @ldap_error($this->_ldap)));
+        }
+        $res = @ldap_get_entries($this->_ldap, $res);
+        if ($res === false) {
+            throw new Vilma_Exception(sprintf(_("Error retrieving LDAP results: %s"), @ldap_error($this->_ldap)));
+        }
+
+        if ($res['count'] === 0) {
+            throw new Vilma_Exception(_("Unable to acquire handle on DN.  Aborting delete operation."));
+        }
+        if ($res['count'] !== 1) {
+            throw new Vilma_Exception(_("More than one DN returned.  Aborting delete operation."));
+        }
+
+        // We now have one unique DN to delete.
+        $res = @ldap_delete($this->_ldap, $res[0]['dn']);
+        if ($res === false) {
+            throw new Vilma_Exception(sprintf(_("Error deleting account from LDAP: %s"), @ldap_error($this->_ldap)));
+        }
+    }
+
+    public function getUserFormAttributes()
+    {
+        return array(array(
+            'label' => _("Account Status"),
+            'name' => 'user_enabled',
+            'type' => 'enum',
+            'required' => true,
+            'readonly' => false,
+            'description' => null,
+            'params' => array(
+                array(
+                    'active' => _("Account is active"),
+                    'noaccess' => _("Disable Delivery Only"),
+                    'disabled' => _("Bounce Incoming Only"),
+                    'deleted' => _("Account is disabled"),
+                ),
+             ),
+             'default' => 'active',
+        ));
+    }
+
+    /**
+     * Returns a list of all users, aliases, or groups and forwards for a
+     * domain.
+     *
+     * @param string $domain      Domain on which to search.
+     * @param string $type        Only return a specific type. One of 'all',
+     *                            'user', 'alias','forward', or 'group'.
+     * @param string $key         Sort list by this key.
+     * @param integer $direction  Sort direction.
+     *
+     * @return array Account information for this domain
+     */
+    protected function _getAddresses($domain, $type = 'all')
+    {
+        $addresses = array();
+        if ($type == 'all' || $type == 'user') {
+            $addresses += $this->_getUsers($domain);
+        }
+        if ($type == 'all' || $type == 'alias') {
+            $addresses += $this->_getAliases($domain);
+        }
+        if ($type == 'all' || $type == 'forward') {
+            $addresses += $this->_getGroupsAndForwards('forward', $domain);
+        }
+        if ($type == 'all' || $type == 'group') {
+            $addresses += $this->_getGroupsAndForwards('group', $domain);
+        }
+        return $addresses;
+    }
+
+    /**
+     * Returns available email address aliases.
+     *
+     * @param string $target  If passed a domain then return all alias emails
+     *                        for the domain, otherwise if passed a user name
+     *                        return all virtual emails for that user.
+     *
+     * @return array  The used email aliases.
+     */
+    protected function _getAliases($target = null)
+    {
+        // FIXME: Add static cache
+
+        // FIXME: Add preconfigured filter from $this->_params['ldap']
+        // Begin filter (cumulative AND).
+        $filter  = '(&';
+        foreach ($this->_params['ldap']['objectclass'] as $objectclass) {
+            // Add each objectClass from parameters
+            $filter .= '(objectClass=' . $objectclass . ')';
+        }
+
+        // Check if filtering only for domain.
+        if (strpos($target, '@') === false && !empty($target)) {
+            $filter .= '(mailAlternateAddress=*@' . $target . ')';
+        } else {
+            // Otherwise filter for all aliases.
+            $filter .= '(mailAlternateAddress=*)';
+            // Restrict the results to $target.
+            if (!empty($target)) {
+                 // Add user's email.
+                $filter .= '(mail=' . $target . ')';
+            }
+        }
+        // End filter.
+        $filter .= ')';
+
+        Horde::logMessage($filter, 'DEBUG');
+        $res = @ldap_search($this->_ldap, $this->_params['ldap']['basedn'], $filter);
+        if ($res === false) {
+            throw new Vilma_Exception(sprintf(_("Error searching LDAP: %s"), @ldap_error($this->_ldap)));
+        }
+
+        $res = @ldap_get_entries($this->_ldap, $res);
+        if ($res === false) {
+            throw new Vilma_Exception(sprintf(_("Error returning LDAP results: %s"), @ldap_error($this->_ldap)));
+        }
+
+        $aliases = array();
+        // Can't use foreach because of the array format returned by LDAP driver
+        for ($e = 0; isset($res[$e]); $entry = $res[$e++]) {
+            // If accountStatus is blank it's the same as active
+            if (!isset($entry[$this->_fieldmap['user_enabled']][0]) ||
+                $entry[$this->_fieldmap['user_enabled']][0] == 'active') {
+                $curstatus = 'active';
+            } else {
+                // accountStatus can also be:
+                // noaccess (receives but cannot pick up mail)
+                // disabled (bounce incoming and deny pickup)
+                // deleted (bounce incoming but allow pickup)
+                $curstatus = $entry[$this->_fieldmap['user_enabled']][0];
+            }
+            for ($a = 0; isset($entry['mailalternateaddress'][$a]); $mail = @$entry['mailalternateaddress'][$a++]) {
+                $aliases[] = array(
+                    'id' => $mail,
+                    'type' => 'alias',
+                    'user_name' => $mail,
+                    'user_full_name' => sprintf(_("Alias for %s"), $entry['mail'][0]),
+                    'destination' => $entry['mail'][0],
+                    'user_enabled' => $curstatus);
+            }
+        }
+
+        return $aliases;
+    }
+
+    /**
+     * Returns all available groups and forwards unless otherwise specified.
+     *
+     * If a domain name is passed then limit the results to groups or forwards
+     * in that domain.
+     *
+     * @param string $acquire The default behavior is to acquire both
+     *                        groups and forwards; a value of 'group'
+     *                        will return only groups and a value of
+     *                        'forward' will return only forwards.
+     * @param string $domain  The name of the domain from which to fetch.
+     *
+     * @return array  The available groups and forwards with details.
+     */
+    protected function _getGroupsAndForwards($acquire = null, $domain = null)
+    {
+        // FIXME: Add preconfigured filter from $this->_params['ldap']
+        // Begin filter (cumulative AND).
+        $filter  = '(&';
+        foreach ($this->_params['ldap']['objectclass'] as $objectclass) {
+            // Add each objectClass from parameters.
+            $filter .= '(objectClass=' . $objectclass . ')';
+        }
+
+        // Only return results which have a forward configured.
+        $filter .= '(mailForwardingAddress=*)';
+
+        if (!empty($domain)) {
+            // mail or mailAlternateAddress.
+            $filter .= '(|';
+            $filter .= '(mail=*@' . $domain . ')';
+            $filter .= '(mailAlternateAddress=*@' . $domain . ')';
+            $filter .= ')';
+        } else {
+            $domain = '_all';
+        }
+
+        // End filter
+        $filter .= ')';
+
+        Horde::logMessage($filter, 'DEBUG');
+        $res = @ldap_search($this->_ldap, $this->_params['ldap']['basedn'], $filter);
+        if ($res === false) {
+            throw new Vilma_Exception(sprintf(_("Error searching LDAP: %s"), @ldap_error($this->_ldap)));
+        }
+
+        $res = @ldap_get_entries($this->_ldap, $res);
+        if ($res === false) {
+            throw new Vilma_Exception(sprintf(_("Error returning LDAP results: %s"), @ldap_error($this->_ldap)));
+        }
+
+        $grpfwds[$domain] = array();
+        // Can't use foreach because of the array format returned by LDAP driver
+        for ($e = 0; isset($res[$e]); $entry = $res[$e++]) {
+            $targets = array();
+            for ($a = 0; isset($res[$e]['mailforwardingaddress'][$a]); $attr = $res[$e]['mailforwardingaddress'][$a++]) {
+                $targets[] = $attr;
+            }
+            $type = $entry['mailforwardingaddress']['count'];
+            if ($type > 1) {
+                $type = 'group';
+            } else {
+                $type = 'forward';
+            }
+            if ($acquire == 'all' || $type == $acquire) {
+                $grpfwds[$domain][$e] = array(
+                    'id'             => $entry['dn'],
+                    'type'           => $type,
+                    'address'        => $entry[$this->_fieldmap['address']][0],
+                    'targets'        => $targets,
+                    'user_name'      => $entry[$this->_fieldmap['user_name']][0],
+                    'user_full_name' => @$entry[$this->_fieldmap['user_name']][0],
+                );
+                // If accountStatus is blank it's the same as active
+                if (!isset($entry[$this->_fieldmap['user_enabled']][0]) ||
+                    $entry[$this->_fieldmap['user_enabled']][0] == 'active') {
+                    $grpfwds[$domain][$e]['user_enabled'] = 'active';
+                } else {
+                    // accountStatus can also be:
+                    // noaccess (receives but cannot pick up mail)
+                    // disabled (bounce incoming and deny pickup)
+                    // deleted (bounce incoming but allow pickup)
+                    $grpfwds[$domain][$e]['user_enabled'] =
+                        $entry[$this->_fieldmap['user_enabled']][0];
+                }
+            }
+        }
+
+        return $grpfwds[$domain];
+    }
+
+    /**
+     * Returns an array of information related to the address passed in.
+     *
+     * @param string $address  Address for which information will be pulled.
+     * @param string $type     Address type to request.
+     *                         One of 'all', 'user', 'alias', 'forward' or
+     *                         'group'.
+     *
+     * @return array  Array of user information on success or empty array
+     *                if the user does not exist.
+     * @throws Vilma_Exception if address of that type doesn't exist.
+     */
+    public function getAddressInfo($address, $type = 'all')
+    {
+        if ($type != 'alias') {
+            return parent::getAddressInfo($address, $type);
+        }
+
+        // FIXME: Which is faster?  A linear array search or an LDAP search?
+        // I think LDAP in this case because we can't assume the domain.
+        // Begin filter (cumulative AND).
+        $filter = '(&';
+        foreach ($this->_params['ldap']['objectclass'] as $objectclass) {
+            // Add each objectClass from parameters.
+            $filter .= '(objectClass=' . $objectclass . ')';
+        }
+        $filter .= '(mailAlternateAddress=' . $address . ')';
+        // End filter.
+        $filter .= ')';
+
+        Horde::logMessage($filter, 'DEBUG');
+        $res = @ldap_search($this->_ldap, $this->_params['ldap']['basedn'], $filter);
+        if ($res === false) {
+            throw new Vilma_Exception(sprintf(_("Error searching LDAP: %s"), @ldap_error($this->_ldap)));
+        }
+        $res = @ldap_get_entries($this->_ldap, $res);
+        if ($res === false) {
+            throw new Vilma_Exception(sprintf(_("Error returning LDAP results: %s"), @ldap_error($this->_ldap)));
+        }
+
+        if ($res['count'] !== 1) {
+            throw new Vilma_Exception(_("More than one DN returned for this alias.  Please contact an administrator to resolve this error."));
+        }
+
+        return array(
+            'id' => $res[0]['dn'],
+            'address' => $address,
+            'destination' => $res[0]['mail'][0],
+        );
+    }
+
+    /**
+     * Saves or creates alias records for a user.
+     *
+     * @param array $info  The info used to store the information.
+     *                     Required fields are:
+     *                     - 'address': The destination address (used for LDAP
+     *                       ID lookup).
+     *                     - 'alias_address': The alias to create or the new
+     *                       data for the modified entry.
+     *                     - 'alias': The alias we are modifying, if we are
+     *                       modifying an existing one.
+     *
+     * @throws Vilma_Exception
+     */
+    public function saveAlias($info)
+    {
+        $address = $info['address'];
+        if (!empty($info['alias'])) {
+            $alias = $info['alias'];
+            $create = false;
+        } else {
+            $create = true;
+        }
+        $alias_address = $info['alias_address'];
+
+        $user_res = $this->_searchForUser($address);
+        if ($res['count'] === 0) {
+            throw new Vilma_Exception(_("Error reading address information from backend."));
+        }
+        $user = $user_res[0];
+
+        // Retrieve the current MAA values.
+        if (isset($user_res[0]['mailalternateaddress'])) {
+            $maa = $user['mailalternateaddress'];
+            unset($maa['count']);
+        } else {
+            $maa = array();
+        }
+
+        $oldmaa = $maa;
+        if ($create) {
+            // Verify that it does not already exist.
+            if (in_array($alias_address, $maa)) {
+                throw new Vilma_Exception(_("That alias already exists!"));
+            }
+
+            // Not there, we create it.
+            $maa[] = $alias_address;
+        } elseif ($alias != $alias_address) {
+            $key = array_search($alias, $maa);
+            if ($key === false) {
+                throw new Vilma_Exception(sprintf(_("Existing entry \"%s\" could not be found."), $alias));
+            }
+            $maa[$key] = $alias_address;
+        } else {
+            return;
+        }
+        sort($maa);
+
+        $dn = $user['dn'];
+        Horde::logMessage("UPDATING: $dn \nOld MAA: " . print_r($oldmaa, true) . "\nNew MAA: " . print_r($maa, true), 'DEBUG');
+
+        // Bind with appropriate dn to give update access.
+        $res = ldap_bind($this->_ldap, $this->_params['ldap']['binddn'],
+                         $this->_params['ldap']['bindpw']);
+        if (!$res) {
+            throw new Vilma_Exception(_("Unable to bind to the LDAP server. Check authentication credentials."));
+        }
+
+        $entry['mailAlternateAddress'] = $maa;
+        $res = @ldap_modify($this->_ldap, $dn, $entry);
+        if ($res === false) {
+            throw new Vilma_Exception(sprintf(_("Error modifying account: %s"), @ldap_error($this->_ldap)));
+        }
+    }
+
+    /**
+     * Deletes alias records for a given user.
+     *
+     * @param array $info  The info used to store the information.
+     *                     Required fields are:
+     *                     - 'address': The destination address (used for LDAP
+     *                       ID lookup).
+     *                     - 'alias': The alias we are deleting.
+     *
+     * @throws Vilma_Exception
+     */
+    public function deleteAlias($info)
+    {
+        $address = $info['address'];
+        $alias = $info['alias'];
+
+        $user_res = $this->_searchForUser($address);
+        if ($res['count'] === 0) {
+            throw new Vilma_Exception(_("Error reading address information from backend."));
+        }
+        $user = $user_res[0];
+
+        // Retrieve the current MAA values.
+        if (!isset($user['mailalternateaddress'])) {
+            return;
+        }
+
+        $maa = $user['mailalternateaddress'];
+        unset($maa['count']);
+        $oldmaa = $maa;
+        $key = array_search($alias, $maa);
+        if ($key === false) {
+            return;
+        }
+
+        unset($maa[$key]);
+        sort($maa);
+
+        $dn = $user['dn'];
+        Horde::logMessage("UPDATING: $dn \nOld MAA: " . print_r($oldmaa, true) . "\nNew MAA: " . print_r($maa, true), 'DEBUG');
+
+        // Bind with appropriate dn to give update access.
+        $res = ldap_bind($this->_ldap, $this->_params['ldap']['binddn'],
+                         $this->_params['ldap']['bindpw']);
+        if (!$res) {
+            throw new Vilma_Exception(_("Unable to bind to the LDAP server. Check authentication credentials."));
+        }
+
+        $entry['mailAlternateAddress'] = $maa;
+        $res = @ldap_modify($this->_ldap, $dn, $entry);
+        if ($res === false) {
+            throw new Vilma_Exception(sprintf(_("Error modifying account: %s"), @ldap_error($this->_ldap)));
+        }
+    }
+
+    /**
+     * Saves or creates forward records for a given user.
+     *
+     * @param array $info  The info used to store the information.
+     *                     Required fields are:
+     *                     - 'address': The destination address (used for LDAP
+     *                       ID lookup).
+     *                     - 'forward_address': The forward to create or the
+     *                       new data for the modified entry.
+     *                     - 'forward': The forward we are modifying, if we are
+     *                       modifying an existing one.
+     *
+     * @throws Vilma_Exception
+     */
+    public function saveForward($info)
+    {
+        $address = $info['address'];
+        if (!empty($info['forward'])) {
+            $forward = $info['forward'];
+            $create = false;
+        } else {
+            $create = true;
+        }
+        $forward_address = $info['forward_address'];
+
+        $user_res = $this->_searchForUser($address);
+        if ($res['count'] === 0) {
+            throw new Vilma_Exception(_("Error reading address information from backend."));
+        }
+        $user = $user_res[0];
+
+        // Retrieve the current MAA values.
+        if (isset($user['mailforwardingaddress'])) {
+            $mfa = $user['mailforwardingaddress'];
+            unset($mfa['count']);
+        } else {
+            $mfa = array();
+        }
+
+        $oldmfa = $mfa;
+        if ($create) {
+            // Verify that it does not already exist
+            if (in_array($forward_address, $mfa)) {
+                throw new Vilma_Exception(sprintf(_("That forward, \"%s\", already exists!"), $forward_address));
+            }
+
+            // Not there, we create it.
+            $mfa[] = $forward_address;
+        } elseif ($forward != $forward_address) {
+            $key = array_search($forward, $mfa);
+            if ($key === false) {
+                throw new Vilma_Exception(sprintf(_("Existing entry \"%s\" could not be found."), $forward));
+            }
+            $mfa[$key] = $forward_address;
+        } else {
+            return;
+        }
+        sort($mfa);
+
+        $dn = $user['dn'];
+        Horde::logMessage("UPDATING: $dn \nOld MFA: " . print_r($oldmfa, true) . "\nNew MFA: " . print_r($mfa, true), 'DEBUG');
+
+        // Bind with appropriate dn to give update access.
+        $res = ldap_bind($this->_ldap, $this->_params['ldap']['binddn'],
+                         $this->_params['ldap']['bindpw']);
+        if (!$res) {
+            throw new Vilma_Exception(_("Unable to bind to the LDAP server. Check authentication credentials."));
+        }
+
+        $entry['mailForwardingAddress'] = $mfa;
+        $res = @ldap_modify($this->_ldap, $dn, $entry);
+        if ($res === false) {
+            throw new Vilma_Exception(sprintf(_("Error modifying account: %s"), @ldap_error($this->_ldap)));
+        }
+    }
+
+    /**
+     * Deletes forward records for a given user.
+     *
+     * @param array $info  The info used to store the information.
+     *                     Required fields are:
+     *                     - 'address': The destination address (used for LDAP
+     *                       ID lookup).
+     *                     - 'forward': The forward we are deleting.
+     *
+     * @throws Vilma_Exception
+     */
+    public function deleteForward($info)
+    {
+        $address = $info['address'];
+        $forward = $info['forward'];
+
+        $user_res = $this->_searchForUser($address);
+        if ($res['count'] === 0) {
+            throw new Vilma_Exception(_("Error reading address information from backend."));
+        }
+        $user = $user_res[0];
+
+        // Retrieve the current MFA values.
+        if (!isset($user['mailforwardingaddress'])) {
+            return;
+        }
+
+        $mfa = $user['mailforwardingaddress'];
+        unset($mfa['count']);
+        $oldmfa = $mfa;
+        $key = array_search($forward, $mfa);
+        if ($key === false) {
+            return;
+        }
+        unset($mfa[$key]);
+        sort($mfa);
+
+        $dn = $user['dn'];
+        Horde::logMessage("UPDATING: $dn \nOld MFA: " . print_r($oldmfa, true) . "\nNew MFA: " . print_r($mfa, true), 'DEBUG');
+        // Bind with appropriate dn to give update access.
+        $res = ldap_bind($this->_ldap, $this->_params['ldap']['binddn'],
+                         $this->_params['ldap']['bindpw']);
+        if (!$res) {
+            throw new Vilma_Exception(_("Unable to bind to the LDAP server. Check authentication credentials."));
+        }
+
+        $entry['mailForwardingAddress'] = $mfa;
+        $res = @ldap_modify($this->_ldap, $dn, $entry);
+        if ($res === false) {
+            throw new Vilma_Exception(sprintf(_("Error modifying account: %s"), @ldap_error($this->_ldap)));
+        }
+    }
+
+    /**
+     * Searchs for a given email account.
+     *
+     * @param string $email_id The id of the account to be searched for.
+     *
+     * @return array  Data for given email account on success or no
+     *                information found.
+     */
+    protected function _searchForUser($email_id)
+    {
+        // Get the user's DN
+        $filter  = '(&';
+        foreach ($this->_params['ldap']['objectclass'] as $objectclass) {
+            // Add each objectClass from parameters.
+            $filter .= '(objectclass=' . $objectclass . ')';
+        }
+        $filter .= '(mail=' . $email_id . '))';
+
+        Horde::logMessage($filter, 'DEBUG');
+        $res = @ldap_search($this->_ldap, $this->_params['ldap']['basedn'], $filter);
+        if ($res === false) {
+            throw new Vilma_Exception(sprintf(_("Error searching LDAP: %s"), @ldap_error($this->_ldap)));
+        }
+        $res = @ldap_get_entries($this->_ldap, $res);
+        if ($res === false) {
+            throw new Vilma_Exception(sprintf(_("Error retrieving LDAP results: %s"), @ldap_error($this->_ldap)));
+        }
+
+        if ($res['count'] === 0) {
+            throw new Vilma_Exception(_("Unable to acquire handle on DN.  Aborting delete operation."));
+        }
+        if($res['count'] !== 1) {
+            throw new Vilma_Exception(_("More than one DN returned.  Aborting delete operation."));
+        }
+
+        return $res;
+    }
+
+    function _connect()
+    {
+        if (!is_null($this->_ldap)) {
+            return;
+        }
+
+        Horde::assertDriverConfig($this->_params['ldap'], 'storage',
+                                  array('ldaphost', 'basedn', 'binddn', 'dn'));
+
+        if (!isset($this->_params['ldap']['bindpw'])) {
+            $this->_params['ldap']['bindpw'] = '';
+        }
+
+        $port = isset($this->_params['ldap']['port'])
+            ? $this->_params['ldap']['port']
+            : 389;
+
+        $this->_ldap = ldap_connect($this->_params['ldap']['ldaphost'], $port);
+        if (!$this->_ldap) {
+            throw new Vilma_Exception("Unable to connect to LDAP server $hostname on $port");
+        }
+        $res = ldap_set_option($this->_ldap, LDAP_OPT_PROTOCOL_VERSION,
+                               $this->_params['ldap']['version']);
+        if (!$res) {
+            throw new Vilma_Exception(_("Unable to set LDAP protocol version"));
+        }
+        $res = ldap_bind($this->_ldap, $this->_params['ldap']['binddn'],
+                         $this->_params['ldap']['bindpw']);
+        if (!$res) {
+            throw new Vilma_Exception(_("Unable to bind to the LDAP server.  Check authentication credentials."));
+        }
+    }
+}
diff --git a/vilma/lib/Driver/Sql.php b/vilma/lib/Driver/Sql.php
new file mode 100644 (file)
index 0000000..fb4d999
--- /dev/null
@@ -0,0 +1,615 @@
+<?php
+/**
+ * Copyright 2003-2010 The Horde Project (http://www.horde.org/)
+ *
+ * See the enclosed file LICENSE for license information (BSD). If you did
+ * did not receive this file, see http://cvs.horde.org/co.php/vilma/LICENSE.
+ *
+ * @author Marko Djukic <marko@oblo.com>
+ * @package Vilma
+ */
+class Vilma_Driver_sql extends Vilma_Driver
+{
+    /**
+     * @var DB
+     */
+    protected $_db;
+
+    /**
+     * Constructor.
+     *
+     * @param array $params  Any parameters needed for this driver.
+     */
+    public function __construct($params)
+    {
+        parent::__construct($params);
+        $this->_initialize();
+    }
+
+    /**
+     * Returns the list of domains from the backend.
+     *
+     * @return array  All the domains and their data in an array.
+     */
+    public function getDomains()
+    {
+        $binds = $this->_getDomainKeyFilter();
+        $sql = 'SELECT ' . $this->_getTableFields('domains')
+            . ' FROM ' . $this->_params['tables']['domains']
+            . $binds[0] . ' ORDER BY domain_name';
+        Horde::logMessage($sql, 'DEBUG');
+        return $this->_db->getAll($sql, $binds[1], DB_FETCHMODE_ASSOC);
+    }
+
+    /**
+     * Returns the specified domain information from the backend.
+     *
+     * @param integer $domain_id  The id of the domain to fetch.
+     *
+     * @return array  The domain's information in an array.
+     */
+    public function getDomain($domain_id)
+    {
+        $binds = $this->_getDomainKeyFilter('AND');
+        $sql = 'SELECT ' . $this->_getTableFields('domains')
+            . ' FROM ' . $this->_params['tables']['domains']
+            . ' WHERE ' . $this->_getTableField('domains', 'domain_id') . ' = ?' . $binds[0];
+        array_unshift($binds[1], (int)$domain_id);
+        Horde::logMessage($sql, 'DEBUG');
+        return $this->_db->getRow($sql, $binds[1], DB_FETCHMODE_ASSOC);
+    }
+
+    /**
+     * Given a domain name returns the information from the backend.
+     *
+     * @param string $name  The name of the domain to fetch.
+     *
+     * @return array  The domain's information in an array.
+     */
+    public function getDomainByName($domain_name)
+    {
+        $binds = $this->_getDomainKeyFilter('AND');
+        $sql = 'SELECT ' . $this->_getTableFields('domains')
+            . ' FROM ' . $this->_params['tables']['domains']
+            . ' WHERE ' . $this->_getTableField('domains', 'domain_name') . ' = ?' . $binds[0];
+        array_unshift($binds[1], $domain_name);
+        Horde::logMessage($sql, 'DEBUG');
+        return $this->_db->getRow($sql, $binds[1], DB_FETCHMODE_ASSOC);
+    }
+
+    /**
+     * Saves a domain with the provided information.
+     *
+     * @param array $info  Array of details to save the domain.
+     */
+    protected function _saveDomain($info)
+    {
+        $record = array('domain_name' => $info['name'],
+                        'domain_transport' => $info['transport'],
+                        'domain_max_users' => (int)$info['max_users'],
+                        'domain_quota' => (int)$info['quota']);
+
+        if (empty($info['domain_id'])) {
+            $record['domain_id'] = $this->_db->nextId($this->_params['tables']['domains']);
+            if (!empty($this->_params['tables']['domainkey'])) {
+                $record['domain_key'] = $this->_params['tables']['domainkey'];
+            }
+
+            $sql = 'INSERT INTO ' . $this->_params['tables']['domains'] . ' '
+                . Horde_SQL::insertValues($this->_db, $this->_prepareRecord('domains', $record));
+            $values = array();
+        } else {
+            $binds = $this->_getDomainKeyFilter('AND');
+            $sql = 'UPDATE ' . $this->_params['tables']['domains']
+                . ' SET ' . Horde_SQL::updateValues($this->_db, $this->_prepareRecord('domains', $record))
+                . ' WHERE ' . $this->_getTableField('domains', 'domain_id') . ' = ?' . $binds[0];
+            array_unshift($binds[1], $info['domain_id']);
+            $values = $binds[1];
+        }
+
+        Horde::logMessage($sql, 'DEBUG');
+        return $this->_db->query($sql, $values);
+    }
+
+    /**
+     * Deletes a domain.
+     *
+     * @param integer $domain_id  The id of the domain to delete.
+     *
+     * @throws Vilma_Exception
+     */
+    protected function _deleteDomain($domain_id)
+    {
+        $domain_record = $this->getDomain($domain_id);
+        $domain_name = $domain_record['domain_name'];
+
+        /* Delete all virtual emails for this domain. */
+        $sql = 'DELETE FROM ' . $this->_params['tables']['virtuals'] .
+               ' WHERE ' . $this->_getTableField('virtuals', 'virtual_email') . ' LIKE ?';
+        $values = array('%@' . $domain_name);
+        $delete = $this->_db->query($sql, $values);
+        if (is_a($delete, 'PEAR_Error')) {
+            throw new Vilma_Exception($delete);
+        }
+
+        /* Delete all users for this domain. */
+        $sql = 'DELETE FROM ' . $this->_params['tables']['users'] .
+               ' WHERE ' . $this->_getTableField('users', 'user_name') . ' LIKE ?';
+        $values = array('%@' . $domain_name);
+        $delete = $this->_db->query($sql, $values);
+        if (is_a($delete, 'PEAR_Error')) {
+            throw new Vilma_Exception($delete);
+        }
+
+        /* Finally delete the domain. */
+        $sql = 'DELETE FROM ' . $this->_params['tables']['domains'] .
+               ' WHERE ' . $this->_getTableField('domains', 'domain_id') . ' = ?';
+        $values = array((int)$domain_id);
+
+        Horde::logMessage($sql, 'DEBUG');
+        return $this->_db->query($sql, $values);
+    }
+
+    /**
+     * Returns the current number of users for a domain.
+     *
+     * @param string $domain_name  The name of the domain for which to
+     *                             get the current number of users.
+     *
+     * @return integer  The current number of users.
+     */
+    public function getDomainNumUsers($domain_name)
+    {
+        $binds = $this->_getUserKeyFilter('AND');
+        $sql = 'SELECT count(' . $this->_getTableField('users', 'user_name') . ')'
+            . ' FROM ' . $this->_params['tables']['users']
+            . ' WHERE ' . $this->_getTableField('users', 'user_name') . ' LIKE ?' . $binds[0];
+        array_unshift($binds[1], '%@' . $domain_name);
+        Horde::logMessage($sql, 'DEBUG');
+        return $this->_db->getOne($sql, $binds[1]);
+    }
+
+    /**
+     * Returns all available users, if a domain name is passed then limit the
+     * list of users only to those users.
+     *
+     * @param string $domain  The name of the domain for which to fetch the
+     *                        users.
+     *
+     * @return array  The available users and their stored information.
+     */
+    public function getUsers($domain = null)
+    {
+        /* Put together the SQL statement. */
+        if (is_null($domain)) {
+            /* Fetch all users. */
+            $binds = $this->_getUserKeyFilter();
+            $sql = 'SELECT ' . $this->_getTableFields('users')
+                . ' FROM ' . $this->_params['tables']['users'] . $binds[0];
+            $values = $binds[1];
+        } else {
+            /* Fetch only users for a domain. */
+            $binds = $this->_getUserKeyFilter('AND');
+            $user_field =  $this->_getTableField('users', 'user_name');
+            $sql = 'SELECT ' . $this->_getTableFields('users')
+                . ' FROM ' . $this->_params['tables']['users']
+                . ' WHERE ' . $user_field . ' LIKE ?' . $binds[0]
+                . ' ORDER BY ' . $user_field;
+            array_unshift($binds[1], '%@' . $domain);
+            $values = $binds[1];
+        }
+        Horde::logMessage($sql, 'DEBUG');
+        return $this->_db->getAll($sql, $values, DB_FETCHMODE_ASSOC);
+    }
+
+    /**
+     * Returns the user information for a given user id.
+     *
+     * @param integer $user_id  The id of the user for which to fetch
+     *                          information.
+     *
+     * @return array  The user information.
+     */
+    public function getUser($user_id)
+    {
+        $binds = $this->_getUserKeyFilter('AND');
+        $sql = 'SELECT ' . $this->_getTableFields('users')
+            . ' FROM ' . $this->_params['tables']['users']
+            . ' WHERE ' . $this->_getTableField('users', 'user_id') . ' = ?' . $binds[0];
+        array_unshift($binds[1], (int)$user_id);
+        Horde::logMessage($sql, 'DEBUG');
+        return $this->_db->getRow($sql, $binds[1], DB_FETCHMODE_ASSOC);
+    }
+
+    /**
+     * Saves a user to the backend.
+     *
+     * @param array $info  The user information to save.
+     *
+     * @return string  The user ID.
+     * @throws Vilma_Exception
+     */
+    protected function _saveUser($info)
+    {
+        /* Access check (for domainkey). */
+        $domain = Vilma::stripDomain($info['user_name']);
+        $this->getDomainByName($domain);
+
+        if (empty($info['user_id'])) {
+            $info['user_id'] = $this->_db->nextId($this->_params['tables']['users']);
+            $create = true;
+        } else {
+            $create = false;
+        }
+
+        // Slightly hackish.
+        $mailboxes = Vilma_MailboxDriver::factory();
+        $mail_dir_base = isset($mailboxes->_params['mail_dir_base'])
+            ? $mailboxes->_params['mail_dir_base']
+            : '?';
+
+        $tuple = array(
+            'user_id'         => (int)$info['user_id'],
+            'user_name'       => $info['user_name'],
+            'user_full_name'  => $info['user_full_name'],
+            'user_home_dir'   => $mail_dir_base,
+            'user_mail_dir'   => $domain . '/' . Vilma::stripUser($info['user_name']) . '/',
+            'user_mail_quota' => $this->getDomainQuota($domain) * 1024 * 1024,
+            'user_enabled'    => (int)$info['user_enabled']);
+
+        // UID and GID are slightly hackish (specific to maildrop driver), too.
+        if (!isset($mailboxes->_params['uid'])) {
+            $tuple['user_uid'] = -1;
+        } else {
+            $tuple['user_uid'] = $mailboxes->_params['uid'];
+        }
+        if (!isset($mailboxes->_params['gid'])) {
+            $tuple['user_gid'] = -1;
+        } else {
+            $tuple['user_gid'] = $mailboxes->_params['gid'];
+        }
+
+        if (!empty($info['password'])) {
+            $tuple['user_clear'] = $info['password'];
+            $tuple['user_crypt'] = crypt($info['password'],
+                                         substr($info['password'], 0, 2));
+        } elseif ($create) {
+            throw new Vilma_Exception(_("Password must be supplied when creating a new user."));
+        }
+
+        if ($create) {
+            $sql = 'INSERT INTO ' . $this->_params['tables']['users'] . ' '
+                . Horde_SQL::insertValues($this->_db, $this->_prepareRecord('users', $tuple));
+        } else {
+            $sql = sprintf('UPDATE %s SET %s WHERE ' . $this->_getTableField('users', 'user_id') . ' = %d',
+                           $this->_params['tables']['users'],
+                           Horde_SQL::updateValues($this->_db, $this->_prepareRecord('users', $tuple)),
+                           (int)$info['user_id']);
+        }
+
+        Horde::logMessage($sql, 'DEBUG');
+        $result = $this->_db->query($sql);
+        if (is_a($result, 'PEAR_Error')) {
+            Horde::logMessage($result, 'ERR');
+            throw new Vilma_Exception($result);
+        }
+
+        return $info['user_id'];
+    }
+
+    /**
+     * Deletes a user.
+     *
+     * @param integer $user_id  The id of the user to delete.
+     *
+     * @throws Vilma_Exception
+     */
+    public function deleteUser($user_id)
+    {
+        $user = $this->getUser($user_id);
+
+        /* Delete all virtual emails for this user. */
+        $sql = 'DELETE FROM ' . $this->_params['tables']['virtuals'] .
+               ' WHERE ' . $this->_getTableField('virtuals', 'virtual_destination') . ' = ?';
+        $values = array($user['user_name']);
+
+        Horde::logMessage($sql, 'DEBUG');
+        $delete = $this->_db->query($sql, $values);
+        if (is_a($delete, 'PEAR_Error')) {
+            throw new Vilma_Exception($delete);
+        }
+
+        /* Delete the actual user. */
+        $sql = 'DELETE FROM ' . $this->_params['tables']['users'] .
+               ' WHERE ' . $this->_getTableField('users', 'user_id') . ' = ?';
+        $values = array((int)$user_id);
+
+        Horde::logMessage($sql, 'DEBUG');
+        $result = $this->_db->query($sql, $values);
+        if (is_a($result, 'PEAR_Error')) {
+            throw new Vilma_Exception($result);
+        }
+
+        Vilma_MailboxDriver::factory()
+            ->deleteMailbox(Vilma::stripUser($user['user_name']),
+                            Vilma::stripDomain($user['user_name']));
+    }
+
+    /**
+     * Returns a list of all users, aliases, or groups and forwards for a
+     * domain.
+     *
+     * @param string $domain      Domain on which to search.
+     * @param string $type        Only return a specific type. One of 'all',
+     *                            'user', 'alias','forward', or 'group'.
+     * @param string $key         Sort list by this key.
+     * @param integer $direction  Sort direction.
+     *
+     * @return array Account information for this domain
+     */
+    protected function _getAddresses($domain, $type = 'all')
+    {
+        $addresses = array();
+        if ($type == 'all' || $type == 'user') {
+            $addresses += $this->getUsers($domain);
+        }
+        if ($type == 'all' || $type == 'alias') {
+            $addresses += $this->getVirtuals($domain);
+        }
+        return $addresses;
+    }
+
+    /**
+     * Returns available virtual emails.
+     *
+     * @param string $filter  If passed a domain then return all virtual emails
+     *                        for the domain, otherwise if passed a user name
+     *                        return all virtual emails for that user.
+     *
+     * @return array  The available virtual emails.
+     */
+    public function getVirtuals($filter)
+    {
+        $email_field = $this->_getTableField('virtuals', 'virtual_email');
+        $destination_field = $this->_getTableField('virtuals', 'virtual_destination');
+
+        /* Check if filtering only for domain. */
+        if (strpos($filter, '@') === false) {
+            $where = $email_field . ' LIKE ?';
+            $values = array('%@' . $filter);
+        } else {
+            $where = $destination_field . ' = ?';
+            $values = array($filter);
+        }
+
+        $binds = $this->_getVirtualKeyFilter('AND');
+        $sql = 'SELECT ' . $this->_getTableFields('virtuals')
+            . ' FROM ' . $this->_params['tables']['virtuals']
+            . ' WHERE ' . $where . $binds[0]
+            . ' ORDER BY ' . $destination_field . ', ' . $email_field;
+        $values = array_merge($values, $binds[1]);
+
+        Horde::logMessage($sql, 'DEBUG');
+        return $this->_db->getAll($sql, $values, DB_FETCHMODE_ASSOC);
+    }
+
+    /**
+     * Returns information for a virtual id.
+     *
+     * @param integer $virtual_id  The virtual id for which to return
+     *                             information.
+     *
+     * @return array  The virtual email information.
+     */
+    public function getVirtual($virtual_id)
+    {
+        $binds = $this->_getVirtualKeyFilter('AND');
+        $sql = 'SELECT ' . $this->_getTableFields('virtuals')
+            . ' FROM ' . $this->_params['tables']['virtuals']
+            . ' WHERE ' . $this->_getTableField('virtuals', 'virtual_id') . ' = ?' . $binds[0];
+        array_unshift($binds[1], (int)$virtual_id);
+
+        Horde::logMessage($sql, 'DEBUG');
+        $virtual = $this->_db->getRow($sql, $binds[1], DB_FETCHMODE_ASSOC);
+        $virtual['stripped_email'] = Vilma::stripUser($virtual['virtual_email']);
+
+        return $virtual;
+    }
+
+    /**
+     * Saves virtual email address to the backend.
+     *
+     * @param array $info     The virtual email data.
+     * @param string $domain  The name of the domain for this virtual email.
+     *
+     * @throws Vilma_Exception
+     */
+    public function saveVirtual($info, $domain)
+    {
+        /* Access check (for domainkey) */
+        $this->getDomainByName($domain);
+
+        if (empty($info['virtual_id'])) {
+            $info['virtual_id'] = $this->_db->nextId($this->_params['tables']['virtuals']);
+            $sql = 'INSERT INTO ' . $this->_params['tables']['virtuals']
+                . ' (' . $this->_getTableField('virtuals', 'virtual_email') . ', '
+                       . $this->_getTableField('virtuals', 'virtual_destination') . ', '
+                       . $this->_getTableField('virtuals', 'virtual_id') . ') VALUES (?, ?, ?)';
+        } else {
+            $sql = 'UPDATE ' . $this->_params['tables']['virtuals']
+                . ' SET ' . $this->_getTableField('virtuals', 'virtual_email') . ' = ?, '
+                          . $this->_getTableField('virtuals', 'virtual_destination') . ' = ?'
+                . ' WHERE ' . $this->_getTableField('virtuals', 'virtual_id') . ' = ?';
+        }
+        $values = array($info['stripped_email'] . '@' . $domain,
+                        $info['virtual_destination'],
+                        $info['virtual_id']);
+
+        Horde::logMessage($sql, 'DEBUG');
+        return $this->_db->query($sql, $values);
+    }
+
+    /**
+     * Deletes a virtual email.
+     *
+     * @param integer $virtual_id  The id of the virtual email to delete.
+     */
+    public function deleteVirtual($virtual_id)
+    {
+        $binds = $this->_getVirtualKeyFilter('AND');
+        $sql = 'DELETE FROM ' . $this->_params['tables']['virtuals']
+            . ' WHERE ' . $this->_getTableField('virtuals', 'virtual_id') . ' = ?' . $binds[0];
+        array_unshift($binds[1], $virtual_id);
+        Horde::logMessage($sql, 'DEBUG');
+        return $this->_db->query($sql, $binds[1]);
+    }
+
+    /**
+     * Constructs an SQL WHERE fragment to filter domains by domain key.
+     *
+     * @param string $join  Keyword to join expression to rest of SQL statement
+     *                      (e.g. 'WHERE' or 'AND').
+     *
+     * @return array  An SQL fragment and a list of values suitable for
+     *                binding.
+     */
+    protected function _getDomainKeyFilter($join = 'WHERE')
+    {
+        if (empty($this->_params['tables']['domainkey'])) {
+            return array('', array());
+        }
+
+        return array(' ' . $join . ' domain_key = ?',
+                     array($this->_params['tables']['domainkey']));
+    }
+
+    /**
+     * Constructs an SQL WHERE fragment to filter users by domain key.
+     *
+     * @param string $join  Keyword to join expression to rest of SQL statement
+     *                      (e.g. 'WHERE' or 'AND'). Default: 'WHERE'.
+     *
+     * @return array  An SQL fragment and a list of values suitable for
+     *                binding.
+     */
+    protected function _getUserKeyFilter($join = 'WHERE')
+    {
+        if (empty($this->_params['tables']['domainkey'])) {
+            return array('', array());
+        }
+
+        $binds = $this->_getDomainKeyFilter('AND');
+        return array(' ' . $join . ' EXISTS (SELECT domain_name' .
+                     ' FROM ' . $this->_params['tables']['domains'] .
+                     ' WHERE ' . $this->_getTableField('users', 'user_name') .
+                     ' LIKE ? || ' . $this->_getTableField('domains', 'domain_name') .
+                     ' ' . $binds[0] . ' )',
+                     array_unshift($binds[1], '%@'));
+    }
+
+    /**
+     * Constructs an SQL WHERE fragment to filter virtuals by domain key.
+     *
+     * @param string $join  Keyword to join expression to rest of SQL statement
+     *                      (e.g. 'WHERE' or 'AND').  Default: 'WHERE'.
+     *
+     * @return array  An SQL fragment and a list of values suitable for
+     *                binding.
+     */
+    protected function _getVirtualKeyFilter($join = 'WHERE')
+    {
+        if (empty($this->_params['tables']['domainkey'])) {
+            return array('', array());
+        }
+
+        $binds = $this->_getDomainKeyFilter('AND');
+        return array(' ' . $join . ' EXISTS (SELECT domain_name' .
+                     ' FROM ' . $this->_params['tables']['domains'] .
+                     ' WHERE ' . $this->_getTableField('virtuals', 'virtual_email') .
+                     ' LIKE ? || ' . $this->_getTableField('domains', 'domain_name') .
+                     ' ' . $binds[0] . ' )',
+                     array_unshift($binds[1], '%@'));
+    }
+
+    /**
+     * Returns the list of fields from a specific table for SQL statements.
+     *
+     * @return string
+     */
+    protected function _getTableFields($table)
+    {
+        if (empty($this->_params['tables'][$table . '_fields'])) {
+            switch ($table) {
+            case 'domains':
+                return 'domain_id, domain_name, domain_transport, domain_max_users, domain_quota';
+            default:
+                return '*';
+            }
+        }
+
+        $domainsFields = $this->_params['tables'][$table . '_fields'];
+        foreach ($domainsFields as $defaultName => $customName) {
+            $fields[] = $customName . ' AS ' . $defaultName;
+        }
+
+        return implode(', ', $fields);
+    }
+
+    /**
+     * Returns the real name of a field from a specific table for SQL
+     * statements.
+     *
+     * @return string
+     */
+    protected function _getTableField($table, $field)
+    {
+        if (empty($this->_params['tables'][$table . '_fields'])) {
+            return $field;
+        }
+        return $this->_params['tables'][$table . '_fields'][$field];
+    }
+
+    /**
+     *
+     *
+     * @return array
+     */
+    protected function _prepareRecord($table, $record)
+    {
+        if (empty($this->_params['tables'][$table . '_fields'])) {
+            return $record;
+        }
+
+        $domainsFields = $this->_params['tables'][$table . '_fields'];
+        $newRecord = array();
+        foreach ($record as $defaultName => $value) {
+            $newRecord[$domainsFields[$defaultName]] = $record[$defaultName];
+        }
+        return $newRecord;
+    }
+
+    /**
+     * Initializes this backend, connects to the SQL database.
+     *
+     * @throws Vilma_Exception
+     */
+    protected function _initialize()
+    {
+        try {
+            $this->_db = $GLOBALS['injector']->getInstance('Horde_Core_Factory_DbPear')->create('rw', 'vilma', 'storage');
+        } catch (Exception $e) {
+            throw Vilma_Exception($e);
+        }
+
+        /* Use default table names if these are not set. */
+        if (!isset($this->_params['tables']['domains'])) {
+            $this->_params['tables']['domains'] = 'vilma_domains';
+        }
+        if (!isset($this->_params['tables']['users'])) {
+            $this->_params['tables']['users'] = 'vilma_users';
+        }
+        if (!isset($this->_params['tables']['virtuals'])) {
+            $this->_params['tables']['virtuals'] = 'vilma_virtuals';
+        }
+    }
+}
diff --git a/vilma/lib/Driver/qmailldap.php b/vilma/lib/Driver/qmailldap.php
deleted file mode 100644 (file)
index 31bef06..0000000
+++ /dev/null
@@ -1,1261 +0,0 @@
-<?php
-/**
- * Copyright 2006-2007 Alkaloid Networks <http://www.alkaloid.net>
- *
- * See the enclosed file LICENSE for license information (BSD). If you did
- * did not receive this file, see http://cvs.horde.org/co.php/vilma/LICENSE.
- *
- * @author Ben Klang <bklang@alkaloid.net>
- * @author David Cummings <davidcummings@acm.org>
- * @package Vilma
- */
-class Vilma_Driver_qmailldap extends Vilma_Driver {
-
-    /**
-     * @var _LDAP Reference to initialized LDAP driver
-     */
-    var $_ldap;
-
-    /**
-     * @var _dbparams Configuration parameters for the LDAP driver
-     */
-    var $_ldapparams;
-
-    /**
-     * @var _db Reference to the initialized database driver
-     */
-    var $_db;
-
-    /**
-     * @var _dbparams Configuration parameters for the database driver
-     */
-    var $_dbparams;
-
-    function Vilma_Driver_qmailldap($params)
-    {
-        parent::Vilma_Driver($params);
-        $this->_ldapparams = $this->_params['ldap'];
-        $this->_sqlparams = Horde::getDriverConfig('storage', 'sql');
-        $res = $this->_connect();
-        if (is_a($res, 'PEAR_Error')) {
-            return $res;
-        }
-
-        /* Connect to the backend for tracking domains. */
-        $this->_dbinit();
-    }
-
-    /**
-     * Gets the list of domains from the backend.
-     *
-     * @return array  All the domains and their data in an array.
-     */
-    function getDomains()
-    {
-        $sql = 'SELECT domain_id, domain_name, domain_transport, ' .
-               'domain_max_users, domain_quota FROM vilma_domains ' .
-               'ORDER BY domain_name';
-
-        Horde::logMessage($sql, 'DEBUG');
-        return $this->_db->getAll($sql, $values, DB_FETCHMODE_ASSOC);
-    }
-
-    /**
-     * Gets the specified domain information from the backend.
-     *
-     * @param integer $domain_id  The id of the domain to fetch.
-     *
-     * @return array  The domain's information in an array.
-     */
-    function getDomain($domain_id)
-    {
-        $sql = 'SELECT domain_id, domain_name, domain_transport, ' .
-               'domain_max_users, domain_quota FROM vilma_domains ' .
-               'WHERE domain_id=? ORDER BY domain_name';
-        $values = array($domain_id);
-
-        Horde::logMessage($sql, 'DEBUG');
-        return $this->_db->getRow($sql, $values, DB_FETCHMODE_ASSOC);
-    }
-
-    /**
-     * Given a domain name returns the information from the backend.
-     *
-     * @param string $name  The name of the domain to fetch.
-     *
-     * @return array  The domain's information in an array.
-     */
-    function getDomainByName($domain_name)
-    {
-        $sql = 'SELECT domain_id, domain_name, domain_transport, ' .
-               'domain_max_users, domain_quota FROM vilma_domains ' .
-               'WHERE domain_name=?';
-        $values = array($domain_name);
-
-        Horde::logMessage($sql, 'DEBUG');
-        return $this->_db->getRow($sql, $values, DB_FETCHMODE_ASSOC);
-    }
-
-    /**
-     * Returns a list of all users, aliases, or groups and forwards for a
-     * domain.
-     *
-     * @param string $domain      Domain on which to search.
-     * @param string $type        Only return a specific type. One of 'all',
-     *                            'user', 'alias','forward', or 'group'.
-     * @param string $key         Sort list by this key.
-     * @param integer $direction  Sort direction.
-     *
-     * @return array Account information for this domain
-     */
-    protected function _getAddresses($domain, $type = 'all')
-    {
-        Horde::logMessage("Get Addresses Called for $domain with type $type and key $key", 'DEBUG');
-        $addresses = array();
-        if ($type == 'all' || $type == 'user') {
-            $addresses += $this->_getUsers($domain);
-        }
-        if ($type == 'all' || $type == 'alias') {
-            $addresses += $this->_getAliases($domain);
-        }
-        if ($type == 'all' || $type == 'forward') {
-            $addresses += $this->_getGroupsAndForwards('forward', $domain);
-        }
-        if ($type == 'all' || $type == 'group') {
-            $addresses += $this->_getGroupsAndForwards('group', $domain);
-        }
-        return $addresses;
-    }
-
-    function getUser($user_id) {
-        $user = $this->getUserStatus($user_id);
-
-        if (is_a($user, 'PEAR_Error')) {
-            return PEAR::raiseError(sprintf(_("Unable to qualify address: %s"), $user->getMessage()));
-        }
-        if(isset($user) && is_array($user)) {
-            return $user;
-        } else {
-            return PEAR::raiseError(_("Unable to qualify address."));
-        }
-    }
-
-    /**
-     * Returns an array of all users, aliases, groups and forwards for this
-     * domain.
-     *
-     * @param string $domain Domain on which to search
-     * @param optional string $type Only return a specific type
-     *
-     * @return array Account information for this domain
-     */
-    function _getUsers($domain = null)
-    {
-        //$domain = $domain['domain_name'];
-        // Cache for multiple calls
-        static $users = array();
-        if (is_null($domain) && isset($users['_all'])) {
-            return $users['_all'];
-        }
-
-        if (!is_null($domain)
-               && isset($users[$domain])) {
-            return $users[$domain];
-        }
-
-        $filter = '(&';
-        if (!is_null($domain)) {
-            $filter .= '(mail=*@' . $domain . ')';
-        } else {
-            $domain = '_all';
-        }
-
-        // Make sure we don't get any forwards
-        $filter .= '(!(mailForwardingAddress=*))';
-
-        // FIXME: Check/add configured filter instead of objectclasses
-        foreach ($this->_ldapparams['objectclass'] as $objectclass) {
-            $filter .= '(objectClass=' . $objectclass . ')';
-        }
-        $filter .= ')';
-
-        Horde::logMessage($filter, 'DEBUG');
-        $res = ldap_search($this->_ldap, $this->_ldapparams['basedn'], $filter);
-        if ($res === false) {
-            return PEAR::raiseError(sprintf(_("Error in LDAP search: %s"), ldap_error($this->LDAP)));
-        }
-
-        $res = ldap_get_entries($this->_ldap, $res);
-        if ($res === false) {
-            return PEAR::raiseError(sprintf(_("Error in LDAP search: %s"), ldap_error($this->LDAP)));
-        }
-
-        $users[$domain] = array();
-        $i = 0;
-        // Can't use foreach because of the array format returned by LDAP driver
-        while ($user = @$res[$i]) {
-            $users[$domain][$i]['id'] = $user['dn'];
-            $users[$domain][$i]['address'] = $user[$this->_getAttrByField('address')][0];
-            $users[$domain][$i]['type'] = 'user';
-            $users[$domain][$i]['user_name'] =
-                $user[$this->_getAttrByField('user_name')][0];
-            // We likely don't have read permission on the crypted password so
-            // avoid any warnings/errors about missing array elements
-            if (isset($user[$this->_getAttrByField('user_crypt')])) {
-                $users[$domain][$i]['user_crypt'] =
-                    $user[$this->_getAttrByField('user_crypt')][0];
-            } else {
-                $users[$domain][$i]['user_crypt'] = '';
-            }
-            $users[$domain][$i]['user_full_name'] =
-                $user[$this->_getAttrByField('user_full_name')][0];
-            // Mute assignment errors on the following optional fields
-            // These may not be present if the mail is only forwarded
-            $users[$domain][$i]['user_uid'] =
-                @$user[$this->_getAttrByField('user_uid')][0];
-            $users[$domain][$i]['user_gid'] =
-                @$user[$this->_getAttrByField('user_gid')][0];
-            $users[$domain][$i]['user_home_dir'] =
-                @$user[$this->_getAttrByField('user_home_dir')][0];
-            $users[$domain][$i]['user_mail_dir'] =
-                @$user[$this->_getAttrByField('user_mail_dir')][0];
-            $users[$domain][$i]['user_mail_quota_bytes'] =
-                @$user[$this->_getAttrByField('user_mail_quota_bytes')][0];
-            $users[$domain][$i]['user_mail_quota_count'] =
-                @$user[$this->_getAttrByField('user_mail_quota_count')][0];
-
-            // If accountStatus is blank it's the same as active
-            if (!isset($user[$this->_getAttrByField('user_enabled')][0]) ||
-                ($user[$this->_getAttrByField('user_enabled')][0] == 'active')) {
-                $users[$domain][$i]['user_enabled'] = 'active';
-            } else {
-                // accountStatus can also be:
-                // noaccess (receives but cannot pick up mail)
-                // disabled (bounce incoming and deny pickup)
-                // deleted (bounce incoming but allow pickup)
-                $users[$domain][$i]['user_enabled'] =
-                    $user[$this->_getAttrByField('user_enabled')][0];
-            }
-
-            $i++;
-        }
-
-        return $users[$domain];
-    }
-
-    function _getFields()
-    {
-        // LDAP attributes are always returned lower case!
-        static $fields = array(
-            'address' => 'mail',
-            'user_name' => 'uid',
-            'user_crypt' => 'userpassword',
-            'user_full_name' => 'cn',
-            'user_uid' => 'qmailuid',
-            'user_gid' => 'qmailgid',
-            'user_home_dir' => 'homedirectory',
-            'user_mail_dir' => 'mailmessagestore',
-            'user_mail_quota_bytes' => 'mailquotasize',
-            'user_mail_quota_count' => 'mailquotacount',
-            'user_enabled' => 'accountstatus',
-        );
-
-        return $fields;
-
-    }
-
-    function _getAttrByField($field) {
-        $fields = $this->_getFields();
-        return $fields[$field];
-    }
-
-    function _getFieldByAttr($attr) {
-        $attrs = array_flip($this->_getFields());
-        return $attrs[$attr];
-    }
-
-    /**
-     * Returns available email address aliases.  This method should not be
-     * called directly but rather by way of getAddresses().
-     *
-     * @access private
-     *
-     * @param string $target  If passed a domain then return all alias emails
-     *                        for the domain, otherwise if passed a user name
-     *                        return all virtual emails for that user.
-     *
-     * @return array  The used email aliases
-     */
-    function _getAliases($target = null)
-    {
-        // FIXME: Add static cache
-
-        $filter  = '(&'; // Begin filter (cumulative AND)
-        foreach ($this->_ldapparams['objectclass'] as $objectclass) {
-            // Add each objectClass from parameters
-            $filter .= '(objectClass=' . $objectclass . ')';
-        }
-        // FIXME: Add preconfigured filter from $this->_ldapparams
-
-        // Check if filtering only for domain.
-        if (($pos = strpos($target, '@')) === false && !empty($target)) {
-            $filter .= '(mailAlternateAddress=*@' . $target . ')';
-        // Otherwise filter for all aliases
-        } else {
-            $filter .= '(mailAlternateAddress=*)';
-            // Restrict the results to $target
-            if (!empty($target)) {
-                $filter .= '(mail=' . $target . ')'; // Add user's email
-            }
-        }
-        $filter .= ')'; // End filter
-
-        Horde::logMessage($filter, 'DEBUG');
-        $res = @ldap_search($this->_ldap, $this->_ldapparams['basedn'], $filter);
-        if ($res === false) {
-            return PEAR::raiseError(sprintf(_("Error searching LDAP: %s"),
-                @ldap_error($this->_ldap)));
-        }
-
-        $res = @ldap_get_entries($this->_ldap, $res);
-        if ($res === false) {
-            return PEAR::raiseError(sprintf(_("Error returning LDAP results: %s"), @ldap_error($this->_ldap)));
-        }
-
-        $aliases = array();
-        // Can't use foreach because of the array format returned by LDAP driver
-        $i = 0; // Virtual address index
-        $e = 0; // Entry counter
-        while ($entry = @$res[$e]) {
-            // If accountStatus is blank it's the same as active
-            if (!isset($entry[$this->_getAttrByField('user_enabled')][0]) ||
-                ($entry[$this->_getAttrByField('user_enabled')][0] == 'active')) {
-                $curstatus = 'active';
-            } else {
-                // accountStatus can also be:
-                // noaccess (receives but cannot pick up mail)
-                // disabled (bounce incoming and deny pickup)
-                // deleted (bounce incoming but allow pickup)
-                $curstatus = $entry[$this->_getAttrByField('user_enabled')][0];
-            }
-            $a = 0; // Attribute counter
-            while ($mail = @$entry['mailalternateaddress'][$a]) {
-                $aliases[$i]['id'] = $mail;
-                $aliases[$i]['type'] = 'alias';
-                $aliases[$i]['user_name'] = $mail;
-                $aliases[$i]['user_full_name'] = sprintf(_("Alias for %s"), $entry['mail'][0]);
-                $aliases[$i]['destination'] = $entry['mail'][0];
-                $aliases[$i]['user_enabled'] = $curstatus;
-                $a++;
-                $i++;
-            }
-            $e++;
-        }
-
-        return $aliases;
-    }
-
-    /**
-     * Returns all available groups and forwards unless otherwise specified.
-     * If a domain name is passed then limit the results to groups or forwards
-     * in that domain.  This method should not be called directly, but rather by
-     * way of getAddresses()
-     *
-     * @access private
-     *
-     * @param string $acquire The default behavior is to acquire both
-     *                        groups and forwards; a value of 'group'
-     *                        will return only groups and a value of
-     *                        'forward' will return only forwards.
-     * @param string $domain  The name of the domain from which to fetch
-     *
-     * @return array  The available groups and forwards with details
-     */
-    function _getGroupsAndForwards($acquire = null, $domain = null)
-    {
-        // Cache
-        static $grpfwds;
-        // TODO ?
-        /*
-        if (is_null($domain) && isset($grpfwds['_all'])) {
-            return $grpfwds['_all'];
-        }
-        if (!is_null($domain) && isset($grpfwds[$domain])) {
-            return $grpfwds[$domain];
-        }
-        */
-        $filter  = '(&'; // Begin filter (cumulative AND)
-        foreach ($this->_ldapparams['objectclass'] as $objectclass) {
-            // Add each objectClass from parameters
-            $filter .= '(objectClass=' . $objectclass . ')';
-        }
-        // FIXME: Add preconfigured filter from $this->_ldapparams
-
-        // Only return results which have a forward configured
-        $filter .= '(mailForwardingAddress=*)';
-
-        if (!empty($domain)) {
-            $filter .= '(|'; // mail or mailAlternateAddress
-            $filter .= '(mail=*@' . $domain . ')';
-            $filter .= '(mailAlternateAddress=*@' . $domain . ')';
-            $filter .= ')'; // end mail or mailAlternateAddress
-        } else {
-            $domain = '_all';
-        }
-        $filter .= ')'; // End filter
-        Horde::logMessage($filter, 'DEBUG');
-        $res = @ldap_search($this->_ldap, $this->_ldapparams['basedn'], $filter);
-        if ($res === false) {
-            return PEAR::raiseError(sprintf(_("Error searching LDAP: %s"),
-                @ldap_error($this->_ldap)));
-        }
-
-        $res = @ldap_get_entries($this->_ldap, $res);
-        if ($res === false) {
-            return PEAR::raiseError(sprintf(_("Error returning LDAP results: %s"), @ldap_error($this->_ldap)));
-        }
-
-        $grpfwds[$domain] = array();
-        // Can't use foreach because of the array format returned by LDAP driver
-        $i = 0; // Address index
-        $e = 0; // Entry counter
-
-        while ($entry = @$res[$e]) {
-            $targets = array();
-            $a = 0; // Attribute counter
-            while ($attr = @$res[$e]['mailforwardingaddress'][$a]) {
-                $targets[] = $attr;
-                $a++;
-            }
-            $type = $entry['mailforwardingaddress']["count"];
-            if($type > 1) {
-                $type = 'group';
-            } else {
-                $type = 'forward';
-            }
-            if(($acquire == 'all') || ($type == $acquire)) {
-                $grpfwds[$domain][$i] = array(
-                    'id' => $entry['dn'],
-                    'type' => $type,
-                    'address' => $entry[$this->_getAttrByField('address')][0],
-                    'targets' => $targets,
-                    'user_name' => $entry[$this->_getAttrByField('user_name')][0],
-                    'user_full_name' => @$entry[$this->_getAttrByField('user_name')][0],
-                );
-                // If accountStatus is blank it's the same as active
-                if (!isset($entry[$this->_getAttrByField('user_enabled')][0]) ||
-                    ($entry[$this->_getAttrByField('user_enabled')][0] == 'active')) {
-                    $grpfwds[$domain][$i]['user_enabled'] = 'active';
-                } else {
-                    // accountStatus can also be:
-                    // noaccess (receives but cannot pick up mail)
-                    // disabled (bounce incoming and deny pickup)
-                    // deleted (bounce incoming but allow pickup)
-                    $grpfwds[$domain][$i]['user_enabled'] =
-                        $entry[$this->_getAttrByField('user_enabled')][0];
-                }
-            } else {
-                $e++;
-                continue;
-            }
-            $e++;
-            $i++;
-        }
-        return $grpfwds[$domain];
-    }
-
-    /**
-     * Returns information for an email alias
-     *
-     * @param string $id  The email alias id for which to return information.
-     *
-     * @return array  The virtual email information.
-     */
-    function getAddressInfo($address, $type = 'all')
-    {
-        Horde::logMessage("Get Addresses Called for $address with type $type and key $key", 'DEBUG');
-        if ($type != 'alias') {
-            return parent::getAddressInfo($address, $type);
-        } else {
-            // FIXME: Which is faster?  A linear array search or an LDAP search?
-            // I think LDAP in this case because we can't assume the domain.
-            $filter = '(&'; // Begin filter (cumulative AND)
-            foreach ($this->_ldapparams['objectclass'] as $objectclass) {
-                // Add each objectClass from parameters
-                $filter .= '(objectClass=' . $objectclass . ')';
-            }
-            $filter .= '(mailAlternateAddress=' . $address . ')';
-            $filter .= ')'; // End filter
-            Horde::logMessage($filter, 'DEBUG');
-            $res = @ldap_search($this->_ldap, $this->_ldapparams['basedn'], $filter);
-            if ($res === false) {
-                return PEAR::raiseError(sprintf(_("Error searching LDAP: %s"),
-                    @ldap_error($this->_ldap)));
-            }
-            $res = @ldap_get_entries($this->_ldap, $res);
-            if ($res === false) {
-                return PEAR::raiseError(sprintf(_("Error returning LDAP results: %s"), @ldap_error($this->_ldap)));
-            }
-
-            if ($res['count'] !== 1) {
-                return PEAR::raiseError(_("More than one DN returned for this alias.  Please contact an administrator to resolve this error."));
-            }
-
-            return array(
-                'id' => $res[0]['dn'],
-                'address' => $address,
-                'destination' => $res[0]['mail'][0],
-            );
-        }
-    }
-
-    /**
-     * Returns the current number of set up users for a domain.
-     *
-     * @param string $domain_name  The name of the domain for which to
-     *                             get the current number of users.
-     *
-     * @return integer  The current number of users.
-     */
-    function getDomainNumUsers($domain_name)
-    {
-        return count($this->_getUsers($domain_name));
-    }
-
-    /**
-     * Saves a domain to the backend.
-     *
-     * @param array $info  The domain information to save to the backend.
-     *
-     * @return mixed  True on success or PEAR error otherwise.
-     */
-    function _saveDomain(&$info)
-    {
-        // We store the records within Horde's configured SQL database for
-        // Vilma because LDAP has no mechanism for tracking domains
-        // that are valid for this system.
-        $values = array($info['name'], $info['transport'],
-                        (int)$info['max_users'], (int)$info['quota']);
-
-        if (empty($info['domain_id'])) {
-            $nextid = $this->_db->nextId('vilma_domains');
-            $sql = 'INSERT INTO vilma_domains (domain_id, domain_name, ' .
-                   'domain_transport, domain_max_users, domain_quota) VALUES ' .
-                   '(?, ?, ?, ?, ?)';
-            array_unshift($values, $nextid);
-        } else {
-            $sql = 'UPDATE vilma_domains SET domain_name=?, ' .
-                   'domain_transport=?, domain_max_users=?, domain_quota=? ' .
-                   'WHERE domain_id=?';
-            array_push($values, $info['domain_id']);
-        }
-        Horde::logMessage($sql, 'DEBUG');
-        return $this->_db->query($sql, $values);
-    }
-
-    /**
-     * Deletes a given domain.
-     *
-     * @param string $domain_id  The id of the domain to delete.
-     *
-     * @return mixed  True on success or PEAR error otherwise.
-     */
-    function _deleteDomain($domain_id)
-    {
-        $domain_record = $this->getDomain($domain_id);
-        if (is_a($domain_record, 'PEAR_Error')) {
-            return $domain_record;
-        }
-
-        $domain_name = $domain_record['domain_name'];
-
-        // FIXME: Add logic to remove all users, aliases, and grpfwds for this
-        // domain
-
-        /* Finally delete the domain. */
-        $sql = 'DELETE FROM vilma_domains WHERE domain_id=?';
-        $values = array((int)$domain_id);
-
-        Horde::logMessage($sql, 'DEBUG');
-        return $this->_db->query($sql, $values);
-    }
-
-    /**
-     * Searchs for a given email account.
-     *
-     * @param string $email_id The id of the account to be searched for.
-     *
-     * @return Array of data for given email account on success or no
-     *     information found; and for an error a PEAR::Error otherwise.
-     */
-    function searchForAliases($email_id) {
-        // Get the user's DN
-        $filter  = '(&'; // Begin filter (cumulative AND)
-        foreach ($this->_ldapparams['objectclass'] as $objectclass) {
-            // Add each objectClass from parameters
-            $filter .= '(objectClass=' . $objectclass . ')';
-        }
-        /*
-        // Check if filtering only for domain.
-        if (($pos = strpos($target, '@')) === false && !empty($email_id)) {
-            $filter .= '(mailAlternateAddress=*@' . $email_id . ')';
-        // Otherwise filter for all aliases
-        } else {
-            $filter .= '(mailAlternateAddress=*)';
-            // Restrict the results to $target
-            if (!empty($email_id)) {
-                $filter .= '(mail=' . $email_id . ')'; // Add user's email
-            }
-        }
-        */
-        $filter .= '(mailAlternateAddress=' . $email_id . ')';
-        $filter .= ')'; // End filter
-
-        //echo $filter;
-        Horde::logMessage($filter, 'DEBUG');
-        $res = @ldap_search($this->_ldap, $this->_ldapparams['basedn'], $filter);
-        if ($res === false) {
-            return PEAR::raiseError(sprintf(_("Error searching LDAP: %s"),
-                @ldap_error($this->_ldap)));
-        }
-        $res = @ldap_get_entries($this->_ldap, $res);
-        if ($res === false) {
-            return PEAR::raiseError(sprintf(_("Error retrieving LDAP results: %s"), @ldap_error($this->_ldap)));
-        }
-
-        return $res;
-    }
-
-    /**
-     * Searchs for a given email account.
-     *
-     * @param string $email_id The id of the account to be searched for.
-     *
-     * @return Array of data for given email account on success or no
-     *     information found; and for an error a PEAR::Error otherwise.
-     */
-    function searchForUser($email_id)
-    {
-        // Get the user's DN
-        $filter  = '(&';
-        foreach ($this->_ldapparams['objectclass'] as $objectclass) {
-            // Add each objectClass from parameters
-            $filter .= '(objectclass=' . $objectclass . ')';
-        }
-        $filter .= '(mail=' . $email_id . '))';
-
-        Horde::logMessage($filter, 'DEBUG');
-        $res = @ldap_search($this->_ldap, $this->_ldapparams['basedn'], $filter);
-        if ($res === false) {
-            return PEAR::raiseError(sprintf(_("Error searching LDAP: %s"),
-                @ldap_error($this->_ldap)));
-        }
-        $res = @ldap_get_entries($this->_ldap, $res);
-        if ($res === false) {
-            return PEAR::raiseError(sprintf(_("Error retrieving LDAP results: %s"), @ldap_error($this->_ldap)));
-        }
-
-        if ($res['count'] === 0) {
-            return PEAR::raiseError(_("Unable to acquire handle on DN.  Aborting delete operation."));
-        } else if($res['count'] !== 1) {
-            return PEAR::raiseError(_("More than one DN returned.  Aborting delete operation."));
-        }
-        return $res;
-    }
-
-    /**
-     * Deletes a given email account.
-     *
-     * @param string $email_id The id of the account to delete (not an alias)
-     *
-     * @return mixed True on success or PEAR::Error otherwise.
-     */
-    function deleteUser($email_id)
-    {
-        // Get the user's DN
-        $filter  = '(&';
-        foreach ($this->_ldapparams['objectclass'] as $objectclass) {
-            // Add each objectClass from parameters
-            $filter .= '(objectclass=' . $objectclass . ')';
-        }
-        $filter .= '(mail=' . $email_id . ')';
-        //echo $email_id . '<br>';
-        $filter .= ')';
-        Horde::logMessage($filter, 'DEBUG');
-        $res = @ldap_search($this->_ldap, $this->_ldapparams['basedn'], $filter);
-        if ($res === false) {
-            return PEAR::raiseError(sprintf(_("Error searching LDAP: %s"),
-                @ldap_error($this->_ldap)));
-        }
-        $res = @ldap_get_entries($this->_ldap, $res);
-        if ($res === false) {
-            return PEAR::raiseError(sprintf(_("Error retrieving LDAP results: %s"), @ldap_error($this->_ldap)));
-        }
-
-        if ($res['count'] === 0) {
-            return PEAR::raiseError(_("Unable to acquire handle on DN.  Aborting delete operation."));
-        } else if($res['count'] !== 1) {
-            return PEAR::raiseError(_("More than one DN returned.  Aborting delete operation."));
-        }
-        // We now have one unique DN to delete.
-        $res = @ldap_delete($this->_ldap, $res[0]['dn']);
-        if ($res === false) {
-            return PEAR::raiseError(sprintf(_("Error deleting account from LDAP: %s"), @ldap_error($this->_ldap)));
-        }
-
-        return true;
-    }
-
-    /**
-     * Modifies alias data on the backend.  See Driver::saveAlias() for parameter info.
-     *
-     * @param mixed $info     The alias, or an array containing the alias and supporting data.
-     *
-     * @return mixed  True on success or PEAR error otherwise.
-     */
-    function _saveAlias($info)
-    {
-        Horde::logMessage("_saveAlias called with info: " . print_r($info, true), 'DEBUG');
-        $address = $info['address'];
-        if (!empty($info['alias'])) {
-          $alias = $info['alias'];
-          $create = false;
-        } else {
-          $create = true;
-        } // if
-        $alias_address = $info['alias_address'];
-
-        $user_res = $this->searchForUser($address);
-        if (is_a($user_res, 'PEAR_Error') || ($res['count'] === 0) ) {
-          return PEAR::raiseError(_("Error reading address information from backend."));
-        } // if
-        $user = $user_res[0];
-
-        // Retrieve the current MAA values
-        if (array_key_exists('mailalternateaddress', $user_res[0])) {
-          $maa = $user['mailalternateaddress'];
-          unset($maa['count']);
-        } else {
-          $maa = array();
-        } // if
-
-        Horde::logMessage("Resource contains: " . print_r($maa, true), 'DEBUG');
-
-        $update = false;
-        $oldmaa = $maa;
-        if ($create) {
-          // Verify that it does not already exist
-          if (in_array($alias_address, $maa) === false) {
-            // Not there, we create it
-            // return PEAR::raiseError(_("We would create a new entry here."));
-            $maa[] = $alias_address;
-            // usort($maa, "compareEmailSort");
-            sort($maa);
-            $update = true;
-          } else {
-            // Already exists, throw a notification
-            return PEAR::raiseError(_("That alias already exists!"));
-          } // if
-
-        } else {
-          if ($alias == $alias_address) {
-            /* do nothing */;
-          } else {
-            $key = array_search($alias, $maa);
-            if ($key > 0 || $key === 0) {
-              $maa[$key] = $alias_address;
-              // usort($maa, "compareEmailSort");
-              sort($maa);
-              $update = true;
-            } else {
-              return PEAR::raiseError(sprintf(_("Existing entry \"%s\" could not be found: " . print_r($key, true)), $alias));
-            } // if
-          }
-        } // if
-
-
-        if ($update) {
-          $dn = $user['dn'];
-          Horde::logMessage("UPDATING: $dn \nOld MAA: " . print_r($oldmaa, true) . "\nNew MAA: " . print_r($maa, true), 'DEBUG');
-          // return PEAR::raiseError(sprintf(_("Update Code Not Written."), $alias));
-          if ($this->_ldap) {
-            // bind with appropriate dn to give update access
-            $res = ldap_bind($this->_ldap, $this->_ldapparams['binddn'],
-                             $this->_ldapparams['bindpw']);
-            if (!$res) {
-                return PEAR::raiseError(_("Unable to bind to the LDAP server. Check authentication credentials."));
-            }
-            $entry["mailAlternateAddress"] = $maa;
-
-            $res = @ldap_modify($this->_ldap, $dn, $entry);
-            if ($res === false) {
-                return PEAR::raiseError(sprintf(_("Error modifying account: %s"), @ldap_error($this->_ldap)));
-            } else {
-                return TRUE;
-            } // if
-          } // if
-        } // if
-
-        return true;
-    }
-
-    function _deleteAlias($info)
-    {
-        Horde::logMessage("_deleteAlias called with info: " . print_r($info, true), 'DEBUG');
-        $address = $info['address'];
-        $alias = $info['alias'];
-
-        $user_res = $this->searchForUser($address);
-        if (is_a($user_res, 'PEAR_Error') || ($res['count'] === 0) ) {
-          return PEAR::raiseError(_("Error reading address information from backend."));
-        } // if
-        $user = $user_res[0];
-
-        // Retrieve the current MAA values
-        if (array_key_exists('mailalternateaddress', $user_res[0])) {
-          $maa = $user['mailalternateaddress'];
-          unset($maa['count']);
-        } else {
-          $maa = array();
-        } // if
-
-        Horde::logMessage("Resource contains: " . print_r($maa, true), 'DEBUG');
-
-        $update = false;
-        $oldmaa = $maa;
-        $key = array_search($alias, $maa);
-        if ($key > 0 || $key === 0) {
-          unset($maa[$key]);
-          sort($maa);
-          $update = true;
-        } else {
-          /* skip */;
-        } // if
-
-        if ($update) {
-          $dn = $user['dn'];
-          Horde::logMessage("UPDATING: $dn \nOld MAA: " . print_r($oldmaa, true) . "\nNew MAA: " . print_r($maa, true), 'DEBUG');
-          // return PEAR::raiseError(sprintf(_("Update Code Not Written."), $alias));
-          if ($this->_ldap) {
-            // bind with appropriate dn to give update access
-            $res = ldap_bind($this->_ldap, $this->_ldapparams['binddn'],
-                             $this->_ldapparams['bindpw']);
-            if (!$res) {
-                return PEAR::raiseError(_("Unable to bind to the LDAP server. Check authentication credentials."));
-            }
-            $entry["mailAlternateAddress"] = $maa;
-
-            $res = @ldap_modify($this->_ldap, $dn, $entry);
-            if ($res === false) {
-                return PEAR::raiseError(sprintf(_("Error modifying account: %s"), @ldap_error($this->_ldap)));
-            } else {
-                return TRUE;
-            } // if
-          } // if
-        } // if
-
-        return true;
-    }
-
-    /**
-     * Modifies forward data on the backend.  See Driver::saveForward() for parameter info.
-     *
-     * @param mixed $info     An array containing the alias and supporting data.
-     *
-     * @return mixed  True on success or PEAR error otherwise.
-     */
-    function _saveForward($info)
-    {
-      Horde::logMessage("_saveForward called with info: " . print_r($info, true), 'DEBUG');
-        $address = $info['address'];
-        if (!empty($info['forward'])) {
-          $forward = $info['forward'];
-          $create = false;
-        } else {
-          $create = true;
-        } // if
-        $forward_address = $info['forward_address'];
-
-        $user_res = $this->searchForUser($address);
-        if (is_a($user_res, 'PEAR_Error') || ($res['count'] === 0) ) {
-          return PEAR::raiseError(_("Error reading address information from backend."));
-        } // if
-        $user = $user_res[0];
-
-        // Retrieve the current MAA values
-        if (array_key_exists('mailforwardingaddress', $user_res[0])) {
-          $mfa = $user['mailforwardingaddress'];
-          unset($mfa['count']);
-        } else {
-          $mfa = array();
-        } // if
-
-        Horde::logMessage("Resource contains: " . print_r($mfa, true), 'DEBUG');
-
-        $update = false;
-        $oldmfa = $mfa;
-        if ($create) {
-          // Verify that it does not already exist
-          if (in_array($forward_address, $mfa) === false) {
-            // Not there, we create it
-            // return PEAR::raiseError(_("We would create a new entry here."));
-            $mfa[] = $forward_address;
-            // usort($mfa, "compareEmailSort");
-            sort($mfa);
-            $update = true;
-          } else {
-            // Already exists, throw a notification
-            return PEAR::raiseError(sprintf(_("That forward, \"%s\", already exists!"), $forward_address));
-          } // if
-
-        } else {
-          if ($forward == $forward_address) {
-            /* do nothing */;
-          } else {
-            $key = array_search($forward, $mfa);
-            if ($key > 0 || $key === 0) {
-              $mfa[$key] = $forward_address;
-              // usort($mfa, "compareEmailSort");
-              sort($mfa);
-              $update = true;
-            } else {
-              return PEAR::raiseError(sprintf(_("Existing entry \"%s\" could not be found: " . print_r($key, true)), $forward));
-            } // if
-          }
-        } // if
-
-
-        if ($update) {
-          $dn = $user['dn'];
-          Horde::logMessage("UPDATING: $dn \nOld MFA: " . print_r($oldmfa, true) . "\nNew MFA: " . print_r($mfa, true), 'DEBUG');
-          // return PEAR::raiseError(sprintf(_("Update Code Not Written."), $alias));
-          if ($this->_ldap) {
-            // bind with appropriate dn to give update access
-            $res = ldap_bind($this->_ldap, $this->_ldapparams['binddn'],
-                             $this->_ldapparams['bindpw']);
-            if (!$res) {
-                return PEAR::raiseError(_("Unable to bind to the LDAP server. Check authentication credentials."));
-            }
-            $entry["mailForwardingAddress"] = $mfa;
-
-            $res = @ldap_modify($this->_ldap, $dn, $entry);
-            if ($res === false) {
-                return PEAR::raiseError(sprintf(_("Error modifying account: %s"), @ldap_error($this->_ldap)));
-            } else {
-                return TRUE;
-            } // if
-          } // if
-        } // if
-
-        return true;
-    }
-
-    /**
-     * Deletes forward data on the backend.  See Driver::deleteForward() for parameter info.
-     *
-     * @param mixed $info     An array containing the forward and supporting data.
-     *
-     * @return mixed  True on success or PEAR error otherwise.
-     */
-    function _deleteForward($info)
-    {
-      Horde::logMessage("_deleteForward called with info: " . print_r($info, true), 'DEBUG');
-        $address = $info['address'];
-        $forward = $info['forward'];
-
-        $user_res = $this->searchForUser($address);
-        if (is_a($user_res, 'PEAR_Error') || ($res['count'] === 0) ) {
-          return PEAR::raiseError(_("Error reading address information from backend."));
-        } // if
-        $user = $user_res[0];
-
-        // Retrieve the current MFA values
-        if (array_key_exists('mailforwardingaddress', $user_res[0])) {
-          $mfa = $user['mailforwardingaddress'];
-          unset($mfa['count']);
-        } else {
-          $mfa = array();
-        } // if
-
-        Horde::logMessage("Resource contains: " . print_r($mfa, true), 'DEBUG');
-
-        $update = false;
-        $oldmfa = $mfa;
-        $key = array_search($forward, $mfa);
-        if ($key > 0 || $key === 0) {
-          unset($mfa[$key]);
-          sort($mfa);
-          $update = true;
-        } else {
-          /* skip */;
-        } // if
-
-        if ($update) {
-          $dn = $user['dn'];
-          Horde::logMessage("UPDATING: $dn \nOld MFA: " . print_r($oldmfa, true) . "\nNew MFA: " . print_r($mfa, true), 'DEBUG');
-          // return PEAR::raiseError(sprintf(_("Update Code Not Written."), $alias));
-          if ($this->_ldap) {
-            // bind with appropriate dn to give update access
-            $res = ldap_bind($this->_ldap, $this->_ldapparams['binddn'],
-                             $this->_ldapparams['bindpw']);
-            if (!$res) {
-                return PEAR::raiseError(_("Unable to bind to the LDAP server. Check authentication credentials."));
-            }
-            $entry["mailForwardingAddress"] = $mfa;
-
-            $res = @ldap_modify($this->_ldap, $dn, $entry);
-            if ($res === false) {
-                return PEAR::raiseError(sprintf(_("Error modifying account: %s"), @ldap_error($this->_ldap)));
-            } else {
-                return TRUE;
-            } // if
-          } // if
-        } // if
-
-        return true;
-    }
-
-    /* Sorting function to sort aliases, forwards, and accounts by domain name first,
-     * then by user component.
-     */
-    function compareEmailSort($a, $b) {
-      $a_comp = split("@", $a);
-      $b_comp = split("@", $b);
-      // not finished.
-    }
-
-    function _saveUser(&$info)
-    {
-        if ($info['mode'] == 'edit') {
-            $address = $info['address'];
-            if(!isset($address) || empty($address)) {
-                $user_name = $info['user_name'];
-                $domain = $info['domain'];
-                if(!(!isset($user_name) || empty($user_name)) && !(!isset($user_name) || empty($user_name))) {
-                    $address = $info['user_name'] . $info['domain'];
-                } else {
-                    return PEAR::raiseError(_("Unable to acquire handle on address."));
-                }
-            }
-            $addrinfo = $this->getAddressInfo($address);
-            if (is_a($addrinfo, 'PEAR_Error')) {
-                return $addrinfo;
-            }
-            $type = $addrinfo['type'];
-            if($type == 'user') {
-                 //continue, this is a user.
-            } else {
-                 //return PEAR::raiseError(_("Unable to save account of type " . $type));
-            }
-
-            $user_info = $this->searchForUser($address);
-            if (is_a($user_info, 'PEAR_Error') || ($res['count'] === 0) ) {
-                return PEAR::raiseError(_("Error reading address information from backend."));
-            }
-
-            $objectClassData = null;
-            if(isset($user_info[0]['objectclass'])) {
-                $objectClassData = $user_info[0]['objectclass'];
-            }
-
-            unset($info['mode']); // Don't want to save this to LDAP
-            // Special case for the password:  If it was provided, it needs
-            // to be crypted.  Otherwise, ignore it.
-            if (isset($info['password'])) {
-                if (!empty($user['password'])) {
-                    // FIXME: Allow choice of hash
-                    $info['user_password'] = Horde_Auth::getCryptedPassowrd($info['password'], '', 'ssha', true);
-                }
-                unset($info['password']);
-            }
-
-            $tmp['dn'] = $addrinfo['id'];
-            foreach ($info as $key => $val) {
-                $attr = $this->_getAttrByField($key);
-                $tmp[$attr] = $val;
-            }
-
-            if ($this->_ldap) {
-                // bind with appropriate dn to give update access
-                $res = ldap_bind($this->_ldap, $this->_ldapparams['binddn'],
-                                 $this->_ldapparams['bindpw']);
-                if (!$res) {
-                    return PEAR::raiseError(_("Unable to bind to the LDAP server.  Check authentication credentials."));
-                }
-
-                // prepare data
-                $entry['cn'] = $info['user_full_name'];
-                // sn is not used operationally but we make an effort to be
-                // something sensical.  No guarantees, though.
-                $entry['sn'] = array_pop(explode(' ', $info['user_full_name']));
-// The next two lines were reversed:  which is right?
-                $entry['mail'] = $info['user_name'] . $info['domain'];
-                //                 $tmp['mail'];
-                $entry['uid'] = $entry['mail'];
-                $entry['homeDirectory'] = '/srv/vhost/mail/' . $info['domain'] .'/' . $info['user_name'];
-                if(($type != 'group') && ($type != 'forward')) {
-                    $entry["qmailUID"] = 8;
-                    $entry["qmailGID"] = 8;
-                }
-                $entry["accountstatus"] = $info["user_enabled"];
-                if(isset($info['password']) && !empty($info['password'])) {
-                    // FIXME: Allow choice of hash
-                    $entry["userPassword"] = Horde_Auth::getCryptedPassword($info['password'], '', 'ssha', true);
-                }
-                if(isset($objectClassData)) {
-                    array_shift($objectClassData);
-                    $entry['objectclass'] = $objectClassData;
-                } else {
-                    $entry['objectclass'] = array();
-                    $entry['objectclass'][] = 'top';
-                    $entry['objectclass'][] = 'person';
-                    $entry['objectclass'][] = 'organizationalPerson';
-                    $entry['objectclass'][] = 'inetOrgPerson';
-                    $entry['objectclass'][] = 'hordePerson';
-                    $entry['objectclass'][] = 'qmailUser';
-                }
-
-                // Stir in any site-local custom LDAP attributes
-                $entry = Horde::callHook('_vilma_hook_getldapattrs',
-                                         array($entry), 'vilma');
-
-                $rdn = 'mail=' . $entry['mail'];
-                $dn = $rdn . ',' . $this->_ldapparams['basedn'];
-                $res = @ldap_modify($this->_ldap, $dn, $entry);
-                if ($res === false) {
-                    return PEAR::raiseError(sprintf(_("Error modifying account: %s"), @ldap_error($this->_ldap)));
-                } else {
-                    return TRUE;
-                }
-            }
-        } else if($info['mode'] == 'new') {
-            if ($this->_ldap) {
-                // bind with appropriate dn to give update access
-                $res = ldap_bind($this->_ldap, $this->_ldapparams['binddn'],
-                                 $this->_ldapparams['bindpw']);
-                if (!$res) {
-                    return PEAR::raiseError(_("Unable to bind to the LDAP server.  Check authentication credentials."));
-                }
-
-                // prepare data
-                $entry['cn'] = $info['user_full_name'];
-                // sn is not used operationally but we make an effort to be
-                // something sensical.  No guarantees, though.
-                $entry['sn'] = array_pop(explode(' ', $info['user_full_name']));
-                $entry['mail'] = $info['user_name'] . '@' . $info['domain'];
-                // uid must match mail or SMTP auth fails
-                $entry['uid'] = $entry['mail'];
-                $entry['homeDirectory'] = '/srv/vhost/mail/' . $info['domain'] .'/' . $info['user_name'];
-                $entry['qmailUID'] = 8;
-                $entry['qmailGID'] = 8;
-                $entry['objectclass'] = array();
-                $entry['objectclass'][] = 'top';
-                $entry['objectclass'][] = 'person';
-                $entry['objectclass'][] = 'organizationalPerson';
-                $entry['objectclass'][] = 'inetOrgPerson';
-                $entry['objectclass'][] = 'hordePerson';
-                $entry['objectclass'][] = 'qmailUser';
-                $entry["accountstatus"] = $info["user_enabled"];
-                // FIXME: Allow choice of hash
-                $entry["userPassword"] = Horde_Auth::getCryptedPassword($info['password'], '', 'ssha', true);
-
-                // Stir in any site-local custom LDAP attributes
-                $entry = Horde::callHook('_vilma_hook_getldapattrs',
-                                         array($entry), 'vilma');
-
-                $rdn = 'mail=' . $entry['mail'];
-                $dn = $rdn . ',' . $this->_ldapparams['basedn'];
-                $res = @ldap_add($this->_ldap, $dn, $entry);
-                if ($res === false) {
-                    return PEAR::raiseError(sprintf(_("Error adding account to LDAP: %s"), @ldap_error($this->_ldap)));
-                } else {
-                    return TRUE;
-                }
-            } else {
-                return  PEAR::raiseError(_("Unable to connect to LDAP server"));
-            }
-        }
-
-        return  PEAR::raiseError(_("Unable to save user information."));
-    }
-
-    /**
-     * Deletes a virtual email.
-     *
-     * @param integer $virtual_id  The id of the virtual email to delete.
-     */
-    function deleteVirtual($virtual_id)
-    {
-        die("deleteVirtual()");
-    }
-
-    public function getUserFormAttributes()
-    {
-        return array(array(
-            'label' => _("Account Status"),
-            'name' => 'user_enabled',
-            'type' => 'enum',
-            'required' => true,
-            'readonly' => false,
-            'description' => null,
-            'params' => array(
-                array(
-                    'active' => _("Account is active"),
-                    'noaccess' => _("Disable Delivery Only"),
-                    'disabled' => _("Bounce Incoming Only"),
-                    'deleted' => _("Account is disabled"),
-                ),
-             ),
-             'default' => 'active',
-        ));
-    }
-
-    function _connect()
-    {
-        if (!is_null($this->_ldap)) {
-            return true;
-        }
-
-        Horde::assertDriverConfig($this->_ldapparams, 'storage',
-            array('ldaphost', 'basedn', 'binddn', 'dn'));
-
-        if (!isset($this->_ldapparams['bindpw'])) {
-            $this->_ldapparams['bindpw'] = '';
-        }
-
-        $port = (isset($this->_ldapparams['port'])) ?
-            $this->_ldapparams['port'] : 389;
-
-        $this->_ldap = ldap_connect($this->_ldapparams['ldaphost'], $port);
-        if (!$this->_ldap) {
-            throw new Vilma_Exception("Unable to connect to LDAP server $hostname on $port");
-        }
-        $res = ldap_set_option($this->_ldap, LDAP_OPT_PROTOCOL_VERSION,
-                               $this->_ldapparams['version']);
-        if (!$res) {
-            return PEAR::raiseError(_("Unable to set LDAP protocol version"));
-        }
-        $res = ldap_bind($this->_ldap, $this->_ldapparams['binddn'],
-                         $this->_ldapparams['bindpw']);
-        if (!$res) {
-            return PEAR::raiseError(_("Unable to bind to the LDAP server.  Check authentication credentials."));
-        }
-
-    }
-
-    /**
-     * Initialise this backend, connect to the SQL database.
-     *
-     * @return mixed  True on success or PEAR error otherwise.
-     */
-    function _dbinit()
-    {
-        global $registry;
-
-        try {
-            $this->_db = $GLOBALS['injector']->getInstance('Horde_Core_Factory_DbPear')->create('rw', 'vilma', 'storage');
-        } catch (Horde_Exception $e) {
-            return PEAR::raiseError($e->getMessage());
-        }
-    }
-}
diff --git a/vilma/lib/Driver/sql.php b/vilma/lib/Driver/sql.php
deleted file mode 100644 (file)
index 2aafc8b..0000000
+++ /dev/null
@@ -1,635 +0,0 @@
-<?php
-/**
- * Copyright 2003-2010 The Horde Project (http://www.horde.org/)
- *
- * See the enclosed file LICENSE for license information (BSD). If you did
- * did not receive this file, see http://cvs.horde.org/co.php/vilma/LICENSE.
- *
- * @author Marko Djukic <marko@oblo.com>
- * @package Vilma
- */
-class Vilma_Driver_sql extends Vilma_Driver {
-
-    /**
-     * @var DB
-     */
-    var $_db;
-
-    function Vilma_Driver_sql($params)
-    {
-        parent::Vilma_Driver($params);
-        $this->initialise();
-    }
-
-    /**
-     * Construct an SQL WHERE fragment to filter domains by domain key.
-     *
-     * @access private
-     *
-     * @param string $join  Keyword to join expression to rest of SQL statement
-     *                      (e.g. 'WHERE' or 'AND'). Default: 'WHERE'.
-     *
-     * @return array  An SQL fragment and a list of values suitable for
-     *                binding.
-     */
-    function _getDomainKeyFilter($join = 'WHERE')
-    {
-        if (empty($this->_params['tables']['domainkey'])) {
-            return array('', array());
-        }
-
-        return array(' ' . $join . ' domain_key = ?',
-                     array($this->_params['tables']['domainkey']));
-    }
-
-    /**
-     * Construct an SQL WHERE fragment to filter users by domain key.
-     *
-     * @access private
-     *
-     * @param string $join  Keyword to join expression to rest of SQL statement
-     *                      (e.g. 'WHERE' or 'AND'). Default: 'WHERE'.
-     *
-     * @return array  An SQL fragment and a list of values suitable for
-     *                binding.
-     */
-    function _getUserKeyFilter($join = 'WHERE')
-    {
-        if (empty($this->_params['tables']['domainkey'])) {
-            return array('', array());
-        }
-        $binds = $this->_getDomainKeyFilter('AND');
-
-        return array(' ' . $join . ' EXISTS (SELECT domain_name' .
-                     ' FROM ' . $this->_params['tables']['domains'] .
-                     ' WHERE ' . $this->_getTableField('users', 'user_name') .
-                     ' LIKE ? || ' . $this->_getTableField('domains', 'domain_name') .
-                     ' ' . $binds[0] . ' )',
-                     array_unshift($binds[1], '%@'));
-    }
-
-    /**
-     * Construct an SQL WHERE fragment to filter virtuals by domain key.
-     *
-     * @access private
-     *
-     * @param string $join  Keyword to join expression to rest of SQL statement
-     *                      (e.g. 'WHERE' or 'AND').  Default: 'WHERE'.
-     *
-     * @return string  An SQL fragment.
-     */
-    function _getVirtualKeyFilter($join = 'WHERE')
-    {
-        if (empty($this->_params['tables']['domainkey'])) {
-            return array('', array());
-        }
-        $binds = $this->_getDomainKeyFilter('AND');
-
-        return array(' ' . $join . ' EXISTS (SELECT domain_name' .
-                     ' FROM ' . $this->_params['tables']['domains'] .
-                     ' WHERE ' . $this->_getTableField('virtuals', 'virtual_email') .
-                     ' LIKE ? || ' . $this->_getTableField('domains', 'domain_name') .
-                     ' ' . $binds[0] . ' )',
-                     array_unshift($binds[1], '%@'));
-    }
-
-    /**
-     * Gets the list of fields from specific table for sql statement.
-     *
-     * @return string
-     */
-    function _getTableFields($table)
-    {
-        if (empty($this->_params['tables'][$table . '_fields'])){
-            return '*';
-        }
-
-        $domainsFields = $this->_params['tables'][$table . '_fields'];
-        foreach ($domainsFields as $defaultName => $customName) {
-            $fields[] = $customName . ' as ' . $defaultName;
-        }
-        return implode(', ', $fields);
-    }
-
-    /**
-     * Gets the real name of the field from specific table for sql statement.
-     *
-     * @return string
-     */
-    function _getTableField($table, $field)
-    {
-        if (empty($this->_params['tables'][$table . '_fields'])) {
-            return $field;
-        } else {
-            return $this->_params['tables'][$table . '_fields'][$field];
-        }
-    }
-
-    /**
-     *
-     *
-     * @return array
-     */
-    function _prepareRecord($table, $record)
-    {
-        if (empty($this->_params['tables'][$table . '_fields'])){
-            return $record;
-        }
-
-        $domainsFields = $this->_params['tables'][$table . '_fields'];
-        $newRecord = array();
-        foreach ($record as $defaultName => $value) {
-            $newRecord[$domainsFields[$defaultName]] = $record[$defaultName];
-        }
-        return $newRecord;
-    }
-
-    /**
-     * Gets the list of domains from the backend.
-     *
-     * @return array  All the domains and their data in an array.
-     */
-    function getDomains()
-    {
-        $binds = $this->_getDomainKeyFilter();
-        $sql = 'SELECT '. $this->_getTableFields('domains') . ' FROM ' . $this->_params['tables']['domains'] .
-               $binds[0] . ' ORDER BY domain_name';
-        $values = $binds[1];
-
-        Horde::logMessage($sql, 'DEBUG');
-        return $this->_db->getAll($sql, $values, DB_FETCHMODE_ASSOC);
-    }
-
-    /**
-     * Gets the specified domain information from the backend.
-     *
-     * @param integer $domain_id  The id of the domain to fetch.
-     *
-     * @return array  The domain's information in an array.
-     */
-    function getDomain($domain_id)
-    {
-        $binds = $this->_getDomainKeyFilter('AND');
-        $sql = 'SELECT '. $this->_getTableFields('domains') . ' FROM ' . $this->_params['tables']['domains'] .
-               ' WHERE ' . $this->_getTableField('domains', 'domain_id') . ' = ?' . $binds[0];
-        array_unshift($binds[1], (int)$domain_id);
-
-        Horde::logMessage($sql, 'DEBUG');
-        return $this->_db->getRow($sql, $binds[1], DB_FETCHMODE_ASSOC);
-    }
-
-    /**
-     * Given a domain name returns the information from the backend.
-     *
-     * @param string $name  The name of the domain to fetch.
-     *
-     * @return array  The domain's information in an array.
-     */
-    function getDomainByName($domain_name)
-    {
-        $binds = $this->_getDomainKeyFilter('AND');
-        $sql = 'SELECT '. $this->_getTableFields('domains') . ' FROM ' . $this->_params['tables']['domains'] .
-               ' WHERE ' . $this->_getTableField('domains', 'domain_name') . ' = ?' . $binds[0];
-        array_unshift($binds[1], $domain_name);
-
-        Horde::logMessage($sql, 'DEBUG');
-        return $this->_db->getRow($sql, $binds[1], DB_FETCHMODE_ASSOC);
-    }
-
-    /**
-     * Returns a list of all users, aliases, or groups and forwards for a
-     * domain.
-     *
-     * @param string $domain      Domain on which to search.
-     * @param string $type        Only return a specific type. One of 'all',
-     *                            'user', 'alias','forward', or 'group'.
-     * @param string $key         Sort list by this key.
-     * @param integer $direction  Sort direction.
-     *
-     * @return array Account information for this domain
-     */
-    protected function _getAddresses($domain, $type = 'all')
-    {
-        $addresses = array();
-        if ($type == 'all' || $type == 'user') {
-            $addresses += $this->getUsers($domain);
-        }
-        if ($type == 'all' || $type == 'alias') {
-            $addresses += $this->getVirtuals($domain);
-        }
-        return $addresses;
-    }
-
-    /**
-     * Returns all available users, if a domain name is passed then limit the
-     * list of users only to those users.
-     *
-     * @param string $domain  The name of the domain for which to fetch the
-     *                        users.
-     *
-     * @return array  The available users and their stored information.
-     */
-    function getUsers($domain = null)
-    {
-        /* Put together the SQL statement. */
-        if (is_null($domain)) {
-            /* Fetch all users. */
-            $binds = $this->_getUserKeyFilter();
-            $sql = 'SELECT '. $this->_getTableFields('users') . ' FROM ' . $this->_params['tables']['users'] .
-                   $binds[0];
-            $values = $binds[1];
-        } else {
-            /* Fetch only users for a domain. */
-            $binds = $this->_getUserKeyFilter('AND');
-            $sql = 'SELECT '. $this->_getTableFields('users') . ' FROM ' . $this->_params['tables']['users'] .
-                   ' WHERE ' . $this->_getTableField('users', 'user_name') . ' LIKE ?' . $binds[0] .
-                   ' ORDER BY user_name';
-            array_unshift($binds[1], '%@' . $domain);
-            $values = $binds[1];
-        }
-
-        Horde::logMessage($sql, 'DEBUG');
-        return $this->_db->getAll($sql, $values, DB_FETCHMODE_ASSOC);
-    }
-
-    /**
-     * Returns the user information for a given user id.
-     *
-     * @param integer $user_id  The id of the user for which to fetch
-     *                          information.
-     *
-     * @return array  The user information.
-     */
-    function getUser($user_id)
-    {
-        $binds = $this->_getUserKeyFilter('AND');
-        $sql = 'SELECT '. $this->_getTableFields('users') . ' FROM ' . $this->_params['tables']['users'] .
-               ' WHERE ' . $this->_getTableField('users', 'user_id') . ' = ?' . $binds[0];
-        array_unshift($binds[1], (int)$user_id);
-
-        Horde::logMessage($sql, 'DEBUG');
-        return $this->_db->getRow($sql, $binds[1], DB_FETCHMODE_ASSOC);
-    }
-
-    /**
-     * Returns available virtual emails.
-     *
-     * @param string $filter  If passed a domain then return all virtual emails
-     *                        for the domain, otherwise if passed a user name
-     *                        return all virtual emails for that user.
-     *
-     * @return array  The available virtual emails.
-     */
-    function getVirtuals($filter)
-    {
-        /* Check if filtering only for domain. */
-        if (($pos = strpos($filter, '@')) === false) {
-            $where = $this->_getTableField('virtuals', 'virtual_email') . ' LIKE ?';
-            $values = array('%@' . $filter);
-        } else {
-            $where = $this->_getTableField('virtuals', 'virtual_destination') . ' = ?';
-            $values = array($filter);
-        }
-
-        $binds = $this->_getVirtualKeyFilter('AND');
-        $sql = 'SELECT '. $this->_getTableFields('virtuals') . ' FROM ' . $this->_params['tables']['virtuals'] .
-               ' WHERE ' . $where . $binds[0] .
-               ' ORDER BY virtual_destination, virtual_email';
-        $values = array_merge($values, $binds[1]);
-
-        Horde::logMessage($sql, 'DEBUG');
-        return $this->_db->getAll($sql, $values, DB_FETCHMODE_ASSOC);
-    }
-
-    /**
-     * Returns information for a virtual id.
-     *
-     * @param integer $virtual_id  The virtual id for which to return
-     *                             information.
-     *
-     * @return array  The virtual email information.
-     */
-    function getVirtual($virtual_id)
-    {
-        $binds = $this->_getVirtualKeyFilter('AND');
-        $sql = 'SELECT '. $this->_getTableFields('virtuals') . ' FROM ' . $this->_params['tables']['virtuals'] .
-               ' WHERE ' . $this->_getTableField('virtuals', 'virtual_id') . ' = ?' . $binds[0];
-        array_unshift($binds[1], (int)$virtual_id);
-
-        Horde::logMessage($sql, 'DEBUG');
-        $virtual = $this->_db->getRow($sql, $binds[1], DB_FETCHMODE_ASSOC);
-        $virtual['stripped_email'] = Vilma::stripUser($virtual['virtual_email']);
-
-        return $virtual;
-    }
-
-    /**
-     * Returns the current number of set up users for a domain.
-     *
-     * @param string $domain_name  The name of the domain for which to
-     *                             get the current number of users.
-     *
-     * @return integer  The current number of users.
-     */
-    function getDomainNumUsers($domain_name)
-    {
-        $binds = $this->_getUserKeyFilter('AND');
-        $sql = 'SELECT count(' . $this->_getTableField('users', 'user_name') . ')' .
-               ' FROM ' . $this->_params['tables']['users'] .
-               ' WHERE ' . $this->_getTableField('users', 'user_name') . ' LIKE ?' . $binds[0];
-        array_unshift($binds[1], '%@' . $domain_name);
-
-        Horde::logMessage($sql, 'DEBUG');
-        return $this->_db->getOne($sql, $binds[1]);
-    }
-
-    /**
-     * Saves a domain to the backend.
-     *
-     * @param array $info  The domain information to save to the backend.
-     *
-     * @return mixed  True on success or PEAR error otherwise.
-     */
-    function _saveDomain($info)
-    {
-        require_once 'Horde/SQL.php';
-
-        $record = array('domain_name' => $info['name'],
-                        'domain_transport' => $info['transport'],
-                        'domain_max_users' => (int)$info['max_users'],
-                        'domain_quota' => (int)$info['quota']);
-
-        if (empty($info['domain_id'])) {
-            $record['domain_id'] = $this->_db->nextId($this->_params['tables']['domains']);
-            if (!empty($this->_params['tables']['domainkey'])) {
-                $record['domain_key'] = $this->_params['tables']['domainkey'];
-            }
-
-            $sql = 'INSERT INTO ' . $this->_params['tables']['domains'] .
-                ' ' . Horde_SQL::insertValues($this->_db, $this->_prepareRecord('domains', $record));
-            $values = array();
-        } else {
-            $binds = $this->_getDomainKeyFilter('AND');
-            $sql = 'UPDATE ' . $this->_params['tables']['domains'] .
-                   ' SET ' . Horde_SQL::updateValues($this->_db, $this->_prepareRecord('domains', $record)) .
-                   ' WHERE ' . $this->_getTableField('domains', 'domain_id') . ' = ?' . $binds[0];
-            array_unshift($binds[1], $info['domain_id']);
-            $values = $binds[1];
-        }
-
-        Horde::logMessage($sql, 'DEBUG');
-        return $this->_db->query($sql, $values);
-    }
-
-    /**
-     * Deletes a given domain.
-     *
-     * @param integer $domain_id  The id of the domain to delete.
-     *
-     * @return mixed  True on success or PEAR error otherwise.
-     */
-    function _deleteDomain($domain_id)
-    {
-        $domain_record = $this->getDomain($domain_id);
-        if (is_a($domain_record, 'PEAR_Error')) {
-            return $domain_record;
-        }
-
-        $domain_name = $domain_record['domain_name'];
-
-        /* Delete all virtual emails for this domain. */
-        $sql = 'DELETE FROM ' . $this->_params['tables']['virtuals'] .
-               ' WHERE ' . $this->_getTableField('virtuals', 'virtual_email') . ' LIKE ?';
-        $values = array('%@' . $domain_name);
-        $delete = $this->_db->query($sql, $values);
-        if (is_a($delete, 'PEAR_Error')) {
-            return $delete;
-        }
-
-        /* Delete all users for this domain. */
-        $sql = 'DELETE FROM ' . $this->_params['tables']['users'] .
-               ' WHERE ' . $this->_getTableField('users', 'user_name') . ' LIKE ?';
-        $values = array('%@' . $domain_name);
-        $delete = $this->_db->query($sql, $values);
-        if (is_a($delete, 'PEAR_Error')) {
-            return $delete;
-        }
-
-        /* Finally delete the domain. */
-        $sql = 'DELETE FROM ' . $this->_params['tables']['domains'] .
-               ' WHERE ' . $this->_getTableField('domains', 'domain_id') . ' = ?';
-        $values = array((int)$domain_id);
-
-        Horde::logMessage($sql, 'DEBUG');
-        return $this->_db->query($sql, $values);
-    }
-
-    /**
-     * Saves a user to the backend.
-     *
-     * @param array $info  The user information to save.
-     *
-     * @return array  The user information.
-     */
-    function _saveUser($info)
-    {
-        global $conf;
-
-        require_once 'Horde/SQL.php';
-
-        /* Access check (for domainkey). */
-        $res = $this->getDomainByName(Vilma::stripDomain($info['user_name']));
-        if (is_a($res, 'PEAR_Error')) {
-            return $res;
-        }
-
-        $mailboxes = &Vilma::getMailboxDriver();
-        if (is_a($mailboxes, 'PEAR_Error')) {
-            return $mailboxes;
-        }
-
-        if (empty($info['user_id'])) {
-            $info['user_id'] = $this->_db->nextId($this->_params['tables']['users']);
-            $create = true;
-        } else {
-            $create = false;
-        }
-
-        // Slightly hackish.
-        $mail_dir_base = isset($mailboxes->_params['mail_dir_base']) ?
-                         $mailboxes->_params['mail_dir_base'] : '?';
-
-        $tuple = array('user_id' =>         (int)$info['user_id'],
-                       'user_name' =>       $info['user_name'],
-                       'user_full_name' =>  $info['user_full_name'],
-                       'user_home_dir' =>   $mail_dir_base,
-                       'user_mail_dir' =>   Vilma::stripDomain($info['user_name']) . '/' . Vilma::stripUser($info['user_name']) . '/',
-                       'user_mail_quota' => $this->getDomainQuota(Vilma::stripDomain($info['user_name'])) * 1024 * 1024,
-                       'user_enabled' =>    (int)$info['user_enabled']);
-
-        // UID and GID are slightly hackish (specific to maildrop driver), too
-        if (!isset($mailboxes->_params['uid'])) {
-            $tuple['user_uid'] = -1;
-        } else {
-            $tuple['user_uid'] = $mailboxes->_params['uid'];
-        }
-        if (!isset($mailboxes->_params['gid'])) {
-            $tuple['user_gid'] = -1;
-        } else {
-            $tuple['user_gid'] = $mailboxes->_params['gid'];
-        }
-
-        if (!empty($info['password'])) {
-            $tuple['user_clear'] = $info['password'];
-            $tuple['user_crypt'] = crypt($info['password'],
-                                         substr($info['password'], 0, 2));
-        } elseif ($create) {
-            return PEAR::raiseError(_("Password must be supplied when creating a new user."));
-        }
-
-        if ($create) {
-            $sql = 'INSERT INTO ' .
-                $this->_params['tables']['users'] . ' ' .
-                Horde_SQL::insertValues($this->_db, $this->_prepareRecord('users', $tuple));
-        } else {
-            $sql = sprintf('UPDATE %s SET %s WHERE ' . $this->_getTableField('users', 'user_id') . ' = %d',
-                           $this->_params['tables']['users'],
-                           Horde_SQL::updateValues($this->_db, $this->_prepareRecord('users', $tuple)),
-                           (int)$info['user_id']);
-        }
-
-        Horde::logMessage($sql, 'DEBUG');
-        $result = $this->_db->query($sql);
-        if (is_a($result, 'PEAR_Error')) {
-            Horde::logMessage($result, 'ERR');
-            return $result;
-        }
-
-        return $info;
-    }
-
-    /**
-     * Deletes a requested user.
-     *
-     * @param integer $user_id  The id of the user to delete.
-     *
-     * @return mixed  True, or PEAR_Error on failure.
-     */
-    function _deleteUser($user_id)
-    {
-        $user = $this->getUser($user_id);
-        if (is_a($user, 'PEAR_Error')) {
-            return $user;
-        }
-
-        /* Delete all virtual emails for this user. */
-        $sql = 'DELETE FROM ' . $this->_params['tables']['virtuals'] .
-               ' WHERE ' . $this->_getTableField('virtuals', 'virtual_destination') . ' = ?';
-        $values = array($user['user_name']);
-
-        Horde::logMessage($sql, 'DEBUG');
-        $delete = $this->_db->query($sql, $values);
-        if (is_a($delete, 'PEAR_Error')) {
-            return $delete;
-        }
-
-        /* Delete the actual user. */
-        $sql = 'DELETE FROM ' . $this->_params['tables']['users'] .
-               ' WHERE ' . $this->_getTableField('users', 'user_id') . ' = ?';
-        $values = array((int)$user_id);
-
-        Horde::logMessage($sql, 'DEBUG');
-        $result = $this->_db->query($sql, $values);
-        if (is_a($result, 'PEAR_Error')) {
-            return $result;
-        }
-
-        $mailboxes = &Vilma::getMailboxDriver();
-        if (is_a($mailboxes, 'PEAR_Error')) {
-            return $mailboxes;
-        }
-
-        return $mailboxes->deleteMailbox(Vilma::stripUser($user['user_name']),
-                                         Vilma::stripDomain($user['user_name']));
-    }
-
-    /**
-     * Saves virtual email address to the backend.
-     *
-     * @param array $info     The virtual email data.
-     * @param string $domain  The name of the domain for this virtual email.
-     *
-     * @return mixed  True on success or PEAR error otherwise.
-     */
-    function saveVirtual(&$info, $domain)
-    {
-        /* Access check (for domainkey) */
-        $res = $this->getDomainByName($domain);
-        if (is_a($res, 'PEAR_Error')) {
-            return $res;
-        }
-
-        if (empty($info['virtual_id'])) {
-            $info['virtual_id'] = $this->_db->nextId($this->_params['tables']['virtuals']);
-            $sql = 'INSERT INTO ' . $this->_params['tables']['virtuals'] .
-                ' (' . $this->_getTableField('virtuals', 'virtual_email') . ', ' .
-                       $this->_getTableField('virtuals', 'virtual_destination') . ', ' .
-                       $this->_getTableField('virtuals', 'virtual_id') . ') VALUES (?, ?, ?)';
-        } else {
-            $sql = 'UPDATE ' . $this->_params['tables']['virtuals'] .
-                ' SET ' . $this->_getTableField('virtuals', 'virtual_email') . ' = ?, '.
-                          $this->_getTableField('virtuals', 'virtual_destination') . ' = ?' .
-                ' WHERE ' . $this->_getTableField('virtuals', 'virtual_id') . ' = ?';
-        }
-        $values = array($info['stripped_email'] . '@' . $domain,
-                        $info['virtual_destination'],
-                        $info['virtual_id']);
-
-        Horde::logMessage($sql, 'DEBUG');
-        return $this->_db->query($sql, $values);
-    }
-
-    /**
-     * Deletes a virtual email.
-     *
-     * @param integer $virtual_id  The id of the virtual email to delete.
-     */
-    function deleteVirtual($virtual_id)
-    {
-        $binds = $this->_getVirtualKeyFilter('AND');
-        $sql = 'DELETE FROM ' . $this->_params['tables']['virtuals'] .
-               ' WHERE ' . $this->_getTableField('virtuals', 'virtual_id') . ' = ?' . $binds[0];
-        array_unshift($binds[1], $virtual_id);
-
-        Horde::logMessage($sql, 'DEBUG');
-        return $this->_db->query($sql, $binds[1]);
-    }
-
-    /**
-     * Initialise this backend, connect to the SQL database.
-     *
-     * @return mixed  True on success or PEAR error otherwise.
-     */
-    function initialise()
-    {
-        try {
-            $this->_db = $GLOBALS['injector']->getInstance('Horde_Core_Factory_DbPear')->create('rw', 'vilma', 'storage');
-        } catch (Horde_Exception $e) {
-            return PEAR::raiseError($e->getMessage());
-        }
-
-        /* Use default table names if these are not set. */
-        if (!isset($this->_params['tables']['domains'])) {
-            $this->_params['tables']['domains'] = 'vilma_domains';
-        }
-        if (!isset($this->_params['tables']['users'])) {
-            $this->_params['tables']['users'] = 'vilma_users';
-        }
-        if (!isset($this->_params['tables']['virtuals'])) {
-            $this->_params['tables']['virtuals'] = 'vilma_virtuals';
-        }
-
-        return true;
-    }
-
-}
diff --git a/vilma/lib/Form/DeleteDomain.php b/vilma/lib/Form/DeleteDomain.php
new file mode 100644 (file)
index 0000000..0532b6c
--- /dev/null
@@ -0,0 +1,25 @@
+<?php
+/**
+ * Copyright 2006-2007 Alkaloid Networks <http://www.alkaloid.net>
+ *
+ * See the enclosed file LICENSE for license information (BSD). If you did
+ * did not receive this file, see http://cvs.horde.org/co.php/vilma/LICENSE.
+ *
+ * @author  Ben Klang <ben@alkaloid.net>
+ * @package Vilma
+ */
+class Vilma_Form_DeleteDomain extends Horde_Form
+{
+    public function __construct($vars)
+    {
+        parent::Horde_Form($vars, _("Delete Domain"));
+
+        $domain_record = $GLOBALS['vilma']->driver->getDomain($vars->get('domain_id'));
+        $domain = $domain_record['domain_name'];
+
+        /* Set up the form. */
+        $this->setButtons(array(_("Delete"), _("Do not delete")));
+        $this->addHidden('', 'domain_id', 'text', false);
+        $this->addVariable(sprintf(_("Delete domain \"%s\" and all associated email addresses?"), $domain), 'description', 'description', false);
+    }
+}
diff --git a/vilma/lib/Form/EditAlias.php b/vilma/lib/Form/EditAlias.php
new file mode 100644 (file)
index 0000000..9d8db86
--- /dev/null
@@ -0,0 +1,36 @@
+<?php
+/**
+ * Copyright 2006-2007 Alkaloid Networks <http://www.alkaloid.net>
+ *
+ * See the enclosed file LICENSE for license information (BSD). If you did
+ * did not receive this file, see http://cvs.horde.org/co.php/vilma/LICENSE.
+ *
+ * @author  Ben Klang <ben@alkaloid.net>
+ * @package Vilma
+ */
+class Vilma_Form_EditAlias extends Horde_Form
+{
+    public function __construct($vars)
+    {
+        $editing = $vars->get('mode') == 'edit';
+        if ($editing) {
+            $title = sprintf(_("Edit Alias \"%s\" for \"%s\""),
+                             $vars->get('alias_address'),
+                             $vars->get('address'));
+        } else {
+            $title = sprintf(_("New Alias for %s"),
+                             $vars->get('address'));
+        }
+        parent::Horde_Form($vars, $title);
+
+        /* Set up the form. */
+        $this->setButtons(true, true);
+        $this->addHidden('', 'address', 'text', false);
+        $this->addHidden('', 'mode', 'text', false);
+        $this->addHidden('', 'id', 'text', false);
+        if ($editing) {
+            $this->addHidden('', 'alias', 'text', false);
+        }
+        $this->addVariable(_("Alias Address"), 'alias_address', 'email', true, false, _("The email address to add as an alias for this user.  Note that the server must be configured to receive mail for the domain contained in this address."));
+    }
+}
diff --git a/vilma/lib/Form/EditDomain.php b/vilma/lib/Form/EditDomain.php
new file mode 100644 (file)
index 0000000..bf88fae
--- /dev/null
@@ -0,0 +1,36 @@
+<?php
+/**
+ * Copyright 2006-2007 Alkaloid Networks <http://www.alkaloid.net>
+ *
+ * See the enclosed file LICENSE for license information (BSD). If you did
+ * did not receive this file, see http://cvs.horde.org/co.php/vilma/LICENSE.
+ *
+ * @author  Ben Klang <ben@alkaloid.net>
+ * @package Vilma
+ */
+class Vilma_Form_EditDomain extends Horde_Form
+{
+    public function __construct($vars)
+    {
+        /* Check if a form is being edited. */
+        $editing = $vars->exists('domain_id');
+        $domain = $GLOBALS['session']->get('vilma', 'domain');
+        parent::Horde_Form($vars, $editing ? _("Edit Domain") : _("New Domain"));
+        if ($editing && !$this->isSubmitted()) {
+            $domain = $GLOBALS['vilma']->driver->getDomain($vars->get('domain_id'));
+            $vars = new Horde_Variables($domain);
+        }
+        $vars->add('name', $domain['domain_name']);
+        $vars->add('transport', $domain['domain_transport']);
+        $vars->add('max_users', $domain['domain_max_users']);
+        $vars->add('quota', $domain['domain_quota']);
+
+        /* Set up the form. */
+        $this->setButtons(true, true);
+        $this->addHidden('', 'domain_id', 'text', false);
+        $this->addVariable(_("Domain"), 'name', 'text', true);
+        $this->addVariable(_("Transport"), 'transport', 'enum', false, false, null, array(Horde_Array::valuesToKeys($GLOBALS['conf']['mta']['transports'])));
+        $this->addVariable(_("Max users"), 'max_users', 'int', false);
+        $this->addVariable(_("Quota"), 'quota', 'int', false, false, _("Value in MB"));
+    }
+}
diff --git a/vilma/lib/Form/EditForward.php b/vilma/lib/Form/EditForward.php
new file mode 100644 (file)
index 0000000..53ff7bb
--- /dev/null
@@ -0,0 +1,36 @@
+<?php
+/**
+ * Copyright 2006-2007 Alkaloid Networks <http://www.alkaloid.net>
+ *
+ * See the enclosed file LICENSE for license information (BSD). If you did
+ * did not receive this file, see http://cvs.horde.org/co.php/vilma/LICENSE.
+ *
+ * @author  Daniel Collins <horde_dev@argentproductions.com>
+ * @package Vilma
+ */
+class Vilma_Form_EditForward extends Horde_Form
+{
+    public function __construct($vars)
+    {
+        $editing = $vars->get('mode') == 'edit';
+        if ($editing) {
+            $title = sprintf(_("Edit Forward \"%s\" for \"%s\""),
+                             $vars->get('forward_address'),
+                             $vars->get('address'));
+        } else {
+            $title = sprintf(_("New Forward for %s"),
+                             $vars->get('address'));
+        }
+        parent::Horde_Form($vars, $title);
+
+        /* Set up the form. */
+        $this->setButtons(true, true);
+        $this->addHidden('', 'address', 'text', false);
+        $this->addHidden('', 'mode', 'text', false);
+        $this->addHidden('', 'id', 'text', false);
+        if ($editing) {
+            $this->addHidden('', 'forward', 'text', false);
+        }
+        $this->addVariable(_("Forward Address"), 'forward_address', 'email', true, false, _("The email address to add as an forward for this user.  Note that the server must be configured to receive mail for the domain contained in this address."));
+    }
+}
diff --git a/vilma/lib/Form/EditUser.php b/vilma/lib/Form/EditUser.php
new file mode 100644 (file)
index 0000000..71b37be
--- /dev/null
@@ -0,0 +1,63 @@
+<?php
+/**
+ * Copyright 2006-2007 Alkaloid Networks <http://www.alkaloid.net>
+ *
+ * See the enclosed file LICENSE for license information (BSD). If you did
+ * did not receive this file, see http://cvs.horde.org/co.php/vilma/LICENSE.
+ *
+ * @author  Ben Klang <ben@alkaloid.net>
+ * @package Vilma
+ */
+class Vilma_Form_EditUser extends Horde_Form
+{
+    public function __construct($vars)
+    {
+        $type = $vars->get('type');
+        $editing = $vars->get('mode') == 'edit';
+        switch ($type) {
+        case 'group':
+            $title = sprintf(_("Edit Group for \"%s\""), $vars->get('domain'));
+            $name = _("Group Name");
+            break;
+        case 'forward':
+            $title = sprintf(_("Edit Forward for \"%s\""), $vars->get('domain'));
+            $name = _("Forward Name");
+            break;
+        default:
+            $title = sprintf(_("Edit User for \"%s\""), $vars->get('domain'));
+            $name = _("User Name");
+            break;
+        }
+        if (!$editing) {
+            $title = sprintf(_("New User @%s"), $vars->get('domain'));
+        }
+        parent::Horde_Form($vars, $title);
+
+        /* Set up the form. */
+        $this->setButtons(true, true);
+        $this->addHidden('', 'address', 'text', false);
+        $this->addHidden('', 'mode', 'text', false);
+        $this->addHidden('', 'domain', 'text', false);
+        $this->addHidden('', 'id', 'text', false);
+        if ($editing) {
+            $this->addHidden('', 'user_name', 'text', false);
+        }
+        $this->addVariable($name, 'user_name', 'text', true, $editing, _("Name must begin with an alphanumeric character, must contain only alphanumeric and '._-' characters, and must end with an alphanumeric character."), array('~^[a-zA-Z0-9]{1,1}[a-zA-Z0-9._-]*[a-zA-Z0-9]$~'));
+        if ($editing) {
+            $this->addVariable(_("Password"), 'password', 'passwordconfirm', false, false, _("Only enter a password if you wish to change this user's password"));
+        } else {
+            $this->addVariable(_("Password"), 'password', 'passwordconfirm', true);
+        }
+        $this->addVariable(_("Full Name"), 'user_full_name', 'text', true);
+        $attrs = $GLOBALS['vilma']->driver->getUserFormAttributes();
+        foreach ($attrs as $attr) {
+            $v = $this->addVariable($attr['label'], $attr['name'],
+                                    $attr['type'], $attr['required'],
+                                    $attr['readonly'], $attr['description'],
+                                    $attr['params']);
+            if (isset($attr['default'])) {
+                $v->setDefault($attr['default']);
+            }
+        }
+    }
+}
diff --git a/vilma/lib/Forms/DeleteDomainForm.php b/vilma/lib/Forms/DeleteDomainForm.php
deleted file mode 100644 (file)
index ff50da7..0000000
+++ /dev/null
@@ -1,29 +0,0 @@
-<?php
-/**
- * Copyright 2006-2007 Alkaloid Networks <http://www.alkaloid.net>
- *
- * See the enclosed file LICENSE for license information (BSD). If you did
- * did not receive this file, see http://cvs.horde.org/co.php/vilma/LICENSE.
- *
- * @author  Ben Klang <ben@alkaloid.net>
- * @package Vilma
- */
-class DeleteDomainForm extends Horde_Form {
-
-    function DeleteDomainForm(&$vars)
-    {
-        parent::Horde_Form($vars, _("Delete Domain"));
-
-        $domain_record = $GLOBALS['vilma']->driver->getDomain($vars->get('domain_id'));
-        if (is_a($domain_record, 'PEAR_Error')) {
-            return $domain_record;
-        }
-
-        $domain = $domain_record['domain_name'];
-
-        /* Set up the form. */
-        $this->setButtons(array(_("Delete"), _("Do not delete")));
-        $this->addHidden('', 'domain_id', 'text', false);
-        $this->addVariable(sprintf(_("Delete domain \"%s\" and all associated email addresses?"), $domain), 'description', 'description', false);
-    }
-}
diff --git a/vilma/lib/Forms/EditAliasForm.php b/vilma/lib/Forms/EditAliasForm.php
deleted file mode 100644 (file)
index f3e1ddf..0000000
+++ /dev/null
@@ -1,38 +0,0 @@
-<?php
-/**
- * Copyright 2006-2007 Alkaloid Networks <http://www.alkaloid.net>
- *
- * See the enclosed file LICENSE for license information (BSD). If you did
- * did not receive this file, see http://cvs.horde.org/co.php/vilma/LICENSE.
- *
- * @author  Ben Klang <ben@alkaloid.net>
- * @package Vilma
- */
-
-class EditAliasForm extends Horde_Form {
-
-    function EditAliasForm(&$vars)
-    {
-        $type = $vars->get('type');
-        $editing = ($vars->get('mode') == 'edit');
-        if ($editing) {
-            $title = sprintf(_("Edit Alias \"%s\" for \"%s\""), $vars->get('alias_address'), $vars->get('address'));
-        } else {
-            $title = sprintf(_("New Alias for %s"), $vars->get('address'));
-        }
-        parent::Horde_Form($vars, $title);
-
-        /* Set up the form. */
-        $this->setButtons(true, true);
-        $this->addHidden('', 'address', 'text', false);
-        $this->addHidden('', 'mode', 'text', false);
-        $this->addHidden('', 'id', 'text', false);
-        if ($editing) {
-            $this->addHidden('', 'alias', 'text', false);
-        }
-        $name = "Alias Address";
-        $type = $vars->get('type');
-        $this->addVariable(_($name), 'alias_address', 'email', true, false, _("The email address to add as an alias for this user.  Note that the server must be configured to receive mail for the domain contained in this address."));
-    }
-
-}
diff --git a/vilma/lib/Forms/EditDomainForm.php b/vilma/lib/Forms/EditDomainForm.php
deleted file mode 100644 (file)
index 550ba2a..0000000
+++ /dev/null
@@ -1,41 +0,0 @@
-<?php
-/**
- * Copyright 2006-2007 Alkaloid Networks <http://www.alkaloid.net>
- *
- * See the enclosed file LICENSE for license information (BSD). If you did
- * did not receive this file, see http://cvs.horde.org/co.php/vilma/LICENSE.
- *
- * @author  Ben Klang <ben@alkaloid.net>
- * @package Vilma
- */
-
-class EditDomainForm extends Horde_Form {
-
-    function EditDomainForm(&$vars)
-    {
-        /* Check if a form is being edited. */
-        $editing = $vars->exists('domain_id');
-        $domain = $GLOBALS['session']->get('vilma', 'domain');
-        parent::Horde_Form($vars, $editing ? _("Edit Domain") : _("New Domain"));
-        if ($editing && !$this->isSubmitted()) {
-            $domain = $GLOBALS['vilma']->driver->getDomain($vars->get('domain_id'));
-            if (is_a($domain, 'PEAR_Error')) {
-                return $domain;
-            }
-            $vars = new Horde_Variables($domain);
-        }
-        $vars->add('name', $domain['domain_name']);
-        $vars->add('transport', $domain['domain_transport']);
-        $vars->add('max_users', $domain['domain_max_users']);
-        $vars->add('quota', $domain['domain_quota']);
-        /* Set up the form. */
-        $this->setButtons(true, true);
-        $this->addHidden('', 'domain_id', 'text', false);
-        $this->addVariable(_("Domain"), 'name', 'text', true);
-        require_once 'Horde/Array.php';
-        $this->addVariable(_("Transport"), 'transport', 'enum', false, false, null, array(Horde_Array::valuesToKeys($GLOBALS['conf']['mta']['transports'])));
-        $this->addVariable(_("Max users"), 'max_users', 'int', false);
-        $this->addVariable(_("Quota"), 'quota', 'int', false, false, _("Value in MB"));
-    }
-
-}
diff --git a/vilma/lib/Forms/EditForwardForm.php b/vilma/lib/Forms/EditForwardForm.php
deleted file mode 100644 (file)
index cd3a4f3..0000000
+++ /dev/null
@@ -1,38 +0,0 @@
-<?php
-/**
- * Copyright 2006-2007 Alkaloid Networks <http://www.alkaloid.net>
- *
- * See the enclosed file LICENSE for license information (BSD). If you did
- * did not receive this file, see http://cvs.horde.org/co.php/vilma/LICENSE.
- *
- * @author  Daniel Collins <horde_dev@argentproductions.com>
- * @package Vilma
- */
-
-class EditForwardForm extends Horde_Form {
-
-    function EditForwardForm(&$vars)
-    {
-        $type = $vars->get('type');
-        $editing = ($vars->get('mode') == 'edit');
-        if ($editing) {
-            $title = sprintf(_("Edit Forward \"%s\" for \"%s\""), $vars->get('forward_address'), $vars->get('address'));
-        } else {
-            $title = sprintf(_("New Forward for %s"), $vars->get('address'));
-        }
-        parent::Horde_Form($vars, $title);
-
-        /* Set up the form. */
-        $this->setButtons(true, true);
-        $this->addHidden('', 'address', 'text', false);
-        $this->addHidden('', 'mode', 'text', false);
-        $this->addHidden('', 'id', 'text', false);
-        if ($editing) {
-            $this->addHidden('', 'forward', 'text', false);
-        }
-        $name = "Forward Address";
-        $type = $vars->get('type');
-        $this->addVariable(_($name), 'forward_address', 'email', true, false, _("The email address to add as an forward for this user.  Note that the server must be configured to receive mail for the domain contained in this address."));
-    }
-
-}
diff --git a/vilma/lib/Forms/EditUserForm.php b/vilma/lib/Forms/EditUserForm.php
deleted file mode 100644 (file)
index e04f301..0000000
+++ /dev/null
@@ -1,68 +0,0 @@
-<?php
-/**
- * Copyright 2006-2007 Alkaloid Networks <http://www.alkaloid.net>
- *
- * See the enclosed file LICENSE for license information (BSD). If you did
- * did not receive this file, see http://cvs.horde.org/co.php/vilma/LICENSE.
- *
- * @author  Ben Klang <ben@alkaloid.net>
- * @package Vilma
- */
-
-class EditUserForm extends Horde_Form {
-
-    function EditUserForm(&$vars)
-    {
-        $type = $vars->get('type');
-        $editing = ($vars->get('mode') == 'edit');
-        if ($editing) {
-            if($type == 'group') {
-                $title = sprintf(_("Edit Group for \"%s\""), $vars->get('domain'));
-            } else if($type == 'forward') {
-                $title = sprintf(_("Edit Forward for \"%s\""), $vars->get('domain'));
-            } else {
-                $title = sprintf(_("Edit User for \"%s\""), $vars->get('domain'));
-            }
-        } else {
-            $title = sprintf(_("New User @%s"), $vars->get('domain'));
-        }
-        parent::Horde_Form($vars, $title);
-
-        /* Set up the form. */
-        $this->setButtons(true, true);
-        $this->addHidden('', 'address', 'text', false);
-        $this->addHidden('', 'mode', 'text', false);
-        $this->addHidden('', 'domain', 'text', false);
-        $this->addHidden('', 'id', 'text', false);
-        if ($editing) {
-            $this->addHidden('', 'user_name', 'text', false);
-        }
-        $name = "User Name";
-        $type = $vars->get('type');
-        if($type == 'group') {
-            $name = "Group Name";
-        } else if($type == 'forward') {
-            $name = "Forward Name";
-        }
-        $this->addVariable(_($name), 'user_name', 'text', true, $editing, _("Name must begin with an alphanumeric character, must contain only alphanumeric and '._-' characters, and must end with an alphanumeric character."), array('~^[a-zA-Z0-9]{1,1}[a-zA-Z0-9._-]*[a-zA-Z0-9]$~'));
-        if ($editing) {
-            $this->addVariable(_("Password"), 'password', 'passwordconfirm', false, false, _("Only enter a password if you wish to change this user's password"));
-        } else {
-            $this->addVariable(_("Password"), 'password', 'passwordconfirm', true);
-        }
-        $this->addVariable(_("Full Name"), 'user_full_name', 'text', true);
-        $attrs = $GLOBALS['vilma']->driver->getUserFormAttributes();
-        foreach ($attrs as $attr) {
-            $v = &$this->addVariable($attr['label'], $attr['name'],
-                                $attr['type'], $attr['required'],
-                                $attr['readonly'], $attr['description'],
-                                $attr['params']);
-
-            if (!isset($attr['default'])) {
-                $v->setDefault($attr['default']);
-            }
-        }
-        //$this->addVariable(_("Target(s)"), 'target', 'text', false);
-    }
-
-}
index 0897bd9..d9865ae 100644 (file)
  * @author  Jason M. Felice <jason.m.felice@gmail.com>
  * @package Vilma
  */
-class Vilma_MailboxDriver {
-
-    var $_params;
-
+abstract class Vilma_MailboxDriver
+{
     /**
-     * Constructor.
+     * A hash containing any parameters for the current driver.
      *
-     * @access private
+     * @var array
      */
-    function Vilma_MailboxDriver($params = array())
-    {
-        $this->_params = $params;
-    }
+    protected $_params = array();
 
     /**
-     * Creates a new mailbox driver instance.
-     *
-     * @param string $driver  The name of the driver to create an instance of.
-     * @param array $params   Driver-specific parameters.
+     * Constructor.
      *
-     * @return Vilma_MailboxDriver  The new driver instance or a PEAR_Error.
+     * @param array $params  Any parameters needed for this driver.
      */
-    function &factory($driver, $params = array())
+    public function __construct(array $params = array())
     {
-        require_once VILMA_BASE . '/lib/MailboxDriver/' . $driver . '.php';
-        $class = 'Vilma_MailboxDriver_' . $driver;
-        $mailbox = &new $class($params);
-        return $mailbox;
+        $this->_params = $params;
     }
 
     /**
-     * Returns a mailbox driver instance with the specified params, creating
-     * it if necessary.
+     * Creates a new mailbox.
      *
-     * @param string $driver  The name of the driver to create an instance of.
-     * @param array $params   Driver-specific parameters.
+     * @param string $user    The name of the mailbox to create.
+     * @param string $domain  The name of the domain in which to create the
+     *                        mailbox.
      *
-     * @return Vilma_MailboxDriver  The new driver instance or a PEAR_Error.
+     * @throws Vilma_Exception
      */
-    function &singleton($driver, $params = array())
-    {
-        static $cache;
-        $key = serialize(array($driver, $params));
-        if (!isset($cache[$key])) {
-            $ret = &Vilma_MailboxDriver::factory($driver, $params);
-            if (is_a($ret, 'PEAR_Error')) {
-                return $ret;
-            }
-            $cache[$key] = &$ret;
-        }
-        return $cache[$key];
-    }
+    abstract public function createMailbox($user, $domain);
 
     /**
-     * Creates a new mailbox.
+     * Deletes an existing mailbox.
      *
-     * This default implementation only returns an error.
+     * @param string $user    The name of the mailbox to delete.
+     * @param string $domain  The name of the domain in which to delete the
+     *                        mailbox.
      *
-     * @param string $user    The name of the mailbox to create
-     * @param string $domain  The name of the domain in which to create the
-     *                        mailbox
-     * @return mixed  True or PEAR_Error:: instance.
+     * @throws Vilma_Exception
      */
-    function createMailbox($user, $domain)
-    {
-        return PEAR::raiseError(_("This driver cannot create mailboxes."));
-    }
+    abstract public function deleteMailbox($user, $domain);
 
     /**
-     * Deletes an existing mailbox.
-     *
-     * This default implementation only returns an error.
+     * Checks whether a mailbox exists and is set up properly.
      *
-     * @param string $user    The name of the mailbox to delete
-     * @param string $domain  The name of the domain in which to delete the
-     *                        mailbox
+     * @param string $user    The name of the mailbox to check.
+     * @param string $domain  The mailbox' domain.
      *
-     * @return mixed  True or PEAR_Error:: instance.
+     * @return boolean  True if the mailbox exists.
+     * @throws Vilma_Exception if the mailbox doesn't exist.
      */
-    function deleteMailbox($user, $domain)
-    {
-        return PEAR::raiseError(_("This driver cannot delete mailboxes."));
-    }
+    abstract public function checkMailbox($user, $domain);
 
     /**
-     * Checks whether a mailbox exists and is set up properly.
+     * Creates a new mailbox driver instance.
      *
-     * @param string $user    The name of the mailbox to check
-     * @param string $domain  The mailbox's domain
+     * @param string $driver  The name of the driver to create an instance of.
+     * @param array $params   Driver-specific parameters.
      *
-     * @return mixed  True or PEAR_Error:: instance.
+     * @return Vilma_MailboxDriver  The new driver instance.
+     * @throws Vilma_Exception
      */
-    function checkMailbox($user, $domain)
+    static public function factory($driver = null, $params = null)
     {
-        return true;
-    }
+        if (is_null($driver)) {
+            $driver = $GLOBALS['conf']['mailboxes']['driver'];
+        }
+        $driver = Horde_String::ucfirst(basename($driver));
 
+        if (is_null($params)) {
+            $params = $GLOBALS['conf']['mailboxes']['params'];
+        }
+
+        $class = 'Vilma_MailboxDriver_' . $driver;
+        if (class_exists($class)) {
+            return new $class($params);
+        }
+
+        throw new Vilma_Exception(sprintf(_("No such mailbox driver \"%s\" found"), $driver));
+    }
 }
diff --git a/vilma/lib/MailboxDriver/Hooks.php b/vilma/lib/MailboxDriver/Hooks.php
new file mode 100644 (file)
index 0000000..4ba2b3e
--- /dev/null
@@ -0,0 +1,69 @@
+<?php
+/**
+ * Copyright 2006-2007 Alkaloid Networks <http://www.alkaloid.net/>
+ *
+ * See the enclosed file LICENSE for license information (BSD). If you did not
+ * did not receive this file, see http://cvs.horde.org/co.php/vilma/LICENSE.
+ *
+ * @author  Ben Klang <bklang@alkaloid.net>
+ * @package Vilma
+ */
+
+class Vilma_MailboxDriver_hooks extends Vilma_MailboxDriver
+{
+    /**
+     * Creates a new mailbox.
+     *
+     * @param string $user    The name of the mailbox to create.
+     * @param string $domain  The name of the domain in which to create the
+     *                        mailbox.
+     *
+     * @throws Vilma_Exception
+     */
+    public function createMailbox($user, $domain)
+    {
+        try {
+            return Horde::callHook('createMailbox', array($user, $domain), 'vilma');
+        } catch (Exception $e) {
+            throw new Vilma_Exception($e);
+        }
+    }
+
+    /**
+     * Deletes an existing mailbox.
+     *
+     * @todo
+     *
+     * @param string $user    The name of the mailbox to delete.
+     * @param string $domain  The name of the domain in which to delete the
+     *                        mailbox.
+     *
+     * @throws Vilma_Exception
+     */
+    public function deleteMailbox($user, $domain)
+    {
+        try {
+            return Horde::callHook('deleteMailbox', array($user, $domain), 'vilma');
+        } catch (Exception $e) {
+            throw new Vilma_Exception($e);
+        }
+    }
+
+    /**
+     * Checks whether a mailbox exists and is set up properly.
+     *
+     * @param string $user    The name of the mailbox to check.
+     * @param string $domain  The mailbox' domain.
+     *
+     * @return boolean  True if the mailbox exists.
+     * @throws Vilma_Exception if the mailbox doesn't exist.
+     */
+    public function checkMailbox($user, $domain)
+    {
+        try {
+            return Horde::callHook('checkMailbox', array($user, $domain), 'vilma');
+        } catch (Exception $e) {
+            throw new Vilma_Exception($e);
+        }
+    }
+}
diff --git a/vilma/lib/MailboxDriver/Imap.php b/vilma/lib/MailboxDriver/Imap.php
new file mode 100644 (file)
index 0000000..69ed9d0
--- /dev/null
@@ -0,0 +1,90 @@
+<?php
+/**
+ * Copyright 2004-2010 The Horde Project (http://www.horde.org/)
+ *
+ * See the enclosed file LICENSE for license information (BSD). If you did not
+ * did not receive this file, see http://cvs.horde.org/co.php/vilma/LICENSE.
+ *
+ * @author  Jason M. Felice <jason.m.felice@gmail.com>
+ * @author  Jan Schneider <jan@horde.org>
+ * @package Vilma
+ */
+class Vilma_MailboxDriver_imap extends Vilma_MailboxDriver
+{
+    /**
+     * An IMAP client.
+     *
+     * @var Horde_Imap_Client_Base
+     */
+    protected $_imap;
+
+    /**
+     * Constructor.
+     *
+     * @param array $params  Any parameters needed for this driver.
+     */
+    public function __construct(array $params = array())
+    {
+        parent::__construct($params);
+        $params = array('username' => $this->_params['admin_user'],
+                        'password' => $this->_params['admin_password'],
+                        'hostspec' => $this->_params['hostspec'],
+                        'port'     => $this->_params['port']);
+        $this->_imap = Horde_Imap_Client::factory('Socket', $params);
+    }
+
+    /**
+     * Creates a new mailbox.
+     *
+     * @param string $user    The name of the mailbox to create.
+     * @param string $domain  The name of the domain in which to create the
+     *                        mailbox.
+     *
+     * @throws Vilma_Exception
+     */
+    public function createMailbox($user, $domain)
+    {
+        try {
+            $this->_imap->createMailbox($this->_params['userhierarchy'] . $user . '@' . $domain);
+        } catch (Exception $e) {
+            throw new Vilma_Exception($e);
+        }
+    }
+
+    /**
+     * Deletes an existing mailbox.
+     *
+     * @todo
+     *
+     * @param string $user    The name of the mailbox to delete.
+     * @param string $domain  The name of the domain in which to delete the
+     *                        mailbox.
+     *
+     * @throws Vilma_Exception
+     */
+    public function deleteMailbox($user, $domain)
+    {
+        try {
+            $this->_imap->deleteMailbox($this->_params['userhierarchy'] . $user . '@' . $domain);
+        } catch (Exception $e) {
+            throw new Vilma_Exception($e);
+        }
+    }
+
+    /**
+     * Checks whether a mailbox exists and is set up properly.
+     *
+     * @param string $user    The name of the mailbox to check.
+     * @param string $domain  The mailbox' domain.
+     *
+     * @return boolean  True if the mailbox exists.
+     * @throws Vilma_Exception if the mailbox doesn't exist.
+     */
+    public function checkMailbox($user, $domain)
+    {
+        if (!$this->_imap->listMailboxes($this->_params['userhierarchy'] . $user . '@' . $domain)) {
+            throw new Vilma_Exception(sprintf(_("Mailbox \"%s\" does not exist."), $user . '@' . $domain));
+        }
+        return true;
+    }
+}
diff --git a/vilma/lib/MailboxDriver/Maildrop.php b/vilma/lib/MailboxDriver/Maildrop.php
new file mode 100644 (file)
index 0000000..db1d532
--- /dev/null
@@ -0,0 +1,86 @@
+<?php
+/**
+ * Copyright 2004-2010 The Horde Project (http://www.horde.org/)
+ *
+ * See the enclosed file LICENSE for license information (BSD). If you did not
+ * did not receive this file, see http://cvs.horde.org/co.php/vilma/LICENSE.
+ *
+ * @author  Jason M. Felice <jason.m.felice@gmail.com>
+ * @package Vilma
+ */
+class Vilma_MailboxDriver_maildrop extends Vilma_MailboxDriver
+{
+    /**
+     * Creates a new mailbox.
+     *
+     * @param string $user    The name of the mailbox to create.
+     * @param string $domain  The name of the domain in which to create the
+     *                        mailbox.
+     *
+     * @throws Vilma_Exception
+     */
+    public function createMailbox($user, $domain)
+    {
+        if (empty($this->_params['system_user'])) {
+            throw new Vilma_Exception(_("No 'system_user' parameter specified to maildrop driver."));
+        }
+
+        $shell = sprintf('sudo -u %s maildirmake %s',
+                         escapeshellarg($this->_params['system_user']),
+                         escapeshellarg($this->_getMailboxDir($user, $domain)));
+        exec($shell);
+    }
+
+    /**
+     * Deletes an existing mailbox.
+     *
+     * @todo
+     *
+     * @param string $user    The name of the mailbox to delete.
+     * @param string $domain  The name of the domain in which to delete the
+     *                        mailbox.
+     *
+     * @throws Vilma_Exception
+     */
+    public function deleteMailbox($user, $domain)
+    {
+    }
+
+    /**
+     * Checks whether a mailbox exists and is set up properly.
+     *
+     * @param string $user    The name of the mailbox to check.
+     * @param string $domain  The mailbox' domain.
+     *
+     * @return boolean  True if the mailbox exists.
+     * @throws Vilma_Exception if the mailbox doesn't exist or a parameter is
+     *                         missing
+     */
+    public function checkMailbox($user, $domain)
+    {
+        $dir = $this->_getMailboxDir($user, $domain);
+
+        if (!is_dir($dir)) {
+            throw new Vilma_Exception(sprintf(_("Maildrop directory \"%s\" does not exist."), $dir));
+        }
+
+        return true;
+    }
+
+    /**
+     * @throws Vilma_Exception
+     */
+    protected function _getMailboxDir($user, $domain)
+    {
+        if (empty($this->_params['mail_dir_base'])) {
+            throw new Vilma_Exception(_("No 'mail_dir_base' parameter specified to maildrop driver."));
+        }
+
+        $dir = $this->_params['mail_dir_base'];
+        if (!empty($this->_params['usedomain'])) {
+            $dir .= '/' . $domain;
+        }
+
+        return $dir . '/' . $user;
+    }
+}
diff --git a/vilma/lib/MailboxDriver/Null.php b/vilma/lib/MailboxDriver/Null.php
new file mode 100644 (file)
index 0000000..bcd5a34
--- /dev/null
@@ -0,0 +1,47 @@
+<?php
+/**
+ * Copyright 2004-2010 The Horde Project (http://www.horde.org/)
+ *
+ * See the enclosed file LICENSE for license information (BSD). If you did not
+ * did not receive this file, see http://cvs.horde.org/co.php/vilma/LICENSE.
+ *
+ * @author  David Cummings <davidcummings@acm.org>
+ * @package Vilma
+ */
+class Vilma_MailboxDriver_null extends Vilma_MailboxDriver
+{
+    /**
+     * Creates a new mailbox.
+     *
+     * @param string $user    The name of the mailbox to create.
+     * @param string $domain  The name of the domain in which to create the
+     *                        mailbox.
+     */
+    public function createMailbox($user, $domain)
+    {
+    }
+
+    /**
+     * Deletes an existing mailbox.
+     *
+     * @param string $user    The name of the mailbox to delete.
+     * @param string $domain  The name of the domain in which to delete the
+     *                        mailbox.
+     */
+    public function deleteMailbox($user, $domain)
+    {
+    }
+
+    /**
+     * Checks whether a mailbox exists and is set up properly.
+     *
+     * @param string $user    The name of the mailbox to check.
+     * @param string $domain  The mailbox' domain.
+     *
+     * @return boolean  True if the mailbox exists.
+     */
+    public function checkMailbox($user, $domain)
+    {
+        return true;
+    }
+}
diff --git a/vilma/lib/MailboxDriver/hooks.php b/vilma/lib/MailboxDriver/hooks.php
deleted file mode 100644 (file)
index ff158e2..0000000
+++ /dev/null
@@ -1,47 +0,0 @@
-<?php
-/**
- * Copyright 2006-2007 Alkaloid Networks <http://www.alkaloid.net/>
- *
- * See the enclosed file LICENSE for license information (BSD). If you did not
- * did not receive this file, see http://cvs.horde.org/co.php/vilma/LICENSE.
- *
- * @author  Ben Klang <bklang@alkaloid.net>
- * @package Vilma
- */
-
-class Vilma_MailboxDriver_hooks extends Vilma_MailboxDriver {
-
-    function Vilma_MailboxDriver_hooks($params)
-    {
-        Horde::loadConfiguration('hooks.php', null, 'vilma');
-    }
-
-
-    function checkMailbox($user, $domain)
-    {
-        if (function_exists('_vilma_hook_checkMailbox')) {
-            return call_user_func('_vilma_hook_checkMailbox', $user, $domain);
-        } else {
-            return true;
-        }
-    }
-
-    function createMailbox($user, $domain)
-    {
-        if (function_exists('_vilma_hook_createMailbox')) {
-            return call_user_func('_vilma_hook_createMailbox', $user, $domain);
-        } else {
-            return true;
-        }
-    }
-
-    function deleteMailbox($user, $domain)
-    {
-        if (function_exists('_vilma_hook_deleteMailbox')) {
-            return call_user_func('_vilma_hook_deleteMailbox', $user, $domain);
-        } else {
-            return true;
-        }
-    }
-
-}
diff --git a/vilma/lib/MailboxDriver/imap.php b/vilma/lib/MailboxDriver/imap.php
deleted file mode 100644 (file)
index f3e59fd..0000000
+++ /dev/null
@@ -1,48 +0,0 @@
-<?php
-/**
- * Copyright 2004-2010 The Horde Project (http://www.horde.org/)
- *
- * See the enclosed file LICENSE for license information (BSD). If you did not
- * did not receive this file, see http://cvs.horde.org/co.php/vilma/LICENSE.
- *
- * @author  Jason M. Felice <jason.m.felice@gmail.com>
- * @author  Jan Schneider <jan@horde.org>
- * @package Vilma
- */
-class Vilma_MailboxDriver_imap extends Vilma_MailboxDriver
-{
-    protected $_imap = null;
-
-    protected function _connect()
-    {
-        if ($this->_imap) {
-            return;
-        }
-        $params = array('username' => $this->_params['admin_user'],
-                        'password' => $this->_params['admin_password'],
-                        'hostspec' => $this->_params['hostspec'],
-                        'port'     => $this->_params['port']);
-        $this->_imap = Horde_Imap_Client::factory('Socket', $params);
-    }
-
-    public function checkMailbox($user, $domain)
-    {
-        $this->_connect();
-        if (!$this->_imap->listMailboxes($this->_params['userhierarchy'] . $user . '@' . $domain)) {
-            throw new Vilma_Exception(sprintf(_("Mailbox \"%s\" does not exist."), $user . '@' . $domain));
-        }
-    }
-
-    public function createMailbox($user, $domain)
-    {
-        $this->_connect();
-        $this->_imap->createMailbox($this->_params['userhierarchy'] . $user . '@' . $domain);
-    }
-
-    public function deleteMailbox($user, $domain)
-    {
-        $this->_connect();
-        $this->_imap->deleteMailbox($this->_params['userhierarchy'] . $user . '@' . $domain);
-    }
-
-}
diff --git a/vilma/lib/MailboxDriver/maildrop.php b/vilma/lib/MailboxDriver/maildrop.php
deleted file mode 100644 (file)
index 734e547..0000000
+++ /dev/null
@@ -1,72 +0,0 @@
-<?php
-/**
- * Copyright 2004-2010 The Horde Project (http://www.horde.org/)
- *
- * See the enclosed file LICENSE for license information (BSD). If you did not
- * did not receive this file, see http://cvs.horde.org/co.php/vilma/LICENSE.
- *
- * @author  Jason M. Felice <jason.m.felice@gmail.com>
- * @package Vilma
- */
-class Vilma_MailboxDriver_maildrop extends Vilma_MailboxDriver {
-
-    function _getMailboxDir($user, $domain)
-    {
-        if (empty($this->_params['mail_dir_base'])) {
-            throw new Vilma_Exception(_("No 'mail_dir_base' parameter specified to maildrop driver."));
-        }
-        $dir = $this->_params['mail_dir_base'];
-        $usedomain = isset($this->_params['usedomain']) ? $this->_params['usedomain'] : false;
-        if ($usedomain) {
-            $dir .= '/' . $domain;
-        }
-
-        return $dir . '/' . $user;
-    }
-
-    function checkMailbox($user, $domain)
-    {
-        static $exists;
-
-        $dir = $this->_getMailboxDir($user, $domain);
-        if (is_a($dir, 'PEAR_Error')) {
-            return $dir;
-        }
-
-        if (!isset($exists[$dir])) {
-            $exists[$dir] = is_dir($dir);
-        }
-
-        if (!$exists[$dir]) {
-            throw new Vilma_Exception(sprintf(_("Maildrop directory \"%s\" does not exist."), $dir));
-        }
-
-        return true;
-    }
-
-    function createMailbox($user, $domain)
-    {
-        $dir = $this->_getMailboxDir($user, $domain);
-        if (is_a($dir, 'PEAR_Error')) {
-            return $dir;
-        }
-        if (empty($this->_params['system_user'])) {
-            throw new Vilma_Exception(_("No 'system_user' parameter specified to maildrop driver."));
-        }
-
-        $create_function = sprintf('sudo -u %s maildirmake %s',
-                                   escapeshellarg($this->_params['system_user']),
-                                   escapeshellarg($dir));
-        exec($create_function);
-        return true;
-    }
-
-    /**
-     * @TODO: Implement
-     */
-    function deleteMailbox($user, $domain)
-    {
-        return true;
-    }
-
-}
diff --git a/vilma/lib/MailboxDriver/null.php b/vilma/lib/MailboxDriver/null.php
deleted file mode 100644 (file)
index 093fb81..0000000
+++ /dev/null
@@ -1,28 +0,0 @@
-<?php
-/**
- * Copyright 2004-2010 The Horde Project (http://www.horde.org/)
- *
- * See the enclosed file LICENSE for license information (BSD). If you did not
- * did not receive this file, see http://cvs.horde.org/co.php/vilma/LICENSE.
- *
- * @author  David Cummings <davidcummings@acm.org>
- * @package Vilma
- */
-class Vilma_MailboxDriver_null extends Vilma_MailboxDriver {
-
-    public function checkMailbox($user, $domain)
-    {
-        return true;
-    }
-
-    public function createMailbox($user, $domain)
-    {
-        return true;
-    }
-
-    public function deleteMailbox($user, $domain)
-    {
-        return true;
-    }
-
-}
index b9d137d..5d9a04b 100644 (file)
@@ -12,7 +12,7 @@
 class Vilma
 {
     /**
-     * Check whether the current user has administrative permissions over the
+     * Checks whether the current user has administrative permissions over the
      * requested domain at the given permissions level.
      *
      * Also checks to see if the user is a Vilma superadmin.  If the user is a
@@ -23,7 +23,7 @@ class Vilma
      *
      * @return boolean  True if the user has the requested permission.
      */
-    public function hasPermission($domain = null, $permmask = null)
+    static public function hasPermission($domain = null, $permmask = null)
     {
         if ($GLOBALS['registry']->isAdmin()) {
             return true;
@@ -45,35 +45,32 @@ class Vilma
         return false;
     }
 
-    function getUserMgrTypes()
+    static public function getUserMgrTypes()
     {
         return array(
             'all' => array(
                 'singular' => _("All"),
-                'plural'   => _("All") ),
+                'plural'   => _("All")),
             'user' => array(
                 'singular' => _("User"),
-                'plural' => _("Users")),
+                'plural' => _("Users")),
             'alias' => array(
                 'singular' => _("Alias"),
-                'plural' => _("Aliases"), ),
-            //'grpfwd' => array(
-            //    'singular' => _("Group/Forward"),
-            //    'plural' => _("Groups and Forwards"), ), );
+                'plural' => _("Aliases")),
             'group' => array(
                 'singular' => _("Group"),
-                'plural' => _("Groups")),
+                'plural' => _("Groups")),
             'forward' => array(
                 'singular' => _("Forward"),
-                'plural' => _("Forwards"),), );
+                'plural' => _("Forwards")));
     }
 
     /**
-     * Create tabs to navigate the user manager area
+     * Creates tabs to navigate the user manager area.
      *
-     * return object Horde_Core_Ui_Tabs object
+     * @return Horde_Core_Ui_Tabs
      */
-    function getUserMgrTabs(&$vars)
+    static public function getUserMgrTabs(Variables $vars)
     {
         $url = Horde::url('users/index.php');
         $tabs = new Horde_Core_Ui_Tabs('section', $vars);
@@ -84,34 +81,38 @@ class Vilma
     }
 
     /**
-     * Set the current domain
+     * Set the current domain.
      */
-    function setCurDomain($domain)
+    static public function setCurDomain($domain = null)
     {
-        $GLOBALS['session']->set('vilma', 'domain', $domain);
+        if ($domain) {
+            $GLOBALS['session']->set('vilma', 'domain', $domain);
+        } else {
+            $GLOBALS['session']->unset('vilma', 'domain');
+        }
     }
 
     /**
-     * Strip the domain from an email address (leaving the Username)
+     * Strips the domain from an email address (leaving the user name).
      *
-     * @param string $email  Email address to strip (leaving the Username)
+     * @param string $email  Email address to strip.
      *
-     * @return string Username portion of supplied email address
+     * @return string  User name portion of the email address.
      */
-    function stripUser($email)
+    static public function stripUser($email)
     {
         list($user, $domain) = explode('@', $email);
         return $user;
     }
 
     /**
-     * Strip the username from an email address (leaving the domain)
+     * Strip the user name from an email address (leaving the domain).
      *
-     * @param string $email  Email address to strip (leaving the domain)
+     * @param string $email  Email address to strip.
      *
-     * @return string Domain portion of supplied email address
+     * @return string  Domain portion of the email address.
      */
-    function stripDomain($email)
+    static public function stripDomain($email)
     {
         $parts = explode('@', $email);
         if (count($parts) == 2) {
@@ -120,14 +121,4 @@ class Vilma
         }
         return null;
     }
-
-    function &getMailboxDriver()
-    {
-        global $conf;
-
-        require_once VILMA_BASE . '/lib/MailboxDriver.php';
-        $driver = &Vilma_MailboxDriver::singleton($conf['mailboxes']['driver'],
-                                                  $conf['mailboxes']['params']);
-        return $driver;
-    }
 }
index 01f9a94..7ed2ead 100644 (file)
@@ -32,7 +32,7 @@ function checkConstruction()
         unset($unfiltered_params['tables']['domainkey']);
     }
 
-    $GLOBALS['unfiltered'] = &Vilma_Driver::singleton('sql', $unfiltered_params);
+    $GLOBALS['unfiltered'] = Vilma_Driver::factory('sql', $unfiltered_params);
     if (is_a($GLOBALS['unfiltered'], 'PEAR_Error')) {
         printf(_("ERROR(1): %s\n"), $GLOBALS['unfiltered']->getMessage());
         return;
@@ -41,7 +41,7 @@ function checkConstruction()
     $filtered_params = $conf['storage']['params'];
     $filtered_params['tables']['domainkey'] = '__FOO';
 
-    $GLOBALS['filtered'] = &Vilma_Driver::singleton('sql', $filtered_params);
+    $GLOBALS['filtered'] = Vilma_Driver::factory('sql', $filtered_params);
     if (is_a($GLOBALS['filtered'], 'PEAR_Error')) {
         printf(_("ERROR(2): %s\n"), $GLOBALS['filtered']->getMessage());
         return;
index b3199f0..ab22281 100644 (file)
@@ -17,12 +17,7 @@ if (!Horde_Cli::runningFromCLI()) {
 // some variables, etc.
 Horde_Cli::init();
 
-/* Make sure there's no compression. */
-@ob_end_clean();
-
-$users_by_domain = $vilma->driver->getAllUsers();
-
-foreach ($users_by_domain as $domain => $users) {
+foreach ($vilma->driver->getAllUsers() as $domain => $users) {
     foreach ($users as $user) {
         /* Check for user's home dir. */
         if (!file_exists($user['user_home_dir'])) {
index 91f30af..f64de0b 100644 (file)
@@ -13,166 +13,148 @@ $vilma = Horde_Registry::appInit('vilma');
 
 /* Only admin should be using this. */
 if (!Vilma::hasPermission($domain)) {
-    $registry->authenticateFailure('vilma', $e);
+    $registry->authenticateFailure('vilma');
 }
 
 $vars = Horde_Variables::getDefaultVariables();
-$address = $vars->get('address');
-$section = Horde_Util::getFormData('section','all');
+$user_id = $vars->address;
+$section = $vars->get('section', 'all');
 
-//$addrInfo = $vilma->driver->getAddressInfo($address, 'all');
-/*
-$user_id = $vars->get('address');
-$formname = $vars->get('formname');
-$user = $vilma->driver->getUser($user_id);
-print_r($vars) . '<br />';
-echo $user_id . '<br />';
-echo $fromname . '<br />';
-print_r($user) . '<br />';
-$domain = Vilma::stripDomain($user['name']);
-$domain = $vilma->driver->getDomainByName($domain);
-*/
-$address = $vilma->driver->getAddressInfo($address);
-$type = $address['type'];
-if(($section == 'all') && ($type == 'alias')) {
-    $address = $vilma->driver->getAddressInfo($vars->get('address'),$type);
+try {
+    $address = $vilma->driver->getAddressInfo($user_id);
+    $type = $address['type'];
+    if ($section == 'all' && $type == 'alias') {
+        $address = $vilma->driver->getAddressInfo($user_id, $type);
+    }
+} catch (Exception $e) {
+    $notification->push(sprintf(_("Error reading address information from backend: %s"), $address->getMessage()), 'horde.error');
+    Horde::url('users/index.php', true)->redirect();
 }
-$user_id = $vars->get('address');
+
 $user = $vilma->driver->getUser($user_id);
+/*
 $aliases = $vilma->driver->_getAliases($user_id);
 $aliasesCount = 0;
-if(is_array($aliases)) {
+if (is_array($aliases)) {
     $aliasesCount = sizeof($aliases);
 }
+*/
+
 $domain = Vilma::stripDomain($user_id);
-$forwards = $vilma->driver->_getGroupsAndForwards('forwards',$domain);
+$forwards = $vilma->driver->_getGroupsAndForwards('forwards', $domain);
 $forwardsCount = 0;
-foreach($forwards as $entry) {
-    foreach($entry['targets'] as $target) {
-        if($user_id === $target) {
+foreach ($forwards as $entry) {
+    foreach ($entry['targets'] as $target) {
+        if ($user_id === $target) {
             $forwardsCount++;
         }
     }
 }
-$groups = $vilma->driver->_getGroupsAndForwards('groups',$domain);
+$groups = $vilma->driver->_getGroupsAndForwards('groups', $domain);
 $groupsCount = 0;
-foreach($groups as $entry) {
-    foreach($entry['targets'] as $target) {
-        if($user_id === $target) {
+foreach ($groups as $entry) {
+    foreach ($entry['targets'] as $target) {
+        if ($user_id === $target) {
             $groupsCount++;
         }
     }
 }
-if (is_a($address, 'PEAR_Error')) {
-    $notification->push(sprintf(_("Error reading address information from backend: %s"), $address->getMessage()), 'horde.error');
-    $url = '/users/index.php';
-    require VILMA_BASE . $url;
-    exit;
-}
+
 $user_name = $address['user_name'];
-if(!isset($user_name) || empty($user_name)) {
+if (empty($user_name)) {
     $user_name = $address['address'];
 }
-$vars->set('user_name', Vilma::stripUser($user_name));
+$vars->user_name = Vilma::stripUser($user_name);
 $domain = Vilma::stripDomain($address);
 $domain = $vilma->driver->getDomainByName($domain);
-$vars->set('domain', $domain);
-$vars->set('mode', 'edit');
+$vars->domain = $domain;
+$vars->mode = 'edit';
 
-$form = new Horde_Form($vars, sprintf(_("Delete %s"), $type));
 /* Set up the form. */
+$form = new Horde_Form($vars, sprintf(_("Delete %s"), $type));
 $form->setButtons(array(_("Delete"), _("Do not delete")));
 //$form->addHidden($user_id, 'user_id', 'text', false);
 $form->addHidden($address['address'], 'address', 'text', false);
 $form->addHidden($section, 'section', 'text', false);
 
-$desc = "Delete $type \"%s\"";
-$sub = " and all dependencies?";
-$tot = $aliasesCount + $groupsCount + $forwardsCount;
-if($tot > 0) {
-    $desc .= $sub;
+if ($aliasesCount + $groupsCount + $forwardsCount) {
+    $desc = _("Delete %s \"%s\" and all dependencies?");
 } else {
-    $desc .= "?";
+    $desc = _("Delete %s \"%s\"?");
 }
-if($aliasesCount > 0) {
-    $desc .= " Account has " . $aliasesCount . " aliases.";
+$desc = sprintf($desc, $type, $user_name);
+if ($aliasesCount) {
+    $desc .= ' ' . sprintf(ngettext("Account has %d alias.", "Account has %d aliases.", $aliasesCount), $aliasesCount);
 }
-if($forwardsCount > 0) {
-    $desc .= " Account is the target of  " . $forwardsCount . " forward(s).";
+if ($forwardsCount) {
+    $desc .= ' ' . sprintf(ngettext("Account is the target of %d forward.", "Account is the target of %d forwards.", $forwardsCount), $forwardsCount);
 }
-if($groupsCount > 0) {
-    $desc .= " Account belongs to  " . $groupsCount . " group(s).";
+if ($groupsCount) {
+    $desc .= ' ' . sprintf(ngettext("Account belongs to %d group.", "Account belongs to %d groups.", $groupsCount), $groupsCount);
 }
-$form->addVariable(sprintf(_($desc), $user_name), 'description', 'description', false);
-if ($vars->get('submitbutton') == _("Delete")) {
-    if ($type == 'alias') {
-        if ($form->validate($vars)) {
-            $form->getInfo($vars, $info);
-            $deleteInfo = array();
-            $deleteInfo['address'] = $address['destination'];
-            $deleteInfo['alias'] = $user_id;
-            $delete = $vilma->driver->deleteAlias($deleteInfo);
-            if (is_a($delete, 'PEAR_Error')) {
-                Horde::logMessage($delete, 'ERR');
-                $notification->push(sprintf(_("Error deleting alias. %s."), $delete->getMessage()), 'horde.error');
-            } else {
-                $notification->push(_("Alias deleted."), 'horde.success');
-            }
-            Horde::url('users/index.php')
-                ->add('domain_id', $domain['id'])
-                ->redirect();
+$form->addVariable($desc, 'description', 'description', false);
+
+if ($vars->get('submitbutton') == _("Do not delete")) {
+    $notification->push(_("User not deleted."), 'horde.message');
+    Horde::url('users/index.php', true)
+        ->add('domain_id', $domain['id'])
+        ->redirect();
+}
+
+if ($vars->get('submitbutton') == _("Delete") &&
+    $form->validate($vars)) {
+    $form->getInfo($vars, $info);
+
+    switch ($type) {
+    case 'alias':
+        $deleteInfo = array('address' => $address['destination'],
+                            'alias' => $user_id);
+        try {
+            $vilma->driver->deleteAlias($deleteInfo);
+            $notification->push(_("Alias deleted."), 'horde.success');
+        } catch (Exception $e) {
+            $notification->push(sprintf(_("Error deleting alias. %s."), $e->getMessage()), 'horde.error');
         }
-    } elseif ($type == 'forward') {
-        if ($form->validate($vars)) {
-            $form->getInfo($vars, $info);
-            $deleteInfo = array();
-            $deleteInfo['address'] = $address['destination'];
-            $deleteInfo['forward'] = $user_id;
-            $delete = $vilma->driver->deleteForward($deleteInfo);
-            if (is_a($delete, 'PEAR_Error')) {
-                Horde::logMessage($delete, 'ERR');
-                $notification->push(sprintf(_("Error deleting forward. %s."), $delete->getMessage()), 'horde.error');
-            } else {
-                $notification->push(_("Forward deleted."), 'horde.success');
-            }
-            Horde::url('users/index.php')
-                ->add('domain_id', $domain['id'])
-                ->redirect();
+        Horde::url('users/index.php', true)
+            ->add('domain_id', $domain['id'])
+            ->redirect();
+
+    case 'forward':
+        $deleteInfo = array('address' => $address['destination'],
+                            'forward' => $user_id);
+        try {
+            $vilma->driver->deleteForward($deleteInfo);
+            $notification->push(_("Forward deleted."), 'horde.success');
+        } catch (Exception $e) {
+            $notification->push(sprintf(_("Error deleting forward. %s."), $e->getMessage()), 'horde.error');
         }
-    } else {
-        if ($form->validate($vars)) {
-            $form->getInfo($vars, $info);
-            //$delete = $vilma->driver->deleteUser($info['user_id']);
-            $delete = $vilma->driver->deleteUser($address['address']);
-            if (is_a($delete, 'PEAR_Error')) {
-                Horde::logMessage($delete, 'ERR');
-                $notification->push(sprintf(_("Error deleting user. %s."), $delete->getMessage()), 'horde.error');
-            } else {
-                $notification->push(_("$type deleted."), 'horde.success');
-            }
-            Horde::url('users/index.php')
-                ->add('domain_id', $domain['id'])
-                ->redirect();
+        Horde::url('users/index.php', true)
+            ->add('domain_id', $domain['id'])
+            ->redirect();
+
+    default:
+        try {
+            $vilma->driver->deleteUser($address['address']);
+            $notification->push(_("$type deleted."), 'horde.success');
+        } catch (Exception $e) {
+            $notification->push(sprintf(_("Error deleting user. %s."), $e->getMessage()), 'horde.error');
         }
+        Horde::url('users/index.php', true)
+            ->add('domain_id', $domain['id'])
+            ->redirect();
     }
-} elseif ($vars->get('submitbutton') == _("Do not delete")) {
-    $notification->push(_("User not deleted."), 'horde.message');
-    Horde::url('users/index.php')
-        ->add('domain_id', $domain['id'])
-        ->redirect();
 }
 
 /* Render the form. */
-require_once 'Horde/Form/Renderer.php';
-$renderer = &new Horde_Form_Renderer();
+$renderer = new Horde_Form_Renderer();
+
+$template = $injector->createInstance('Horde_Template');
 
 Horde::startBuffer();
 $form->renderActive($renderer, $vars, 'delete.php', 'post');
-$main = Horde::endBuffer();
+$template->set('main', Horde::endBuffer());
 
-$template = $injector->createInstance('Horde_Template');
-$template->set('main', $main);
-$template->set('menu', Vilma::getMenu('string'));
+$template->set('menu', Horde::menu());
 
 Horde::startBuffer();
 $notification->notify(array('listeners' => 'status'));
index 3a7d180..3868b06 100644 (file)
 require_once dirname(__FILE__) . '/../lib/Application.php';
 $vilma = Horde_Registry::appInit('vilma');
 
-require_once VILMA_BASE . '/lib/Forms/EditUserForm.php';
-
 /* Only admin should be using this. */
 if (!Vilma::hasPermission($domain)) {
-    $registry->authenticateFailure('vilma', $e);
+    $registry->authenticateFailure('vilma');
 }
-$vars = Horde_Variables::getDefaultVariables();
-$address = $vars->get('address');
-$section = Horde_Util::getFormData('section','all');
 
-//$addrInfo = $vilma->driver->getAddressInfo($address, 'all');
+$vars = Horde_Variables::getDefaultVariables();
+$address = $vars->address;
+$section = $vars->get('section', 'all');
 $domain = Vilma::stripDomain($address);
 
 /* Check if a form is being edited. */
-if (!$vars->exists('mode')) {
+if (!isset($vars->mode)) {
     if ($address) {
-        $address = $vilma->driver->getAddressInfo($address,$section);
-        if (is_a($address, 'PEAR_Error')) {
-            $notification->push(sprintf(_("Error reading address information from backend: %s"), $address->getMessage()), 'horde.error');
-            $url = '/users/index.php';
-            require VILMA_BASE . $url;
-            exit;
+        try {
+            $address = $vilma->driver->getAddressInfo($address, $section);
+        } catch (Exception $e) {
+            $notification->push(sprintf(_("Error reading address information from backend: %s"), $e->getMessage()), 'horde.error');
+            Horde::url('users/index.php', true)->redirect();
         }
         $vars = new Horde_Variables($address);
-        $user_name = //$vars->get('address');
-                     $vars->get('user_name');
-        $vars->set('user_name', Vilma::stripUser($user_name));
+        $user_name = $vars->get('user_name');
+        $vars->user_name = Vilma::stripUser($user_name);
         $domain = Vilma::stripDomain($user_name);
-        $vars->set('domain', $domain);
-        $vars->set('type', $address['type']);
-        $vars->set('target', 'test'); //$address['target']);
-        $vars->set('mode', 'edit');
+        $vars->domain = $domain;
+        $vars->type = $address['type'];
+        $vars->target = 'test'; //$address['target']);
+        $vars->mode = 'edit';
     } else {
-        $vars->set('mode', 'new');
+        $vars->mode = 'new';
         $domain_info = $session->get('vilma', 'domain');
         $domain = $domain_info['domain_name'];
         $domain_id = $domain_info['domain_id'];
-        $vars->set('domain', $domain);
-        $vars->set('id', $domain_id);
-        $vars->add('user_name', Horde_Util::getFormData('user_name',''));
+        $vars->domain = $domain;
+        $vars->id = $domain_id;
+        $vars->add('user_name', Horde_Util::getFormData('user_name', ''));
     }
 }
 
 $domain = Vilma::stripDomain($address['address']);
-$tmp = $vars->get('domain');
-if(!isset($tmp)) {
-    $vars->set('domain', $domain);
+$tmp = $vars->domain;
+if (!$tmp) {
+    $vars->domain = $domain;
 }
-$form = &new EditUserForm($vars);
-if (!$vars->exists('id') && !$vilma->driver->isBelowMaxUsers($domain)) {
+
+if (!isset($vars->id) && !$vilma->driver->isBelowMaxUsers($domain)) {
     $notification->push(sprintf(_("\"%s\" already has the maximum number of users allowed."), $domain), 'horde.error');
-    require VILMA_BASE . '/users/index.php';
-    exit;
+            Horde::url('users/index.php', true)->redirect();
 }
+
+$form = new Vilma_Form_EditUser($vars);
 if ($form->validate($vars)) {
     $form->getInfo($vars, $info);
     $info['user_name'] = Horde_String::lower($info['user_name']) . '@' . $domain;
-    $user_id = $vilma->driver->saveUser($info);
-    if (is_a($user_id, 'PEAR_Error')) {
-        Horde::logMessage($user_id, 'ERR');
-        $notification->push(sprintf(_("Error saving user. %s"), $user_id->getMessage()), 'horde.error');
-    } else {
+    try {
+        $vilma->driver->saveUser($info);
         $notification->push(_("User details saved."), 'horde.success');
         /*
         $virtuals = $vilma->driver->getVirtuals($info['name']);
@@ -92,20 +85,21 @@ if ($form->validate($vars)) {
         }
         */
         //exit;
+    } catch (Exception $e) {
+        $notification->push(sprintf(_("Error saving user. %s"), $e->getMessage()), 'horde.error');
     }
 }
 
 /* Render the form. */
-require_once 'Horde/Form/Renderer.php';
-$renderer = &new Horde_Form_Renderer();
+$renderer = new Horde_Form_Renderer();
+
+$template = $injector->createInstance('Horde_Template');
 
 Horde::startBuffer();
 $form->renderActive($renderer, $vars, 'edit.php', 'post');
-$main = Horde::endBuffer();
+$template->set('main', Horde::endBuffer());
 
-$template = $injector->createInstance('Horde_Template');
-$template->set('main', $main);
-$template->set('menu', Vilma::getMenu('string'));
+$template->set('menu', Horde::menu());
 
 Horde::startBuffer();
 $notification->notify(array('listeners' => 'status'));
index 9bd8d66..790ab16 100644 (file)
 require_once dirname(__FILE__) . '/../lib/Application.php';
 $vilma = Horde_Registry::appInit('vilma');
 
-require_once VILMA_BASE . '/lib/Forms/EditAliasForm.php';
-
 /* Only admin should be using this. */
 if (!Vilma::hasPermission($domain)) {
-    $registry->authenticateFailure('vilma', $e);
+    $registry->authenticateFailure('vilma');
 }
 $vars = Variables::getDefaultVariables();
 
-/* If the form is submitted, $vars['mode'] will be set. Catch this and process the submission so that the displayed form accurately indicates the result of the transaction. */
-if ($vars->exists('mode')) {
-    Horde::logMessage("Submit Detected: " . print_r(serialize($vars), true), 'DEBUG');
-    $form = &new EditAliasForm($vars);
-
+/* If the form is submitted, $vars['mode'] will be set. Catch this and process
+ * the submission so that the displayed form accurately indicates the result of
+ * the transaction. */
+if (isset($vars->mode)) {
+    $form = new Vilma_Form_EditAlias($vars);
     if ($form->validate($vars)) {
         $form->getInfo($vars, $info);
-        $alias_id = $vilma->driver->saveAlias($info);
-        if (is_a($alias_id, 'PEAR_Error')) {
-            Horde::logMessage($user_id, 'ERR');
-            $notification->push(sprintf(_("Error saving alias. %s"), $alias_id->getMessage()), 'horde.error');
-            // remove the mode, and rearrange the alias information to clean
-            // up the form.
-            $vars->remove('mode');
-            $vars->add('retry', true);
-            if ($vars->exists('alias')) {
-                $vars->remove('alias_address');
-            } elseif ($vars->exists('address')) {
-                $vars->remove('alias_address');
-                $vars->remove('alias');
-            }
-        } else {
+        try {
+            $alias_id = $vilma->driver->saveAlias($info);
             $notification->push(_("Alias saved."), 'horde.success');
-            Horde::url('users/index.php')
+            Horde::url('users/index.php', true)
                 ->add('domain_id', $domain['id'])
                 ->redirect();
+        } catch (Exception $e) {
+            Horde::logMessage($e);
+            $notification->push(sprintf(_("Error saving alias. %s"), $e->getMessage()), 'horde.error');
+            // Remove the mode, and rearrange the alias information to clean
+            // up the form.
+            unset($vars->mode);
+            $vars->add('retry', true);
+            if (isset($vars->alias)) {
+                unset($vars->alias_address);
+            } elseif (isset($vars->address)) {
+                unset($vars->alias_address, $vars->alias);
+            }
         }
     }
 }
 
 /* Check if a form is being edited. */
-if (!$vars->exists('mode') || $vars->getExists('retry')) {
-    Horde::logMessage("No-Submit Detected: " . print_r(serialize($vars), true), 'DEBUG');
-    if ($vars->exists("alias")) {
-        $alias = $vars->get("alias");
-        Horde::logMessage("Alias Detected: $alias", 'DEBUG');
-
-        $addrInfo = $vilma->driver->getAddressInfo($alias,'alias');
-        Horde::logMessage("addrInfo contains: " . print_r($addrInfo, true), 'DEBUG');
-        if (is_a($addrInfo, 'PEAR_Error')) {
-            $notification->push(sprintf(_("Error reading address information from backend: %s"), $addrInfo->getMessage()), 'horde.error');
-            $url = '/users/index.php';
-            require VILMA_BASE . $url;
-            exit;
+if (!isset($vars->mode) || $vars->retry) {
+    if (isset($vars->alias)) {
+        $alias = $vars->alias;
+        try {
+            $addrInfo = $vilma->driver->getAddressInfo($alias, 'alias');
+            $address = $vilma->driver->getAddressInfo($addrInfo['destination']);
+        } catch (Exception $e) {
+            $notification->push(sprintf(_("Error reading address information from backend: %s"), $e->getMessage()), 'horde.error');
+            Horde::url('users/index.php', true)->redirect();
         }
-        $address = $vilma->driver->getAddressInfo($addrInfo['destination']);
-        Horde::logMessage("address Info contains: " . print_r($address, true), 'DEBUG');
         $vars = new Variables($address);
-        $vars->set('mode', 'edit');
+        $vars->mode = 'edit';
         $vars->add('alias_address', $alias);
         $vars->add('alias', $alias);
         $vars->add('address', $address['address']);
-    } elseif ($vars->exists("address")) {
-        $tmp_address = $vars->get("address");
-        Horde::logMessage("Address Detected: $tmp_address", 'DEBUG');
-
-        $address = $vilma->driver->getAddressInfo($tmp_address, 'all');
-        Horde::logMessage("addrInfo contains: " . print_r($addrInfo, true), 'DEBUG');
+    } elseif (isset($vars->address)) {
+        try {
+            $address = $vilma->driver->getAddressInfo($vars->address, 'all');
+        } catch (Exception $e) {
+            $notification->push(sprintf(_("Error reading address information from backend: %s"), $e->getMessage()), 'horde.error');
+            Horde::url('users/index.php', true)->redirect();
+        }
         $vars = new Variables($address);
-        $vars->set('mode', 'new');
+        $vars->mode = 'new';
     }
 
-    $form = &new EditAliasForm($vars);
+    $form = new Vilma_Form_EditAlias($vars);
 /*
     if ($form->validate($vars)) {
         $form->getInfo($vars, $info);
@@ -98,18 +90,16 @@ if (!$vars->exists('mode') || $vars->getExists('retry')) {
 */
 }
 
-
 /* Render the form. */
-require_once 'Horde/Form/Renderer.php';
-$renderer = &new Horde_Form_Renderer();
+$renderer = new Horde_Form_Renderer();
+
+$template = $injector->createInstance('Horde_Template');
 
 Horde::startBuffer();
 $form->renderActive($renderer, $vars, 'editAlias.php', 'post');
-$main = Horde::endBuffer();
+$template->set('main', Horde::endBuffer());
 
-$template = $injector->createInstance('Horde_Template');
-$template->set('main', $main);
-$template->set('menu', Vilma::getMenu('string'));
+$template->set('menu', Horde::menu());
 
 Horde::startBuffer();
 $notification->notify(array('listeners' => 'status'));
index 4822db8..6ee88da 100644 (file)
 require_once dirname(__FILE__) . '/../lib/Application.php';
 $vilma = Horde_Registry::appInit('vilma');
 
-require_once VILMA_BASE . '/lib/Forms/EditForwardForm.php';
-
 /* Only admin should be using this. */
 if (!Vilma::hasPermission($domain)) {
-    $registry->authenticateFailure('vilma', $e);
+    $registry->authenticateFailure('vilma');
 }
-$vars = Variables::getDefaultVariables();
 
-/* If the form is submitted, $vars['mode'] will be set. Catch this and process the submission so that the displayed form accurately indicates the result of the transaction. */
-if ($vars->exists('mode')) {
-  Horde::logMessage("Submit Detected: " . print_r(serialize($vars), true), 'DEBUG');
-  $form = &new EditForwardForm($vars);
+$vars = Variables::getDefaultVariables();
 
-  if ($form->validate($vars)) {
-      $form->getInfo($vars, $info);
-      $forward_id = $vilma->driver->saveForward($info);
-      if (is_a($forward_id, 'PEAR_Error')) {
-          Horde::logMessage($user_id, 'ERR');
-          $notification->push(sprintf(_("Error saving forward. %s"), $forward_id->getMessage()), 'horde.error');
-          // remove the mode, and rearrange the forward information to clean up the form.
-          $vars->remove('mode');
-          $vars->add('retry', true);
-          if ($vars->exists('forward')) {
-            $vars->remove('forward_address');
-          } elseif ($vars->exists('address')) {
-            $vars->remove('forward_address');
-            $vars->remove('forward');
-          }
-      } else {
-          $notification->push(_("forward saved."), 'horde.success');
-      }
-  }
-} // if
+/* If the form is submitted, $vars['mode'] will be set. Catch this and process
+ * the submission so that the displayed form accurately indicates the result of
+ * the transaction. */
+if (isset($vars->mode)) {
+    $form = new Vilma_Form_EditForward($vars);
+    if ($form->validate($vars)) {
+        $form->getInfo($vars, $info);
+        try {
+            $forward_id = $vilma->driver->saveForward($info);
+            $notification->push(_("forward saved."), 'horde.success');
+        } catch (Exception $e) {
+            Horde::logMessage($e);
+            $notification->push(sprintf(_("Error saving forward. %s"), $e->getMessage()), 'horde.error');
+            // Remove the mode, and rearrange the forward information to clean
+            // up the form.
+            unset($vars->mode);
+            $vars->add('retry', true);
+            if (isset($vars->forward)) {
+                unset($vars->forward_address);
+            } elseif (isset($vars->address)) {
+                unset($vars->forward_address, $vars->forward);
+            }
+        }
+    }
+}
 
 /* Check if a form is being edited. */
-if (!$vars->exists('mode') || $vars->getExists('retry')) {
-  Horde::logMessage("No-Submit Detected: " . print_r(serialize($vars), true), 'DEBUG');
-    if ($vars->exists("forward")) {
-        $forward = $vars->get("forward");
-        Horde::logMessage("Forward Detected: $forward", 'DEBUG');
-
-        $addrInfo = $vilma->driver->getAddressInfo($forward,'forward');
-        Horde::logMessage("addrInfo contains: " . print_r($addrInfo, true), 'DEBUG');
-        if (is_a($addrInfo, 'PEAR_Error')) {
-            $notification->push(sprintf(_("Error reading address information from backend: %s"), $addrInfo->getMessage()), 'horde.error');
-            $url = '/users/index.php';
-            require VILMA_BASE . $url;
-            exit;
+if (!isset($vars->mode) || $vars->retry) {
+    if (isset($vars->forward)) {
+        try {
+            $addrInfo = $vilma->driver->getAddressInfo($vars->forward, 'forward');
+            $address = $vilma->driver->getAddressInfo($addrInfo['destination']);
+        } catch (Exception $e) {
+            Horde::logMessage($e);
+            $notification->push(sprintf(_("Error reading address information from backend: %s"), $e->getMessage()), 'horde.error');
+            Horde::url('users/index.php', true)->redirect();
         }
-        $address = $vilma->driver->getAddressInfo($addrInfo['destination']);
-        Horde::logMessage("address Info contains: " . print_r($address, true), 'DEBUG');
         $vars = new Variables($address);
-        $vars->set('mode', 'edit');
+        $vars->mode = 'edit';
         $vars->add('forward_address', $forward);
         $vars->add('forward', $forward);
         $vars->add('address', $address['address']);
-    } elseif ($vars->exists("address")) {
-        $tmp_address = $vars->get("address");
-        Horde::logMessage("Address Detected: $tmp_address", 'DEBUG');
-
-        $address = $vilma->driver->getAddressInfo($tmp_address, 'all');
-        Horde::logMessage("addrInfo contains: " . print_r($addrInfo, true), 'DEBUG');
+    } elseif (isset($vars->address)) {
+        $address = $vilma->driver->getAddressInfo($vars->address, 'all');
         $vars = new Variables($address);
-        $vars->set('mode', 'new');
+        $vars->mode = 'new';
     }
 
-    $form = &new EditforwardForm($vars);
+    $form = new EditforwardForm($vars);
 /*
     if ($form->validate($vars)) {
         $form->getInfo($vars, $info);
@@ -94,18 +83,16 @@ if (!$vars->exists('mode') || $vars->getExists('retry')) {
 */
 }
 
-
 /* Render the form. */
-require_once 'Horde/Form/Renderer.php';
-$renderer = &new Horde_Form_Renderer();
+$renderer = new Horde_Form_Renderer();
+
+$template = $injector->createInstance('Horde_Template');
 
 Horde::startBuffer();
 $form->renderActive($renderer, $vars, 'editForward.php', 'post');
-$main = Horde::endBuffer();
+$template->set('main', Horde::endBuffer());
 
-$template = $injector->createInstance('Horde_Template');
-$template->set('main', $main);
-$template->set('menu', Vilma::getMenu('string'));
+$template->set('menu', Horde::menu());
 
 Horde::startBuffer();
 $notification->notify(array('listeners' => 'status'));
index 22607bd..6da9053 100644 (file)
@@ -15,117 +15,93 @@ $vilma = Horde_Registry::appInit('vilma');
 
 /* Only admin should be using this. */
 if (!Vilma::hasPermission($curdomain)) {
-    $registry->authenticateFailure('vilma', $e);
+    $registry->authenticateFailure('vilma');
 }
 
-// Input validation: make sure we have a valid section
+// Input validation: make sure we have a valid section.
 $vars = Horde_Variables::getDefaultVariables();
-$section = $vars->get('section');
-$tmp = Vilma::getUserMgrTypes();
-if (!array_key_exists($section, Vilma::getUserMgrTypes())) {
-    $section = 'all';
-    $vars->set('section', $section);
+$section = $vars->section;
+$types = Vilma::getUserMgrTypes();
+if (!isset($types[$section])) {
+    $vars->section = $section = 'all';
 }
 $tabs = Vilma::getUserMgrTabs($vars);
 
-$addresses = $vilma->driver->getAddresses($curdomain['domain_name'], $section);
-if (is_a($addresses, 'PEAR_Error')) {
-    $notification->push($addresses);
-    Horde::url('index.php')->redirect();
+try {
+    $addresses = $vilma->driver->getAddresses($curdomain['domain_name'], $section);
+} catch (Exception $e) {
+    $notification->push($e);
+    Horde::url('index.php', true)->redirect();
 }
 
 // Page results
-$page = Horde_Util::getGet('page', 0);
 $perpage = $prefs->getValue('addresses_perpage');
-$url = 'users/index.php';
-$url = Horde_Util::addParameter($url, 'section', $section);
+$url = Horde::url('users/index.php')->add('section', $section);
 $pager = new Horde_Core_Ui_Pager('page',
-                            Horde_Variables::getDefaultVariables(),
-                            array('num' => count($addresses),
-                                  'url' => $url,
-                                  'page_count' => 10,
-                                  'perpage' => $perpage));
-$addresses = array_slice($addresses, $page*$perpage, $perpage);
+                                 $vars,
+                                 array('num' => count($addresses),
+                                       'url' => $url,
+                                       'page_count' => 10,
+                                       'perpage' => $perpage));
+$addresses = array_slice($addresses, $vars->page * $perpage, $perpage);
 
-$types = Vilma::getUserMgrTypes();
-foreach ($addresses as $i => $address) {
+foreach ($addresses as &$address) {
     $type = $address['type'];
     $id = $address['id'];
 
-    if($type === 'alias') {
-        $url = Horde::url('users/editAlias.php');
-        $url = Horde_Util::addParameter($url, 'alias', $id);
-        $url = Horde_Util::addParameter($url, 'section', $section);
-        $addresses[$i]['edit_url'] = $url;
-        $addresses[$i]['add_alias_url'] = false;
-        $addresses[$i]['add_forward_url'] = false;
-    } elseif($type === 'forward') {
-        $url = Horde::url('users/editForward.php');
-        $url = Horde_Util::addParameter($url, 'forward', $id);
-        $url = Horde_Util::addParameter($url, 'section', $section);
-        $addresses[$i]['edit_url'] = $url;
-        $addresses[$i]['add_alias_url'] = false;
-        $addresses[$i]['add_forward_url'] = false;
-    } else {
-        $url = Horde::url('users/edit.php');
-        $url = Horde_Util::addParameter($url, 'address', $id);
-        $url = Horde_Util::addParameter($url, 'section', $section);
-        $addresses[$i]['edit_url'] = $url;
-        $url = Horde::url('users/editAlias.php');
-        $url = Horde_Util::addParameter($url, 'address', $id);
-        $url = Horde_Util::addParameter($url, 'section', $section);
-        $addresses[$i]['add_alias_url'] = $url;
-        $url = Horde::url('users/editForward.php');
-        $url = Horde_Util::addParameter($url, 'address', $id);
-        $url = Horde_Util::addParameter($url, 'section', $section);
-        $addresses[$i]['add_forward_url'] = $url;
+    switch ($type) {
+    case 'alias':
+        $address['edit_url'] = Horde::url('users/editAlias.php')
+            ->add(array('alias' => $id, 'section' => $section));
+        $address['add_alias_url'] = $address['add_forward_url'] = false;
+        break;
+    case 'forward':
+        $address['edit_url'] = Horde::url('users/editForward.php')
+            ->add(array('forward' => $id, 'section' => $section));
+        $address['add_alias_url'] = $address['add_forward_url'] = false;
+        break;
+    default:
+        $params = array('address' => $id, 'section' => $section);
+        $address['edit_url'] = Horde::url('users/edit.php')
+            ->add($params);
+        $address['add_alias_url'] = Horde::url('users/editAlias.php')
+            ->add($params);
+        $address['add_forward_url'] = Horde::url('users/editForward.php')
+            ->add($params);
+        break;
     }
-    $url = Horde::url('users/delete.php');
     $currentAddress = $address['address'];
-    if(!isset($currentAddress) || empty($currentAddress)) {
+    if (empty($currentAddress)) {
         $currentAddress = $address['user_name'] . $address['domain'];
     }
-    $url = Horde_Util::addParameter($url, 'address', $currentAddress);
-    //$addresses[$i]['del_url'] = Horde_Util::addParameter($url, 'address', $id);
-    $addresses[$i]['del_url'] = Horde_Util::addParameter($url, 'section', $section);
-    //$url = Horde::url('users/edit.php');
-    //$addresses[$i]['view_url'] = Horde_Util::addParameter($url, 'address', $address['user_name']);
+    $address['del_url'] = $url = Horde::url('users/delete.php')
+        ->add(array('address' => $currentAddress, 'section' => $section));
 
-    if($type === 'alias') {
-        $url = Horde::url('users/editAlias.php');
-        $url = Horde_Util::addParameter($url, 'alias', $id);
-        $url = Horde_Util::addParameter($url, 'section', $section);
-        $addresses[$i]['view_url'] = $url;
-    } elseif ($type === 'forward') {
-        $url = Horde::url('users/editForward.php');
-        $url = Horde_Util::addParameter($url, 'forward', $id);
-        $url = Horde_Util::addParameter($url, 'section', $section);
-        $addresses[$i]['view_url'] = $url;
-    } else {
-        $url = Horde::url('users/edit.php');
-        $url = Horde_Util::addParameter($url, 'address', $id);
-        $url = Horde_Util::addParameter($url, 'section', $section);
-        $addresses[$i]['view_url'] = $url;
+    switch ($type) {
+    case 'alias':
+        $address['view_url'] = Horde::url('users/editAlias.php')
+            ->add(array('alias' => $id, 'section' => $section));
+        break;
+    case 'forward':
+        $address['view_url'] = Horde::url('users/editForward.php')
+            ->add(array('forward' => $id, 'section' => $section));
+        break;
+    default:
+        $address['view_url'] = Horde::url('users/edit.php')
+            ->add(array('address' => $id, 'section' => $section));
+        break;
     }
-    $addresses[$i]['type'] = $types[$address['type']]['singular'];
-    $addresses[$i]['status'] = $vilma->driver->getUserStatus($address);
-}
-
-/* Set up the template action links. */
-if ($vilma->driver->isBelowMaxUsers($curdomain['domain_name'])) {
-    $url = Horde::url('users/edit.php');
-    $maxusers = '';
-} else {
-    $maxusers = _("Maximum Users");
+    $address['type'] = $types[$address['type']]['singular'];
+    $address['status'] = $vilma->driver->getUserStatus($address);
 }
 
-$url = Horde::url('virtuals/edit.php');
-
 /* Set up the template fields. */
 $template = $injector->createInstance('Horde_Template');
 $template->setOption('gettext', true);
-$template->set('addresses', $addresses, true);
-$template->set('maxusers', $maxusers, true);
+$template->set('addresses', $addresses);
+if (!$vilma->driver->isBelowMaxUsers($curdomain['domain_name'])) {
+    $template->set('maxusers', _("Maximum Users"));
+}
 $template->set('menu', Horde::menu());
 $template->set('tabs', $tabs->render());
 
index 7253307..d80dc82 100644 (file)
@@ -13,17 +13,24 @@ $vilma = Horde_Registry::appInit('vilma');
 
 /* Only admin should be using this. */
 if (!$registry->isAdmin()) {
-    $registry->authenticateFailure('vilma', $e);
+    $registry->authenticateFailure('vilma');
 }
 
 $vars = Horde_Variables::getDefaultVariables();
-$virtual_id = $vars->get('virtual_id');
-$formname = $vars->get('formname');
+$virtual_id = $vars->virtual_id;
+$formname = $vars->formname;
 
 $virtual = $vilma->driver->getVirtual($virtual_id);
 $domain = Vilma::stripDomain($virtual['virtual_email']);
 $domain = $vilma->driver->getDomainByName($domain);
 
+if ($vars->submitbutton == _("Do not delete")) {
+    $notification->push(_("Virtual email not deleted."), 'horde.message');
+    Horde::url('virtuals/index.php')
+        ->add('domain_id', $domain['domain_id'])
+        ->redirect();
+}
+
 $form = new Horde_Form($vars, _("Delete Virtual Email Address"));
 
 /* Set up the form. */
@@ -31,38 +38,30 @@ $form->setButtons(array(_("Delete"), _("Do not delete")));
 $form->addHidden('', 'virtual_id', 'text', false);
 $form->addVariable(sprintf(_("Delete the virtual email address \"%s\" => \"%s\"?"), $virtual['virtual_email'], $virtual['virtual_destination']), 'description', 'description', false);
 
-if ($vars->get('submitbutton') == _("Delete")) {
-    if ($form->validate($vars)) {
-        $form->getInfo($vars, $info);
+if ($vars->submitbutton == _("Delete") &&
+    $form->validate($vars)) {
+    $form->getInfo($vars, $info);
+    try {
         $delete = $vilma->driver->deleteVirtual($info['virtual_id']);
-        if (is_a($delete, 'PEAR_Error')) {
-            Horde::logMessage($delete, 'ERR');
-            $notification->push(sprintf(_("Error deleting virtual email. %s."), $delete->getMessage()), 'horde.error');
-        } else {
-            $notification->push(_("Virtual email deleted."), 'horde.success');
-            Horde::url('virtuals/index.php')
-                ->add('domain_id', $domain['domain_id'])
-                ->redirect();
-        }
+        $notification->push(_("Virtual email deleted."), 'horde.success');
+        Horde::url('virtuals/index.php', true)
+            ->add('domain_id', $domain['domain_id'])
+            ->redirect();
+    } catch (Exception $e) {
+        Horde::logMessage($e);
+        $notification->push(sprintf(_("Error deleting virtual email. %s."), $e->getMessage()), 'horde.error');
     }
-} elseif ($vars->get('submitbutton') == _("Do not delete")) {
-    $notification->push(_("Virtual email not deleted."), 'horde.message');
-    Horde::url('virtuals/index.php')
-        ->add('domain_id', $domain['domain_id'])
-        ->redirect();
 }
 
 /* Render the form. */
-require_once 'Horde/Form/Renderer.php';
-$renderer = &new Horde_Form_Renderer();
+$renderer = new Horde_Form_Renderer();
+
+$template = $injector->createInstance('Horde_Template');
 
 Horde::startBuffer();
 $form->renderActive($renderer, $vars, 'delete.php', 'post');
-$main = Horde::endBuffer();
-
-$template = $injector->createInstance('Horde_Template');
-$template->set('main', $main);
-$template->set('menu', Vilma::getMenu('string'));
+$template->set('main', Horde::endBuffer());
+$template->set('menu', Horde::menu());
 
 Horde::startBuffer();
 $notification->notify(array('listeners' => 'status'));
index f1cd4b0..1c0323b 100644 (file)
@@ -13,14 +13,14 @@ $vilma = Horde_Registry::appInit('vilma');
 
 /* Only admin should be using this. */
 if (!$registry->isAdmin() && !Vilma::isDomainAdmin()) {
-    $registry->authenticateFailure('vilma', $e);
+    $registry->authenticateFailure('vilma');
 }
 
 $domain = Vilma::getDomain();
 $vars = Horde_Variables::getDefaultVariables();
-$virtual_id = $vars->get('virtual_id');
-$user = $vars->get('user');
-$formname = $vars->get('formname');
+$virtual_id = $vars->virtual_id;
+$user = $vars->user;
+$formname = $vars->formname;
 
 /* Check if a form is being edited. */
 $editing = false;
@@ -30,7 +30,7 @@ if ($virtual_id && !$formname) {
 }
 
 if (empty($domain)) {
-    $domain = Vilma::stripDomain($vars->get('virtual_destination'));
+    $domain = Vilma::stripDomain($vars->virtual_destination);
 }
 $users = $vilma->driver->getUsers($domain);
 $user_list = array();
@@ -39,7 +39,7 @@ foreach ($users as $user) {
     $user_list[$user['user_name']] = $virtual_destination;
 }
 
-$form = new Horde_Form($vars, ($editing) ? _("Edit Virtual Email Address") : _("New Virtual Email Address"));
+$form = new Horde_Form($vars, $editing ? _("Edit Virtual Email Address") : _("New Virtual Email Address"));
 
 /* Set up the form. */
 $form->setButtons(true, true);
@@ -50,9 +50,8 @@ $var = &$form->addVariable(_("Destination type"), 'destination_type', 'enum',
                            true, false, null,
                            array(array('local' => _("Local user"),
                                        'remote' => _("Remote address"))));
-$action = Horde_Form_Action::factory('reload');
-$var->setAction($action);
-if ($vars->get('destination_type') == 'remote') {
+$var->setAction(Horde_Form_Action::factory('reload'));
+if ($vars->destination_type == 'remote') {
     $form->addVariable(_("Remote e-mail address"), 'virtual_destination',
                        'email', true, false);
 } else {
@@ -66,29 +65,28 @@ if ($form->validate($vars)) {
     if ($info['destination_type'] == 'remote') {
         $info['virtual_destination'] = Horde_String::lower($info['virtual_destination']);
     }
-    $virtual_id = $vilma->driver->saveVirtual($info, $domain);
-    if (is_a($virtual_id, 'PEAR_Error')) {
-        Horde::logMessage($virtual_id, 'ERR');
-        $notification->push(sprintf(_("Error saving virtual email. %s."), $virtual_id->getMessage()), 'horde.error');
-    } else {
+    try {
+        $virtual_id = $vilma->driver->saveVirtual($info, $domain);
         $notification->push(_("Virtual email saved."), 'horde.success');
-        Horde::url('virtuals/index.php')
+        Horde::url('virtuals/index.php', true)
             ->add('user', $info['virtual_destination'])
             ->redirect();
+    } catch (Exception $e) {
+        Horde::logMessage($e);
+        $notification->push(sprintf(_("Error saving virtual email. %s."), $e->getMessage()), 'horde.error');
     }
 }
 
 /* Render the form. */
-require_once 'Horde/Form/Renderer.php';
 $renderer = new Horde_Form_Renderer();
 
+$template = $injector->createInstance('Horde_Template');
+
 Horde::startBuffer();
 $form->renderActive($renderer, $vars, 'edit.php', 'post');
-$main = Horde::endBuffer();
+$template->set('main', Horde::endBuffer());
 
-$template = $injector->createInstance('Horde_Template');
-$template->set('main', $main);
-$template->set('menu', Vilma::getMenu('string'));
+$template->set('menu', Horde::menu());
 
 Horde::startBuffer();
 $notification->notify(array('listeners' => 'status'));
index 73a4ffe..e49ce90 100644 (file)
@@ -13,28 +13,28 @@ $vilma = Horde_Registry::appInit('vilma');
 
 /* Only admin should be using this. */
 if (!$registry->isAdmin() && !Vilma::isDomainAdmin()) {
-    $registry->authenticateFailure('vilma', $e);
+    $registry->authenticateFailure('vilma');
 }
 
 $user = Horde_Util::getFormData('user');
-if (!empty($user)) {
-    $virtuals = $vilma->driver->getVirtuals($user);
-    $domain = Vilma::stripDomain($user);
-} else {
-    $domain = Vilma::getDomain();
-    $virtuals = $vilma->driver->getVirtuals($domain);
-}
-
-if (is_a($virtuals, 'PEAR_Error')) {
-    $notification->push($virtuals);
-    Horde::url('index.php')->redirect();
+try {
+    if (!empty($user)) {
+        $virtuals = $vilma->driver->getVirtuals($user);
+        $domain = Vilma::stripDomain($user);
+    } else {
+        $domain = Vilma::getDomain();
+        $virtuals = $vilma->driver->getVirtuals($domain);
+    }
+} catch (Exception $e) {
+    $notification->push($e);
+    Horde::url('index.php', true)->redirect();
 }
 
 foreach ($virtuals as $id => $virtual) {
-    $url = Horde::url('virtuals/edit.php');
-    $virtuals[$id]['edit_url'] = Horde_Util::addParameter($url, 'virtual_id', $virtual['virtual_id']);
-    $url = Horde::url('virtuals/delete.php');
-    $virtuals[$id]['del_url'] = Horde_Util::addParameter($url, 'virtual_id', $virtual['virtual_id']);
+    $virtuals[$id]['edit_url'] = Horde::url('virtuals/edit.php')
+        ->add('virtual_id', $virtual['virtual_id']);
+    $virtuals[$id]['del_url'] = Horde::url('virtuals/delete.php')
+        ->add('virtual_id', $virtual['virtual_id']);
 }
 
 $template = $injector->createInstance('Horde_Template');
@@ -44,10 +44,16 @@ $template->set('virtuals', $virtuals, true);
 /* Set up the template action links. */
 $actions = array();
 $url = Horde::url('virtuals/edit.php');
-$actions['new_url'] = (Vilma::isDomainAdmin() ? $url : Horde_Util::addParameter($url, 'domain', $domain));
+if (!Vilma::isDomainAdmin()) {
+    $url->add('domain', $domain);
+}
+$actions['new_url'] = $url;
 $actions['new_text'] = _("New Virtual Email");
 $url = Horde::url('users/index.php');
-$actions['users_url'] = (Vilma::isDomainAdmin() ? $url : Horde_Util::addParameter($url, 'domain', $domain));
+if (!Vilma::isDomainAdmin()) {
+    $url->add('domain', $domain);
+}
+$actions['users_url'] = $url;
 $actions['users_text'] = _("Users");
 $template->set('actions', $actions);