Elgg  Version 1.9
Request.php
Go to the documentation of this file.
1 <?php
2 
41  public $query;
42 
47  public $request;
48 
53  public $cookies;
54 
59  public $files;
60 
65  public $server;
66 
71  public $headers;
72 
76  protected $baseUrl = null;
77 
81  protected $requestUri = null;
82 
86  protected $pathInfo = null;
87 
97  public function __construct(array $query = array(), array $request = array(),
98  array $cookies = array(), array $files = array(), array $server = array()) {
100  }
101 
112  protected function initialize(array $query = array(), array $request = array(),
113  array $cookies = array(), array $files = array(), array $server = array()) {
114  $this->query = new Elgg_Http_ParameterBag($this->stripSlashesIfMagicQuotes($query));
115  $this->request = new Elgg_Http_ParameterBag($this->stripSlashesIfMagicQuotes($request));
116  $this->cookies = new Elgg_Http_ParameterBag($this->stripSlashesIfMagicQuotes($cookies));
117  // Symfony uses FileBag so this will change in next Elgg version
118  $this->files = new Elgg_Http_ParameterBag($files);
119  $this->server = new Elgg_Http_ParameterBag($server);
120 
121  $headers = $this->prepareHeaders();
122  // Symfony uses HeaderBag so this will change in next Elgg version
123  $this->headers = new Elgg_Http_ParameterBag($headers);
124  }
125 
131  public static function createFromGlobals() {
132  return new Elgg_Http_Request($_GET, $_POST, $_COOKIE, $_FILES, $_SERVER);
133  }
134 
150  public static function create($uri, $method = 'GET', $parameters = array(), $cookies = array(), $files = array(), $server = array()) {
151  $server = array_merge(array(
152  'SERVER_NAME' => 'localhost',
153  'SERVER_PORT' => 80,
154  'HTTP_HOST' => 'localhost',
155  'HTTP_USER_AGENT' => 'Symfony/2.X',
156  'HTTP_ACCEPT' => 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
157  'HTTP_ACCEPT_LANGUAGE' => 'en-us,en;q=0.5',
158  'HTTP_ACCEPT_CHARSET' => 'ISO-8859-1,utf-8;q=0.7,*;q=0.7',
159  'REMOTE_ADDR' => '127.0.0.1',
160  'SCRIPT_NAME' => '',
161  'SCRIPT_FILENAME' => '',
162  'SERVER_PROTOCOL' => 'HTTP/1.1',
163  'REQUEST_TIME' => time(),
164  ), $server);
165 
166  $server['PATH_INFO'] = '';
167  $server['REQUEST_METHOD'] = strtoupper($method);
168 
169  $components = parse_url($uri);
170  if (isset($components['host'])) {
171  $server['SERVER_NAME'] = $components['host'];
172  $server['HTTP_HOST'] = $components['host'];
173  }
174 
175  if (isset($components['scheme'])) {
176  if ('https' === $components['scheme']) {
177  $server['HTTPS'] = 'on';
178  $server['SERVER_PORT'] = 443;
179  } else {
180  unset($server['HTTPS']);
181  $server['SERVER_PORT'] = 80;
182  }
183  }
184 
185  if (isset($components['port'])) {
186  $server['SERVER_PORT'] = $components['port'];
187  $server['HTTP_HOST'] = $server['HTTP_HOST'] . ':' . $components['port'];
188  }
189 
190  if (!isset($components['path'])) {
191  $components['path'] = '/';
192  }
193 
194  switch (strtoupper($method)) {
195  case 'POST':
196  case 'PUT':
197  case 'DELETE':
198  if (!isset($server['CONTENT_TYPE'])) {
199  $server['CONTENT_TYPE'] = 'application/x-www-form-urlencoded';
200  }
201  case 'PATCH':
202  $request = $parameters;
203  $query = array();
204  break;
205  default:
206  $request = array();
207  $query = $parameters;
208  break;
209  }
210 
211  if (isset($components['query'])) {
212  parse_str(html_entity_decode($components['query']), $qs);
213  // original uses array_replace. using array_merge for 5.2 BC
214  $query = array_merge($qs, $query);
215  }
216  $queryString = http_build_query($query, '', '&');
217 
218  $server['REQUEST_URI'] = $components['path'] . ('' !== $queryString ? '?' . $queryString : '');
219  $server['QUERY_STRING'] = $queryString;
220 
222  }
223 
234  public static function normalizeQueryString($qs) {
235  if ('' == $qs) {
236  return '';
237  }
238 
239  $parts = array();
240  $order = array();
241 
242  foreach (explode('&', $qs) as $param) {
243  if ('' === $param || '=' === $param[0]) {
244  // Ignore useless delimiters, e.g. "x=y&".
245  // Also ignore pairs with empty key, even if there was a value, e.g. "=value",
246  // as such nameless values cannot be retrieved anyway.
247  // PHP also does not include them when building _GET.
248  continue;
249  }
250 
251  $keyValuePair = explode('=', $param, 2);
252 
253  // GET parameters, that are submitted from a HTML form,
254  // encode spaces as "+" by default (as defined in enctype application/x-www-form-urlencoded).
255  // PHP also converts "+" to spaces when filling the global _GET or
256  // when using the function parse_str. This is why we use urldecode and then normalize to
257  // RFC 3986 with rawurlencode.
258  $parts[] = isset($keyValuePair[1]) ?
259  rawurlencode(urldecode($keyValuePair[0])) . '=' . rawurlencode(urldecode($keyValuePair[1])) :
260  rawurlencode(urldecode($keyValuePair[0]));
261  $order[] = urldecode($keyValuePair[0]);
262  }
263 
264  array_multisort($order, SORT_ASC, $parts);
265 
266  return implode('&', $parts);
267  }
268 
279  public function get($key, $default = null) {
280  if ($this->query->has($key)) {
281  return $this->query->get($key);
282  } else if ($this->request->has($key)) {
283  return $this->request->get($key);
284  } else {
285  return $default;
286  }
287  }
288 
294  public function getRequestUri() {
295  if (null === $this->requestUri) {
296  $this->requestUri = $this->prepareRequestUri();
297  }
298 
299  return $this->requestUri;
300  }
301 
307  public function getUri() {
308  if (null !== $qs = $this->getQueryString()) {
309  $qs = '?' . $qs;
310  }
311 
312  return $this->getSchemeAndHttpHost() . $this->getBaseUrl() . $this->getPathInfo() . $qs;
313  }
314 
322  public function getSchemeAndHttpHost() {
323  return $this->getScheme() . '://' . $this->getHttpHost();
324  }
325 
331  public function getScheme() {
332  return $this->isSecure() ? 'https' : 'http';
333  }
334 
342  public function getHttpHost() {
343  $scheme = $this->getScheme();
344  $port = $this->getPort();
345 
346  if (('http' == $scheme && $port == 80) || ('https' == $scheme && $port == 443)) {
347  return $this->getHost();
348  }
349 
350  return $this->getHost() . ':' . $port;
351  }
352 
360  public function getHost() {
361  if (!$host = $this->headers->get('HOST')) {
362  if (!$host = $this->server->get('SERVER_NAME')) {
363  $host = $this->server->get('SERVER_ADDR', '');
364  }
365  }
366 
367  // trim and remove port number from host
368  // host is lowercase as per RFC 952/2181
369  $host = strtolower(preg_replace('/:\d+$/', '', trim($host)));
370 
371  // as the host can come from the user (HTTP_HOST and depending on the configuration,
372  // SERVER_NAME too can come from the user)
373  // check that it does not contain forbidden characters (see RFC 952 and RFC 2181)
374  if ($host && !preg_match('/^\[?(?:[a-zA-Z0-9-:\]_]+\.?)+$/', $host)) {
375  throw new UnexpectedValueException('Invalid Host');
376  }
377 
378  return $host;
379  }
380 
386  public function isSecure() {
387  return 'on' == strtolower($this->server->get('HTTPS')) || 1 == $this->server->get('HTTPS');
388  }
389 
395  public function getPort() {
396  return $this->server->get('SERVER_PORT');
397  }
398 
412  public function getBaseUrl() {
413  if (null === $this->baseUrl) {
414  $this->baseUrl = $this->prepareBaseUrl();
415  }
416 
417  return $this->baseUrl;
418  }
419 
435  public function getPathInfo() {
436  if (null === $this->pathInfo) {
437  $this->pathInfo = $this->preparePathInfo();
438  }
439 
440  return $this->pathInfo;
441  }
442 
451  public function getQueryString() {
452  $qs = Elgg_Http_Request::normalizeQueryString($this->server->get('QUERY_STRING'));
453 
454  return '' === $qs ? null : $qs;
455  }
456 
464  public function getUrlSegments() {
465  $path = trim($this->query->get('__elgg_uri'), '/');
466  if (!$path) {
467  return array();
468  }
469 
470  return explode('/', $path);
471  }
472 
480  public function getFirstUrlSegment() {
481  $segments = $this->getUrlSegments();
482  if ($segments) {
483  return array_shift($segments);
484  } else {
485  return '';
486  }
487  }
488 
494  public function getClientIp() {
496 
497  $ip_address = $server->get('HTTP_X_FORWARDED_FOR');
498  if (!empty($ip_address)) {
499  return array_pop(explode(',', $ip_address));
500  }
501 
502  $ip_address = $server->get('HTTP_X_REAL_IP');
503  if (!empty($ip_address)) {
504  return array_pop(explode(',', $ip_address));
505  }
506 
507  return $server->get('REMOTE_ADDR');
508  }
509 
515  public function isXmlHttpRequest() {
516  return $this->headers->get('X-Requested-With') == 'XMLHttpRequest' ||
517  $this->get('X-Requested-With') === 'XMLHttpRequest';
518  }
519 
526  protected function stripSlashesIfMagicQuotes($data) {
527  if (get_magic_quotes_gpc()) {
529  } else {
530  return $data;
531  }
532  }
533 
539  protected function prepareHeaders() {
540  $headers = array();
541  $contentHeaders = array('CONTENT_LENGTH' => true, 'CONTENT_MD5' => true, 'CONTENT_TYPE' => true);
542  foreach ($this->server as $key => $value) {
543  if (0 === strpos($key, 'HTTP_')) {
544  $key = strtr(strtolower(substr($key, 5)), '_', '-');
545  $key = implode('-', array_map('ucfirst', explode('-', $key)));
546  $headers[$key] = $value;
547  } elseif (isset($contentHeaders[$key])) {
548  $key = strtr(strtolower($key), '_', '-');
549  $key = implode('-', array_map('ucfirst', explode('-', $key)));
550  $headers[$key] = $value;
551  }
552  }
553 
554  return $headers;
555  }
556 
565  protected function prepareRequestUri() {
566  return $this->server->get('REQUEST_URI');
567  }
568 
574  protected function prepareBaseUrl() {
575  $filename = basename($this->server->get('SCRIPT_FILENAME'));
576 
577  if (basename($this->server->get('SCRIPT_NAME')) === $filename) {
578  $baseUrl = $this->server->get('SCRIPT_NAME');
579  } elseif (basename($this->server->get('PHP_SELF')) === $filename) {
580  $baseUrl = $this->server->get('PHP_SELF');
581  } elseif (basename($this->server->get('ORIG_SCRIPT_NAME')) === $filename) {
582  $baseUrl = $this->server->get('ORIG_SCRIPT_NAME'); // 1and1 shared hosting compatibility
583  } else {
584  // Backtrack up the script_filename to find the portion matching
585  // php_self
586  $path = $this->server->get('PHP_SELF', '');
587  $file = $this->server->get('SCRIPT_FILENAME', '');
588  $segs = explode('/', trim($file, '/'));
589  $segs = array_reverse($segs);
590  $index = 0;
591  $last = count($segs);
592  $baseUrl = '';
593  do {
594  $seg = $segs[$index];
595  $baseUrl = '/' . $seg . $baseUrl;
596  ++$index;
597  } while (($last > $index) && (false !== ($pos = strpos($path, $baseUrl))) && (0 != $pos));
598  }
599 
600  // Does the baseUrl have anything in common with the request_uri?
601  $requestUri = $this->getRequestUri();
602 
603  if ($baseUrl && false !== $prefix = $this->getUrlencodedPrefix($requestUri, $baseUrl)) {
604  // full $baseUrl matches
605  return $prefix;
606  }
607 
608  if ($baseUrl && false !== $prefix = $this->getUrlencodedPrefix($requestUri, dirname($baseUrl))) {
609  // directory portion of $baseUrl matches
610  return rtrim($prefix, '/');
611  }
612 
613  $truncatedRequestUri = $requestUri;
614  if (($pos = strpos($requestUri, '?')) !== false) {
615  $truncatedRequestUri = substr($requestUri, 0, $pos);
616  }
617 
618  $basename = basename($baseUrl);
619  if (empty($basename) || !strpos(rawurldecode($truncatedRequestUri), $basename)) {
620  // no match whatsoever; set it blank
621  return '';
622  }
623 
624  // If using mod_rewrite or ISAPI_Rewrite strip the script filename
625  // out of baseUrl. $pos !== 0 makes sure it is not matching a value
626  // from PATH_INFO or QUERY_STRING
627  if ((strlen($requestUri) >= strlen($baseUrl)) && ((false !== ($pos = strpos($requestUri, $baseUrl))) && ($pos !== 0))) {
628  $baseUrl = substr($requestUri, 0, $pos + strlen($baseUrl));
629  }
630 
631  return rtrim($baseUrl, '/');
632  }
633 
639  protected function preparePathInfo() {
640  $baseUrl = $this->getBaseUrl();
641 
642  if (null === ($requestUri = $this->getRequestUri())) {
643  return '/';
644  }
645 
646  $pathInfo = '/';
647 
648  // Remove the query string from REQUEST_URI
649  if ($pos = strpos($requestUri, '?')) {
650  $requestUri = substr($requestUri, 0, $pos);
651  }
652 
653  if ((null !== $baseUrl) && (false === ($pathInfo = substr($requestUri, strlen($baseUrl))))) {
654  // If substr() returns false then PATH_INFO is set to an empty string
655  return '/';
656  } elseif (null === $baseUrl) {
657  return $requestUri;
658  }
659 
660  return (string) $pathInfo;
661  }
662 
672  private function getUrlencodedPrefix($string, $prefix) {
673  if (0 !== strpos(rawurldecode($string), $prefix)) {
674  return false;
675  }
676 
677  $len = strlen($prefix);
678 
679  if (preg_match("#^(%[[:xdigit:]]{2}|.){{$len}}#", $string, $match)) {
680  return $match[0];
681  }
682 
683  return false;
684  }
685 
686 }
$filename
Definition: crop.php:23
getFirstUrlSegment()
Get first URL segment from the path info.
Definition: Request.php:480
static createFromGlobals()
Creates a request from PHP's globals.
Definition: Request.php:131
getPort()
Returns the port on which the request is made.
Definition: Request.php:395
prepareBaseUrl()
Prepares the base URL.
Definition: Request.php:574
static normalizeQueryString($qs)
Normalizes a query string.
Definition: Request.php:234
prepareRequestUri()
Set the request URI.
Definition: Request.php:565
getBaseUrl()
Returns the root url from which this request is executed.
Definition: Request.php:412
preparePathInfo()
Prepares the path info.
Definition: Request.php:639
static create($uri, $method='GET', $parameters=array(), $cookies=array(), $files=array(), $server=array())
Creates a Request based on a given URI and configuration.
Definition: Request.php:150
prepareHeaders()
Get the HTTP headers from server.
Definition: Request.php:539
getSchemeAndHttpHost()
Gets the scheme and HTTP host.
Definition: Request.php:322
getScheme()
Gets the request's scheme.
Definition: Request.php:331
getUrlSegments()
Get URL segments from the path info.
Definition: Request.php:464
getHost()
Returns the host name.
Definition: Request.php:360
initialize(array $query=array(), array $request=array(), array $cookies=array(), array $files=array(), array $server=array())
Initialize the request.
Definition: Request.php:112
__construct(array $query=array(), array $request=array(), array $cookies=array(), array $files=array(), array $server=array())
Create a request.
Definition: Request.php:97
getClientIp()
Get the IP address of the client.
Definition: Request.php:494
getQueryString()
Gets the normalized query string for the Request.
Definition: Request.php:451
getUri()
Generates a normalized URI for the Request.
Definition: Request.php:307
isXmlHttpRequest()
Is this an ajax request.
Definition: Request.php:515
getRequestUri()
Returns the requested URI.
Definition: Request.php:294
getHttpHost()
Returns the HTTP host being requested.
Definition: Request.php:342
getPathInfo()
Returns the path being requested relative to the executed script.
Definition: Request.php:435
stripSlashesIfMagicQuotes($data)
Strip slashes if magic quotes is on.
Definition: Request.php:526
isSecure()
Is this request using SSL.
Definition: Request.php:386
$default
Definition: checkbox.php:36
$value
Definition: longtext.php:29
_elgg_stripslashes_deep($value)
Strip slashes.
Definition: input.php:511
$method
Definition: form.php:25
$path
Definition: invalid.php:17
$data
Definition: opendd.php:13
$key
Definition: summary.php:34
$string