<?php
/**
 * $Horde: forwards/lib/Driver/sql.php,v 1.10 2003/08/25 18:28:42 jan Exp $
 *
 * Copyright 2001-2003 Ilya Krel and Mike Cochrane
 *
 * See the enclosed file LICENSE for license information (BSD). If you
 * did not receive this file, see http://www.horde.org/licenses/bsdl.php.
 *
 * Forwards_Driver_sql:: implements the Forwards_Driver API for SQL servers.
 *
 * @author  Ilya Krel <mail@krel.org.org>
 * @author  Mike Cochrane <mike@graftonhall.co.nz>
 * @version $Revision: 1.10 $
 * @since   Forwards 2.1
 * @package forwards
 */
class Forwards_Driver_sql extends Forwards_Driver {

    /** file pointer to the sql connection. */
    var $_db;

    /** error string returned to user if an eror occurs. */
    var $_err_str;

    /** boolean which contains state of sql connection */
    var $_connected = false;

    var $params;

    /**
     * Constructs a new sql Forwards_Driver object.
     *
     * @param array  $params        A hash containing connection parameters.
     */
    function Forwards_Driver_sql($params = null)
    {
        if (is_null($params)) {
            $params = Horde::getDriverConfig('', 'sql');
        }
        $this->_params = $params;
    }

    /**
     * Do an sql connect and login as user with privilege to change passwd.
     *
     * @return   boolean   True or False based on success of connect
     */
    function _connect()
    {
        if (!$this->_connected) {
            Horde::assertDriverConfig($this->_params, 'server',
                array('phptype', 'hostspec', 'username', 'database', 'table'),
                'authentication SQL');

            /* Connect to SQL server using supplied parameters. */
            include_once 'DB.php';
            $this->_db = &DB::connect($this->_params,
                                     array('persistent' => !empty($this->_params['persistent'])));
            if (DB::isError($this->_db)) {
                Horde::fatal(new PEAR_Error(_("Unable to connect to SQL server.")), __FILE__, __LINE__);
            }

            /* Enable the "portability" option. */
            $this->_db->setOption('optimize', 'portability');
            $this->_connected = true;
        }

        return true;
    }

    /**
     * Disconnect from the SQL server and clean up the connection.
     *
     * @return boolean true on success, false on failure.
     */
    function _disconnect()
    {
        if ($this->_connected) {
            $this->_connected = false;
            return $this->_db->disconnect();
        }

        return true;
    }

    /**
     * Begins forwarding of mail for a user.
     *
     * @param string        $user     The username to enable forwarding for.
     * @param string        $realm    The realm of the user.
     * @param string        $pass     The password of the user.
     *
     * @param string        $target   The email address that mail should
     *                                be forwarded to.
     *
     * @param optional boolean $keeplocal A flag that if true causes a
     *                                    copy of forwarded email to be
     *                                     kept in the local mailbox.
     *
     * @return boolean  Returns true on success, false on error.
     */
    function enableForwarding($user, $realm, $password, $target, $keeplocal)
    {
        // set forwarding flag
        /* _connect() will die with Horde::fatal() upon failure. */
        $this->_connect();
        $local_target=$user . '@' . $realm;

        /* Build the SQL query. */
        $query = 'UPDATE ' . $this->_params['table'];
        $query .= ' SET ' . $this->_params['forward'] . ' = ' . $this->_db->quote("y");
        $query .= ' WHERE ' . $this->_params['user_col'] . ' = ' . $this->_db->quote($user);
        $query .= ' AND ' . $this->_params['pass_col'] . ' = ' . $this->_db->quote(md5($password));

        $query1 = 'UPDATE ' . $this->_params['table'];
        if ($keeplocal === 'ON') {
            if(!strstr($target,$local_target)) {
                $query1 .= ' SET ' . $this->_params['altemail'] . ' = ' .
                    $this->_db->quote($target . ',' . $local_target);
            }
        } else {
            $query1 .= ' SET ' . $this->_params['altemail'] . ' = ' . $this->_db->quote($target);
        }
        $query1 .= ' WHERE ' . $this->_params['user_col'] . ' = ' . $this->_db->quote($user);
        $query1 .= ' and ' . $this->_params['pass_col'] . ' = ' . $this->_db->quote(md5($password));

        /* Execute the query. */
        $result = $this->_db->query($query);
        $result1 = $this->_db->query($query1);

        if (!DB::isError($result) && !DB::isError($result1)) {
            if ($result === DB_OK && $result1 === DB_OK) {
                $this->_disconnect();
                return true;
            } else {
                $this->_disconnect();
                return false;
            }
        } else {
            $this->_disconnect();
            return false;
        }
        $this->_disconnect();
        return false;
    }

