summaryrefslogtreecommitdiffstats
path: root/Auth/OpenID/SQLStore.php
diff options
context:
space:
mode:
authortailor <cygnus@janrain.com>2006-02-14 22:43:46 +0000
committertailor <cygnus@janrain.com>2006-02-14 22:43:46 +0000
commita51e8efee3d6e83e7df10df42c0762a6b8d127b2 (patch)
treedee35be3bd4da499aa1293c9aa422dda974d1938 /Auth/OpenID/SQLStore.php
parent7ad76515d6f91b4951a6b70377b6854e5d21cb69 (diff)
downloadphp-openid-a51e8efee3d6e83e7df10df42c0762a6b8d127b2.zip
php-openid-a51e8efee3d6e83e7df10df42c0762a6b8d127b2.tar.gz
php-openid-a51e8efee3d6e83e7df10df42c0762a6b8d127b2.tar.bz2
[project @ Moved files from Store/ into Auth/OpenID/]
Diffstat (limited to 'Auth/OpenID/SQLStore.php')
-rw-r--r--Auth/OpenID/SQLStore.php871
1 files changed, 871 insertions, 0 deletions
diff --git a/Auth/OpenID/SQLStore.php b/Auth/OpenID/SQLStore.php
new file mode 100644
index 0000000..a27118e
--- /dev/null
+++ b/Auth/OpenID/SQLStore.php
@@ -0,0 +1,871 @@
+<?php
+
+/**
+ * SQL-backed OpenID stores, including PostgreSQL, MySQL and SQLite.
+ *
+ * PHP versions 4 and 5
+ *
+ * LICENSE: See the COPYING file included in this distribution.
+ *
+ * @package OpenID
+ * @author JanRain, Inc. <openid@janrain.com>
+ * @copyright 2005 Janrain, Inc.
+ * @license http://www.gnu.org/copyleft/lesser.html LGPL
+ */
+
+/**
+ * Require the PEAR DB module because we'll need it for the SQL-based
+ * stores implemented here.
+ */
+require_once 'DB.php';
+/**
+ * @access private
+ */
+require_once 'Auth/OpenID/Interface.php';
+
+/**
+ * This is the parent class for the SQL stores, which contains the
+ * logic common to all of the SQL stores.
+ *
+ * The table names used are determined by the class variables
+ * settings_table_name, associations_table_name, and
+ * nonces_table_name. To change the name of the tables used, pass new
+ * table names into the constructor.
+ *
+ * To create the tables with the proper schema, see the createTables
+ * method.
+ *
+ * This class shouldn't be used directly. Use one of its subclasses
+ * instead, as those contain the code necessary to use a specific
+ * database.
+ *
+ * All methods other than the constructor and createTables should be
+ * considered implementation details.
+ *
+ * @access private
+ * @package OpenID
+ */
+class Auth_OpenID_SQLStore extends Auth_OpenID_OpenIDStore {
+
+ /**
+ * This creates a new SQLStore instance. It requires an
+ * established database connection be given to it, and it allows
+ * overriding the default table names.
+ *
+ * @param connection $conn This must be an established connection
+ * to a database of the correct type for the SQLStore subclass
+ * you're using.
+ *
+ * @param string $settings_table This is an optional parameter to
+ * specify the name of the table used for this store's settings.
+ * The default value is 'oid_settings'.
+ *
+ * @param associations_table: This is an optional parameter to
+ * specify the name of the table used for storing associations.
+ * The default value is 'oid_associations'.
+ *
+ * @param nonces_table: This is an optional parameter to specify
+ * the name of the table used for storing nonces. The default
+ * value is 'oid_nonces'.
+ */
+ function Auth_OpenID_SQLStore($connection, $settings_table = null,
+ $associations_table = null,
+ $nonces_table = null)
+ {
+ $this->settings_table_name = "oid_settings";
+ $this->associations_table_name = "oid_associations";
+ $this->nonces_table_name = "oid_nonces";
+
+ // Check the connection object type to be sure it's a PEAR
+ // database connection.
+ if (!(is_object($connection) &&
+ (is_subclass_of($connection, 'db_common') ||
+ is_subclass_of($connection,
+ 'auth_openid_databaseconnection')))) {
+ trigger_error("Auth_OpenID_SQLStore expected PEAR connection " .
+ "object (got ".get_class($connection).")",
+ E_USER_ERROR);
+ return;
+ }
+
+ $this->connection = $connection;
+
+ // Be sure to set the fetch mode so the results are keyed on
+ // column name instead of column index.
+ $this->connection->setFetchMode(DB_FETCHMODE_ASSOC);
+
+ if ($settings_table) {
+ $this->settings_table_name = $settings_table;
+ }
+
+ if ($associations_table) {
+ $this->associations_table_name = $associations_table;
+ }
+
+ if ($nonces_table) {
+ $this->nonces_table_name = $nonces_table;
+ }
+
+ $this->max_nonce_age = 6 * 60 * 60;
+
+ // Be sure to run the database queries with auto-commit mode
+ // turned OFF, because we want every function to run in a
+ // transaction, implicitly. As a rule, methods named with a
+ // leading underscore will NOT control transaction behavior.
+ // Callers of these methods will worry about transactions.
+ $this->connection->autoCommit(false);
+
+ // Create an empty SQL strings array.
+ $this->sql = array();
+
+ // Call this method (which should be overridden by subclasses)
+ // to populate the $this->sql array with SQL strings.
+ $this->setSQL();
+
+ // Verify that all required SQL statements have been set, and
+ // raise an error if any expected SQL strings were either
+ // absent or empty.
+ list($missing, $empty) = $this->_verifySQL();
+
+ if ($missing) {
+ trigger_error("Expected keys in SQL query list: " .
+ implode(", ", $missing),
+ E_USER_ERROR);
+ return;
+ }
+
+ if ($empty) {
+ trigger_error("SQL list keys have no SQL strings: " .
+ implode(", ", $empty),
+ E_USER_ERROR);
+ return;
+ }
+
+ // Add table names to queries.
+ $this->_fixSQL();
+ }
+
+ function tableExists($table_name)
+ {
+ return !$this->isError(
+ $this->connection->query("SELECT * FROM %s LIMIT 0",
+ $table_name));
+ }
+
+ /**
+ * Returns true if $value constitutes a database error; returns
+ * false otherwise.
+ */
+ function isError($value)
+ {
+ return PEAR::isError($value);
+ }
+
+ /**
+ * Converts a query result to a boolean. If the result is a
+ * database error according to $this->isError(), this returns
+ * false; otherwise, this returns true.
+ */
+ function resultToBool($obj)
+ {
+ if ($this->isError($obj)) {
+ return false;
+ } else {
+ return true;
+ }
+ }
+
+ /**
+ * This method should be overridden by subclasses. This method is
+ * called by the constructor to set values in $this->sql, which is
+ * an array keyed on sql name.
+ */
+ function setSQL()
+ {
+ }
+
+ /**
+ * Resets the store by removing all records from the store's
+ * tables.
+ */
+ function reset()
+ {
+ $this->connection->query(sprintf("DELETE FROM %s",
+ $this->associations_table_name));
+
+ $this->connection->query(sprintf("DELETE FROM %s",
+ $this->nonces_table_name));
+
+ $this->connection->query(sprintf("DELETE FROM %s",
+ $this->settings_table_name));
+ }
+
+ /**
+ * @access private
+ */
+ function _verifySQL()
+ {
+ $missing = array();
+ $empty = array();
+
+ $required_sql_keys = array(
+ 'nonce_table',
+ 'assoc_table',
+ 'settings_table',
+ 'get_auth',
+ 'create_auth',
+ 'set_assoc',
+ 'get_assoc',
+ 'get_assocs',
+ 'remove_assoc',
+ 'add_nonce',
+ 'get_nonce',
+ 'remove_nonce'
+ );
+
+ foreach ($required_sql_keys as $key) {
+ if (!array_key_exists($key, $this->sql)) {
+ $missing[] = $key;
+ } else if (!$this->sql[$key]) {
+ $empty[] = $key;
+ }
+ }
+
+ return array($missing, $empty);
+ }
+
+ /**
+ * @access private
+ */
+ function _fixSQL()
+ {
+ $replacements = array(
+ array(
+ 'value' => $this->nonces_table_name,
+ 'keys' => array('nonce_table',
+ 'add_nonce',
+ 'get_nonce',
+ 'remove_nonce')
+ ),
+ array(
+ 'value' => $this->associations_table_name,
+ 'keys' => array('assoc_table',
+ 'set_assoc',
+ 'get_assoc',
+ 'get_assocs',
+ 'remove_assoc')
+ ),
+ array(
+ 'value' => $this->settings_table_name,
+ 'keys' => array('settings_table',
+ 'get_auth',
+ 'create_auth')
+ )
+ );
+
+ foreach ($replacements as $item) {
+ $value = $item['value'];
+ $keys = $item['keys'];
+
+ foreach ($keys as $k) {
+ if (is_array($this->sql[$k])) {
+ foreach ($this->sql[$k] as $part_key => $part_value) {
+ $this->sql[$k][$part_key] = sprintf($part_value,
+ $value);
+ }
+ } else {
+ $this->sql[$k] = sprintf($this->sql[$k], $value);
+ }
+ }
+ }
+ }
+
+ function blobDecode($blob)
+ {
+ return $blob;
+ }
+
+ function blobEncode($str)
+ {
+ return $str;
+ }
+
+ function createTables()
+ {
+ $this->connection->autoCommit(true);
+ $n = $this->create_nonce_table();
+ $a = $this->create_assoc_table();
+ $s = $this->create_settings_table();
+ $this->connection->autoCommit(false);
+
+ if ($n && $a && $s) {
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ function create_nonce_table()
+ {
+ if (!$this->tableExists($this->nonces_table_name)) {
+ $r = $this->connection->query($this->sql['nonce_table']);
+ return $this->resultToBool($r);
+ }
+ return true;
+ }
+
+ function create_assoc_table()
+ {
+ if (!$this->tableExists($this->associations_table_name)) {
+ $r = $this->connection->query($this->sql['assoc_table']);
+ return $this->resultToBool($r);
+ }
+ return true;
+ }
+
+ function create_settings_table()
+ {
+ if (!$this->tableExists($this->settings_table_name)) {
+ $r = $this->connection->query($this->sql['settings_table']);
+ return $this->resultToBool($r);
+ }
+ return true;
+ }
+
+ /**
+ * @access private
+ */
+ function _get_auth()
+ {
+ return $this->connection->getOne($this->sql['get_auth']);
+ }
+
+ /**
+ * @access private
+ */
+ function _create_auth($str)
+ {
+ return $this->connection->query($this->sql['create_auth'],
+ array($str));
+ }
+
+ function getAuthKey()
+ {
+ $value = $this->_get_auth();
+ if (!$value) {
+ $auth_key = Auth_OpenID_randomString($this->AUTH_KEY_LEN);
+
+ $auth_key_s = $this->blobEncode($auth_key);
+ $this->_create_auth($auth_key_s);
+ } else {
+ $auth_key_s = $value;
+ $auth_key = $this->blobDecode($auth_key_s);
+ }
+
+ $this->connection->commit();
+
+ if (strlen($auth_key) != $this->AUTH_KEY_LEN) {
+ $fmt = "Expected %d-byte string for auth key. Got key of length %d";
+ trigger_error(sprintf($fmt, $this->AUTH_KEY_LEN, strlen($auth_key)),
+ E_USER_WARNING);
+ return null;
+ }
+
+ return $auth_key;
+ }
+
+ /**
+ * @access private
+ */
+ function _set_assoc($server_url, $handle, $secret, $issued,
+ $lifetime, $assoc_type)
+ {
+ return $this->connection->query($this->sql['set_assoc'],
+ array(
+ $server_url,
+ $handle,
+ $secret,
+ $issued,
+ $lifetime,
+ $assoc_type));
+ }
+
+ function storeAssociation($server_url, $association)
+ {
+ if ($this->resultToBool($this->_set_assoc(
+ $server_url,
+ $association->handle,
+ $this->blobEncode(
+ $association->secret),
+ $association->issued,
+ $association->lifetime,
+ $association->assoc_type
+ ))) {
+ $this->connection->commit();
+ } else {
+ $this->connection->rollback();
+ }
+ }
+
+ /**
+ * @access private
+ */
+ function _get_assoc($server_url, $handle)
+ {
+ $result = $this->connection->getRow($this->sql['get_assoc'],
+ array($server_url, $handle));
+ if ($this->isError($result)) {
+ return null;
+ } else {
+ return $result;
+ }
+ }
+
+ /**
+ * @access private
+ */
+ function _get_assocs($server_url)
+ {
+ return $this->connection->getAll($this->sql['get_assocs'],
+ array($server_url));
+ }
+
+ function removeAssociation($server_url, $handle)
+ {
+ if (!$this->getAssociation($server_url, $handle)) {
+ return false;
+ }
+
+ if ($this->resultToBool($this->connection->query(
+ $this->sql['remove_assoc'],
+ array($server_url, $handle)))) {
+ $this->connection->commit();
+ } else {
+ $this->connection->rollback();
+ }
+
+ return true;
+ }
+
+ function getAssociation($server_url, $handle = null)
+ {
+ if ($handle !== null) {
+ $assoc = $this->_get_assoc($server_url, $handle);
+
+ $assocs = array();
+ if ($assoc) {
+ $assocs[] = $assoc;
+ }
+ } else {
+ $assocs = $this->_get_assocs($server_url);
+ }
+
+ if (count($assocs) == 0) {
+ return null;
+ } else {
+ $associations = array();
+
+ foreach ($assocs as $assoc_row) {
+ $assoc = new Auth_OpenID_Association($assoc_row['handle'],
+ $assoc_row['secret'],
+ $assoc_row['issued'],
+ $assoc_row['lifetime'],
+ $assoc_row['assoc_type']);
+
+ $assoc->secret = $this->blobDecode($assoc->secret);
+
+ if ($assoc->getExpiresIn() == 0) {
+ $this->removeAssociation($server_url, $assoc->handle);
+ } else {
+ $associations[] = array($assoc->issued, $assoc);
+ }
+ }
+
+ if ($associations) {
+ $issued = array();
+ $assocs = array();
+ foreach ($associations as $key => $assoc) {
+ $issued[$key] = $assoc[0];
+ $assocs[$key] = $assoc[1];
+ }
+
+ array_multisort($issued, SORT_DESC, $assocs, SORT_DESC,
+ $associations);
+
+ // return the most recently issued one.
+ list($issued, $assoc) = $associations[0];
+ return $assoc;
+ } else {
+ return null;
+ }
+ }
+ }
+
+ /**
+ * @access private
+ */
+ function _add_nonce($nonce, $expires)
+ {
+ $sql = $this->sql['add_nonce'];
+ $result = $this->connection->query($sql, array($nonce, $expires));
+ return $this->resultToBool($result);
+ }
+
+ /**
+ * @access private
+ */
+ function storeNonce($nonce)
+ {
+ if ($this->_add_nonce($nonce, time())) {
+ $this->connection->commit();
+ } else {
+ $this->connection->rollback();
+ }
+ }
+
+ /**
+ * @access private
+ */
+ function _get_nonce($nonce)
+ {
+ $result = $this->connection->getRow($this->sql['get_nonce'],
+ array($nonce));
+
+ if ($this->isError($result)) {
+ return null;
+ } else {
+ return $result;
+ }
+ }
+
+ /**
+ * @access private
+ */
+ function _remove_nonce($nonce)
+ {
+ $this->connection->query($this->sql['remove_nonce'],
+ array($nonce));
+ }
+
+ function useNonce($nonce)
+ {
+ $row = $this->_get_nonce($nonce);
+
+ if ($row !== null) {
+ $nonce = $row['nonce'];
+ $timestamp = $row['expires'];
+ $nonce_age = time() - $timestamp;
+
+ if ($nonce_age > $this->max_nonce_age) {
+ $present = 0;
+ } else {
+ $present = 1;
+ }
+
+ $this->_remove_nonce($nonce);
+ } else {
+ $present = 0;
+ }
+
+ $this->connection->commit();
+
+ return $present;
+ }
+
+ /**
+ * "Octifies" a binary string by returning a string with escaped
+ * octal bytes. This is used for preparing binary data for
+ * PostgreSQL BYTEA fields.
+ *
+ * @access private
+ */
+ function _octify($str)
+ {
+ $result = "";
+ for ($i = 0; $i < strlen($str); $i++) {
+ $ch = substr($str, $i, 1);
+ if ($ch == "\\") {
+ $result .= "\\\\\\\\";
+ } else if (ord($ch) == 0) {
+ $result .= "\\\\000";
+ } else {
+ $result .= "\\" . strval(decoct(ord($ch)));
+ }
+ }
+ return $result;
+ }
+
+ /**
+ * "Unoctifies" octal-escaped data from PostgreSQL and returns the
+ * resulting ASCII (possibly binary) string.
+ *
+ * @access private
+ */
+ function _unoctify($str)
+ {
+ $result = "";
+ $i = 0;
+ while ($i < strlen($str)) {
+ $char = $str[$i];
+ if ($char == "\\") {
+ // Look to see if the next char is a backslash and
+ // append it.
+ if ($str[$i + 1] != "\\") {
+ $octal_digits = substr($str, $i + 1, 3);
+ $dec = octdec($octal_digits);
+ $char = chr($dec);
+ $i += 4;
+ } else {
+ $char = "\\";
+ $i += 2;
+ }
+ } else {
+ $i += 1;
+ }
+
+ $result .= $char;
+ }
+
+ return $result;
+ }
+}
+
+/**
+ * An SQL store that uses PostgreSQL as its backend.
+ *
+ * @package OpenID
+ */
+class Auth_OpenID_PostgreSQLStore extends Auth_OpenID_SQLStore {
+ /**
+ * @access private
+ */
+ function setSQL()
+ {
+ $this->sql['nonce_table'] =
+ "CREATE TABLE %s (nonce CHAR(8) UNIQUE PRIMARY KEY, ".
+ "expires INTEGER)";
+
+ $this->sql['assoc_table'] =
+ "CREATE TABLE %s (server_url VARCHAR(2047), handle VARCHAR(255), ".
+ "secret BYTEA, issued INTEGER, lifetime INTEGER, ".
+ "assoc_type VARCHAR(64), PRIMARY KEY (server_url, handle), ".
+ "CONSTRAINT secret_length_constraint CHECK ".
+ "(LENGTH(secret) <= 128))";
+
+ $this->sql['settings_table'] =
+ "CREATE TABLE %s (setting VARCHAR(128) UNIQUE PRIMARY KEY, ".
+ "value BYTEA, ".
+ "CONSTRAINT value_length_constraint CHECK (LENGTH(value) <= 20))";
+
+ $this->sql['create_auth'] =
+ "INSERT INTO %s VALUES ('auth_key', '!')";
+
+ $this->sql['get_auth'] =
+ "SELECT value FROM %s WHERE setting = 'auth_key'";
+
+ $this->sql['set_assoc'] =
+ array(
+ 'insert_assoc' => "INSERT INTO %s (server_url, handle, ".
+ "secret, issued, lifetime, assoc_type) VALUES ".
+ "(?, ?, '!', ?, ?, ?)",
+ 'update_assoc' => "UPDATE %s SET secret = '!', issued = ?, ".
+ "lifetime = ?, assoc_type = ? WHERE server_url = ? AND ".
+ "handle = ?"
+ );
+
+ $this->sql['get_assocs'] =
+ "SELECT handle, secret, issued, lifetime, assoc_type FROM %s ".
+ "WHERE server_url = ?";
+
+ $this->sql['get_assoc'] =
+ "SELECT handle, secret, issued, lifetime, assoc_type FROM %s ".
+ "WHERE server_url = ? AND handle = ?";
+
+ $this->sql['remove_assoc'] =
+ "DELETE FROM %s WHERE server_url = ? AND handle = ?";
+
+ $this->sql['add_nonce'] =
+ array(
+ 'insert_nonce' => "INSERT INTO %s (nonce, expires) VALUES ".
+ "(?, ?)",
+ 'update_nonce' => "UPDATE %s SET expires = ? WHERE nonce = ?"
+ );
+
+ $this->sql['get_nonce'] =
+ "SELECT * FROM %s WHERE nonce = ?";
+
+ $this->sql['remove_nonce'] =
+ "DELETE FROM %s WHERE nonce = ?";
+ }
+
+ /**
+ * @access private
+ */
+ function _set_assoc($server_url, $handle, $secret, $issued, $lifetime,
+ $assoc_type)
+ {
+ $result = $this->_get_assoc($server_url, $handle);
+ if ($result) {
+ // Update the table since this associations already exists.
+ $this->connection->query($this->sql['set_assoc']['update_assoc'],
+ array($secret, $issued, $lifetime,
+ $assoc_type, $server_url, $handle));
+ } else {
+ // Insert a new record because this association wasn't
+ // found.
+ $this->connection->query($this->sql['set_assoc']['insert_assoc'],
+ array($server_url, $handle, $secret,
+ $issued, $lifetime, $assoc_type));
+ }
+ }
+
+ /**
+ * @access private
+ */
+ function _add_nonce($nonce, $expires)
+ {
+ if ($this->_get_nonce($nonce)) {
+ return $this->resultToBool($this->connection->query(
+ $this->sql['add_nonce']['update_nonce'],
+ array($expires, $nonce)));
+ } else {
+ return $this->resultToBool($this->connection->query(
+ $this->sql['add_nonce']['insert_nonce'],
+ array($nonce, $expires)));
+ }
+ }
+
+ /**
+ * @access private
+ */
+ function blobEncode($blob)
+ {
+ return $this->_octify($blob);
+ }
+
+ /**
+ * @access private
+ */
+ function blobDecode($blob)
+ {
+ return $this->_unoctify($blob);
+ }
+}
+
+/**
+ * An SQL store that uses SQLite as its backend.
+ *
+ * @package OpenID
+ */
+class Auth_OpenID_SQLiteStore extends Auth_OpenID_SQLStore {
+ function setSQL()
+ {
+ $this->sql['nonce_table'] =
+ "CREATE TABLE %s (nonce CHAR(8) UNIQUE PRIMARY KEY, ".
+ "expires INTEGER)";
+
+ $this->sql['assoc_table'] =
+ "CREATE TABLE %s (server_url VARCHAR(2047), handle VARCHAR(255), ".
+ "secret BLOB(128), issued INTEGER, lifetime INTEGER, ".
+ "assoc_type VARCHAR(64), PRIMARY KEY (server_url, handle))";
+
+ $this->sql['settings_table'] =
+ "CREATE TABLE %s (setting VARCHAR(128) UNIQUE PRIMARY KEY, ".
+ "value BLOB(20))";
+
+ $this->sql['create_auth'] =
+ "INSERT INTO %s VALUES ('auth_key', ?)";
+
+ $this->sql['get_auth'] =
+ "SELECT value FROM %s WHERE setting = 'auth_key'";
+
+ $this->sql['set_assoc'] =
+ "INSERT OR REPLACE INTO %s VALUES (?, ?, ?, ?, ?, ?)";
+
+ $this->sql['get_assocs'] =
+ "SELECT handle, secret, issued, lifetime, assoc_type FROM %s ".
+ "WHERE server_url = ?";
+
+ $this->sql['get_assoc'] =
+ "SELECT handle, secret, issued, lifetime, assoc_type FROM %s ".
+ "WHERE server_url = ? AND handle = ?";
+
+ $this->sql['remove_assoc'] =
+ "DELETE FROM %s WHERE server_url = ? AND handle = ?";
+
+ $this->sql['add_nonce'] =
+ "INSERT OR REPLACE INTO %s (nonce, expires) VALUES (?, ?)";
+
+ $this->sql['get_nonce'] =
+ "SELECT * FROM %s WHERE nonce = ?";
+
+ $this->sql['remove_nonce'] =
+ "DELETE FROM %s WHERE nonce = ?";
+ }
+}
+
+/**
+ * An SQL store that uses MySQL as its backend.
+ *
+ * @package OpenID
+ */
+class Auth_OpenID_MySQLStore extends Auth_OpenID_SQLStore {
+ /**
+ * @access private
+ */
+ function setSQL()
+ {
+ $this->sql['nonce_table'] =
+ "CREATE TABLE %s (nonce CHAR(8) UNIQUE PRIMARY KEY, ".
+ "expires INTEGER) TYPE=InnoDB";
+
+ $this->sql['assoc_table'] =
+ "CREATE TABLE %s (server_url BLOB, handle VARCHAR(255), ".
+ "secret BLOB, issued INTEGER, lifetime INTEGER, ".
+ "assoc_type VARCHAR(64), PRIMARY KEY (server_url(255), handle)) ".
+ "TYPE=InnoDB";
+
+ $this->sql['settings_table'] =
+ "CREATE TABLE %s (setting VARCHAR(128) UNIQUE PRIMARY KEY, ".
+ "value BLOB) TYPE=InnoDB";
+
+ $this->sql['create_auth'] =
+ "INSERT INTO %s VALUES ('auth_key', !)";
+
+ $this->sql['get_auth'] =
+ "SELECT value FROM %s WHERE setting = 'auth_key'";
+
+ $this->sql['set_assoc'] =
+ "REPLACE INTO %s VALUES (?, ?, !, ?, ?, ?)";
+
+ $this->sql['get_assocs'] =
+ "SELECT handle, secret, issued, lifetime, assoc_type FROM %s ".
+ "WHERE server_url = ?";
+
+ $this->sql['get_assoc'] =
+ "SELECT handle, secret, issued, lifetime, assoc_type FROM %s ".
+ "WHERE server_url = ? AND handle = ?";
+
+ $this->sql['remove_assoc'] =
+ "DELETE FROM %s WHERE server_url = ? AND handle = ?";
+
+ $this->sql['add_nonce'] =
+ "REPLACE INTO %s (nonce, expires) VALUES (?, ?)";
+
+ $this->sql['get_nonce'] =
+ "SELECT * FROM %s WHERE nonce = ?";
+
+ $this->sql['remove_nonce'] =
+ "DELETE FROM %s WHERE nonce = ?";
+ }
+
+ /**
+ * @access private
+ */
+ function blobEncode($blob)
+ {
+ return "0x" . bin2hex($blob);
+ }
+}
+
+?>