TYPO3 API  SVNRelease
class.tx_openid_store.php
Go to the documentation of this file.
00001 <?php
00002 /***************************************************************
00003 *  Copyright notice
00004 *
00005 *  (c) 2009-2011 Dmitry Dulepov (dmitry.dulepov@gmail.com)
00006 *  All rights reserved
00007 *
00008 *  This script is part of the Typo3 project. The Typo3 project is
00009 *  free software; you can redistribute it and/or modify
00010 *  it under the terms of the GNU General Public License as published by
00011 *  the Free Software Foundation; either version 2 of the License, or
00012 *  (at your option) any later version.
00013 *
00014 *  The GNU General Public License can be found at
00015 *  http://www.gnu.org/copyleft/gpl.html.
00016 *
00017 *  This script is distributed in the hope that it will be useful,
00018 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00019 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00020 *  GNU General Public License for more details.
00021 *
00022 *  This copyright notice MUST APPEAR in all copies of the script!
00023 ***************************************************************/
00024 /**
00025  * $Id: class.tx_openid_store.php 10120 2011-01-18 20:03:36Z ohader $
00026  */
00027 
00028 require_once(t3lib_extMgm::extPath('openid', 'lib/php-openid/Auth/OpenID/Interface.php'));
00029 
00030 /**
00031   * This class is a TYPO3-specific OpenID store.
00032   *
00033   * @author Dmitry Dulepov <dmitry.dulepov@gmail.com>
00034   * @package TYPO3
00035   * @subpackage tx_openid
00036   */
00037 class tx_openid_store extends Auth_OpenID_OpenIDStore {
00038 
00039     const ASSOCIATION_TABLE_NAME = 'tx_openid_assoc_store';
00040 
00041     const ASSOCIATION_EXPIRATION_SAFETY_INTERVAL = 120; /* 2 minutes */
00042 
00043     const NONCE_TABLE_NAME = 'tx_openid_nonce_store';
00044 
00045     const NONCE_STORAGE_TIME = 864000; /* 10 days */
00046 
00047     /**
00048      * Sores the association for future use
00049      *
00050      * @param string $serverUrl Server URL
00051      * @param Auth_OpenID_Association $association OpenID association
00052      * @return void
00053      */
00054     public function storeAssociation($serverUrl, $association) {
00055         /* @var $association Auth_OpenID_Association */
00056         $GLOBALS['TYPO3_DB']->sql_query('START TRANSACTION');
00057 
00058         if ($this->doesAssociationExist($serverUrl, $association->handle)) {
00059             $this->updateExistingAssociation($serverUrl, $association);
00060         }
00061         else {
00062             $this->storeNewAssociation($serverUrl, $association);
00063         }
00064 
00065         $GLOBALS['TYPO3_DB']->sql_query('COMMIT');
00066     }
00067 
00068     /**
00069      * Removes all expired associations.
00070      *
00071      * @return int A number of removed associations
00072      */
00073     public function cleanupAssociations() {
00074         $where = sprintf('expires<=%d', time());
00075         $GLOBALS['TYPO3_DB']->exec_DELETEquery(self::ASSOCIATION_TABLE_NAME, $where);
00076         return $GLOBALS['TYPO3_DB']->sql_affected_rows();
00077     }
00078 
00079     /**
00080      * Obtains the association to the server
00081      *
00082      * @param string $serverUrl Server URL
00083      * @param string $handle Association handle (optional)
00084      * @return Auth_OpenID_Association
00085      */
00086     public function getAssociation($serverUrl, $handle = null) {
00087         $this->cleanupAssociations();
00088 
00089         $where = sprintf('server_url=%s AND expires>%d',
00090             $GLOBALS['TYPO3_DB']->fullQuoteStr($serverUrl, self::ASSOCIATION_TABLE_NAME),
00091             time());
00092         if ($handle != null) {
00093             $where .= sprintf(' AND assoc_handle=%s',
00094                 $GLOBALS['TYPO3_DB']->fullQuoteStr($handle, self::ASSOCIATION_TABLE_NAME));
00095             $sort = '';
00096         }
00097         else {
00098             $sort = 'tstamp DESC';
00099         }
00100         $row = $GLOBALS['TYPO3_DB']->exec_SELECTgetSingleRow(
00101             'uid, content',
00102             self::ASSOCIATION_TABLE_NAME,
00103             $where,
00104             '',
00105             $sort
00106         );
00107 
00108         $result = null;
00109         if (is_array($row)) {
00110             $result = @unserialize(base64_decode($row['content']));
00111             if ($result === false) {
00112                 $result = null;
00113             }
00114             else {
00115                 $this->updateAssociationTimeStamp($row['tstamp']);
00116             }
00117         }
00118         return $result;
00119     }
00120 
00121     /**
00122      * Removes the association
00123      *
00124      * @param string $serverUrl Server URL
00125      * @param string $handle Association handle (optional)
00126      * @return boolean true if the association existed
00127      */
00128     function removeAssociation($serverUrl, $handle) {
00129         $where = sprintf('server_url=%s AND assoc_handle=%s',
00130             $GLOBALS['TYPO3_DB']->fullQuoteStr($serverUrl, self::ASSOCIATION_TABLE_NAME),
00131             $GLOBALS['TYPO3_DB']->fullQuoteStr($handle, self::ASSOCIATION_TABLE_NAME));
00132         $GLOBALS['TYPO3_DB']->exec_DELETEquery(self::ASSOCIATION_TABLE_NAME, $where);
00133         $deletedCount = $GLOBALS['TYPO3_DB']->sql_affected_rows();
00134         return ($deletedCount > 0);
00135     }
00136 
00137     /**
00138      * Removes old nonces
00139      *
00140      * @return void
00141      */
00142     public function cleanupNonces() {
00143         $where = sprintf('crdate<%d', time() - self::NONCE_STORAGE_TIME);
00144         $GLOBALS['TYPO3_DB']->exec_DELETEquery(self::NONCE_TABLE_NAME, $where);
00145     }
00146 
00147     /**
00148      * Checks if this nonce was already used
00149      * @param $serverUrl Server URL
00150      * @param $timestamp Time stamp
00151      * @param $salt Nonce value
00152      * @return boolean true if nonce was not used before anc can be used now
00153      */
00154     public function useNonce($serverUrl, $timestamp, $salt) {
00155         $result = false;
00156 
00157         if (abs($timestamp - time()) < $GLOBALS['Auth_OpenID_SKEW']) {
00158             $values = array(
00159                 'crdate' => time(),
00160                 'salt' => $salt,
00161                 'server_url' => $serverUrl,
00162                 'tstamp' => $timestamp
00163             );
00164             $GLOBALS['TYPO3_DB']->exec_INSERTquery(self::NONCE_TABLE_NAME,
00165                 $values);
00166             $affectedRows = $GLOBALS['TYPO3_DB']->sql_affected_rows();
00167             $result = ($affectedRows > 0);
00168         }
00169 
00170         return $result;
00171     }
00172 
00173     /**
00174      * Resets the store by removing all data in it
00175      *
00176      * @return void
00177      */
00178     public function reset() {
00179         $GLOBALS['TYPO3_DB']->exec_DELETEquery(self::ASSOCIATION_TABLE_NAME, '1=1');
00180         $GLOBALS['TYPO3_DB']->exec_DELETEquery(self::NONCE_TABLE_NAME, '1=1');
00181     }
00182 
00183     /**
00184      * Checks if such association exists.
00185      *
00186      * @param string $serverUrl Server URL
00187      * @param Auth_OpenID_Association $association OpenID association
00188      * @return boolean
00189      */
00190     protected function doesAssociationExist($serverUrl, $association) {
00191         $where = sprintf('server_url=%s AND assoc_handle=%s AND expires>%d',
00192             $GLOBALS['TYPO3_DB']->fullQuoteStr($serverUrl, self::ASSOCIATION_TABLE_NAME),
00193             $GLOBALS['TYPO3_DB']->fullQuoteStr($association->handle, self::ASSOCIATION_TABLE_NAME),
00194             time());
00195         $row = $GLOBALS['TYPO3_DB']->exec_SELECTgetSingleRow(
00196             'COUNT(*) as assocCount', self::ASSOCIATION_TABLE_NAME, $where);
00197         return ($row['assocCount'] > 0);
00198     }
00199 
00200     /**
00201      * Updates existing association.
00202      *
00203      * @param string $serverUrl Server URL
00204      * @param Auth_OpenID_Association $association OpenID association
00205      * @return void
00206      */
00207     protected function updateExistingAssociation($serverUrl, Auth_OpenID_Association $association) {
00208         $where = sprintf('server_url=%s AND assoc_handle=%s AND expires>%d',
00209             $GLOBALS['TYPO3_DB']->fullQuoteStr($serverUrl, self::ASSOCIATION_TABLE_NAME),
00210             $GLOBALS['TYPO3_DB']->fullQuoteStr($association->handle, self::ASSOCIATION_TABLE_NAME),
00211             time());
00212         $serializedAssociation = serialize($association);
00213         $values = array(
00214             'content' => base64_encode($serializedAssociation),
00215             'tstamp' => time(),
00216         );
00217         $GLOBALS['TYPO3_DB']->exec_UPDATEquery(self::ASSOCIATION_TABLE_NAME, $where, $values);
00218     }
00219 
00220     /**
00221      * Stores new association to the database.
00222      *
00223      * @param $serverUrl Server URL
00224      * @param $association OpenID association
00225      * @return void
00226      */
00227     protected function storeNewAssociation($serverUrl, $association) {
00228         $serializedAssociation = serialize($association);
00229         $values = array(
00230             'assoc_handle' => $association->handle,
00231             'content' => base64_encode($serializedAssociation),
00232             'crdate' => $association->issued,
00233             'tstamp' => time(),
00234             'expires' => $association->issued + $association->lifetime - self::ASSOCIATION_EXPIRATION_SAFETY_INTERVAL,
00235             'server_url' => $serverUrl
00236         );
00237         // In the next query we can get race conditions. sha1_hash prevents many
00238         // asociations from being stored for one server
00239         $GLOBALS['TYPO3_DB']->exec_INSERTquery(self::ASSOCIATION_TABLE_NAME, $values);
00240     }
00241 
00242     /**
00243      * Updates association time stamp.
00244      *
00245      * @param $recordId Association record id in the database
00246      * @return void
00247      */
00248     protected function updateAssociationTimeStamp($recordId) {
00249         $where = sprintf('uid=%d', $recordId);
00250         $values = array(
00251             'tstamp' => time()
00252         );
00253         $GLOBALS['TYPO3_DB']->exec_UPDATEquery(self::ASSOCIATION_TABLE_NAME, $where, $values);
00254     }
00255 }
00256 
00257 if (defined('TYPO3_MODE') && isset($GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['XCLASS']['ext/openid/class.tx_openid_store.php'])) {
00258     include_once($GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['XCLASS']['ext/openid/class.tx_openid_store.php']);
00259 }
00260 
00261 ?>