<?php
/*
* @package LabCMS
* @copyright (c) 2006 Alexander Levin aka Loki (loki_angel@mail.ru)
* @support http://labcms.ru
* @license http://opensource.org/licenses/gpl-license.php GNU Public License
*/


// Если не поддерживается random, сбрасываем переменную в null
define('Auth_OpenID_RAND_SOURCE', null);

class OpenId
{
    public $required=array();
    public $optional=array();
    public $returnTo=null;
    
    public function SendOpenId($openid)
    {
        $consumer = $this->getConsumer();
        // Начало процесса OpenID авторизации
        $auth_request = $consumer->begin(trim($openid));
        // No auth request means we can't begin OpenID.
        if (!$auth_request) 
        {
            $this->error("Некорректный OpenID.");
            return false;
        }
        
        if (!empty($this->required) || !empty($this->optional))
        {
            require_once LAB_PATH_KERNEL.'/classes/Auth/OpenID/SReg.php';
            if (Auth_OpenID_supportsSReg($auth_request->endpoint))
            {
                $sreg_req = Auth_OpenID_SRegRequest::build($this->required, $this->optional);
                $auth_request->addExtension($sreg_req);
            }
            else
            {
                require_once LAB_PATH_KERNEL.'/classes/Auth/OpenID/AXWrapper.php';
                if ($auth_request->endpoint->usesExtension(Auth_OpenID_AX_NS_URI))
                {
                    $ax=Auth_OpenID_AXmake($this->required, $this->optional);
                    // Add AX fetch request to authentication request
                    $auth_request->addExtension($ax);
                }
            }
        }

        if (!$this->returnTo) $this->returnTo=$this->getReturnTo();
        // Редирект пользователя на OpenID server для авторизации.
        // Для OpenID 1, делаем редирект.  Для OpenID 2, используем форму для  отправки POST
        if ($auth_request->shouldSendRedirect())
        {
            $redirect_url = $auth_request->redirectURL($this->getTrustRoot(),$this->returnTo);
            // Если redirect URL не может быть сформирован, выведем сообщение об ошибках.
            if (Auth_OpenID::isFailure($redirect_url)) 
            {
                $this->error("Не могу перенаправить на сервер: ");
                $this->error($redirect_url->message, true);
                return false;
            } 
            else
            {
                // Делаем редирект.
                refresh('', $redirect_url);
            }
        } 
        else
        {
            // Создаем форму для JS-редиректа
            $form_id = 'openid_message';
            $form_html = $auth_request->formMarkup($this->getTrustRoot(), $this->returnTo,
            false, array('id' => $form_id));
            // Сделаем форму невидимой
            $s = " style=\"display:none\" ";
            $form_html = str_replace("<form","<form $s",$form_html);

            // Отправляем форму
            if (Auth_OpenID::isFailure($form_html)) 
            {
                $this->error("Не могу перенаправить на сервер: " . $form_html->message);
                return false;
            }
            else
            {
                $page_contents = array(
                "<html><body 
                onload='document.getElementById(\"".$form_id."\").submit()'>",  
                $form_html,"</body></html>");
                print implode("\n", $page_contents);
                
            }
        }
        exit;
    }
    
    function getConsumer()
    {
        // Создание клиентского объекта
        $store =  new Auth_OpenID_FileStore(LAB_PATH_DATA.'/cache');
        return new Auth_OpenID_Consumer($store);
    }

    function getScheme()
    {
        $scheme = 'http';
        if (isset($_SERVER['HTTPS']) and $_SERVER['HTTPS'] == 'on')
        {
            $scheme .= 's';
        }
        return $scheme;
    }

    function getReturnTo()
    {
        
        $u=parse_url($_SERVER['REQUEST_URI']);
        $s = $this->getScheme()."://".$_SERVER['HTTP_HOST'].$u['path'];
        if(!empty($u['query']))
        {
            $u['query']=explode('&', $u['query']);
            foreach($u['query'] as $key=>$var)
            {
                if(substr($var, 0, 7)=='openid.') unset($u['query'][$key]);
            }
            $u['query']='?'.implode('&', $u['query']);
            $s.=$u['query'];
        }
        return $s;
    }

    function getTrustRoot()
    {
        $s = $this->getScheme()."://".$_SERVER['HTTP_HOST'];
        return $s;
    }
    
    public function CheckAuthByOpenId()
    {
        $consumer = $this->getConsumer();

        $response = $consumer->complete($this->getReturnTo());
        if($response->status == Auth_OpenID_SUCCESS)
        {
            if (!empty($_GET['openid_ns_sreg']))
            {
                $sreg_resp = Auth_OpenID_SRegResponse::fromSuccessResponse($response);
                $sreg_resp->data['openid'] = $response->getDisplayIdentifier();
                return $sreg_resp->data;
            }
            elseif(!empty($_GET['openid_ext1_mode']))
            {
                require_once LAB_PATH_KERNEL.'/classes/Auth/OpenID/AXWrapper.php';
                $data=Auth_OpenID_AXResponse($response);
                $data['openid'] = $response->getDisplayIdentifier();
                return $data;
            }
            else
            return $response->getDisplayIdentifier();
        }
        if ($response->status == Auth_OpenID_CANCEL)
        {
            $this->error("Проверка отменена.");
        }
        elseif($response->status == Auth_OpenID_FAILURE)
        {
            $this->error("Аутентификация не удалась: ");
            $this->error($response->message, true);
        }
        return false;
    }

    private function error($mess, $html=false)
    {
        if (LabCMS::is_object())
        {
            if ($html) LabCMS::i()->error(_m($mess), true);
            else LabCMS::i()->error($mess);
        }
	else die($mess);
    }
}