<?php
/**
 * phpaga
 *
 * User management functionality.
 *
 * This file contains the necessary routines to manage users.
 *
 * @author Florian Lanthaler <florian@phpaga.net>
 * @version $Id: users.php 656 2006-01-19 20:48:39Z worf $
 *
 * Copyright (c) 2002, Florian Lanthaler <florian@phpaga.net>
 *
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met:
 *
 *    * Redistributions of source code must retain the above copyright
 *      notice, this list of conditions and the following disclaimer.
 *
 *    * Redistributions in binary form must reproduce the above copyright
 *      notice, this list of conditions and the following disclaimer in
 *      the documentation and/or other materials provided with the
 *      distribution.
 *
 *    * Neither the name of Florian Lanthaler nor the names of his
 *      contributors may be used to endorse or promote products derived
 *      from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */


/**
 * Gets a user's information from the database.
 *
 * @param int    $userID    Users's ID
 * @param array  &$userInfo Users's information
 *
 * @return int   $result    A result code.
 *
 * @author Florian Lanthaler <florian@phpaga.net>
 * @since phpaga 0.1
 */

function phpaga_user_getUserInfo ($userID,
                                  &$userInfo)
{

    $userInfo = array();
    $h_perm = array();

    if (!isset($userID) || !is_numeric($userID))
        return PHPAGA_ERR_USER_INVALIDID;

    phpaga_db_connect($db);

    $query =
        "SELECT usr_login, users.pe_id, pe_lastname, pe_firstname, ".
        "pe_email, persons.cpn_id, cpn_name, ".
        "users.lng_id, lng_code, usr_skin, usr_perm ".
        "FROM users ".
        "LEFT JOIN persons ON users.pe_id = persons.pe_id ".
        "LEFT JOIN companies ON persons.cpn_id = companies.cpn_id ".
        "LEFT JOIN languages ON users.lng_id = languages.lng_id ".
        "WHERE usr_id = ".$db->quoteSmart($userID);

    $result = $db->query($query);

    if (DB::isError($result))
        return PHPAGA_ERR_DB_EXEC_QUERY;

    if ($result->numRows() < 1)
        return PHPAGA_ERR_DB_NO_ROWS;

    $qrow = $result->fetchRow();
    $result->free();

    if (is_array($qrow))
    {
        $userInfo["usr_id"] = $userID;
        $userInfo["usr_login"] = $qrow["usr_login"];
        $userInfo["pe_id"] = $qrow["pe_id"];

        $userInfo["usr_name"] = phpaga_persons_formatname($qrow["pe_lastname"],
                                                          $qrow["pe_firstname"]);

        $userInfo["usr_email"] = $qrow["pe_email"];
        $userInfo["cpn_id"] = $qrow["cpn_id"];
        $userInfo["cpn_name"] = $qrow["cpn_name"];
        $userInfo["lng_id"] = $qrow["lng_id"];
        $userInfo["lng_code"] = $qrow["lng_code"];
        $userInfo["skin"] = $qrow["usr_skin"];

        $userInfo["perm"] = array();

        if (strlen($qrow["usr_perm"]))
        {
            $h_perm = explode("|", trim($qrow["usr_perm"]));

            foreach ($h_perm as $h_p)
                $userInfo["perm"][$h_p] = true;
        }

        return PHPAGA_ERR_NONE;
    }
    else
        return PHPAGA_ERR_USER_FIND;
}


/**
 * Loads all users matching search criteria into an array.
 *
 * @param array  &$userInfo    Array containing the results
 * @param int    $count        Number of records matching the query
 * @param array  $s_userInfo   User information (search criteria)
 * @param int    $offset       Offset
 * @param int    $limit        Limit
 *
 * @return int   $result       A result code.
 *
 * @author Florian Lanthaler <florian@phpaga.net>
 * @since phpaga 0.1
 */

