<?php

require_once HORDE_BASE . '/lib/Auth/sql.php';

/**
 * The Auth_sqlquery class provides a sql implementation of the Horde
 * authentication system with the possibility to set custom-made queries.
 * Only the "authenticate" capability is implemented for the moment.
 *
 * Required parameters:
 * ====================
 *   'database'  --  The name of the database.
 *   'hostspec'  --  The hostname of the database server.
 *   'query_auth'    A custom query to be used to authenticate the user.
 *                   Some special tokens can be used in this string. They are
 *                   replaced at the _authenticate() stage :
 *                     - "\L" will be replaced by the user's login
 *                     - "\P" will be replaced by the user's password.
 *                   Eg: "SELECT * FROM users WHERE uid = \L
 *                                            AND passwd = \P
 *                                            AND billing = 'paid'
 *   'password'  --  The password associated with 'username'.
 *   'phptype'   --  The database type (ie. 'pgsql', 'mysql, etc.).
 *   'protocol'  --  The communication protocol ('tcp', 'unix', etc.).
 *   'username'  --  The username with which to connect to the database.
 *
 * Required by some database implementations:
 * ==========================================
 *   'options'  --  Additional options to pass to the database.
 *   'port'     --  The port on which to connect to the database.
 *   'tty'      --  The TTY on which to connect to the database.
 *
 *
 * $Horde: horde/lib/Auth/customsql.php,v 1.2 2003/07/10 21:42:55 slusarz Exp $
 *
 * Copyright 2002 Ronnie Garcia <ronnie@mk2.net>
 *
 * See the enclosed file COPYING for license information (LGPL). If you
 * did not receive this file, see http://www.fsf.org/copyleft/lgpl.html.
 *
 * @author  Ronnie Garcia <ronnie@mk2.net>
 * @author  Chuck Hagenbuch <chuck@horde.org>
 * @version $Revision: 1.2 $
 * @since   Horde 1.3
 * @package horde.auth
 */
class Auth_sqlquery extends Auth_sql {

    /**
     * An array of capabilities, so that the driver can report which
     * operations it supports and which it doesn't.
     *
     * @var array $capabilities
     */
    var $capabilities = array('add'         => false,
                              'update'      => false,
                              'remove'      => false,
                              'list'        => false,
                              'transparent' => false,
                              'loginscreen' => false);

    /**
     * Constructs a new SQL authentication object.
     *
     * @access public
     *
     * @param optional array $params  A hash containing connection parameters.
     */
    function Auth_sqlquery($params = array())
    {
        $this->_params = $params;

        if (!isset($this->_params['query_auth'])) {
            Horde::fatal(new PEAR_Error(_("Required 'query_auth' not specified in authentication configuration.")), __FILE__, __LINE__);
        }
    }

    /**
     * Find out if a set of login credentials are valid.
     *
     * @access private
     *
     * @param string $userID      The userID to check.
     * @param array $credentials  The credentials to use.
     *
     * @return boolean  Whether or not the credentials are valid.
     */
    function _authenticate($userID, $credentials)
    {
        /* _connect() will die with Horde::fatal() upon failure. */
        $this->_connect();

        /* Build a custom query, based on the config file */
        $query = $this->_params['query_auth'];
        $query = str_replace("\L", $this->_db->quote($userID), $query);
        $query = str_replace("\P", $this->_db->quote(md5($credentials['password'])), $query);

        $result = $this->_db->query($query);
        if (!DB::isError($result)) {
            $row = $result->fetchRow(DB_GETMODE_ASSOC);
            /* if we have at least one returned row, then the user is valid */
            if (is_array($row)) {
                $result->free();
                return true;
            } else {
                $result->free();
                $this->_setAuthError();
                return false;
            }
        } else {
            $this->_setAuthError();
            return false;
        }
    }
}
