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"));
 | |
|         }
 | |
|     }
 | |
| }
 | |
| ?>
 |