Elgg  Version 4.3
Request.php
Go to the documentation of this file.
1 <?php
2 
3 namespace Elgg\Http;
4 
5 use Elgg\Config;
6 use Elgg\Context;
10 use Symfony\Component\HttpFoundation\Request as SymfonyRequest;
11 
17 class Request extends SymfonyRequest {
18 
19  const REWRITE_TEST_TOKEN = '__testing_rewrite';
20  const REWRITE_TEST_OUTPUT = 'success';
21 
25  protected $context_stack;
26 
30  protected $route;
31 
35  protected $request_overrides;
36 
40  protected $filtered_params;
41 
45  protected $unfiltered_params;
46 
50  public function __construct(
51  array $query = [],
52  array $request = [],
53  array $attributes = [],
54  array $cookies = [],
55  array $files = [],
56  array $server = [],
57  $content = null
58  ) {
59  parent::__construct($query, $request, $attributes, $cookies, $files, $server, $content);
60 
61  $this->initializeContext();
62 
63  $this->request_overrides = [];
64  }
65 
72  $trusted_proxies = $config->http_request_trusted_proxy_ips;
73  if (empty($trusted_proxies)) {
74  return;
75  }
76 
77  $allowed_headers = $config->http_request_trusted_proxy_headers;
78  if (empty($allowed_headers)) {
79  $allowed_headers = self::HEADER_X_FORWARDED_FOR | self::HEADER_X_FORWARDED_HOST | self::HEADER_X_FORWARDED_PORT | self::HEADER_X_FORWARDED_PROTO;
80  }
81 
82  $this->setTrustedProxies($trusted_proxies, $allowed_headers);
83  }
84 
90  public function initializeContext() {
91  $context = new Context($this);
92  $this->context_stack = $context;
93 
94  return $this;
95  }
96 
102  public function getContextStack() {
103  return $this->context_stack;
104  }
105 
113  public function setRoute(Route $route) {
114  $this->route = $route;
115  foreach ($route->getMatchedParameters() as $key => $value) {
116  $this->setParam($key, $value);
117  }
118 
119  return $this;
120  }
121 
127  public function getRoute() {
128  return $this->route;
129  }
130 
142  public function setParam(string $key, $value, bool $override_request = false) {
143  if ($override_request) {
144  $this->request_overrides[$key] = $value;
145  } else {
146  $this->request->set($key, $value);
147  }
148 
149  // reset the cached params
150  unset($this->filtered_params);
151  unset($this->unfiltered_params);
152 
153  return $this;
154  }
155 
169  public function getParam(string $key, $default = null, bool $filter_result = true) {
170  $values = $this->getParams($filter_result);
171 
172  return elgg_extract($key, $values, $default);
173  }
174 
182  public function getParams(bool $filter_result = true) {
183  if (isset($this->filtered_params) && isset($this->unfiltered_params)) {
184  return $filter_result ? $this->filtered_params : $this->unfiltered_params;
185  }
186 
188  $query = $this->query->all();
189  $attributes = $this->attributes->all();
190  $post = $this->request->all();
191 
192  $this->unfiltered_params = array_merge($post, $attributes, $query, $request_overrides);
193 
194  // filter the input params
195  $this->getContextStack()->push('input');
196  $this->filtered_params = elgg_sanitize_input($this->unfiltered_params);
197  $this->getContextStack()->pop();
198 
199  return $filter_result ? $this->filtered_params : $this->unfiltered_params;
200  }
201 
210  public function getCurrentURL() {
212 
213  $page = $url['scheme'] . "://" . $url['host'];
214 
215  if (isset($url['port']) && $url['port']) {
216  $page .= ":" . $url['port'];
217  }
218 
219  $page = trim($page, "/");
220 
221  $page .= $this->getRequestUri();
222 
223  return $page;
224  }
225 
233  public function getUrlSegments(bool $raw = false) {
234  $path = trim($this->getElggPath(), '/');
235  if (!$raw) {
236  $path = htmlspecialchars($path, ENT_QUOTES, 'UTF-8');
237  }
238  if (!$path) {
239  return [];
240  }
241 
242  return explode('/', $path);
243  }
244 
252  public function setUrlSegments(array $segments) {
253  $base_path = trim($this->getBasePath(), '/');
254  $server = $this->server->all();
255  $server['REQUEST_URI'] = "$base_path/" . implode('/', $segments);
256 
257  return $this->duplicate(null, null, null, null, null, $server);
258  }
259 
267  public function getFirstUrlSegment() {
268  $segments = $this->getUrlSegments();
269  if (!empty($segments)) {
270  return array_shift($segments);
271  }
272 
273  return '';
274  }
275 
281  public function getElggPath() {
282  if (php_sapi_name() === 'cli-server') {
283  $path = $this->getRequestUri();
284  } else {
285  $path = $this->getPathInfo();
286  }
287 
288  return preg_replace('~(\?.*)$~', '', $path);
289  }
290 
294  public function getClientIp() {
295  $ip = parent::getClientIp();
296 
297  if ($ip == $this->server->get('REMOTE_ADDR')) {
298  // try one more
299  $ip_addresses = $this->server->get('HTTP_X_REAL_IP');
300  if ($ip_addresses) {
301  $ip_addresses = explode(',', $ip_addresses);
302 
303  return array_pop($ip_addresses);
304  }
305  }
306 
307  return $ip;
308  }
309 
313  public function isXmlHttpRequest() {
314  return (strtolower($this->headers->get('X-Requested-With') ?: '') === 'xmlhttprequest'
315  || $this->query->get('X-Requested-With') === 'XMLHttpRequest'
316  || $this->request->get('X-Requested-With') === 'XMLHttpRequest');
317  }
318 
324  public function sniffElggUrl() {
325  $base_url = $this->getBaseUrl();
326 
327  // baseURL may end with the PHP script
328  if ('.php' === substr($base_url, -4)) {
329  $base_url = dirname($base_url);
330  }
331 
332  $base_url = str_replace('\\', '/', $base_url);
333 
334  return rtrim($this->getSchemeAndHttpHost() . $base_url, '/') . '/';
335  }
336 
342  public function isRewriteCheck() {
343  if ($this->getPathInfo() !== ('/' . self::REWRITE_TEST_TOKEN)) {
344  return false;
345  }
346 
347  if (!$this->get(self::REWRITE_TEST_TOKEN)) {
348  return false;
349  }
350 
351  return true;
352  }
353 
360  public function isAction(): bool {
361  return $this->getFirstUrlSegment() === 'action';
362  }
363 
369  public function isCliServer() {
370  return php_sapi_name() === 'cli-server';
371  }
372 
380  public function isCliServable($root) {
381  $file = rtrim($root, '\\/') . $this->getElggPath();
382  if (!is_file($file)) {
383  return false;
384  }
385 
386  // http://php.net/manual/en/features.commandline.webserver.php
387  $extensions = ".3gp, .apk, .avi, .bmp, .css, .csv, .doc, .docx, .flac, .gif, .gz, .gzip, .htm, .html, .ics, .jpe, .jpeg, .jpg, .js, .kml, .kmz, .m4a, .mov, .mp3, .mp4, .mpeg, .mpg, .odp, .ods, .odt, .oga, .ogg, .ogv, .pdf, .pdf, .png, .pps, .pptx, .qt, .svg, .swf, .tar, .text, .tif, .txt, .wav, .webm, .wmv, .xls, .xlsx, .xml, .xsl, .xsd, and .zip";
388 
389  // The CLI server routes ALL requests here (even existing files), so we have to check for these.
390  $ext = pathinfo($file, PATHINFO_EXTENSION);
391  if (!$ext) {
392  return false;
393  }
394 
395  $ext = preg_quote($ext, '~');
396 
397  return (bool) preg_match("~\\.{$ext}[,$]~", $extensions);
398  }
399 
407  public function getFiles($input_name) {
408  $files = $this->files->get($input_name);
409  if (empty($files)) {
410  return [];
411  }
412 
413  if (!is_array($files)) {
414  $files = [$files];
415  }
416 
417  return $files;
418  }
419 
428  public function getFile($input_name, $check_for_validity = true) {
429  $files = $this->getFiles($input_name);
430  if (empty($files)) {
431  return false;
432  }
433 
434  $file = $files[0];
435  if (empty($file)) {
436  return false;
437  }
438 
439  if ($check_for_validity && !$file->isValid()) {
440  return false;
441  }
442 
443  return $file;
444  }
445 
452  public function validate() {
453  $this->validateRequestHostHeader();
455  }
456 
466  protected function validateRequestHostHeader() {
467  $config = _elgg_services()->config;
468  if (empty($config->wwwroot)) {
469  return;
470  }
471 
472  $config_host = parse_url($config->wwwroot, PHP_URL_HOST);
473  if ($config_host === $this->getHost()) {
474  return;
475  }
476 
477  throw new BadRequestException(elgg_echo('BadRequestException:invalid_host_header'));
478  }
479 
487  protected function validateRequestBodyTruncated(): void {
488  $reported_bytes = $this->server->get('CONTENT_LENGTH');
489 
490  // Requests with multipart content type
491  $post_data_count = count($this->request->all());
492 
493  // Requests with other content types
494  $content = $this->getContent();
495  $post_body_length = is_string($content) ? elgg_strlen($content) : 0;
496 
497  $file_count = count($this->files->all());
498 
499  $is_valid = function() use ($reported_bytes, $post_data_count, $post_body_length, $file_count) {
500  if (empty($reported_bytes)) {
501  // Content length is set for POST requests only
502  return true;
503  }
504 
505  if (empty($post_data_count) && empty($post_body_length) && empty($file_count)) {
506  // The size of $_POST or uploaded files has exceed the size limit
507  // and the request body/query has been truncated
508  // thus the request reported bytes is set, but no postdata is found
509  return false;
510  }
511 
512  return true;
513  };
514 
515  if ($is_valid()) {
516  return;
517  }
518 
519  $error_msg = elgg_trigger_deprecated_plugin_hook('action_gatekeeper:upload_exceeded_msg', 'all', [
520  'post_size' => $reported_bytes,
521  'visible_errors' => true,
522  ], elgg_echo('actiongatekeeper:uploadexceeded'), "The 'action_gatekeeper:upload_exceeded_msg', 'all' has been deprecated", '4.3');
523 
524  throw new BadRequestException($error_msg);
525  }
526 
536  public function correctBaseURL(\Elgg\Config $config): void {
537  if (\Elgg\Application::isCli()) {
538  return;
539  }
540 
541  $path = parse_url($config->wwwroot, PHP_URL_PATH);
542 
543  $this->baseUrl = rtrim($path, '/');
544  }
545 }
$default
Definition: checkbox.php:31
validate()
Validate the request.
Definition: Request.php:452
validateRequestHostHeader()
Validate that the request was made on the correct host.
Definition: Request.php:466
getElggPath()
Get the Request URI minus querystring.
Definition: Request.php:281
initializeTrustedProxyConfiguration(Config $config)
Configure trusted proxy servers to allow access to more client information.
Definition: Request.php:71
Elgg HTTP request.
Definition: Request.php:17
$context
Definition: add.php:8
$input_name
Definition: crop.php:24
isCliServer()
Is PHP running the CLI server front controller.
Definition: Request.php:369
getParam(string $key, $default=null, bool $filter_result=true)
Get some input from variables passed submitted through GET or POST.
Definition: Request.php:169
$server
setRoute(Route $route)
Sets the route matched for this request by the router.
Definition: Request.php:113
getFiles($input_name)
Returns an array of uploaded file objects regardless of upload status/errors.
Definition: Request.php:407
getFirstUrlSegment()
Get first Elgg URL segment.
Definition: Request.php:267
$request
Definition: livesearch.php:11
initializeContext()
Initialize context stack.
Definition: Request.php:90
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 plus the scripts used to control compilation and installation of the executable as a special the source code distributed need not include anything that is normally and so on of the operating system on which the executable unless that component itself accompanies the executable If distribution of executable or object code is made by offering access to copy from a designated then offering equivalent access to copy the source code from the same place counts as distribution of the source even though third parties are not compelled to copy the source along with the object code You may not or distribute the Program except as expressly provided under this License Any attempt otherwise to sublicense or distribute the Program is void
Definition: LICENSE.txt:215
validateRequestBodyTruncated()
Validate that the request body hasn&#39;t been truncated (eg.
Definition: Request.php:487
elgg_sanitize_input($input)
Filter input from a given string based on registered hooks.
Definition: input.php:78
elgg parse_url
Parse a URL into its parts.
Definition: elgglib.js:135
setUrlSegments(array $segments)
Get a cloned request with new Elgg URL segments.
Definition: Request.php:252
elgg_echo($message_key, array $args=[], $language="")
Elgg language module Functions to manage language and translations.
Definition: languages.php:18
sniffElggUrl()
Sniff the Elgg site URL with trailing slash.
Definition: Request.php:324
$value
Definition: generic.php:51
isCliServable($root)
Is the request pointing to a file that the CLI server can handle?
Definition: Request.php:380
elgg_strlen()
Wrapper function for mb_strlen().
Definition: mb_wrapper.php:52
$config
Advanced site settings, debugging section.
Definition: debugging.php:6
$page
Definition: admin.php:23
setParam(string $key, $value, bool $override_request=false)
Sets an input value that may later be retrieved by get_input.
Definition: Request.php:142
if(!$pagination &&$limit!==false &&!empty($items)&&count($items) >=$limit) $base_url
Definition: list.php:113
$path
Definition: details.php:68
isXmlHttpRequest()
{}
Definition: Request.php:313
Route Wrapper.
Definition: Route.php:8
if(elgg_view_exists('elgg/admin.js')) $segments
Definition: admin.php:19
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:210
getCurrentURL()
Returns current page URL.
Definition: Request.php:210
static isCli()
Is application running in CLI.
getRoute()
Returns the route matched for this request by the router.
Definition: Request.php:127
isAction()
Is the request an action.
Definition: Request.php:360
getUrlSegments(bool $raw=false)
Get the Elgg URL segments.
Definition: Request.php:233
elgg_get_site_url()
Get the URL for the current (or specified) site, ending with "/".
const REWRITE_TEST_TOKEN
Definition: Request.php:19
elgg_trigger_deprecated_plugin_hook($hook, $type, $params=null, $returnvalue=null, $message=null, $version=null)
Trigger an plugin hook normally, but send a notice about deprecated use if any handlers are registere...
Definition: deprecation.php:39
elgg_extract($key, $array, $default=null, $strict=true)
Checks for $array[$key] and returns its value if it exists, else returns $default.
Definition: elgglib.php:547
$extensions
if($container instanceof ElggGroup &&$container->guid!=elgg_get_page_owner_guid()) $key
Definition: summary.php:44
getContextStack()
Returns context stack.
Definition: Request.php:102
isRewriteCheck()
Is the request for checking URL rewriting?
Definition: Request.php:342
Thrown when request is malformatted.
getParams(bool $filter_result=true)
Returns all values parsed from the request.
Definition: Request.php:182
getFile($input_name, $check_for_validity=true)
Returns the first file found based on the input name.
Definition: Request.php:428
$query
$content
Set robots.txt action.
Definition: set_robots.php:6
foreach($plugin_guids as $guid) if(empty($deactivated_plugins)) $url
Definition: deactivate.php:39
_elgg_services()
Get the global service provider.
Definition: elgglib.php:638
const REWRITE_TEST_OUTPUT
Definition: Request.php:20
$attributes
Elgg AJAX loader.
Definition: ajax_loader.php:10
getMatchedParameters()
Get matched parameters.
Definition: Route.php:34
Manages a global stack of strings for sharing information about the current execution context...
Definition: Context.php:27
__construct(array $query=[], array $request=[], array $attributes=[], array $cookies=[], array $files=[], array $server=[], $content=null)
{}
Definition: Request.php:50
correctBaseURL(\Elgg\Config $config)
Correct the base URL of the request.
Definition: Request.php:536