Subversion-Projekte lars-tiefland.prado

Revision

Details | Letzte Änderung | Log anzeigen | RSS feed

Revision Autor Zeilennr. Zeile
1 lars 1
<?php
2
/**
3
 * THttpRequest, THttpCookie, THttpCookieCollection, TUri class file
4
 *
5
 * @author Qiang Xue <qiang.xue@gmail.com>
6
 * @link http://www.pradosoft.com/
7
 * @copyright Copyright &copy; 2005-2008 PradoSoft
8
 * @license http://www.pradosoft.com/license/
9
 * @version $Id: THttpRequest.php 2541 2008-10-21 15:05:13Z qiang.xue $
10
 * @package System.Web
11
 */
12
 
13
Prado::using('System.Web.TUrlManager');
14
 
15
/**
16
 * THttpRequest class
17
 *
18
 * THttpRequest provides storage and access scheme for user request sent via HTTP.
19
 * It also encapsulates a uniform way to parse and construct URLs.
20
 *
21
 * User post data can be retrieved from THttpRequest by using it like an associative array.
22
 * For example, to test if a user supplies a variable named 'param1', you can use,
23
 * <code>
24
 *   if(isset($request['param1'])) ...
25
 *   // equivalent to:
26
 *   // if($request->contains('param1')) ...
27
 * </code>
28
 * To get the value of 'param1', use,
29
 * <code>
30
 *   $value=$request['param1'];
31
 *   // equivalent to:
32
 *   //   $value=$request->itemAt('param1');
33
 * </code>
34
 * To traverse the user post data, use
35
 * <code>
36
 *   foreach($request as $name=>$value) ...
37
 * </code>
38
 * Note, POST and GET variables are merged together in THttpRequest.
39
 * If a variable name appears in both POST and GET data, then POST data
40
 * takes precedence.
41
 *
42
 * To construct a URL that can be recognized by Prado, use {@link constructUrl()}.
43
 * The format of the recognizable URLs is determined according to
44
 * {@link setUrlManager UrlManager}. By default, the following two formats
45
 * are recognized:
46
 * <code>
47
 * /index.php?ServiceID=ServiceParameter&Name1=Value1&Name2=Value2
48
 * /index.php/ServiceID,ServiceParameter/Name1,Value1/Name2,Value2
49
 * </code>
50
 * The first format is called 'Get' while the second 'Path', which is specified
51
 * via {@link setUrlFormat UrlFormat}. For advanced users who want to use
52
 * their own URL formats, they can write customized URL management modules
53
 * and install the managers as application modules and set {@link setUrlManager UrlManager}.
54
 *
55
 * The ServiceID in the above URLs is as defined in the application configuration
56
 * (e.g. the default page service's service ID is 'page').
57
 * As a consequence, your GET variable names should not conflict with the service
58
 * IDs that your application supports.
59
 *
60
 * THttpRequest also provides the cookies sent by the user, user information such
61
 * as his browser capabilities, accepted languages, etc.
62
 *
63
 * By default, THttpRequest is registered with {@link TApplication} as the
64
 * request module. It can be accessed via {@link TApplication::getRequest()}.
65
 *
66
 * @author Qiang Xue <qiang.xue@gmail.com>
67
 * @version $Id: THttpRequest.php 2541 2008-10-21 15:05:13Z qiang.xue $
68
 * @package System.Web
69
 * @since 3.0
70
 */
