PageRenderTime 104ms CodeModel.GetById 60ms app.highlight 19ms RepoModel.GetById 21ms app.codeStats 0ms

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

https://bitbucket.org/baruffaldi/cms-php-bfcms
PHP | 453 lines | 305 code | 14 blank | 134 comment | 58 complexity | 51ff100406ae32263afb89c765658cce 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-2008 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 9250 2008-04-18 21:00:13Z darby $
 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-2008 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 (is_null($dir)) {
 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        $f = @fopen($name1, 'w+');
137        if ($f === false) {
138            fclose($lock);
139            return false;
140        }
141        $data = serialize(array($url, $handle, $macFunc, $secret, $expires));
142        fwrite($f, $data);
143        if (function_exists('symlink')) {
144            @unlink($name2);
145            symlink($name1, $name2);
146        } else {
147            $f2 = @fopen($name2, 'w+');
148            if ($f2) {
149                fwrite($f2, $data);
150                fclose($f2);
151            }
152        }
153        fclose($f);
154        fclose($lock);
155        return true;
156    }
157
158    /**
159     * Gets information about association identified by $url
160     * Returns true if given association found and not expired and false
161     * otherwise
162     *
163     * @param string $url OpenID server URL
164     * @param string &$handle assiciation handle
165     * @param string &$macFunc HMAC function (sha1 or sha256)
166     * @param string &$secret shared secret
167     * @param long &$expires expiration UNIX time
168     * @return bool
169     */
170    public function getAssociation($url, &$handle, &$macFunc, &$secret, &$expires)
171    {
172        $name1 = $this->_dir . '/assoc_url_' . md5($url);
173        $lock = @fopen($this->_dir . '/assoc.lock', 'w+');
174        if ($lock === false) {
175            return false;
176        }
177        if (!flock($lock, LOCK_EX)) {
178            fclose($lock);
179            return false;
180        }
181        $f = @fopen($name1, 'r');
182        if ($f === false) {
183            fclose($lock);
184            return false;
185        }
186        $ret = false;
187        $data = stream_get_contents($f);
188        if (!empty($data)) {
189            list($storedUrl, $handle, $macFunc, $secret, $expires) = unserialize($data);
190            if ($url === $storedUrl && $expires > time()) {
191                $ret = true;
192            } else {
193                $name2 = $this->_dir . '/assoc_handle_' . md5($handle);
194                fclose($f);
195                @unlink($name2);
196                @unlink($name1);
197                fclose($lock);
198                return false;
199            }
200        }
201        fclose($f);
202        fclose($lock);
203        return $ret;
204    }
205
206    /**
207     * Gets information about association identified by $handle
208     * Returns true if given association found and not expired and false
209     * otherwise
210     *
211     * @param string $handle assiciation handle
212     * @param string &$url OpenID server URL
213     * @param string &$macFunc HMAC function (sha1 or sha256)
214     * @param string &$secret shared secret
215     * @param long &$expires expiration UNIX time
216     * @return bool
217     */
218    public function getAssociationByHandle($handle, &$url, &$macFunc, &$secret, &$expires)
219    {
220        $name2 = $this->_dir . '/assoc_handle_' . md5($handle);
221        $lock = @fopen($this->_dir . '/assoc.lock', 'w+');
222        if ($lock === false) {
223            return false;
224        }
225        if (!flock($lock, LOCK_EX)) {
226            fclose($lock);
227            return false;
228        }
229        $f = @fopen($name2, 'r');
230        if ($f === false) {
231            fclose($lock);
232            return false;
233        }
234        $ret = false;
235        $data = stream_get_contents($f);
236        if (!empty($data)) {
237            list($url, $storedHandle, $macFunc, $secret, $expires) = unserialize($data);
238            if ($handle === $storedHandle && $expires > time()) {
239                $ret = true;
240            } else {
241                fclose($f);
242                @unlink($name2);
243                $name1 = $this->_dir . '/assoc_url_' . md5($url);
244                @unlink($name1);
245                fclose($lock);
246                return false;
247            }
248        }
249        fclose($f);
250        fclose($lock);
251        return $ret;
252    }
253
254    /**
255     * Deletes association identified by $url
256     *
257     * @param string $url OpenID server URL
258     * @return bool
259     */
260    public function delAssociation($url)
261    {
262        $name1 = $this->_dir . '/assoc_url_' . md5($url);
263        $lock = @fopen($this->_dir . '/assoc.lock', 'w+');
264        if ($lock === false) {
265            return false;
266        }
267        if (!flock($lock, LOCK_EX)) {
268            fclose($lock);
269            return false;
270        }
271        $f = @fopen($name1, 'r');
272        if ($f === false) {
273            fclose($lock);
274            return false;
275        }
276        $data = stream_get_contents($f);
277        if (!empty($data)) {
278            list($storedUrl, $handle, $macFunc, $secret, $expires) = unserialize($data);
279            if ($url === $storedUrl) {
280                $name2 = $this->_dir . '/assoc_handle_' . md5($handle);
281                fclose($f);
282                @unlink($name2);
283                @unlink($name1);
284                fclose($lock);
285                return true;
286            }
287        }
288        fclose($f);
289        fclose($lock);
290        return true;
291    }
292
293    /**
294     * Stores information discovered from identity $id
295     *
296     * @param string $id identity
297     * @param string $realId discovered real identity URL
298     * @param string $server discovered OpenID server URL
299     * @param float $version discovered OpenID protocol version
300     * @param long $expires expiration UNIX time
301     * @return bool
302     */
303    public function addDiscoveryInfo($id, $realId, $server, $version, $expires)
304    {
305        $name = $this->_dir . '/discovery_' . md5($id);
306        $lock = @fopen($this->_dir . '/discovery.lock', 'w+');
307        if ($lock === false) {
308            return false;
309        }
310        if (!flock($lock, LOCK_EX)) {
311            fclose($lock);
312            return false;
313        }
314        $f = @fopen($name, 'w+');
315        if ($f === false) {
316            fclose($lock);
317            return false;
318        }
319        $data = serialize(array($id, $realId, $server, $version, $expires));
320        fwrite($f, $data);
321        fclose($f);
322        fclose($lock);
323        return true;
324    }
325
326    /**
327     * Gets information discovered from identity $id
328     * Returns true if such information exists and false otherwise
329     *
330     * @param string $id identity
331     * @param string &$realId discovered real identity URL
332     * @param string &$server discovered OpenID server URL
333     * @param float &$version discovered OpenID protocol version
334     * @param long &$expires expiration UNIX time
335     * @return bool
336     */
337    public function getDiscoveryInfo($id, &$realId, &$server, &$version, &$expires)
338    {
339        $name = $this->_dir . '/discovery_' . md5($id);
340        $lock = @fopen($this->_dir . '/discovery.lock', 'w+');
341        if ($lock === false) {
342            return false;
343        }
344        if (!flock($lock, LOCK_EX)) {
345            fclose($lock);
346            return false;
347        }
348        $f = @fopen($name, 'r');
349        if ($f === false) {
350            fclose($lock);
351            return false;
352        }
353        $ret = false;
354        $data = stream_get_contents($f);
355        if (!empty($data)) {
356            list($storedId, $realId, $server, $version, $expires) = unserialize($data);
357            if ($id === $storedId && $expires > time()) {
358                $ret = true;
359            } else {
360                fclose($f);
361                @unlink($name);
362                fclose($lock);
363                return false;
364            }
365        }
366        fclose($f);
367        fclose($lock);
368        return $ret;
369    }
370
371    /**
372     * Removes cached information discovered from identity $id
373     *
374     * @param string $id identity
375     * @return bool
376     */
377    public function delDiscoveryInfo($id)
378    {
379        $name = $this->_dir . '/discovery_' . md5($id);
380        $lock = @fopen($this->_dir . '/discovery.lock', 'w+');
381        if ($lock === false) {
382            return false;
383        }
384        if (!flock($lock, LOCK_EX)) {
385            fclose($lock);
386            return false;
387        }
388        @unlink($name);
389        fclose($lock);
390        return true;
391    }
392
393    /**
394     * The function checks the uniqueness of openid.response_nonce
395     *
396     * @param string $provider openid.openid_op_endpoint field from authentication response
397     * @param  string $nonce openid.response_nonce field from authentication response
398     * @return bool
399     */
400    public function isUniqueNonce($provider, $nonce)
401    {
402        $name = $this->_dir . '/nonce_' . md5($provider.';'.$nonce);
403        $lock = @fopen($this->_dir . '/nonce.lock', 'w+');
404        if ($lock === false) {
405            return false;
406        }
407        if (!flock($lock, LOCK_EX)) {
408            fclose($lock);
409            return false;
410        }
411        $f = @fopen($name, 'x');
412        if ($f === false) {
413            fclose($lock);
414            return false;
415        }
416        fwrite($f, $provider.';'.$nonce);
417        fclose($f);
418        fclose($lock);
419        return true;
420    }
421
422    /**
423     * Removes data from the uniqueness database that is older then given date
424     *
425     * @param mixed $date date of expired data
426     */
427    public function purgeNonces($date=null)
428    {
429        $lock = @fopen($this->_dir . '/nonce.lock', 'w+');
430        if ($lock !== false) {
431            flock($lock, LOCK_EX);
432        }
433        if (!is_int($date) && !is_string($date)) {
434            foreach (glob($this->_dir . '/nonce_*') as $name) {
435                @unlink($name);
436            }
437        } else {
438            if (is_string($date)) {
439                $time = time($date);
440            } else {
441                $time = $date;
442            }
443            foreach (glob($this->_dir . '/nonce_*') as $name) {
444                if (filemtime($name) < $time) {
445                    @unlink($name);
446                }
447            }
448        }
449        if ($lock !== false) {
450            fclose($lock);
451        }
452    }
453}