[ Index ]

PHP Cross Reference of Limb3

title

Body

[close]

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

   1  <?php
   2      /**

   3       *    Base include file for SimpleTest

   4       *    @package    SimpleTest

   5       *    @subpackage    WebTester

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

   7       */
   8  
   9      /**#@+

  10       *    include other SimpleTest class files

  11       */
  12      require_once(dirname(__FILE__) . '/simpletest.php');
  13      require_once(dirname(__FILE__) . '/http.php');
  14      require_once(dirname(__FILE__) . '/encoding.php');
  15      require_once(dirname(__FILE__) . '/page.php');
  16      require_once(dirname(__FILE__) . '/selector.php');
  17      require_once(dirname(__FILE__) . '/frames.php');
  18      require_once(dirname(__FILE__) . '/user_agent.php');
  19      /**#@-*/

  20  
  21      if (!defined('DEFAULT_MAX_NESTED_FRAMES')) {
  22          define('DEFAULT_MAX_NESTED_FRAMES', 3);
  23      }
  24  
  25      /**

  26       *    Browser history list.

  27       *    @package SimpleTest

  28       *    @subpackage WebTester

  29       */
  30      class SimpleBrowserHistory {
  31          var $_sequence;
  32          var $_position;
  33  
  34          /**

  35           *    Starts empty.

  36           *    @access public

  37           */
  38          function SimpleBrowserHistory() {
  39              $this->_sequence = array();
  40              $this->_position = -1;
  41          }
  42  
  43          /**

  44           *    Test for no entries yet.

  45           *    @return boolean        True if empty.

  46           *    @access private

  47           */
  48          function _isEmpty() {
  49              return ($this->_position == -1);
  50          }
  51  
  52          /**

  53           *    Test for being at the beginning.

  54           *    @return boolean        True if first.

  55           *    @access private

  56           */
  57          function _atBeginning() {
  58              return ($this->_position == 0) && ! $this->_isEmpty();
  59          }
  60  
  61          /**

  62           *    Test for being at the last entry.

  63           *    @return boolean        True if last.

  64           *    @access private

  65           */
  66          function _atEnd() {
  67              return ($this->_position + 1 >= count($this->_sequence)) && ! $this->_isEmpty();
  68          }
  69  
  70          /**

  71           *    Adds a successfully fetched page to the history.

  72           *    @param SimpleUrl $url                 URL of fetch.

  73           *    @param SimpleEncoding $parameters     Any post data with the fetch.

  74           *    @access public

  75           */
  76          function recordEntry($url, $parameters) {
  77              $this->_dropFuture();
  78              array_push(
  79                      $this->_sequence,
  80                      array('url' => $url, 'parameters' => $parameters));
  81              $this->_position++;
  82          }
  83  
  84          /**

  85           *    Last fully qualified URL for current history

  86           *    position.

  87           *    @return SimpleUrl        URL for this position.

  88           *    @access public

  89           */
  90          function getUrl() {
  91              if ($this->_isEmpty()) {
  92                  return false;
  93              }
  94              return $this->_sequence[$this->_position]['url'];
  95          }
  96  
  97          /**

  98           *    Parameters of last fetch from current history

  99           *    position.

 100           *    @return SimpleFormEncoding    Post parameters.

 101           *    @access public

 102           */
 103          function getParameters() {
 104              if ($this->_isEmpty()) {
 105                  return false;
 106              }
 107              return $this->_sequence[$this->_position]['parameters'];
 108          }
 109  
 110          /**

 111           *    Step back one place in the history. Stops at

 112           *    the first page.

 113           *    @return boolean     True if any previous entries.

 114           *    @access public

 115           */
 116          function back() {
 117              if ($this->_isEmpty() || $this->_atBeginning()) {
 118                  return false;
 119              }
 120              $this->_position--;
 121              return true;
 122          }
 123  
 124          /**

 125           *    Step forward one place. If already at the

 126           *    latest entry then nothing will happen.

 127           *    @return boolean     True if any future entries.

 128           *    @access public

 129           */
 130          function forward() {
 131              if ($this->_isEmpty() || $this->_atEnd()) {
 132                  return false;
 133              }
 134              $this->_position++;
 135              return true;
 136          }
 137  
 138          /**

 139           *    Ditches all future entries beyond the current

 140           *    point.

 141           *    @access private

 142           */
 143          function _dropFuture() {
 144              if ($this->_isEmpty()) {
 145                  return;
 146              }
 147              while (! $this->_atEnd()) {
 148                  array_pop($this->_sequence);
 149              }
 150          }
 151      }
 152  
 153      /**

 154       *    Simulated web browser. This is an aggregate of

 155       *    the user agent, the HTML parsing, request history

 156       *    and the last header set.

 157       *    @package SimpleTest

 158       *    @subpackage WebTester

 159       */
 160      class SimpleBrowser {
 161          var $_user_agent;
 162          var $_page;
 163          var $_history;
 164          var $_ignore_frames;
 165          var $_maximum_nested_frames;
 166  
 167          /**

 168           *    Starts with a fresh browser with no

 169           *    cookie or any other state information. The

 170           *    exception is that a default proxy will be

 171           *    set up if specified in the options.

 172           *    @access public

 173           */
 174          function SimpleBrowser() {
 175              $this->_user_agent = &$this->_createUserAgent();
 176              $this->_user_agent->useProxy(
 177                      SimpleTest::getDefaultProxy(),
 178                      SimpleTest::getDefaultProxyUsername(),
 179                      SimpleTest::getDefaultProxyPassword());
 180              $this->_page = &new SimplePage();
 181              $this->_history = &$this->_createHistory();
 182              $this->_ignore_frames = false;
 183              $this->_maximum_nested_frames = DEFAULT_MAX_NESTED_FRAMES;
 184          }
 185  
 186          /**

 187           *    Creates the underlying user agent.

 188           *    @return SimpleFetcher    Content fetcher.

 189           *    @access protected

 190           */
 191          function &_createUserAgent() {
 192              $user_agent = &new SimpleUserAgent();
 193              return $user_agent;
 194          }
 195  
 196          /**

 197           *    Creates a new empty history list.

 198           *    @return SimpleBrowserHistory    New list.

 199           *    @access protected

 200           */
 201          function &_createHistory() {
 202              $history = &new SimpleBrowserHistory();
 203              return $history;
 204          }
 205  
 206          /**

 207           *    Disables frames support. Frames will not be fetched

 208           *    and the frameset page will be used instead.

 209           *    @access public

 210           */
 211          function ignoreFrames() {
 212              $this->_ignore_frames = true;
 213          }
 214  
 215          /**

 216           *    Enables frames support. Frames will be fetched from

 217           *    now on.

 218           *    @access public

 219           */
 220          function useFrames() {
 221              $this->_ignore_frames = false;
 222          }
 223          
 224          /**

 225           *    Switches off cookie sending and recieving.

 226           *    @access public

 227           */
 228          function ignoreCookies() {
 229              $this->_user_agent->ignoreCookies();
 230          }
 231          
 232          /**

 233           *    Switches back on the cookie sending and recieving.

 234           *    @access public

 235           */
 236          function useCookies() {
 237              $this->_user_agent->useCookies();
 238          }
 239  
 240          /**

 241           *    Parses the raw content into a page. Will load further

 242           *    frame pages unless frames are disabled.

 243           *    @param SimpleHttpResponse $response    Response from fetch.

 244           *    @param integer $depth                  Nested frameset depth.

 245           *    @return SimplePage                     Parsed HTML.

 246           *    @access private

 247           */
 248          function &_parse($response, $depth = 0) {
 249              $page = &$this->_buildPage($response);
 250              if ($this->_ignore_frames || ! $page->hasFrames() || ($depth > $this->_maximum_nested_frames)) {
 251                  return $page;
 252              }
 253              $frameset = &new SimpleFrameset($page);
 254              foreach ($page->getFrameset() as $key => $url) {
 255                  $frame = &$this->_fetch($url, new SimpleGetEncoding(), $depth + 1);
 256                  $frameset->addFrame($frame, $key);
 257              }
 258              return $frameset;
 259          }
 260          
 261          /**

 262           *    Assembles the parsing machinery and actually parses

 263           *    a single page. Frees all of the builder memory and so

 264           *    unjams the PHP memory management.

 265           *    @param SimpleHttpResponse $response    Response from fetch.

 266           *    @return SimplePage                     Parsed top level page.

 267           *    @access protected

 268           */
 269          function &_buildPage($response) {
 270              $builder = &new SimplePageBuilder();
 271              $page = &$builder->parse($response);
 272              $builder->free();
 273              unset($builder);
 274              return $page;
 275          }
 276  
 277          /**

 278           *    Fetches a page. Jointly recursive with the _parse()

 279           *    method as it descends a frameset.

 280           *    @param string/SimpleUrl $url          Target to fetch.

 281           *    @param SimpleEncoding $encoding       GET/POST parameters.

 282           *    @param integer $depth                 Nested frameset depth protection.

 283           *    @return SimplePage                    Parsed page.

 284           *    @access private

 285           */
 286          function &_fetch($url, $encoding, $depth = 0) {
 287              $response = &$this->_user_agent->fetchResponse($url, $encoding);
 288              if ($response->isError()) {
 289                  $page = &new SimplePage($response);
 290              } else {
 291                  $page = &$this->_parse($response, $depth);
 292              }
 293              return $page;
 294          }
 295  
 296          /**

 297           *    Fetches a page or a single frame if that is the current

 298           *    focus.

 299           *    @param SimpleUrl $url                   Target to fetch.

 300           *    @param SimpleEncoding $parameters       GET/POST parameters.

 301           *    @return string                          Raw content of page.

 302           *    @access private

 303           */
 304          function _load($url, $parameters) {
 305              $frame = $url->getTarget();
 306              if (! $frame || ! $this->_page->hasFrames() || (strtolower($frame) == '_top')) {
 307                  return $this->_loadPage($url, $parameters);
 308              }
 309              return $this->_loadFrame(array($frame), $url, $parameters);
 310          }
 311  
 312          /**

 313           *    Fetches a page and makes it the current page/frame.

 314           *    @param string/SimpleUrl $url            Target to fetch as string.

 315           *    @param SimplePostEncoding $parameters   POST parameters.

 316           *    @return string                          Raw content of page.

 317           *    @access private

 318           */
 319          function _loadPage($url, $parameters) {
 320              $this->_page = &$this->_fetch($url, $parameters);
 321              $this->_history->recordEntry(
 322                      $this->_page->getUrl(),
 323                      $this->_page->getRequestData());
 324              return $this->_page->getRaw();
 325          }
 326  
 327          /**

 328           *    Fetches a frame into the existing frameset replacing the

 329           *    original.

 330           *    @param array $frames                    List of names to drill down.

 331           *    @param string/SimpleUrl $url            Target to fetch as string.

 332           *    @param SimpleFormEncoding $parameters   POST parameters.

 333           *    @return string                          Raw content of page.

 334           *    @access private

 335           */
 336          function _loadFrame($frames, $url, $parameters) {
 337              $page = &$this->_fetch($url, $parameters);
 338              $this->_page->setFrame($frames, $page);
 339          }
 340  
 341          /**

 342           *    Removes expired and temporary cookies as if

 343           *    the browser was closed and re-opened.

 344           *    @param string/integer $date   Time when session restarted.

 345           *                                  If omitted then all persistent

 346           *                                  cookies are kept.

 347           *    @access public

 348           */
 349          function restart($date = false) {
 350              $this->_user_agent->restart($date);
 351          }
 352  
 353          /**

 354           *    Adds a header to every fetch.

 355           *    @param string $header       Header line to add to every

 356           *                                request until cleared.

 357           *    @access public

 358           */
 359          function addHeader($header) {
 360              $this->_user_agent->addHeader($header);
 361          }
 362  
 363          /**

 364           *    Ages the cookies by the specified time.

 365           *    @param integer $interval    Amount in seconds.

 366           *    @access public

 367           */
 368          function ageCookies($interval) {
 369              $this->_user_agent->ageCookies($interval);
 370          }
 371  
 372          /**

 373           *    Sets an additional cookie. If a cookie has

 374           *    the same name and path it is replaced.

 375           *    @param string $name       Cookie key.

 376           *    @param string $value      Value of cookie.

 377           *    @param string $host       Host upon which the cookie is valid.

 378           *    @param string $path       Cookie path if not host wide.

 379           *    @param string $expiry     Expiry date.

 380           *    @access public

 381           */
 382          function setCookie($name, $value, $host = false, $path = '/', $expiry = false) {
 383              $this->_user_agent->setCookie($name, $value, $host, $path, $expiry);
 384          }
 385  
 386          /**

 387           *    Reads the most specific cookie value from the

 388           *    browser cookies.

 389           *    @param string $host        Host to search.

 390           *    @param string $path        Applicable path.

 391           *    @param string $name        Name of cookie to read.

 392           *    @return string             False if not present, else the

 393           *                               value as a string.

 394           *    @access public

 395           */
 396          function getCookieValue($host, $path, $name) {
 397              return $this->_user_agent->getCookieValue($host, $path, $name);
 398          }
 399  
 400          /**

 401           *    Reads the current cookies for the current URL.

 402           *    @param string $name   Key of cookie to find.

 403           *    @return string        Null if there is no current URL, false

 404           *                          if the cookie is not set.

 405           *    @access public

 406           */
 407          function getCurrentCookieValue($name) {
 408              return $this->_user_agent->getBaseCookieValue($name, $this->_page->getUrl());
 409          }
 410  
 411          /**

 412           *    Sets the maximum number of redirects before

 413           *    a page will be loaded anyway.

 414           *    @param integer $max        Most hops allowed.

 415           *    @access public

 416           */
 417          function setMaximumRedirects($max) {
 418              $this->_user_agent->setMaximumRedirects($max);
 419          }
 420  
 421          /**

 422           *    Sets the maximum number of nesting of framed pages

 423           *    within a framed page to prevent loops.

 424           *    @param integer $max        Highest depth allowed.

 425           *    @access public

 426           */
 427          function setMaximumNestedFrames($max) {
 428              $this->_maximum_nested_frames = $max;
 429          }
 430  
 431          /**

 432           *    Sets the socket timeout for opening a connection.

 433           *    @param integer $timeout      Maximum time in seconds.

 434           *    @access public

 435           */
 436          function setConnectionTimeout($timeout) {
 437              $this->_user_agent->setConnectionTimeout($timeout);
 438          }
 439  
 440          /**

 441           *    Sets proxy to use on all requests for when

 442           *    testing from behind a firewall. Set URL

 443           *    to false to disable.

 444           *    @param string $proxy        Proxy URL.

 445           *    @param string $username     Proxy username for authentication.

 446           *    @param string $password     Proxy password for authentication.

 447           *    @access public

 448           */
 449          function useProxy($proxy, $username = false, $password = false) {
 450              $this->_user_agent->useProxy($proxy, $username, $password);
 451          }
 452  
 453          /**

 454           *    Fetches the page content with a HEAD request.

 455           *    Will affect cookies, but will not change the base URL.

 456           *    @param string/SimpleUrl $url                Target to fetch as string.

 457           *    @param hash/SimpleHeadEncoding $parameters  Additional parameters for

 458           *                                                HEAD request.

 459           *    @return boolean                             True if successful.

 460           *    @access public

 461           */
 462          function head($url, $parameters = false) {
 463              if (! is_object($url)) {
 464                  $url = new SimpleUrl($url);
 465              }
 466              if ($this->getUrl()) {
 467                  $url = $url->makeAbsolute($this->getUrl());
 468              }
 469              $response = &$this->_user_agent->fetchResponse($url, new SimpleHeadEncoding($parameters));
 470              return ! $response->isError();
 471          }
 472  
 473          /**

 474           *    Fetches the page content with a simple GET request.

 475           *    @param string/SimpleUrl $url                Target to fetch.

 476           *    @param hash/SimpleFormEncoding $parameters  Additional parameters for

 477           *                                                GET request.

 478           *    @return string                              Content of page or false.

 479           *    @access public

 480           */
 481          function get($url, $parameters = false) {
 482              if (! is_object($url)) {
 483                  $url = new SimpleUrl($url);
 484              }
 485              if ($this->getUrl()) {
 486                  $url = $url->makeAbsolute($this->getUrl());
 487              }
 488              return $this->_load($url, new SimpleGetEncoding($parameters));
 489          }
 490  
 491          /**

 492           *    Fetches the page content with a POST request.

 493           *    @param string/SimpleUrl $url                Target to fetch as string.

 494           *    @param hash/SimpleFormEncoding $parameters  POST parameters.

 495           *    @return string                              Content of page.

 496           *    @access public

 497           */
 498          function post($url, $parameters = false) {
 499              if (! is_object($url)) {
 500                  $url = new SimpleUrl($url);
 501              }
 502              if ($this->getUrl()) {
 503                  $url = $url->makeAbsolute($this->getUrl());
 504              }
 505              return $this->_load($url, new SimplePostEncoding($parameters));
 506          }
 507  
 508          /**

 509           *    Equivalent to hitting the retry button on the

 510           *    browser. Will attempt to repeat the page fetch. If

 511           *    there is no history to repeat it will give false.

 512           *    @return string/boolean   Content if fetch succeeded

 513           *                             else false.

 514           *    @access public

 515           */
 516          function retry() {
 517              $frames = $this->_page->getFrameFocus();
 518              if (count($frames) > 0) {
 519                  $this->_loadFrame(
 520                          $frames,
 521                          $this->_page->getUrl(),
 522                          $this->_page->getRequestData());
 523                  return $this->_page->getRaw();
 524              }
 525              if ($url = $this->_history->getUrl()) {
 526                  $this->_page = &$this->_fetch($url, $this->_history->getParameters());
 527                  return $this->_page->getRaw();
 528              }
 529              return false;
 530          }
 531  
 532          /**

 533           *    Equivalent to hitting the back button on the

 534           *    browser. The browser history is unchanged on

 535           *    failure. The page content is refetched as there

 536           *    is no concept of content caching in SimpleTest.

 537           *    @return boolean     True if history entry and

 538           *                        fetch succeeded

 539           *    @access public

 540           */
 541          function back() {
 542              if (! $this->_history->back()) {
 543                  return false;
 544              }
 545              $content = $this->retry();
 546              if (! $content) {
 547                  $this->_history->forward();
 548              }
 549              return $content;
 550          }
 551  
 552          /**

 553           *    Equivalent to hitting the forward button on the

 554           *    browser. The browser history is unchanged on

 555           *    failure. The page content is refetched as there

 556           *    is no concept of content caching in SimpleTest.

 557           *    @return boolean     True if history entry and

 558           *                        fetch succeeded