MDL-15476
[moodle-linuxchix.git] / lib / simpletestlib / cookies.php
blobb346a7962e8bb07d97d46b32f4e061f1538c61a6
1 <?php
2 /**
3 * Base include file for SimpleTest
4 * @package SimpleTest
5 * @subpackage WebTester
6 * @version $Id$
7 */
9 /**#@+
10 * include other SimpleTest class files
12 require_once(dirname(__FILE__) . '/url.php');
13 /**#@-*/
15 /**
16 * Cookie data holder. Cookie rules are full of pretty
17 * arbitary stuff. I have used...
18 * http://wp.netscape.com/newsref/std/cookie_spec.html
19 * http://www.cookiecentral.com/faq/
20 * @package SimpleTest
21 * @subpackage WebTester
23 class SimpleCookie {
24 var $_host;
25 var $_name;
26 var $_value;
27 var $_path;
28 var $_expiry;
29 var $_is_secure;
31 /**
32 * Constructor. Sets the stored values.
33 * @param string $name Cookie key.
34 * @param string $value Value of cookie.
35 * @param string $path Cookie path if not host wide.
36 * @param string $expiry Expiry date as string.
37 * @param boolean $is_secure Currently ignored.
39 function SimpleCookie($name, $value = false, $path = false, $expiry = false, $is_secure = false) {
40 $this->_host = false;
41 $this->_name = $name;
42 $this->_value = $value;
43 $this->_path = ($path ? $this->_fixPath($path) : "/");
44 $this->_expiry = false;
45 if (is_string($expiry)) {
46 $this->_expiry = strtotime($expiry);
47 } elseif (is_integer($expiry)) {
48 $this->_expiry = $expiry;
50 $this->_is_secure = $is_secure;
53 /**
54 * Sets the host. The cookie rules determine
55 * that the first two parts are taken for
56 * certain TLDs and three for others. If the
57 * new host does not match these rules then the
58 * call will fail.
59 * @param string $host New hostname.
60 * @return boolean True if hostname is valid.
61 * @access public
63 function setHost($host) {
64 if ($host = $this->_truncateHost($host)) {
65 $this->_host = $host;
66 return true;
68 return false;
71 /**
72 * Accessor for the truncated host to which this
73 * cookie applies.
74 * @return string Truncated hostname.
75 * @access public
77 function getHost() {
78 return $this->_host;
81 /**
82 * Test for a cookie being valid for a host name.
83 * @param string $host Host to test against.
84 * @return boolean True if the cookie would be valid
85 * here.
87 function isValidHost($host) {
88 return ($this->_truncateHost($host) === $this->getHost());
91 /**
92 * Extracts just the domain part that determines a
93 * cookie's host validity.
94 * @param string $host Host name to truncate.
95 * @return string Domain or false on a bad host.
96 * @access private
98 function _truncateHost($host) {
99 $tlds = SimpleUrl::getAllTopLevelDomains();
100 if (preg_match('/[a-z\-]+\.(' . $tlds . ')$/i', $host, $matches)) {
101 return $matches[0];
102 } elseif (preg_match('/[a-z\-]+\.[a-z\-]+\.[a-z\-]+$/i', $host, $matches)) {
103 return $matches[0];
105 return false;
109 * Accessor for name.
110 * @return string Cookie key.
111 * @access public
113 function getName() {
114 return $this->_name;
118 * Accessor for value. A deleted cookie will
119 * have an empty string for this.
120 * @return string Cookie value.
121 * @access public
123 function getValue() {
124 return $this->_value;
128 * Accessor for path.
129 * @return string Valid cookie path.
130 * @access public
132 function getPath() {
133 return $this->_path;
137 * Tests a path to see if the cookie applies
138 * there. The test path must be longer or
139 * equal to the cookie path.
140 * @param string $path Path to test against.
141 * @return boolean True if cookie valid here.
142 * @access public
144 function isValidPath($path) {
145 return (strncmp(
146 $this->_fixPath($path),
147 $this->getPath(),
148 strlen($this->getPath())) == 0);
152 * Accessor for expiry.
153 * @return string Expiry string.
154 * @access public
156 function getExpiry() {
157 if (! $this->_expiry) {
158 return false;
160 return gmdate("D, d M Y H:i:s", $this->_expiry) . " GMT";
164 * Test to see if cookie is expired against
165 * the cookie format time or timestamp.
166 * Will give true for a session cookie.
167 * @param integer/string $now Time to test against. Result
168 * will be false if this time
169 * is later than the cookie expiry.
170 * Can be either a timestamp integer
171 * or a cookie format date.
172 * @access public
174 function isExpired($now) {
175 if (! $this->_expiry) {
176 return true;
178 if (is_string($now)) {
179 $now = strtotime($now);
181 return ($this->_expiry < $now);
185 * Ages the cookie by the specified number of
186 * seconds.
187 * @param integer $interval In seconds.
188 * @public
190 function agePrematurely($interval) {
191 if ($this->_expiry) {
192 $this->_expiry -= $interval;
197 * Accessor for the secure flag.
198 * @return boolean True if cookie needs SSL.
199 * @access public
201 function isSecure() {
202 return $this->_is_secure;
206 * Adds a trailing and leading slash to the path
207 * if missing.
208 * @param string $path Path to fix.
209 * @access private
211 function _fixPath($path) {
212 if (substr($path, 0, 1) != '/') {
213 $path = '/' . $path;
215 if (substr($path, -1, 1) != '/') {
216 $path .= '/';
218 return $path;
223 * Repository for cookies. This stuff is a
224 * tiny bit browser dependent.
225 * @package SimpleTest
226 * @subpackage WebTester
228 class SimpleCookieJar {
229 var $_cookies;
232 * Constructor. Jar starts empty.
233 * @access public
235 function SimpleCookieJar() {
236 $this->_cookies = array();
240 * Removes expired and temporary cookies as if
241 * the browser was closed and re-opened.
242 * @param string/integer $now Time to test expiry against.
243 * @access public
245 function restartSession($date = false) {
246 $surviving_cookies = array();
247 for ($i = 0; $i < count($this->_cookies); $i++) {
248 if (! $this->_cookies[$i]->getValue()) {
249 continue;
251 if (! $this->_cookies[$i]->getExpiry()) {
252 continue;
254 if ($date && $this->_cookies[$i]->isExpired($date)) {
255 continue;
257 $surviving_cookies[] = $this->_cookies[$i];
259 $this->_cookies = $surviving_cookies;
263 * Ages all cookies in the cookie jar.
264 * @param integer $interval The old session is moved
265 * into the past by this number
266 * of seconds. Cookies now over
267 * age will be removed.
268 * @access public
270 function agePrematurely($interval) {
271 for ($i = 0; $i < count($this->_cookies); $i++) {
272 $this->_cookies[$i]->agePrematurely($interval);
277 * Sets an additional cookie. If a cookie has
278 * the same name and path it is replaced.
279 * @param string $name Cookie key.
280 * @param string $value Value of cookie.
281 * @param string $host Host upon which the cookie is valid.
282 * @param string $path Cookie path if not host wide.
283 * @param string $expiry Expiry date.
284 * @access public
286 function setCookie($name, $value, $host = false, $path = '/', $expiry = false) {
287 $cookie = new SimpleCookie($name, $value, $path, $expiry);
288 if ($host) {
289 $cookie->setHost($host);
291 $this->_cookies[$this->_findFirstMatch($cookie)] = $cookie;
295 * Finds a matching cookie to write over or the
296 * first empty slot if none.
297 * @param SimpleCookie $cookie Cookie to write into jar.
298 * @return integer Available slot.
299 * @access private
301 function _findFirstMatch($cookie) {
302 for ($i = 0; $i < count($this->_cookies); $i++) {
303 $is_match = $this->_isMatch(
304 $cookie,
305 $this->_cookies[$i]->getHost(),
306 $this->_cookies[$i]->getPath(),
307 $this->_cookies[$i]->getName());
308 if ($is_match) {
309 return $i;
312 return count($this->_cookies);
316 * Reads the most specific cookie value from the
317 * browser cookies. Looks for the longest path that
318 * matches.
319 * @param string $host Host to search.
320 * @param string $path Applicable path.
321 * @param string $name Name of cookie to read.
322 * @return string False if not present, else the
323 * value as a string.
324 * @access public
326 function getCookieValue($host, $path, $name) {
327 $longest_path = '';
328 foreach ($this->_cookies as $cookie) {
329 if ($this->_isMatch($cookie, $host, $path, $name)) {
330 if (strlen($cookie->getPath()) > strlen($longest_path)) {
331 $value = $cookie->getValue();
332 $longest_path = $cookie->getPath();
336 return (isset($value) ? $value : false);
340 * Tests cookie for matching against search
341 * criteria.
342 * @param SimpleTest $cookie Cookie to test.
343 * @param string $host Host must match.
344 * @param string $path Cookie path must be shorter than
345 * this path.
346 * @param string $name Name must match.
347 * @return boolean True if matched.
348 * @access private
350 function _isMatch($cookie, $host, $path, $name) {
351 if ($cookie->getName() != $name) {
352 return false;
354 if ($host && $cookie->getHost() && ! $cookie->isValidHost($host)) {
355 return false;
357 if (! $cookie->isValidPath($path)) {
358 return false;
360 return true;
364 * Uses a URL to sift relevant cookies by host and
365 * path. Results are list of strings of form "name=value".
366 * @param SimpleUrl $url Url to select by.
367 * @return array Valid name and value pairs.
368 * @access public
370 function selectAsPairs($url) {
371 $pairs = array();
372 foreach ($this->_cookies as $cookie) {
373 if ($this->_isMatch($cookie, $url->getHost(), $url->getPath(), $cookie->getName())) {
374 $pairs[] = $cookie->getName() . '=' . $cookie->getValue();
377 return $pairs;