71
class THttpRequest extends TApplicationComponent implements IteratorAggregate,ArrayAccess,Countable,IModule
72
{
73
	/**
74
	 * @var TUrlManager the URL manager module
75
	 */
76
	private $_urlManager=null;
77
	/**
78
	 * @var string the ID of the URL manager module
79
	 */
80
	private $_urlManagerID='';
81
	/**
82
	 * @var string Separator used to separate GET variable name and value when URL format is Path.
83
	 */
84
	private $_separator=',';
85
	/**
86
	 * @var string requested service ID
87
	 */
88
	private $_serviceID=null;
89
	/**
90
	 * @var string requested service parameter
91
	 */
92
	private $_serviceParam=null;
93
	/**
94
	 * @var THttpCookieCollection cookies sent from user
95
	 */
96
	private $_cookies=null;
97
	/**
98
	 * @var string requested URI (URL w/o host info)
99
	 */
100
	private $_requestUri;
101
	/**
102
	 * @var string path info of URL
103
	 */
104
	private $_pathInfo;
105
	/**
106
	 * @var boolean whether the session ID should be kept in cookie only
107
	 */
108
	private $_cookieOnly=false;
109
	private $_urlFormat=THttpRequestUrlFormat::Get;
110
	private $_services;
111
	private $_requestResolved=false;
112
	private $_enableCookieValidation=false;
113
	/**
114
	 * @var string request URL
115
	 */
116
	private $_url=null;
117
 
118
	/**
119
	 * @var string module id
120
	 */
121
	private $_id;
122
 
123
	/**
124
	 * @var array contains all request variables
125
	 */
126
	private $_items=array();
127
 
128
	/**
129
	 * @return string id of this module
130
	 */
131
	public function getID()
132
	{
133
		return $this->_id;
134
	}
135
 
136
	/**
137
	 * @param string id of this module
138
	 */
139
	public function setID($value)
140
	{
141
		$this->_id=$value;
142
	}
143
 
144
	/**
145
	 * Initializes the module.
146
	 * This method is required by IModule and is invoked by application.
147
	 * @param TXmlElement module configuration
148
	 */
149
	public function init($config)
150
	{
151
		if(empty($this->_urlManagerID))
152
		{
153
			$this->_urlManager=new TUrlManager;
154
			$this->_urlManager->init(null);
155
		}
156
		else
157
		{
158
			$this->_urlManager=$this->getApplication()->getModule($this->_urlManagerID);
159
			if($this->_urlManager===null)
160
				throw new TConfigurationException('httprequest_urlmanager_inexist',$this->_urlManagerID);
161
			if(!($this->_urlManager instanceof TUrlManager))
162
				throw new TConfigurationException('httprequest_urlmanager_invalid',$this->_urlManagerID);
163
		}
164
 
165
		// Fill in default request info when the script is run in command line
166
		if(php_sapi_name()==='cli')
167
		{
168
			$_SERVER['REMOTE_ADDR']='127.0.0.1';
169
			$_SERVER['REQUEST_METHOD']='GET';
170
			$_SERVER['SERVER_NAME']='localhost';
171
			$_SERVER['SERVER_PORT']=80;
172
			$_SERVER['HTTP_USER_AGENT']='';
173
		}
174
 
175
		$this->_cookieOnly=(int)ini_get('session.use_cookies') && (int)ini_get('session.use_only_cookies');
176
 
177
		// Info about server variables:
178
		// PHP_SELF contains real URI (w/ path info, w/o query string)
179
		// SCRIPT_NAME is the real URI for the requested script (w/o path info and query string)
180
		// QUERY_STRING is the string following the '?' in the ur (eg the a=x part in http://foo/bar?a=x)
181
		// REQUEST_URI contains the URI part entered in the browser address bar
182
		// SCRIPT_FILENAME is the file path to the executing script
183
		if(isset($_SERVER['REQUEST_URI']))
184
			$this->_requestUri=$_SERVER['REQUEST_URI'];
185
		else  // TBD: in this case, SCRIPT_NAME need to be escaped
186
			$this->_requestUri=$_SERVER['SCRIPT_NAME'].(empty($_SERVER['QUERY_STRING'])?'':'?'.$_SERVER['QUERY_STRING']);
187
 
188
		if(isset($_SERVER['PATH_INFO']))
189
			$this->_pathInfo=$_SERVER['PATH_INFO'];
190
		else if(strpos($_SERVER['PHP_SELF'],$_SERVER['SCRIPT_NAME'])===0 && $_SERVER['PHP_SELF']!==$_SERVER['SCRIPT_NAME'])
191
			$this->_pathInfo=substr($_SERVER['PHP_SELF'],strlen($_SERVER['SCRIPT_NAME']));
192
		else
193
			$this->_pathInfo='';
194
 
195
		if(get_magic_quotes_gpc())
196
		{
197
			if(isset($_GET))
198
				$_GET=$this->stripSlashes($_GET);
199
			if(isset($_POST))
200
				$_POST=$this->stripSlashes($_POST);
201
			if(isset($_REQUEST))
202
				$_REQUEST=$this->stripSlashes($_REQUEST);
203
			if(isset($_COOKIE))
204
				$_COOKIE=$this->stripSlashes($_COOKIE);
205
		}
206
 
207
		$this->getApplication()->setRequest($this);
208
	}
209
 
210
	/**
211
	 * Strips slashes from input data.
212
	 * This method is applied when magic quotes is enabled.
213
	 * @param mixed input data to be processed
214
	 * @return mixed processed data
215
	 */
216
	public function stripSlashes(&$data)
217
	{
218
		return is_array($data)?array_map(array($this,'stripSlashes'),$data):stripslashes($data);
219
	}
220
 
221
	/**
222
	 * @return TUri the request URL
223
	 */
224
	public function getUrl()
225
	{
226
		if($this->_url===null)
227
		{
228
			$secure=$this->getIsSecureConnection();
229
			$url=$secure?'https://':'http://';
230
			if(empty($_SERVER['HTTP_HOST']))
231
			{
232
				$url.=$_SERVER['SERVER_NAME'];
233
				$port=$_SERVER['SERVER_PORT'];
234
				if(($port!=80 && !$secure) || ($port!=443 && $secure))
235
					$url.=':'.$port;
236
			}
237
			else
238
				$url.=$_SERVER['HTTP_HOST'];
239
			$url.=$this->getRequestUri();
240
			$this->_url=new TUri($url);
241
		}
242
		return $this->_url;
243
	}
244
 
245
	/**
246
	 * @return string the ID of the URL manager module
247
	 */
248
	public function getUrlManager()
249
	{
250
		return $this->_urlManagerID;
251
	}
252
 
253
	/**
254
	 * Sets the URL manager module.
255
	 * By default, {@link TUrlManager} is used for managing URLs.
256
	 * You may specify a different module for URL managing tasks
257
	 * by loading it as an application module and setting this property
258
	 * with the module ID.
259
	 * @param string the ID of the URL manager module
260
	 */
261
	public function setUrlManager($value)
262
	{
263
		$this->_urlManagerID=$value;
264
	}
265
 
266
	/**
267
	 * @return TUrlManager the URL manager module
268
	 */
269
	public function getUrlManagerModule()
270
	{
271
		return $this->_urlManager;
272
	}
273
 
274
	/**
275
	 * @return THttpRequestUrlFormat the format of URLs. Defaults to THttpRequestUrlFormat::Get.
276
	 */
277
	public function getUrlFormat()
278
	{
279
		return $this->_urlFormat;
280
	}
281
 
282
	/**
283
	 * Sets the format of URLs constructed and interpretted by the request module.
284
	 * A Get URL format is like index.php?name1=value1&name2=value2
285
	 * while a Path URL format is like index.php/name1,value1/name2,value.
286
	 * Changing the UrlFormat will affect {@link constructUrl} and how GET variables
287
	 * are parsed.
288
	 * @param THttpRequestUrlFormat the format of URLs.
289
	 */
290
	public function setUrlFormat($value)
291
	{
292
		$this->_urlFormat=TPropertyValue::ensureEnum($value,'THttpRequestUrlFormat');
293
	}
294
 
295
	/**
296
	 * @return string separator used to separate GET variable name and value when URL format is Path. Defaults to comma ','.
297
	 */
298
	public function getUrlParamSeparator()
299
	{
300
		return $this->_separator;
301
	}
302
 
303
	/**
304
	 * @param string separator used to separate GET variable name and value when URL format is Path.
305
	 * @throws TInvalidDataValueException if the separator is not a single character
306
	 */
307
	public function setUrlParamSeparator($value)
308
	{
309
		if(strlen($value)===1)
310
			$this->_separator=$value;
311
		else
312
			throw new TInvalidDataValueException('httprequest_separator_invalid');
313
	}
314
 
315
	/**
316
	 * @return string request type, can be GET, POST, HEAD, or PUT
317
	 */
318
	public function getRequestType()
319
	{
320
		return $_SERVER['REQUEST_METHOD'];
321
	}
322
 
323
	/**
324
	 * @return boolean if the request is sent via secure channel (https)
325
	 */
326
	public function getIsSecureConnection()
327
	{
328
	    return isset($_SERVER['HTTPS']) && strcasecmp($_SERVER['HTTPS'],'off');
329
	}
330
 
331
	/**
332
	 * @return string part of the request URL after script name and before question mark.
333
	 */
334
	public function getPathInfo()
335
	{
336
		return $this->_pathInfo;
337
	}
338
 
339
	/**
340
	 * @return string part of that request URL after the question mark
341
	 */
342
	public function getQueryString()
343
	{
344
		return isset($_SERVER['QUERY_STRING'])?$_SERVER['QUERY_STRING']:'';
345
	}
346
 
347
	/**
348
	 * @return string the requested http procolol. Blank string if not defined.
349
	 */
350
	public function getHttpProtocolVersion ()
351
	{
352
		return isset($_SERVER['SERVER_PROTOCOL'])?$_SERVER['SERVER_PROTOCOL']:'';
353
	}
354
 
355
	/**
356
	 * @return string part of that request URL after the host info (including pathinfo and query string)
357
	 */
358
	public function getRequestUri()
359
	{
360
		return $this->_requestUri;
361
	}
362
 
363
	/**
364
	 * @param boolean whether to use HTTPS instead of HTTP even if the current request is sent via HTTP
365
	 * @return string schema and hostname of the requested URL
366
	 */
367
	public function getBaseUrl($forceSecureConnection=false)
368
	{
369
		$url=$this->getUrl();
370
		$scheme=($forceSecureConnection)?"https":$url->getScheme();
371
		$host=$url->getHost();
372
		if (($port=$url->getPort())) $host.=':'.$port;
373
		return $scheme.'://'.$host;
374
	}
375
 
376
	/**
377
	 * @return string entry script URL (w/o host part)
378
	 */
379
	public function getApplicationUrl()
380
	{
381
		return $_SERVER['SCRIPT_NAME'];
382
	}
383
 
384
	/**
385
	 * @param boolean whether to use HTTPS instead of HTTP even if the current request is sent via HTTP
386
	 * @return string entry script URL (w/ host part)
387
	 */
388
	public function getAbsoluteApplicationUrl($forceSecureConnection=false)
389
	{
390
		return $this->getBaseUrl($forceSecureConnection) . $this->getApplicationUrl();
391
	}
392
 
393
	/**
394
	 * @return string application entry script file path (processed w/ realpath())
395
	 */
396
	public function getApplicationFilePath()
397
	{
398
		return realpath($_SERVER['SCRIPT_FILENAME']);
399
	}
400
 
401
	/**
402
	 * @return string server name
403
	 */
404
	public function getServerName()
405
	{
406
		return $_SERVER['SERVER_NAME'];
407
	}
408
 
409
	/**
410
	 * @return integer server port number
411
	 */
412
	public function getServerPort()
413
	{
414
		return $_SERVER['SERVER_PORT'];
415
	}
416
 
417
	/**
418
	 * @return string URL referrer, null if not present
419
	 */
420
	public function getUrlReferrer()
421
	{
422
		return isset($_SERVER['HTTP_REFERER'])?$_SERVER['HTTP_REFERER']:null;
423
	}
424
 
425
	/**
426
	 * @return array user browser capabilities
427
	 * @see get_browser
428
	 */
429
	public function getBrowser()
430
	{
431
	    try
432
	    {
433
		    return get_browser();
434
	    }
435
	    catch(TPhpErrorException $e)
436
	    {
437
	        throw new TConfigurationException('httprequest_browscap_required');
438
	    }
439
	}
440
 
441
	/**
442
	 * @return string user agent
443
	 */
444
	public function getUserAgent()
445
	{
446
		return $_SERVER['HTTP_USER_AGENT'];
447
	}
448
 
449
	/**
450
	 * @return string user IP address
451
	 */
452
	public function getUserHostAddress()
453
	{
454
		return $_SERVER['REMOTE_ADDR'];
455
	}
456
 
457
	/**
458
	 * @return string user host name, null if cannot be determined
459
	 */
460
	public function getUserHost()
461
	{
462
		return isset($_SERVER['REMOTE_HOST'])?$_SERVER['REMOTE_HOST']:null;
463
	}
464
 
465
	/**
466
	 * @return string user browser accept types
467
	 */
468
	public function getAcceptTypes()
469
	{
470
		// TBD: break it into array??
471
		return $_SERVER['HTTP_ACCEPT'];
472
	}
473
 
474
	/**
475
	 * Returns a list of user preferred languages.
476
	 * The languages are returned as an array. Each array element
477
	 * represents a single language preference. The languages are ordered
478
	 * according to user preferences. The first language is the most preferred.
479
	 * @return array list of user preferred languages.
480
	 */
481
	public function getUserLanguages()
482
	{
483
		return Prado::getUserLanguages();
484
	}
485
 
486
	/**
487
	 * @return boolean whether cookies should be validated. Defaults to false.
488
	 */
489
	public function getEnableCookieValidation()
490
	{
491
		return $this->_enableCookieValidation;
492
	}
493
 
494
	/**
495
	 * @param boolean whether cookies should be validated.
496
	 */
497
	public function setEnableCookieValidation($value)
498
	{
499
		$this->_enableCookieValidation=TPropertyValue::ensureBoolean($value);
500
	}
501
 
502
	/**
503
	 * @return THttpCookieCollection list of cookies to be sent
504
	 */
505
	public function getCookies()
506
	{
507
		if($this->_cookies===null)
508
		{
509
			$this->_cookies=new THttpCookieCollection;
510
			if($this->getEnableCookieValidation())
511
			{
512
				$sm=$this->getApplication()->getSecurityManager();
513
				foreach($_COOKIE as $key=>$value)
514
				{
515
					if(($value=$sm->validateData($value))!==false)
516
						$this->_cookies->add(new THttpCookie($key,$value));
517
				}
518
			}
519
			else
520
			{
521
				foreach($_COOKIE as $key=>$value)
522
					$this->_cookies->add(new THttpCookie($key,$value));
523
			}
524
		}
525
		return $this->_cookies;
526
	}
527
 
528
	/**
529
	 * @return array list of uploaded files.
530
	 */
531
	public function getUploadedFiles()
532
	{
533
		return $_FILES;
534
	}
535
 
536
	/**
537
	 * @return array list of server variables.
538
	 */
539
	public function getServerVariables()
540
	{
541
		return $_SERVER;
542
	}
543
 
544
	/**
545
	 * @return array list of environment variables.
546
	 */
547
	public function getEnvironmentVariables()
548
	{
549
		return $_ENV;
550
	}
551
 
552
	/**
553
	 * Constructs a URL that can be recognized by PRADO.
554
	 * The actual construction work is done by the URL manager module.
555
	 * This method may append session information to the generated URL if needed.
556
	 * You may provide your own URL manager module by setting {@link setUrlManager UrlManager}
557
	 * to provide your own URL scheme.
558
	 *
559
	 * Note, the constructed URL does not contain the protocol and hostname part.
560
	 * You may obtain an absolute URL by prepending the constructed URL with {@link getBaseUrl BaseUrl}.
561
	 * @param string service ID
562
	 * @param string service parameter
563
	 * @param array GET parameters, null if not needed
564
	 * @param boolean whether to encode the ampersand in URL, defaults to true.
565
	 * @param boolean whether to encode the GET parameters (their names and values), defaults to false.
566
	 * @return string URL
567
	 * @see TUrlManager::constructUrl
568
	 */
569
	public function constructUrl($serviceID,$serviceParam,$getItems=null,$encodeAmpersand=true,$encodeGetItems=true)
570
	{
571
		$url=$this->_urlManager->constructUrl($serviceID,$serviceParam,$getItems,$encodeAmpersand,$encodeGetItems);
572
		if(defined('SID') && SID != '' && !$this->_cookieOnly)
573
			return $url . (strpos($url,'?')===false? '?' : ($encodeAmpersand?'&amp;':'&')) . SID;
574
		else
575
			return $url;
576
	}
577
 
578
	/**
579
	 * Parses the request URL and returns an array of input parameters (excluding GET variables).
580
	 * You may override this method to support customized URL format.
581
	 * @return array list of input parameters, indexed by parameter names
582
	 * @see TUrlManager::parseUrl
583
	 */
584
	protected function parseUrl()
585
	{
586
		return $this->_urlManager->parseUrl();
587
	}
588
 
589
	/**
590
	 * Resolves the requested service.
591
	 * This method implements a URL-based service resolution.
592
	 * A URL in the format of /index.php?sp=serviceID.serviceParameter
593
	 * will be resolved with the serviceID and the serviceParameter.
594
	 * You may override this method to provide your own way of service resolution.
595
	 * @param array list of valid service IDs
596
	 * @return string the currently requested service ID, null if no service ID is found
597
	 * @see constructUrl
598
	 */
599
	public function resolveRequest($serviceIDs)
600
	{
601
		Prado::trace("Resolving request from ".$_SERVER['REMOTE_ADDR'],'System.Web.THttpRequest');
602
		$getParams=$this->parseUrl();
603
		foreach($getParams as $name=>$value)
604
			$_GET[$name]=$value;
605
		$this->_items=array_merge($_GET,$_POST);
606
		$this->_requestResolved=true;
607
		foreach($serviceIDs as $serviceID)
608
		{
609
			if($this->contains($serviceID))
610
			{
611
				$this->setServiceID($serviceID);
612
				$this->setServiceParameter($this->itemAt($serviceID));
613
				return $serviceID;
614
			}
615
		}
616
		return null;
617
	}
618
 
619
	/**
620
	 * @return boolean true if request is already resolved, false otherwise.
621
	 */
622
	public function getRequestResolved()
623
	{
624
		return $this->_requestResolved;
625
	}
626
 
627
	/**
628
	 * @return string requested service ID
629
	 */
630
	public function getServiceID()
631
	{
632
		return $this->_serviceID;
633
	}
634
 
635
	/**
636
	 * Sets the requested service ID.
637
	 * @param string requested service ID
638
	 */
639
	public function setServiceID($value)
640
	{
641
		$this->_serviceID=$value;
642
	}
643
 
644
	/**
645
	 * @return string requested service parameter
646
	 */
647
	public function getServiceParameter()
648
	{
649
		return $this->_serviceParam;
650
	}
651
 
652
	/**
653
	 * Sets the requested service parameter.
654
	 * @param string requested service parameter
655
	 */
656
	public function setServiceParameter($value)
657
	{
658
		$this->_serviceParam=$value;
659
	}
660
 
661
	//------ The following methods enable THttpRequest to be TMap-like -----
662
 
663
	/**
664
	 * Returns an iterator for traversing the items in the list.
665
	 * This method is required by the interface IteratorAggregate.
666
	 * @return Iterator an iterator for traversing the items in the list.
667
	 */
668
	public function getIterator()
669
	{
670
		return new TMapIterator($this->_items);
671
	}
672
 
673
	/**
674
	 * @return integer the number of items in the request
675
	 */
676
	public function getCount()
677
	{
678
		return count($this->_items);
679
	}
680
 
681
	/**
682
	 * Returns the number of items in the request.
683
	 * This method is required by Countable interface.
684
	 * @return integer number of items in the request.
685
	 */
686
	public function count()
687
	{
688
		return $this->getCount();
689
	}
690
 
691
	/**
692
	 * @return array the key list
693
	 */
694
	public function getKeys()
695
	{
696
		return array_keys($this->_items);
697
	}
698
 
699
	/**
700
	 * Returns the item with the specified key.
701
	 * This method is exactly the same as {@link offsetGet}.
702
	 * @param mixed the key
703
	 * @return mixed the element at the offset, null if no element is found at the offset
704
	 */
705
	public function itemAt($key)
706
	{
707
		return isset($this->_items[$key]) ? $this->_items[$key] : null;
708
	}
709
 
710
	/**
711
	 * Adds an item into the request.
712
	 * Note, if the specified key already exists, the old value will be overwritten.
713
	 * @param mixed key
714
	 * @param mixed value
715
	 */
716
	public function add($key,$value)
717
	{
718
		$this->_items[$key]=$value;
719
	}
720
 
721
	/**
722
	 * Removes an item from the request by its key.
723
	 * @param mixed the key of the item to be removed
724
	 * @return mixed the removed value, null if no such key exists.
725
	 * @throws TInvalidOperationException if the item cannot be removed
726
	 */
727
	public function remove($key)
728
	{
729
		if(isset($this->_items[$key]) || array_key_exists($key,$this->_items))
730
		{
731
			$value=$this->_items[$key];
732
			unset($this->_items[$key]);
733
			return $value;
734
		}
735
		else
736
			return null;
737
	}
738
 
739
	/**
740
	 * Removes all items in the request.
741
	 */
742
	public function clear()
743
	{
744
		foreach(array_keys($this->_items) as $key)
745
			$this->remove($key);
746
	}
747
 
748
	/**
749
	 * @param mixed the key
750
	 * @return boolean whether the request contains an item with the specified key
751
	 */
752
	public function contains($key)
753
	{
754
		return isset($this->_items[$key]) || array_key_exists($key,$this->_items);
755
	}
756
 
757
	/**
758
	 * @return array the list of items in array
759
	 */
760
	public function toArray()
761
	{
762
		return $this->_items;
763
	}
764
 
765
	/**
766
	 * Returns whether there is an element at the specified offset.
767
	 * This method is required by the interface ArrayAccess.
768
	 * @param mixed the offset to check on
769
	 * @return boolean
770
	 */
771
	public function offsetExists($offset)
772
	{
773
		return $this->contains($offset);
774
	}
775
 
776
	/**
777
	 * Returns the element at the specified offset.
778
	 * This method is required by the interface ArrayAccess.
779
	 * @param integer the offset to retrieve element.
780
	 * @return mixed the element at the offset, null if no element is found at the offset
781
	 */
782
	public function offsetGet($offset)
783
	{
784
		return $this->itemAt($offset);
785
	}
786
 
787
	/**
788
	 * Sets the element at the specified offset.
789
	 * This method is required by the interface ArrayAccess.
790
	 * @param integer the offset to set element
791
	 * @param mixed the element value
792
	 */
793
	public function offsetSet($offset,$item)
794
	{
795
		$this->add($offset,$item);
796
	}
797
 
798
	/**
799
	 * Unsets the element at the specified offset.
800
	 * This method is required by the interface ArrayAccess.
801
	 * @param mixed the offset to unset element
802
	 */
803
	public function offsetUnset($offset)
804
	{
805
		$this->remove($offset);
806
	}
807
}
808
 
