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

https://github.com/shevron/zf2 · PHP · 426 lines · 317 code · 14 blank · 95 comment · 49 complexity · f20741f1a3e0c3ec54ce0de1d0938445 MD5 · raw file

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