Other half of the changes from Daniel Collins (missed from the last commit)
authorBen Klang <ben@alkaloid.net>
Thu, 17 Dec 2009 19:59:25 +0000 (14:59 -0500)
committerBen Klang <ben@alkaloid.net>
Thu, 17 Dec 2009 19:59:25 +0000 (14:59 -0500)
vilma/lib/Driver.php
vilma/lib/Driver/qmailldap.php
vilma/templates/users/index.html
vilma/users/delete.php
vilma/users/index.php

index 240dc50..14b4f85 100644 (file)
@@ -6,6 +6,7 @@
  * 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>
  * @package Vilma
  */
 class Vilma_Driver {
@@ -94,6 +95,7 @@ class Vilma_Driver {
      */
     function getAddressInfo($address, $type = 'all')
     {
+        Horde::logMessage("Get Addresses Called for $domain with type $type and key $key", __FILE__, __LINE__, PEAR_LOG_DEBUG);
         $domain = Vilma::stripDomain($address);
         $addresses = $this->getAddresses($domain, $type);
         foreach($addresses as $addrinfo) {
@@ -156,6 +158,80 @@ class Vilma_Driver {
         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), __FILE__, __LINE__, PEAR_LOG_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), __FILE__, __LINE__, PEAR_LOG_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), __FILE__, __LINE__, PEAR_LOG_DEBUG);
+        $result = $this->_saveForward($info);
+        if (is_a($result, 'PEAR_Error')) {
+          return $result;
+        }
+        
+        return true;
+    }
+    
+    /* 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.
+     */
+    function deleteForward(&$info)
+    {
+        Horde::logMessage("deleteForward called with info: " . print_r($info, true), __FILE__, __LINE__, PEAR_LOG_DEBUG);
+        $result = $this->_deleteForwrd($info);
+        if (is_a($result, 'PEAR_Error')) {
+          return $result;
+        }
+        
+        return true;
+    }
+    
     function saveUser(&$info)
     {
         $create = false;
index 9dea67b..3ff99f2 100644 (file)
@@ -114,6 +114,7 @@ class Vilma_Driver_qmailldap extends Vilma_Driver {
     function getAddresses($domain, $type = 'all', $key = 'user_name',
                           $direction = 0)
     {
+        Horde::logMessage("Get Addresses Called for $domain with type $type and key $key", __FILE__, __LINE__, PEAR_LOG_DEBUG);
         $addresses = array();
         if ($type == 'all' || $type == 'user') {
             $users = $this->_getUsers($domain);
@@ -483,6 +484,7 @@ class Vilma_Driver_qmailldap extends Vilma_Driver {
      */
     function getAddressInfo($address, $type = 'all')
     {
+        Horde::logMessage("Get Addresses Called for $address with type $type and key $key", __FILE__, __LINE__, PEAR_LOG_DEBUG);
         if ($type != 'alias') {
             return parent::getAddressInfo($address, $type);
         } else {
@@ -493,7 +495,7 @@ class Vilma_Driver_qmailldap extends Vilma_Driver {
                 // Add each objectClass from parameters
                 $filter .= '(objectClass=' . $objectclass . ')';
             }
-            $filter .= '(mailAlternateAddress= ' . $address . ')';
+            $filter .= '(mailAlternateAddress=' . $address . ')';
             $filter .= ')'; // End filter
             Horde::logMessage($filter, __FILE__, __LINE__, PEAR_LOG_DEBUG);
             $res = @ldap_search($this->_ldap, $this->_ldapparams['basedn'], $filter);
@@ -668,7 +670,7 @@ class Vilma_Driver_qmailldap extends Vilma_Driver {
             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; 
     }
 
@@ -716,65 +718,322 @@ class Vilma_Driver_qmailldap extends Vilma_Driver {
     }
 
     /**
-     * Modifies alias data on the backend.
+     * 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.
-     * @param string $mode    The operation requested: add, update, delete.
      *
      * @return mixed  True on success or PEAR error otherwise.
      */
-    function _savealias($info,$mode = null)
+    function _saveAlias($info)
     {
-        if ($mode == 'delete') {
-            $address = $info;
-
-            $user_info = $this->searchForAliases($address);
-            $aliasesList = $user_info[0]['mailalternateaddress'];
-            if (is_a($user_info, 'PEAR_Error') || ($res['count'] === 0) ) { 
-                return PEAR::raiseError(_("Error reading address information from backend."));
-            }
-            $addrinfo = $this->getAddressInfo($address);
-            if (is_a($addrinfo, 'PEAR_Error')) {
-                return $addrinfo;
+        Horde::logMessage("_saveAlias called with info: " . print_r($info, true), __FILE__, __LINE__, PEAR_LOG_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), __FILE__, __LINE__, PEAR_LOG_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), __FILE__, __LINE__, PEAR_LOG_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."));
             }
-            $type = $addrinfo['type'];
-            $addrinfo = $this->getAddressInfo($address,$type);
-            if (is_a($addrinfo, 'PEAR_Error')) {
-                return $addrinfo;
+            $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), __FILE__, __LINE__, PEAR_LOG_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), __FILE__, __LINE__, PEAR_LOG_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), __FILE__, __LINE__, PEAR_LOG_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."));
             }
-            $objectClassData = null;
-            if(isset($user_info[0]['objectclass'])) {
-                $objectClassData = $user_info[0]['objectclass'];
+            $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), __FILE__, __LINE__, PEAR_LOG_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), __FILE__, __LINE__, PEAR_LOG_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), __FILE__, __LINE__, PEAR_LOG_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."));
             }
-            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."));
-                }
-                $tmp = array();
-                $key = null;
-                foreach($aliasesList as $key => $val) {
-                    if($val != $address) {
-                        array_push($tmp,$val);
-                    }
-                }
-                $entry["mailalternateaddress"] = $tmp;
-                
-                $rdn = 'mail=' . $addrinfo['destination'];
-                $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;
-                }
+            $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), __FILE__, __LINE__, PEAR_LOG_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), __FILE__, __LINE__, PEAR_LOG_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), __FILE__, __LINE__, PEAR_LOG_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  PEAR::raiseError(_("Unable to save user information."));
+        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)
     {
index f4dad37..68a2d93 100644 (file)
      <a href="<tag:addresses.edit_url />"><tag:images.edit /></a>
    </if:addresses.edit_url>
    <a href="<tag:addresses.del_url />"><tag:images.delete /></a>
+   <if:addresses.add_alias_url>
+     <a href="<tag:addresses.add_alias_url />">+Alias</a>
+   </if:addresses.add_alias_url>
+   <if:addresses.add_forward_url>
+     <a href="<tag:addresses.add_forward_url />">+Forward</a>
+   </if:addresses.add_forward_url>
   </td>
   <td>
    <if:addresses.view_url>
index 80c9c16..d44ca5f 100644 (file)
@@ -80,14 +80,14 @@ $domain = $vilma_driver->getDomainByName($domain);
 $vars->set('domain', $domain);
 $vars->set('mode', 'edit');
 
-$form = new Horde_Form($vars, _("Delete User"));
+$form = new Horde_Form($vars, _("Delete " . $type));
 /* Set up the form. */
 $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 user \"%s\"";
+$desc = "Delete $type \"%s\"";
 $sub = " and all dependencies?";
 $tot = $aliasesCount + $groupsCount + $forwardsCount;
 if($tot > 0) {
@@ -109,15 +109,38 @@ if ($vars->get('submitbutton') == _("Delete")) {
     if($type == 'alias') {
         if ($form->validate($vars)) {
             $form->getInfo($vars, $info);
-            $delete = $vilma_driver->_savealias($address['address'],'delete');
+            $deleteInfo = array();
+             $deleteInfo['address'] = $address['destination'];
+             $deleteInfo['alias'] = $user_id;
+             $delete = $vilma_driver->deleteAlias($deleteInfo);
             if (is_a($delete, 'PEAR_Error')) {
                 Horde::logMessage($delete, __FILE__, __LINE__, PEAR_LOG_ERR);
-                $notification->push(sprintf(_("Error deleting user. %s."), $delete->getMessage()), 'horde.error');
+                 $notification->push(sprintf(_("Error deleting alias. %s."), $delete->getMessage()), 'horde.error');
+                 $url = Util::addParameter(Horde::applicationUrl('users/index.php'), 'domain_id', $domain['id'], false);
+                 header('Location: ' . $url);
+                 exit;
+             } else {
+                 $notification->push(_("Alias deleted."), 'horde.success');
+                 $url = Util::addParameter(Horde::applicationUrl('users/index.php'), 'domain_id', $domain['id'], false);
+                 header('Location: ' . $url);
+                 exit;
+             }
+         }
+     } 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, __FILE__, __LINE__, PEAR_LOG_ERR);
+                $notification->push(sprintf(_("Error deleting forward. %s."), $delete->getMessage()), 'horde.error');
                 $url = Horde_Util::addParameter(Horde::applicationUrl('users/index.php'), 'domain_id', $domain['id'], false);
                 header('Location: ' . $url);
                 exit;
             } else {
-                $notification->push(_("User deleted."), 'horde.success');
+                $notification->push(_("Forward deleted."), 'horde.success');
                 $url = Horde_Util::addParameter(Horde::applicationUrl('users/index.php'), 'domain_id', $domain['id'], false);
                 header('Location: ' . $url);
                 exit;
@@ -135,7 +158,7 @@ if ($vars->get('submitbutton') == _("Delete")) {
                 header('Location: ' . $url);
                 exit;
             } else {
-                $notification->push(_("User deleted."), 'horde.success');
+                $notification->push(_("$type deleted."), 'horde.success');
                 $url = Horde_Util::addParameter(Horde::applicationUrl('users/index.php'), 'domain_id', $domain['id'], false);
                 header('Location: ' . $url);
                 exit;
index e080897..a3438b7 100644 (file)
@@ -51,12 +51,34 @@ $types = Vilma::getUserMgrTypes();
 foreach ($addresses as $i => $address) {
     $type = $address['type'];
     $id = $address['id'];
-    $url = Horde::applicationUrl('users/edit.php');
-    $url = Horde_Util::addParameter($url, 'address', $id);
+
     if($type === 'alias') {
-        $addresses[$i]['edit_url'] = '';
+        $url = Horde::applicationUrl('users/editAlias.php');
+        $url = Util::addParameter($url, 'alias', $id);
+        $url = 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::applicationUrl('users/editForward.php');
+        $url = Util::addParameter($url, 'forward', $id);
+        $url = Util::addParameter($url, 'section', $section);
+        $addresses[$i]['edit_url'] = $url;
+        $addresses[$i]['add_alias_url'] = false;
+        $addresses[$i]['add_forward_url'] = false;
     } else {
-        $addresses[$i]['edit_url'] = Horde_Util::addParameter($url, 'section', $section);
+        $url = Horde::applicationUrl('users/edit.php');
+        $url = Util::addParameter($url, 'address', $id);
+        $url = Util::addParameter($url, 'section', $section);
+        $addresses[$i]['edit_url'] = $url;
+        $url = Horde::applicationURL('users/editAlias.php');
+        $url = Util::addParameter($url, 'address', $id);
+        $url = Util::addParameter($url, 'section', $section);
+        $addresses[$i]['add_alias_url'] = $url;
+        $url = Horde::applicationURL('users/editForward.php');
+        $url = Util::addParameter($url, 'address', $id);
+        $url = Util::addParameter($url, 'section', $section);
+        $addresses[$i]['add_forward_url'] = $url;
     }
     $url = Horde::applicationUrl('users/delete.php');
     $currentAddress = $address['address'];
@@ -68,12 +90,22 @@ foreach ($addresses as $i => $address) {
     $addresses[$i]['del_url'] = Horde_Util::addParameter($url, 'section', $section);
     //$url = Horde::applicationUrl('users/edit.php');
     //$addresses[$i]['view_url'] = Horde_Util::addParameter($url, 'address', $address['user_name']);
-    $url = Horde::applicationUrl('users/edit.php');
-    $url = Horde_Util::addParameter($url, 'address', $id);
+
     if($type === 'alias') {
-        $addresses[$i]['view_url'] = '';
+        $url = Horde::applicationUrl('users/editAlias.php');
+        $url = Util::addParameter($url, 'alias', $id);
+        $url = Util::addParameter($url, 'section', $section);
+        $addresses[$i]['view_url'] = $url;
+    } elseif ($type === 'forward') {
+        $url = Horde::applicationUrl('users/editForward.php');
+        $url = Util::addParameter($url, 'forward', $id);
+        $url = Util::addParameter($url, 'section', $section);
+        $addresses[$i]['view_url'] = $url;
     } else {
-        $addresses[$i]['view_url'] = Horde_Util::addParameter($url, 'section', $section);
+        $url = Horde::applicationUrl('users/edit.php');
+        $url = Util::addParameter($url, 'address', $id);
+        $url = Util::addParameter($url, 'section', $section);
+        $addresses[$i]['view_url'] = $url;
     }
     $addresses[$i]['type'] = $types[$address['type']]['singular'];
     $addresses[$i]['status'] = $vilma_driver->getUserStatus($address);