Elgg  Version 5.1
RewriteTester.php
Go to the documentation of this file.
1 <?php
2 
3 namespace Elgg\Router;
4 
8 
15 
16  protected string $webserver;
17 
18  protected bool $serverSupportsRemoteRead;
19 
20  protected bool $rewriteTestPassed;
21 
22  protected string $htaccessIssue;
23 
27  public function __construct() {
28  $this->webserver = 'unknown';
29  }
30 
39  public function run($url, $path = null) {
40 
41  $this->webserver = $this->guessWebServer();
42 
43  $this->rewriteTestPassed = $this->runRewriteTest($url);
44 
45  if ($this->rewriteTestPassed === false) {
46  if ($this->webserver == 'apache' || $this->webserver == 'unknown') {
47  if ($this->createHtaccess($url)) {
48  $this->rewriteTestPassed = $this->runRewriteTest($url);
49  }
50  }
51  }
52 
53  return $this->returnStatus($url);
54  }
55 
61  protected function guessWebServer() {
62  if (empty($_SERVER['SERVER_SOFTWARE'])) {
63  return 'unknown';
64  }
65 
66  $serverString = strtolower($_SERVER['SERVER_SOFTWARE']);
67  $possibleServers = ['apache', 'nginx', 'lighttpd', 'iis'];
68  foreach ($possibleServers as $server) {
69  if (elgg_strpos($serverString, $server) !== false) {
70  return $server;
71  }
72  }
73 
74  return 'unknown';
75  }
76 
85  protected function guessSubdirectory($url) {
86  $elements = parse_url($url);
87  if (!is_array($elements) || !isset($elements['path'])) {
88  return false;
89  }
90 
91  $subdir = trim(dirname($elements['path']), '/');
92  if (!$subdir) {
93  return false;
94  }
95 
96  return "/$subdir/";
97  }
98 
106  public function runRewriteTest($url) {
107  $this->serverSupportsRemoteRead = ($this->fetchUrl($url) === Request::REWRITE_TEST_OUTPUT);
109  }
110 
116  public function runLocalhostAccessTest() {
117  return (bool) $this->fetchUrl(_elgg_services()->config->wwwroot);
118  }
119 
127  private function fetchUrl($url) {
128  $response = '';
129 
130  if (ini_get('allow_url_fopen')) {
131  $ctx = stream_context_create([
132  'http' => [
133  'follow_location' => 0,
134  'timeout' => 5,
135  ],
136  ]);
137  $response = @file_get_contents($url, false, $ctx);
138  }
139 
140  if (!$response && function_exists('curl_init')) {
141  $ch = curl_init();
142  curl_setopt($ch, CURLOPT_URL, $url);
143  curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
144  curl_setopt($ch, CURLOPT_TIMEOUT, 5);
145  curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
146  $response = curl_exec($ch);
147  curl_close($ch);
148  }
149 
150  return (string) $response;
151  }
152 
160  public function createHtaccess($url) {
161  $root = Local::projectRoot();
162  $file = $root->getFile('.htaccess');
163 
164  if ($file->exists()) {
165  // check that this is the Elgg .htaccess
166  $data = $file->getContents();
167  if (empty($data)) {
168  // don't have permission to read the file
169  $this->htaccessIssue = 'read_permission';
170  return false;
171  }
172 
173  if (elgg_strpos($data, 'Elgg') === false) {
174  $this->htaccessIssue = 'non_elgg_htaccess';
175  return false;
176  }
177 
178  // check if this is an old Elgg htaccess
179  if (elgg_strpos($data, 'RewriteRule ^rewrite.php$ install.php') === false) {
180  $this->htaccessIssue = 'old_elgg_htaccess';
181  return false;
182  }
183 
184  return true;
185  }
186 
187  if (!is_writable($root->getPath())) {
188  $this->htaccessIssue = 'write_permission';
189  return false;
190  }
191 
192  // create the .htaccess file
193  $result = copy(Paths::elgg() . 'install/config/htaccess.dist', $file->getPath());
194  if (!$result) {
195  $this->htaccessIssue = 'cannot_copy';
196  return false;
197  }
198 
199  // does default RewriteBase work already?
200  if (!$this->runRewriteTest($url)) {
201  //try to rewrite to guessed subdirectory
202  $subdir = $this->guessSubdirectory($url);
203  if (!empty($subdir)) {
204  $contents = $file->getContents();
205  $contents = preg_replace("/#RewriteBase \/(\r?\n)/", "RewriteBase $subdir\$1", $contents);
206  if ($contents) {
207  $file->putContents($contents);
208  }
209  }
210  }
211 
212  return true;
213  }
214 
222  protected function returnStatus($url) {
223  if ($this->rewriteTestPassed) {
224  return [
225  'severity' => 'success',
226  'message' => _elgg_services()->translator->translate('install:check:rewrite:success'),
227  ];
228  }
229 
230  if ($this->serverSupportsRemoteRead === false) {
231  $msg = _elgg_services()->translator->translate('install:warning:rewrite:unknown', [$url]);
232  $msg .= elgg_view('install/js_rewrite_check', ['url' => $url]);
233 
234  return [
235  'severity' => 'warning',
236  'message' => $msg,
237  ];
238  }
239 
240  if ($this->webserver === 'apache') {
241  $msg = _elgg_services()->translator->translate('install:error:rewrite:apache');
242  $msg .= PHP_EOL . PHP_EOL;
243  if (!isset($this->htaccessIssue)) {
244  $msg .= _elgg_services()->translator->translate('install:error:rewrite:allowoverride');
245  $msg .= elgg_view('install/js_rewrite_check', ['url' => $url]);
246 
247  return [
248  'severity' => 'warning',
249  'message' => $msg,
250  ];
251  }
252 
253  $msg .= _elgg_services()->translator->translate("install:error:rewrite:htaccess:{$this->htaccessIssue}");
254  return [
255  'severity' => 'warning',
256  'message' => $msg,
257  ];
258  }
259 
260  if ($this->webserver !== 'unknown') {
261  $msg = _elgg_services()->translator->translate("install:error:rewrite:{$this->webserver}");
262  $msg .= PHP_EOL . PHP_EOL;
263  $msg .= _elgg_services()->translator->translate('install:error:rewrite:altserver');
264  return [
265  'severity' => 'warning',
266  'message' => $msg,
267  ];
268  }
269 
270  return [
271  'severity' => 'warning',
272  'message' => _elgg_services()->translator->translate('install:error:rewrite:unknown'),
273  ];
274  }
275 }
static elgg()
Get the Elgg codebase path with "/".
Definition: Paths.php:44
$server
runRewriteTest($url)
Hit the rewrite test URL to determine if the rewrite rules are working.
elgg parse_url
Parse a URL into its parts.
Definition: elgglib.js:139
guessSubdirectory($url)
Guess if url contains subdirectory or not.
__construct()
Set the webserver as unknown.
static projectRoot()
Get the root composer install directory.
Definition: Local.php:36
Test if URL rewriting is working.
$path
Definition: details.php:70
if(!$entity instanceof\ElggUser) $data
Definition: attributes.php:13
runLocalhostAccessTest()
Check whether the site homepage can be fetched via curl.
elgg_view(string $view, array $vars=[], string $viewtype= '')
Return a parsed view.
Definition: views.php:177
returnStatus($url)
Create the status array required by the ElggInstaller.
elgg_strpos()
Wrapper function for mb_strpos().
Definition: mb_wrapper.php:71
run($url, $path=null)
Run the rewrite test and return a status array.
guessWebServer()
Guess the web server from $_SERVER[&#39;SERVER_SOFTWARE&#39;].
and give any other recipients of the Program a copy of this License along with the Program You may charge a fee for the physical act of transferring a copy
Definition: LICENSE.txt:140
foreach($plugin_guids as $guid) if(empty($deactivated_plugins)) $url
Definition: deactivate.php:39
_elgg_services()
Get the global service provider.
Definition: elgglib.php:346
createHtaccess($url)
Create Elgg&#39;s .htaccess file or confirm that it exists.
if(!empty($title)&&!empty($icon_name)) if(!empty($title)) if(!empty($menu)) if(!empty($header)) if(!empty($body)) $contents
Definition: message.php:73