Elgg  Version 4.x
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 = filter_tags($this->unfiltered_params);
197  $this->getContextStack()->pop();
198 
199  return $filter_result ? $this->filtered_params : $this->unfiltered_params;
200  }
201 
207  public function getCurrentURL() {
209 
210  $page = $url['scheme'] . "://" . $url['host'];
211 
212  if (isset($url['port']) && $url['port']) {
213  $page .= ":" . $url['port'];
214  }
215 
216  $page = trim($page, "/");
217 
218  $page .= $this->getRequestUri();
219 
220  return $page;
221  }
222 
230  public function getUrlSegments(bool $raw = false) {
231  $path = trim($this->getElggPath(), '/');
232  if (!$raw) {
233  $path = htmlspecialchars($path, ENT_QUOTES, 'UTF-8');
234  }
235  if (!$path) {
236  return [];
237  }
238 
239  return explode('/', $path);
240  }
241 
249  public function setUrlSegments(array $segments) {
250  $base_path = trim($this->getBasePath(), '/');
251  $server = $this->server->all();
252  $server['REQUEST_URI'] = "$base_path/" . implode('/', $segments);
253 
254  return $this->duplicate(null, null, null, null, null, $server);
255  }
256 
264  public function getFirstUrlSegment() {
265  $segments = $this->getUrlSegments();
266  if (!empty($segments)) {
267  return array_shift($segments);
268  }
269 
270  return '';
271  }
272 
278  public function getElggPath() {
279  if (php_sapi_name() === 'cli-server') {
280  $path = $this->getRequestUri();
281  } else {
282  $path = $this->getPathInfo();
283  }
284 
285  return preg_replace('~(\?.*)$~', '', $path);
286  }
287 
291  public function getClientIp() {
292  $ip = parent::getClientIp();
293 
294  if ($ip == $this->server->get('REMOTE_ADDR')) {
295  // try one more
296  $ip_addresses = $this->server->get('HTTP_X_REAL_IP');
297  if ($ip_addresses) {
298  $ip_addresses = explode(',', $ip_addresses);
299 
300  return array_pop($ip_addresses);
301  }
302  }
303 
304  return $ip;
305  }
306 
310  public function isXmlHttpRequest() {
311  return (strtolower($this->headers->get('X-Requested-With') ?: '') === 'xmlhttprequest'
312  || $this->query->get('X-Requested-With') === 'XMLHttpRequest'
313  || $this->request->get('X-Requested-With') === 'XMLHttpRequest');
314  }
315 
321  public function sniffElggUrl() {
322  $base_url = $this->getBaseUrl();
323 
324  // baseURL may end with the PHP script
325  if ('.php' === substr($base_url, -4)) {
326  $base_url = dirname($base_url);
327  }
328 
329  $base_url = str_replace('\\', '/', $base_url);
330 
331  return rtrim($this->getSchemeAndHttpHost() . $base_url, '/') . '/';
332  }
333 
339  public function isRewriteCheck() {
340  if ($this->getPathInfo() !== ('/' . self::REWRITE_TEST_TOKEN)) {
341  return false;
342  }
343 
344  if (!$this->get(self::REWRITE_TEST_TOKEN)) {
345  return false;
346  }
347 
348  return true;
349  }
350 
357  public function isAction(): bool {
358  return $this->getFirstUrlSegment() === 'action';
359  }
360 
366  public function isCliServer() {
367  return php_sapi_name() === 'cli-server';
368  }
369 
377  public function isCliServable($root) {
378  $file = rtrim($root, '\\/') . $this->getElggPath();
379  if (!is_file($file)) {
380  return false;
381  }
382 
383  // http://php.net/manual/en/features.commandline.webserver.php
384  $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";
385 
386  // The CLI server routes ALL requests here (even existing files), so we have to check for these.
387  $ext = pathinfo($file, PATHINFO_EXTENSION);
388  if (!$ext) {
389  return false;
390  }
391 
392  $ext = preg_quote($ext, '~');
393 
394  return (bool) preg_match("~\\.{$ext}[,$]~", $extensions);
395  }
396 
404  public function getFiles($input_name) {
405  $files = $this->files->get($input_name);
406  if (empty($files)) {
407  return [];
408  }
409 
410  if (!is_array($files)) {
411  $files = [$files];
412  }
413 
414  return $files;
415  }
416 
425  public function getFile($input_name, $check_for_validity = true) {
426  $files = $this->getFiles($input_name);
427  if (empty($files)) {
428  return false;
429  }
430 
431  $file = $files[0];
432  if (empty($file)) {
433  return false;
434  }
435 
436  if ($check_for_validity && !$file->isValid()) {
437  return false;
438  }
439 
440  return $file;
441  }
442 
449  public function validate() {
450 
451  $reported_bytes = $this->server->get('CONTENT_LENGTH');
452 
453  // Requests with multipart content type
454  $post_data_count = count($this->request->all());
455 
456  // Requests with other content types
457  $content = $this->getContent();
458  $post_body_length = is_string($content) ? elgg_strlen($content) : 0;
459 
460  $file_count = count($this->files->all());
461 
462  $is_valid = function() use ($reported_bytes, $post_data_count, $post_body_length, $file_count) {
463  if (empty($reported_bytes)) {
464  // Content length is set for POST requests only
465  return true;
466  }
467 
468  if (empty($post_data_count) && empty($post_body_length) && empty($file_count)) {
469  // The size of $_POST or uploaded files has exceed the size limit
470  // and the request body/query has been truncated
471  // thus the request reported bytes is set, but no postdata is found
472  return false;
473  }
474 
475  return true;
476  };
477 
478  if (!$is_valid()) {
479  $error_msg = elgg_trigger_plugin_hook('action_gatekeeper:upload_exceeded_msg', 'all', [
480  'post_size' => $reported_bytes,
481  'visible_errors' => true,
482  ], elgg_echo('actiongatekeeper:uploadexceeded'));
483 
484  throw new BadRequestException($error_msg);
485  }
486  }
487 }
$default
Definition: checkbox.php:31
validate()
Validate the request.
Definition: Request.php:449
getElggPath()
Get the Request URI minus querystring.
Definition: Request.php:278
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:366
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:404
getFirstUrlSegment()
Get first Elgg URL segment.
Definition: Request.php:264
$request
Definition: livesearch.php:11
initializeContext()
Initialize context stack.
Definition: Request.php:90
elgg parse_url
Parse a URL into its parts.
Definition: elgglib.js:135
filter_tags($var)
Filter tags from a given string based on registered hooks.
Definition: input.php:77
setUrlSegments(array $segments)
Get a cloned request with new Elgg URL segments.
Definition: Request.php:249
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:321
$value
Definition: generic.php:51
isCliServable($root)
Is the request pointing to a file that the CLI server can handle?
Definition: Request.php:377
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
$path
Definition: details.php:68
isXmlHttpRequest()
{}
Definition: Request.php:310
Route Wrapper.
Definition: Route.php:8
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:207
getRoute()
Returns the route matched for this request by the router.
Definition: Request.php:127
isAction()
Is the request an action.
Definition: Request.php:357
getUrlSegments(bool $raw=false)
Get the Elgg URL segments.
Definition: Request.php:230
elgg_trigger_plugin_hook($hook, $type, $params=null, $returnvalue=null)
Definition: elgglib.php:380
elgg_get_site_url()
Get the URL for the current (or specified) site, ending with "/".
const REWRITE_TEST_TOKEN
Definition: Request.php:19
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:686
$extensions
if($container instanceof ElggGroup &&$container->guid!=elgg_get_page_owner_guid()) $key
Definition: summary.php:44
if($pagination &&($position== 'after'||$position== 'both')) $base_url
Definition: list.php:108
getContextStack()
Returns context stack.
Definition: Request.php:102
isRewriteCheck()
Is the request for checking URL rewriting?
Definition: Request.php:339
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:425
$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
$segments
Definition: admin.php:15
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