<?php
/**
 * アクセス制御マネージャー
 *
 * PHP versions 5
 *
 * LICENSE: This source file is licensed under the terms of the GNU General Public License.
 *
 * @package    Magic3 Framework
 * @author     平田直毅(Naoki Hirata) <naoki@aplo.co.jp>
 * @copyright  Copyright 2006-2007 Magic3 Project.
 * @license    http://www.gnu.org/copyleft/gpl.html  GPL License
 * @version    SVN: $Id: accessManager.php 412 2008-03-19 02:53:48Z fishbone $
 * @link       http://www.magic3.org
 */
class AccessManager
{
	var $db;						// DBオブジェクト
	var $_clientId;					// クライアントID(クッキー用)
	var $_oldSessionId;				// 古いセッションID
	var $_accessLogSerialNo;		// アクセスログのシリアルNo
   	const LOG_REQUEST_PARAM_MAX_LENGTH	= 1024;				// ログに保存するリクエストパラメータの最大長

	/**
	 * コンストラクタ
	 */
	function __construct()
	{
		global $gInstanceManager;
		
		// システムDBオブジェクト取得
		$this->db = $gInstanceManager->getSytemDbObject();
	}
	/**
	 * ログイン処理
	 *
	 * ログイン処理を行う。可能な場合はユーザ情報を読み込む
	 *
	 * @param RequestManager $request		HTTPリクエスト処理クラス
	 * @return bool   						true=アクセス可能、false=アクセス不可
	 */
	function userLogin($request)
	{
		// アカウント、パスワード取得
		$account = $request->trimValueOf('account');
		$password = $request->trimValueOf('password');
		return $this->userLoginByAccount($account, $password);
	}
	/**
	 * ログイン処理
	 *
	 * ログイン処理を行う。可能な場合はユーザ情報を読み込む
	 *
	 * @param string $account		アカウント
	 * @param string $password		パスワード
	 * @return bool   				true=アクセス可能、false=アクセス不可
	 */
	function userLoginByAccount($account, $password)
	{
		global $gInstanceManager;
		global $gRequestManager;
		
		// 戻り値初期化
		$retValue = false;
		
		// アカウントが空のときはアクセス不可
		if (empty($account)) return false;
		
		$accessIp = $gRequestManager->trimServerValueOf('REMOTE_ADDR');		// アクセスIP
		
		// ユーザ情報取得
		if ($this->db->getLoginUserRecord($account, $row)){
			// ******** ユーザのログインチェック             ********
			// ******** ログインのチェックを行うのはここだけ ********
			$pass  = $row['lu_password'];
			if ($pass == $password) {	// パスワード一致のとき
				// ユーザ情報オブジェクトを作成
				$userInfo = new UserInfo();
				$userInfo->userId	= $row['lu_id'];		// ユーザID
				$userInfo->account	= $row['lu_account'];	// ユーザアカウント
				$userInfo->name		= $row['lu_name'];		// ユーザ名
				$userInfo->userType	= $row['lu_user_type'];	// ユーザタイプ
				$userInfo->_recordSerial = $row['lu_serial'];	// レコードシリアル番号
				
				// 管理者の場合は、管理者キーを発行
				if ($userInfo->isSystemAdmin()){
					$adminKey = $this->createAdminKey();
					if ($this->db->addAdminKey($adminKey, $accessIp)) $userInfo->_adminKey = $adminKey;
				} else {
					$userInfo->_adminKey = '';
				}
				
				// インスタンスマネージャーとセッションに保存
				$gInstanceManager->setUserInfo($userInfo);
				$gRequestManager->setSessionValueWithSerialize(M3_SESSION_USER_INFO, $userInfo);
				
				// ログインのログを残す
				$this->db->updateLoginLog($userInfo->userId, $this->_accessLogSerialNo);
				$retValue = true;
			}
		}
		// ログインエラーの場合は、入力アカウントを保存する
		if (!$retValue) $this->db->addErrorLoginLog($account, $accessIp, $this->_accessLogSerialNo);
		return $retValue;
	}
	/**
	 * ユーザログアウト処理
	 *
	 * @param bool $delSession		セッションを削除するかどうか
	 */
	function userLogout($delSession = false)
	{
		global $gInstanceManager;
		
		// セッション終了
		if ($delSession){
//			session_start();
			session_destroy();
		}
		
		// ユーザ情報を削除
		$gInstanceManager->setUserInfo(null);
	}
	/**
	 * アクセスログの記録
	 *
	 * アクセスログを記録する
	 */
	function accessLog()
	{
		global $gRequestManager;
		global $gEnvManager;
		
		// ユーザ情報が存在しているときは、ユーザIDを登録する
		$userId = 0;
		$userInfo = $gEnvManager->getCurrentUserInfo();
		if (!is_null($userInfo)){		// ユーザ情報がある場合
			$userId = $userInfo->userId;
		}
		//$user		= 0;							// ユーザID
		$cookieVal	= $this->_clientId;							// アクセス管理用クッキー
		$ip			= $gRequestManager->trimServerValueOf('REMOTE_ADDR');		// クライアントIP
		$method		= $gRequestManager->trimServerValueOf('REQUEST_METHOD');	// アクセスメソッド
		$uri		= $gRequestManager->trimServerValueOf('REQUEST_URI');
		$referer	= $gRequestManager->trimServerValueOf('HTTP_REFERER');
		$agent		= $gRequestManager->trimServerValueOf('HTTP_USER_AGENT');		// クライアントアプリケーション
		$language	= $gRequestManager->trimServerValueOf('HTTP_ACCEPT_LANGUAGE');	// クライアント認識可能言語
		
		$request = '';
		foreach ($_REQUEST as $strKey => $strValue ) {
			$request .= sprintf("[%s]=[%s];", $strKey, $strValue);
		}
		$request = substr($request, 0, self::LOG_REQUEST_PARAM_MAX_LENGTH);	// 格納長を制限
		
		// アクセスログのシリアルNoを保存
		$this->_accessLogSerialNo = $this->db->accessLog($userId, $cookieVal, $ip, $method, $uri, $referer, $request, $agent, $language);
	}
	
