<?php

/**
 * @file
 * Token verify and resource retrieve endpoint.
 *
 * Nifty OAuth Specification based on OAuth 2.0 draft 26.
 *
 */

$logid = 'OAuth';

//require "lib/MemcacheOAuth2.inc";
require "lib/PDOOAuth2.inc";
require_once("/var/www/lib/util.php");

$log = &Log::singleton('syslog', LOG_LOCAL5, $logid);

// 設定ファイル取得
$conf_oauth = parse_ini_file("/var/www/conf/oauth.conf");
if (empty($conf_oauth)) {
	$log->crit(logformat("Can't read oauth.conf"));
	header("HTTP/1.1 "."500 internal server error");
	header("Content-Type: application/json");
	header("Cache-Control: no-store");
	$result['error'] = "system_error99";
	echo json_encode($result);
	exit();
}

$conf = $conf_oauth;
$conf['endpoint'] = 'resource';

// auth_level設定
$request_uri = $_SERVER["REQUEST_URI"];
if (preg_match('/\/Oauth-middle\//', $request_uri)) {
	$conf['auth_level'] = 'middle';
}
else if (preg_match('/\/Oauth-high\//', $request_uri)) {
	$conf['auth_level'] = 'high';
}

//$oauth = new MemcacheOAuth2($conf);
$oauth = new PDOOAuth2($conf);

// Token検証成功の場合、クライアントIDとユーザIDを返す
$approved = $oauth->verifyAccessToken();

//=============================================================================
//============================= OAuth2.0 Finished =============================
//=============================================================================

