/standard/tags/release-1.5.0RC3/library/Zend/OpenId/Consumer/Storage/File.php

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