<?php
#
#   FILE:  auth_cwis.php
#
#   Part of the Collection Workflow Integration System (CWIS)
#   Copyright 2011 Edward Almasy and Internet Scout
#   http://scout.wisc.edu
#

# This file defines a phpBB authentication plugion.
#  Details on their API can be found here:
#  http://wiki.phpbb.com/Authentication_plugins

if (!defined('IN_PHPBB'))
{
        exit;
}

/**
* Creates a Database object connected to the CWIS DB.
* @return Database object
*/
function create_cwis_db()
{
    global $config, $phpbb_root_path;
    require_once($phpbb_root_path.'includes/auth/Axis--Database.php');
    return  new Database(
        $config["cwis_db_user"],
        $config["cwis_db_pass"],
        $config["cwis_db_database"],
        $config["cwis_db_server"]);
}

/**
* Pull user data from the phpBB database.
* @param username giving the username to search for
*/
function fetch_user_row($username)
{
    global $db;
    # Check for a phpBB user row:
    $sql = 'SELECT * FROM ' . USERS_TABLE . "
                WHERE username_clean = '" .
        $db->sql_escape(utf8_clean_string($username)) . "'";
    $result = $db->sql_query($sql);
    $row = $db->sql_fetchrow($result);
    $db->sql_freeresult($result);

    return $row;
}

/**
* Create phpbb user data.
* @param username giving the username to create
* @param password giving the plain text pass for this user.
*/
function create_user_row($username, $password)
{
    global $db, $user, $config;
    # first retrieve default group id
    $sql = 'SELECT group_id FROM ' . GROUPS_TABLE . " "
        ."WHERE group_name = '" . $db->sql_escape('REGISTERED') . "' "
        ."AND group_type = " . GROUP_SPECIAL;
    $result = $db->sql_query($sql);
    $row = $db->sql_fetchrow($result);
    $db->sql_freeresult($result);

    if (!$row)
    {
        trigger_error('NO_GROUP');
    }

    # generate user account data
    return array(
        'username'		=> $username,
        'user_password'	=> phpbb_hash($password),
        'user_email'	=> '',
        'group_id'		=> (int) $row['group_id'],
        'user_type'		=> USER_NORMAL,
        'user_ip'		=> $user->ip,
        'user_new'		=> ($config['new_member_post_limit']) ? 1 : 0
        );
}

/**
* Log in to phpBB using CWIS credentials.  This is necessary so that
* admins can access the admin control panel.  Normal user logins are
* handled with the autologin functions defined below.
* @param username giving the username to log in
* @param password giving the plain text pass
* @return array having keys 'status', 'error_msg', and 'user_row' in a
*     format expected by phpbb.
*/
function login_cwis(&$username, &$password)
{
    global $db, $config, $user;

    # do not allow empty password
    if (!$password)
    {
        return array(
            'status'	=> LOGIN_ERROR_PASSWORD,
            'error_msg'	=> 'NO_PASSWORD_SUPPLIED',
            'user_row'	=> array('user_id' => ANONYMOUS),
            );
    }

    if (!$username)
    {
        return array(
            'status'	=> LOGIN_ERROR_USERNAME,
            'error_msg'	=> 'LOGIN_ERROR_USERNAME',
            'user_row'	=> array('user_id' => ANONYMOUS),
            );
    }

    # Now, pull user data from CWIS:
    $CwisDB = create_cwis_db();
    $CwisDB->Query(
        "SELECT UserId, UserPassword FROM APUsers "
        ."WHERE UserName='".addslashes($username)."'");
    $cwis_user_row = $CwisDB->FetchRow();

    # If there was no such user, or if the password didn't match, bail.
    if ( !isset($cwis_user_row["UserPassword"]) ||
         crypt($password, $cwis_user_row["UserPassword"]) !=
         $cwis_user_row["UserPassword"])
    {
        return array(
            'status'		=> LOGIN_ERROR_EXTERNAL_AUTH,
            'error_msg'		=> 'LOGIN_ERROR_EXTERNAL_AUTH_CWIS',
            'user_row'		=> array('user_id' => ANONYMOUS),
            );
    }

    # Check for a phpBB user row:
    $row = fetch_user_row($username);

    if (!$row)
    {
        # There was no user row, so we must create one:
        $row = create_user_row($username, $password);

        return array(
            'status'		=> LOGIN_SUCCESS_CREATE_PROFILE,
            'error_msg'		=> false,
            'user_row'		=> $row
            );
    }
    else
    {
        # Successful login on an existing account.
        return array(
            'status'		=> LOGIN_SUCCESS,
            'error_msg'		=> false,
            'user_row'		=> $row
            );
    }
}

