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 }
getUri()
Generates a normalized URI for the Request.
Definition: Request.php:307
getBaseUrl()
Returns the root url from which this request is executed.
Definition: Request.php:412
$method
Definition: form.php:25
getPathInfo()
Returns the path being requested relative to the executed script.
Definition: Request.php:435
isSecure()
Is this request using SSL.
Definition: Request.php:386
getRequestUri()
Returns the requested URI.
Definition: Request.php:294
elgg parse_str
Returns an object with key/values of the parsed query string.
Definition: elgglib.js:505
$data
Definition: opendd.php:13
$value
Definition: longtext.php:29
getFirstUrlSegment()
Get first URL segment from the path info.
Definition: Request.php:480
$default
Definition: checkbox.php:36
elgg parse_url
Parse a URL into its parts.
Definition: elgglib.js:432
getQueryString()
Gets the normalized query string for the Request.
Definition: Request.php:451
getScheme()
Gets the request&#39;s scheme.
Definition: Request.php:331
$string
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
static normalizeQueryString($qs)
Normalizes a query string.
Definition: Request.php:234
getHttpHost()
Returns the HTTP host being requested.
Definition: Request.php:342
$key
Definition: summary.php:34
getUrlSegments()
Get URL segments from the path info.
Definition: Request.php:464
getSchemeAndHttpHost()
Gets the scheme and HTTP host.
Definition: Request.php:322
getClientIp()
Get the IP address of the client.
Definition: Request.php:494
stripSlashesIfMagicQuotes($data)
Strip slashes if magic quotes is on.
Definition: Request.php:526
initialize(array $query=array(), array $request=array(), array $cookies=array(), array $files=array(), array $server=array())
Initialize the request.
Definition: Request.php:112
static createFromGlobals()
Creates a request from PHP&#39;s globals.
Definition: Request.php:131
prepareBaseUrl()
Prepares the base URL.
Definition: Request.php:574
_elgg_stripslashes_deep($value)
Strip slashes.
Definition: input.php:511
prepareHeaders()
Get the HTTP headers from server.
Definition: Request.php:539
getPort()
Returns the port on which the request is made.
Definition: Request.php:395
isXmlHttpRequest()
Is this an ajax request.
Definition: Request.php:515
$filename
Definition: crop.php:23
prepareRequestUri()
Set the request URI.
Definition: Request.php:565
c Accompany it with the information you received as to the offer to distribute corresponding source complete source code means all the source code for all modules it plus any associated interface definition files
Definition: LICENSE.txt:157
preparePathInfo()
Prepares the path info.
Definition: Request.php:639
$path
Definition: invalid.php:17
getHost()
Returns the host name.
Definition: Request.php:360
__construct(array $query=array(), array $request=array(), array $cookies=array(), array $files=array(), array $server=array())
Create a request.
Definition: Request.php:97