809
/**
810
 * THttpCookieCollection class.
811
 *
812
 * THttpCookieCollection implements a collection class to store cookies.
813
 * Besides using all functionalities from {@link TList}, you can also
814
 * retrieve a cookie by its name using either {@link findCookieByName} or
815
 * simply:
816
 * <code>
817
 *   $cookie=$collection[$cookieName];
818
 * </code>
819
 *
820
 * @author Qiang Xue <qiang.xue@gmail.com>
821
 * @version $Id: THttpRequest.php 2541 2008-10-21 15:05:13Z qiang.xue $
822
 * @package System.Web
823
 * @since 3.0
824
 */
825
class THttpCookieCollection extends TList
826
{
827
	/**
828
	 * @var mixed owner of this collection
829
	 */
830
	private $_o;
831
 
832
	/**
833
	 * Constructor.
834
	 * @param mixed owner of this collection.
835
	 */
836
	public function __construct($owner=null)
837
	{
838
		$this->_o=$owner;
839
	}
840
 
841
	/**
842
	 * Inserts an item at the specified position.
843
	 * This overrides the parent implementation by performing additional
844
	 * operations for each newly added THttpCookie object.
845
	 * @param integer the specified position.
846
	 * @param mixed new item
847
	 * @throws TInvalidDataTypeException if the item to be inserted is not a THttpCookie object.
848
	 */
849
	public function insertAt($index,$item)
850
	{
851
		if($item instanceof THttpCookie)
852
		{
853
			parent::insertAt($index,$item);
854
			if($this->_o instanceof THttpResponse)
855
				$this->_o->addCookie($item);
856
		}
857
		else
858
			throw new TInvalidDataTypeException('httpcookiecollection_httpcookie_required');
859
	}
860
 
861
	/**
862
	 * Removes an item at the specified position.
863
	 * This overrides the parent implementation by performing additional
864
	 * cleanup work when removing a TCookie object.
865
	 * @param integer the index of the item to be removed.
866
	 * @return mixed the removed item.
867
	 */
868
	public function removeAt($index)
869
	{
870
		$item=parent::removeAt($index);
871
		if($this->_o instanceof THttpResponse)
872
			$this->_o->removeCookie($item);
873
		return $item;
874
	}
875
 
876
	/**
877
	 * @param integer|string index of the cookie in the collection or the cookie's name
878
	 * @return THttpCookie the cookie found
879
	 */
880
	public function itemAt($index)
881
	{
882
		if(is_integer($index))
883
			return parent::itemAt($index);
884
		else
885
			return $this->findCookieByName($index);
886
	}
887
 
888
	/**
889
	 * Finds the cookie with the specified name.
890
	 * @param string the name of the cookie to be looked for
891
	 * @return THttpCookie the cookie, null if not found
892
	 */
893
	public function findCookieByName($name)
894
	{
895
		foreach($this as $cookie)
896
			if($cookie->getName()===$name)
897
				return $cookie;
898
		return null;
899
	}
900
}
901
 
