Cleanup: Updated copyright comments
[Packages/TYPO3.CMS.git] / typo3 / sysext / openid / sv1 / class.tx_openid_store.php
1 <?php
2 /***************************************************************
3 * Copyright notice
4 *
5 * (c) 2009-2011 Dmitry Dulepov (dmitry.dulepov@gmail.com)
6 * All rights reserved
7 *
8 * This script is part of the Typo3 project. The Typo3 project is
9 * free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
13 *
14 * The GNU General Public License can be found at
15 * http://www.gnu.org/copyleft/gpl.html.
16 *
17 * This script is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * This copyright notice MUST APPEAR in all copies of the script!
23 ***************************************************************/
24 /**
25 * $Id$
26 */
27
28 require_once(t3lib_extMgm::extPath('openid', 'lib/php-openid/Auth/OpenID/Interface.php'));
29
30 /**
31 * This class is a TYPO3-specific OpenID store.
32 *
33 * @author Dmitry Dulepov <dmitry.dulepov@gmail.com>
34 * @package TYPO3
35 * @subpackage tx_openid
36 */
37 class tx_openid_store extends Auth_OpenID_OpenIDStore {
38
39 const ASSOCIATION_TABLE_NAME = 'tx_openid_assoc_store';
40
41 const ASSOCIATION_EXPIRATION_SAFETY_INTERVAL = 120; /* 2 minutes */
42
43 const NONCE_TABLE_NAME = 'tx_openid_nonce_store';
44
45 const NONCE_STORAGE_TIME = 864000; /* 10 days */
46
47 /**
48 * Sores the association for future use
49 *
50 * @param string $serverUrl Server URL
51 * @param Auth_OpenID_Association $association OpenID association
52 * @return void
53 */
54 public function storeAssociation($serverUrl, $association) {
55 /* @var $association Auth_OpenID_Association */
56 $GLOBALS['TYPO3_DB']->sql_query('START TRANSACTION');
57
58 if ($this->doesAssociationExist($serverUrl, $association->handle)) {
59 $this->updateExistingAssociation($serverUrl, $association);
60 }
61 else {
62 $this->storeNewAssociation($serverUrl, $association);
63 }
64
65 $GLOBALS['TYPO3_DB']->sql_query('COMMIT');
66 }
67
68 /**
69 * Removes all expired associations.
70 *
71 * @return int A number of removed associations
72 */
73 public function cleanupAssociations() {
74 $where = sprintf('expires<=%d', time());
75 $GLOBALS['TYPO3_DB']->exec_DELETEquery(self::ASSOCIATION_TABLE_NAME, $where);
76 return $GLOBALS['TYPO3_DB']->sql_affected_rows();
77 }
78
79 /**
80 * Obtains the association to the server
81 *
82 * @param string $serverUrl Server URL
83 * @param string $handle Association handle (optional)
84 * @return Auth_OpenID_Association
85 */
86 public function getAssociation($serverUrl, $handle = null) {
87 $this->cleanupAssociations();
88
89 $where = sprintf('server_url=%s AND expires>%d',
90 $GLOBALS['TYPO3_DB']->fullQuoteStr($serverUrl, self::ASSOCIATION_TABLE_NAME),
91 time());
92 if ($handle != null) {
93 $where .= sprintf(' AND assoc_handle=%s',
94 $GLOBALS['TYPO3_DB']->fullQuoteStr($handle, self::ASSOCIATION_TABLE_NAME));
95 $sort = '';
96 }
97 else {
98 $sort = 'tstamp DESC';
99 }
100 $row = $GLOBALS['TYPO3_DB']->exec_SELECTgetSingleRow(
101 'uid, content',
102 self::ASSOCIATION_TABLE_NAME,
103 $where,
104 '',
105 $sort
106 );
107
108 $result = null;
109 if (is_array($row)) {
110 $result = @unserialize(base64_decode($row['content']));
111 if ($result === false) {
112 $result = null;
113 }
114 else {
115 $this->updateAssociationTimeStamp($row['tstamp']);
116 }
117 }
118 return $result;
119 }
120
121 /**
122 * Removes the association
123 *
124 * @param string $serverUrl Server URL
125 * @param string $handle Association handle (optional)
126 * @return boolean true if the association existed
127 */
128 function removeAssociation($serverUrl, $handle) {
129 $where = sprintf('server_url=%s AND assoc_handle=%s',
130 $GLOBALS['TYPO3_DB']->fullQuoteStr($serverUrl, self::ASSOCIATION_TABLE_NAME),
131 $GLOBALS['TYPO3_DB']->fullQuoteStr($handle, self::ASSOCIATION_TABLE_NAME));
132 $GLOBALS['TYPO3_DB']->exec_DELETEquery(self::ASSOCIATION_TABLE_NAME, $where);
133 $deletedCount = $GLOBALS['TYPO3_DB']->sql_affected_rows();
134 return ($deletedCount > 0);
135 }
136
137 /**
138 * Removes old nonces
139 *
140 * @return void
141 */
142 public function cleanupNonces() {
143 $where = sprintf('crdate<%d', time() - self::NONCE_STORAGE_TIME);
144 $GLOBALS['TYPO3_DB']->exec_DELETEquery(self::NONCE_TABLE_NAME, $where);
145 }
146
147 /**
148 * Checks if this nonce was already used
149 * @param $serverUrl Server URL
150 * @param $timestamp Time stamp
151 * @param $salt Nonce value
152 * @return boolean true if nonce was not used before anc can be used now
153 */
154 public function useNonce($serverUrl, $timestamp, $salt) {
155 $result = false;
156
157 if (abs($timestamp - time()) < $GLOBALS['Auth_OpenID_SKEW']) {
158 $values = array(
159 'crdate' => time(),
160 'salt' => $salt,
161 'server_url' => $serverUrl,
162 'tstamp' => $timestamp
163 );
164 $GLOBALS['TYPO3_DB']->exec_INSERTquery(self::NONCE_TABLE_NAME,
165 $values);
166 $affectedRows = $GLOBALS['TYPO3_DB']->sql_affected_rows();
167 $result = ($affectedRows > 0);
168 }
169
170 return $result;
171 }
172
173 /**
174 * Resets the store by removing all data in it
175 *
176 * @return void
177 */
178 public function reset() {
179 $GLOBALS['TYPO3_DB']->exec_DELETEquery(self::ASSOCIATION_TABLE_NAME, '1=1');
180 $GLOBALS['TYPO3_DB']->exec_DELETEquery(self::NONCE_TABLE_NAME, '1=1');
181 }
182
183 /**
184 * Checks if such association exists.
185 *
186 * @param string $serverUrl Server URL
187 * @param Auth_OpenID_Association $association OpenID association
188 * @return boolean
189 */
190 protected function doesAssociationExist($serverUrl, $association) {
191 $where = sprintf('server_url=%s AND assoc_handle=%s AND expires>%d',
192 $GLOBALS['TYPO3_DB']->fullQuoteStr($serverUrl, self::ASSOCIATION_TABLE_NAME),
193 $GLOBALS['TYPO3_DB']->fullQuoteStr($association->handle, self::ASSOCIATION_TABLE_NAME),
194 time());
195 $row = $GLOBALS['TYPO3_DB']->exec_SELECTgetSingleRow(
196 'COUNT(*) as assocCount', self::ASSOCIATION_TABLE_NAME, $where);
197 return ($row['assocCount'] > 0);
198 }
199
200 /**
201 * Updates existing association.
202 *
203 * @param string $serverUrl Server URL
204 * @param Auth_OpenID_Association $association OpenID association
205 * @return void
206 */
207 protected function updateExistingAssociation($serverUrl, Auth_OpenID_Association $association) {
208 $where = sprintf('server_url=%s AND assoc_handle=%s AND expires>%d',
209 $GLOBALS['TYPO3_DB']->fullQuoteStr($serverUrl, self::ASSOCIATION_TABLE_NAME),
210 $GLOBALS['TYPO3_DB']->fullQuoteStr($association->handle, self::ASSOCIATION_TABLE_NAME),
211 time());
212 $serializedAssociation = serialize($association);
213 $values = array(
214 'content' => base64_encode($serializedAssociation),
215 'tstamp' => time(),
216 );
217 $GLOBALS['TYPO3_DB']->exec_UPDATEquery(self::ASSOCIATION_TABLE_NAME, $where, $values);
218 }
219
220 /**
221 * Stores new association to the database.
222 *
223 * @param $serverUrl Server URL
224 * @param $association OpenID association
225 * @return void
226 */
227 protected function storeNewAssociation($serverUrl, $association) {
228 $serializedAssociation = serialize($association);
229 $values = array(
230 'assoc_handle' => $association->handle,
231 'content' => base64_encode($serializedAssociation),
232 'crdate' => $association->issued,
233 'tstamp' => time(),
234 'expires' => $association->issued + $association->lifetime - self::ASSOCIATION_EXPIRATION_SAFETY_INTERVAL,
235 'server_url' => $serverUrl
236 );
237 // In the next query we can get race conditions. sha1_hash prevents many
238 // asociations from being stored for one server
239 $GLOBALS['TYPO3_DB']->exec_INSERTquery(self::ASSOCIATION_TABLE_NAME, $values);
240 }
241
242 /**
243 * Updates association time stamp.
244 *
245 * @param $recordId Association record id in the database
246 * @return void
247 */
248 protected function updateAssociationTimeStamp($recordId) {
249 $where = sprintf('uid=%d', $recordId);
250 $values = array(
251 'tstamp' => time()
252 );
253 $GLOBALS['TYPO3_DB']->exec_UPDATEquery(self::ASSOCIATION_TABLE_NAME, $where, $values);
254 }
255 }
256
257 if (defined('TYPO3_MODE') && isset($GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['XCLASS']['ext/openid/class.tx_openid_store.php'])) {
258 include_once($GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['XCLASS']['ext/openid/class.tx_openid_store.php']);
259 }
260
261 ?>