<?php
/**
 * $Horde: forwards/lib/Driver/ldap.php,v 1.1 2003/07/11 12:28:21 opal Exp $
 *
 * Copyright 2001-2003 Eric Rostetter <eric.rostetter@physics.utexas.edu>
 *
 * See the enclosed file LICENSE for license information (BSD). If you
 * did not receive this file, see http://www.horde.org/bsdl.php.
 *
 * Forwards_Driver_forwards:: implements the Forwards_Driver API for ftp driven
 * dot-forward compliant mail servers.
 *
 * @author  Eric Rostetter <eric.rostetter@physics.utexas.edu>
 * @version $Revision: 1.1 $
 * @package Forwards
 */

class Forwards_Driver_ldap extends Forwards_Driver {

    /** Pointer to the ldap connection. */
    var $_ds;

    /** Hash containing connection parameters. */
    var $_params;

    /** The error string returned to the user if an error occurs. */
    var $err_str;

/**
 * Constructs a new ftp dot-forward Forwards_Driber object.
 *
 * @param array  $params    A hash containing connection parameters.
 */
function Forwards_Driver_ldap($params = array())
{
    $this->_params = $params;
}

    /**
     * Do an ldap connect and bind as the guest user or as the optional userdn.
     *
     * @param    $userdn      The optional dn to use when binding non-anonymously.
     * @param    $oldpassword The optional password for $userdn.
     *
     * @return   boolean   True or False based on success of connect and bind.
     *
     */
    function _connect($userdn = null, $password = null, $realm = 'default') {
        $this->_ds = ldap_connect($this->_params[$realm]['host'], $this->_params[$realm]['port']);
        if (!$this->_ds) {
           return PEAR::raiseError(_("Could not connect to ldap server"));
        }

        if (!is_null($userdn)) {
            $result = @ldap_bind($this->_ds, $userdn, $password);
        } else {
            $result = @ldap_bind($this->_ds);
        }

        if (!$result) {
          return PEAR::raiseError(_("Could not bind to ldap server"));
        }

        return true;
    }

    /**
     * Close the ldap connection.
     */
    function _disconnect() {
        @ldap_close($this->_ds);
    }

/**
 * Check if the realm has a specific configuration.  If not, try to fall
 * back on the default configuration.  If still not a valid configuration
 * then exit with an error.
 *
 * @param string    $realm      The realm of the user, or "default" if none.
 *                              Note: passed by reference so we can change
 *                              it's value!
 *
 */

function check_config(&$realm) {

    // If no realm passed in, or no host config for the realm passed in,
    // then we fall back to the default realm

    if ( empty($realm) || empty($this->_params[$realm]['server']) ) {
       $realm = "default";
    }

    // If still no host/port, then we have a misconfigured module
    if (empty($this->_params[$realm]['host']) ||
        empty($this->_params[$realm]['port']) ) {
            $this->err_str = _("The module is not properly configured!");
            return false;
    }
    return true;
}

    /**
     * Lookup and return the user's dn.
     *
     * @param  $user     The username of the user.
     * @param  $realm    The realm (domain) name of the user.
     * @param  $basedn   The ldap basedn.
     * @param  $uid      The ldap uid.
     *
     * @return string    The ldap dn for the user.
     */
    function _lookupdn($user, $realm) {
        // bind as guest
        $this->_connect();

        // construct search
        $search = $this->_params[$realm]['uid'] . '=' . $user;
        if (!empty($this->_params[$realm]['realm'])) {
            $search .= '@' . $this->_params[$realm]['realm'];
        }

        // get userdn
        $result = ldap_search($this->_ds, $this->_params[$realm]['basedn'], $search);
        $entry = ldap_first_entry($this->_ds, $result);
        if ($entry === false) {
            $this->_disconnect();
            return PEAR::raiseError(_("User not found."));
        }
        $userdn = ldap_get_dn($this->_ds, $entry);

        // disconnect from ldap server
        $this->_disconnect();

        return $userdn;
    }

/**
 * Set the forwards notice up.
 * @param string    $user       The username to enable forwards for.
 * @param string    $realm      The realm of the user.
 * @param string    $target     The message to install.
 * @return boolean  Returns true on success, false on error.
 */

