Completed
Pull Request — master (#3787)
by Robin
23:20 queued 08:55
created
lib/private/AppFramework/Http/Request.php 2 patches
Indentation   +806 added lines, -806 removed lines patch added patch discarded remove patch
@@ -55,811 +55,811 @@
 block discarded – undo
55 55
  */
56 56
 class Request implements \ArrayAccess, \Countable, IRequest {
57 57
 
58
-	const USER_AGENT_IE = '/(MSIE)|(Trident)/';
59
-	// Microsoft Edge User Agent from https://msdn.microsoft.com/en-us/library/hh869301(v=vs.85).aspx
60
-	const USER_AGENT_MS_EDGE = '/^Mozilla\/5\.0 \([^)]+\) AppleWebKit\/[0-9.]+ \(KHTML, like Gecko\) Chrome\/[0-9.]+ (Mobile Safari|Safari)\/[0-9.]+ Edge\/[0-9.]+$/';
61
-	// Firefox User Agent from https://developer.mozilla.org/en-US/docs/Web/HTTP/Gecko_user_agent_string_reference
62
-	const USER_AGENT_FIREFOX = '/^Mozilla\/5\.0 \([^)]+\) Gecko\/[0-9.]+ Firefox\/[0-9.]+$/';
63
-	// Chrome User Agent from https://developer.chrome.com/multidevice/user-agent
64
-	const USER_AGENT_CHROME = '/^Mozilla\/5\.0 \([^)]+\) AppleWebKit\/[0-9.]+ \(KHTML, like Gecko\)( Ubuntu Chromium\/[0-9.]+|) Chrome\/[0-9.]+ (Mobile Safari|Safari)\/[0-9.]+$/';
65
-	// Safari User Agent from http://www.useragentstring.com/pages/Safari/
66
-	const USER_AGENT_SAFARI = '/^Mozilla\/5\.0 \([^)]+\) AppleWebKit\/[0-9.]+ \(KHTML, like Gecko\) Version\/[0-9.]+ Safari\/[0-9.A-Z]+$/';
67
-	// Android Chrome user agent: https://developers.google.com/chrome/mobile/docs/user-agent
68
-	const USER_AGENT_ANDROID_MOBILE_CHROME = '#Android.*Chrome/[.0-9]*#';
69
-	const USER_AGENT_FREEBOX = '#^Mozilla/5\.0$#';
70
-	const REGEX_LOCALHOST = '/^(127\.0\.0\.1|localhost)$/';
71
-
72
-	/**
73
-	 * @deprecated use \OCP\IRequest::USER_AGENT_CLIENT_IOS instead
74
-	 */
75
-	const USER_AGENT_OWNCLOUD_IOS = '/^Mozilla\/5\.0 \(iOS\) (ownCloud|Nextcloud)\-iOS.*$/';
76
-	/**
77
-	 * @deprecated use \OCP\IRequest::USER_AGENT_CLIENT_ANDROID instead
78
-	 */
79
-	const USER_AGENT_OWNCLOUD_ANDROID = '/^Mozilla\/5\.0 \(Android\) ownCloud\-android.*$/';
80
-	/**
81
-	 * @deprecated use \OCP\IRequest::USER_AGENT_CLIENT_DESKTOP instead
82
-	 */
83
-	const USER_AGENT_OWNCLOUD_DESKTOP = '/^Mozilla\/5\.0 \([A-Za-z ]+\) (mirall|csyncoC)\/.*$/';
84
-
85
-	protected $inputStream;
86
-	protected $content;
87
-	protected $items = array();
88
-	protected $allowedKeys = array(
89
-		'get',
90
-		'post',
91
-		'files',
92
-		'server',
93
-		'env',
94
-		'cookies',
95
-		'urlParams',
96
-		'parameters',
97
-		'method',
98
-		'requesttoken',
99
-	);
100
-	/** @var ISecureRandom */
101
-	protected $secureRandom;
102
-	/** @var IConfig */
103
-	protected $config;
104
-	/** @var string */
105
-	protected $requestId = '';
106
-	/** @var ICrypto */
107
-	protected $crypto;
108
-	/** @var CsrfTokenManager|null */
109
-	protected $csrfTokenManager;
110
-
111
-	/** @var bool */
112
-	protected $contentDecoded = false;
113
-
114
-	/**
115
-	 * @param array $vars An associative array with the following optional values:
116
-	 *        - array 'urlParams' the parameters which were matched from the URL
117
-	 *        - array 'get' the $_GET array
118
-	 *        - array|string 'post' the $_POST array or JSON string
119
-	 *        - array 'files' the $_FILES array
120
-	 *        - array 'server' the $_SERVER array
121
-	 *        - array 'env' the $_ENV array
122
-	 *        - array 'cookies' the $_COOKIE array
123
-	 *        - string 'method' the request method (GET, POST etc)
124
-	 *        - string|false 'requesttoken' the requesttoken or false when not available
125
-	 * @param ISecureRandom $secureRandom
126
-	 * @param IConfig $config
127
-	 * @param CsrfTokenManager|null $csrfTokenManager
128
-	 * @param string $stream
129
-	 * @see http://www.php.net/manual/en/reserved.variables.php
130
-	 */
131
-	public function __construct(array $vars=array(),
132
-								ISecureRandom $secureRandom = null,
133
-								IConfig $config,
134
-								CsrfTokenManager $csrfTokenManager = null,
135
-								$stream = 'php://input') {
136
-		$this->inputStream = $stream;
137
-		$this->items['params'] = array();
138
-		$this->secureRandom = $secureRandom;
139
-		$this->config = $config;
140
-		$this->csrfTokenManager = $csrfTokenManager;
141
-
142
-		if(!array_key_exists('method', $vars)) {
143
-			$vars['method'] = 'GET';
144
-		}
145
-
146
-		foreach($this->allowedKeys as $name) {
147
-			$this->items[$name] = isset($vars[$name])
148
-				? $vars[$name]
149
-				: array();
150
-		}
151
-
152
-		$this->items['parameters'] = array_merge(
153
-			$this->items['get'],
154
-			$this->items['post'],
155
-			$this->items['urlParams'],
156
-			$this->items['params']
157
-		);
158
-
159
-	}
160
-	/**
161
-	 * @param array $parameters
162
-	 */
163
-	public function setUrlParameters(array $parameters) {
164
-		$this->items['urlParams'] = $parameters;
165
-		$this->items['parameters'] = array_merge(
166
-			$this->items['parameters'],
167
-			$this->items['urlParams']
168
-		);
169
-	}
170
-
171
-	/**
172
-	 * Countable method
173
-	 * @return int
174
-	 */
175
-	public function count() {
176
-		return count(array_keys($this->items['parameters']));
177
-	}
178
-
179
-	/**
180
-	* ArrayAccess methods
181
-	*
182
-	* Gives access to the combined GET, POST and urlParams arrays
183
-	*
184
-	* Examples:
185
-	*
186
-	* $var = $request['myvar'];
187
-	*
188
-	* or
189
-	*
190
-	* if(!isset($request['myvar']) {
191
-	* 	// Do something
192
-	* }
193
-	*
194
-	* $request['myvar'] = 'something'; // This throws an exception.
195
-	*
196
-	* @param string $offset The key to lookup
197
-	* @return boolean
198
-	*/
199
-	public function offsetExists($offset) {
200
-		return isset($this->items['parameters'][$offset]);
201
-	}
202
-
203
-	/**
204
-	* @see offsetExists
205
-	*/
206
-	public function offsetGet($offset) {
207
-		return isset($this->items['parameters'][$offset])
208
-			? $this->items['parameters'][$offset]
209
-			: null;
210
-	}
211
-
212
-	/**
213
-	* @see offsetExists
214
-	*/
215
-	public function offsetSet($offset, $value) {
216
-		throw new \RuntimeException('You cannot change the contents of the request object');
217
-	}
218
-
219
-	/**
220
-	* @see offsetExists
221
-	*/
222
-	public function offsetUnset($offset) {
223
-		throw new \RuntimeException('You cannot change the contents of the request object');
224
-	}
225
-
226
-	/**
227
-	 * Magic property accessors
228
-	 * @param string $name
229
-	 * @param mixed $value
230
-	 */
231
-	public function __set($name, $value) {
232
-		throw new \RuntimeException('You cannot change the contents of the request object');
233
-	}
234
-
235
-	/**
236
-	* Access request variables by method and name.
237
-	* Examples:
238
-	*
239
-	* $request->post['myvar']; // Only look for POST variables
240
-	* $request->myvar; or $request->{'myvar'}; or $request->{$myvar}
241
-	* Looks in the combined GET, POST and urlParams array.
242
-	*
243
-	* If you access e.g. ->post but the current HTTP request method
244
-	* is GET a \LogicException will be thrown.
245
-	*
246
-	* @param string $name The key to look for.
247
-	* @throws \LogicException
248
-	* @return mixed|null
249
-	*/
250
-	public function __get($name) {
251
-		switch($name) {
252
-			case 'put':
253
-			case 'patch':
254
-			case 'get':
255
-			case 'post':
256
-				if($this->method !== strtoupper($name)) {
257
-					throw new \LogicException(sprintf('%s cannot be accessed in a %s request.', $name, $this->method));
258
-				}
259
-				return $this->getContent();
260
-			case 'files':
261
-			case 'server':
262
-			case 'env':
263
-			case 'cookies':
264
-			case 'urlParams':
265
-			case 'method':
266
-				return isset($this->items[$name])
267
-					? $this->items[$name]
268
-					: null;
269
-			case 'parameters':
270
-			case 'params':
271
-				return $this->getContent();
272
-			default;
273
-				return isset($this[$name])
274
-					? $this[$name]
275
-					: null;
276
-		}
277
-	}
278
-
279
-	/**
280
-	 * @param string $name
281
-	 * @return bool
282
-	 */
283
-	public function __isset($name) {
284
-		if (in_array($name, $this->allowedKeys, true)) {
285
-			return true;
286
-		}
287
-		return isset($this->items['parameters'][$name]);
288
-	}
289
-
290
-	/**
291
-	 * @param string $id
292
-	 */
293
-	public function __unset($id) {
294
-		throw new \RuntimeException('You cannot change the contents of the request object');
295
-	}
296
-
297
-	/**
298
-	 * Returns the value for a specific http header.
299
-	 *
300
-	 * This method returns null if the header did not exist.
301
-	 *
302
-	 * @param string $name
303
-	 * @return string
304
-	 */
305
-	public function getHeader($name) {
306
-
307
-		$name = strtoupper(str_replace(array('-'),array('_'),$name));
308
-		if (isset($this->server['HTTP_' . $name])) {
309
-			return $this->server['HTTP_' . $name];
310
-		}
311
-
312
-		// There's a few headers that seem to end up in the top-level
313
-		// server array.
314
-		switch($name) {
315
-			case 'CONTENT_TYPE' :
316
-			case 'CONTENT_LENGTH' :
317
-				if (isset($this->server[$name])) {
318
-					return $this->server[$name];
319
-				}
320
-				break;
321
-
322
-		}
323
-
324
-		return null;
325
-	}
326
-
327
-	/**
328
-	 * Lets you access post and get parameters by the index
329
-	 * In case of json requests the encoded json body is accessed
330
-	 *
331
-	 * @param string $key the key which you want to access in the URL Parameter
332
-	 *                     placeholder, $_POST or $_GET array.
333
-	 *                     The priority how they're returned is the following:
334
-	 *                     1. URL parameters
335
-	 *                     2. POST parameters
336
-	 *                     3. GET parameters
337
-	 * @param mixed $default If the key is not found, this value will be returned
338
-	 * @return mixed the content of the array
339
-	 */
340
-	public function getParam($key, $default = null) {
341
-		return isset($this->parameters[$key])
342
-			? $this->parameters[$key]
343
-			: $default;
344
-	}
345
-
346
-	/**
347
-	 * Returns all params that were received, be it from the request
348
-	 * (as GET or POST) or throuh the URL by the route
349
-	 * @return array the array with all parameters
350
-	 */
351
-	public function getParams() {
352
-		return $this->parameters;
353
-	}
354
-
355
-	/**
356
-	 * Returns the method of the request
357
-	 * @return string the method of the request (POST, GET, etc)
358
-	 */
359
-	public function getMethod() {
360
-		return $this->method;
361
-	}
362
-
363
-	/**
364
-	 * Shortcut for accessing an uploaded file through the $_FILES array
365
-	 * @param string $key the key that will be taken from the $_FILES array
366
-	 * @return array the file in the $_FILES element
367
-	 */
368
-	public function getUploadedFile($key) {
369
-		return isset($this->files[$key]) ? $this->files[$key] : null;
370
-	}
371
-
372
-	/**
373
-	 * Shortcut for getting env variables
374
-	 * @param string $key the key that will be taken from the $_ENV array
375
-	 * @return array the value in the $_ENV element
376
-	 */
377
-	public function getEnv($key) {
378
-		return isset($this->env[$key]) ? $this->env[$key] : null;
379
-	}
380
-
381
-	/**
382
-	 * Shortcut for getting cookie variables
383
-	 * @param string $key the key that will be taken from the $_COOKIE array
384
-	 * @return string the value in the $_COOKIE element
385
-	 */
386
-	public function getCookie($key) {
387
-		return isset($this->cookies[$key]) ? $this->cookies[$key] : null;
388
-	}
389
-
390
-	/**
391
-	 * Returns the request body content.
392
-	 *
393
-	 * If the HTTP request method is PUT and the body
394
-	 * not application/x-www-form-urlencoded or application/json a stream
395
-	 * resource is returned, otherwise an array.
396
-	 *
397
-	 * @return array|string|resource The request body content or a resource to read the body stream.
398
-	 *
399
-	 * @throws \LogicException
400
-	 */
401
-	protected function getContent() {
402
-		// If the content can't be parsed into an array then return a stream resource.
403
-		if ($this->method === 'PUT'
404
-			&& strpos($this->getHeader('Content-Type'), 'application/x-www-form-urlencoded') === false
405
-			&& strpos($this->getHeader('Content-Type'), 'application/json') === false
406
-		) {
407
-			if ($this->content === false) {
408
-				throw new \LogicException(
409
-					'"put" can only be accessed once if not '
410
-					. 'application/x-www-form-urlencoded or application/json.'
411
-				);
412
-			}
413
-			$this->content = false;
414
-			return fopen($this->inputStream, 'rb');
415
-		} else {
416
-			$this->decodeContent();
417
-			return $this->items['parameters'];
418
-		}
419
-	}
420
-
421
-	/**
422
-	 * Attempt to decode the content and populate parameters
423
-	 */
424
-	protected function decodeContent() {
425
-		if ($this->contentDecoded) {
426
-			return;
427
-		}
428
-		$params = [];
429
-
430
-		// 'application/json' must be decoded manually.
431
-		if (strpos($this->getHeader('Content-Type'), 'application/json') !== false) {
432
-			$params = json_decode(file_get_contents($this->inputStream), true);
433
-			if(count($params) > 0) {
434
-				$this->items['params'] = $params;
435
-				if($this->method === 'POST') {
436
-					$this->items['post'] = $params;
437
-				}
438
-			}
439
-
440
-		// Handle application/x-www-form-urlencoded for methods other than GET
441
-		// or post correctly
442
-		} elseif($this->method !== 'GET'
443
-				&& $this->method !== 'POST'
444
-				&& strpos($this->getHeader('Content-Type'), 'application/x-www-form-urlencoded') !== false) {
445
-
446
-			parse_str(file_get_contents($this->inputStream), $params);
447
-			if(is_array($params)) {
448
-				$this->items['params'] = $params;
449
-			}
450
-		}
451
-
452
-		if (is_array($params)) {
453
-			$this->items['parameters'] = array_merge($this->items['parameters'], $params);
454
-		}
455
-		$this->contentDecoded = true;
456
-	}
457
-
458
-
459
-	/**
460
-	 * Checks if the CSRF check was correct
461
-	 * @return bool true if CSRF check passed
462
-	 */
463
-	public function passesCSRFCheck() {
464
-		if($this->csrfTokenManager === null) {
465
-			return false;
466
-		}
467
-
468
-		if(!$this->passesStrictCookieCheck()) {
469
-			return false;
470
-		}
471
-
472
-		if (isset($this->items['get']['requesttoken'])) {
473
-			$token = $this->items['get']['requesttoken'];
474
-		} elseif (isset($this->items['post']['requesttoken'])) {
475
-			$token = $this->items['post']['requesttoken'];
476
-		} elseif (isset($this->items['server']['HTTP_REQUESTTOKEN'])) {
477
-			$token = $this->items['server']['HTTP_REQUESTTOKEN'];
478
-		} else {
479
-			//no token found.
480
-			return false;
481
-		}
482
-		$token = new CsrfToken($token);
483
-
484
-		return $this->csrfTokenManager->isTokenValid($token);
485
-	}
486
-
487
-	/**
488
-	 * Whether the cookie checks are required
489
-	 *
490
-	 * @return bool
491
-	 */
492
-	private function cookieCheckRequired() {
493
-		if ($this->getHeader('OCS-APIREQUEST')) {
494
-			return false;
495
-		}
496
-		if($this->getCookie(session_name()) === null && $this->getCookie('nc_token') === null) {
497
-			return false;
498
-		}
499
-
500
-		return true;
501
-	}
502
-
503
-	/**
504
-	 * Wrapper around session_get_cookie_params
505
-	 *
506
-	 * @return array
507
-	 */
508
-	protected function getCookieParams() {
509
-		return session_get_cookie_params();
510
-	}
511
-
512
-	/**
513
-	 * Appends the __Host- prefix to the cookie if applicable
514
-	 *
515
-	 * @param string $name
516
-	 * @return string
517
-	 */
518
-	protected function getProtectedCookieName($name) {
519
-		$cookieParams = $this->getCookieParams();
520
-		$prefix = '';
521
-		if($cookieParams['secure'] === true && $cookieParams['path'] === '/') {
522
-			$prefix = '__Host-';
523
-		}
524
-
525
-		return $prefix.$name;
526
-	}
527
-
528
-	/**
529
-	 * Checks if the strict cookie has been sent with the request if the request
530
-	 * is including any cookies.
531
-	 *
532
-	 * @return bool
533
-	 * @since 9.1.0
534
-	 */
535
-	public function passesStrictCookieCheck() {
536
-		if(!$this->cookieCheckRequired()) {
537
-			return true;
538
-		}
539
-
540
-		$cookieName = $this->getProtectedCookieName('nc_sameSiteCookiestrict');
541
-		if($this->getCookie($cookieName) === 'true'
542
-			&& $this->passesLaxCookieCheck()) {
543
-			return true;
544
-		}
545
-		return false;
546
-	}
547
-
548
-	/**
549
-	 * Checks if the lax cookie has been sent with the request if the request
550
-	 * is including any cookies.
551
-	 *
552
-	 * @return bool
553
-	 * @since 9.1.0
554
-	 */
555
-	public function passesLaxCookieCheck() {
556
-		if(!$this->cookieCheckRequired()) {
557
-			return true;
558
-		}
559
-
560
-		$cookieName = $this->getProtectedCookieName('nc_sameSiteCookielax');
561
-		if($this->getCookie($cookieName) === 'true') {
562
-			return true;
563
-		}
564
-		return false;
565
-	}
566
-
567
-
568
-	/**
569
-	 * Returns an ID for the request, value is not guaranteed to be unique and is mostly meant for logging
570
-	 * If `mod_unique_id` is installed this value will be taken.
571
-	 * @return string
572
-	 */
573
-	public function getId() {
574
-		if(isset($this->server['UNIQUE_ID'])) {
575
-			return $this->server['UNIQUE_ID'];
576
-		}
577
-
578
-		if(empty($this->requestId)) {
579
-			$this->requestId = $this->secureRandom->generate(20);
580
-		}
581
-
582
-		return $this->requestId;
583
-	}
584
-
585
-	/**
586
-	 * Returns the remote address, if the connection came from a trusted proxy
587
-	 * and `forwarded_for_headers` has been configured then the IP address
588
-	 * specified in this header will be returned instead.
589
-	 * Do always use this instead of $_SERVER['REMOTE_ADDR']
590
-	 * @return string IP address
591
-	 */
592
-	public function getRemoteAddress() {
593
-		$remoteAddress = isset($this->server['REMOTE_ADDR']) ? $this->server['REMOTE_ADDR'] : '';
594
-		$trustedProxies = $this->config->getSystemValue('trusted_proxies', []);
595
-
596
-		if(is_array($trustedProxies) && in_array($remoteAddress, $trustedProxies)) {
597
-			$forwardedForHeaders = $this->config->getSystemValue('forwarded_for_headers', [
598
-				'HTTP_X_FORWARDED_FOR'
599
-				// only have one default, so we cannot ship an insecure product out of the box
600
-			]);
601
-
602
-			foreach($forwardedForHeaders as $header) {
603
-				if(isset($this->server[$header])) {
604
-					foreach(explode(',', $this->server[$header]) as $IP) {
605
-						$IP = trim($IP);
606
-						if (filter_var($IP, FILTER_VALIDATE_IP) !== false) {
607
-							return $IP;
608
-						}
609
-					}
610
-				}
611
-			}
612
-		}
613
-
614
-		return $remoteAddress;
615
-	}
616
-
617
-	/**
618
-	 * Check overwrite condition
619
-	 * @param string $type
620
-	 * @return bool
621
-	 */
622
-	private function isOverwriteCondition($type = '') {
623
-		$regex = '/' . $this->config->getSystemValue('overwritecondaddr', '')  . '/';
624
-		$remoteAddr = isset($this->server['REMOTE_ADDR']) ? $this->server['REMOTE_ADDR'] : '';
625
-		return $regex === '//' || preg_match($regex, $remoteAddr) === 1
626
-		|| $type !== 'protocol';
627
-	}
628
-
629
-	/**
630
-	 * Returns the server protocol. It respects one or more reverse proxies servers
631
-	 * and load balancers
632
-	 * @return string Server protocol (http or https)
633
-	 */
634
-	public function getServerProtocol() {
635
-		if($this->config->getSystemValue('overwriteprotocol') !== ''
636
-			&& $this->isOverwriteCondition('protocol')) {
637
-			return $this->config->getSystemValue('overwriteprotocol');
638
-		}
639
-
640
-		if (isset($this->server['HTTP_X_FORWARDED_PROTO'])) {
641
-			if (strpos($this->server['HTTP_X_FORWARDED_PROTO'], ',') !== false) {
642
-				$parts = explode(',', $this->server['HTTP_X_FORWARDED_PROTO']);
643
-				$proto = strtolower(trim($parts[0]));
644
-			} else {
645
-				$proto = strtolower($this->server['HTTP_X_FORWARDED_PROTO']);
646
-			}
647
-
648
-			// Verify that the protocol is always HTTP or HTTPS
649
-			// default to http if an invalid value is provided
650
-			return $proto === 'https' ? 'https' : 'http';
651
-		}
652
-
653
-		if (isset($this->server['HTTPS'])
654
-			&& $this->server['HTTPS'] !== null
655
-			&& $this->server['HTTPS'] !== 'off'
656
-			&& $this->server['HTTPS'] !== '') {
657
-			return 'https';
658
-		}
659
-
660
-		return 'http';
661
-	}
662
-
663
-	/**
664
-	 * Returns the used HTTP protocol.
665
-	 *
666
-	 * @return string HTTP protocol. HTTP/2, HTTP/1.1 or HTTP/1.0.
667
-	 */
668
-	public function getHttpProtocol() {
669
-		$claimedProtocol = strtoupper($this->server['SERVER_PROTOCOL']);
670
-
671
-		$validProtocols = [
672
-			'HTTP/1.0',
673
-			'HTTP/1.1',
674
-			'HTTP/2',
675
-		];
676
-
677
-		if(in_array($claimedProtocol, $validProtocols, true)) {
678
-			return $claimedProtocol;
679
-		}
680
-
681
-		return 'HTTP/1.1';
682
-	}
683
-
684
-	/**
685
-	 * Returns the request uri, even if the website uses one or more
686
-	 * reverse proxies
687
-	 * @return string
688
-	 */
689
-	public function getRequestUri() {
690
-		$uri = isset($this->server['REQUEST_URI']) ? $this->server['REQUEST_URI'] : '';
691
-		if($this->config->getSystemValue('overwritewebroot') !== '' && $this->isOverwriteCondition()) {
692
-			$uri = $this->getScriptName() . substr($uri, strlen($this->server['SCRIPT_NAME']));
693
-		}
694
-		return $uri;
695
-	}
696
-
697
-	/**
698
-	 * Get raw PathInfo from request (not urldecoded)
699
-	 * @throws \Exception
700
-	 * @return string Path info
701
-	 */
702
-	public function getRawPathInfo() {
703
-		$requestUri = isset($this->server['REQUEST_URI']) ? $this->server['REQUEST_URI'] : '';
704
-		// remove too many leading slashes - can be caused by reverse proxy configuration
705
-		if (strpos($requestUri, '/') === 0) {
706
-			$requestUri = '/' . ltrim($requestUri, '/');
707
-		}
708
-
709
-		$requestUri = preg_replace('%/{2,}%', '/', $requestUri);
710
-
711
-		// Remove the query string from REQUEST_URI
712
-		if ($pos = strpos($requestUri, '?')) {
713
-			$requestUri = substr($requestUri, 0, $pos);
714
-		}
715
-
716
-		$scriptName = $this->server['SCRIPT_NAME'];
717
-		$pathInfo = $requestUri;
718
-
719
-		// strip off the script name's dir and file name
720
-		// FIXME: Sabre does not really belong here
721
-		list($path, $name) = \Sabre\HTTP\URLUtil::splitPath($scriptName);
722
-		if (!empty($path)) {
723
-			if($path === $pathInfo || strpos($pathInfo, $path.'/') === 0) {
724
-				$pathInfo = substr($pathInfo, strlen($path));
725
-			} else {
726
-				throw new \Exception("The requested uri($requestUri) cannot be processed by the script '$scriptName')");
727
-			}
728
-		}
729
-		if (strpos($pathInfo, '/'.$name) === 0) {
730
-			$pathInfo = substr($pathInfo, strlen($name) + 1);
731
-		}
732
-		if (strpos($pathInfo, $name) === 0) {
733
-			$pathInfo = substr($pathInfo, strlen($name));
734
-		}
735
-		if($pathInfo === false || $pathInfo === '/'){
736
-			return '';
737
-		} else {
738
-			return $pathInfo;
739
-		}
740
-	}
741
-
742
-	/**
743
-	 * Get PathInfo from request
744
-	 * @throws \Exception
745
-	 * @return string|false Path info or false when not found
746
-	 */
747
-	public function getPathInfo() {
748
-		$pathInfo = $this->getRawPathInfo();
749
-		// following is taken from \Sabre\HTTP\URLUtil::decodePathSegment
750
-		$pathInfo = rawurldecode($pathInfo);
751
-		$encoding = mb_detect_encoding($pathInfo, ['UTF-8', 'ISO-8859-1']);
752
-
753
-		switch($encoding) {
754
-			case 'ISO-8859-1' :
755
-				$pathInfo = utf8_encode($pathInfo);
756
-		}
757
-		// end copy
758
-
759
-		return $pathInfo;
760
-	}
761
-
762
-	/**
763
-	 * Returns the script name, even if the website uses one or more
764
-	 * reverse proxies
765
-	 * @return string the script name
766
-	 */
767
-	public function getScriptName() {
768
-		$name = $this->server['SCRIPT_NAME'];
769
-		$overwriteWebRoot =  $this->config->getSystemValue('overwritewebroot');
770
-		if ($overwriteWebRoot !== '' && $this->isOverwriteCondition()) {
771
-			// FIXME: This code is untestable due to __DIR__, also that hardcoded path is really dangerous
772
-			$serverRoot = str_replace('\\', '/', substr(__DIR__, 0, -strlen('lib/private/appframework/http/')));
773
-			$suburi = str_replace('\\', '/', substr(realpath($this->server['SCRIPT_FILENAME']), strlen($serverRoot)));
774
-			$name = '/' . ltrim($overwriteWebRoot . $suburi, '/');
775
-		}
776
-		return $name;
777
-	}
778
-
779
-	/**
780
-	 * Checks whether the user agent matches a given regex
781
-	 * @param array $agent array of agent names
782
-	 * @return bool true if at least one of the given agent matches, false otherwise
783
-	 */
784
-	public function isUserAgent(array $agent) {
785
-		if (!isset($this->server['HTTP_USER_AGENT'])) {
786
-			return false;
787
-		}
788
-		foreach ($agent as $regex) {
789
-			if (preg_match($regex, $this->server['HTTP_USER_AGENT'])) {
790
-				return true;
791
-			}
792
-		}
793
-		return false;
794
-	}
795
-
796
-	/**
797
-	 * Returns the unverified server host from the headers without checking
798
-	 * whether it is a trusted domain
799
-	 * @return string Server host
800
-	 */
801
-	public function getInsecureServerHost() {
802
-		$host = 'localhost';
803
-		if (isset($this->server['HTTP_X_FORWARDED_HOST'])) {
804
-			if (strpos($this->server['HTTP_X_FORWARDED_HOST'], ',') !== false) {
805
-				$parts = explode(',', $this->server['HTTP_X_FORWARDED_HOST']);
806
-				$host = trim(current($parts));
807
-			} else {
808
-				$host = $this->server['HTTP_X_FORWARDED_HOST'];
809
-			}
810
-		} else {
811
-			if (isset($this->server['HTTP_HOST'])) {
812
-				$host = $this->server['HTTP_HOST'];
813
-			} else if (isset($this->server['SERVER_NAME'])) {
814
-				$host = $this->server['SERVER_NAME'];
815
-			}
816
-		}
817
-		return $host;
818
-	}
819
-
820
-
821
-	/**
822
-	 * Returns the server host from the headers, or the first configured
823
-	 * trusted domain if the host isn't in the trusted list
824
-	 * @return string Server host
825
-	 */
826
-	public function getServerHost() {
827
-		// overwritehost is always trusted
828
-		$host = $this->getOverwriteHost();
829
-		if ($host !== null) {
830
-			return $host;
831
-		}
832
-
833
-		// get the host from the headers
834
-		$host = $this->getInsecureServerHost();
835
-
836
-		// Verify that the host is a trusted domain if the trusted domains
837
-		// are defined
838
-		// If no trusted domain is provided the first trusted domain is returned
839
-		$trustedDomainHelper = new TrustedDomainHelper($this->config);
840
-		if ($trustedDomainHelper->isTrustedDomain($host)) {
841
-			return $host;
842
-		} else {
843
-			$trustedList = $this->config->getSystemValue('trusted_domains', []);
844
-			if(!empty($trustedList)) {
845
-				return $trustedList[0];
846
-			} else {
847
-				return '';
848
-			}
849
-		}
850
-	}
851
-
852
-	/**
853
-	 * Returns the overwritehost setting from the config if set and
854
-	 * if the overwrite condition is met
855
-	 * @return string|null overwritehost value or null if not defined or the defined condition
856
-	 * isn't met
857
-	 */
858
-	private function getOverwriteHost() {
859
-		if($this->config->getSystemValue('overwritehost') !== '' && $this->isOverwriteCondition()) {
860
-			return $this->config->getSystemValue('overwritehost');
861
-		}
862
-		return null;
863
-	}
58
+    const USER_AGENT_IE = '/(MSIE)|(Trident)/';
59
+    // Microsoft Edge User Agent from https://msdn.microsoft.com/en-us/library/hh869301(v=vs.85).aspx
60
+    const USER_AGENT_MS_EDGE = '/^Mozilla\/5\.0 \([^)]+\) AppleWebKit\/[0-9.]+ \(KHTML, like Gecko\) Chrome\/[0-9.]+ (Mobile Safari|Safari)\/[0-9.]+ Edge\/[0-9.]+$/';
61
+    // Firefox User Agent from https://developer.mozilla.org/en-US/docs/Web/HTTP/Gecko_user_agent_string_reference
62
+    const USER_AGENT_FIREFOX = '/^Mozilla\/5\.0 \([^)]+\) Gecko\/[0-9.]+ Firefox\/[0-9.]+$/';
63
+    // Chrome User Agent from https://developer.chrome.com/multidevice/user-agent
64
+    const USER_AGENT_CHROME = '/^Mozilla\/5\.0 \([^)]+\) AppleWebKit\/[0-9.]+ \(KHTML, like Gecko\)( Ubuntu Chromium\/[0-9.]+|) Chrome\/[0-9.]+ (Mobile Safari|Safari)\/[0-9.]+$/';
65
+    // Safari User Agent from http://www.useragentstring.com/pages/Safari/
66
+    const USER_AGENT_SAFARI = '/^Mozilla\/5\.0 \([^)]+\) AppleWebKit\/[0-9.]+ \(KHTML, like Gecko\) Version\/[0-9.]+ Safari\/[0-9.A-Z]+$/';
67
+    // Android Chrome user agent: https://developers.google.com/chrome/mobile/docs/user-agent
68
+    const USER_AGENT_ANDROID_MOBILE_CHROME = '#Android.*Chrome/[.0-9]*#';
69
+    const USER_AGENT_FREEBOX = '#^Mozilla/5\.0$#';
70
+    const REGEX_LOCALHOST = '/^(127\.0\.0\.1|localhost)$/';
71
+
72
+    /**
73
+     * @deprecated use \OCP\IRequest::USER_AGENT_CLIENT_IOS instead
74
+     */
75
+    const USER_AGENT_OWNCLOUD_IOS = '/^Mozilla\/5\.0 \(iOS\) (ownCloud|Nextcloud)\-iOS.*$/';
76
+    /**
77
+     * @deprecated use \OCP\IRequest::USER_AGENT_CLIENT_ANDROID instead
78
+     */
79
+    const USER_AGENT_OWNCLOUD_ANDROID = '/^Mozilla\/5\.0 \(Android\) ownCloud\-android.*$/';
80
+    /**
81
+     * @deprecated use \OCP\IRequest::USER_AGENT_CLIENT_DESKTOP instead
82
+     */
83
+    const USER_AGENT_OWNCLOUD_DESKTOP = '/^Mozilla\/5\.0 \([A-Za-z ]+\) (mirall|csyncoC)\/.*$/';
84
+
85
+    protected $inputStream;
86
+    protected $content;
87
+    protected $items = array();
88
+    protected $allowedKeys = array(
89
+        'get',
90
+        'post',
91
+        'files',
92
+        'server',
93
+        'env',
94
+        'cookies',
95
+        'urlParams',
96
+        'parameters',
97
+        'method',
98
+        'requesttoken',
99
+    );
100
+    /** @var ISecureRandom */
101
+    protected $secureRandom;
102
+    /** @var IConfig */
103
+    protected $config;
104
+    /** @var string */
105
+    protected $requestId = '';
106
+    /** @var ICrypto */
107
+    protected $crypto;
108
+    /** @var CsrfTokenManager|null */
109
+    protected $csrfTokenManager;
110
+
111
+    /** @var bool */
112
+    protected $contentDecoded = false;
113
+
114
+    /**
115
+     * @param array $vars An associative array with the following optional values:
116
+     *        - array 'urlParams' the parameters which were matched from the URL
117
+     *        - array 'get' the $_GET array
118
+     *        - array|string 'post' the $_POST array or JSON string
119
+     *        - array 'files' the $_FILES array
120
+     *        - array 'server' the $_SERVER array
121
+     *        - array 'env' the $_ENV array
122
+     *        - array 'cookies' the $_COOKIE array
123
+     *        - string 'method' the request method (GET, POST etc)
124
+     *        - string|false 'requesttoken' the requesttoken or false when not available
125
+     * @param ISecureRandom $secureRandom
126
+     * @param IConfig $config
127
+     * @param CsrfTokenManager|null $csrfTokenManager
128
+     * @param string $stream
129
+     * @see http://www.php.net/manual/en/reserved.variables.php
130
+     */
131
+    public function __construct(array $vars=array(),
132
+                                ISecureRandom $secureRandom = null,
133
+                                IConfig $config,
134
+                                CsrfTokenManager $csrfTokenManager = null,
135
+                                $stream = 'php://input') {
136
+        $this->inputStream = $stream;
137
+        $this->items['params'] = array();
138
+        $this->secureRandom = $secureRandom;
139
+        $this->config = $config;
140
+        $this->csrfTokenManager = $csrfTokenManager;
141
+
142
+        if(!array_key_exists('method', $vars)) {
143
+            $vars['method'] = 'GET';
144
+        }
145
+
146
+        foreach($this->allowedKeys as $name) {
147
+            $this->items[$name] = isset($vars[$name])
148
+                ? $vars[$name]
149
+                : array();
150
+        }
151
+
152
+        $this->items['parameters'] = array_merge(
153
+            $this->items['get'],
154
+            $this->items['post'],
155
+            $this->items['urlParams'],
156
+            $this->items['params']
157
+        );
158
+
159
+    }
160
+    /**
161
+     * @param array $parameters
162
+     */
163
+    public function setUrlParameters(array $parameters) {
164
+        $this->items['urlParams'] = $parameters;
165
+        $this->items['parameters'] = array_merge(
166
+            $this->items['parameters'],
167
+            $this->items['urlParams']
168
+        );
169
+    }
170
+
171
+    /**
172
+     * Countable method
173
+     * @return int
174
+     */
175
+    public function count() {
176
+        return count(array_keys($this->items['parameters']));
177
+    }
178
+
179
+    /**
180
+     * ArrayAccess methods
181
+     *
182
+     * Gives access to the combined GET, POST and urlParams arrays
183
+     *
184
+     * Examples:
185
+     *
186
+     * $var = $request['myvar'];
187
+     *
188
+     * or
189
+     *
190
+     * if(!isset($request['myvar']) {
191
+     * 	// Do something
192
+     * }
193
+     *
194
+     * $request['myvar'] = 'something'; // This throws an exception.
195
+     *
196
+     * @param string $offset The key to lookup
197
+     * @return boolean
198
+     */
199
+    public function offsetExists($offset) {
200
+        return isset($this->items['parameters'][$offset]);
201
+    }
202
+
203
+    /**
204
+     * @see offsetExists
205
+     */
206
+    public function offsetGet($offset) {
207
+        return isset($this->items['parameters'][$offset])
208
+            ? $this->items['parameters'][$offset]
209
+            : null;
210
+    }
211
+
212
+    /**
213
+     * @see offsetExists
214
+     */
215
+    public function offsetSet($offset, $value) {
216
+        throw new \RuntimeException('You cannot change the contents of the request object');
217
+    }
218
+
219
+    /**
220
+     * @see offsetExists
221
+     */
222
+    public function offsetUnset($offset) {
223
+        throw new \RuntimeException('You cannot change the contents of the request object');
224
+    }
225
+
226
+    /**
227
+     * Magic property accessors
228
+     * @param string $name
229
+     * @param mixed $value
230
+     */
231
+    public function __set($name, $value) {
232
+        throw new \RuntimeException('You cannot change the contents of the request object');
233
+    }
234
+
235
+    /**
236
+     * Access request variables by method and name.
237
+     * Examples:
238
+     *
239
+     * $request->post['myvar']; // Only look for POST variables
240
+     * $request->myvar; or $request->{'myvar'}; or $request->{$myvar}
241
+     * Looks in the combined GET, POST and urlParams array.
242
+     *
243
+     * If you access e.g. ->post but the current HTTP request method
244
+     * is GET a \LogicException will be thrown.
245
+     *
246
+     * @param string $name The key to look for.
247
+     * @throws \LogicException
248
+     * @return mixed|null
249
+     */
250
+    public function __get($name) {
251
+        switch($name) {
252
+            case 'put':
253
+            case 'patch':
254
+            case 'get':
255
+            case 'post':
256
+                if($this->method !== strtoupper($name)) {
257
+                    throw new \LogicException(sprintf('%s cannot be accessed in a %s request.', $name, $this->method));
258
+                }
259
+                return $this->getContent();
260
+            case 'files':
261
+            case 'server':
262
+            case 'env':
263
+            case 'cookies':
264
+            case 'urlParams':
265
+            case 'method':
266
+                return isset($this->items[$name])
267
+                    ? $this->items[$name]
268
+                    : null;
269
+            case 'parameters':
270
+            case 'params':
271
+                return $this->getContent();
272
+            default;
273
+                return isset($this[$name])
274
+                    ? $this[$name]
275
+                    : null;
276
+        }
277
+    }
278
+
279
+    /**
280
+     * @param string $name
281
+     * @return bool
282
+     */
283
+    public function __isset($name) {
284
+        if (in_array($name, $this->allowedKeys, true)) {
285
+            return true;
286
+        }
287
+        return isset($this->items['parameters'][$name]);
288
+    }
289
+
290
+    /**
291
+     * @param string $id
292
+     */
293
+    public function __unset($id) {
294
+        throw new \RuntimeException('You cannot change the contents of the request object');
295
+    }
296
+
297
+    /**
298
+     * Returns the value for a specific http header.
299
+     *
300
+     * This method returns null if the header did not exist.
301
+     *
302
+     * @param string $name
303
+     * @return string
304
+     */
305
+    public function getHeader($name) {
306
+
307
+        $name = strtoupper(str_replace(array('-'),array('_'),$name));
308
+        if (isset($this->server['HTTP_' . $name])) {
309
+            return $this->server['HTTP_' . $name];
310
+        }
311
+
312
+        // There's a few headers that seem to end up in the top-level
313
+        // server array.
314
+        switch($name) {
315
+            case 'CONTENT_TYPE' :
316
+            case 'CONTENT_LENGTH' :
317
+                if (isset($this->server[$name])) {
318
+                    return $this->server[$name];
319
+                }
320
+                break;
321
+
322
+        }
323
+
324
+        return null;
325
+    }
326
+
327
+    /**
328
+     * Lets you access post and get parameters by the index
329
+     * In case of json requests the encoded json body is accessed
330
+     *
331
+     * @param string $key the key which you want to access in the URL Parameter
332
+     *                     placeholder, $_POST or $_GET array.
333
+     *                     The priority how they're returned is the following:
334
+     *                     1. URL parameters
335
+     *                     2. POST parameters
336
+     *                     3. GET parameters
337
+     * @param mixed $default If the key is not found, this value will be returned
338
+     * @return mixed the content of the array
339
+     */
340
+    public function getParam($key, $default = null) {
341
+        return isset($this->parameters[$key])
342
+            ? $this->parameters[$key]
343
+            : $default;
344
+    }
345
+
346
+    /**
347
+     * Returns all params that were received, be it from the request
348
+     * (as GET or POST) or throuh the URL by the route
349
+     * @return array the array with all parameters
350
+     */
351
+    public function getParams() {
352
+        return $this->parameters;
353
+    }
354
+
355
+    /**
356
+     * Returns the method of the request
357
+     * @return string the method of the request (POST, GET, etc)
358
+     */
359
+    public function getMethod() {
360
+        return $this->method;
361
+    }
362
+
363
+    /**
364
+     * Shortcut for accessing an uploaded file through the $_FILES array
365
+     * @param string $key the key that will be taken from the $_FILES array
366
+     * @return array the file in the $_FILES element
367
+     */
368
+    public function getUploadedFile($key) {
369
+        return isset($this->files[$key]) ? $this->files[$key] : null;
370
+    }
371
+
372
+    /**
373
+     * Shortcut for getting env variables
374
+     * @param string $key the key that will be taken from the $_ENV array
375
+     * @return array the value in the $_ENV element
376
+     */
377
+    public function getEnv($key) {
378
+        return isset($this->env[$key]) ? $this->env[$key] : null;
379
+    }
380
+
381
+    /**
382
+     * Shortcut for getting cookie variables
383
+     * @param string $key the key that will be taken from the $_COOKIE array
384
+     * @return string the value in the $_COOKIE element
385
+     */
386
+    public function getCookie($key) {
387
+        return isset($this->cookies[$key]) ? $this->cookies[$key] : null;
388
+    }
389
+
390
+    /**
391
+     * Returns the request body content.
392
+     *
393
+     * If the HTTP request method is PUT and the body
394
+     * not application/x-www-form-urlencoded or application/json a stream
395
+     * resource is returned, otherwise an array.
396
+     *
397
+     * @return array|string|resource The request body content or a resource to read the body stream.
398
+     *
399
+     * @throws \LogicException
400
+     */
401
+    protected function getContent() {
402
+        // If the content can't be parsed into an array then return a stream resource.
403
+        if ($this->method === 'PUT'
404
+            && strpos($this->getHeader('Content-Type'), 'application/x-www-form-urlencoded') === false
405
+            && strpos($this->getHeader('Content-Type'), 'application/json') === false
406
+        ) {
407
+            if ($this->content === false) {
408
+                throw new \LogicException(
409
+                    '"put" can only be accessed once if not '
410
+                    . 'application/x-www-form-urlencoded or application/json.'
411
+                );
412
+            }
413
+            $this->content = false;
414
+            return fopen($this->inputStream, 'rb');
415
+        } else {
416
+            $this->decodeContent();
417
+            return $this->items['parameters'];
418
+        }
419
+    }
420
+
421
+    /**
422
+     * Attempt to decode the content and populate parameters
423
+     */
424
+    protected function decodeContent() {
425
+        if ($this->contentDecoded) {
426
+            return;
427
+        }
428
+        $params = [];
429
+
430
+        // 'application/json' must be decoded manually.
431
+        if (strpos($this->getHeader('Content-Type'), 'application/json') !== false) {
432
+            $params = json_decode(file_get_contents($this->inputStream), true);
433
+            if(count($params) > 0) {
434
+                $this->items['params'] = $params;
435
+                if($this->method === 'POST') {
436
+                    $this->items['post'] = $params;
437
+                }
438
+            }
439
+
440
+        // Handle application/x-www-form-urlencoded for methods other than GET
441
+        // or post correctly
442
+        } elseif($this->method !== 'GET'
443
+                && $this->method !== 'POST'
444
+                && strpos($this->getHeader('Content-Type'), 'application/x-www-form-urlencoded') !== false) {
445
+
446
+            parse_str(file_get_contents($this->inputStream), $params);
447
+            if(is_array($params)) {
448
+                $this->items['params'] = $params;
449
+            }
450
+        }
451
+
452
+        if (is_array($params)) {
453
+            $this->items['parameters'] = array_merge($this->items['parameters'], $params);
454
+        }
455
+        $this->contentDecoded = true;
456
+    }
457
+
458
+
459
+    /**
460
+     * Checks if the CSRF check was correct
461
+     * @return bool true if CSRF check passed
462
+     */
463
+    public function passesCSRFCheck() {
464
+        if($this->csrfTokenManager === null) {
465
+            return false;
466
+        }
467
+
468
+        if(!$this->passesStrictCookieCheck()) {
469
+            return false;
470
+        }
471
+
472
+        if (isset($this->items['get']['requesttoken'])) {
473
+            $token = $this->items['get']['requesttoken'];
474
+        } elseif (isset($this->items['post']['requesttoken'])) {
475
+            $token = $this->items['post']['requesttoken'];
476
+        } elseif (isset($this->items['server']['HTTP_REQUESTTOKEN'])) {
477
+            $token = $this->items['server']['HTTP_REQUESTTOKEN'];
478
+        } else {
479
+            //no token found.
480
+            return false;
481
+        }
482
+        $token = new CsrfToken($token);
483
+
484
+        return $this->csrfTokenManager->isTokenValid($token);
485
+    }
486
+
487
+    /**
488
+     * Whether the cookie checks are required
489
+     *
490
+     * @return bool
491
+     */
492
+    private function cookieCheckRequired() {
493
+        if ($this->getHeader('OCS-APIREQUEST')) {
494
+            return false;
495
+        }
496
+        if($this->getCookie(session_name()) === null && $this->getCookie('nc_token') === null) {
497
+            return false;
498
+        }
499
+
500
+        return true;
501
+    }
502
+
503
+    /**
504
+     * Wrapper around session_get_cookie_params
505
+     *
506
+     * @return array
507
+     */
508
+    protected function getCookieParams() {
509
+        return session_get_cookie_params();
510
+    }
511
+
512
+    /**
513
+     * Appends the __Host- prefix to the cookie if applicable
514
+     *
515
+     * @param string $name
516
+     * @return string
517
+     */
518
+    protected function getProtectedCookieName($name) {
519
+        $cookieParams = $this->getCookieParams();
520
+        $prefix = '';
521
+        if($cookieParams['secure'] === true && $cookieParams['path'] === '/') {
522
+            $prefix = '__Host-';
523
+        }
524
+
525
+        return $prefix.$name;
526
+    }
527
+
528
+    /**
529
+     * Checks if the strict cookie has been sent with the request if the request
530
+     * is including any cookies.
531
+     *
532
+     * @return bool
533
+     * @since 9.1.0
534
+     */
535
+    public function passesStrictCookieCheck() {
536
+        if(!$this->cookieCheckRequired()) {
537
+            return true;
538
+        }
539
+
540
+        $cookieName = $this->getProtectedCookieName('nc_sameSiteCookiestrict');
541
+        if($this->getCookie($cookieName) === 'true'
542
+            && $this->passesLaxCookieCheck()) {
543
+            return true;
544
+        }
545
+        return false;
546
+    }
547
+
548
+    /**
549
+     * Checks if the lax cookie has been sent with the request if the request
550
+     * is including any cookies.
551
+     *
552
+     * @return bool
553
+     * @since 9.1.0
554
+     */
555
+    public function passesLaxCookieCheck() {
556
+        if(!$this->cookieCheckRequired()) {
557
+            return true;
558
+        }
559
+
560
+        $cookieName = $this->getProtectedCookieName('nc_sameSiteCookielax');
561
+        if($this->getCookie($cookieName) === 'true') {
562
+            return true;
563
+        }
564
+        return false;
565
+    }
566
+
567
+
568
+    /**
569
+     * Returns an ID for the request, value is not guaranteed to be unique and is mostly meant for logging
570
+     * If `mod_unique_id` is installed this value will be taken.
571
+     * @return string
572
+     */
573
+    public function getId() {
574
+        if(isset($this->server['UNIQUE_ID'])) {
575
+            return $this->server['UNIQUE_ID'];
576
+        }
577
+
578
+        if(empty($this->requestId)) {
579
+            $this->requestId = $this->secureRandom->generate(20);
580
+        }
581
+
582
+        return $this->requestId;
583
+    }
584
+
585
+    /**
586
+     * Returns the remote address, if the connection came from a trusted proxy
587
+     * and `forwarded_for_headers` has been configured then the IP address
588
+     * specified in this header will be returned instead.
589
+     * Do always use this instead of $_SERVER['REMOTE_ADDR']
590
+     * @return string IP address
591
+     */
592
+    public function getRemoteAddress() {
593
+        $remoteAddress = isset($this->server['REMOTE_ADDR']) ? $this->server['REMOTE_ADDR'] : '';
594
+        $trustedProxies = $this->config->getSystemValue('trusted_proxies', []);
595
+
596
+        if(is_array($trustedProxies) && in_array($remoteAddress, $trustedProxies)) {
597
+            $forwardedForHeaders = $this->config->getSystemValue('forwarded_for_headers', [
598
+                'HTTP_X_FORWARDED_FOR'
599
+                // only have one default, so we cannot ship an insecure product out of the box
600
+            ]);
601
+
602
+            foreach($forwardedForHeaders as $header) {
603
+                if(isset($this->server[$header])) {
604
+                    foreach(explode(',', $this->server[$header]) as $IP) {
605
+                        $IP = trim($IP);
606
+                        if (filter_var($IP, FILTER_VALIDATE_IP) !== false) {
607
+                            return $IP;
608
+                        }
609
+                    }
610
+                }
611
+            }
612
+        }
613
+
614
+        return $remoteAddress;
615
+    }
616
+
617
+    /**
618
+     * Check overwrite condition
619
+     * @param string $type
620
+     * @return bool
621
+     */
622
+    private function isOverwriteCondition($type = '') {
623
+        $regex = '/' . $this->config->getSystemValue('overwritecondaddr', '')  . '/';
624
+        $remoteAddr = isset($this->server['REMOTE_ADDR']) ? $this->server['REMOTE_ADDR'] : '';
625
+        return $regex === '//' || preg_match($regex, $remoteAddr) === 1
626
+        || $type !== 'protocol';
627
+    }
628
+
629
+    /**
630
+     * Returns the server protocol. It respects one or more reverse proxies servers
631
+     * and load balancers
632
+     * @return string Server protocol (http or https)
633
+     */
634
+    public function getServerProtocol() {
635
+        if($this->config->getSystemValue('overwriteprotocol') !== ''
636
+            && $this->isOverwriteCondition('protocol')) {
637
+            return $this->config->getSystemValue('overwriteprotocol');
638
+        }
639
+
640
+        if (isset($this->server['HTTP_X_FORWARDED_PROTO'])) {
641
+            if (strpos($this->server['HTTP_X_FORWARDED_PROTO'], ',') !== false) {
642
+                $parts = explode(',', $this->server['HTTP_X_FORWARDED_PROTO']);
643
+                $proto = strtolower(trim($parts[0]));
644
+            } else {
645
+                $proto = strtolower($this->server['HTTP_X_FORWARDED_PROTO']);
646
+            }
647
+
648
+            // Verify that the protocol is always HTTP or HTTPS
649
+            // default to http if an invalid value is provided
650
+            return $proto === 'https' ? 'https' : 'http';
651
+        }
652
+
653
+        if (isset($this->server['HTTPS'])
654
+            && $this->server['HTTPS'] !== null
655
+            && $this->server['HTTPS'] !== 'off'
656
+            && $this->server['HTTPS'] !== '') {
657
+            return 'https';
658
+        }
659
+
660
+        return 'http';
661
+    }
662
+
663
+    /**
664
+     * Returns the used HTTP protocol.
665
+     *
666
+     * @return string HTTP protocol. HTTP/2, HTTP/1.1 or HTTP/1.0.
667
+     */
668
+    public function getHttpProtocol() {
669
+        $claimedProtocol = strtoupper($this->server['SERVER_PROTOCOL']);
670
+
671
+        $validProtocols = [
672
+            'HTTP/1.0',
673
+            'HTTP/1.1',
674
+            'HTTP/2',
675
+        ];
676
+
677
+        if(in_array($claimedProtocol, $validProtocols, true)) {
678
+            return $claimedProtocol;
679
+        }
680
+
681
+        return 'HTTP/1.1';
682
+    }
683
+
684
+    /**
685
+     * Returns the request uri, even if the website uses one or more
686
+     * reverse proxies
687
+     * @return string
688
+     */
689
+    public function getRequestUri() {
690
+        $uri = isset($this->server['REQUEST_URI']) ? $this->server['REQUEST_URI'] : '';
691
+        if($this->config->getSystemValue('overwritewebroot') !== '' && $this->isOverwriteCondition()) {
692
+            $uri = $this->getScriptName() . substr($uri, strlen($this->server['SCRIPT_NAME']));
693
+        }
694
+        return $uri;
695
+    }
696
+
697
+    /**
698
+     * Get raw PathInfo from request (not urldecoded)
699
+     * @throws \Exception
700
+     * @return string Path info
701
+     */
702
+    public function getRawPathInfo() {
703
+        $requestUri = isset($this->server['REQUEST_URI']) ? $this->server['REQUEST_URI'] : '';
704
+        // remove too many leading slashes - can be caused by reverse proxy configuration
705
+        if (strpos($requestUri, '/') === 0) {
706
+            $requestUri = '/' . ltrim($requestUri, '/');
707
+        }
708
+
709
+        $requestUri = preg_replace('%/{2,}%', '/', $requestUri);
710
+
711
+        // Remove the query string from REQUEST_URI
712
+        if ($pos = strpos($requestUri, '?')) {
713
+            $requestUri = substr($requestUri, 0, $pos);
714
+        }
715
+
716
+        $scriptName = $this->server['SCRIPT_NAME'];
717
+        $pathInfo = $requestUri;
718
+
719
+        // strip off the script name's dir and file name
720
+        // FIXME: Sabre does not really belong here
721
+        list($path, $name) = \Sabre\HTTP\URLUtil::splitPath($scriptName);
722
+        if (!empty($path)) {
723
+            if($path === $pathInfo || strpos($pathInfo, $path.'/') === 0) {
724
+                $pathInfo = substr($pathInfo, strlen($path));
725
+            } else {
726
+                throw new \Exception("The requested uri($requestUri) cannot be processed by the script '$scriptName')");
727
+            }
728
+        }
729
+        if (strpos($pathInfo, '/'.$name) === 0) {
730
+            $pathInfo = substr($pathInfo, strlen($name) + 1);
731
+        }
732
+        if (strpos($pathInfo, $name) === 0) {
733
+            $pathInfo = substr($pathInfo, strlen($name));
734
+        }
735
+        if($pathInfo === false || $pathInfo === '/'){
736
+            return '';
737
+        } else {
738
+            return $pathInfo;
739
+        }
740
+    }
741
+
742
+    /**
743
+     * Get PathInfo from request
744
+     * @throws \Exception
745
+     * @return string|false Path info or false when not found
746
+     */
747
+    public function getPathInfo() {
748
+        $pathInfo = $this->getRawPathInfo();
749
+        // following is taken from \Sabre\HTTP\URLUtil::decodePathSegment
750
+        $pathInfo = rawurldecode($pathInfo);
751
+        $encoding = mb_detect_encoding($pathInfo, ['UTF-8', 'ISO-8859-1']);
752
+
753
+        switch($encoding) {
754
+            case 'ISO-8859-1' :
755
+                $pathInfo = utf8_encode($pathInfo);
756
+        }
757
+        // end copy
758
+
759
+        return $pathInfo;
760
+    }
761
+
762
+    /**
763
+     * Returns the script name, even if the website uses one or more
764
+     * reverse proxies
765
+     * @return string the script name
766
+     */
767
+    public function getScriptName() {
768
+        $name = $this->server['SCRIPT_NAME'];
769
+        $overwriteWebRoot =  $this->config->getSystemValue('overwritewebroot');
770
+        if ($overwriteWebRoot !== '' && $this->isOverwriteCondition()) {
771
+            // FIXME: This code is untestable due to __DIR__, also that hardcoded path is really dangerous
772
+            $serverRoot = str_replace('\\', '/', substr(__DIR__, 0, -strlen('lib/private/appframework/http/')));
773
+            $suburi = str_replace('\\', '/', substr(realpath($this->server['SCRIPT_FILENAME']), strlen($serverRoot)));
774
+            $name = '/' . ltrim($overwriteWebRoot . $suburi, '/');
775
+        }
776
+        return $name;
777
+    }
778
+
779
+    /**
780
+     * Checks whether the user agent matches a given regex
781
+     * @param array $agent array of agent names
782
+     * @return bool true if at least one of the given agent matches, false otherwise
783
+     */
784
+    public function isUserAgent(array $agent) {
785
+        if (!isset($this->server['HTTP_USER_AGENT'])) {
786
+            return false;
787
+        }
788
+        foreach ($agent as $regex) {
789
+            if (preg_match($regex, $this->server['HTTP_USER_AGENT'])) {
790
+                return true;
791
+            }
792
+        }
793
+        return false;
794
+    }
795
+
796
+    /**
797
+     * Returns the unverified server host from the headers without checking
798
+     * whether it is a trusted domain
799
+     * @return string Server host
800
+     */
801
+    public function getInsecureServerHost() {
802
+        $host = 'localhost';
803
+        if (isset($this->server['HTTP_X_FORWARDED_HOST'])) {
804
+            if (strpos($this->server['HTTP_X_FORWARDED_HOST'], ',') !== false) {
805
+                $parts = explode(',', $this->server['HTTP_X_FORWARDED_HOST']);
806
+                $host = trim(current($parts));
807
+            } else {
808
+                $host = $this->server['HTTP_X_FORWARDED_HOST'];
809
+            }
810
+        } else {
811
+            if (isset($this->server['HTTP_HOST'])) {
812
+                $host = $this->server['HTTP_HOST'];
813
+            } else if (isset($this->server['SERVER_NAME'])) {
814
+                $host = $this->server['SERVER_NAME'];
815
+            }
816
+        }
817
+        return $host;
818
+    }
819
+
820
+
821
+    /**
822
+     * Returns the server host from the headers, or the first configured
823
+     * trusted domain if the host isn't in the trusted list
824
+     * @return string Server host
825
+     */
826
+    public function getServerHost() {
827
+        // overwritehost is always trusted
828
+        $host = $this->getOverwriteHost();
829
+        if ($host !== null) {
830
+            return $host;
831
+        }
832
+
833
+        // get the host from the headers
834
+        $host = $this->getInsecureServerHost();
835
+
836
+        // Verify that the host is a trusted domain if the trusted domains
837
+        // are defined
838
+        // If no trusted domain is provided the first trusted domain is returned
839
+        $trustedDomainHelper = new TrustedDomainHelper($this->config);
840
+        if ($trustedDomainHelper->isTrustedDomain($host)) {
841
+            return $host;
842
+        } else {
843
+            $trustedList = $this->config->getSystemValue('trusted_domains', []);
844
+            if(!empty($trustedList)) {
845
+                return $trustedList[0];
846
+            } else {
847
+                return '';
848
+            }
849
+        }
850
+    }
851
+
852
+    /**
853
+     * Returns the overwritehost setting from the config if set and
854
+     * if the overwrite condition is met
855
+     * @return string|null overwritehost value or null if not defined or the defined condition
856
+     * isn't met
857
+     */
858
+    private function getOverwriteHost() {
859
+        if($this->config->getSystemValue('overwritehost') !== '' && $this->isOverwriteCondition()) {
860
+            return $this->config->getSystemValue('overwritehost');
861
+        }
862
+        return null;
863
+    }
864 864
 
865 865
 }
Please login to merge, or discard this patch.
Spacing   +40 added lines, -40 removed lines patch added patch discarded remove patch
@@ -128,7 +128,7 @@  discard block
 block discarded – undo
128 128
 	 * @param string $stream
129 129
 	 * @see http://www.php.net/manual/en/reserved.variables.php
130 130
 	 */
131
-	public function __construct(array $vars=array(),
131
+	public function __construct(array $vars = array(),
132 132
 								ISecureRandom $secureRandom = null,
133 133
 								IConfig $config,
134 134
 								CsrfTokenManager $csrfTokenManager = null,
@@ -139,11 +139,11 @@  discard block
 block discarded – undo
139 139
 		$this->config = $config;
140 140
 		$this->csrfTokenManager = $csrfTokenManager;
141 141
 
142
-		if(!array_key_exists('method', $vars)) {
142
+		if (!array_key_exists('method', $vars)) {
143 143
 			$vars['method'] = 'GET';
144 144
 		}
145 145
 
146
-		foreach($this->allowedKeys as $name) {
146
+		foreach ($this->allowedKeys as $name) {
147 147
 			$this->items[$name] = isset($vars[$name])
148 148
 				? $vars[$name]
149 149
 				: array();
@@ -248,12 +248,12 @@  discard block
 block discarded – undo
248 248
 	* @return mixed|null
249 249
 	*/
250 250
 	public function __get($name) {
251
-		switch($name) {
251
+		switch ($name) {
252 252
 			case 'put':
253 253
 			case 'patch':
254 254
 			case 'get':
255 255
 			case 'post':
256
-				if($this->method !== strtoupper($name)) {
256
+				if ($this->method !== strtoupper($name)) {
257 257
 					throw new \LogicException(sprintf('%s cannot be accessed in a %s request.', $name, $this->method));
258 258
 				}
259 259
 				return $this->getContent();
@@ -304,14 +304,14 @@  discard block
 block discarded – undo
304 304
 	 */
305 305
 	public function getHeader($name) {
306 306
 
307
-		$name = strtoupper(str_replace(array('-'),array('_'),$name));
308
-		if (isset($this->server['HTTP_' . $name])) {
309
-			return $this->server['HTTP_' . $name];
307
+		$name = strtoupper(str_replace(array('-'), array('_'), $name));
308
+		if (isset($this->server['HTTP_'.$name])) {
309
+			return $this->server['HTTP_'.$name];
310 310
 		}
311 311
 
312 312
 		// There's a few headers that seem to end up in the top-level
313 313
 		// server array.
314
-		switch($name) {
314
+		switch ($name) {
315 315
 			case 'CONTENT_TYPE' :
316 316
 			case 'CONTENT_LENGTH' :
317 317
 				if (isset($this->server[$name])) {
@@ -430,21 +430,21 @@  discard block
 block discarded – undo
430 430
 		// 'application/json' must be decoded manually.
431 431
 		if (strpos($this->getHeader('Content-Type'), 'application/json') !== false) {
432 432
 			$params = json_decode(file_get_contents($this->inputStream), true);
433
-			if(count($params) > 0) {
433
+			if (count($params) > 0) {
434 434
 				$this->items['params'] = $params;
435
-				if($this->method === 'POST') {
435
+				if ($this->method === 'POST') {
436 436
 					$this->items['post'] = $params;
437 437
 				}
438 438
 			}
439 439
 
440 440
 		// Handle application/x-www-form-urlencoded for methods other than GET
441 441
 		// or post correctly
442
-		} elseif($this->method !== 'GET'
442
+		} elseif ($this->method !== 'GET'
443 443
 				&& $this->method !== 'POST'
444 444
 				&& strpos($this->getHeader('Content-Type'), 'application/x-www-form-urlencoded') !== false) {
445 445
 
446 446
 			parse_str(file_get_contents($this->inputStream), $params);
447
-			if(is_array($params)) {
447
+			if (is_array($params)) {
448 448
 				$this->items['params'] = $params;
449 449
 			}
450 450
 		}
@@ -461,11 +461,11 @@  discard block
 block discarded – undo
461 461
 	 * @return bool true if CSRF check passed
462 462
 	 */
463 463
 	public function passesCSRFCheck() {
464
-		if($this->csrfTokenManager === null) {
464
+		if ($this->csrfTokenManager === null) {
465 465
 			return false;
466 466
 		}
467 467
 
468
-		if(!$this->passesStrictCookieCheck()) {
468
+		if (!$this->passesStrictCookieCheck()) {
469 469
 			return false;
470 470
 		}
471 471
 
@@ -493,7 +493,7 @@  discard block
 block discarded – undo
493 493
 		if ($this->getHeader('OCS-APIREQUEST')) {
494 494
 			return false;
495 495
 		}
496
-		if($this->getCookie(session_name()) === null && $this->getCookie('nc_token') === null) {
496
+		if ($this->getCookie(session_name()) === null && $this->getCookie('nc_token') === null) {
497 497
 			return false;
498 498
 		}
499 499
 
@@ -518,7 +518,7 @@  discard block
 block discarded – undo
518 518
 	protected function getProtectedCookieName($name) {
519 519
 		$cookieParams = $this->getCookieParams();
520 520
 		$prefix = '';
521
-		if($cookieParams['secure'] === true && $cookieParams['path'] === '/') {
521
+		if ($cookieParams['secure'] === true && $cookieParams['path'] === '/') {
522 522
 			$prefix = '__Host-';
523 523
 		}
524 524
 
@@ -533,12 +533,12 @@  discard block
 block discarded – undo
533 533
 	 * @since 9.1.0
534 534
 	 */
535 535
 	public function passesStrictCookieCheck() {
536
-		if(!$this->cookieCheckRequired()) {
536
+		if (!$this->cookieCheckRequired()) {
537 537
 			return true;
538 538
 		}
539 539
 
540 540
 		$cookieName = $this->getProtectedCookieName('nc_sameSiteCookiestrict');
541
-		if($this->getCookie($cookieName) === 'true'
541
+		if ($this->getCookie($cookieName) === 'true'
542 542
 			&& $this->passesLaxCookieCheck()) {
543 543
 			return true;
544 544
 		}
@@ -553,12 +553,12 @@  discard block
 block discarded – undo
553 553
 	 * @since 9.1.0
554 554
 	 */
555 555
 	public function passesLaxCookieCheck() {
556
-		if(!$this->cookieCheckRequired()) {
556
+		if (!$this->cookieCheckRequired()) {
557 557
 			return true;
558 558
 		}
559 559
 
560 560
 		$cookieName = $this->getProtectedCookieName('nc_sameSiteCookielax');
561
-		if($this->getCookie($cookieName) === 'true') {
561
+		if ($this->getCookie($cookieName) === 'true') {
562 562
 			return true;
563 563
 		}
564 564
 		return false;
@@ -571,11 +571,11 @@  discard block
 block discarded – undo
571 571
 	 * @return string
572 572
 	 */
573 573
 	public function getId() {
574
-		if(isset($this->server['UNIQUE_ID'])) {
574
+		if (isset($this->server['UNIQUE_ID'])) {
575 575
 			return $this->server['UNIQUE_ID'];
576 576
 		}
577 577
 
578
-		if(empty($this->requestId)) {
578
+		if (empty($this->requestId)) {
579 579
 			$this->requestId = $this->secureRandom->generate(20);
580 580
 		}
581 581
 
@@ -593,15 +593,15 @@  discard block
 block discarded – undo
593 593
 		$remoteAddress = isset($this->server['REMOTE_ADDR']) ? $this->server['REMOTE_ADDR'] : '';
594 594
 		$trustedProxies = $this->config->getSystemValue('trusted_proxies', []);
595 595
 
596
-		if(is_array($trustedProxies) && in_array($remoteAddress, $trustedProxies)) {
596
+		if (is_array($trustedProxies) && in_array($remoteAddress, $trustedProxies)) {
597 597
 			$forwardedForHeaders = $this->config->getSystemValue('forwarded_for_headers', [
598 598
 				'HTTP_X_FORWARDED_FOR'
599 599
 				// only have one default, so we cannot ship an insecure product out of the box
600 600
 			]);
601 601
 
602
-			foreach($forwardedForHeaders as $header) {
603
-				if(isset($this->server[$header])) {
604
-					foreach(explode(',', $this->server[$header]) as $IP) {
602
+			foreach ($forwardedForHeaders as $header) {
603
+				if (isset($this->server[$header])) {
604
+					foreach (explode(',', $this->server[$header]) as $IP) {
605 605
 						$IP = trim($IP);
606 606
 						if (filter_var($IP, FILTER_VALIDATE_IP) !== false) {
607 607
 							return $IP;
@@ -620,7 +620,7 @@  discard block
 block discarded – undo
620 620
 	 * @return bool
621 621
 	 */
622 622
 	private function isOverwriteCondition($type = '') {
623
-		$regex = '/' . $this->config->getSystemValue('overwritecondaddr', '')  . '/';
623
+		$regex = '/'.$this->config->getSystemValue('overwritecondaddr', '').'/';
624 624
 		$remoteAddr = isset($this->server['REMOTE_ADDR']) ? $this->server['REMOTE_ADDR'] : '';
625 625
 		return $regex === '//' || preg_match($regex, $remoteAddr) === 1
626 626
 		|| $type !== 'protocol';
@@ -632,7 +632,7 @@  discard block
 block discarded – undo
632 632
 	 * @return string Server protocol (http or https)
633 633
 	 */
634 634
 	public function getServerProtocol() {
635
-		if($this->config->getSystemValue('overwriteprotocol') !== ''
635
+		if ($this->config->getSystemValue('overwriteprotocol') !== ''
636 636
 			&& $this->isOverwriteCondition('protocol')) {
637 637
 			return $this->config->getSystemValue('overwriteprotocol');
638 638
 		}
@@ -674,7 +674,7 @@  discard block
 block discarded – undo
674 674
 			'HTTP/2',
675 675
 		];
676 676
 
677
-		if(in_array($claimedProtocol, $validProtocols, true)) {
677
+		if (in_array($claimedProtocol, $validProtocols, true)) {
678 678
 			return $claimedProtocol;
679 679
 		}
680 680
 
@@ -688,8 +688,8 @@  discard block
 block discarded – undo
688 688
 	 */
689 689
 	public function getRequestUri() {
690 690
 		$uri = isset($this->server['REQUEST_URI']) ? $this->server['REQUEST_URI'] : '';
691
-		if($this->config->getSystemValue('overwritewebroot') !== '' && $this->isOverwriteCondition()) {
692
-			$uri = $this->getScriptName() . substr($uri, strlen($this->server['SCRIPT_NAME']));
691
+		if ($this->config->getSystemValue('overwritewebroot') !== '' && $this->isOverwriteCondition()) {
692
+			$uri = $this->getScriptName().substr($uri, strlen($this->server['SCRIPT_NAME']));
693 693
 		}
694 694
 		return $uri;
695 695
 	}
@@ -703,7 +703,7 @@  discard block
 block discarded – undo
703 703
 		$requestUri = isset($this->server['REQUEST_URI']) ? $this->server['REQUEST_URI'] : '';
704 704
 		// remove too many leading slashes - can be caused by reverse proxy configuration
705 705
 		if (strpos($requestUri, '/') === 0) {
706
-			$requestUri = '/' . ltrim($requestUri, '/');
706
+			$requestUri = '/'.ltrim($requestUri, '/');
707 707
 		}
708 708
 
709 709
 		$requestUri = preg_replace('%/{2,}%', '/', $requestUri);
@@ -720,7 +720,7 @@  discard block
 block discarded – undo
720 720
 		// FIXME: Sabre does not really belong here
721 721
 		list($path, $name) = \Sabre\HTTP\URLUtil::splitPath($scriptName);
722 722
 		if (!empty($path)) {
723
-			if($path === $pathInfo || strpos($pathInfo, $path.'/') === 0) {
723
+			if ($path === $pathInfo || strpos($pathInfo, $path.'/') === 0) {
724 724
 				$pathInfo = substr($pathInfo, strlen($path));
725 725
 			} else {
726 726
 				throw new \Exception("The requested uri($requestUri) cannot be processed by the script '$scriptName')");
@@ -732,7 +732,7 @@  discard block
 block discarded – undo
732 732
 		if (strpos($pathInfo, $name) === 0) {
733 733
 			$pathInfo = substr($pathInfo, strlen($name));
734 734
 		}
735
-		if($pathInfo === false || $pathInfo === '/'){
735
+		if ($pathInfo === false || $pathInfo === '/') {
736 736
 			return '';
737 737
 		} else {
738 738
 			return $pathInfo;
@@ -750,7 +750,7 @@  discard block
 block discarded – undo
750 750
 		$pathInfo = rawurldecode($pathInfo);
751 751
 		$encoding = mb_detect_encoding($pathInfo, ['UTF-8', 'ISO-8859-1']);
752 752
 
753
-		switch($encoding) {
753
+		switch ($encoding) {
754 754
 			case 'ISO-8859-1' :
755 755
 				$pathInfo = utf8_encode($pathInfo);
756 756
 		}
@@ -766,12 +766,12 @@  discard block
 block discarded – undo
766 766
 	 */
767 767
 	public function getScriptName() {
768 768
 		$name = $this->server['SCRIPT_NAME'];
769
-		$overwriteWebRoot =  $this->config->getSystemValue('overwritewebroot');
769
+		$overwriteWebRoot = $this->config->getSystemValue('overwritewebroot');
770 770
 		if ($overwriteWebRoot !== '' && $this->isOverwriteCondition()) {
771 771
 			// FIXME: This code is untestable due to __DIR__, also that hardcoded path is really dangerous
772 772
 			$serverRoot = str_replace('\\', '/', substr(__DIR__, 0, -strlen('lib/private/appframework/http/')));
773 773
 			$suburi = str_replace('\\', '/', substr(realpath($this->server['SCRIPT_FILENAME']), strlen($serverRoot)));
774
-			$name = '/' . ltrim($overwriteWebRoot . $suburi, '/');
774
+			$name = '/'.ltrim($overwriteWebRoot.$suburi, '/');
775 775
 		}
776 776
 		return $name;
777 777
 	}
@@ -841,7 +841,7 @@  discard block
 block discarded – undo
841 841
 			return $host;
842 842
 		} else {
843 843
 			$trustedList = $this->config->getSystemValue('trusted_domains', []);
844
-			if(!empty($trustedList)) {
844
+			if (!empty($trustedList)) {
845 845
 				return $trustedList[0];
846 846
 			} else {
847 847
 				return '';
@@ -856,7 +856,7 @@  discard block
 block discarded – undo
856 856
 	 * isn't met
857 857
 	 */
858 858
 	private function getOverwriteHost() {
859
-		if($this->config->getSystemValue('overwritehost') !== '' && $this->isOverwriteCondition()) {
859
+		if ($this->config->getSystemValue('overwritehost') !== '' && $this->isOverwriteCondition()) {
860 860
 			return $this->config->getSystemValue('overwritehost');
861 861
 		}
862 862
 		return null;
Please login to merge, or discard this patch.