PageRenderTime 37ms CodeModel.GetById 9ms app.highlight 21ms RepoModel.GetById 1ms app.codeStats 1ms

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

https://bitbucket.org/nosen/jelly2
PHP | 511 lines | 363 code | 14 blank | 134 comment | 60 complexity | edb3f487bfa11574627c88b6a01d9088 MD5 | raw file
  1<?php
  2
  3/**
  4 * Zend Framework
  5 *
  6 * LICENSE
  7 *
  8 * This source file is subject to the new BSD license that is bundled
  9 * with this package in the file LICENSE.txt.
 10 * It is also available through the world-wide-web at this URL:
 11 * http://framework.zend.com/license/new-bsd
 12 * If you did not receive a copy of the license and are unable to
 13 * obtain it through the world-wide-web, please send an email
 14 * to license@zend.com so we can send you a copy immediately.
 15 *
 16 * @category   Zend
 17 * @package    Zend_OpenId
 18 * @subpackage Zend_OpenId_Consumer
 19 * @copyright  Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com)
 20 * @license    http://framework.zend.com/license/new-bsd     New BSD License
 21 * @version    $Id: File.php 23775 2011-03-01 17:25:24Z ralph $
 22 */
 23
 24/**
 25 * @see Zend_OpenId_Consumer_Storage
 26 */
 27require_once "Zend/OpenId/Consumer/Storage.php";
 28
 29/**
 30 * External storage implemmentation using serialized files
 31 *
 32 * @category   Zend
 33 * @package    Zend_OpenId
 34 * @subpackage Zend_OpenId_Consumer
 35 * @copyright  Copyright (c) 2005-2011 Zend Technologies USA Inc. (http://www.zend.com)
 36 * @license    http://framework.zend.com/license/new-bsd     New BSD License
 37 */
 38class Zend_OpenId_Consumer_Storage_File extends Zend_OpenId_Consumer_Storage
 39{
 40
 41    /**
 42     * Directory name to store data files in
 43     *
 44     * @var string $_dir
 45     */
 46    private $_dir;
 47
 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/consumer';
 69        }
 70        $this->_dir = $dir;
 71        if (!is_dir($this->_dir)) {
 72            if (!@mkdir($this->_dir, 0700, 1)) {
 73                /**
 74                 * @see Zend_OpenId_Exception
 75                 */
 76                require_once 'Zend/OpenId/Exception.php';
 77                throw new Zend_OpenId_Exception(
 78                    'Cannot access storage directory ' . $dir,
 79                    Zend_OpenId_Exception::ERROR_STORAGE);
 80            }
 81        }
 82        if (($f = fopen($this->_dir.'/assoc.lock', 'w+')) === null) {
 83            /**
 84             * @see Zend_OpenId_Exception
 85             */
 86            require_once 'Zend/OpenId/Exception.php';
 87            throw new Zend_OpenId_Exception(
 88                'Cannot create a lock file in the directory ' . $dir,
 89                Zend_OpenId_Exception::ERROR_STORAGE);
 90        }
 91        fclose($f);
 92        if (($f = fopen($this->_dir.'/discovery.lock', 'w+')) === null) {
 93            /**
 94             * @see Zend_OpenId_Exception
 95             */
 96            require_once 'Zend/OpenId/Exception.php';
 97            throw new Zend_OpenId_Exception(
 98                'Cannot create a lock file in the directory ' . $dir,
 99                Zend_OpenId_Exception::ERROR_STORAGE);
100        }
101        fclose($f);
102        if (($f = fopen($this->_dir.'/nonce.lock', 'w+')) === null) {
103            /**
104             * @see Zend_OpenId_Exception
105             */
106            require_once 'Zend/OpenId/Exception.php';
107            throw new Zend_OpenId_Exception(
108                'Cannot create a lock file in the directory ' . $dir,
109                Zend_OpenId_Exception::ERROR_STORAGE);
110        }
111        fclose($f);
112    }
113
114    /**
115     * Stores information about association identified by $url/$handle
116     *
117     * @param string $url OpenID server URL
118     * @param string $handle assiciation handle
119     * @param string $macFunc HMAC function (sha1 or sha256)
120     * @param string $secret shared secret
121     * @param long $expires expiration UNIX time
122     * @return bool
123     */
124    public function addAssociation($url, $handle, $macFunc, $secret, $expires)
125    {
126        $name1 = $this->_dir . '/assoc_url_' . md5($url);
127        $name2 = $this->_dir . '/assoc_handle_' . md5($handle);
128        $lock = @fopen($this->_dir . '/assoc.lock', 'w+');
129        if ($lock === false) {
130            return false;
131        }
132        if (!flock($lock, LOCK_EX)) {
133            fclose($lock);
134            return false;
135        }
136        try {
137            $f = @fopen($name1, 'w+');
138            if ($f === false) {
139                fclose($lock);
140                return false;
141            }
142            $data = serialize(array($url, $handle, $macFunc, $secret, $expires));
143            fwrite($f, $data);
144            if (function_exists('symlink')) {
145                @unlink($name2);
146                if (symlink($name1, $name2)) {
147                    fclose($f);
148                    fclose($lock);
149                    return true;
150                }
151            }
152            $f2 = @fopen($name2, 'w+');
153            if ($f2) {
154                fwrite($f2, $data);
155                fclose($f2);
156                @unlink($name1);
157                $ret = true;
158            } else {
159                $ret = false;
160            }
161            fclose($f);
162            fclose($lock);
163            return $ret;
164        } catch (Exception $e) {
165            fclose($lock);
166            throw $e;
167        }
168    }
169
170    /**
171     * Gets information about association identified by $url
172     * Returns true if given association found and not expired and false
173     * otherwise
174     *
175     * @param string $url OpenID server URL
176     * @param string &$handle assiciation handle
177     * @param string &$macFunc HMAC function (sha1 or sha256)
178     * @param string &$secret shared secret
179     * @param long &$expires expiration UNIX time
180     * @return bool
181     */
182    public function getAssociation($url, &$handle, &$macFunc, &$secret, &$expires)
183    {
184        $name1 = $this->_dir . '/assoc_url_' . md5($url);
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            $f = @fopen($name1, 'r');
195            if ($f === false) {
196                fclose($lock);
197                return false;
198            }
199            $ret = false;
200            $data = stream_get_contents($f);
201            if (!empty($data)) {
202                list($storedUrl, $handle, $macFunc, $secret, $expires) = unserialize($data);
203                if ($url === $storedUrl && $expires > time()) {
204                    $ret = true;
205                } else {
206                    $name2 = $this->_dir . '/assoc_handle_' . md5($handle);
207                    fclose($f);
208                    @unlink($name2);
209                    @unlink($name1);
210                    fclose($lock);
211                    return false;
212                }
213            }
214            fclose($f);
215            fclose($lock);
216            return $ret;
217        } catch (Exception $e) {
218            fclose($lock);
219            throw $e;
220        }
221    }
222
223    /**
224     * Gets information about association identified by $handle
225     * Returns true if given association found and not expired and false
226     * otherwise
227     *
228     * @param string $handle assiciation handle
229     * @param string &$url OpenID server URL
230     * @param string &$macFunc HMAC function (sha1 or sha256)
231     * @param string &$secret shared secret
232     * @param long &$expires expiration UNIX time
233     * @return bool
234     */
235    public function getAssociationByHandle($handle, &$url, &$macFunc, &$secret, &$expires)
236    {
237        $name2 = $this->_dir . '/assoc_handle_' . md5($handle);
238        $lock = @fopen($this->_dir . '/assoc.lock', 'w+');
239        if ($lock === false) {
240            return false;
241        }
242        if (!flock($lock, LOCK_EX)) {
243            fclose($lock);
244            return false;
245        }
246        try {
247            $f = @fopen($name2, 'r');
248            if ($f === false) {
249                fclose($lock);
250                return false;
251            }
252            $ret = false;
253            $data = stream_get_contents($f);
254            if (!empty($data)) {
255                list($url, $storedHandle, $macFunc, $secret, $expires) = unserialize($data);
256                if ($handle === $storedHandle && $expires > time()) {
257                    $ret = true;
258                } else {
259                    fclose($f);
260                    @unlink($name2);
261                    $name1 = $this->_dir . '/assoc_url_' . md5($url);
262                    @unlink($name1);
263                    fclose($lock);
264                    return false;
265                }
266            }
267            fclose($f);
268            fclose($lock);
269            return $ret;
270        } catch (Exception $e) {
271            fclose($lock);
272            throw $e;
273        }
274    }
275
276    /**
277     * Deletes association identified by $url
278     *
279     * @param string $url OpenID server URL
280     * @return bool
281     */
282    public function delAssociation($url)
283    {
284        $name1 = $this->_dir . '/assoc_url_' . md5($url);
285        $lock = @fopen($this->_dir . '/assoc.lock', 'w+');
286        if ($lock === false) {
287            return false;
288        }
289        if (!flock($lock, LOCK_EX)) {
290            fclose($lock);
291            return false;
292        }
293        try {
294            $f = @fopen($name1, 'r');
295            if ($f === false) {
296                fclose($lock);
297                return false;
298            }
299            $data = stream_get_contents($f);
300            if (!empty($data)) {
301                list($storedUrl, $handle, $macFunc, $secret, $expires) = unserialize($data);
302                if ($url === $storedUrl) {
303                    $name2 = $this->_dir . '/assoc_handle_' . md5($handle);
304                    fclose($f);
305                    @unlink($name2);
306                    @unlink($name1);
307                    fclose($lock);
308                    return true;
309                }
310            }
311            fclose($f);
312            fclose($lock);
313            return true;
314        } catch (Exception $e) {
315            fclose($lock);
316            throw $e;
317        }
318    }
319
320    /**
321     * Stores information discovered from identity $id
322     *
323     * @param string $id identity
324     * @param string $realId discovered real identity URL
325     * @param string $server discovered OpenID server URL
326     * @param float $version discovered OpenID protocol version
327     * @param long $expires expiration UNIX time
328     * @return bool
329     */
330    public function addDiscoveryInfo($id, $realId, $server, $version, $expires)
331    {
332        $name = $this->_dir . '/discovery_' . md5($id);
333        $lock = @fopen($this->_dir . '/discovery.lock', 'w+');
334        if ($lock === false) {
335            return false;
336        }
337        if (!flock($lock, LOCK_EX)) {
338            fclose($lock);
339            return false;
340        }
341        try {
342            $f = @fopen($name, 'w+');
343            if ($f === false) {
344                fclose($lock);
345                return false;
346            }
347            $data = serialize(array($id, $realId, $server, $version, $expires));
348            fwrite($f, $data);
349            fclose($f);
350            fclose($lock);
351            return true;
352        } catch (Exception $e) {
353            fclose($lock);
354            throw $e;
355        }
356    }
357
358    /**
359     * Gets information discovered from identity $id
360     * Returns true if such information exists and false otherwise
361     *
362     * @param string $id identity
363     * @param string &$realId discovered real identity URL
364     * @param string &$server discovered OpenID server URL
365     * @param float &$version discovered OpenID protocol version
366     * @param long &$expires expiration UNIX time
367     * @return bool
368     */
369    public function getDiscoveryInfo($id, &$realId, &$server, &$version, &$expires)
370    {
371        $name = $this->_dir . '/discovery_' . md5($id);
372        $lock = @fopen($this->_dir . '/discovery.lock', 'w+');
373        if ($lock === false) {
374            return false;
375        }
376        if (!flock($lock, LOCK_EX)) {
377            fclose($lock);
378            return false;
379        }
380        try {
381            $f = @fopen($name, 'r');
382            if ($f === false) {
383                fclose($lock);
384                return false;
385            }
386            $ret = false;
387            $data = stream_get_contents($f);
388            if (!empty($data)) {
389                list($storedId, $realId, $server, $version, $expires) = unserialize($data);
390                if ($id === $storedId && $expires > time()) {
391                    $ret = true;
392                } else {
393                    fclose($f);
394                    @unlink($name);
395                    fclose($lock);
396                    return false;
397                }
398            }
399            fclose($f);
400            fclose($lock);
401            return $ret;
402        } catch (Exception $e) {
403            fclose($lock);
404            throw $e;
405        }
406    }
407
408    /**
409     * Removes cached information discovered from identity $id
410     *
411     * @param string $id identity
412     * @return bool
413     */
414    public function delDiscoveryInfo($id)
415    {
416        $name = $this->_dir . '/discovery_' . md5($id);
417        $lock = @fopen($this->_dir . '/discovery.lock', 'w+');
418        if ($lock === false) {
419            return false;
420        }
421        if (!flock($lock, LOCK_EX)) {
422            fclose($lock);
423            return false;
424        }
425        try {
426            @unlink($name);
427            fclose($lock);
428            return true;
429        } catch (Exception $e) {
430            fclose($lock);
431            throw $e;
432        }
433    }
434
435    /**
436     * The function checks the uniqueness of openid.response_nonce
437     *
438     * @param string $provider openid.openid_op_endpoint field from authentication response
439     * @param  string $nonce openid.response_nonce field from authentication response
440     * @return bool
441     */
442    public function isUniqueNonce($provider, $nonce)
443    {
444        $name = $this->_dir . '/nonce_' . md5($provider.';'.$nonce);
445        $lock = @fopen($this->_dir . '/nonce.lock', 'w+');
446        if ($lock === false) {
447            return false;
448        }
449        if (!flock($lock, LOCK_EX)) {
450            fclose($lock);
451            return false;
452        }
453        try {
454            $f = @fopen($name, 'x');
455            if ($f === false) {
456                fclose($lock);
457                return false;
458            }
459            fwrite($f, $provider.';'.$nonce);
460            fclose($f);
461            fclose($lock);
462            return true;
463        } catch (Exception $e) {
464            fclose($lock);
465            throw $e;
466        }
467    }
468
469    /**
470     * Removes data from the uniqueness database that is older then given date
471     *
472     * @param mixed $date date of expired data
473     */
474    public function purgeNonces($date=null)
475    {
476        $lock = @fopen($this->_dir . '/nonce.lock', 'w+');
477        if ($lock !== false) {
478            flock($lock, LOCK_EX);
479        }
480        try {
481            if (!is_int($date) && !is_string($date)) {
482                $nonceFiles = glob($this->_dir . '/nonce_*');
483                foreach ((array) $nonceFiles as $name) {
484                    @unlink($name);
485                }
486                unset($nonceFiles);
487            } else {
488                if (is_string($date)) {
489                    $time = time($date);
490                } else {
491                    $time = $date;
492                }
493                $nonceFiles = glob($this->_dir . '/nonce_*');
494                foreach ((array) $nonceFiles as $name) {
495                    if (filemtime($name) < $time) {
496                        @unlink($name);
497                    }
498                }
499                unset($nonceFiles);
500            }
501            if ($lock !== false) {
502                fclose($lock);
503            }
504        } catch (Exception $e) {
505            if ($lock !== false) {
506                fclose($lock);
507            }
508            throw $e;
509        }
510    }
511}