    // Keeplocals is NEVER USED!
    function enableForwarding($user, $realm, $pass, $message, $keeplocal) {

        // Make sure the configuration file is correct
        if (!$this->check_config($realm)) {
            return false;
        }

        // get the user's dn
        if (array_key_exists('userdn', $this->_params[$realm])) {
            $userdn = $this->_params[$realm]['userdn'];
        } else {
            $userdn = $this->_lookupdn($user, $realm);
            if (PEAR::isError($userdn)) {
                return $userdn;
            }
        }

        // connect as the user
        $res = $this->_connect($userdn, $pass, $realm);
        if (PEAR::isError($res)) {
            $this->_disconnect();
            if ($res->getMessage() == _("Could not bind to ldap server")) {
                return PEAR::raiseError(_("Incorect Password"));
            }
            return $res;
        }

	// change the user's forwards.
        $newDetails[$this->_params[$realm]['forwards']] = $message;
        $res = ldap_mod_replace($this->_ds, $userdn, $newDetails);
        $value = $this->_get_forwards($userdn, $this->_params[$realm]['forwards']);
        if (!$res) {
            $res = PEAR::raiseError(ldap_error($this->_ds));
        }

        // disconnect from ldap server
        $this->_disconnect();

        return true;
    }

  function get_forwards($realm = 'default', $user, $pass) {
        // Make sure the configuration file is correct
        if (!$this->check_config($realm)) {
            return false;
        }

        // get the user's dn
        if ( array_key_exists('userdn', $this->_params[$realm])) {
            $userdn = $this->_params[$realm]['userdn'];
        } else {
            $userdn = $this->_lookupdn($user, $realm);
            if (PEAR::isError($userdn)) {
                return $userdn;
            }
        }

        // connect as the user
        $res = $this->_connect($userdn, $pass, $realm);
        if (PEAR::isError($res)) {
            $this->_disconnect();
            if ($res->getMessage() == _("Could not bind to ldap server")) {
                return PEAR::raiseError(_("Incorect Password"));
            }
            return $res;
        }

	$vac = $this->_params[$realm]['forwards'];
	$msg = $this->_get_forwards($userdn, $vac);

        // disconnect from ldap server
        $this->_disconnect();

	return $msg;
  }

  function _get_forwards($userdn, $vac) {
	$sr = ldap_search($this->_ds, $userdn, "$vac=*");
	$entry = ldap_first_entry($this->_ds, $sr);
	if (!$entry) {
	  return false;
        }
	$values = ldap_get_values($this->_ds, $entry, $vac);
	if ($values["count"] == 0) {
	   return false;
        }
	return $values[0];
  }

/**
 * Remove any existing forwards notices.
 *
 * @param string    $user       The user to disable forwards notices for.
 * @param string    $realm      The realm of the user.
 * @param string    $pass       The password of the user.
 *
 * @return boolean  Returns true on success, false on error.
 */

    function disableForwarding($user, $realm, $pass) {

        // Make sure the configuration file is correct
        if (!$this->check_config($realm)) {
            return false;
        }

        // get the user's dn
        if ( array_key_exists('userdn', $this->_params[$realm])) {
            $userdn = $this->_params[$realm]['userdn'];
        } else {
            $userdn = $this->_lookupdn($user, $realm);
            if (PEAR::isError($userdn)) {
                return $userdn;
            }
        }

        // connect as the user
        $res = $this->_connect($userdn, $pass, $realm);
        if (PEAR::isError($res)) {
            $this->_disconnect();
            if ($res->getMessage() == _("Could not bind to ldap server")) {
                return PEAR::raiseError(_("Incorect Password"));
            }
            return $res;
        }

	// del the user's forwards.
	$value = $this->_get_forwards($userdn,
				      $this->_params[$realm]['forwards']);
	$newDetails[$this->_params[$realm]['forwards']] = $value;
        $res = ldap_mod_del($this->_ds, $userdn, $newDetails);
        if (!$res) {
            $res = PEAR::raiseError(ldap_error($this->_ds));
        }

        // disconnect from ldap server
        $this->_disconnect();

        return true;
    }

}

	/**
	 * Retrieves status of mail redirection for a user
	 *
	 * @param string	$user	   The username of the user to check.
	 *
	 * @param string	$realm	  The realm of the user to check.
	 *
	 * @return boolean	Returns true if forwarding is enabled for the user or false if
	 *				  forwarding is currently disabled.
	 */
	function isEnabledForwarding($user, $realm, $pass)
	{
		if ($this->get_forwards($user, $realm, $pass)) {
                   return true;
                }
                else {
                   return false;
                }
	}

?>