function phpaga_user_search (&$userInfo,
                             $s_userInfo = null,
                             $offset = "",
                             $limit = "")
{

    $where = array();
    $userInfo = array();

    if (isset($s_userInfo) && !is_array($s_userInfo))
    {
        $s_userInfo = array();
        return PHPAGA_ERR_INVALIDSEARCHPARAM;
    }

    phpaga_db_connect($db);

    $query =
        "SELECT usr_id, usr_login, users.pe_id, pe_lastname, pe_firstname, ".
        "pe_email, persons.cpn_id, cpn_name, ".
        "users.lng_id, lng_code, usr_skin "."FROM users ".
        "LEFT JOIN persons ON users.pe_id = persons.pe_id ".
        "LEFT JOIN companies ON persons.cpn_id = companies.cpn_id ".
        "LEFT JOIN languages ON users.lng_id = languages.lng_id ";

    if (isset($s_userInfo["prj_id"]) && is_numeric($s_userInfo["prj_id"]))
        $query .= // "LEFT JOIN projects p ON p.pe_id = persons.pe_id ".
            "LEFT JOIN project_members pm ON ((pm.pe_id = persons.pe_id) )";//AND (pm.prj_id = ".
//            $db->quoteSmart($s_userInfo["prj_id"]).")) ";

    if (isset($s_userInfo["usr_id"]) && is_numeric($s_userInfo["usr_id"]))
        $where[] = "usr_id = ".$db->quoteSmart($s_userInfo["usr_id"]);

    if (isset($s_userInfo["usr_login"]) && strlen($s_userInfo["usr_login"]))
        $where[] = "usr_login LIKE '%".$db->escapeSimple($s_userInfo["usr_login"])."%'";

    if (isset($s_userInfo["pe_lastname"]) && strlen($s_userInfo["pe_lastname"]))
        $where[] = "pe_lastname LIKE '%".$db->escapeSimple($s_userInfo["pe_lastname"])."%'";

    if (isset($s_userInfo["prj_id"]) && is_numeric($s_userInfo["prj_id"]))
        $where[] = "pm.prj_id = ".$db->quoteSmart($s_userInfo["prj_id"]);


    if ((PHPAGA_DB_SYSTEM != "mysql")
        && (isset($s_userInfo["notmemberof_prj_id"])
            && is_numeric($s_userInfo["notmemberof_prj_id"])))

        $where[] = "(persons.pe_id NOT IN (SELECT pe_id FROM project_members WHERE prj_id = ".
            $db->quoteSmart($s_userInfo["notmemberof_prj_id"])."))";


    if (count($where) > 0)
        $query .= "WHERE ".implode (" AND ", $where)." ";

    if (isset($s_userInfo["sort"]) && ($s_userInfo["sort"] == "person"))
        $query .= "ORDER BY pe_lastname, pe_firstname ";
    else
        $query .= "ORDER BY usr_login ";

    if (isset($offset) && is_numeric($offset) && isset($limit) &&
        is_numeric($limit) && ($limit > 0))

        $result = $db->limitQuery($query, $offset, $limit);
    else
        $result = $db->query($query);

    if (DB::isError($result))
        return PHPAGA_ERR_DB_EXEC_QUERY;

    if ($result->numRows() < 1)
        return PHPAGA_ERR_DB_NO_ROWS;

    while ($qrow = $result->fetchRow())
    {
        phpaga_sanitizeArray($qrow);

        $qrow["pe_name"] =
            phpaga_persons_formatname($qrow["pe_lastname"],
                                      $qrow["pe_firstname"]);

        $userInfo[] = $qrow;
    }

    $result->free();
    return PHPAGA_ERR_NONE;
}


/**
 * Modifies an existing user profile in the database
 *
 * @param  int    $userID    Users's ID
 * @param  array  $userInfo  Array with the values to be set
 *
 * @return int   $result     A result code.
 *
 * @author Florian Lanthaler <florian@phpaga.net>
 * @since phpaga 0.1
 */

