]> git.mxchange.org Git - quix0rs-gnu-social.git/blobdiff - extlib/Auth/OpenID/MDB2Store.php
Updating Janrain OpenID auth library
[quix0rs-gnu-social.git] / extlib / Auth / OpenID / MDB2Store.php
diff --git a/extlib/Auth/OpenID/MDB2Store.php b/extlib/Auth/OpenID/MDB2Store.php
new file mode 100644 (file)
index 0000000..fb27d5c
--- /dev/null
@@ -0,0 +1,413 @@
+<?php
+
+/**
+ * SQL-backed OpenID stores for use with PEAR::MDB2.
+ *
+ * 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_once 'MDB2.php';
+
+/**
+ * @access private
+ */
+require_once 'Auth/OpenID/Interface.php';
+
+/**
+ * @access private
+ */
+require_once 'Auth/OpenID.php';
+
+/**
+ * @access private
+ */
+require_once 'Auth/OpenID/Nonce.php';
+
+/**
+ * This store uses a PEAR::MDB2 connection to store persistence
+ * information.
+ *
+ * The table names used are determined by the class variables
+ * 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.
+ *
+ * @package OpenID
+ */
+class Auth_OpenID_MDB2Store extends Auth_OpenID_OpenIDStore {
+    /**
+     * This creates a new MDB2Store instance.  It requires an
+     * established database connection be given to it, and it allows
+     * overriding the default table names.
+     *
+     * @param connection $connection This must be an established
+     * connection to a database of the correct type for the SQLStore
+     * subclass you're using.  This must be a PEAR::MDB2 connection
+     * handle.
+     *
+     * @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_MDB2Store($connection,
+                                  $associations_table = null,
+                                  $nonces_table = null)
+    {
+        $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, 'mdb2_driver_common')) {
+            trigger_error("Auth_OpenID_MDB2Store 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(MDB2_FETCHMODE_ASSOC);
+        
+        if (@PEAR::isError($this->connection->loadModule('Extended'))) {
+            trigger_error("Unable to load MDB2_Extended module", E_USER_ERROR);
+            return;
+        }
+
+        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;
+    }
+
+    function tableExists($table_name)
+    {
+        return !@PEAR::isError($this->connection->query(
+                                  sprintf("SELECT * FROM %s LIMIT 0",
+                                          $table_name)));
+    }
+
+    function createTables()
+    {
+        $n = $this->create_nonce_table();
+        $a = $this->create_assoc_table();
+
+        if (!$n || !$a) {
+            return false;
+        }
+        return true;
+    }
+
+    function create_nonce_table()
+    {
+        if (!$this->tableExists($this->nonces_table_name)) {
+            switch ($this->connection->phptype) {
+                case "mysql":
+                case "mysqli":
+                    // Custom SQL for MySQL to use InnoDB and variable-
+                    // length keys
+                    $r = $this->connection->exec(
+                        sprintf("CREATE TABLE %s (\n".
+                                "  server_url VARCHAR(2047) NOT NULL DEFAULT '',\n".
+                                "  timestamp INTEGER NOT NULL,\n".
+                                "  salt CHAR(40) NOT NULL,\n".
+                                "  UNIQUE (server_url(255), timestamp, salt)\n".
+                                ") TYPE=InnoDB",
+                                $this->nonces_table_name));
+                    if (@PEAR::isError($r)) {
+                        return false;
+                    }
+                    break;
+                default:
+                    if (@PEAR::isError(
+                        $this->connection->loadModule('Manager'))) {
+                        return false;
+                    }
+                    $fields = array(
+                        "server_url" => array(
+                            "type" => "text",
+                            "length" => 2047,
+                            "notnull" => true
+                        ),
+                        "timestamp" => array(
+                            "type" => "integer",
+                            "notnull" => true
+                        ),
+                        "salt" => array(
+                            "type" => "text",
+                            "length" => 40,
+                            "fixed" => true,
+                            "notnull" => true
+                        )
+                    );
+                    $constraint = array(
+                        "unique" => 1,
+                        "fields" => array(
+                            "server_url" => true,
+                            "timestamp" => true,
+                            "salt" => true
+                        )
+                    );
+                    
+                    $r = $this->connection->createTable($this->nonces_table_name,
+                                                        $fields);
+                    if (@PEAR::isError($r)) {
+                        return false;
+                    }
+                    
+                    $r = $this->connection->createConstraint(
+                        $this->nonces_table_name,
+                        $this->nonces_table_name . "_constraint",
+                        $constraint);
+                    if (@PEAR::isError($r)) {
+                        return false;
+                    }
+                    break;
+            }
+        }
+        return true;
+    }
+
+    function create_assoc_table()
+    {
+        if (!$this->tableExists($this->associations_table_name)) {
+            switch ($this->connection->phptype) {
+                case "mysql":
+                case "mysqli":
+                    // Custom SQL for MySQL to use InnoDB and variable-
+                    // length keys
+                    $r = $this->connection->exec(
+                        sprintf("CREATE TABLE %s(\n".
+                                "  server_url VARCHAR(2047) NOT NULL DEFAULT '',\n".
+                                "  handle VARCHAR(255) NOT NULL,\n".
+                                "  secret BLOB NOT NULL,\n".
+                                "  issued INTEGER NOT NULL,\n".
+                                "  lifetime INTEGER NOT NULL,\n".
+                                "  assoc_type VARCHAR(64) NOT NULL,\n".
+                                "  PRIMARY KEY (server_url(255), handle)\n".
+                                ") TYPE=InnoDB",
+                            $this->associations_table_name));
+                    if (@PEAR::isError($r)) {
+                        return false;
+                    }
+                    break;
+                default:
+                    if (@PEAR::isError(
+                        $this->connection->loadModule('Manager'))) {
+                        return false;
+                    }
+                    $fields = array(
+                        "server_url" => array(
+                            "type" => "text",
+                            "length" => 2047,
+                            "notnull" => true
+                        ),
+                        "handle" => array(
+                            "type" => "text",
+                            "length" => 255,
+                            "notnull" => true
+                        ),
+                        "secret" => array(
+                            "type" => "blob",
+                            "length" => "255",
+                            "notnull" => true
+                        ),
+                        "issued" => array(
+                            "type" => "integer",
+                            "notnull" => true
+                        ),
+                        "lifetime" => array(
+                            "type" => "integer",
+                            "notnull" => true
+                        ),
+                        "assoc_type" => array(
+                            "type" => "text",
+                            "length" => 64,
+                            "notnull" => true
+                        )
+                    );
+                    $options = array(
+                        "primary" => array(
+                            "server_url" => true,
+                            "handle" => true
+                        )
+                    );
+                    
+                    $r = $this->connection->createTable(
+                        $this->associations_table_name,
+                        $fields,
+                        $options);
+                    if (@PEAR::isError($r)) {
+                        return false;
+                    }
+                    break;
+            }
+        }
+        return true;
+    }
+
+    function storeAssociation($server_url, $association)
+    {
+        $fields = array(
+            "server_url" => array(
+                "value" => $server_url,
+                "key" => true
+            ),
+            "handle" => array(
+                "value" => $association->handle,
+                "key" => true
+            ),
+            "secret" => array(
+                "value" => $association->secret,
+                "type" => "blob"
+            ),
+            "issued" => array(
+                "value" => $association->issued
+            ),
+            "lifetime" => array(
+                "value" => $association->lifetime
+            ),
+            "assoc_type" => array(
+                "value" => $association->assoc_type
+            )
+        );
+        
+        return !@PEAR::isError($this->connection->replace(
+                                  $this->associations_table_name,
+                                  $fields));
+    }
+
+    function cleanupNonces()
+    {
+        global $Auth_OpenID_SKEW;
+        $v = time() - $Auth_OpenID_SKEW;
+
+        return $this->connection->exec(
+            sprintf("DELETE FROM %s WHERE timestamp < %d",
+                    $this->nonces_table_name, $v));
+    }
+
+    function cleanupAssociations()
+    {
+        return $this->connection->exec(
+            sprintf("DELETE FROM %s WHERE issued + lifetime < %d",
+                    $this->associations_table_name, time()));
+    }
+
+    function getAssociation($server_url, $handle = null)
+    {
+        $sql = "";
+        $params = null;
+        $types = array(
+                       "text",
+                       "blob",
+                       "integer",
+                       "integer",
+                       "text"
+                       );
+        if ($handle !== null) {
+            $sql = sprintf("SELECT handle, secret, issued, lifetime, assoc_type " .
+                           "FROM %s WHERE server_url = ? AND handle = ?",
+                           $this->associations_table_name);
+            $params = array($server_url, $handle);
+        } else {
+            $sql = sprintf("SELECT handle, secret, issued, lifetime, assoc_type " .
+                           "FROM %s WHERE server_url = ? ORDER BY issued DESC",
+                           $this->associations_table_name);
+            $params = array($server_url);
+        }
+        
+        $assoc = $this->connection->getRow($sql, $types, $params);
+
+        if (!$assoc || @PEAR::isError($assoc)) {
+            return null;
+        } else {
+            $association = new Auth_OpenID_Association($assoc['handle'],
+                                                       stream_get_contents(
+                                                           $assoc['secret']),
+                                                       $assoc['issued'],
+                                                       $assoc['lifetime'],
+                                                       $assoc['assoc_type']);
+            fclose($assoc['secret']);
+            return $association;
+        }
+    }
+
+    function removeAssociation($server_url, $handle)
+    {
+        $r = $this->connection->execParam(
+            sprintf("DELETE FROM %s WHERE server_url = ? AND handle = ?",
+                    $this->associations_table_name),
+            array($server_url, $handle));
+        
+        if (@PEAR::isError($r) || $r == 0) {
+            return false;
+        }
+        return true;
+    }
+
+    function useNonce($server_url, $timestamp, $salt)
+    {
+        global $Auth_OpenID_SKEW;
+
+        if (abs($timestamp - time()) > $Auth_OpenID_SKEW ) {
+            return false;
+        }
+        
+        $fields = array(
+                        "timestamp" => $timestamp,
+                        "salt" => $salt
+                        );
+        
+        if (!empty($server_url)) {
+            $fields["server_url"] = $server_url;
+        }
+        
+        $r = $this->connection->autoExecute(
+            $this->nonces_table_name,
+            $fields,
+            MDB2_AUTOQUERY_INSERT);
+        
+        if (@PEAR::isError($r)) {
+            return false;
+        }
+        return true;
+    }
+
+    /**
+     * 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));
+    }
+
+}
+
+?>