	/**
	 * アクセスログユーザの記録
	 *
	 * アクセスログユーザを記録する
	 */
	function accessLogUser()
	{
		global $gEnvManager;
				
		$userId = 0;
		$userInfo = $gEnvManager->getCurrentUserInfo();
		if (!is_null($userInfo)){		// ユーザ情報がある場合
			$userId = $userInfo->userId;
		}
		// ユーザ情報が存在しているときは、ユーザIDを登録する
		if ($userId != 0) $this->db->updateAccessLogUser($this->_accessLogSerialNo, $userId);
	}
	/**
	 * クッキーに保存するクライアントIDを生成
	 */
	function createClientId()
	{
		global $gRequestManager;
			
		// アクセスログの最大シリアルNoを取得
		$max = $this->db->getMaxSerialOfAccessLog();
		$this->_clientId = md5(time() . $gRequestManager->trimServerValueOf('REMOTE_ADDR') . ($max + 1));
		return $this->_clientId;				// クライアントID(クッキー用)
	}
	/**
	 * クッキーから取得したクライアントIDを設定
	 *
	 * @param string $clientId		クライアントID
	 */
	function setClientId($clientId)
	{
		$this->_clientId = $clientId;				// クライアントID(クッキー用)
	}
	/**
	 * 管理者用一時キーを作成
	 */
	function createAdminKey()
	{
		global $gRequestManager;
			
		return md5($gRequestManager->trimServerValueOf('REMOTE_ADDR') . time());
	}
	/**
	 * 変更前のセッションIDを設定
	 *
	 * @param string $sessionId		セッションID
	 */
	function setOldSessionId($sessionId)
	{
		$this->_oldSessionId = $sessionId;
	}
	
	/**
	 * アクセスログのシリアルNoを取得
	 *
	 * @return int		シリアルNo
	 */
	function getAccessLogSerialNo()
	{
		return $this->_accessLogSerialNo;
	}
	/**
	 * システム管理者の認証が完了しているかどうか判断(フレームワーク以外のアクセス制御用)
	 *
	 * @return bool		true=完了、false=未完了
	 */
	function loginedByAdmin()
	{
		global $gRequestManager;
		global $gSystemManager;
		
		// セッション変数を取得可能にする
		session_cache_limiter('none');		// IE対策(暫定対応20070703)
		session_start();
		
		// セッションを再生成する(セキュリティ対策)
		if ($gSystemManager->regenerateSessionId()){
			$this->setOldSessionId(session_id());		// 古いセッションIDを保存
			session_regenerate_id(true);
		}

		// セッションからユーザ情報を取得
		// セッションが残っていない場合がある(IEのみ)→アクセスできない(原因不明)
		$userInfo = $gRequestManager->getSessionValueWithSerialize(M3_SESSION_USER_INFO);
		if (is_null($userInfo)) return false;		// ログインしていない場合

		if ($userInfo->isSystemAdmin()){	// システム管理者の場合
			return true;
		} else {
			return false;
		}
	}
	/**
	 * 管理者認証用一時キーが存在するかどうか
	 *
	 * @param RequestManager $request		HTTPリクエスト処理クラス
	 * @return bool			true=完了、false=未完了
	 */
	function isValidAdminKey($request)
	{
		// 管理者一時キーを取得
		$adminKey = $request->trimValueOf(M3_REQUEST_PARAM_ADMIN_KEY);
		if (empty($adminKey)) return false;

		$ret = $this->db->isValidAdminKey($adminKey, $request->trimServerValueOf('REMOTE_ADDR'));
		return $ret;
	}
	/**
	 * URL用のパラメータとして使用するセッションIDを取得
	 *
	 * @return string			セッションIDパラメータ文字列
	 */	
	function getSessionIdUrlParam()
	{
		return session_name() . '=' . session_id();
	}
}
?>
