]> git.mxchange.org Git - quix0rs-gnu-social.git/blobdiff - extlib/Auth/OpenID/MemcachedStore.php
include external libs in a subdir to make install easier
[quix0rs-gnu-social.git] / extlib / Auth / OpenID / MemcachedStore.php
diff --git a/extlib/Auth/OpenID/MemcachedStore.php b/extlib/Auth/OpenID/MemcachedStore.php
new file mode 100644 (file)
index 0000000..d357c6b
--- /dev/null
@@ -0,0 +1,208 @@
+<?php
+
+/**
+ * This file supplies a memcached store backend for OpenID servers and
+ * consumers.
+ *
+ * PHP versions 4 and 5
+ *
+ * LICENSE: See the COPYING file included in this distribution.
+ *
+ * @package OpenID
+ * @author Artemy Tregubenko <me@arty.name>
+ * @copyright 2008 JanRain, Inc.
+ * @license http://www.apache.org/licenses/LICENSE-2.0 Apache
+ * Contributed by Open Web Technologies <http://openwebtech.ru/>
+ */
+
+/**
+ * Import the interface for creating a new store class.
+ */
+require_once 'Auth/OpenID/Interface.php';
+
+/**
+ * This is a memcached-based store for OpenID associations and
+ * nonces. 
+ * 
+ * As memcache has limit of 250 chars for key length, 
+ * server_url, handle and salt are hashed with sha1(). 
+ *
+ * Most of the methods of this class are implementation details.
+ * People wishing to just use this store need only pay attention to
+ * the constructor.
+ *
+ * @package OpenID
+ */
+class Auth_OpenID_MemcachedStore extends Auth_OpenID_OpenIDStore {
+
+    /**
+     * Initializes a new {@link Auth_OpenID_MemcachedStore} instance.
+     * Just saves memcached object as property.
+     *
+     * @param resource connection Memcache connection resourse
+     */
+    function Auth_OpenID_MemcachedStore($connection, $compress = false)
+    {
+        $this->connection = $connection;
+        $this->compress = $compress ? MEMCACHE_COMPRESSED : 0;
+    }
+
+    /**
+     * Store association until its expiration time in memcached. 
+     * Overwrites any existing association with same server_url and 
+     * handle. Handles list of associations for every server. 
+     */
+    function storeAssociation($server_url, $association)
+    {
+        // create memcached keys for association itself 
+        // and list of associations for this server
+        $associationKey = $this->associationKey($server_url, 
+            $association->handle);
+        $serverKey = $this->associationServerKey($server_url);
+        
+        // get list of associations 
+        $serverAssociations = $this->connection->get($serverKey);
+        
+        // if no such list, initialize it with empty array
+        if (!$serverAssociations) {
+            $serverAssociations = array();
+        }
+        // and store given association key in it
+        $serverAssociations[$association->issued] = $associationKey;
+        
+        // save associations' keys list 
+        $this->connection->set(
+            $serverKey,
+            $serverAssociations,
+            $this->compress
+        );
+        // save association itself
+        $this->connection->set(
+            $associationKey,
+            $association, 
+            $this->compress, 
+            $association->issued + $association->lifetime);
+    }
+
+    /**
+     * Read association from memcached. If no handle given 
+     * and multiple associations found, returns latest issued
+     */
+    function getAssociation($server_url, $handle = null)
+    {
+        // simple case: handle given
+        if ($handle !== null) {
+            // get association, return null if failed
+            $association = $this->connection->get(
+                $this->associationKey($server_url, $handle));
+            return $association ? $association : null;
+        }
+        
+        // no handle given, working with list
+        // create key for list of associations
+        $serverKey = $this->associationServerKey($server_url);
+        
+        // get list of associations
+        $serverAssociations = $this->connection->get($serverKey);
+        // return null if failed or got empty list
+        if (!$serverAssociations) {
+            return null;
+        }
+        
+        // get key of most recently issued association
+        $keys = array_keys($serverAssociations);
+        sort($keys);
+        $lastKey = $serverAssociations[array_pop($keys)];
+        
+        // get association, return null if failed
+        $association = $this->connection->get($lastKey);
+        return $association ? $association : null;
+    }
+
+    /**
+     * Immediately delete association from memcache.
+     */
+    function removeAssociation($server_url, $handle)
+    {
+        // create memcached keys for association itself 
+        // and list of associations for this server
+        $serverKey = $this->associationServerKey($server_url);
+        $associationKey = $this->associationKey($server_url, 
+            $handle);
+        
+        // get list of associations
+        $serverAssociations = $this->connection->get($serverKey);
+        // return null if failed or got empty list
+        if (!$serverAssociations) {
+            return false;
+        }
+        
+        // ensure that given association key exists in list
+        $serverAssociations = array_flip($serverAssociations);
+        if (!array_key_exists($associationKey, $serverAssociations)) {
+            return false;
+        }
+        
+        // remove given association key from list
+        unset($serverAssociations[$associationKey]);
+        $serverAssociations = array_flip($serverAssociations);
+        
+        // save updated list
+        $this->connection->set(
+            $serverKey,
+            $serverAssociations,
+            $this->compress
+        );
+
+        // delete association 
+        return $this->connection->delete($associationKey);
+    }
+
+    /**
+     * Create nonce for server and salt, expiring after 
+     * $Auth_OpenID_SKEW seconds.
+     */
+    function useNonce($server_url, $timestamp, $salt)
+    {
+        global $Auth_OpenID_SKEW;
+        
+        // save one request to memcache when nonce obviously expired 
+        if (abs($timestamp - time()) > $Auth_OpenID_SKEW) {
+            return false;
+        }
+        
+        // returns false when nonce already exists
+        // otherwise adds nonce
+        return $this->connection->add(
+            'openid_nonce_' . sha1($server_url) . '_' . sha1($salt), 
+            1, // any value here 
+            $this->compress, 
+            $Auth_OpenID_SKEW);
+    }
+    
+    /**
+     * Memcache key is prefixed with 'openid_association_' string. 
+     */
+    function associationKey($server_url, $handle = null) 
+    {
+        return 'openid_association_' . sha1($server_url) . '_' . sha1($handle);
+    }
+    
+    /**
+     * Memcache key is prefixed with 'openid_association_' string. 
+     */
+    function associationServerKey($server_url) 
+    {
+        return 'openid_association_server_' . sha1($server_url);
+    }
+    
+    /**
+     * Report that this storage doesn't support cleanup
+     */
+    function supportsCleanup()
+    {
+        return false;
+    }
+}
+
+?>
\ No newline at end of file