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