PageRenderTime 55ms CodeModel.GetById 17ms RepoModel.GetById 1ms app.codeStats 1ms

/library/Zend/OpenId/Provider/Storage/File.php

http://github.com/zendframework/zf2
PHP | 444 lines | 317 code | 14 blank | 113 comment | 49 complexity | 5c415be01060556fba46406435749568 MD5 | raw file
Possible License(s): BSD-3-Clause
  1. <?php
  2. /**
  3. * Zend Framework
  4. *
  5. * LICENSE
  6. *
  7. * This source file is subject to the new BSD license that is bundled
  8. * with this package in the file LICENSE.txt.
  9. * It is also available through the world-wide-web at this URL:
  10. * http://framework.zend.com/license/new-bsd
  11. * If you did not receive a copy of the license and are unable to
  12. * obtain it through the world-wide-web, please send an email
  13. * to license@zend.com so we can send you a copy immediately.
  14. *
  15. * @category Zend
  16. * @package Zend_OpenId
  17. * @subpackage Zend_OpenId_Provider
  18. * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
  19. * @license http://framework.zend.com/license/new-bsd New BSD License
  20. */
  21. /**
  22. * @namespace
  23. */
  24. namespace Zend\OpenId\Provider\Storage;
  25. use Zend\OpenId;
  26. /**
  27. * External storage implemmentation using serialized files
  28. *
  29. * @uses Zend\OpenId\Exception
  30. * @uses Zend\OpenId\Provider\Storage
  31. * @category Zend
  32. * @package Zend_OpenId
  33. * @subpackage Zend_OpenId_Provider
  34. * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
  35. * @license http://framework.zend.com/license/new-bsd New BSD License
  36. */
  37. class File extends AbstractStorage
  38. {
  39. /**
  40. * Directory name to store data files in
  41. *
  42. * @var string $_dir
  43. */
  44. private $_dir;
  45. /**
  46. * Constructs storage object and creates storage directory
  47. *
  48. * @param string $dir directory name to store data files in
  49. * @throws Zend\OpenId\Exception
  50. */
  51. public function __construct($dir = null)
  52. {
  53. if ($dir === null) {
  54. $tmp = getenv('TMP');
  55. if (empty($tmp)) {
  56. $tmp = getenv('TEMP');
  57. if (empty($tmp)) {
  58. $tmp = "/tmp";
  59. }
  60. }
  61. $user = get_current_user();
  62. if (is_string($user) && !empty($user)) {
  63. $tmp .= '/' . $user;
  64. }
  65. $dir = $tmp . '/openid/provider';
  66. }
  67. $this->_dir = $dir;
  68. if (!is_dir($this->_dir)) {
  69. if (!@mkdir($this->_dir, 0700, 1)) {
  70. throw new OpenId\Exception(
  71. "Cannot access storage directory $dir",
  72. OpenId\Exception::ERROR_STORAGE);
  73. }
  74. }
  75. if (($f = fopen($this->_dir.'/assoc.lock', 'w+')) === null) {
  76. throw new OpenId\Exception(
  77. 'Cannot create a lock file in the directory ' . $dir,
  78. OpenId\Exception::ERROR_STORAGE);
  79. }
  80. fclose($f);
  81. if (($f = fopen($this->_dir.'/user.lock', 'w+')) === null) {
  82. throw new OpenId\Exception(
  83. 'Cannot create a lock file in the directory ' . $dir,
  84. OpenId\Exception::ERROR_STORAGE);
  85. }
  86. fclose($f);
  87. }
  88. /**
  89. * Stores information about session identified by $handle
  90. *
  91. * @param string $handle assiciation handle
  92. * @param string $macFunc HMAC function (sha1 or sha256)
  93. * @param string $secret shared secret
  94. * @param string $expires expiration UNIX time
  95. * @return bool
  96. */
  97. public function addAssociation($handle, $macFunc, $secret, $expires)
  98. {
  99. $name = $this->_dir . '/assoc_' . md5($handle);
  100. $lock = @fopen($this->_dir . '/assoc.lock', 'w+');
  101. if ($lock === false) {
  102. return false;
  103. }
  104. if (!flock($lock, LOCK_EX)) {
  105. fclose($lock);
  106. return false;
  107. }
  108. try {
  109. $f = @fopen($name, 'w+');
  110. if ($f === false) {
  111. fclose($lock);
  112. return false;
  113. }
  114. $data = serialize(array($handle, $macFunc, $secret, $expires));
  115. fwrite($f, $data);
  116. fclose($f);
  117. fclose($lock);
  118. return true;
  119. } catch (\Exception $e) {
  120. fclose($lock);
  121. throw $e;
  122. }
  123. }
  124. /**
  125. * Gets information about association identified by $handle
  126. * Returns true if given association found and not expired and false
  127. * otherwise
  128. *
  129. * @param string $handle assiciation handle
  130. * @param string &$macFunc HMAC function (sha1 or sha256)
  131. * @param string &$secret shared secret
  132. * @param string &$expires expiration UNIX time
  133. * @return bool
  134. */
  135. public function getAssociation($handle, &$macFunc, &$secret, &$expires)
  136. {
  137. $name = $this->_dir . '/assoc_' . md5($handle);
  138. $lock = @fopen($this->_dir . '/assoc.lock', 'w+');
  139. if ($lock === false) {
  140. return false;
  141. }
  142. if (!flock($lock, LOCK_EX)) {
  143. fclose($lock);
  144. return false;
  145. }
  146. try {
  147. $f = @fopen($name, 'r');
  148. if ($f === false) {
  149. fclose($lock);
  150. return false;
  151. }
  152. $ret = false;
  153. $data = stream_get_contents($f);
  154. if (!empty($data)) {
  155. list($storedHandle, $macFunc, $secret, $expires) = unserialize($data);
  156. if ($handle === $storedHandle && $expires > time()) {
  157. $ret = true;
  158. } else {
  159. fclose($f);
  160. @unlink($name);
  161. fclose($lock);
  162. return false;
  163. }
  164. }
  165. fclose($f);
  166. fclose($lock);
  167. return $ret;
  168. } catch (\Exception $e) {
  169. fclose($lock);
  170. throw $e;
  171. }
  172. }
  173. /**
  174. * Removes information about association identified by $handle
  175. *
  176. * @param string $handle assiciation handle
  177. * @return bool
  178. */
  179. public function delAssociation($handle)
  180. {
  181. $name = $this->_dir . '/assoc_' . md5($handle);
  182. $lock = @fopen($this->_dir . '/assoc.lock', 'w+');
  183. if ($lock === false) {
  184. return false;
  185. }
  186. if (!flock($lock, LOCK_EX)) {
  187. fclose($lock);
  188. return false;
  189. }
  190. try {
  191. @unlink($name);
  192. fclose($lock);
  193. return true;
  194. } catch (\Exception $e) {
  195. fclose($lock);
  196. throw $e;
  197. }
  198. }
  199. /**
  200. * Register new user with given $id and $password
  201. * Returns true in case of success and false if user with given $id already
  202. * exists
  203. *
  204. * @param string $id user identity URL
  205. * @param string $password encoded user password
  206. * @return bool
  207. */
  208. public function addUser($id, $password)
  209. {
  210. $name = $this->_dir . '/user_' . md5($id);
  211. $lock = @fopen($this->_dir . '/user.lock', 'w+');
  212. if ($lock === false) {
  213. return false;
  214. }
  215. if (!flock($lock, LOCK_EX)) {
  216. fclose($lock);
  217. return false;
  218. }
  219. try {
  220. $f = @fopen($name, 'x');
  221. if ($f === false) {
  222. fclose($lock);
  223. return false;
  224. }
  225. $data = serialize(array($id, $password, array()));
  226. fwrite($f, $data);
  227. fclose($f);
  228. fclose($lock);
  229. return true;
  230. } catch (\Exception $e) {
  231. fclose($lock);
  232. throw $e;
  233. }
  234. }
  235. /**
  236. * Returns true if user with given $id exists and false otherwise
  237. *
  238. * @param string $id user identity URL
  239. * @return bool
  240. */
  241. public function hasUser($id)
  242. {
  243. $name = $this->_dir . '/user_' . md5($id);
  244. $lock = @fopen($this->_dir . '/user.lock', 'w+');
  245. if ($lock === false) {
  246. return false;
  247. }
  248. if (!flock($lock, LOCK_SH)) {
  249. fclose($lock);
  250. return false;
  251. }
  252. try {
  253. $f = @fopen($name, 'r');
  254. if ($f === false) {
  255. fclose($lock);
  256. return false;
  257. }
  258. $ret = false;
  259. $data = stream_get_contents($f);
  260. if (!empty($data)) {
  261. list($storedId, $storedPassword, $trusted) = unserialize($data);
  262. if ($id === $storedId) {
  263. $ret = true;
  264. }
  265. }
  266. fclose($f);
  267. fclose($lock);
  268. return $ret;
  269. } catch (\Exception $e) {
  270. fclose($lock);
  271. throw $e;
  272. }
  273. }
  274. /**
  275. * Verify if user with given $id exists and has specified $password
  276. *
  277. * @param string $id user identity URL
  278. * @param string $password user password
  279. * @return bool
  280. */
  281. public function checkUser($id, $password)
  282. {
  283. $name = $this->_dir . '/user_' . md5($id);
  284. $lock = @fopen($this->_dir . '/user.lock', 'w+');
  285. if ($lock === false) {
  286. return false;
  287. }
  288. if (!flock($lock, LOCK_SH)) {
  289. fclose($lock);
  290. return false;
  291. }
  292. try {
  293. $f = @fopen($name, 'r');
  294. if ($f === false) {
  295. fclose($lock);
  296. return false;
  297. }
  298. $ret = false;
  299. $data = stream_get_contents($f);
  300. if (!empty($data)) {
  301. list($storedId, $storedPassword, $trusted) = unserialize($data);
  302. if ($id === $storedId && $password === $storedPassword) {
  303. $ret = true;
  304. }
  305. }
  306. fclose($f);
  307. fclose($lock);
  308. return $ret;
  309. } catch (\Exception $e) {
  310. fclose($lock);
  311. throw $e;
  312. }
  313. }
  314. /**
  315. * Removes information abou specified user
  316. *
  317. * @param string $id user identity URL
  318. * @return bool
  319. */
  320. public function delUser($id)
  321. {
  322. $name = $this->_dir . '/user_' . md5($id);
  323. $lock = @fopen($this->_dir . '/user.lock', 'w+');
  324. if ($lock === false) {
  325. return false;
  326. }
  327. if (!flock($lock, LOCK_EX)) {
  328. fclose($lock);
  329. return false;
  330. }
  331. try {
  332. @unlink($name);
  333. fclose($lock);
  334. return true;
  335. } catch (\Exception $e) {
  336. fclose($lock);
  337. throw $e;
  338. }
  339. }
  340. /**
  341. * Returns array of all trusted/untrusted sites for given user identified
  342. * by $id
  343. *
  344. * @param string $id user identity URL
  345. * @return array
  346. */
  347. public function getTrustedSites($id)
  348. {
  349. $name = $this->_dir . '/user_' . md5($id);
  350. $lock = @fopen($this->_dir . '/user.lock', 'w+');
  351. if ($lock === false) {
  352. return false;
  353. }
  354. if (!flock($lock, LOCK_SH)) {
  355. fclose($lock);
  356. return false;
  357. }
  358. try {
  359. $f = @fopen($name, 'r');
  360. if ($f === false) {
  361. fclose($lock);
  362. return false;
  363. }
  364. $ret = false;
  365. $data = stream_get_contents($f);
  366. if (!empty($data)) {
  367. list($storedId, $storedPassword, $trusted) = unserialize($data);
  368. if ($id === $storedId) {
  369. $ret = $trusted;
  370. }
  371. }
  372. fclose($f);
  373. fclose($lock);
  374. return $ret;
  375. } catch (\Exception $e) {
  376. fclose($lock);
  377. throw $e;
  378. }
  379. }
  380. /**
  381. * Stores information about trusted/untrusted site for given user
  382. *
  383. * @param string $id user identity URL
  384. * @param string $site site URL
  385. * @param mixed $trusted trust data from extension or just a boolean value
  386. * @return bool
  387. */
  388. public function addSite($id, $site, $trusted)
  389. {
  390. $name = $this->_dir . '/user_' . md5($id);
  391. $lock = @fopen($this->_dir . '/user.lock', 'w+');
  392. if ($lock === false) {
  393. return false;
  394. }
  395. if (!flock($lock, LOCK_EX)) {
  396. fclose($lock);
  397. return false;
  398. }
  399. try {
  400. $f = @fopen($name, 'r+');
  401. if ($f === false) {
  402. fclose($lock);
  403. return false;
  404. }
  405. $ret = false;
  406. $data = stream_get_contents($f);
  407. if (!empty($data)) {
  408. list($storedId, $storedPassword, $sites) = unserialize($data);
  409. if ($id === $storedId) {
  410. if ($trusted === null) {
  411. unset($sites[$site]);
  412. } else {
  413. $sites[$site] = $trusted;
  414. }
  415. rewind($f);
  416. ftruncate($f, 0);
  417. $data = serialize(array($id, $storedPassword, $sites));
  418. fwrite($f, $data);
  419. $ret = true;
  420. }
  421. }
  422. fclose($f);
  423. fclose($lock);
  424. return $ret;
  425. } catch (\Exception $e) {
  426. fclose($lock);
  427. throw $e;
  428. }
  429. }
  430. }