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

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