if ($approved) {
	// 設定ファイル取得
	$conf_sam = parse_ini_file("/var/www/conf/sam.conf");
	if (empty($conf_sam)) {
		$log->crit(logformat("Can't read sam.conf"));
		$oauth->handleException("500 internal server error", 'system_error99');
	}

	$client_id = $approved["client_id"];
	$username = $approved["username"];
	$additional_data = $approved["additional_data"];
	$approved_scope = $approved["scope"];
	$contents_id = $approved["contents_id"];

	// サービス情報取得
	try {
		$client = $oauth->getClient($client_id);
	}
	catch (Exception $e) {
		$oauth->handleException("500 internal server error", 'system_error01');
	}
	// SAPS用
	$crmode1 = $client["crmode1"];
	$crmode2 = $client["crmode2"];
	$crmode3 = $client["crmode3"];
	$samode1 = $client["samode1"];
	$samode2 = $client["samode2"];
	$samode3 = $client["samode3"];
	$pattern = $client["pattern"];

	// アラートメール用
	$serviceName = $client["name"];
	$serviceProvider = $client["provider"];
	$serviceEmail = $client["email"];
	$serviceServerurl = $client["serverurl"];
	$serviceScopeflag = $client["scope_flag"];
	$serviceIdHashFlag = $client["id_hash_flag"];
	$serviceSalt = $client["salt"];

//=============================================================================
	// アクセス回数アラート 2012-12-25
	$happen = date("Y-m-d H:i:s");		//発生日時
	$ipaddr = $_SERVER['REMOTE_ADDR'];	//IPアドレス
	$origin = $_SERVER['SCRIPT_URI'];	//アクセスURL

	$requestInterval = $conf['resource_alert_interval'];	//期限
	$requestAlertval = $conf['resource_alert_threshold'];	//閾値
	// アクセス回数取得
	$requestCount = $oauth->getAccessCount($ipaddr, "resource_request", $requestInterval);
	// 閾値を超えたら、アラートメールを送信
	if ($requestCount >= $requestAlertval) {
		$log->notice(logformat("OAuth resource alert limit exceeded for $client_id from $ipaddr"));

		if (isset($conf['smtp_host']) && $conf['smtp_host']) {
			// 送信用メールサーバを設定
			$options = array(
				'host' => $conf['smtp_host'],
				'port' => $conf['smtp_port'] ? $conf['smtp_port'] : 25,
			);
			if ($conf['smtp_auth']) {
				$options['auth'] = true;
				$options['username'] = $conf['smtp_user'];
				$options['password'] = $conf['smtp_pass'];
			}

			// 送受信メールアドレスを設定
			$from = $conf['mail_from'];
			$to = $conf['mail_to'];

			// メールテンプレートを設定
			$template = file_get_contents($conf['resource_alert_template']);
			if ($template === false) { 
				$log->err(logformat("OAuth send resource alert failed for $client_id from $ipaddr: failed to get mail template"));
			}
			else {
				// メール変数を設定
				$params = array(
					'ALERTVAL' => $requestAlertval,
					'INTERVAL' => $requestInterval,
					'ALERT_TIME' => $happen,
					'IP_ADDRESS' => $ipaddr,
					'ACCESS_URL' => $origin,
					'SERVICE_ID' => $client_id,
					'SERVICE_NAME' => $serviceName,
					'SERVICE_PROVIDER' => $serviceProvider,
					'SERVICE_EMAIL' => $serviceEmail,
					'SERVICE_SERVERURL' => $serviceServerurl,
					'SERVICE_SCOPE_FLAG' => $serviceScopeflag,
					'SERVICE_ID_HASH_FLAG' => $serviceIdHashFlag,
				);

				$mailSent = sendMail($options, $from, $to, $template, $params);
				if ($mailSent == TRUE) {
					$log->debug(logformat("DEBUG - OAuth send resource alert succeeded for $client_id from $ipaddr"));
					// 送信成功の場合、カウントをリセットする
					$oauth->resetAccessCount($ipaddr, "resource_request");
				}
				else {
					$log->err(logformat("OAuth send resource alert failed for $client_id from $ipaddr"));
				}
			}
		}
	}
//=============================================================================

	// SAPSエラーファイルチェック
	if (file_exists($conf_sam["saps_error_file"])) {
		$log->err(logformat("SAPS has stopped"));
		$oauth->handleException("500 internal server error", 'system_error03');
	}

	// SAPSへユーザ情報を請求
	$id_type = $conf_sam["id_type"];

	$param  = "?id=$additional_data&passwdchkflg=0";
	$param .= "&crmode1=$crmode1&crmode2=$crmode2&crmode3=$crmode3";
	$param .= "&samode1=$samode1&samode2=$samode2&samode3=$samode3";
	$param .= "&pattern=$pattern";
	$param .= "&id_type=$id_type";

	$saps_uri = $conf_sam['url'].$param;

	// get user info from SAPS start
	$response = $oauth->getContentsByUrl($saps_uri, $conf_sam['auth_timeout']);
	if ($response === FALSE) {
		$log->err(logformat("OAuth get userinfo failed for $client_id: SAPS error"));
		$oauth->handleException("500 internal server error", 'system_error03');
	}
	//$response = mb_check_encoding($response, 'UTF-8') ? $response : utf8_encode($response);
	$response = iconv("SHIFT-JIS", "UTF-8//IGNORE", $response);
	// get user info from SAPS end

//=============================================================================

	// parse response data and return data in json format
	$arr_res = preg_split("/[\n|\r]/", $response);
	$result = array();
	foreach ($arr_res as $value) {
		if ($value) {
			preg_match('/([^=]*)=(.*)$/', $value, $matches);
			$result[$matches[1]] = $matches[2];
		}
	}

	if ($result['return_code'] == 0) {
		$log->debug(logformat("DEBUG - OAuth get userinfo from SAPS succeeded for $client_id"));
	}
	else if ($result['return_code'] == 1) {
		$log->err(logformat("OAuth get userinfo from SAPS failed for $client_id: authentication error"));
		if ($result['error_code'] == '20101' || $result['error_code'] == '50101') {
			//
		}
		else {
			//
		}
		//$oauth->handleException("500 internal server error", 'invalid_user'); // see #205
	}
	else if ($result['return_code'] == -1) {
		$log->err(logformat("OAuth get userinfo from SAPS failed for $client_id: system error"));
		$oauth->handleException("500 internal server error", 'system_error99');
	}
	else if ($result['return_code'] == -2) {
		$log->err(logformat("OAuth get userinfo from SAPS failed for $client_id: parameter error"));
		$oauth->handleException("500 internal server error", 'system_error99');
	}

//=============================================================================

	// IDハッシュフラグ有効の場合、3-5IDをハッシュし、user identifierとしてクライアントSPに渡す
	// ニフティAPIを使ってハッシュを生成する
	if ($serviceIdHashFlag) {
		if ($contents_id) {
			$result['id'] = $contents_id;
			$contents_id = NULL;
		}
		else if (isset($conf['hash_uri']) && $conf['hash_uri']) {
			// ニフティID→ハッシュ変換：ニフティ「コンテンツID情報の発行API」を使用
			$hash_uri = $conf['hash_uri'];
			if (preg_match('/\?/', $hash_uri)) {
				$param_hash_id  = "&niftyId=$username&svcId=$serviceSalt";
			}
			else {
				$param_hash_id  = "?niftyId=$username&svcId=$serviceSalt";
			}

			//=============================================================================
			// リトライ3回まで
			for ($i = 1; $i <= 3; $i++) {
				$res_hash_id = $oauth->getContentsByUrl($hash_uri.$param_hash_id, $conf_sam['auth_timeout']);
				if ($res_hash_id === FALSE) {
					$log->err(logformat("OAuth hash userid failed for $client_id ($i/3)"));
					if ($i == 3) {
						$oauth->handleException("500 internal server error", 'system_error05');
					}
					continue;
				}
				break;
			}
			//=============================================================================

			// the name and value must be enclosed in double quotes
			// single quotes are not valid 
			// the name must be enclosed in double quotes
			// trailing commas are not allowed
			if (preg_match('/json(\?)?$/', $hash_uri)) {
				//$hashed_id = json_decode($res_hash_id, true);
				$json = new Services_JSON();
				$hashed_id = $json->decode($res_hash_id);
				$contents_id = $hashed_id['contentId']['contentId'];
			}
			else if (preg_match('/xml(\?)?$/', $hash_uri)) {
				$xml = simplexml_load_string($res_hash_id);
				$contents_id = (string)$xml->contentId->contentId;
			}
			$result['id'] = $contents_id;
		}
		else {
			$log->err(logformat("OAuth hash userid failed for $client_id: unable to get hash_uri from conf"));
			$oauth->handleException("500 internal server error", 'system_error99');
		}
	}
	else {
		$contents_id = NULL;
	}

//=============================================================================


	// 最終更新日を更新
	// ユーザIDがハッシュされた場合、ユーザIDハッシュをキャッシュする
	// 更新失敗の場合、スルー
	if (!$oauth->updateAuthorizedApps($username, $client_id, NULL, $contents_id)) {
		$log->err(logformat("OAuth update authorization info failed for $client_id: system_error04"));
	}

	$log_scope = "";

	// scopeフラグ（認可画面表示フラグ）チェック
	$userInfo = array();
	if ($serviceScopeflag == TRUE) {
		if (!$approved_scope) {
			$approved_scope = $conf['default_scopes'];
			$log_scope = "with default scpoe '$approved_scope'";
		}
		else {
			$log_scope = "with scpoe '$approved_scope'";
		}

		// scopeによってユーザ情報作成
		$userInfo = $oauth->createUserInfoFromSAPSByScope($result, $approved_scope);
	}
	else {
		// scopeフラグ設定しない場合、SAPSのレスポンスをそのまま返す
		$userInfo = $result;
		$log_scope = "without scope";
	}

//=============================================================================

	// OAuth側ログ出力
	$log->notice(logformat("OAuth approve resource succeeded for $client_id $log_scope"));

	// 連携履歴ログ出力
	if (isset($conf['resource_history_file']) && $conf['resource_history_file']) {
		$resourceHistory = &Log::singleton('file', $conf['resource_history_file'], $logid);
		$resourceHistory->notice(logformat("OAuth approved resource succeeded for $client_id $log_scope"));
	}


	header("Content-Type: application/json");
	header("Cache-Control: no-store");
	echo json_encode($userInfo);
}

?>
