Skip to content
Snippets Groups Projects
Commit 80777199 authored by Jaime Perez Crespo's avatar Jaime Perez Crespo
Browse files

Reformat SimpleSAML_Auth_Store and fix phpdoc comments.

parent dbc3cbf0
Branches
Tags
No related merge requests found
<?php <?php
/** /**
* A SQL datastore. * A data store using a RDBMS to keep the data.
* *
* @package SimpleSAMLphp * @package SimpleSAMLphp
*/ */
class SimpleSAML_Store_SQL extends SimpleSAML_Store { class SimpleSAML_Store_SQL extends SimpleSAML_Store
{
/**
* The PDO object for our database. /**
* * The PDO object for our database.
* @var PDO *
*/ * @var PDO
public $pdo; */
public $pdo;
/**
* Our database driver. /**
* * Our database driver.
* @var string *
*/ * @var string
public $driver; */
public $driver;
/**
* The prefix we should use for our tables. /**
* * The prefix we should use for our tables.
* @var string *
*/ * @var string
public $prefix; */
public $prefix;
/**
* Associative array of table versions. /**
* * Associative array of table versions.
* @var array *
*/ * @var array
private $tableVersions; */
private $tableVersions;
/**
* Initialize the SQL datastore. /**
*/ * Initialize the SQL data store.
protected function __construct() { */
protected function __construct()
$config = SimpleSAML_Configuration::getInstance(); {
$config = SimpleSAML_Configuration::getInstance();
$dsn = $config->getString('store.sql.dsn');
$username = $config->getString('store.sql.username', NULL); $dsn = $config->getString('store.sql.dsn');
$password = $config->getString('store.sql.password', NULL); $username = $config->getString('store.sql.username', null);
$this->prefix = $config->getString('store.sql.prefix', 'simpleSAMLphp'); $password = $config->getString('store.sql.password', null);
$this->prefix = $config->getString('store.sql.prefix', 'simpleSAMLphp');
$this->pdo = new PDO($dsn, $username, $password);
$this->pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); $this->pdo = new PDO($dsn, $username, $password);
$this->pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$this->driver = $this->pdo->getAttribute(PDO::ATTR_DRIVER_NAME);
$this->driver = $this->pdo->getAttribute(PDO::ATTR_DRIVER_NAME);
if ($this->driver === 'mysql') {
$this->pdo->exec('SET time_zone = "+00:00"'); if ($this->driver === 'mysql') {
} $this->pdo->exec('SET time_zone = "+00:00"');
}
$this->initTableVersionTable();
$this->initKVTable(); $this->initTableVersionTable();
} $this->initKVTable();
}
/**
* Initialize table-version table. /**
*/ * Initialize the table-version table.
private function initTableVersionTable() { */
private function initTableVersionTable()
$this->tableVersions = array(); {
$this->tableVersions = array();
try {
$fetchTableVersion = $this->pdo->query('SELECT _name, _version FROM ' . $this->prefix . '_tableVersion'); try {
} catch (PDOException $e) { $fetchTableVersion = $this->pdo->query('SELECT _name, _version FROM '.$this->prefix.'_tableVersion');
$this->pdo->exec('CREATE TABLE ' . $this->prefix .'_tableVersion (_name VARCHAR(30) NOT NULL UNIQUE, _version INTEGER NOT NULL)'); } catch (PDOException $e) {
return; $this->pdo->exec(
} 'CREATE TABLE '.$this->prefix.
'_tableVersion (_name VARCHAR(30) NOT NULL UNIQUE, _version INTEGER NOT NULL)'
while ( ($row = $fetchTableVersion->fetch(PDO::FETCH_ASSOC)) !== FALSE) { );
$this->tableVersions[$row['_name']] = (int)$row['_version']; return;
} }
}
while (($row = $fetchTableVersion->fetch(PDO::FETCH_ASSOC)) !== false) {
$this->tableVersions[$row['_name']] = (int) $row['_version'];
/** }
* Initialize key-value table. }
*/
private function initKVTable() {
/**
if ($this->getTableVersion('kvstore') === 1) { * Initialize key-value table.
// Table initialized */
return; private function initKVTable()
} {
$text_t = 'TEXT'; if ($this->getTableVersion('kvstore') === 1) {
if ($this->driver === 'mysql') { // Table initialized
// TEXT data type has size constraints that can be hit at some point, so we use LONGTEXT instead return;
$text_t = 'LONGTEXT'; }
}
$query = 'CREATE TABLE ' . $this->prefix . '_kvstore (_type VARCHAR(30) NOT NULL, _key VARCHAR(50) NOT NULL, _value '.$text_t.' NOT NULL, _expire TIMESTAMP, PRIMARY KEY (_key, _type))'; $text_t = 'TEXT';
$this->pdo->exec($query); if ($this->driver === 'mysql') {
// TEXT data type has size constraints that can be hit at some point, so we use LONGTEXT instead
$query = 'CREATE INDEX ' . $this->prefix . '_kvstore_expire ON ' . $this->prefix . '_kvstore (_expire)'; $text_t = 'LONGTEXT';
$this->pdo->exec($query); }
$query = 'CREATE TABLE '.$this->prefix.
$this->setTableVersion('kvstore', 1); '_kvstore (_type VARCHAR(30) NOT NULL, _key VARCHAR(50) NOT NULL, _value '.$text_t.
} ' NOT NULL, _expire TIMESTAMP, PRIMARY KEY (_key, _type))';
$this->pdo->exec($query);
/** $query = 'CREATE INDEX '.$this->prefix.'_kvstore_expire ON '.$this->prefix.'_kvstore (_expire)';
* Get table version. $this->pdo->exec($query);
*
* @param string Table name. $this->setTableVersion('kvstore', 1);
* @return int The table version, which is 0 if the table doesn't exist. }
*/
public function getTableVersion($name) {
assert('is_string($name)'); /**
* Get table version.
if (!isset($this->tableVersions[$name])) { *
return 0; * @param string $name Table name.
} *
* @return int The table version, or 0 if the table doesn't exist.
return $this->tableVersions[$name]; */
} public function getTableVersion($name)
{
assert('is_string($name)');
/**
* Set table version. if (!isset($this->tableVersions[$name])) {
* return 0;
* @param string $name Table name. }
* @parav int $version Table version.
*/ return $this->tableVersions[$name];
public function setTableVersion($name, $version) { }
assert('is_string($name)');
assert('is_int($version)');
/**
$this->insertOrUpdate($this->prefix . '_tableVersion', array('_name'), * Set table version.
array('_name' => $name, '_version' => $version)); *
$this->tableVersions[$name] = $version; * @param string $name Table name.
} * @param int $version Table version.
*/
public function setTableVersion($name, $version)
/** {
* Insert or update into a table. assert('is_string($name)');
* assert('is_int($version)');
* Since various databases implement different methods for doing this,
* we abstract it away here. $this->insertOrUpdate(
* $this->prefix.'_tableVersion',
* @param string $table The table we should update. array('_name'),
* @param array $key The key columns. array('_name' => $name, '_version' => $version)
* @param array $data Associative array with columns. );
*/ $this->tableVersions[$name] = $version;
public function insertOrUpdate($table, array $keys, array $data) { }
assert('is_string($table)');
$colNames = '(' . implode(', ', array_keys($data)) . ')'; /**
$values = 'VALUES(:' . implode(', :', array_keys($data)) . ')'; * Insert or update a key-value in the store.
*
switch ($this->driver) { * Since various databases implement different methods for doing this, we abstract it away here.
case 'mysql': *
$query = 'REPLACE INTO ' . $table . ' ' . $colNames . ' ' . $values; * @param string $table The table we should update.
$query = $this->pdo->prepare($query); * @param array $keys The key columns.
$query->execute($data); * @param array $data Associative array with columns.
return; */
case 'sqlite': public function insertOrUpdate($table, array $keys, array $data)
$query = 'INSERT OR REPLACE INTO ' . $table . ' ' . $colNames . ' ' . $values; {
$query = $this->pdo->prepare($query); assert('is_string($table)');
$query->execute($data);
return; $colNames = '('.implode(', ', array_keys($data)).')';
} $values = 'VALUES(:'.implode(', :', array_keys($data)).')';
// Default implementation. Try INSERT, and UPDATE if that fails. switch ($this->driver) {
case 'mysql':
$insertQuery = 'INSERT INTO ' . $table . ' ' . $colNames . ' ' . $values; $query = 'REPLACE INTO '.$table.' '.$colNames.' '.$values;
$insertQuery = $this->pdo->prepare($insertQuery); $query = $this->pdo->prepare($query);
try { $query->execute($data);
$insertQuery->execute($data); return;
return; case 'sqlite':
} catch (PDOException $e) { $query = 'INSERT OR REPLACE INTO '.$table.' '.$colNames.' '.$values;
$ecode = (string)$e->getCode(); $query = $this->pdo->prepare($query);
switch ($ecode) { $query->execute($data);
case '23505': // PostgreSQL return;
break; }
default:
SimpleSAML\Logger::error('Error while saving data: ' . $e->getMessage()); // Default implementation. Try INSERT, and UPDATE if that fails.
throw $e;
} $insertQuery = 'INSERT INTO '.$table.' '.$colNames.' '.$values;
} $insertQuery = $this->pdo->prepare($insertQuery);
try {
$updateCols = array(); $insertQuery->execute($data);
$condCols = array(); return;
foreach ($data as $col => $value) { } catch (PDOException $e) {
$ecode = (string) $e->getCode();
$tmp = $col . ' = :' . $col; switch ($ecode) {
case '23505': // PostgreSQL
if (in_array($col, $keys, TRUE)) { break;
$condCols[] = $tmp; default:
} else { SimpleSAML\Logger::error('Error while saving data: '.$e->getMessage());
$updateCols[] = $tmp; throw $e;
} }
} }
$updateQuery = 'UPDATE ' . $table . ' SET ' . implode(',', $updateCols) . ' WHERE ' . implode(' AND ', $condCols); $updateCols = array();
$updateQuery = $this->pdo->prepare($updateQuery); $condCols = array();
$updateQuery->execute($data); foreach ($data as $col => $value) {
}
$tmp = $col.' = :'.$col;
/** if (in_array($col, $keys, true)) {
* Clean the key-value table of expired entries. $condCols[] = $tmp;
*/ } else {
private function cleanKVStore() { $updateCols[] = $tmp;
}
SimpleSAML\Logger::debug('store.sql: Cleaning key-value store.'); }
$query = 'DELETE FROM ' . $this->prefix . '_kvstore WHERE _expire < :now'; $updateQuery = 'UPDATE '.$table.' SET '.implode(',', $updateCols).' WHERE '.implode(' AND ', $condCols);
$params = array('now' => gmdate('Y-m-d H:i:s')); $updateQuery = $this->pdo->prepare($updateQuery);
$updateQuery->execute($data);
$query = $this->pdo->prepare($query); }
$query->execute($params);
}
/**
* Clean the key-value table of expired entries.
/** */
* Retrieve a value from the datastore. private function cleanKVStore()
* {
* @param string $type The datatype.
* @param string $key The key. SimpleSAML\Logger::debug('store.sql: Cleaning key-value store.');
* @return mixed|NULL The value.
*/ $query = 'DELETE FROM '.$this->prefix.'_kvstore WHERE _expire < :now';
public function get($type, $key) { $params = array('now' => gmdate('Y-m-d H:i:s'));
assert('is_string($type)');
assert('is_string($key)'); $query = $this->pdo->prepare($query);
$query->execute($params);
if (strlen($key) > 50) { }
$key = sha1($key);
}
/**
$query = 'SELECT _value FROM ' . $this->prefix . '_kvstore WHERE _type = :type AND _key = :key AND (_expire IS NULL OR _expire > :now)'; * Retrieve a value from the data store.
$params = array('type' => $type, 'key' => $key, 'now' => gmdate('Y-m-d H:i:s')); *
* @param string $type The type of the data.
$query = $this->pdo->prepare($query); * @param string $key The key to retrieve.
$query->execute($params); *
* @return mixed|null The value associated with that key, or null if there's no such key.
$row = $query->fetch(PDO::FETCH_ASSOC); */
if ($row === FALSE) { public function get($type, $key)
return NULL; {
} assert('is_string($type)');
assert('is_string($key)');
$value = $row['_value'];
if (is_resource($value)) { if (strlen($key) > 50) {
$value = stream_get_contents($value); $key = sha1($key);
} }
$value = urldecode($value);
$value = unserialize($value); $query = 'SELECT _value FROM '.$this->prefix.
'_kvstore WHERE _type = :type AND _key = :key AND (_expire IS NULL OR _expire > :now)';
if ($value === FALSE) { $params = array('type' => $type, 'key' => $key, 'now' => gmdate('Y-m-d H:i:s'));
return NULL;
} $query = $this->pdo->prepare($query);
return $value; $query->execute($params);
}
$row = $query->fetch(PDO::FETCH_ASSOC);
if ($row === false) {
/** return null;
* Save a value to the datastore. }
*
* @param string $type The datatype. $value = $row['_value'];
* @param string $key The key. if (is_resource($value)) {
* @param mixed $value The value. $value = stream_get_contents($value);
* @param int|NULL $expire The expiration time (unix timestamp), or NULL if it never expires. }
*/ $value = urldecode($value);
public function set($type, $key, $value, $expire = NULL) { $value = unserialize($value);
assert('is_string($type)');
assert('is_string($key)'); if ($value === false) {
assert('is_null($expire) || (is_int($expire) && $expire > 2592000)'); return null;
}
if (rand(0, 1000) < 10) { return $value;
$this->cleanKVStore(); }
}
if (strlen($key) > 50) { /**
$key = sha1($key); * Save a value in the data store.
} *
* @param string $type The type of the data.
if ($expire !== NULL) { * @param string $key The key to insert.
$expire = gmdate('Y-m-d H:i:s', $expire); * @param mixed $value The value itself.
} * @param int|null $expire The expiration time (unix timestamp), or null if it never expires.
*/
$value = serialize($value); public function set($type, $key, $value, $expire = null)
$value = rawurlencode($value); {
assert('is_string($type)');
$data = array( assert('is_string($key)');
'_type' => $type, assert('is_null($expire) || (is_int($expire) && $expire > 2592000)');
'_key' => $key,
'_value' => $value, if (rand(0, 1000) < 10) {
'_expire' => $expire, $this->cleanKVStore();
); }
if (strlen($key) > 50) {
$this->insertOrUpdate($this->prefix . '_kvstore', array('_type', '_key'), $data); $key = sha1($key);
} }
if ($expire !== null) {
/** $expire = gmdate('Y-m-d H:i:s', $expire);
* Delete a value from the datastore. }
*
* @param string $type The datatype. $value = serialize($value);
* @param string $key The key. $value = rawurlencode($value);
*/
public function delete($type, $key) { $data = array(
assert('is_string($type)'); '_type' => $type,
assert('is_string($key)'); '_key' => $key,
'_value' => $value,
if (strlen($key) > 50) { '_expire' => $expire,
$key = sha1($key); );
}
$data = array( $this->insertOrUpdate($this->prefix.'_kvstore', array('_type', '_key'), $data);
'_type' => $type, }
'_key' => $key,
);
/**
$query = 'DELETE FROM ' . $this->prefix . '_kvstore WHERE _type=:_type AND _key=:_key'; * Delete an entry from the data store.
$query = $this->pdo->prepare($query); *
$query->execute($data); * @param string $type The type of the data
} * @param string $key The key to delete.
*/
public function delete($type, $key)
{
assert('is_string($type)');
assert('is_string($key)');
if (strlen($key) > 50) {
$key = sha1($key);
}
$data = array(
'_type' => $type,
'_key' => $key,
);
$query = 'DELETE FROM '.$this->prefix.'_kvstore WHERE _type=:_type AND _key=:_key';
$query = $this->pdo->prepare($query);
$query->execute($data);
}
} }
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment