Merge branch 'MDL-29201_20' of git://github.com/timhunt/moodle into MOODLE_20_STABLE
[moodle.git] / lib / simpletestlib / authentication.php
blob382f1289aaa365624389e6c853d45df9bfae68fe
1 <?php
2 /**
3 * Base include file for SimpleTest
4 * @package SimpleTest
5 * @subpackage WebTester
6 * @version $Id$
7 */
8 /**
9 * include http class
11 require_once(dirname(__FILE__) . '/http.php');
13 /**
14 * Represents a single security realm's identity.
15 * @package SimpleTest
16 * @subpackage WebTester
18 class SimpleRealm {
19 var $_type;
20 var $_root;
21 var $_username;
22 var $_password;
24 /**
25 * Starts with the initial entry directory.
26 * @param string $type Authentication type for this
27 * realm. Only Basic authentication
28 * is currently supported.
29 * @param SimpleUrl $url Somewhere in realm.
30 * @access public
32 function SimpleRealm($type, $url) {
33 $this->_type = $type;
34 $this->_root = $url->getBasePath();
35 $this->_username = false;
36 $this->_password = false;
39 /**
40 * Adds another location to the realm.
41 * @param SimpleUrl $url Somewhere in realm.
42 * @access public
44 function stretch($url) {
45 $this->_root = $this->_getCommonPath($this->_root, $url->getPath());
48 /**
49 * Finds the common starting path.
50 * @param string $first Path to compare.
51 * @param string $second Path to compare.
52 * @return string Common directories.
53 * @access private
55 function _getCommonPath($first, $second) {
56 $first = explode('/', $first);
57 $second = explode('/', $second);
58 for ($i = 0; $i < min(count($first), count($second)); $i++) {
59 if ($first[$i] != $second[$i]) {
60 return implode('/', array_slice($first, 0, $i)) . '/';
63 return implode('/', $first) . '/';
66 /**
67 * Sets the identity to try within this realm.
68 * @param string $username Username in authentication dialog.
69 * @param string $username Password in authentication dialog.
70 * @access public
72 function setIdentity($username, $password) {
73 $this->_username = $username;
74 $this->_password = $password;
77 /**
78 * Accessor for current identity.
79 * @return string Last succesful username.
80 * @access public
82 function getUsername() {
83 return $this->_username;
86 /**
87 * Accessor for current identity.
88 * @return string Last succesful password.
89 * @access public
91 function getPassword() {
92 return $this->_password;
95 /**
96 * Test to see if the URL is within the directory
97 * tree of the realm.
98 * @param SimpleUrl $url URL to test.
99 * @return boolean True if subpath.
100 * @access public
102 function isWithin($url) {
103 if ($this->_isIn($this->_root, $url->getBasePath())) {
104 return true;
106 if ($this->_isIn($this->_root, $url->getBasePath() . $url->getPage() . '/')) {
107 return true;
109 return false;
113 * Tests to see if one string is a substring of
114 * another.
115 * @param string $part Small bit.
116 * @param string $whole Big bit.
117 * @return boolean True if the small bit is
118 * in the big bit.
119 * @access private
121 function _isIn($part, $whole) {
122 return strpos($whole, $part) === 0;
127 * Manages security realms.
128 * @package SimpleTest
129 * @subpackage WebTester
131 class SimpleAuthenticator {
132 var $_realms;
135 * Clears the realms.
136 * @access public
138 function SimpleAuthenticator() {
139 $this->restartSession();
143 * Starts with no realms set up.
144 * @access public
146 function restartSession() {
147 $this->_realms = array();
151 * Adds a new realm centered the current URL.
152 * Browsers vary wildly on their behaviour in this
153 * regard. Mozilla ignores the realm and presents
154 * only when challenged, wasting bandwidth. IE
155 * just carries on presenting until a new challenge
156 * occours. SimpleTest tries to follow the spirit of
157 * the original standards committee and treats the
158 * base URL as the root of a file tree shaped realm.
159 * @param SimpleUrl $url Base of realm.
160 * @param string $type Authentication type for this
161 * realm. Only Basic authentication
162 * is currently supported.
163 * @param string $realm Name of realm.
164 * @access public
166 function addRealm($url, $type, $realm) {
167 $this->_realms[$url->getHost()][$realm] = new SimpleRealm($type, $url);
171 * Sets the current identity to be presented
172 * against that realm.
173 * @param string $host Server hosting realm.
174 * @param string $realm Name of realm.
175 * @param string $username Username for realm.
176 * @param string $password Password for realm.
177 * @access public
179 function setIdentityForRealm($host, $realm, $username, $password) {
180 if (isset($this->_realms[$host][$realm])) {
181 $this->_realms[$host][$realm]->setIdentity($username, $password);
186 * Finds the name of the realm by comparing URLs.
187 * @param SimpleUrl $url URL to test.
188 * @return SimpleRealm Name of realm.
189 * @access private
191 function _findRealmFromUrl($url) {
192 if (! isset($this->_realms[$url->getHost()])) {
193 return false;
195 foreach ($this->_realms[$url->getHost()] as $name => $realm) {
196 if ($realm->isWithin($url)) {
197 return $realm;
200 return false;
204 * Presents the appropriate headers for this location.
205 * @param SimpleHttpRequest $request Request to modify.
206 * @param SimpleUrl $url Base of realm.
207 * @access public
209 function addHeaders(&$request, $url) {
210 if ($url->getUsername() && $url->getPassword()) {
211 $username = $url->getUsername();
212 $password = $url->getPassword();
213 } elseif ($realm = $this->_findRealmFromUrl($url)) {
214 $username = $realm->getUsername();
215 $password = $realm->getPassword();
216 } else {
217 return;
219 $this->addBasicHeaders($request, $username, $password);
223 * Presents the appropriate headers for this
224 * location for basic authentication.
225 * @param SimpleHttpRequest $request Request to modify.
226 * @param string $username Username for realm.
227 * @param string $password Password for realm.
228 * @access public
229 * @static
231 function addBasicHeaders(&$request, $username, $password) {
232 if ($username && $password) {
233 $request->addHeaderLine(
234 'Authorization: Basic ' . base64_encode("$username:$password"));