<?php
// vim: set expandtab tabstop=4 shiftwidth=4 foldmethod=marker:
/**
 * Funciones para autenticación de usuarios con Auth de Pear.
 * Con base en {@link http://structio.sourceforge.net/seguidor}
 * que a su vez se basa en
 * {@link http://pear.php.net/manual/en/package.authentication.auth.intro.php}
 *
 * PHP version 5
 *
 * @category  SIVeL
 * @package   SIVeL
 * @author    Vladimir Támara <vtamara@pasosdeJesus.org>
 * @copyright 2004 Dominio público. Sin garantías.
 * @license   http://creativecommons.org/licenses/publicdomain/ Dominio Público. Sin garantías.
 * @version   $Id: aut.php,v 1.32 2009/05/03 12:23:21 vtamara Exp $
 * @link      http://sivel.sf.net
 */

/**
 * Funciones para autenticación de usuarios con Auth de Pear.
 */
require_once "Auth.php";
require_once "DB.php";


/**
 * Formulario de ingreso.
 *
 * @return  Nada
 */
function loginFunction()
{
    echo "<form method=\"post\" action=\"" . 
        htmlspecialchars($_SERVER['PHP_SELF']) . "\">";
    echo "<table border='0'>";
    echo "<tr><td bgcolor='#c0c0c0' colspan='2'>Autenticación</td></tr>";
    echo "<tr><td>Usuario:</td><td><input type=\"text\" name=\"username\">" .
        "</td></tr>";
    echo "<tr><td>Clave:</td><td><input type=\"password\" name=\"password\">" .
        "<br></td></tr>";
    echo "<tr><td colspan='2' align='center'><input type=\"submit\" " .
        "value=\"Enviar\"></tr></td>";
    echo "</table>";
    echo "</form>";
}


/**
 * Extrae opciones para un usuario.
 *
 * @param string  $usuario Login del usuario
 * @param handle  &$db     Conexión a BD
 * @param array   &$op     Se llena con opciones del usuario.
 * @param integer &$rol    Rol del usuario
 *
 * @return  Nada
 */
function sacaOpciones($usuario, &$db, &$op, &$rol) 
{
    $q = "SELECT id_rol FROM usuario " .
         "WHERE id_usuario='" .  $usuario . "';";
    $result = $db->query($q);
    if (PEAR::isError($result)) {
        die($result->getMessage()."<br>" . $q);
    }
    $row = array();
    if ($result->fetchInto($row)) {
        $rol = $row[0];
    }
    $q = "SELECT id_opcion FROM opcion_rol " .
        "WHERE id_rol='" . $rol . "';";
    $result = $db->query($q);
    if (PEAR::isError($result)) {
        die("No se encontró el rol del usuario");
    }
    $row = array();
    while ($result->fetchInto($row)) {
        $op[] = $row[0];
    }   
}

/**
 * Retorna nombre de la sesión basado en URL.
 * Podría considerarse una forma de almacenar sesiones diferente --drupal
 * usa base de datos.
 *
 * @return string Nombre de la sesión
 */
function nomSesion() 
{
    $sru = $_SERVER['REQUEST_URI'];
    if (($l = strrpos($sru, '/')) === false) {
        $dsru = $sru;
    } else {
        $dsru = substr($sru, 0, $l);
    }
    // La idea de usar HTTP_HOST es de fuentes de Drupal pero no basta porque
    // al menos en php 5.2.5 de OpenBSD 4.2 el nombre de la sesión debe
    // ser alfanumérico (documentado) y comenzar con letra (no documentado).
    // Así mismo varias instalaciones en el mismo HOST corriendo simultaneamente
    // confundirían el nombre de sesión.
    $snru = preg_replace('/[^a-z0-9]/i', '', 
        "s" . $_SERVER['HTTP_HOST'] . $dsru);
    return $snru;
}

/** 
 * De requerirlo inicia sesión y autentica un usuario listado como usuario 
 * en la base de datos y consulta opciones a las que puede acceder.
 * Si el usuario tiene permiso para la opcion $opcion retorna true.
 * En otro caso falla.
 * 
 * @param string  $dsn      URL de base de datos
 * @param string  $accno    Mensaje de error por mostrar si no autentica
 * @param string  &$usuario Retorna en esta variable el login del usuario
 * @param integer $opcion   Código de la opción del menu que el usuario desea 
 *
 * @return mixed Conectar base de datos
 */
function autenticaUsuario($dsn,  $accno, &$usuario, $opcion) 
{
    $snru = nomSesion();
    if (!isset($_SESSION) || session_name() != $snru) {
        session_name($snru);
        session_start();
    }
    $options = array('debug'       => 5);
    $db =& DB::connect($dsn, $options);
    if (PEAR::isError($db)) {
        $m = $db->getMessage()."<br>\n" . $db->getUserInfo();
        $m = str_replace($dsn, '', $m);
        die($m);
    }
    $params = array(
        "dsn" => $dsn,
        "table" => "usuario",
        "usernamecol" => "id_usuario",
        "passwordcol" => "password"
    );
    $a = new Auth("DB", $params, "loginFunction");
    $a->setSessionName($snru);
    $a->start();
    if ($a->checkAuth()) {
        //echo "<script>alert(document.cookie);</script>";
        $usuario = $a->getUsername();
        if (!isset($_SESSION['opciones']) 
            || !isset($_SESSION['id_funcionario']) ) {
            $op = array();
            $rol = -1;

            //Prevenir session fixation 
            //http://shiflett.org/articles/session-fixation
            session_regenerate_id();  

            sacaOpciones($usuario, $db, $op, $rol);
            if (count($op) == 0) {
                echo "No tiene opciones este usuario, " .
                    "¿seguro la base está bien inicializada?";
            }
            $_SESSION['opciones'] = $op;
            $q = "SELECT id FROM funcionario " .
                "WHERE nombre='" . $usuario . "';";
            $result = $db->query($q);
            if (PEAR::isError($result)) {
                die($result->getMessage());
            }
            $row = array();
            if ($result->fetchInto($row)) {
                $idf = $row[0];
            }
            $_SESSION['id_funcionario'] = $idf;

        }
        if (in_array($opcion, $_SESSION['opciones'])) {
            return $db;
        }
        die($accno . " (1)");
    } else {
        die($accno . " (2)");         
    }
}


/**
 * Cierra sesión iniciada con autenticaUsuario.
 *
 * @param string $dsn URL de base de datos
 *
 * @return nada
 */
function cierraSesion($dsn) 
{
    $snru = nomSesion();
    if (!isset($_SESSION) || session_name() != $snru) {
        session_name($snru);
        session_start();
    }
    $params = array(
        "dsn" => $dsn,
        "table" => "usuario",
        "usernamecol" => "id_usuario",
        "passwordcol" => "password"
    );
    $a = new Auth("DB", $params, "loginFunction");
    $a->setSessionName($snru);
    $nv = "_auth_" . nomSesion();
    unset($_SESSION[$nv]); 
    unset($_SESSION['_authession']); 
    unset($_SESSION['id_funcionario']);
    unset($_SESSION['opciones']);
    $a->logout();
    session_write_close();
    unset($_SESSION);
}

?>