function phpaga_user_update ($userInfo)
{

    global $phpaga_languages;

    $fields = array();

    if (!isset($userInfo["usr_id"]) || !is_numeric($userInfo["usr_id"])
        || !is_array($userInfo))

        return PHPAGA_ERR_USER_INVALIDID;

    if (isset($userInfo["pe_id"]) && is_numeric($userInfo["pe_id"]))
        $fields["pe_id"] = $userInfo["pe_id"];

    if (isset($userInfo["usr_pe_id"]) && is_numeric($userInfo["usr_pe_id"]))
        $fields["usr_pe_id"] = $userInfo["usr_pe_id"];

    if (isset($userInfo["lng_id"]) && is_numeric($userInfo["lng_id"]))
    {
        $fields["lng_id"] = $userInfo["lng_id"];

        /* check whether the locales for the selected language are available */

        $current = setlocale(LC_COLLATE, NULL);
        $result = phpaga_getLanguageCode($fields["lng_id"], $lng_code);

        $langname = setlocale(LC_ALL, $phpaga_languages[$lng_code]);

        if ($langname === false)
            return PHPAGA_ERR_LOCALENOTAVAIL;

        if (strstr(PHP_OS, 'WIN'))
        {
            putenv("LANG=".$langname);
            putenv("LANGUAGE=".$langname);
        }

        setlocale(LC_ALL, $current);
    }

    if (isset($userInfo["usr_passwd"]) && strlen($userInfo["usr_passwd"]))
        $fields["usr_passwd"] = phpaga_password($userInfo["usr_passwd"]);

    if (isset($userInfo["usr_skin"]) && strlen($userInfo["usr_skin"]))
        $fields["usr_skin"] = $userInfo["usr_skin"];

    if (isset($userInfo["perm"]) && is_array($userInfo["perm"]))
    {
        if (count($userInfo["perm"]) == 0)
            $fields["usr_perm"] = NULL;
        else
            $fields["usr_perm"] = implode("|", $userInfo["perm"]);
    }

    if (count($fields) == 0)
        return PHPAGA_ERR_NONE;

    phpaga_db_connect($db);
    $result = $db->autoExecute("users", $fields, DB_AUTOQUERY_UPDATE,
                               "usr_id = ".$db->quoteSmart($userInfo["usr_id"]));

    if (DB::isError($result))
        return PHPAGA_ERR_DB_EXEC_QUERY;

    /* reload the auth_user information and set the session variables
     * accordingly if we're doing modifications on the current user
     */

    if ($_SESSION["auth_user"]["usr_id"] == $userInfo["usr_id"])
    {
        phpaga_user_getUserInfo($userInfo["usr_id"], $userInfo);
        $_SESSION["auth_user"] = $userInfo;
    }

    return PHPAGA_ERR_NONE;
}


/**
 * Gets all user IDs from the database
 *
 * @param array  $userInfo Users's information
 *
 * @return int   $result  A result code.
 *
 * @author Florian Lanthaler <florian@phpaga.net>
 * @since phpaga 0.1
 */

function phpaga_user_getUserIDs (&$userIDs)
{
    $userIDs = array();

    phpaga_db_connect($db);

    $result = $db->query("SELECT usr_id FROM users");

    if (DB::isError($result))
        return PHPAGA_ERR_DB_EXEC_QUERY;

    if ($result->numRows() < 1)
        return PHPAGA_ERR_DB_NO_ROWS;

    while ($qrow = $result->fetchRow())
        $userIDs[] = $qrow["usr_id"];

    $result->free();

    return PHPAGA_ERR_NONE;
}


/**
 * Adds a new user.
 *
 * @param  array   $user     Array containing user information.
 *
 * @return int     $result   A result code.
 *
 * @author Florian Lanthaler <florian@phpaga.net>
 * @since phpaga 0.1
 */

function phpaga_user_add ($user)
{

    /* make sure login and password have at least more than 0 length */
    if (!isset($user["usr_login"]) || !strlen($user["usr_login"]))
        return PHPAGA_ERR_AUTH_LOGINLENGTH;
    elseif (!isset($user["usr_passwd"]) || !strlen($user["usr_passwd"]))
        return PHPAGA_ERR_AUTH_PASSWDLENGTH;
    elseif (!isset($user["pe_id"]) || !is_numeric($user["pe_id"]))
        return PHPAGA_ERR_USR_NOPEASSOC;

    /* if some values are not set then set them to healthy defaults */
    if (!isset($user["lng_id"]) || !is_numeric($user["lng_id"]))
        $user["lng_id"] = PHPAGA_DEFAULTLANGUAGE;

    if (!isset($user["usr_skin"]) || !strlen($user["usr_skin"]))
        $user["usr_skin"] = PHPAGA_DEFAULT_SKIN;

    if (!isset($user["usr_pe_id"]) || !is_numeric($user["usr_pe_id"]))
        $user["usr_pe_id"] = 1;

    phpaga_db_connect($db);

    $fields = array("usr_id"=> $db->nextId("users_usr_id"),
                    "pe_id" => $user["pe_id"],
                    "lng_id" => $user["lng_id"],
                    "usr_login" => $user["usr_login"],
                    "usr_passwd" => phpaga_password($user["usr_passwd"]),
                    "usr_pe_id" => $user["usr_pe_id"],
                    "usr_skin" => $user["usr_skin"]
        );

    if (isset($user["perm"]) && is_array($user["perm"]))
    {
        if (count($user["perm"]) == 0)
            $fields["usr_perm"] = NULL;
        else
            $fields["usr_perm"] = implode("|", $user["perm"]);
    }

    $result = $db->autoExecute("users", $fields, DB_AUTOQUERY_INSERT);

    if (DB::isError($result))
    {
        if ($result->code == DB_ERROR_CONSTRAINT)
            return PHPAGA_ERR_USR_LOGINDUPLICATE;

        return PHPAGA_ERR_DB_EXEC_QUERY;
    }
    else
        return PHPAGA_ERR_NONE;
}

