[ Index ]

PHP Cross Reference of Limb3

title

Body

[close]

/tests_runner/lib/simpletest/ -> http.php (source)

   1  <?php
   2      /**

   3       *    base include file for SimpleTest

   4       *    @package    SimpleTest

   5       *    @subpackage    WebTester

   6       *    @version    $Id: http.php 5999 2007-06-18 13:13:08Z pachanga $

   7       */
   8  
   9      /**#@+

  10       *    include other SimpleTest class files

  11       */
  12      require_once(dirname(__FILE__) . '/socket.php');
  13      require_once(dirname(__FILE__) . '/cookies.php');
  14      require_once(dirname(__FILE__) . '/url.php');
  15      /**#@-*/

  16      
  17      /**

  18       *    Creates HTTP headers for the end point of

  19       *    a HTTP request.

  20       *    @package SimpleTest

  21       *    @subpackage WebTester

  22       */
  23      class SimpleRoute {
  24          var $_url;
  25          
  26          /**

  27           *    Sets the target URL.

  28           *    @param SimpleUrl $url   URL as object.

  29           *    @access public

  30           */
  31          function SimpleRoute($url) {
  32              $this->_url = $url;
  33          }
  34          
  35          /**

  36           *    Resource name.

  37           *    @return SimpleUrl        Current url.

  38           *    @access protected

  39           */
  40          function getUrl() {
  41              return $this->_url;
  42          }
  43          
  44          /**

  45           *    Creates the first line which is the actual request.

  46           *    @param string $method   HTTP request method, usually GET.

  47           *    @return string          Request line content.

  48           *    @access protected

  49           */
  50          function _getRequestLine($method) {
  51              return $method . ' ' . $this->_url->getPath() .
  52                      $this->_url->getEncodedRequest() . ' HTTP/1.0';
  53          }
  54          
  55          /**

  56           *    Creates the host part of the request.

  57           *    @return string          Host line content.

  58           *    @access protected

  59           */
  60          function _getHostLine() {
  61              $line = 'Host: ' . $this->_url->getHost();
  62              if ($this->_url->getPort()) {
  63                  $line .= ':' . $this->_url->getPort();
  64              }
  65              return $line;
  66          }
  67          
  68          /**

  69           *    Opens a socket to the route.

  70           *    @param string $method      HTTP request method, usually GET.

  71           *    @param integer $timeout    Connection timeout.

  72           *    @return SimpleSocket       New socket.

  73           *    @access public

  74           */
  75          function &createConnection($method, $timeout) {
  76              $default_port = ('https' == $this->_url->getScheme()) ? 443 : 80;
  77              $socket = &$this->_createSocket(
  78                      $this->_url->getScheme() ? $this->_url->getScheme() : 'http',
  79                      $this->_url->getHost(),
  80                      $this->_url->getPort() ? $this->_url->getPort() : $default_port,
  81                      $timeout);
  82              if (! $socket->isError()) {
  83                  $socket->write($this->_getRequestLine($method) . "\r\n");
  84                  $socket->write($this->_getHostLine() . "\r\n");
  85                  $socket->write("Connection: close\r\n");
  86              }
  87              return $socket;
  88          }
  89          
  90          /**

  91           *    Factory for socket.

  92           *    @param string $scheme                   Protocol to use.

  93           *    @param string $host                     Hostname to connect to.

  94           *    @param integer $port                    Remote port.

  95           *    @param integer $timeout                 Connection timeout.

  96           *    @return SimpleSocket/SimpleSecureSocket New socket.

  97           *    @access protected

  98           */
  99          function &_createSocket($scheme, $host, $port, $timeout) {
 100              if (in_array($scheme, array('https'))) {
 101                  $socket = &new SimpleSecureSocket($host, $port, $timeout);
 102              } else {
 103                  $socket = &new SimpleSocket($host, $port, $timeout);
 104              }
 105              return $socket;
 106          }
 107      }
 108      
 109      /**

 110       *    Creates HTTP headers for the end point of

 111       *    a HTTP request via a proxy server.

 112       *    @package SimpleTest

 113       *    @subpackage WebTester

 114       */
 115      class SimpleProxyRoute extends SimpleRoute {
 116          var $_proxy;
 117          var $_username;
 118          var $_password;
 119          
 120          /**

 121           *    Stashes the proxy address.

 122           *    @param SimpleUrl $url     URL as object.

 123           *    @param string $proxy      Proxy URL.

 124           *    @param string $username   Username for autentication.

 125           *    @param string $password   Password for autentication.

 126           *    @access public

 127           */
 128          function SimpleProxyRoute($url, $proxy, $username = false, $password = false) {
 129              $this->SimpleRoute($url);
 130              $this->_proxy = $proxy;
 131              $this->_username = $username;
 132              $this->_password = $password;
 133          }
 134          
 135          /**

 136           *    Creates the first line which is the actual request.

 137           *    @param string $method   HTTP request method, usually GET.

 138           *    @param SimpleUrl $url   URL as object.

 139           *    @return string          Request line content.

 140           *    @access protected

 141           */
 142          function _getRequestLine($method) {
 143              $url = $this->getUrl();
 144              $scheme = $url->getScheme() ? $url->getScheme() : 'http';
 145              $port = $url->getPort() ? ':' . $url->getPort() : '';
 146              return $method . ' ' . $scheme . '://' . $url->getHost() . $port .
 147                      $url->getPath() . $url->getEncodedRequest() . ' HTTP/1.0';
 148          }
 149          
 150          /**

 151           *    Creates the host part of the request.

 152           *    @param SimpleUrl $url   URL as object.

 153           *    @return string          Host line content.

 154           *    @access protected

 155           */
 156          function _getHostLine() {
 157              $host = 'Host: ' . $this->_proxy->getHost();
 158              $port = $this->_proxy->getPort() ? $this->_proxy->getPort() : 8080;
 159              return "$host:$port";
 160          }
 161          
 162          /**

 163           *    Opens a socket to the route.

 164           *    @param string $method       HTTP request method, usually GET.

 165           *    @param integer $timeout     Connection timeout.

 166           *    @return SimpleSocket        New socket.

 167           *    @access public

 168           */
 169          function &createConnection($method, $timeout) {
 170              $socket = &$this->_createSocket(
 171                      $this->_proxy->getScheme() ? $this->_proxy->getScheme() : 'http',
 172                      $this->_proxy->getHost(),
 173                      $this->_proxy->getPort() ? $this->_proxy->getPort() : 8080,
 174                      $timeout);
 175              if ($socket->isError()) {
 176                  return $socket;
 177              }
 178              $socket->write($this->_getRequestLine($method) . "\r\n");
 179              $socket->write($this->_getHostLine() . "\r\n");
 180              if ($this->_username && $this->_password) {
 181                  $socket->write('Proxy-Authorization: Basic ' .
 182                          base64_encode($this->_username . ':' . $this->_password) .
 183                          "\r\n");
 184              }
 185              $socket->write("Connection: close\r\n");
 186              return $socket;
 187          }
 188      }
 189  
 190      /**

 191       *    HTTP request for a web page. Factory for

 192       *    HttpResponse object.

 193       *    @package SimpleTest

 194       *    @subpackage WebTester

 195       */
 196      class SimpleHttpRequest {
 197          var $_route;
 198          var $_encoding;
 199          var $_headers;
 200          var $_cookies;
 201          
 202          /**

 203           *    Builds the socket request from the different pieces.

 204           *    These include proxy information, URL, cookies, headers,

 205           *    request method and choice of encoding.

 206           *    @param SimpleRoute $route              Request route.

 207           *    @param SimpleFormEncoding $encoding    Content to send with

 208           *                                           request.

 209           *    @access public

 210           */
 211          function SimpleHttpRequest(&$route, $encoding) {
 212              $this->_route = &$route;
 213              $this->_encoding = $encoding;
 214              $this->_headers = array();
 215              $this->_cookies = array();
 216          }
 217          
 218          /**

 219           *    Dispatches the content to the route's socket.

 220           *    @param integer $timeout      Connection timeout.

 221           *    @return SimpleHttpResponse   A response which may only have

 222           *                                 an error, but hopefully has a

 223           *                                 complete web page.

 224           *    @access public

 225           */
 226          function &fetch($timeout) {
 227              $socket = &$this->_route->createConnection($this->_encoding->getMethod(), $timeout);
 228              if (! $socket->isError()) {
 229                  $this->_dispatchRequest($socket, $this->_encoding);
 230              }
 231              $response = &$this->_createResponse($socket);
 232              return $response;
 233          }
 234          
 235          /**

 236           *    Sends the headers.

 237           *    @param SimpleSocket $socket           Open socket.

 238           *    @param string $method                 HTTP request method,

 239           *                                          usually GET.

 240           *    @param SimpleFormEncoding $encoding   Content to send with request.

 241           *    @access private

 242           */
 243          function _dispatchRequest(&$socket, $encoding) {
 244              foreach ($this->_headers as $header_line) {
 245                  $socket->write($header_line . "\r\n");
 246              }
 247              if (count($this->_cookies) > 0) {
 248                  $socket->write("Cookie: " . implode(";", $this->_cookies) . "\r\n");
 249              }
 250              $encoding->writeHeadersTo($socket);
 251              $socket->write("\r\n");
 252              $encoding->writeTo($socket);
 253          }
 254          
 255          /**

 256           *    Adds a header line to the request.

 257           *    @param string $header_line    Text of full header line.

 258           *    @access public

 259           */
 260          function addHeaderLine($header_line) {
 261              $this->_headers[] = $header_line;
 262          }
 263          
 264          /**

 265           *    Reads all the relevant cookies from the

 266           *    cookie jar.

 267           *    @param SimpleCookieJar $jar     Jar to read

 268           *    @param SimpleUrl $url           Url to use for scope.

 269           *    @access public

 270           */
 271          function readCookiesFromJar($jar, $url) {
 272              $this->_cookies = $jar->selectAsPairs($url);
 273          }
 274          
 275          /**

 276           *    Wraps the socket in a response parser.

 277           *    @param SimpleSocket $socket   Responding socket.

 278           *    @return SimpleHttpResponse    Parsed response object.

 279           *    @access protected

 280           */
 281          function &_createResponse(&$socket) {
 282              $response = &new SimpleHttpResponse(
 283                      $socket,
 284                      $this->_route->getUrl(),
 285                      $this->_encoding);
 286              return $response;
 287          }
 288      }
 289      
 290      /**

 291       *    Collection of header lines in the response.

 292       *    @package SimpleTest

 293       *    @subpackage WebTester

 294       */
 295      class SimpleHttpHeaders {
 296          var $_raw_headers;
 297          var $_response_code;
 298          var $_http_version;
 299          var $_mime_type;
 300          var $_location;
 301          var $_cookies;
 302          var $_authentication;
 303          var $_realm;
 304          
 305          /**

 306           *    Parses the incoming header block.

 307           *    @param string $headers     Header block.

 308           *    @access public

 309           */
 310          function SimpleHttpHeaders($headers) {
 311              $this->_raw_headers = $headers;
 312              $this->_response_code = false;
 313              $this->_http_version = false;
 314              $this->_mime_type = '';
 315              $this->_location = false;
 316              $this->_cookies = array();
 317              $this->_authentication = false;
 318              $this->_realm = false;
 319              foreach (split("\r\n", $headers) as $header_line) {
 320                  $this->_parseHeaderLine($header_line);
 321              }
 322          }
 323          
 324          /**

 325           *    Accessor for parsed HTTP protocol version.

 326           *    @return integer           HTTP error code.

 327           *    @access public

 328           */
 329          function getHttpVersion() {
 330              return $this->_http_version;
 331          }
 332          
 333          /**

 334           *    Accessor for raw header block.

 335           *    @return string        All headers as raw string.

 336           *    @access public

 337           */
 338          function getRaw() {
 339              return $this->_raw_headers;
 340          }
 341          
 342          /**

 343           *    Accessor for parsed HTTP error code.

 344           *    @return integer           HTTP error code.

 345           *    @access public

 346           */
 347          function getResponseCode() {
 348              return (integer)$this->_response_code;
 349          }
 350          
 351          /**

 352           *    Returns the redirected URL or false if

 353           *    no redirection.

 354           *    @return string      URL or false for none.

 355           *    @access public

 356           */
 357          function getLocation() {
 358              return $this->_location;
 359          }
 360          
 361          /**

 362           *    Test to see if the response is a valid redirect.

 363           *    @return boolean       True if valid redirect.

 364           *    @access public

 365           */
 366          function isRedirect() {
 367              return in_array($this->_response_code, array(301, 302, 303, 307)) &&
 368                      (boolean)$this->getLocation();
 369          }
 370          
 371          /**

 372           *    Test to see if the response is an authentication

 373           *    challenge.

 374           *    @return boolean       True if challenge.

 375           *    @access public

 376           */
 377          function isChallenge() {
 378              return ($this->_response_code == 401) &&
 379                      (boolean)$this->_authentication &&
 380                      (boolean)$this->_realm;
 381          }
 382          
 383          /**

 384           *    Accessor for MIME type header information.

 385           *    @return string           MIME type.

 386           *    @access public

 387           */
 388          function getMimeType() {
 389              return $this->_mime_type;
 390          }
 391          
 392          /**

 393           *    Accessor for authentication type.

 394           *    @return string        Type.

 395           *    @access public

 396           */
 397          function getAuthentication() {
 398              return $this->_authentication;
 399          }
 400          
 401          /**

 402           *    Accessor for security realm.

 403           *    @return string        Realm.

 404           *    @access public

 405           */
 406          function getRealm() {
 407              return $this->_realm;
 408          }
 409          
 410          /**

 411           *    Writes new cookies to the cookie jar.

 412           *    @param SimpleCookieJar $jar   Jar to write to.

 413           *    @param SimpleUrl $url         Host and path to write under.

 414           *    @access public

 415           */
 416          function writeCookiesToJar(&$jar, $url) {
 417              foreach ($this->_cookies as $cookie) {
 418                  $jar->setCookie(
 419                          $cookie->getName(),
 420                          $cookie->getValue(),
 421                          $url->getHost(),
 422                          $cookie->getPath(),
 423                          $cookie->getExpiry());
 424              }
 425          }
 426  
 427          /**

 428           *    Called on each header line to accumulate the held

 429           *    data within the class.

 430           *    @param string $header_line        One line of header.

 431           *    @access protected

 432           */
 433          function _parseHeaderLine($header_line) {
 434              if (preg_match('/HTTP\/(\d+\.\d+)\s+(\d+)/i', $header_line, $matches)) {
 435                  $this->_http_version = $matches[1];
 436                  $this->_response_code = $matches[2];
 437              }
 438              if (preg_match('/Content-type:\s*(.*)/i', $header_line, $matches)) {
 439                  $this->_mime_type = trim($matches[1]);
 440              }
 441              if (preg_match('/Location:\s*(.*)/i', $header_line, $matches)) {
 442                  $this->_location = trim($matches[1]);
 443              }
 444              if (preg_match('/Set-cookie:(.*)/i', $header_line, $matches)) {
 445                  $this->_cookies[] = $this->_parseCookie($matches[1]);
 446              }
 447              if (preg_match('/WWW-Authenticate:\s+(\S+)\s+realm=\"(.*?)\"/i', $header_line, $matches)) {
 448                  $this->_authentication = $matches[1];
 449                  $this->_realm = trim($matches[2]);
 450              }
 451          }
 452          
 453          /**

 454           *    Parse the Set-cookie content.

 455           *    @param string $cookie_line    Text after "Set-cookie:"

 456           *    @return SimpleCookie          New cookie object.

 457           *    @access private

 458           */
 459          function _parseCookie($cookie_line) {
 460              $parts = split(";", $cookie_line);
 461              $cookie = array();
 462              preg_match('/\s*(.*?)\s*=(.*)/', array_shift($parts), $cookie);
 463              foreach ($parts as $part) {
 464                  if (preg_match('/\s*(.*?)\s*=(.*)/', $part, $matches)) {
 465                      $cookie[$matches[1]] = trim($matches[2]);
 466                  }
 467              }
 468              return new SimpleCookie(
 469                      $cookie[1],
 470                      trim($cookie[2]),
 471                      isset($cookie["path"]) ? $cookie["path"] : "",
 472                      isset($cookie["expires"]) ? $cookie["expires"] : false);
 473          }
 474      }
 475      
 476      /**

 477       *    Basic HTTP response.

 478       *    @package SimpleTest

 479       *    @subpackage WebTester

 480       */
 481      class SimpleHttpResponse extends SimpleStickyError {
 482          var $_url;
 483          var $_encoding;
 484          var $_sent;
 485          var $_content;
 486          var $_headers;
 487          
 488          /**

 489           *    Constructor. Reads and parses the incoming

 490           *    content and headers.

 491           *    @param SimpleSocket $socket   Network connection to fetch

 492           *                                  response text from.

 493           *    @param SimpleUrl $url         Resource name.

 494           *    @param mixed $encoding        Record of content sent.

 495           *    @access public

 496           */
 497          function SimpleHttpResponse(&$socket, $url, $encoding) {
 498              $this->SimpleStickyError();
 499              $this->_url = $url;
 500              $this->_encoding = $encoding;
 501              $this->_sent = $socket->getSent();
 502              $this->_content = false;
 503              $raw = $this->_readAll($socket);
 504              if ($socket->isError()) {
 505                  $this->_setError('Error reading socket [' . $socket->getError() . ']');
 506                  return;
 507              }
 508              $this->_parse($raw);
 509          }
 510          
 511          /**

 512           *    Splits up the headers and the rest of the content.

 513           *    @param string $raw    Content to parse.

 514           *    @access private

 515           */
 516          function _parse(