237 lines
		
	
	
		
			7.2 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
			
		
		
	
	
			237 lines
		
	
	
		
			7.2 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
<?php
 | 
						|
/**
 | 
						|
 *  Base include file for SimpleTest
 | 
						|
 *  @package    SimpleTest
 | 
						|
 *  @subpackage WebTester
 | 
						|
 *  @version    $Id: authentication.php 2011 2011-04-29 08:22:48Z pp11 $
 | 
						|
 */
 | 
						|
/**
 | 
						|
 *  include http class
 | 
						|
 */
 | 
						|
require_once(dirname(__FILE__) . '/http.php');
 | 
						|
 | 
						|
/**
 | 
						|
 *    Represents a single security realm's identity.
 | 
						|
 *    @package SimpleTest
 | 
						|
 *    @subpackage WebTester
 | 
						|
 */
 | 
						|
class SimpleRealm {
 | 
						|
    private $type;
 | 
						|
    private $root;
 | 
						|
    private $username;
 | 
						|
    private $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
 | 
						|
     */
 | 
						|
    protected 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
 | 
						|
     */
 | 
						|
    protected function isIn($part, $whole) {
 | 
						|
        return strpos($whole, $part) === 0;
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
 *    Manages security realms.
 | 
						|
 *    @package SimpleTest
 | 
						|
 *    @subpackage WebTester
 | 
						|
 */
 | 
						|
class SimpleAuthenticator {
 | 
						|
    private $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 privatey 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
 | 
						|
     */
 | 
						|
    protected 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 function addBasicHeaders(&$request, $username, $password) {
 | 
						|
        if ($username && $password) {
 | 
						|
            $request->addHeaderLine(
 | 
						|
                'Authorization: Basic ' . base64_encode("$username:$password"));
 | 
						|
        }
 | 
						|
    }
 | 
						|
}
 | 
						|
?>
 |