902
/**
903
 * THttpCookie class.
904
 *
905
 * A THttpCookie instance stores a single cookie, including the cookie name, value,
906
 * domain, path, expire, and secure.
907
 *
908
 * @author Qiang Xue <qiang.xue@gmail.com>
909
 * @version $Id: THttpRequest.php 2541 2008-10-21 15:05:13Z qiang.xue $
910
 * @package System.Web
911
 * @since 3.0
912
 */
913
class THttpCookie extends TComponent
914
{
915
	/**
916
	 * @var string domain of the cookie
917
	 */
918
	private $_domain='';
919
	/**
920
	 * @var string name of the cookie
921
	 */
922
	private $_name;
923
	/**
924
	 * @var string value of the cookie
925
	 */
926
	private $_value='';
927
	/**
928
	 * @var integer expire of the cookie
929
	 */
930
	private $_expire=0;
931
	/**
932
	 * @var string path of the cookie
933
	 */
934
	private $_path='/';
935
	/**
936
	 * @var boolean whether cookie should be sent via secure connection
937
	 */
938
	private $_secure=false;
939
 
940
	/**
941
	 * Constructor.
942
	 * @param string name of this cookie
943
	 * @param string value of this cookie
944
	 */
945
	public function __construct($name,$value)
946
	{
947
		$this->_name=$name;
948
		$this->_value=$value;
949
	}
950
 
951
	/**
952
	 * @return string the domain to associate the cookie with
953
	 */
954
	public function getDomain()
955
	{
956
		return $this->_domain;
957
	}
958
 
959
	/**
960
	 * @param string the domain to associate the cookie with
961
	 */
962
	public function setDomain($value)
963
	{
964
		$this->_domain=$value;
965
	}
966
 
967
	/**
968
	 * @return integer the time the cookie expires. This is a Unix timestamp so is in number of seconds since the epoch.
969
	 */
970
	public function getExpire()
971
	{
972
		return $this->_expire;
973
	}
974
 
975
	/**
976
	 * @param integer the time the cookie expires. This is a Unix timestamp so is in number of seconds since the epoch.
977
	 */
978
	public function setExpire($value)
979
	{
980
		$this->_expire=TPropertyValue::ensureInteger($value);
981
	}
982
 
983
	/**
984
	 * @return string the name of the cookie
985
	 */
986
	public function getName()
987
	{
988
		return $this->_name;
989
	}
990
 
991
	/**
992
	 * @param string the name of the cookie
993
	 */
994
	public function setName($value)
995
	{
996
		$this->_name=$value;
997
	}
998
 
999
	/**
1000
	 * @return string the value of the cookie
1001
	 */
1002
	public function getValue()
1003
	{
1004
		return $this->_value;
1005
	}
1006
 
1007
	/**
1008
	 * @param string the value of the cookie
1009
	 */
1010
	public function setValue($value)
1011
	{
1012
		$this->_value=$value;
1013
	}
1014
 
1015
	/**
1016
	 * @return string the path on the server in which the cookie will be available on, default is '/'
1017
	 */
1018
	public function getPath()
1019
	{
1020
		return $this->_path;
1021
	}
1022
 
1023
	/**
1024
	 * @param string the path on the server in which the cookie will be available on
1025
	 */
1026
	public function setPath($value)
1027
	{
1028
		$this->_path=$value;
1029
	}
1030
 
1031
	/**
1032
	 * @return boolean whether the cookie should only be transmitted over a secure HTTPS connection
1033
	 */
1034
	public function getSecure()
1035
	{
1036
		return $this->_secure;
1037
	}
1038
 
1039
	/**
1040
	 * @param boolean ether the cookie should only be transmitted over a secure HTTPS connection
1041
	 */
1042
	public function setSecure($value)
1043
	{
1044
		$this->_secure=TPropertyValue::ensureBoolean($value);
1045
	}
1046
}
1047
 
