PageRenderTime 84ms CodeModel.GetById 25ms RepoModel.GetById 0ms app.codeStats 0ms

/www/protected/extensions/eauth-old/EAuthServiceBase.php

https://bitbucket.org/badenkov/demo
PHP | 485 lines | 223 code | 57 blank | 205 comment | 22 complexity | 82df2295759d156c51a75c96c046ea27 MD5 | raw file
Possible License(s): Apache-2.0, MIT, LGPL-2.1, BSD-2-Clause, CC-BY-SA-3.0, BSD-3-Clause
  1. <?php
  2. /**
  3. * EAuthServiceBase class file.
  4. *
  5. * @author Maxim Zemskov <nodge@yandex.ru>
  6. * @link http://code.google.com/p/yii-eauth/
  7. * @license http://www.opensource.org/licenses/bsd-license.php
  8. */
  9. require_once 'IAuthService.php';
  10. /**
  11. * EAuthServiceBase is a base class for providers.
  12. * @package application.extensions.eauth
  13. */
  14. abstract class EAuthServiceBase extends CComponent implements IAuthService {
  15. /**
  16. * @var string the service name.
  17. */
  18. protected $name;
  19. /**
  20. *
  21. * @var string the service title to display in views.
  22. */
  23. protected $title;
  24. /**
  25. * @var string the service type (e.g. OpenID, OAuth).
  26. */
  27. protected $type;
  28. /**
  29. * @var array arguments for the jQuery.eauth() javascript function.
  30. */
  31. protected $jsArguments = array();
  32. /**
  33. * @var array authorization attributes.
  34. * @see getAttribute
  35. * @see getItem
  36. */
  37. protected $attributes = array();
  38. /**
  39. * @var boolean whether user was successfuly authenticated.
  40. * @see getIsAuthenticated
  41. */
  42. protected $authenticated = false;
  43. /**
  44. * @var boolean whether is attributes was fetched.
  45. */
  46. private $fetched = false;
  47. /**
  48. * @var EAuth the {@link EAuth} application component.
  49. */
  50. private $component;
  51. /**
  52. * @var string the redirect url after successful authorization.
  53. */
  54. private $redirectUrl = '';
  55. /**
  56. * @var string the redirect url after unsuccessful authorization (e.g. user canceled).
  57. */
  58. private $cancelUrl = '';
  59. /**
  60. * PHP getter magic method.
  61. * This method is overridden so that service attributes can be accessed like properties.
  62. * @param string $name property name.
  63. * @return mixed property value.
  64. * @see getAttribute
  65. */
  66. public function __get($name) {
  67. if ($this->hasAttribute($name))
  68. return $this->getAttribute($name);
  69. else
  70. return parent::__get($name);
  71. }
  72. /**
  73. * Checks if a attribute value is null.
  74. * This method overrides the parent implementation by checking
  75. * if the attribute is null or not.
  76. * @param string $name the attribute name.
  77. * @return boolean whether the attribute value is null.
  78. */
  79. public function __isset($name) {
  80. if ($this->hasAttribute($name))
  81. return true;
  82. else
  83. return parent::__isset($name);
  84. }
  85. /**
  86. * Initialize the component.
  87. * Sets the default {@link redirectUrl} and {@link cancelUrl}.
  88. * @param EAuth $component the component instance.
  89. * @param array $options properties initialization.
  90. */
  91. public function init($component, $options = array()) {
  92. if (isset($component))
  93. $this->setComponent($component);
  94. foreach ($options as $key => $val)
  95. $this->$key = $val;
  96. $this->setRedirectUrl(Yii::app()->user->returnUrl);
  97. $server = Yii::app()->request->getHostInfo();
  98. $path = Yii::app()->request->getPathInfo();
  99. $this->setCancelUrl($server.'/'.$path);
  100. }
  101. /**
  102. * Returns service name(id).
  103. * @return string the service name(id).
  104. */
  105. public function getServiceName() {
  106. return $this->name;
  107. }
  108. /**
  109. * Returns service title.
  110. * @return string the service title.
  111. */
  112. public function getServiceTitle() {
  113. return $this->title;
  114. }
  115. /**
  116. * Returns service type (e.g. OpenID, OAuth).
  117. * @return string the service type (e.g. OpenID, OAuth).
  118. */
  119. public function getServiceType() {
  120. return $this->type;
  121. }
  122. /**
  123. * Returns arguments for the jQuery.eauth() javascript function.
  124. * @return array the arguments for the jQuery.eauth() javascript function.
  125. */
  126. public function getJsArguments() {
  127. return $this->jsArguments;
  128. }
  129. /**
  130. * Sets {@link EAuth} application component
  131. * @param EAuth $component the application auth component.
  132. */
  133. public function setComponent($component) {
  134. $this->component = $component;
  135. }
  136. /**
  137. * Returns the {@link EAuth} application component.
  138. * @return EAuth the {@link EAuth} application component.
  139. */
  140. public function getComponent() {
  141. return $this->component;
  142. }
  143. /**
  144. * Sets redirect url after successful authorization.
  145. * @param string url to redirect.
  146. */
  147. public function setRedirectUrl($url) {
  148. $this->redirectUrl = $url;
  149. }
  150. /**
  151. * Returns the redirect url after successful authorization.
  152. * @return string the redirect url after successful authorization.
  153. */
  154. public function getRedirectUrl() {
  155. return $this->redirectUrl;
  156. }
  157. /**
  158. * Sets redirect url after unsuccessful authorization (e.g. user canceled).
  159. * @param string url to redirect.
  160. */
  161. public function setCancelUrl($url) {
  162. $this->cancelUrl = $url;
  163. }
  164. /**
  165. * Returns the redirect url after unsuccessful authorization (e.g. user canceled).
  166. * @return string the redirect url after unsuccessful authorization (e.g. user canceled).
  167. */
  168. public function getCancelUrl() {
  169. return $this->cancelUrl;
  170. }
  171. /**
  172. * Authenticate the user.
  173. * @return boolean whether user was successfuly authenticated.
  174. */
  175. public function authenticate() {
  176. return $this->getIsAuthenticated();
  177. }
  178. /**
  179. * Whether user was successfuly authenticated.
  180. * @return boolean whether user was successfuly authenticated.
  181. */
  182. public function getIsAuthenticated() {
  183. return $this->authenticated;
  184. }
  185. /**
  186. * Redirect to the url. If url is null, {@link redirectUrl} will be used.
  187. * @param string $url url to redirect.
  188. */
  189. public function redirect($url = null) {
  190. $this->component->redirect(isset($url) ? $url : $this->redirectUrl, true);
  191. }
  192. /**
  193. * Redirect to the {@link cancelUrl} or simply close the popup window.
  194. */
  195. public function cancel($url = null) {
  196. $this->component->redirect(isset($url) ? $url : $this->cancelUrl, false);
  197. }
  198. /**
  199. * Makes the curl request to the url.
  200. * @param string $url url to request.
  201. * @param array $options HTTP request options. Keys: query, data, referer.
  202. * @param boolean $parseJson Whether to parse response in json format.
  203. * @return string the response.
  204. */
  205. protected function makeRequest($url, $options = array(), $parseJson = true) {
  206. $ch = $this->initRequest($url, $options);
  207. if (isset($options['referer']))
  208. curl_setopt($ch, CURLOPT_REFERER, $options['referer']);
  209. if (isset($options['query'])) {
  210. $url_parts = parse_url($url);
  211. if (isset($url_parts['query'])) {
  212. $old_query = http_build_query($url_parts['query']);
  213. $url_parts['query'] = array_merge($url_parts['query'], $options['query']);
  214. $new_query = http_build_query($url_parts['query']);
  215. $url = str_replace($old_query, $new_query, $url);
  216. }
  217. else {
  218. $url_parts['query'] = $options['query'];
  219. $new_query = http_build_query($url_parts['query']);
  220. $url .= '?'.$new_query;
  221. }
  222. }
  223. if (isset($options['data'])) {
  224. curl_setopt($ch, CURLOPT_POST, 1);
  225. curl_setopt($ch, CURLOPT_POSTFIELDS, $options['data']);
  226. }
  227. curl_setopt($ch, CURLOPT_URL, $url);
  228. $result = curl_exec($ch);
  229. $headers = curl_getinfo($ch);
  230. if (curl_errno($ch) > 0)
  231. throw new EAuthException(curl_error($ch), curl_errno($ch));
  232. if ($headers['http_code'] != 200) {
  233. Yii::log(
  234. 'Invalid response http code: '.$headers['http_code'].'.'.PHP_EOL.
  235. 'URL: '.$url.PHP_EOL.
  236. 'Options: '.var_export($options, true).PHP_EOL.
  237. 'Result: '.$result,
  238. CLogger::LEVEL_ERROR, 'application.extensions.eauth'
  239. );
  240. throw new EAuthException('Invalid response http code: '.$headers['http_code'].'.', $headers['http_code']);
  241. }
  242. curl_close($ch);
  243. if ($parseJson)
  244. $result = $this->parseJson($result);
  245. return $result;
  246. }
  247. /**
  248. * Initializes a new session and return a cURL handle.
  249. * @param string $url url to request.
  250. * @param array $options HTTP request options. Keys: query, data, referer.
  251. * @param boolean $parseJson Whether to parse response in json format.
  252. * @return cURL handle.
  253. */
  254. protected function initRequest($url, $options = array()) {
  255. $ch = curl_init();
  256. //curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1); // error with open_basedir or safe mode
  257. curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 0);
  258. curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
  259. curl_setopt($ch, CURLOPT_HEADER, 0);
  260. curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
  261. return $ch;
  262. }
  263. /**
  264. * Parse response from {@link makeRequest} in json format and check OAuth errors.
  265. * @param string $response Json string.
  266. * @return object result.
  267. */
  268. protected function parseJson($response) {
  269. try {
  270. $result = json_decode($response);
  271. $error = $this->fetchJsonError($result);
  272. if (!isset($result)) {
  273. throw new EAuthException('Invalid response format.', 500);
  274. }
  275. else if (isset($error)) {
  276. throw new EAuthException($error['message'], $error['code']);
  277. }
  278. else
  279. return $result;
  280. }
  281. catch(Exception $e) {
  282. throw new EAuthException($e->getMessage(), $e->getCode());
  283. }
  284. }
  285. /**
  286. * Returns the error info from json.
  287. * @param stdClass $json the json response.
  288. * @return array the error array with 2 keys: code and message. Should be null if no errors.
  289. */
  290. protected function fetchJsonError($json) {
  291. if (isset($json->error)) {
  292. return array(
  293. 'code' => 500,
  294. 'message' => 'Unknown error occurred.',
  295. );
  296. }
  297. else
  298. return null;
  299. }
  300. /**
  301. * @return string a prefix for the name of the session variables storing eauth session data.
  302. */
  303. protected function getStateKeyPrefix() {
  304. return '__eauth_'.$this->getServiceName().'__';
  305. }
  306. /**
  307. * Stores a variable in eauth session.
  308. * @param string $key variable name.
  309. * @param mixed $value variable value.
  310. * @param mixed $defaultValue default value. If $value===$defaultValue, the variable will be
  311. * removed from the session.
  312. * @see getState
  313. */
  314. protected function setState($key, $value, $defaultValue = null) {
  315. $session = Yii::app()->session;
  316. $key = $this->getStateKeyPrefix().$key;
  317. if($value === $defaultValue)
  318. unset($session[$key]);
  319. else
  320. $session[$key] = $value;
  321. }
  322. /**
  323. * Returns a value indicating whether there is a state of the specified name.
  324. * @param string $key state name.
  325. * @return boolean whether there is a state of the specified name.
  326. */
  327. protected function hasState($key) {
  328. $session = Yii::app()->session;
  329. $key = $this->getStateKeyPrefix().$key;
  330. return isset($session[$key]);
  331. }
  332. /**
  333. * Returns the value of a variable that is stored in eauth session.
  334. * @param string $key variable name.
  335. * @param mixed $defaultValue default value.
  336. * @return mixed the value of the variable. If it doesn't exist in the session,
  337. * the provided default value will be returned.
  338. * @see setState
  339. */
  340. protected function getState($key, $defaultValue = null) {
  341. $session = Yii::app()->session;
  342. $key = $this->getStateKeyPrefix().$key;
  343. return isset($session[$key]) ? $session[$key] : $defaultValue;
  344. }
  345. /**
  346. * Fetch attributes array.
  347. * @return boolean whether the attributes was successfully fetched.
  348. */
  349. protected function fetchAttributes() {
  350. return true;
  351. }
  352. /**
  353. * Fetch attributes array.
  354. * This function is internally used to handle fetched state.
  355. */
  356. protected function _fetchAttributes() {
  357. if (!$this->fetched) {
  358. $this->fetched = true;
  359. $result = $this->fetchAttributes();
  360. if (isset($result))
  361. $this->fetched = $result;
  362. }
  363. }
  364. /**
  365. * Returns the user unique id.
  366. * @return mixed the user id.
  367. */
  368. public function getId() {
  369. $this->_fetchAttributes();
  370. return $this->attributes['id'];
  371. }
  372. /**
  373. * Returns the array that contains all available authorization attributes.
  374. * @return array the attributes.
  375. */
  376. public function getAttributes() {
  377. $this->_fetchAttributes();
  378. $attributes = array();
  379. foreach ($this->attributes as $key => $val) {
  380. $attributes[$key] = $this->getAttribute($key);
  381. }
  382. return $attributes;
  383. }
  384. /**
  385. * Returns the authorization attribute value.
  386. * @param string $key the attribute name.
  387. * @param mixed $default the default value.
  388. * @return mixed the attribute value.
  389. */
  390. public function getAttribute($key, $default = null) {
  391. $this->_fetchAttributes();
  392. $getter = 'get'.$key;
  393. if (method_exists($this, $getter))
  394. return $this->$getter();
  395. else
  396. return isset($this->attributes[$key]) ? $this->attributes[$key] : $default;
  397. }
  398. /**
  399. * Whether the authorization attribute exists.
  400. * @param string $key the attribute name.
  401. * @return boolean true if attribute exists, false otherwise.
  402. */
  403. public function hasAttribute($key) {
  404. $this->_fetchAttributes();
  405. return isset($this->attributes[$key]);
  406. }
  407. /**
  408. * Returns the object with a human-readable representation of the current authorization.
  409. * @return stdClass the object.
  410. */
  411. public function getItem() {
  412. $item = new stdClass;
  413. $item->title = $this->getAttribute('name');
  414. if (empty($this->title))
  415. $item->title = $this->getId();
  416. if ($this->hasAttribute('url'))
  417. $item->url = $this->getAttribute('url');
  418. return $item;
  419. }
  420. /**
  421. * Returns the array that contains all available authorization attributes.
  422. * @return array the attributes.
  423. * @deprecated because getAttributes is more semantic.
  424. */
  425. public function getItemAttributes() {
  426. return $this->getAttributes();
  427. }
  428. }