From a789b5502a21b21b01513c2d61f6501274947c76 Mon Sep 17 00:00:00 2001 From: Artem Konenko <yadummer@gmail.com> Date: Tue, 11 Oct 2016 20:52:41 +0300 Subject: [PATCH] #138 Add library for OpenID --- ~dev_rating/application/classes/OpenID.php | 342 +++++++++++++++++++++ 1 file changed, 342 insertions(+) create mode 100644 ~dev_rating/application/classes/OpenID.php diff --git a/~dev_rating/application/classes/OpenID.php b/~dev_rating/application/classes/OpenID.php new file mode 100644 index 000000000..af53f22dd --- /dev/null +++ b/~dev_rating/application/classes/OpenID.php @@ -0,0 +1,342 @@ +<?php defined('SYSPATH') OR die('No direct script access.'); + +class OpenID +{ + public $openid_url_identity; + public $google_openid = 0; + public $openid_user = ''; + public $URLs = []; + public $error = []; + public $fields = [ + 'required' => [], + 'optional' => [], + ]; + + public function __construct() + { + } + + + public function SetOpenIDUser($s) + { + $this->openid_user = $s; + } + + public function GetOpenIDUser() + { + if (!empty($_GET['openid_ext1_value_firstname']) && !empty($_GET['openid_ext1_type_lastname'])) { + return urldecode($_GET['openid_ext1_value_firstname'] . ' ' . $_GET['openid_ext1_value_lastname']); + } else if (!empty($_GET['openid_ext1_value_email'])) { + return urldecode($_GET['openid_ext1_value_email']); + } else { + $id = $this->GetIdentity(); + if (preg_match('/^http[s]*:\/\/([\S]+)$/', $id, $arr)) { + if (strrpos($arr[1], '/') == strlen($arr[1]) - 1) { + return substr($arr[1], 0, strlen($arr[1]) - 1); + } else { + return $arr[1]; + } + } else { + return $id; + } + } + } + + public function SetGoogleOpenID() + { + $this->google_openid = 1; + } + + public function SimpleOpenID() + { + if (!function_exists('curl_exec')) { + die('Error: Class SimpleOpenID requires curl extension to work'); + } + } + + public function SetOpenIDServer($a) + { + $this->URLs['openid_server'] = $a; + } + + public function SetTrustRoot($a) + { + $this->URLs['trust_root'] = $a; + } + + public function SetCancelURL($a) + { + $this->URLs['cancel'] = $a; + } + + public function SetApprovedURL($a) + { + $this->URLs['approved'] = $a; + } + + public function SetRequiredFields($a) + { + if (is_array($a)) { + $this->fields['required'] = $a; + } else { + $this->fields['required'][] = $a; + } + } + + public function SetOptionalFields($a) + { + if (is_array($a)) { + $this->fields['optional'] = $a; + } else { + $this->fields['optional'][] = $a; + } + } + + public function SetIdentity($a) + { + if ((stripos($a, 'http://') === false) && (stripos($a, 'https://') === false)) { + $a = 'http://' . $a; + } + $this->openid_url_identity = $a; + } + + public function GetIdentity() + { + return $this->openid_url_identity; + } + + public function GetError() + { + $e = $this->error; + return ['code' => $e[0], 'description' => $e[1]]; + } + + public function ErrorStore($code, $desc = null) + { + $errs['OPENID_NOSERVERSFOUND'] = 'Cannot find OpenID Server TAG on Identity page.'; + if ($desc == null) { + $desc = $errs[$code]; + } + $this->error = [$code, $desc]; + } + + public function IsError() + { + if (count($this->error) > 0) { + return true; + } else { + return false; + } + } + + public function splitResponse($response) + { + $r = array(); + $response = explode("\n", $response); + foreach ($response as $line) { + $line = trim($line); + if ($line != "") { + list($key, $value) = explode(":", $line, 2); + $r[trim($key)] = trim($value); + } + } + return $r; + } + + public function OpenID_Standarize($openid_identity = null) + { + if ($openid_identity === null) + $openid_identity = $this->openid_url_identity; + + $u = parse_url(strtolower(trim($openid_identity))); + + if (!isset($u['path']) || ($u['path'] == '/')) { + $u['path'] = ''; + } + if (substr($u['path'], -1, 1) == '/') { + $u['path'] = substr($u['path'], 0, strlen($u['path']) - 1); + } + if (isset($u['query'])) { + return $u['host'] . $u['path'] . '?' . $u['query']; + } else { + return $u['host'] . $u['path']; + } + } + + public function array2url($arr) + { + if (!is_array($arr)) { + return false; + } + $query = ''; + foreach ($arr as $key => $value) { + $query .= $key . "=" . $value . "&"; + } + return $query; + } + + public function FSOCK_Request($url, $method = "GET", $params = "") + { + $fp = fsockopen("ssl://www.myopenid.com", 443, $errno, $errstr, 3); + if (!$fp) { + $this->ErrorStore('OPENID_SOCKETERROR', $errstr); + return false; + } else { + $request = $method . " /server HTTP/1.0\r\n"; + $request .= "User-Agent: Simple OpenID PHP Class (http://www.phpclasses.org/simple_openid)\r\n"; + $request .= "Connection: close\r\n\r\n"; + fwrite($fp, $request); + stream_set_timeout($fp, 4); + $res = fread($fp, 2000); + $info = stream_get_meta_data($fp); + fclose($fp); + + if ($info['timed_out']) { + $this->ErrorStore('OPENID_SOCKETTIMEOUT'); + } else { + return $res; + } + } + return false; + } + + public function CURL_Request($url, $method = "GET", $params = "") + { + + $url = trim($url); + if (is_array($params)) $params = $this->array2url($params); + $curl = curl_init($url . ($method == "GET" && $params != "" ? "?" . $params : "")); + curl_setopt($curl, CURLOPT_FOLLOWLOCATION, true); + curl_setopt($curl, CURLOPT_HEADER, false); + curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false); + curl_setopt($curl, CURLOPT_HTTPGET, ($method == "GET")); + curl_setopt($curl, CURLOPT_POST, ($method == "POST")); + if ($method == "POST") curl_setopt($curl, CURLOPT_POSTFIELDS, $params); + curl_setopt($curl, CURLOPT_RETURNTRANSFER, true); + $response = curl_exec($curl); + + if (curl_errno($curl) == 0) { + return $response; + } else { + $this->ErrorStore('OPENID_CURL', curl_error($curl)); + } + return $response; + } + + public function HTML2OpenIDServer($content) + { + if (preg_match('/<xrds:/', $content)) { + $this->SetGoogleOpenID(); + preg_match_all('/<URI>([^>]*)<\/URI>/', $content, $servers); + $ret = array($servers[1], array()); + } else { + preg_match_all('/<link[^>]*rel=[\'"][openid2.provider ]*openid.server[\'"][^>]*href=[\'"]([^\'"]+)[\'"][^>]*\/?>/', $content, $matches1); + preg_match_all('/<link[^>]*href=\'"([^\'"]+)[\'"][^>]*rel=[\'"]openid.server[\'"][^>]*\/?>/', $content, $matches2); + + $servers = array_merge($matches1[1], $matches2[1]); + + preg_match_all('/<link[^>]*rel=[\'"]openid.delegate[\'"][^>]*href=[\'"]([^\'"]+)[\'"][^>]*\/?>/', $content, $matches1); + + preg_match_all('/<link[^>]*href=[\'"]([^\'"]+)[\'"][^>]*rel=[\'"]openid.delegate[\'"][^>]*\/?>/', $content, $matches2); + + $delegates = array_merge($matches1[1], $matches2[1]); + + $ret = [$servers, $delegates]; + } + + + return $ret; + } + + public function GetOpenIDServer() + { + + $response = $this->CURL_Request($this->openid_url_identity); + list($servers, $delegates) = $this->HTML2OpenIDServer($response); + + if (count($servers) == 0) { + $this->ErrorStore('OPENID_NOSERVERSFOUND'); + return false; + } + if (isset($delegates[0]) + && ($delegates[0] != "") + ) { + $this->SetIdentity($delegates[0]); + } + $this->SetOpenIDServer($servers[0]); + return $servers[0]; + } + + public function GetRedirectURL() + { + $params = array(); + $params['openid.return_to'] = urlencode($this->URLs['approved']); + $params['openid.mode'] = 'checkid_setup'; + $params['openid.identity'] = urlencode($this->openid_url_identity); + $params['openid.trust_root'] = urlencode($this->URLs['trust_root']); + $params['openid.ns'] = urlencode('http://specs.openid.net/auth/2.0'); + $params['openid.claimed_id'] = urlencode($this->openid_url_identity); + $params['openid.realm'] = urlencode($this->URLs['trust_root']); + $params['openid.ns.sreg'] = 'http://openid.net/extensions/sreg/1.1'; + if (isset($this->fields['required']) + && (count($this->fields['required']) > 0) + ) { + $params['openid.sreg.required'] = urlencode(implode(',', $this->fields['required'])); + } + if (isset($this->fields['optional']) + && (count($this->fields['optional']) > 0) + ) { + $params['openid.sreg.optional'] = urlencode(implode(',', $this->fields['optional'])); + } + return $this->URLs['openid_server'] . "?" . $this->array2url($params); + } + + public function Redirect() + { + $redirect_to = $this->GetRedirectURL(); + if (headers_sent()) { + echo 'sent'; + echo '<script language="JavaScript" type="text/javascript">window.location=\''; + echo $redirect_to; + echo '\';</script>'; + } else { + //echo 'not sent: '.$redirect_to; + header('Location: ' . $redirect_to, true); + die(); + } + } + + public function ValidateWithServer() + { + + $params = [ + 'openid.assoc_handle' => urlencode($_GET['openid_assoc_handle']), + 'openid.signed' => urlencode($_GET['openid_signed']), + 'openid.sig' => urlencode($_GET['openid_sig']) + ]; + $arr_signed = explode(",", str_replace('sreg.', 'sreg_', $_GET['openid_signed'])); + for ($i = 0; $i < count($arr_signed); $i++) { + $s = str_replace('sreg_', 'sreg.', $arr_signed[$i]); + $c = @$_GET['openid_' . $arr_signed[$i]]; + $params['openid.' . $s] = urlencode($c); + } + $params['openid.mode'] = "check_authentication"; + + $openid_server = $this->GetOpenIDServer(); + + if ($openid_server == false) { + return false; + } elseif (preg_match('/[google.com|gmail.com|googlemail.com]/', $openid_server)) { + return true; + } + + $response = $this->CURL_Request($openid_server, 'POST', $params); + $data = $this->splitResponse($response); + + if ($data['is_valid'] == "true") { + return true; + } else { + return false; + } + } +} \ No newline at end of file -- GitLab