<?php
/* SVN FILE: $Id: OpenIDInterface.php 616 2008-07-20 03:28:17Z bb_yujiro $ */
/**
 * Auth_OpenIDインターフェース
 *
 * PHP versions 5
 *
 *      hitSuji : Social Network Service <http://rakuto.net/rktSNS/>
 *      Copyright (c) 2007-2008 Yujiro Takahashi
 *
 * Licensed under The MIT License
 * Redistributions of files must retain the above copyright notice.
 *
 * @filesource
 * @package         hitSuji
 * @copyright       Copyright (c) 2008 Yujiro Takahashi
 * @link            http://rakuto.net/
 * @author          Yujiro Takahashi <yujiro@rakuto.net>
 * @version         $Revision: 616 $
 * @modifiedby      $LastChangedBy: bb_yujiro $
 * @lastmodified    $Date: 2008-07-20 12:28:17 +0900 (日, 20 7 2008) $
 * @license         http://opensource.org/licenses/mit-license.php The MIT License
 */

define('Auth_OpenID_RAND_SOURCE', null);
define('Auth_Yadis_CURL_OVERRIDE', '1');

require_once LIB_DIR.'PEAR/PEAR.php';
require_once LIB_DIR.'PEAR/Auth/OpenID/Consumer.php';
require_once LIB_DIR.'PEAR/Auth/OpenID/SReg.php';
require_once LIB_DIR.'PEAR/Auth/OpenID/PAPE.php';

require LIB_DIR.'rktAuth/OpenID/Store.php';

/**
 * Auth_OpenIDInterfaceクラス
 *
 * @category        Authentication
 * @package         hitSuji
 * @copyright       Copyright (c) 2008 Yujiro Takahashi
 * @link            http://rakuto.net/
 * @author          Yujiro Takahashi <yujiro@rakuto.net>
 * @version         $Revision: 616 $
 * @modifiedby      $LastChangedBy: bb_yujiro $
 * @lastmodified    $Date: 2008-07-20 12:28:17 +0900 (日, 20 7 2008) $
 * @license         http://opensource.org/licenses/mit-license.php The MIT License
 */
class Auth_OpenIDInterface
{
    /**
     * デフォルトIdentifier
     * @const string
     *
     * OpenID.jp    yujiro.openid.ne.jp
     * Yahoo!JAPAN  yahoo.co.jp
     * はてな       www.hatena.ne.jp/[userid]/
     */
    const DEFAULT_IDENTIFIER = 'yahoo.co.jp';

    /**
     * 認証リクエスト
     * @var object
     */
    private $_request;

    /**
     * 認証結果
     * @var object
     */
    private $_response;

    /**
     * 認証結果
     * @var object
     */
    private $_openid;

    /**
     * トラストルート
     * @var string
     */
    private $_trust;

    /**
     * リターンURL
     * @var string
     */
    private $_return;

    /**
     * コンストラクタ
     *
     * @access public
     * @return void
     */
    public function __construct($trust_root, $return_to)
    {
        $this->_trust  = $trust_root;
        $this->_return = $return_to;
    }

    /**
     * 認証リクエストの設定
     *
     * Example:
     * <code>
     * ?>
     *  $required = array(      // 必須項目
     *      'email',
     *      'nickname',
     *  );
     *  $optional = array(      // オプション
     *      'fullname',
     *      'gender',
     *      'dob',
     *  );
     * $openid->setAuthRequest($required, $optional);
     * <?php
     * </code>
     *
     * @access  public
     * @param array  $required
     * @param array  $optional
     * @param string $identifier
     * @return  void
     * @link http://openid-japan.org/wiki/index.php/OpenID_Simple_Registration_Extension_1.1_-_Draft_1#4._Response_Format
     */
    public function setAuthRequest($required, $optional, $identifier=null)
    {
        $store    =  new Auth_OpenID_Store();
        $consumer =& new Auth_OpenID_Consumer($store);

        /* Nullの場合にデフォルトを使用 */
        if (empty($identifier)){
            $identifier = self::DEFAULT_IDENTIFIER;
        }
        /* OpenIDの取得先を設定 */
        $this->_request = $consumer->begin($identifier);


        /* 取得するプロフィールを指定 */
        $sreg_request = Auth_OpenID_SRegRequest::build($required, $optional);
        $this->_request->addExtension($sreg_request);

        /* ポリシーの設定 */
        $pape_policy_uris = array(
        //    PAPE_AUTH_MULTI_FACTOR_PHYSICAL,
        //    PAPE_AUTH_MULTI_FACTOR,
            PAPE_AUTH_PHISHING_RESISTANT,
        );
        $pape_request = new Auth_OpenID_PAPE_Request($pape_policy_uris);
        $this->_request->addExtension($pape_request);
    }

