ILIAS  Release_4_4_x_branch Revision 61816
 All Data Structures Namespaces Files Functions Variables Groups Pages
MDB2Store.php
Go to the documentation of this file.
1 <?php
2 
16 require_once 'MDB2.php';
17 
21 require_once 'Auth/OpenID/Interface.php';
22 
26 require_once 'Auth/OpenID.php';
27 
31 require_once 'Auth/OpenID/Nonce.php';
32 
65  function Auth_OpenID_MDB2Store($connection,
66  $associations_table = null,
67  $nonces_table = null)
68  {
69  $this->associations_table_name = "oid_associations";
70  $this->nonces_table_name = "oid_nonces";
71 
72  // Check the connection object type to be sure it's a PEAR
73  // database connection.
74  if (!is_object($connection) ||
75  !is_subclass_of($connection, 'mdb2_driver_common')) {
76  trigger_error("Auth_OpenID_MDB2Store expected PEAR connection " .
77  "object (got ".get_class($connection).")",
78  E_USER_ERROR);
79  return;
80  }
81 
82  $this->connection = $connection;
83 
84  // Be sure to set the fetch mode so the results are keyed on
85  // column name instead of column index.
86  $this->connection->setFetchMode(MDB2_FETCHMODE_ASSOC);
87 
88  if (PEAR::isError($this->connection->loadModule('Extended'))) {
89  trigger_error("Unable to load MDB2_Extended module", E_USER_ERROR);
90  return;
91  }
92 
93  if ($associations_table) {
94  $this->associations_table_name = $associations_table;
95  }
96 
97  if ($nonces_table) {
98  $this->nonces_table_name = $nonces_table;
99  }
100 
101  $this->max_nonce_age = 6 * 60 * 60;
102  }
103 
104  function tableExists($table_name)
105  {
106  return !PEAR::isError($this->connection->query(
107  sprintf("SELECT * FROM %s LIMIT 0",
108  $table_name)));
109  }
110 
111  function createTables()
112  {
113  $n = $this->create_nonce_table();
114  $a = $this->create_assoc_table();
115 
116  if (!$n || !$a) {
117  return false;
118  }
119  return true;
120  }
121 
123  {
124  if (!$this->tableExists($this->nonces_table_name)) {
125  switch ($this->connection->phptype) {
126  case "mysql":
127  case "mysqli":
128  // Custom SQL for MySQL to use InnoDB and variable-
129  // length keys
130  $r = $this->connection->exec(
131  sprintf("CREATE TABLE %s (\n".
132  " server_url VARCHAR(2047) NOT NULL DEFAULT '',\n".
133  " timestamp INTEGER NOT NULL,\n".
134  " salt CHAR(40) NOT NULL,\n".
135  " UNIQUE (server_url(255), timestamp, salt)\n".
136  ") TYPE=InnoDB",
137  $this->nonces_table_name));
138  if (PEAR::isError($r)) {
139  return false;
140  }
141  break;
142  default:
143  if (PEAR::isError(
144  $this->connection->loadModule('Manager'))) {
145  return false;
146  }
147  $fields = array(
148  "server_url" => array(
149  "type" => "text",
150  "length" => 2047,
151  "notnull" => true
152  ),
153  "timestamp" => array(
154  "type" => "integer",
155  "notnull" => true
156  ),
157  "salt" => array(
158  "type" => "text",
159  "length" => 40,
160  "fixed" => true,
161  "notnull" => true
162  )
163  );
164  $constraint = array(
165  "unique" => 1,
166  "fields" => array(
167  "server_url" => true,
168  "timestamp" => true,
169  "salt" => true
170  )
171  );
172 
173  $r = $this->connection->createTable($this->nonces_table_name,
174  $fields);
175  if (PEAR::isError($r)) {
176  return false;
177  }
178 
179  $r = $this->connection->createConstraint(
180  $this->nonces_table_name,
181  $this->nonces_table_name . "_constraint",
182  $constraint);
183  if (PEAR::isError($r)) {
184  return false;
185  }
186  break;
187  }
188  }
189  return true;
190  }
191 
193  {
194  if (!$this->tableExists($this->associations_table_name)) {
195  switch ($this->connection->phptype) {
196  case "mysql":
197  case "mysqli":
198  // Custom SQL for MySQL to use InnoDB and variable-
199  // length keys
200  $r = $this->connection->exec(
201  sprintf("CREATE TABLE %s(\n".
202  " server_url VARCHAR(2047) NOT NULL DEFAULT '',\n".
203  " handle VARCHAR(255) NOT NULL,\n".
204  " secret BLOB NOT NULL,\n".
205  " issued INTEGER NOT NULL,\n".
206  " lifetime INTEGER NOT NULL,\n".
207  " assoc_type VARCHAR(64) NOT NULL,\n".
208  " PRIMARY KEY (server_url(255), handle)\n".
209  ") TYPE=InnoDB",
210  $this->associations_table_name));
211  if (PEAR::isError($r)) {
212  return false;
213  }
214  break;
215  default:
216  if (PEAR::isError(
217  $this->connection->loadModule('Manager'))) {
218  return false;
219  }
220  $fields = array(
221  "server_url" => array(
222  "type" => "text",
223  "length" => 2047,
224  "notnull" => true
225  ),
226  "handle" => array(
227  "type" => "text",
228  "length" => 255,
229  "notnull" => true
230  ),
231  "secret" => array(
232  "type" => "blob",
233  "length" => "255",
234  "notnull" => true
235  ),
236  "issued" => array(
237  "type" => "integer",
238  "notnull" => true
239  ),
240  "lifetime" => array(
241  "type" => "integer",
242  "notnull" => true
243  ),
244  "assoc_type" => array(
245  "type" => "text",
246  "length" => 64,
247  "notnull" => true
248  )
249  );
250  $options = array(
251  "primary" => array(
252  "server_url" => true,
253  "handle" => true
254  )
255  );
256 
257  $r = $this->connection->createTable(
258  $this->associations_table_name,
259  $fields,
260  $options);
261  if (PEAR::isError($r)) {
262  return false;
263  }
264  break;
265  }
266  }
267  return true;
268  }
269 
270  function storeAssociation($server_url, $association)
271  {
272  $fields = array(
273  "server_url" => array(
274  "value" => $server_url,
275  "key" => true
276  ),
277  "handle" => array(
278  "value" => $association->handle,
279  "key" => true
280  ),
281  "secret" => array(
282  "value" => $association->secret,
283  "type" => "blob"
284  ),
285  "issued" => array(
286  "value" => $association->issued
287  ),
288  "lifetime" => array(
289  "value" => $association->lifetime
290  ),
291  "assoc_type" => array(
292  "value" => $association->assoc_type
293  )
294  );
295 
296  return !PEAR::isError($this->connection->replace(
297  $this->associations_table_name,
298  $fields));
299  }
300 
301  function cleanupNonces()
302  {
303  global $Auth_OpenID_SKEW;
304  $v = time() - $Auth_OpenID_SKEW;
305 
306  return $this->connection->exec(
307  sprintf("DELETE FROM %s WHERE timestamp < %d",
308  $this->nonces_table_name, $v));
309  }
310 
312  {
313  return $this->connection->exec(
314  sprintf("DELETE FROM %s WHERE issued + lifetime < %d",
315  $this->associations_table_name, time()));
316  }
317 
318  function getAssociation($server_url, $handle = null)
319  {
320  $sql = "";
321  $params = null;
322  $types = array(
323  "text",
324  "blob",
325  "integer",
326  "integer",
327  "text"
328  );
329  if ($handle !== null) {
330  $sql = sprintf("SELECT handle, secret, issued, lifetime, assoc_type " .
331  "FROM %s WHERE server_url = ? AND handle = ?",
332  $this->associations_table_name);
333  $params = array($server_url, $handle);
334  } else {
335  $sql = sprintf("SELECT handle, secret, issued, lifetime, assoc_type " .
336  "FROM %s WHERE server_url = ? ORDER BY issued DESC",
337  $this->associations_table_name);
338  $params = array($server_url);
339  }
340 
341  $assoc = $this->connection->getRow($sql, $types, $params);
342 
343  if (!$assoc || PEAR::isError($assoc)) {
344  return null;
345  } else {
346  $association = new Auth_OpenID_Association($assoc['handle'],
347  stream_get_contents(
348  $assoc['secret']),
349  $assoc['issued'],
350  $assoc['lifetime'],
351  $assoc['assoc_type']);
352  fclose($assoc['secret']);
353  return $association;
354  }
355  }
356 
357  function removeAssociation($server_url, $handle)
358  {
359  $r = $this->connection->execParam(
360  sprintf("DELETE FROM %s WHERE server_url = ? AND handle = ?",
361  $this->associations_table_name),
362  array($server_url, $handle));
363 
364  if (PEAR::isError($r) || $r == 0) {
365  return false;
366  }
367  return true;
368  }
369 
370  function useNonce($server_url, $timestamp, $salt)
371  {
372  global $Auth_OpenID_SKEW;
373 
374  if (abs($timestamp - time()) > $Auth_OpenID_SKEW ) {
375  return false;
376  }
377 
378  $fields = array(
379  "timestamp" => $timestamp,
380  "salt" => $salt
381  );
382 
383  if (!empty($server_url)) {
384  $fields["server_url"] = $server_url;
385  }
386 
387  $r = $this->connection->autoExecute(
388  $this->nonces_table_name,
389  $fields,
391 
392  if (PEAR::isError($r)) {
393  return false;
394  }
395  return true;
396  }
397 
402  function reset()
403  {
404  $this->connection->query(sprintf("DELETE FROM %s",
405  $this->associations_table_name));
406 
407  $this->connection->query(sprintf("DELETE FROM %s",
408  $this->nonces_table_name));
409  }
410 
411 }
412 
413 ?>