<?php

/**
 * <pre>
 * Invision Power Services
 * IP.Board v3.4.6
 * Login handler abstraction : Internal Method
 * Last Updated: $Date: 2013-03-19 18:24:44 -0400 (Tue, 19 Mar 2013) $
 * </pre>
 *
 * @author 		$Author: bfarber $
 * @copyright	(c) 2001 - 2009 Invision Power Services, Inc.
 * @license		http://www.invisionpower.com/company/standards.php#license
 * @package		IP.Board
 * @link		http://www.invisionpower.com
 * @since		Tuesday 1st March 2005 (11:52)
 * @version		$Revision: 12088 $
 * @note		Be aware that MOST users will not be able to use this login module "out of the box" and will need to adapt it to suit their specific needs and configuration.
 */

if ( ! defined( 'IN_IPB' ) )
{
	print "<h1>Incorrect access</h1>You cannot access this file directly. If you have recently upgraded, make sure you upgraded 'admin.php'.";
	exit();
}

class login_external extends login_core implements interface_login
{
	/**
	 * Login method configuration
	 *
	 * @access	protected
	 * @var		array
	 */
	protected $method_config	= array();
	
	/**
	 * Constructor
	 *
	 * @access	public
	 * @param	object		ipsRegistry reference
	 * @param	array 		Configuration info for this method
	 * @param	array 		Custom configuration info for this method
	 * @return	@e void
	 */
	public function __construct( ipsRegistry $registry, $method, $conf=array() )
	{
		$this->method_config	= $method;
		$this->external_conf	= $conf;
		
		parent::__construct( $registry );
	}

	/**
	 * Compare passwords
	 *
	 * @access	protected
	 * @param	string		Plain text password
	 * @param	array 		Record from the remote table
	 * @return	boolean
	 */
	protected function _comparePasswords( $password, $remote_member )
	{
		$check_pass = $password;
		
		switch( REMOTE_PASSWORD_SCHEME )
		{
			case 'md5':
				$check_pass = md5($password);
			break;
			
			case 'sha1':
				$check_pass = sha1($password);
			break;
		}
		
		if ( $check_pass == $remote_member[ REMOTE_FIELD_PASS ] )
		{
			return true;
		}
		else
		{
			return false;
		}
	}

