summaryrefslogtreecommitdiffstats
path: root/lib/SimpleSAML
diff options
context:
space:
mode:
authorJaime Perez Crespo <jaime.perez@uninett.no>2016-06-02 12:08:49 +0200
committerJaime Perez Crespo <jaime.perez@uninett.no>2016-06-02 12:08:49 +0200
commit8077719905f97ea7997a4fdeb079298b07f41f16 (patch)
tree429f7193693804b756a7f9c9d5006b901c79a682 /lib/SimpleSAML
parentdbc3cbf0266ba325fe70eabad9e73e14cf0e58ef (diff)
downloadsimplesamlphp-8077719905f97ea7997a4fdeb079298b07f41f16.zip
simplesamlphp-8077719905f97ea7997a4fdeb079298b07f41f16.tar.gz
simplesamlphp-8077719905f97ea7997a4fdeb079298b07f41f16.tar.bz2
Reformat SimpleSAML_Auth_Store and fix phpdoc comments.
Diffstat (limited to 'lib/SimpleSAML')
-rw-r--r--lib/SimpleSAML/Store/SQL.php667
1 files changed, 343 insertions, 324 deletions
diff --git a/lib/SimpleSAML/Store/SQL.php b/lib/SimpleSAML/Store/SQL.php
index 534f2ea..41ed260 100644
--- a/lib/SimpleSAML/Store/SQL.php
+++ b/lib/SimpleSAML/Store/SQL.php
@@ -1,331 +1,350 @@
<?php
+
/**
- * A SQL datastore.
+ * A data store using a RDBMS to keep the data.
*
* @package SimpleSAMLphp
*/
-class SimpleSAML_Store_SQL extends SimpleSAML_Store {
-
- /**
- * The PDO object for our database.
- *
- * @var PDO
- */
- public $pdo;
-
-
- /**
- * Our database driver.
- *
- * @var string
- */
- public $driver;
-
-
- /**
- * The prefix we should use for our tables.
- *
- * @var string
- */
- public $prefix;
-
-
- /**
- * Associative array of table versions.
- *
- * @var array
- */
- private $tableVersions;
-
-
- /**
- * Initialize the SQL datastore.
- */
- protected function __construct() {
-
- $config = SimpleSAML_Configuration::getInstance();
-
- $dsn = $config->getString('store.sql.dsn');
- $username = $config->getString('store.sql.username', NULL);
- $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->driver = $this->pdo->getAttribute(PDO::ATTR_DRIVER_NAME);
-
- if ($this->driver === 'mysql') {
- $this->pdo->exec('SET time_zone = "+00:00"');
- }
-
- $this->initTableVersionTable();
- $this->initKVTable();
- }
-
-
- /**
- * Initialize table-version table.
- */
- private function initTableVersionTable() {
-
- $this->tableVersions = array();
-
- try {
- $fetchTableVersion = $this->pdo->query('SELECT _name, _version FROM ' . $this->prefix . '_tableVersion');
- } catch (PDOException $e) {
- $this->pdo->exec('CREATE TABLE ' . $this->prefix .'_tableVersion (_name VARCHAR(30) NOT NULL UNIQUE, _version INTEGER NOT NULL)');
- 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) {
- // Table initialized
- return;
- }
-
- $text_t = 'TEXT';
- if ($this->driver === 'mysql') {
- // TEXT data type has size constraints that can be hit at some point, so we use LONGTEXT instead
- $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))';
- $this->pdo->exec($query);
-
- $query = 'CREATE INDEX ' . $this->prefix . '_kvstore_expire ON ' . $this->prefix . '_kvstore (_expire)';
- $this->pdo->exec($query);
-
- $this->setTableVersion('kvstore', 1);
- }
-
-
- /**
- * Get table version.
- *
- * @param string Table name.
- * @return int The table version, which is 0 if the table doesn't exist.
- */
- public function getTableVersion($name) {
- assert('is_string($name)');
-
- if (!isset($this->tableVersions[$name])) {
- return 0;
- }
-
- return $this->tableVersions[$name];
- }
-
-
- /**
- * Set table version.
- *
- * @param string $name Table name.
- * @parav int $version Table version.
- */
- public function setTableVersion($name, $version) {
- assert('is_string($name)');
- assert('is_int($version)');
-
- $this->insertOrUpdate($this->prefix . '_tableVersion', array('_name'),
- array('_name' => $name, '_version' => $version));
- $this->tableVersions[$name] = $version;
- }
-
-
- /**
- * Insert or update into a table.
- *
- * Since various databases implement different methods for doing this,
- * we abstract it away here.
- *
- * @param string $table The table we should update.
- * @param array $key The key columns.
- * @param array $data Associative array with columns.
- */
- public function insertOrUpdate($table, array $keys, array $data) {
- assert('is_string($table)');
-
- $colNames = '(' . implode(', ', array_keys($data)) . ')';
- $values = 'VALUES(:' . implode(', :', array_keys($data)) . ')';
-
- switch ($this->driver) {
- case 'mysql':
- $query = 'REPLACE INTO ' . $table . ' ' . $colNames . ' ' . $values;
- $query = $this->pdo->prepare($query);
- $query->execute($data);
- return;
- case 'sqlite':
- $query = 'INSERT OR REPLACE INTO ' . $table . ' ' . $colNames . ' ' . $values;
- $query = $this->pdo->prepare($query);
- $query->execute($data);
- return;
- }
-
- // Default implementation. Try INSERT, and UPDATE if that fails.
-
- $insertQuery = 'INSERT INTO ' . $table . ' ' . $colNames . ' ' . $values;
- $insertQuery = $this->pdo->prepare($insertQuery);
- try {
- $insertQuery->execute($data);
- return;
- } catch (PDOException $e) {
- $ecode = (string)$e->getCode();
- switch ($ecode) {
- case '23505': // PostgreSQL
- break;
- default:
- SimpleSAML\Logger::error('Error while saving data: ' . $e->getMessage());
- throw $e;
- }
- }
-
- $updateCols = array();
- $condCols = array();
- foreach ($data as $col => $value) {
-
- $tmp = $col . ' = :' . $col;
-
- if (in_array($col, $keys, TRUE)) {
- $condCols[] = $tmp;
- } else {
- $updateCols[] = $tmp;
- }
- }
-
- $updateQuery = 'UPDATE ' . $table . ' SET ' . implode(',', $updateCols) . ' WHERE ' . implode(' AND ', $condCols);
- $updateQuery = $this->pdo->prepare($updateQuery);
- $updateQuery->execute($data);
- }
-
-
- /**
- * Clean the key-value table of expired entries.
- */
- private function cleanKVStore() {
-
- SimpleSAML\Logger::debug('store.sql: Cleaning key-value store.');
-
- $query = 'DELETE FROM ' . $this->prefix . '_kvstore WHERE _expire < :now';
- $params = array('now' => gmdate('Y-m-d H:i:s'));
-
- $query = $this->pdo->prepare($query);
- $query->execute($params);
- }
-
-
- /**
- * Retrieve a value from the datastore.
- *
- * @param string $type The datatype.
- * @param string $key The key.
- * @return mixed|NULL The value.
- */
- public function get($type, $key) {
- assert('is_string($type)');
- assert('is_string($key)');
-
- 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)';
- $params = array('type' => $type, 'key' => $key, 'now' => gmdate('Y-m-d H:i:s'));
-
- $query = $this->pdo->prepare($query);
- $query->execute($params);
-
- $row = $query->fetch(PDO::FETCH_ASSOC);
- if ($row === FALSE) {
- return NULL;
- }
-
- $value = $row['_value'];
- if (is_resource($value)) {
- $value = stream_get_contents($value);
- }
- $value = urldecode($value);
- $value = unserialize($value);
-
- if ($value === FALSE) {
- return NULL;
- }
- return $value;
- }
-
-
- /**
- * Save a value to the datastore.
- *
- * @param string $type The datatype.
- * @param string $key The key.
- * @param mixed $value The value.
- * @param int|NULL $expire The expiration time (unix timestamp), or NULL if it never expires.
- */
- public function set($type, $key, $value, $expire = NULL) {
- assert('is_string($type)');
- assert('is_string($key)');
- assert('is_null($expire) || (is_int($expire) && $expire > 2592000)');
-
- if (rand(0, 1000) < 10) {
- $this->cleanKVStore();
- }
-
- if (strlen($key) > 50) {
- $key = sha1($key);
- }
-
- if ($expire !== NULL) {
- $expire = gmdate('Y-m-d H:i:s', $expire);
- }
-
- $value = serialize($value);
- $value = rawurlencode($value);
-
- $data = array(
- '_type' => $type,
- '_key' => $key,
- '_value' => $value,
- '_expire' => $expire,
- );
-
-
- $this->insertOrUpdate($this->prefix . '_kvstore', array('_type', '_key'), $data);
- }
-
-
- /**
- * Delete a value from the datastore.
- *
- * @param string $type The datatype.
- * @param string $key The key.
- */
- 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);
- }
-
+class SimpleSAML_Store_SQL extends SimpleSAML_Store
+{
+
+ /**
+ * The PDO object for our database.
+ *
+ * @var PDO
+ */
+ public $pdo;
+
+
+ /**
+ * Our database driver.
+ *
+ * @var string
+ */
+ public $driver;
+
+
+ /**
+ * The prefix we should use for our tables.
+ *
+ * @var string
+ */
+ public $prefix;
+
+
+ /**
+ * Associative array of table versions.
+ *
+ * @var array
+ */
+ private $tableVersions;
+
+
+ /**
+ * Initialize the SQL data store.
+ */
+ protected function __construct()
+ {
+ $config = SimpleSAML_Configuration::getInstance();
+
+ $dsn = $config->getString('store.sql.dsn');
+ $username = $config->getString('store.sql.username', null);
+ $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->driver = $this->pdo->getAttribute(PDO::ATTR_DRIVER_NAME);
+
+ if ($this->driver === 'mysql') {
+ $this->pdo->exec('SET time_zone = "+00:00"');
+ }
+
+ $this->initTableVersionTable();
+ $this->initKVTable();
+ }
+
+
+ /**
+ * Initialize the table-version table.
+ */
+ private function initTableVersionTable()
+ {
+ $this->tableVersions = array();
+
+ try {
+ $fetchTableVersion = $this->pdo->query('SELECT _name, _version FROM '.$this->prefix.'_tableVersion');
+ } catch (PDOException $e) {
+ $this->pdo->exec(
+ 'CREATE TABLE '.$this->prefix.
+ '_tableVersion (_name VARCHAR(30) NOT NULL UNIQUE, _version INTEGER NOT NULL)'
+ );
+ 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) {
+ // Table initialized
+ return;
+ }
+
+ $text_t = 'TEXT';
+ if ($this->driver === 'mysql') {
+ // TEXT data type has size constraints that can be hit at some point, so we use LONGTEXT instead
+ $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))';
+ $this->pdo->exec($query);
+
+ $query = 'CREATE INDEX '.$this->prefix.'_kvstore_expire ON '.$this->prefix.'_kvstore (_expire)';
+ $this->pdo->exec($query);
+
+ $this->setTableVersion('kvstore', 1);
+ }
+
+
+ /**
+ * Get table version.
+ *
+ * @param string $name Table name.
+ *
+ * @return int The table version, or 0 if the table doesn't exist.
+ */
+ public function getTableVersion($name)
+ {
+ assert('is_string($name)');
+
+ if (!isset($this->tableVersions[$name])) {
+ return 0;
+ }
+
+ return $this->tableVersions[$name];
+ }
+
+
+ /**
+ * Set table version.
+ *
+ * @param string $name Table name.
+ * @param int $version Table version.
+ */
+ public function setTableVersion($name, $version)
+ {
+ assert('is_string($name)');
+ assert('is_int($version)');
+
+ $this->insertOrUpdate(
+ $this->prefix.'_tableVersion',
+ array('_name'),
+ array('_name' => $name, '_version' => $version)
+ );
+ $this->tableVersions[$name] = $version;
+ }
+
+
+ /**
+ * Insert or update a key-value in the store.
+ *
+ * Since various databases implement different methods for doing this, we abstract it away here.
+ *
+ * @param string $table The table we should update.
+ * @param array $keys The key columns.
+ * @param array $data Associative array with columns.
+ */
+ public function insertOrUpdate($table, array $keys, array $data)
+ {
+ assert('is_string($table)');
+
+ $colNames = '('.implode(', ', array_keys($data)).')';
+ $values = 'VALUES(:'.implode(', :', array_keys($data)).')';
+
+ switch ($this->driver) {
+ case 'mysql':
+ $query = 'REPLACE INTO '.$table.' '.$colNames.' '.$values;
+ $query = $this->pdo->prepare($query);
+ $query->execute($data);
+ return;
+ case 'sqlite':
+ $query = 'INSERT OR REPLACE INTO '.$table.' '.$colNames.' '.$values;
+ $query = $this->pdo->prepare($query);
+ $query->execute($data);
+ return;
+ }
+
+ // Default implementation. Try INSERT, and UPDATE if that fails.
+
+ $insertQuery = 'INSERT INTO '.$table.' '.$colNames.' '.$values;
+ $insertQuery = $this->pdo->prepare($insertQuery);
+ try {
+ $insertQuery->execute($data);
+ return;
+ } catch (PDOException $e) {
+ $ecode = (string) $e->getCode();
+ switch ($ecode) {
+ case '23505': // PostgreSQL
+ break;
+ default:
+ SimpleSAML\Logger::error('Error while saving data: '.$e->getMessage());
+ throw $e;
+ }
+ }
+
+ $updateCols = array();
+ $condCols = array();
+ foreach ($data as $col => $value) {
+
+ $tmp = $col.' = :'.$col;
+
+ if (in_array($col, $keys, true)) {
+ $condCols[] = $tmp;
+ } else {
+ $updateCols[] = $tmp;
+ }
+ }
+
+ $updateQuery = 'UPDATE '.$table.' SET '.implode(',', $updateCols).' WHERE '.implode(' AND ', $condCols);
+ $updateQuery = $this->pdo->prepare($updateQuery);
+ $updateQuery->execute($data);
+ }
+
+
+ /**
+ * Clean the key-value table of expired entries.
+ */
+ private function cleanKVStore()
+ {
+
+ SimpleSAML\Logger::debug('store.sql: Cleaning key-value store.');
+
+ $query = 'DELETE FROM '.$this->prefix.'_kvstore WHERE _expire < :now';
+ $params = array('now' => gmdate('Y-m-d H:i:s'));
+
+ $query = $this->pdo->prepare($query);
+ $query->execute($params);
+ }
+
+
+ /**
+ * Retrieve a value from the data store.
+ *
+ * @param string $type The type of the data.
+ * @param string $key The key to retrieve.
+ *
+ * @return mixed|null The value associated with that key, or null if there's no such key.
+ */
+ public function get($type, $key)
+ {
+ assert('is_string($type)');
+ assert('is_string($key)');
+
+ 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)';
+ $params = array('type' => $type, 'key' => $key, 'now' => gmdate('Y-m-d H:i:s'));
+
+ $query = $this->pdo->prepare($query);
+ $query->execute($params);
+
+ $row = $query->fetch(PDO::FETCH_ASSOC);
+ if ($row === false) {
+ return null;
+ }
+
+ $value = $row['_value'];
+ if (is_resource($value)) {
+ $value = stream_get_contents($value);
+ }
+ $value = urldecode($value);
+ $value = unserialize($value);
+
+ if ($value === false) {
+ return null;
+ }
+ return $value;
+ }
+
+
+ /**
+ * Save a value in the data store.
+ *
+ * @param string $type The type of the data.
+ * @param string $key The key to insert.
+ * @param mixed $value The value itself.
+ * @param int|null $expire The expiration time (unix timestamp), or null if it never expires.
+ */
+ public function set($type, $key, $value, $expire = null)
+ {
+ assert('is_string($type)');
+ assert('is_string($key)');
+ assert('is_null($expire) || (is_int($expire) && $expire > 2592000)');
+
+ if (rand(0, 1000) < 10) {
+ $this->cleanKVStore();
+ }
+
+ if (strlen($key) > 50) {
+ $key = sha1($key);
+ }
+
+ if ($expire !== null) {
+ $expire = gmdate('Y-m-d H:i:s', $expire);
+ }
+
+ $value = serialize($value);
+ $value = rawurlencode($value);
+
+ $data = array(
+ '_type' => $type,
+ '_key' => $key,
+ '_value' => $value,
+ '_expire' => $expire,
+ );
+
+
+ $this->insertOrUpdate($this->prefix.'_kvstore', array('_type', '_key'), $data);
+ }
+
+
+ /**
+ * Delete an entry from the data store.
+ *
+ * @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);
+ }
}