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

https://github.com/kiranatama/sagalaya · PHP · 439 lines · 317 code · 14 blank · 108 comment · 49 complexity · c5a9250bce60805329cf56d34021ee43 MD5 · raw file

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