	/**
	 * Authenticate the request
	 *
	 * @access	public
	 * @param	string		Username
	 * @param	string		Email Address
	 * @param	string		Password
	 * @return	boolean		Authentication successful
	 */
	public function authenticate( $username, $email_address, $password )
	{
		//-----------------------------------------
		// Check admin authentication request
		//-----------------------------------------
		
		if ( $this->is_admin_auth )
		{
			$this->adminAuthLocal( $username, $email_address, $password );
			
  			if ( $this->return_code == 'SUCCESS' )
  			{
  				return true;
  			}
		}

		/*-------------------------------------------------------------------------*/
		// SET UP: Edit DB details to suit
		/*-------------------------------------------------------------------------*/

		define( 'REMOTE_DB_SERVER'  , $this->external_conf['REMOTE_DB_SERVER']   );
		define( 'REMOTE_DB_PORT'	, $this->external_conf['REMOTE_DB_PORT']	 );
		define( 'REMOTE_DB_DATABASE', $this->external_conf['REMOTE_DB_DATABASE'] );
		define( 'REMOTE_DB_USER'	, $this->external_conf['REMOTE_DB_USER']	 );
		define( 'REMOTE_DB_PASS'	, $this->external_conf['REMOTE_DB_PASS']	 );

		/*-------------------------------------------------------------------------*/
		// SET UP: Edit these DB tables to suit
		/*-------------------------------------------------------------------------*/

		define( 'REMOTE_TABLE_NAME'  , $this->external_conf['REMOTE_TABLE_NAME']  );
		define( 'REMOTE_FIELD_NAME'  , $this->external_conf['REMOTE_FIELD_NAME']  );
		define( 'REMOTE_FIELD_PASS'  , $this->external_conf['REMOTE_FIELD_PASS']  );
		define( 'REMOTE_EXTRA_QUERY' , $this->external_conf['REMOTE_EXTRA_QUERY'] );
		define( 'REMOTE_TABLE_PREFIX', $this->external_conf['REMOTE_TABLE_PREFIX'] );
		define( 'REMOTE_PASSWORD_SCHEME', $this->external_conf['REMOTE_PASSWORD_SCHEME'] );

		//-----------------------------------------
		// GET DB object
		//-----------------------------------------

		if ( ! class_exists( 'dbMain' ) )
		{
			require_once( IPS_KERNEL_PATH.'classDb.php' );/*noLibHook*/
			require_once( IPS_KERNEL_PATH.'classDb' . ucwords($this->settings['sql_driver']) . '.php' );/*noLibHook*/
		}

		$classname = "db_driver_" . $this->settings['sql_driver'];

		$RDB = new $classname;

		$RDB->obj['sql_database']			= REMOTE_DB_DATABASE;
		$RDB->obj['sql_user']				= REMOTE_DB_USER;
		$RDB->obj['sql_pass']				= REMOTE_DB_PASS;
		$RDB->obj['sql_host']				= REMOTE_DB_SERVER;
		$RDB->obj['sql_port']				= REMOTE_DB_PORT;  
		$RDB->obj['sql_tbl_prefix']			= REMOTE_TABLE_PREFIX;
		$RDB->obj['use_shutdown']			= 0;
		$RDB->obj['force_new_connection']	= 1;
		
		if( $this->external_conf['REMOTE_SQL_TYPE'] )
		{
			$RDB->connect_vars['sql_type']	= $this->external_conf['REMOTE_SQL_TYPE'];
		}

		//--------------------------------
		// Get a DB connection
		//--------------------------------

		$RDB->connect();

		//-----------------------------------------
		// Get member from remote DB
		//-----------------------------------------

		$remote_member = $RDB->buildAndFetch( array( 'select' => '*',
															'from'   => REMOTE_TABLE_NAME,
															'where'  => REMOTE_FIELD_NAME."='".$RDB->addSlashes($username)."' ".REMOTE_EXTRA_QUERY ) );

		$RDB->disconnect();

		//-----------------------------------------
		// Check
		//-----------------------------------------

		if ( ! $remote_member[ REMOTE_FIELD_NAME ] )
		{
			$this->return_code = 'NO_USER';
			return false;
		}

		//-----------------------------------------
		// Check password
		//-----------------------------------------

		$password			= html_entity_decode($password, ENT_QUOTES);
		$html_entities		= array( "&#33;", "&#036;", "&#092;" );
		$replacement_char	= array( "!", "$", "\\" );
		$password 			= str_replace( $html_entities, $replacement_char, $password );

		if ( ! $this->_comparePasswords( $password, $remote_member ) )
		{
			$this->return_code = 'WRONG_AUTH';
			return false;
		}

		//-----------------------------------------
		// Still here? Then we have a username
		// and matching password.. so get local member
		// and see if there's a match.. if not, create
		// one!
		//-----------------------------------------

		$this->_loadMember( $username );

		if ( $this->member_data['member_id'] )
		{
			$this->return_code = 'SUCCESS';
			return false;
		}
		else
		{
			//-----------------------------------------
			// Got no member - but auth passed - create?
			//-----------------------------------------

			$this->return_code = 'SUCCESS';

			$this->member_data = $this->createLocalMember( array( 'members' => array( 'name' => $username, 'password' => $password, 'email' => $email_address ) ) );
			
			return true;
		}
	}

	/**
	 * Load a member
	 *
	 * @access	protected
	 * @param	string		Username
	 * @return	@e void
	 */
	protected function _loadMember( $username )
	{
		$member = $this->DB->buildAndFetch( array( 'select' => 'member_id', 'from' => 'members', 'where' => "members_l_username='" . strtolower($username) . "'" ) );
		
		if( $member['member_id'] )
		{
			$this->member_data = IPSMember::load( $member['member_id'], 'extendedProfile,groups' );
		}
	}
}