/**
* Checks for and validates login cookies set by CWIS, logging users in when required.
* Records will be added to the phpBB database if a user doesn't already exist there.
*/
function autologin_cwis()
{
    global $db, $config;
    $CookieName = "phpBBLoginToken";
    $CwisDB = create_cwis_db();

    # Fetch users to disable from the CWIS DB:
    $CwisDB->Query(
        "SELECT UserName FROM phpBBSync_LoginData WHERE RemIp='GoAwayMrUser'");
    $UsersToDisable = array();
    while ( $Row = $CwisDB->FetchRow() )
    {
        $UsersToDisable []= $Row;
    }

    # Iterate over them, disabling the ones we find
    foreach ($UsersToDisable as $User)
    {
        $username = array_pop ($User);

        $row = fetch_user_row($username);
        if ($row)
        {
            $sql = 'UPDATE '. USERS_TABLE
                .' SET user_type = ' . USER_INACTIVE
                .' WHERE user_id = '. $row['user_id'];
            $db->sql_query($sql);

            $CwisDB->Query(
                "DELETE FROM phpBBSync_LoginData WHERE UserName='".$username."'");
        }
    }

    if (isset($_COOKIE[$CookieName]))
    {
        $CookieData = unserialize(
            gzuncompress(base64_decode(urldecode($_COOKIE[$CookieName]))));

        if ($CookieData["Version"]==1)
        {
            $CwisDB->Query(
                "SELECT UserName FROM phpBBSync_LoginData "
                ."WHERE RemIp='".$_SERVER["REMOTE_ADDR"]."' "
                ."AND Token=".$CookieData["Token"]);
            $row = $CwisDB->FetchRow();

            $UserName=array_pop($row);

            if ($UserName !== NULL)
            {
                $sql = "SELECT * FROM " . USERS_TABLE . " WHERE "
                    ."username = '".$db->sql_escape($UserName)."'";
                $result = $db->sql_query($sql);
                $row = $db->sql_fetchrow($result);
                $db->sql_freeresult($result);

                if ($row)
                {
                    return ($row['user_type'] == USER_INACTIVE ||
                            $row['user_type'] == USER_IGNORE) ?
                        array() :
                        $row;
                }

                if (!function_exists('user_add'))
                {
                    global $phpbb_root_path, $phpEx;
                    include($phpbb_root_path . 'includes/functions_user.'
                            . $phpEx);
                }

                $row = create_user_row($UserName, md5($Data["Token"]));

                user_add($row);

                $row = fetch_user_row($UserName);

                if ($row)
                {
                    return $row;
                }
            }
        }
    }
    return array();
}

/**
* Checks to be sure the login cookie set by CWIS still exists, logging
* a user out if it does not.
*/
function validate_session_cwis($user_row)
{
    return
        (  isset($_COOKIE["phpBBLoginToken"]) && $user_row['user_id'] != ANONYMOUS ) ||
        ( !isset($_COOKIE["phpBBLoginToken"]) && $user_row['user_id'] == ANONYMOUS );
}

/**
* Add CWIS configuration entries to the phpBB admin control panel.
*/
function acp_cwis(&$new)
{
    global $user;

    $tpl =
      '<dl>'
      .'<dt><label for="cwis_db_server">CWIS DB Server:</label>'
      .'<dd><input type="text" id="cwis_db_server" size="40" name="config[cwis_db_server]" value="'.$new["cwis_db_server"].'"/></dd>'

      .'</dl><dl>'
      .'<dt><label for="cwis_db_user">CWIS DB User:</label>'
      .'<dd><input type="text" id="cwis_db_user" size="40" name="config[cwis_db_user]" value="'.$new["cwis_db_user"].'"/></dd>'

      .'</dl><dl>'
      .'<dt><label for="cwis_db_pass">CWIS DB Password:</label>'
      .'<dd><input type="text" id="cwis_db_pass" size="40" name="config[cwis_db_pass]" value="'.$new["cwis_db_pass"].'"/></dd>'

      .'</dl><dl>'
      .'<dt><label for="cwis_db_database">CWIS DB Database:</label>'
      .'<dd><input type="text" id="cwis_db_database" size="40" name="config[cwis_db_database]" value="'.$new["cwis_db_database"].'"/></dd>'

      .'</dl><dl>'
      .'<dt><label for="cwis_url">CWIS base url:</label>'
      .'<dd><input type="text" id="cwis_url" size="40" name="config[cwis_url]" value="'.$new["cwis_url"].'"/></dd>'
      .'</dl>'
      ;

    # These are fields required in the config table
    return array(
        'tpl'		=> $tpl,
        'config'	=> array('cwis_db_server', 'cwis_db_user', 'cwis_db_pass', 'cwis_db_database', 'cwis_url')
        );
}

?>