/**
 * Deletes a user and his settings from the database.
 *
 * @param int    $userID    Users's ID
 *
 * @return int   $result    A result code.
 *
 * @author Florian Lanthaler <florian@phpaga.net>
 * @since phpaga 0.3
 */

function phpaga_user_delete ($userID)
{

    if (!isset($userID) || !is_numeric($userID))
        return PHPAGA_ERR_USER_INVALIDID;

    phpaga_db_connect($db);

    $query = "DELETE FROM userconfig ".
        "WHERE usr_id = ".$db->quoteSmart($userID);

    $result = $db->query($query);

    if (DB::isError($result))
        return PHPAGA_ERR_DB_EXEC_QUERY;

    $query = "DELETE FROM users ".
        "WHERE usr_id = ".$db->quoteSmart($userID);

    $result = $db->query($query);

    if (DB::isError($result))
        return PHPAGA_ERR_DB_EXEC_QUERY;
    else
        return PHPAGA_ERR_NONE;
}

/**
 * Checks whether a user has a determined permission. If no user id
 * is given then take the user from the current session.
 *
 * @param  int    $perm       Permission ID
 * @param  int    $uid        User ID (optional)
 *
 * @return bool   $hasperm    true if user has permission, false otherwise
 *
 * @author Florian Lanthaler <florian@phpaga.net>
 * @since phpaga 0.3
 */

function phpaga_user_hasperm ($perm, $uid = "")
{

    if (!strlen($uid) || !is_numeric($uid))
    {
        return(is_numeric($perm) && isset($_SESSION["auth_user"])
               && isset($_SESSION["auth_user"]["perm"])
               && isset($_SESSION["auth_user"]["perm"][$perm]));
    }
    else
    {
        $result = phpaga_user_getUserInfo($uid, $user);

        if ($result != PHPAGA_ERR_NONE)
            return false;
        else
            return(is_numeric($perm)
                   && isset($user["perm"])
                   && isset($user["perm"][$perm]));
    }
}


/**
 * Checks whether the current user has a determined permission or one
 * of a series of permissions (in an array).
 * Outputs an error message and stop the program if the permission is
 * missing.
 *
 * @param  int    $perm       Permission ID
 *
 * @return void
 *
 * @author Florian Lanthaler <florian@phpaga.net>
 * @since phpaga 0.3
 */

function phpaga_user_pageperm ($perm)
{

    if (is_array($perm))
    {
        foreach($perm as $p)
            if (phpaga_user_hasperm($p))
                return;
    }
    else if (phpaga_user_hasperm($perm))
        return;

    phpaga_header();
    phpaga_message (_("No access"),
                    _("You don't have the necessary rights to access this page."));
    phpaga_footer();
    die();
}


/**
 * Gets the count of available users. This routine is used
 * to determine whether phpaga has been set up and configured
 * properly.
 *
 * @param int    $numusers  Number of available users
 *
 * @return int   $result    A result code.
 *
 * @author Florian Lanthaler <florian@phpaga.net>
 * @since phpaga 0.3
 */

function phpaga_user_getNumUsers (&$numusers)
{

    phpaga_db_connect($db);

    $numusers = $db->getOne("SELECT count(usr_id) FROM users");

    if (DB::isError($numusers))
    {
        $numusers = 0;
        return PHPAGA_ERR_DB_EXEC_QUERY;
    }

    return PHPAGA_ERR_NONE;

}

?>