    /**
     * 認証アクション
     *
     * @access  public
     * @return  string
     */
    public function authAction()
    {
        $check = $this->_request->shouldSendRedirect();

        if ($check) {
            $redirect_url = $this->_request->redirectURL($this->_trust, $this->_return);
            // If the redirect URL can't be built, display an error
            // message.
            if (Auth_OpenID::isFailure($redirect_url)) {
                error_log('-----------  '.date('Y-m-d H:i:s')."  --------------\r\n", 3, ERROR_LOG_FILE);
                error_log($_SERVER['REQUEST_URI']."\r\n", 3, ERROR_LOG_FILE);
                error_log('Could not redirect to server: ' . $redirect_url->message."\r\n", 3, ERROR_LOG_FILE);
                throw new RKT_Exception(RKT_Exception::UNKNOWN_ERROR);
            } else {
                // Send redirect.
                header("Location: ".$redirect_url);
                exit();
            }
        } else {
            // Generate form markup and render it.
            $form_id = 'openid_message';
            $form_html = $this->_request->htmlMarkup($this->_trust, $this->_return,
                                                   false, array('id' => $form_id));
            // Display an error if the form markup couldn't be generated;
            // otherwise, render the HTML.
            if (Auth_OpenID::isFailure($form_html)) {
                error_log('-----------  '.date('Y-m-d H:i:s')."  --------------\r\n", 3, ERROR_LOG_FILE);
                error_log($_SERVER['REQUEST_URI']."\r\n", 3, ERROR_LOG_FILE);
                error_log('Could not redirect to server: ' . $form_html->message."\r\n", 3, ERROR_LOG_FILE);
                throw new RKT_Exception(RKT_Exception::UNKNOWN_ERROR);
            } else {
                exit($form_html);
            }
        }
    }

    /**
     * 認証結果の設定
     *
     * @access  public
     * @return  void
     */
    public function setResponse()
    {
        $store    =  new Auth_OpenID_Store();
        $consumer =& new Auth_OpenID_Consumer($store);

        $this->_response = $consumer->complete($this->_return);

        if ($this->_response->status == Auth_OpenID_SUCCESS) {
            $this->_openid = $this->_response->getDisplayIdentifier();
        }

        if ($this->_response->endpoint->canonicalID) {
            $this->_openid = $this->_response->endpoint->canonicalID;
        }
    }
    
    /**
     * OpenIDの取得
     *
     * @access public
     * @return string
     */
    public function getOpenID()
    {
        return $this->_openid;
    }

    /**
     * 結果メッセージの取得
     *
     * @access  public
     * @return  string
     */
    public function getResponseMessage()
    {
        // Check the response status.
        if ($this->_response->status == Auth_OpenID_CANCEL) {
            // This means the authentication was cancelled.
            $msg = _('Verification cancelled.');
        } else if ($this->_response->status == Auth_OpenID_FAILURE) {
            // Authentication failed; display the error message.
            $msg = _('OpenID authentication failed: ') . $this->_response->message;
        } else if ($this->_response->status == Auth_OpenID_SUCCESS) {
            $esc_identity = htmlentities($this->_openid);

            $msg = sprintf(_('You have successfully verified <a href="%1$s">%1$s</a> as your identity.'),
                           $esc_identity);
        }
        return $msg;
    }

    /**
     * リクエストデータの取得
     *
     * @access public
     * @return array
     */
    public function getResponseRequest()
    {
        $sreg_resp = Auth_OpenID_SRegResponse::fromSuccessResponse($this->_response);
        $sreg = $sreg_resp->contents();

        return $sreg;
    }

    /**
     * レスポンスステータスの取得
     *
     * @access public
     * @return integer
     */
    public function getResponseStatus()
    {
        return $this->_response->status;
    }
} // Auth_OpenIDInterface
?>