1<?php
2
3/**
4 * In-memory OpenID store implementation for testing only
5 */
6require_once "Auth/OpenID/Interface.php";
7require_once 'Auth/OpenID/Nonce.php';
8
9class ServerAssocs {
10    function __construct()
11    {
12        $this->assocs = [];
13    }
14
15    function set($assoc)
16    {
17        $this->assocs[$assoc->handle] = $assoc;
18    }
19
20    function get($handle)
21    {
22        return Auth_OpenID::arrayGet($this->assocs, $handle);
23    }
24
25    function remove($handle)
26    {
27        if (array_key_exists($handle, $this->assocs)) {
28            unset($this->assocs[$handle]);
29            return true;
30        } else {
31            return false;
32        }
33    }
34
35    /*
36     * Returns association with the oldest issued date.
37     *
38     * or null if there are no associations.
39     */
40    function best()
41    {
42        $best = null;
43        foreach ($this->assocs as $handle => $assoc) {
44            if (($best === null) || ($best->issued < $assoc->issued)) {
45                $best = $assoc;
46            }
47        }
48        return $best;
49    }
50
51    /*
52     * Remove expired associations.
53     *
54     * @return (removed associations, remaining associations)
55     */
56    function cleanup()
57    {
58        $remove = [];
59        foreach ($this->assocs as $handle => $assoc) {
60            if ($assoc->getExpiresIn() == 0) {
61                $remove[] = $handle;
62            }
63        }
64
65        foreach ($remove as $handle) {
66            unset($this->assocs[$handle]);
67        }
68
69        return [count($remove), count($this->assocs)];
70    }
71}
72
73/*
74 * In-process memory store.
75 *
76 * Use for single long-running processes.  No persistence supplied.
77 */
78class Tests_Auth_OpenID_MemStore extends Auth_OpenID_OpenIDStore {
79    function __construct()
80    {
81        $this->server_assocs = [];
82        $this->nonces = [];
83    }
84
85    function &_getServerAssocs($server_url)
86    {
87        if (!array_key_exists($server_url, $this->server_assocs)) {
88            $this->server_assocs[$server_url] = new ServerAssocs();
89        }
90
91        return $this->server_assocs[$server_url];
92    }
93
94    function storeAssociation($server_url, $assoc)
95    {
96        $assocs =& $this->_getServerAssocs($server_url);
97        $assocs->set($assoc);
98    }
99
100    function getAssociation($server_url, $handle=null)
101    {
102        $assocs =& $this->_getServerAssocs($server_url);
103        if ($handle === null) {
104            return $assocs->best();
105        } else {
106            return $assocs->get($handle);
107        }
108    }
109
110    function removeAssociation($server_url, $handle)
111    {
112        $assocs =& $this->_getServerAssocs($server_url);
113        return $assocs->remove($handle);
114    }
115
116    function useNonce($server_url, $timestamp, $salt)
117    {
118        global $Auth_OpenID_SKEW;
119
120        if (abs($timestamp - time()) > $Auth_OpenID_SKEW) {
121            return false;
122        }
123
124        $anonce = [$server_url, intval($timestamp), $salt];
125
126        if (in_array($anonce, $this->nonces)) {
127            return false;
128        } else {
129            array_push($this->nonces, $anonce);
130            return true;
131        }
132    }
133
134    function cleanupNonces()
135    {
136        global $Auth_OpenID_SKEW;
137
138        $now = time();
139        $expired = [];
140        foreach ($this->nonces as $anonce) {
141            if (abs($anonce[1] - $now) > $Auth_OpenID_SKEW) {
142                // removing items while iterating over the set could
143                // be bad.
144                $expired[] = $anonce;
145            }
146        }
147
148        foreach ($expired as $anonce) {
149            unset($this->nonces[array_search($anonce, $this->nonces)]);
150        }
151
152        return count($expired);
153    }
154
155    function cleanupAssociations()
156    {
157        $remove_urls = [];
158        $removed_assocs = 0;
159        foreach ($this->server_assocs as $server_url => $assocs) {
160            list($removed, $remaining) = $assocs->cleanup();
161            $removed_assocs += $removed;
162            if (!$remaining) {
163                $remove_urls[] = $server_url;
164            }
165        }
166
167        // Remove entries from server_assocs that had none remaining.
168        foreach ($remove_urls as $server_url) {
169            unset($this->server_assocs[$server_url]);
170        }
171
172        return $removed_assocs;
173    }
174}
175
176
177