1048
/**
1049
 * TUri class
1050
 *
1051
 * TUri represents a URI. Given a URI
1052
 * http://joe:whatever@example.com:8080/path/to/script.php?param=value#anchor
1053
 * it will be decomposed as follows,
1054
 * - scheme: http
1055
 * - host: example.com
1056
 * - port: 8080
1057
 * - user: joe
1058
 * - password: whatever
1059
 * - path: /path/to/script.php
1060
 * - query: param=value
1061
 * - fragment: anchor
1062
 *
1063
 * @author Qiang Xue <qiang.xue@gmail.com>
1064
 * @version $Id: THttpRequest.php 2541 2008-10-21 15:05:13Z qiang.xue $
1065
 * @package System.Web
1066
 * @since 3.0
1067
 */
1068
class TUri extends TComponent
1069
{
1070
	/**
1071
	 * @var array list of default ports for known schemes
1072
	 */
1073
	private static $_defaultPort=array(
1074
		'ftp'=>21,
1075
		'gopher'=>70,
1076
		'http'=>80,
1077
		'https'=>443,
1078
		'news'=>119,
1079
		'nntp'=>119,
1080
		'wais'=>210,
1081
		'telnet'=>23
1082
	);
1083
	/**
1084
	 * @var string scheme of the URI
1085
	 */
1086
	private $_scheme;
1087
	/**
1088
	 * @var string host name of the URI
1089
	 */
1090
	private $_host;
1091
	/**
1092
	 * @var integer port of the URI
1093
	 */
1094
	private $_port;
1095
	/**
1096
	 * @var string user of the URI
1097
	 */
1098
	private $_user;
1099
	/**
1100
	 * @var string password of the URI
1101
	 */
1102
	private $_pass;
1103
	/**
1104
	 * @var string path of the URI
1105
	 */
1106
	private $_path;
1107
	/**
1108
	 * @var string query string of the URI
1109
	 */
1110
	private $_query;
1111
	/**
1112
	 * @var string fragment of the URI
1113
	 */
1114
	private $_fragment;
1115
	/**
1116
	 * @var string the URI
1117
	 */
1118
	private $_uri;
1119
 
1120
	/**
1121
	 * Constructor.
1122
	 * Decomposes the specified URI into parts.
1123
	 * @param string URI to be represented
1124
	 * @throws TInvalidDataValueException if URI is of bad format
1125
	 */
1126
	public function __construct($uri)
1127
	{
1128
		if(($ret=@parse_url($uri))!==false)
1129
		{
1130
			// decoding???
1131
			$this->_scheme=isset($ret['scheme'])?$ret['scheme']:'';
1132
			$this->_host=isset($ret['host'])?$ret['host']:'';
1133
			$this->_port=isset($ret['port'])?$ret['port']:'';
1134
			$this->_user=isset($ret['user'])?$ret['user']:'';
1135
			$this->_pass=isset($ret['pass'])?$ret['pass']:'';
1136
			$this->_path=isset($ret['path'])?$ret['path']:'';
1137
			$this->_query=isset($ret['query'])?$ret['query']:'';
1138
			$this->_fragment=isset($ret['fragment'])?$ret['fragment']:'';
1139
			$this->_uri=$uri;
1140
		}
1141
		else
1142
		{
1143
			throw new TInvalidDataValueException('uri_format_invalid',$uri);
1144
		}
1145
	}
1146
 
1147
	/**
1148
	 * @return string URI
1149
	 */
1150
	public function getUri()
1151
	{
1152
		return $this->_uri;
1153
	}
1154
 
1155
	/**
1156
	 * @return string scheme of the URI, such as 'http', 'https', 'ftp', etc.
1157
	 */
1158
	public function getScheme()
1159
	{
1160
		return $this->_scheme;
1161
	}
1162
 
1163
	/**
1164
	 * @return string hostname of the URI
1165
	 */
1166
	public function getHost()
1167
	{
1168
		return $this->_host;
1169
	}
1170
 
1171
	/**
1172
	 * @return integer port number of the URI
1173
	 */
1174
	public function getPort()
1175
	{
1176
		return $this->_port;
1177
	}
1178
 
1179
	/**
1180
	 * @return string username of the URI
1181
	 */
1182
	public function getUser()
1183
	{
1184
		return $this->_user;
1185
	}
1186
 
1187
	/**
1188
	 * @return string password of the URI
1189
	 */
1190
	public function getPassword()
1191
	{
1192
		return $this->_pass;
1193
	}
1194
 
1195
	/**
1196
	 * @return string path of the URI
1197
	 */
1198
	public function getPath()
1199
	{
1200
		return $this->_path;
1201
	}
1202
 
1203
	/**
1204
	 * @return string query string of the URI
1205
	 */
1206
	public function getQuery()
1207
	{
1208
		return $this->_query;
1209
	}
1210
 
1211
	/**
1212
	 * @return string fragment of the URI
1213
	 */
1214
	public function getFragment()
1215
	{
1216
		return $this->_fragment;
1217
	}
1218
}
1219
 
1220
/**
1221
 * THttpRequestUrlFormat class.
1222
 * THttpRequestUrlFormat defines the enumerable type for the possible URL formats
1223
 * that can be recognized by {@link THttpRequest}.
1224
 *
1225
 * The following enumerable values are defined:
1226
 * - Get: the URL format is like /path/to/index.php?name1=value1&name2=value2...
1227
 * - Path: the URL format is like /path/to/index.php/name1,value1/name2,value2...
1228
 *
1229
 * @author Qiang Xue <qiang.xue@gmail.com>
1230
 * @version $Id: THttpRequest.php 2541 2008-10-21 15:05:13Z qiang.xue $
1231
 * @package System.Web
1232
 * @since 3.0.4
1233
 */
1234
class THttpRequestUrlFormat extends TEnumerable
1235
{
1236
	const Get='Get';
1237
	const Path='Path';
1238
}
1239