    /**
     * Stops forwarding of mail for a user.
     *
     * @param string        $user      The username of the user.
     * @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, $password)
    {
        // set forwarding flag
        /* _connect() will die with Horde::fatal() upon failure. */
        $this->_connect();

        /* Build the SQL query. */
        $query = 'UPDATE ' . $this->_params['table'];
        $query .= ' SET ' . $this->_params['forward'] . ' = ' . $this->_db->quote("n");
        $query .= ' ,  ' . $this->_params['altemail'] . ' = ' . $this->_db->quote("");
        $query .= ' WHERE ' . $this->_params['user_col'] . ' = ' . $this->_db->quote($user);
        $query .= ' and ' . $this->_params['pass_col'] . ' = ' . $this->_db->quote(md5($password));

        /* Execute the query. */
        $result = $this->_db->query($query);

        if (!DB::isError($result)) {
            if ($result === DB_OK) {
                $this->_disconnect();
                return true;
            } else {
                $this->_disconnect();
                return false;
            }
        } else {
            $this->_disconnect();
            return false;
        }
        $this->_disconnect();
        return false;
    }

    /**
     * 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 for the user.
     */
    function isEnabledForwarding($user, $realm, $password)
    {
        // get current details
        $current_details = $this->_getUserDetails($user, $realm, $password);
        if ($current_details === false) {
            //$this->_err_str = _("Not able to retrieve current details.");
            return false;
        }

        // check forwarding flag
        if ($current_details[$this->_params['forward']] === 'y' ||
             $current_details[$this->_params['forward']] === 'Y') {
            return true;
        } else {
            return false;
        }
    }

    /**
     * Returns true if a local copy of forwarded messages is being kept
     *
     * @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 retain local copy is enabled
     *                      else false.
     */
    function isKeepLocal($user, $realm, $password)
    {
        // get current details
        $current_details = $this->_getUserDetails($user, $realm, $password);
        if ($current_details === false) {
            //$this->_err_str = _("Not able to retrieve current details.");
            return false;
        }

        // check retain copy flag
        if (substr_count($current_details[$this->_params['altemail']], $user . '@' . $realm)) {
            return true;
        } else {
            return false;
        }
    }

    /**
     * Retrieves current target of mail redirection
     *
     * @param string        $user      The username of the user.
     * @param string        $realm    The realm of the user.
     *
     * @return string   A string of current forwarding address or false.
     */
    function currentTarget($user, $realm, $password)
    {
        $searchString = ",$user@$realm";
        $current_details = $this->_getUserDetails($user, $realm, $password);

        // check current forwarding mail address
        $targets = $current_details[$this->_params['altemail']];
        return str_replace($searchString, "", $current_details[$this->_params['altemail']]);
    }

    /**
     * Retreive relevant line from sql server
     *
     * @param   $user            The username for which to retrieve details.
     * @param   $realm           The realm (domain) for the user.
     * @param   $password        The password for user.
     *
     * @return  Mixed            Mysql result resource or (boolean) False.
     */
    function _getUserDetails($user, $realm, $password)
    {
        /* _connect() will die with Horde::fatal() upon failure. */
        $this->_connect();

        /* Build the SQL query. */
        $query = 'SELECT * FROM ' . $this->_params['table'];
        $query .= ' WHERE ' . $this->_params['user_col'] . ' = ' . $this->_db->quote($user);
       $query .= ' AND password = ' . $this->_db->quote(md5($password));

        /* Execute the query. */
        $result = $this->_db->query($query);

        if (!DB::isError($result)) {
            $row = $result->fetchRow(DB_FETCHMODE_ASSOC);

            if (is_array($row)) {
                $this->_disconnect();
                return $row;
            } else {
                $this->_disconnect();
                $result->free();
                return false;
            }
        }
        $this->_disconnect();
        return false;
    }

}
