Test Failed
Push — master ( 8c47c2...3acf9f )
by Steve
12:37
created

engine/classes/ElggRewriteTester.php (1 issue)

Labels
Severity

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

1
<?php
2
3
use Elgg\Filesystem\Directory;
0 ignored issues
show
This use statement conflicts with another class in this namespace, Directory.

Let’s assume that you have a directory layout like this:

.
|-- OtherDir
|   |-- Bar.php
|   `-- Foo.php
`-- SomeDir
    `-- Foo.php

and let’s assume the following content of Bar.php:

// Bar.php
namespace OtherDir;

use SomeDir\Foo; // This now conflicts the class OtherDir\Foo

If both files OtherDir/Foo.php and SomeDir/Foo.php are loaded in the same runtime, you will see a PHP error such as the following:

PHP Fatal error:  Cannot use SomeDir\Foo as Foo because the name is already in use in OtherDir/Foo.php

However, as OtherDir/Foo.php does not necessarily have to be loaded and the error is only triggered if it is loaded before OtherDir/Bar.php, this problem might go unnoticed for a while. In order to prevent this error from surfacing, you must import the namespace with a different alias:

// Bar.php
namespace OtherDir;

use SomeDir\Foo as SomeDirFoo; // There is no conflict anymore.
Loading history...
4
5
/**
6
 * Elgg RewriteTester.
7
 * Test if URL rewriting is working.
8
 *
9
 * @package    Elgg.Core
10
 * @subpackage Installer
11
 */
12
class ElggRewriteTester {
13
	protected $webserver;
14
	protected $serverSupportsRemoteRead;
15
	protected $rewriteTestPassed;
16
	protected $htaccessIssue;
17
18
	/**
19
	 * Set the webserver as unknown.
20
	 */
21
	public function __construct() {
22
		$this->webserver = 'unknown';
23
	}
24
25
	/**
26
	 * Run the rewrite test and return a status array
27
	 *
28
	 * @param string $url  URL of rewrite test
29
	 * @param string $path Root directory of Elgg with trailing slash
30
	 *
31
	 * @return array
32
	 */
33
	public function run($url, $path) {
34
35
		$this->webserver = \ElggRewriteTester::guessWebServer();
36
37
		$this->rewriteTestPassed = $this->runRewriteTest($url);
38
39
		if ($this->rewriteTestPassed == false) {
40
			if ($this->webserver == 'apache' || $this->webserver == 'unknown') {
41
				if ($this->createHtaccess($url, $path)) {
42
					$this->rewriteTestPassed = $this->runRewriteTest($url);
43
				}
44
			}
45
		}
46
47
		return $this->returnStatus($url);
48
	}
49
50
	/**
51
	 * Guess the web server from $_SERVER['SERVER_SOFTWARE']
52
	 *
53
	 * @return string
54
	 */
55
	public static function guessWebServer() {
56
		$serverString = strtolower($_SERVER['SERVER_SOFTWARE']);
57
		$possibleServers = ['apache', 'nginx', 'lighttpd', 'iis'];
58
		foreach ($possibleServers as $server) {
59
			if (strpos($serverString, $server) !== false) {
60
				return $server;
61
			}
62
		}
63
		return 'unknown';
64
	}
65
66
	/**
67
	 * Guess if url contains subdirectory or not.
68
	 *
69
	 * @param string $url Rewrite test URL
70
	 *
71
	 * @return string|bool Subdirectory string with beginning and trailing slash or false if were unable to determine subdirectory
72
	 * or pointing at root of domain already
73
	 */
74
	public function guessSubdirectory($url) {
75
		$elements = parse_url($url);
76
		if (!$elements || !isset($elements['path'])) {
77
			return false;
78
		}
79
		$subdir = trim(dirname($elements['path']), '/');
80
		if (!$subdir) {
81
			return false;
82
		} else {
83
			return "/$subdir/";
84
		}
85
	}
86
87
	/**
88
	 * Hit the rewrite test URL to determine if the rewrite rules are working
89
	 *
90
	 * @param string $url Rewrite test URL
91
	 *
92
	 * @return bool
93
	 */
94
	public function runRewriteTest($url) {
95
		$this->serverSupportsRemoteRead = ($this->fetchUrl($url) === \Elgg\Application::REWRITE_TEST_OUTPUT);
96
		return $this->serverSupportsRemoteRead;
97
	}
98
	
99
	/**
100
	 * Check whether the site homepage can be fetched via curl
101
	 *
102
	 * @return boolean
103
	 */
104
	public function runLocalhostAccessTest() {
105
		$url = _elgg_services()->config->wwwroot;
106
		return (bool) $this->fetchUrl($url);
107
	}
108
109
	/**
110
	 * Fetch a URL
111
	 *
112
	 * @param string $url The URL
113
	 *
114
	 * @return string Note that empty string may imply failure in fetching or empty response
115
	 */
116
	private function fetchUrl($url) {
117
		$response = '';
118
119
		if (ini_get('allow_url_fopen')) {
120
			$ctx = stream_context_create([
121
				'http' => [
122
					'follow_location' => 0,
123
					'timeout' => 5,
124
				],
125
			]);
126
			$response = @file_get_contents($url, null, $ctx);
127
		}
128
129
		if (!$response && function_exists('curl_init')) {
130
			$ch = curl_init();
131
			curl_setopt($ch, CURLOPT_URL, $url);
132
			curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
133
			curl_setopt($ch, CURLOPT_TIMEOUT, 5);
134
			curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
135
			$response = curl_exec($ch);
136
			curl_close($ch);
137
		}
138
139
		return (string) $response;
140
	}
141
142
	/**
143
	 * Create Elgg's .htaccess file or confirm that it exists
144
	 *
145
	 * @param string $url URL of rewrite test
146
	 *
147
	 * @return bool
148
	 */
149
	public function createHtaccess($url) {
150
		$root = Directory\Local::root();
151
		$file = $root->getFile(".htaccess");
152
		if ($file->exists()) {
153
			// check that this is the Elgg .htaccess
154
			$data = $file->getContents();
155
			if ($data === false) {
156
				// don't have permission to read the file
157
				$this->htaccessIssue = 'read_permission';
158
				return false;
159
			}
160
			if (strpos($data, 'Elgg') === false) {
161
				$this->htaccessIssue = 'non_elgg_htaccess';
162
				return false;
163
			} else {
164
				// check if this is an old Elgg htaccess
165
				if (strpos($data, 'RewriteRule ^rewrite.php$ install.php') == false) {
166
					$this->htaccessIssue = 'old_elgg_htaccess';
167
					return false;
168
				}
169
				return true;
170
			}
171
		}
172
173
		if (!is_writable($root->getPath())) {
174
			$this->htaccessIssue = 'write_permission';
175
			return false;
176
		}
177
178
		// create the .htaccess file
179
		$result = copy(\Elgg\Application::elggDir()->getPath("install/config/htaccess.dist"), $file->getPath());
180
		if (!$result) {
181
			$this->htaccessIssue = 'cannot_copy';
182
			return false;
183
		}
184
		
185
		// does default RewriteBase work already?
186
		if (!$this->runRewriteTest($url)) {
187
			//try to rewrite to guessed subdirectory
188
			if ($subdir = $this->guessSubdirectory($url)) {
189
				$contents = $file->getContents();
190
				$contents = preg_replace("/#RewriteBase \/(\r?\n)/", "RewriteBase $subdir\$1", $contents);
191
				if ($contents) {
192
					$file->putContents($contents);
193
				}
194
			}
195
		}
196
197
		return true;
198
	}
199
200
	/**
201
	 * Create the status array required by the ElggInstaller
202
	 *
203
	 * @param string $url Rewrite test URL
204
	 *
205
	 * @return array
206
	 */
207
	protected function returnStatus($url) {
208
		if ($this->rewriteTestPassed) {
209
			return [
210
				'severity' => 'pass',
211
				'message' => _elgg_services()->translator->translate('install:check:rewrite:success'),
212
			];
213
		}
214
215
		if ($this->serverSupportsRemoteRead == false) {
216
			$msg = _elgg_services()->translator->translate('install:warning:rewrite:unknown', [$url]);
217
			$msg .= elgg_view('install/js_rewrite_check', ['url' => $url]);
218
			
219
			return [
220
				'severity' => 'warning',
221
				'message' => $msg,
222
			];
223
		}
224
225
		if ($this->webserver == 'apache') {
226
			$serverString = _elgg_services()->translator->translate('install:error:rewrite:apache');
227
			$msg = "$serverString\n\n";
228
			if (!isset($this->htaccessIssue)) {
229
				$msg .= _elgg_services()->translator->translate('install:error:rewrite:allowoverride');
230
				$msg .= elgg_view('install/js_rewrite_check', ['url' => $url]);
231
			
232
				return [
233
					'severity' => 'warning',
234
					'message' => $msg,
235
				];
236
			}
237
			$msg .= _elgg_services()->translator->translate("install:error:rewrite:htaccess:{$this->htaccessIssue}");
238
			return [
239
				'severity' => 'warning',
240
				'message' => $msg,
241
			];
242
		}
243
244
		if ($this->webserver != 'unknown') {
245
			$serverString = _elgg_services()->translator->translate("install:error:rewrite:{$this->webserver}");
246
			$msg = "$serverString\n\n";
247
			$msg .= _elgg_services()->translator->translate("install:error:rewrite:altserver");
248
			return [
249
				'severity' => 'warning',
250
				'message' => $msg,
251
			];
252
		}
253
254
		return [
255
			'severity' => 'warning',
256
			'message' => _elgg_services()->translator->translate('install:error:rewrite:unknown'),
257
		];
258
	}
259
}
260