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

Request   A

Complexity

Total Complexity 30

Size/Duplication

Total Lines 205
Duplicated Lines 0 %

Test Coverage

Coverage 68.48%

Importance

Changes 0
Metric Value
dl 0
loc 205
ccs 50
cts 73
cp 0.6848
rs 10
c 0
b 0
f 0
wmc 30

12 Methods

Rating   Name   Duplication   Size   Complexity  
A getClientIp() 0 13 3
A setUrlSegments() 0 6 1
A getUrlSegments() 0 10 3
A isXmlHttpRequest() 0 4 3
A getElggPath() 0 7 2
A getFirstUrlSegment() 0 6 2
A isCliServable() 0 17 3
B getFile() 0 16 5
A isRewriteCheck() 0 10 3
A getFiles() 0 6 2
A isCliServer() 0 2 1
A sniffElggUrl() 0 11 2
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 Cash Costello
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
0 ignored issues
show
Bug introduced by Jeroen Dalsem
The type Elgg\Http\UploadedFile was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
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