Passed
Push — master ( c0a3a7...3b84a4 )
by Jeroen
58:51
created

engine/classes/Elgg/Http/Request.php (1 issue)

1
<?php
2
namespace Elgg\Http;
3
4
use Symfony\Component\HttpFoundation\Request as SymfonyRequest;
5
use Elgg\Application;
6
7
/**
8
 * Elgg HTTP request.
9
 *
10
 * @access private
11
 */
12
class Request extends SymfonyRequest {
13
14
	const REWRITE_TEST_TOKEN = '__testing_rewrite';
15
	const REWRITE_TEST_OUTPUT = 'success';
16
17
	/**
18
	 * Get the Elgg URL segments
19
	 *
20
	 * @param bool $raw If true, the segments will not be HTML escaped
21
	 *
22
	 * @return string[]
23
	 */
24 146
	public function getUrlSegments($raw = false) {
25 146
		$path = trim($this->getElggPath(), '/');
26 146
		if (!$raw) {
27 137
			$path = htmlspecialchars($path, ENT_QUOTES, 'UTF-8');
28
		}
29 146
		if (!$path) {
30 44
			return [];
31
		}
32
33 123
		return explode('/', $path);
34
	}
35
36
	/**
37
	 * Get a cloned request with new Elgg URL segments
38
	 *
39
	 * @param string[] $segments URL segments
40
	 *
41
	 * @return Request
42
	 */
43 1
	public function setUrlSegments(array $segments) {
44 1
		$base_path = trim($this->getBasePath(), '/');
45 1
		$server = $this->server->all();
46 1
		$server['REQUEST_URI'] = "$base_path/" . implode('/', $segments);
47
48 1
		return $this->duplicate(null, null, null, null, null, $server);
49
	}
50
51
	/**
52
	 * Get first Elgg URL segment
53
	 *
54
	 * @see \Elgg\Http\Request::getUrlSegments()
55
	 *
56
	 * @return string
57
	 */
58 12
	public function getFirstUrlSegment() {
59 12
		$segments = $this->getUrlSegments();
60 12
		if ($segments) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $segments of type string[] is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
61 5
			return array_shift($segments);
62
		} else {
63 7
			return '';
64
		}
65
	}
66
67
	/**
68
	 * Get the Request URI minus querystring
69
	 *
70
	 * @return string
71
	 */
72 156
	public function getElggPath() {
73 156
		if (php_sapi_name() === 'cli-server') {
74
			$path = $this->getRequestUri();
75
		} else {
76 156
			$path = $this->getPathInfo();
77
		}
78 156
		return preg_replace('~(\?.*)$~', '', $path);
79
	}
80
81
	/**
82
	 * {@inheritdoc}
83
	 */
84 427
	public function getClientIp() {
85 427
		$ip = parent::getClientIp();
86
87 427
		if ($ip == $this->server->get('REMOTE_ADDR')) {
88
			// try one more
89 427
			$ip_addresses = $this->server->get('HTTP_X_REAL_IP');
90 427
			if ($ip_addresses) {
91 1
				$ip_addresses = explode(',', $ip_addresses);
92 1
				return array_pop($ip_addresses);
93
			}
94
		}
95
96 426
		return $ip;
97
	}
98
99
	/**
100
	 * {@inheritdoc}
101
	 */
102 102
	public function isXmlHttpRequest() {
103 102
		return (strtolower($this->headers->get('X-Requested-With')) === 'xmlhttprequest'
104 50
			|| $this->query->get('X-Requested-With') === 'XMLHttpRequest'
105 102
			|| $this->request->get('X-Requested-With') === 'XMLHttpRequest');
106
		// GET/POST check is necessary for jQuery.form and other iframe-based "ajax". #8735
107
	}
108
109
	/**
110
	 * Sniff the Elgg site URL with trailing slash
111
	 *
112
	 * @return string
113
	 */
114 9
	public function sniffElggUrl() {
115 9
		$base_url = $this->getBaseUrl();
116
117
		// baseURL may end with the PHP script
118 9
		if ('.php' === substr($base_url, -4)) {
119
			$base_url = dirname($base_url);
120
		}
121
122 9
		$base_url = str_replace('\\', '/', $base_url);
123
124 9
		return rtrim($this->getSchemeAndHttpHost() . $base_url, '/') . '/';
125
	}
126
127
	/**
128
	 * Is the request for checking URL rewriting?
129
	 *
130
	 * @return bool
131
	 */
132
	public function isRewriteCheck() {
133
		if ($this->getPathInfo() !== ('/' . self::REWRITE_TEST_TOKEN)) {
134
			return false;
135
		}
136
137
		if (!$this->get(self::REWRITE_TEST_TOKEN)) {
138
			return false;
139
		}
140
141
		return true;
142
	}
143
144
	/**
145
	 * Is PHP running the CLI server front controller
146
	 *
147
	 * @return bool
148
	 */
149
	public function isCliServer() {
150
		return php_sapi_name() === 'cli-server';
151
	}
152
153
	/**
154
	 * Is the request pointing to a file that the CLI server can handle?
155
	 *
156
	 * @param string $root Root directory
157
	 *
158
	 * @return bool
159
	 */
160
	public function isCliServable($root) {
161
		$file = rtrim($root, '\\/') . $this->getElggPath();
162
		if (!is_file($file)) {
163
			return false;
164
		}
165
166
		// http://php.net/manual/en/features.commandline.webserver.php
167
		$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";
168
169
		// The CLI server routes ALL requests here (even existing files), so we have to check for these.
170
		$ext = pathinfo($file, PATHINFO_EXTENSION);
171
		if (!$ext) {
172
			return false;
173
		}
174
175
		$ext = preg_quote($ext, '~');
176
		return (bool) preg_match("~\\.{$ext}[,$]~", $extensions);
177
	}
178
	
179
	/**
180
	 * Returns an array of uploaded file objects regardless of upload status/errors
181
	 *
182
	 * @param string $input_name Form input name
183
	 * @return UploadedFile[]
184
	 */
185 6
	public function getFiles($input_name) {
186 6
		$files = $this->files->get($input_name, []);
187 6
		if (!is_array($files)) {
188 2
			$files = [$files];
189
		}
190 6
		return $files;
191
	}
192
	
193
	/**
194
	 * Returns the first file found based on the input name
195
	 *
196
	 * @param string $input_name         Form input name
197
	 * @param bool   $check_for_validity If there is an uploaded file, is it required to be valid
198
	 *
199
	 * @return UploadedFile|false
200
	 */
201 1
	public function getFile($input_name, $check_for_validity = true) {
202 1
		$files = $this->getFiles($input_name);
203 1
		if (empty($files)) {
204
			return false;
205
		}
206
		
207 1
		$file = $files[0];
208 1
		if (empty($file)) {
209
			return false;
210
		}
211
		
212 1
		if ($check_for_validity && !$file->isValid()) {
213
			return false;
214
		}
215
		
216 1
		return $file;
217
	}
218
}
219