summaryrefslogtreecommitdiff
path: root/tests/test_tools/simpletest/authentication.php
blob: cae366b328fbc43c6978f3111d3112775dc0b742 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
<?php
    /**
     *	Base include file for SimpleTest
     *	@package	SimpleTest
     *	@subpackage	WebTester
     *	@version	$Id: authentication.php 1532 2006-12-01 12:28:55Z xue $
     */
    /**
     *	include http class
     */
    require_once(dirname(__FILE__) . '/http.php');

    /**
     *    Represents a single security realm's identity.
	 *    @package SimpleTest
	 *    @subpackage WebTester
     */
    class SimpleRealm {
        protected $_type;
        protected $_root;
        protected $_username;
        protected $_password;

        /**
         *    Starts with the initial entry directory.
         *    @param string $type      Authentication type for this
         *                             realm. Only Basic authentication
         *                             is currently supported.
         *    @param SimpleUrl $url    Somewhere in realm.
         *    @access public
         */
        function SimpleRealm($type, $url) {
            $this->_type = $type;
            $this->_root = $url->getBasePath();
            $this->_username = false;
            $this->_password = false;
        }

        /**
         *    Adds another location to the realm.
         *    @param SimpleUrl $url    Somewhere in realm.
         *    @access public
         */
        function stretch($url) {
            $this->_root = $this->_getCommonPath($this->_root, $url->getPath());
        }

        /**
         *    Finds the common starting path.
         *    @param string $first        Path to compare.
         *    @param string $second       Path to compare.
         *    @return string              Common directories.
         *    @access private
         */
        function _getCommonPath($first, $second) {
            $first = explode('/', $first);
            $second = explode('/', $second);
            for ($i = 0; $i < min(count($first), count($second)); $i++) {
                if ($first[$i] != $second[$i]) {
                    return implode('/', array_slice($first, 0, $i)) . '/';
                }
            }
            return implode('/', $first) . '/';
        }

        /**
         *    Sets the identity to try within this realm.
         *    @param string $username    Username in authentication dialog.
         *    @param string $username    Password in authentication dialog.
         *    @access public
         */
        function setIdentity($username, $password) {
            $this->_username = $username;
            $this->_password = $password;
        }

        /**
         *    Accessor for current identity.
         *    @return string        Last succesful username.
         *    @access public
         */
        function getUsername() {
            return $this->_username;
        }

        /**
         *    Accessor for current identity.
         *    @return string        Last succesful password.
         *    @access public
         */
        function getPassword() {
            return $this->_password;
        }

        /**
         *    Test to see if the URL is within the directory
         *    tree of the realm.
         *    @param SimpleUrl $url    URL to test.
         *    @return boolean          True if subpath.
         *    @access public
         */
        function isWithin($url) {
            if ($this->_isIn($this->_root, $url->getBasePath())) {
                return true;
            }
            if ($this->_isIn($this->_root, $url->getBasePath() . $url->getPage() . '/')) {
                return true;
            }
            return false;
        }

        /**
         *    Tests to see if one string is a substring of
         *    another.
         *    @param string $part        Small bit.
         *    @param string $whole       Big bit.
         *    @return boolean            True if the small bit is
         *                               in the big bit.
         *    @access private
         */
        function _isIn($part, $whole) {
            return strpos($whole, $part) === 0;
        }
    }

    /**
     *    Manages security realms.
	 *    @package SimpleTest
	 *    @subpackage WebTester
     */
    class SimpleAuthenticator {
        protected $_realms;

        /**
         *    Clears the realms.
         *    @access public
         */
        function SimpleAuthenticator() {
            $this->restartSession();
        }

        /**
         *    Starts with no realms set up.
         *    @access public
         */
        function restartSession() {
            $this->_realms = array();
        }

        /**
         *    Adds a new realm centered the current URL.
         *    Browsers vary wildly on their behaviour in this
         *    regard. Mozilla ignores the realm and presents
         *    only when challenged, wasting bandwidth. IE
         *    just carries on presenting until a new challenge
         *    occours. SimpleTest tries to follow the spirit of
         *    the original standards committee and treats the
         *    base URL as the root of a file tree shaped realm.
         *    @param SimpleUrl $url    Base of realm.
         *    @param string $type      Authentication type for this
         *                             realm. Only Basic authentication
         *                             is currently supported.
         *    @param string $realm     Name of realm.
         *    @access public
         */
        function addRealm($url, $type, $realm) {
            $this->_realms[$url->getHost()][$realm] = new SimpleRealm($type, $url);
        }

        /**
         *    Sets the current identity to be presented
         *    against that realm.
         *    @param string $host        Server hosting realm.
         *    @param string $realm       Name of realm.
         *    @param string $username    Username for realm.
         *    @param string $password    Password for realm.
         *    @access public
         */
        function setIdentityForRealm($host, $realm, $username, $password) {
            if (isset($this->_realms[$host][$realm])) {
                $this->_realms[$host][$realm]->setIdentity($username, $password);
            }
        }

        /**
         *    Finds the name of the realm by comparing URLs.
         *    @param SimpleUrl $url        URL to test.
         *    @return SimpleRealm          Name of realm.
         *    @access private
         */
        function _findRealmFromUrl($url) {
            if (! isset($this->_realms[$url->getHost()])) {
                return false;
            }
            foreach ($this->_realms[$url->getHost()] as $name => $realm) {
                if ($realm->isWithin($url)) {
                    return $realm;
                }
            }
            return false;
        }

        /**
         *    Presents the appropriate headers for this location.
         *    @param SimpleHttpRequest $request  Request to modify.
         *    @param SimpleUrl $url              Base of realm.
         *    @access public
         */
        function addHeaders($request, $url) {
            if ($url->getUsername() && $url->getPassword()) {
                $username = $url->getUsername();
                $password = $url->getPassword();
            } elseif ($realm = $this->_findRealmFromUrl($url)) {
                $username = $realm->getUsername();
                $password = $realm->getPassword();
            } else {
                return;
            }
            $this->addBasicHeaders($request, $username, $password);
        }

        /**
         *    Presents the appropriate headers for this
         *    location for basic authentication.
         *    @param SimpleHttpRequest $request  Request to modify.
         *    @param string $username            Username for realm.
         *    @param string $password            Password for realm.
         *    @access public
         *    @static
         */
        static function addBasicHeaders($request, $username, $password) {
            if ($username && $password) {
                $request->addHeaderLine(
                        'Authorization: Basic ' . base64_encode("$username:$password"));
            }
        }
    }
?>