3 * Base include file for SimpleTest
5 * @subpackage WebTester
10 * include other SimpleTest class files
12 require_once(dirname(__FILE__
) . '/cookies.php');
13 require_once(dirname(__FILE__
) . '/http.php');
14 require_once(dirname(__FILE__
) . '/encoding.php');
15 require_once(dirname(__FILE__
) . '/authentication.php');
18 if (! defined('DEFAULT_MAX_REDIRECTS')) {
19 define('DEFAULT_MAX_REDIRECTS', 3);
22 if (! defined('DEFAULT_CONNECTION_TIMEOUT')) {
23 define('DEFAULT_CONNECTION_TIMEOUT', 15);
27 * Fetches web pages whilst keeping track of
28 * cookies and authentication.
30 * @subpackage WebTester
32 class SimpleUserAgent
{
34 var $_cookies_enabled = true;
36 var $_max_redirects = DEFAULT_MAX_REDIRECTS
;
38 var $_proxy_username = false;
39 var $_proxy_password = false;
40 var $_connection_timeout = DEFAULT_CONNECTION_TIMEOUT
;
41 var $_additional_headers = array();
44 * Starts with no cookies, realms or proxies.
47 function SimpleUserAgent() {
48 $this->_cookie_jar
= &new SimpleCookieJar();
49 $this->_authenticator
= &new SimpleAuthenticator();
53 * Removes expired and temporary cookies as if
54 * the browser was closed and re-opened. Authorisation
55 * has to be obtained again as well.
56 * @param string/integer $date Time when session restarted.
57 * If omitted then all persistent
61 function restart($date = false) {
62 $this->_cookie_jar
->restartSession($date);
63 $this->_authenticator
->restartSession();
67 * Adds a header to every fetch.
68 * @param string $header Header line to add to every
69 * request until cleared.
72 function addHeader($header) {
73 $this->_additional_headers
[] = $header;
77 * Ages the cookies by the specified time.
78 * @param integer $interval Amount in seconds.
81 function ageCookies($interval) {
82 $this->_cookie_jar
->agePrematurely($interval);
86 * Sets an additional cookie. If a cookie has
87 * the same name and path it is replaced.
88 * @param string $name Cookie key.
89 * @param string $value Value of cookie.
90 * @param string $host Host upon which the cookie is valid.
91 * @param string $path Cookie path if not host wide.
92 * @param string $expiry Expiry date.
95 function setCookie($name, $value, $host = false, $path = '/', $expiry = false) {
96 $this->_cookie_jar
->setCookie($name, $value, $host, $path, $expiry);
100 * Reads the most specific cookie value from the
102 * @param string $host Host to search.
103 * @param string $path Applicable path.
104 * @param string $name Name of cookie to read.
105 * @return string False if not present, else the
109 function getCookieValue($host, $path, $name) {
110 return $this->_cookie_jar
->getCookieValue($host, $path, $name);
114 * Reads the current cookies within the base URL.
115 * @param string $name Key of cookie to find.
116 * @param SimpleUrl $base Base URL to search from.
117 * @return string/boolean Null if there is no base URL, false
118 * if the cookie is not set.
121 function getBaseCookieValue($name, $base) {
125 return $this->getCookieValue($base->getHost(), $base->getPath(), $name);
129 * Switches off cookie sending and recieving.
132 function ignoreCookies() {
133 $this->_cookies_enabled
= false;
137 * Switches back on the cookie sending and recieving.
140 function useCookies() {
141 $this->_cookies_enabled
= true;
145 * Sets the socket timeout for opening a connection.
146 * @param integer $timeout Maximum time in seconds.
149 function setConnectionTimeout($timeout) {
150 $this->_connection_timeout
= $timeout;
154 * Sets the maximum number of redirects before
155 * a page will be loaded anyway.
156 * @param integer $max Most hops allowed.
159 function setMaximumRedirects($max) {
160 $this->_max_redirects
= $max;
164 * Sets proxy to use on all requests for when
165 * testing from behind a firewall. Set URL
166 * to false to disable.
167 * @param string $proxy Proxy URL.
168 * @param string $username Proxy username for authentication.
169 * @param string $password Proxy password for authentication.
172 function useProxy($proxy, $username, $password) {
174 $this->_proxy
= false;
177 if ((strncmp($proxy, 'http://', 7) != 0) && (strncmp($proxy, 'https://', 8) != 0)) {
178 $proxy = 'http://'. $proxy;
180 $this->_proxy
= &new SimpleUrl($proxy);
181 $this->_proxy_username
= $username;
182 $this->_proxy_password
= $password;
186 * Test to see if the redirect limit is passed.
187 * @param integer $redirects Count so far.
188 * @return boolean True if over.
191 function _isTooManyRedirects($redirects) {
192 return ($redirects > $this->_max_redirects
);
196 * Sets the identity for the current realm.
197 * @param string $host Host to which realm applies.
198 * @param string $realm Full name of realm.
199 * @param string $username Username for realm.
200 * @param string $password Password for realm.
203 function setIdentity($host, $realm, $username, $password) {
204 $this->_authenticator
->setIdentityForRealm($host, $realm, $username, $password);
208 * Fetches a URL as a response object. Will keep trying if redirected.
209 * It will also collect authentication realm information.
210 * @param string/SimpleUrl $url Target to fetch.
211 * @param SimpleEncoding $encoding Additional parameters for request.
212 * @return SimpleHttpResponse Hopefully the target page.
215 function &fetchResponse($url, $encoding) {
216 if ($encoding->getMethod() != 'POST') {
217 $url->addRequestParameters($encoding);
220 $response = &$this->_fetchWhileRedirected($url, $encoding);
221 if ($headers = $response->getHeaders()) {
222 if ($headers->isChallenge()) {
223 $this->_authenticator
->addRealm(
225 $headers->getAuthentication(),
226 $headers->getRealm());
233 * Fetches the page until no longer redirected or
234 * until the redirect limit runs out.
235 * @param SimpleUrl $url Target to fetch.
236 * @param SimpelFormEncoding $encoding Additional parameters for request.
237 * @return SimpleHttpResponse Hopefully the target page.
240 function &_fetchWhileRedirected($url, $encoding) {
243 $response = &$this->_fetch($url, $encoding);
244 if ($response->isError()) {
247 $headers = $response->getHeaders();
248 $location = new SimpleUrl($headers->getLocation());
249 $url = $location->makeAbsolute($url);
250 if ($this->_cookies_enabled
) {
251 $headers->writeCookiesToJar($this->_cookie_jar
, $url);
253 if (! $headers->isRedirect()) {
256 $encoding = new SimpleGetEncoding();
257 } while (! $this->_isTooManyRedirects(++
$redirects));
262 * Actually make the web request.
263 * @param SimpleUrl $url Target to fetch.
264 * @param SimpleFormEncoding $encoding Additional parameters for request.
265 * @return SimpleHttpResponse Headers and hopefully content.
268 function &_fetch($url, $encoding) {
269 $request = &$this->_createRequest($url, $encoding);
270 $response = &$request->fetch($this->_connection_timeout
);
275 * Creates a full page request.
276 * @param SimpleUrl $url Target to fetch as url object.
277 * @param SimpleFormEncoding $encoding POST/GET parameters.
278 * @return SimpleHttpRequest New request.
281 function &_createRequest($url, $encoding) {
282 $request = &$this->_createHttpRequest($url, $encoding);
283 $this->_addAdditionalHeaders($request);
284 if ($this->_cookies_enabled
) {
285 $request->readCookiesFromJar($this->_cookie_jar
, $url);
287 $this->_authenticator
->addHeaders($request, $url);
292 * Builds the appropriate HTTP request object.
293 * @param SimpleUrl $url Target to fetch as url object.
294 * @param SimpleFormEncoding $parameters POST/GET parameters.
295 * @return SimpleHttpRequest New request object.
298 function &_createHttpRequest($url, $encoding) {
299 $request = &new SimpleHttpRequest($this->_createRoute($url), $encoding);
304 * Sets up either a direct route or via a proxy.
305 * @param SimpleUrl $url Target to fetch as url object.
306 * @return SimpleRoute Route to take to fetch URL.
309 function &_createRoute($url) {
311 $route = &new SimpleProxyRoute(
314 $this->_proxy_username
,
315 $this->_proxy_password
);
317 $route = &new SimpleRoute($url);
323 * Adds additional manual headers.
324 * @param SimpleHttpRequest $request Outgoing request.
327 function _addAdditionalHeaders(&$request) {
328 foreach ($this->_additional_headers
as $header) {
329 $request->addHeaderLine($header);