3 * @copyright Copyright (C) 2010-2023, the Friendica project
5 * @license GNU AGPL version 3 or any later version
7 * This program is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU Affero General Public License as
9 * published by the Free Software Foundation, either version 3 of the
10 * License, or (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU Affero General Public License for more details.
17 * You should have received a copy of the GNU Affero General Public License
18 * along with this program. If not, see <https://www.gnu.org/licenses/>.
22 namespace Friendica\Test\src\Util;
24 use Friendica\App\BaseURL;
25 use Friendica\Core\Config\Capability\IManageConfigValues;
26 use Friendica\Test\MockedTest;
28 class BaseURLTest extends MockedTest
30 public function dataDefault()
44 'sslPolicy' => BaseURL::DEFAULT_SSL_SCHEME,
49 'WithSubDirectory' => [
51 'SERVER_NAME' => 'friendica.local',
52 'REDIRECT_URI' => 'test/module/more',
53 'QUERY_STRING' => 'module/more',
62 'hostname' => 'friendica.local',
64 'sslPolicy' => BaseURL::DEFAULT_SSL_SCHEME,
65 'url' => 'http://friendica.local/test',
72 'hostname' => 'friendica.local',
74 'sslPolicy' => BaseURL::SSL_POLICY_FULL,
75 'url' => 'http://friendica.local/test',
78 'hostname' => 'friendica.local',
80 'sslPolicy' => BaseURL::SSL_POLICY_FULL,
81 'url' => 'http://friendica.local/test',
85 'WithHttpsScheme' => [
87 'SERVER_NAME' => 'friendica.local',
88 'REDIRECT_URI' => 'test/module/more',
89 'QUERY_STRING' => 'module/more',
99 'hostname' => 'friendica.local',
101 'sslPolicy' => BaseURL::SSL_POLICY_FULL,
102 'url' => 'https://friendica.local/test',
106 'WithoutQueryString' => [
108 'SERVER_NAME' => 'friendica.local',
109 'REDIRECT_URI' => 'test/more',
119 'hostname' => 'friendica.local',
120 'urlPath' => 'test/more',
121 'sslPolicy' => BaseURL::SSL_POLICY_FULL,
122 'url' => 'https://friendica.local/test/more',
128 'SERVER_NAME' => 'friendica.local',
129 'SERVER_PORT' => '1234',
130 'REDIRECT_URI' => 'test/more',
140 'hostname' => 'friendica.local:1234',
141 'urlPath' => 'test/more',
142 'sslPolicy' => BaseURL::SSL_POLICY_FULL,
143 'url' => 'https://friendica.local:1234/test/more',
149 'SERVER_NAME' => 'friendica.local',
150 'SERVER_PORT' => '443',
151 'REDIRECT_URI' => 'test/more',
160 'hostname' => 'friendica.local',
161 'urlPath' => 'test/more',
162 'sslPolicy' => BaseURL::SSL_POLICY_FULL,
163 'url' => 'https://friendica.local/test/more',
169 'SERVER_NAME' => 'friendica.local',
170 'SERVER_PORT' => '80',
171 'REDIRECT_URI' => 'test/more',
180 'hostname' => 'friendica.local',
181 'urlPath' => 'test/more',
182 'sslPolicy' => BaseURL::DEFAULT_SSL_SCHEME,
183 'url' => 'http://friendica.local/test/more',
191 * Test the default config determination
192 * @dataProvider dataDefault
194 public function testCheck($server, $input, $assert)
196 $configMock = \Mockery::mock(IManageConfigValues::class);
197 $configMock->shouldReceive('get')->with('config', 'hostname')->andReturn($input['hostname']);
198 $configMock->shouldReceive('get')->with('system', 'urlpath')->andReturn($input['urlPath']);
199 $configMock->shouldReceive('get')->with('system', 'ssl_policy')->andReturn($input['sslPolicy']);
200 $configMock->shouldReceive('get')->with('system', 'url')->andReturn($input['url']);
202 // If we don't have an urlPath as an input, we assert it, we will save it to the DB for the next time
203 if (!isset($input['urlPath']) && isset($assert['urlPath'])) {
204 $configMock->shouldReceive('set')->with('system', 'urlpath', $assert['urlPath'])->once();
207 // If we don't have the ssl_policy as an input, we assert it, we will save it to the DB for the next time
208 if (!isset($input['sslPolicy']) && isset($assert['sslPolicy'])) {
209 $configMock->shouldReceive('set')->with('system', 'ssl_policy', $assert['sslPolicy'])->once();
212 // If we don't have the hostname as an input, we assert it, we will save it to the DB for the next time
213 if (empty($input['hostname']) && !empty($assert['hostname'])) {
214 $configMock->shouldReceive('set')->with('config', 'hostname', $assert['hostname'])->once();
217 // If we don't have an URL at first, but we assert it, we will save it to the DB for the next time
218 if (empty($input['url']) && !empty($assert['url'])) {
219 $configMock->shouldReceive('set')->with('system', 'url', $assert['url'])->once();
222 $baseUrl = new BaseURL($configMock, $server);
224 self::assertEquals($assert['hostname'], $baseUrl->getHostname());
225 self::assertEquals($assert['urlPath'], $baseUrl->getUrlPath());
226 self::assertEquals($assert['sslPolicy'], $baseUrl->getSSLPolicy());
227 self::assertEquals($assert['scheme'], $baseUrl->getScheme());
228 self::assertEquals($assert['url'], $baseUrl->get());
231 public function dataSave()
236 'hostname' => 'friendica.old',
237 'urlPath' => 'is/old/path',
238 'sslPolicy' => BaseURL::DEFAULT_SSL_SCHEME,
239 'url' => 'http://friendica.old/is/old/path',
243 'hostname' => 'friendica.local',
244 'urlPath' => 'new/path',
245 'sslPolicy' => BaseURL::SSL_POLICY_FULL,
247 'url' => 'https://friendica.local/new/path',
251 'hostname' => 'friendica.old',
252 'urlPath' => 'is/old/path',
253 'sslPolicy' => BaseURL::DEFAULT_SSL_SCHEME,
254 'url' => 'http://friendica.old/is/old/path',
262 'url' => 'http://friendica.old/is/old/path',
264 'changeHostname' => [
266 'hostname' => 'friendica.old',
267 'urlPath' => 'is/old/path',
268 'sslPolicy' => BaseURL::DEFAULT_SSL_SCHEME,
269 'url' => 'http://friendica.old/is/old/path',
273 'hostname' => 'friendica.local',
277 'url' => 'http://friendica.local/is/old/path',
281 'hostname' => 'friendica.old',
282 'urlPath' => 'is/old/path',
283 'sslPolicy' => BaseURL::DEFAULT_SSL_SCHEME,
284 'url' => 'http://friendica.old/is/old/path',
289 'urlPath' => 'new/path',
292 'url' => 'http://friendica.old/new/path',
294 'changeSSLPolicy' => [
296 'hostname' => 'friendica.old',
297 'urlPath' => 'is/old/path',
298 'sslPolicy' => BaseURL::DEFAULT_SSL_SCHEME,
299 'url' => 'http://friendica.old/is/old/path',
305 'sslPolicy' => BaseURL::SSL_POLICY_FULL,
307 'url' => 'https://friendica.old/is/old/path',
313 * Test the save() method
314 * @dataProvider dataSave
316 public function testSave($input, $save, $url)
318 $configMock = \Mockery::mock(IManageConfigValues::class);
319 $configMock->shouldReceive('get')->with('config', 'hostname')->andReturn($input['hostname']);
320 $configMock->shouldReceive('get')->with('system', 'urlpath')->andReturn($input['urlPath']);
321 $configMock->shouldReceive('get')->with('system', 'ssl_policy')->andReturn($input['sslPolicy']);
322 $configMock->shouldReceive('get')->with('system', 'url')->andReturn($input['url']);
323 $configMock->shouldReceive('get')->with('system', 'force_ssl')->andReturn($input['force_ssl']);
325 $baseUrl = new BaseURL($configMock, []);
327 if (isset($save['hostname'])) {
328 $configMock->shouldReceive('set')->with('config', 'hostname', $save['hostname'])->andReturn(true)->once();
331 if (isset($save['urlPath'])) {
332 $configMock->shouldReceive('set')->with('system', 'urlpath', $save['urlPath'])->andReturn(true)->once();
335 if (isset($save['sslPolicy'])) {
336 $configMock->shouldReceive('set')->with('system', 'ssl_policy', $save['sslPolicy'])->andReturn(true)->once();
339 $configMock->shouldReceive('set')->with('system', 'url', $url)->andReturn(true)->once();
341 $baseUrl->save($save['hostname'], $save['sslPolicy'], $save['urlPath']);
343 self::assertEquals($url, $baseUrl->get());
347 * Test the saveByUrl() method
348 * @dataProvider dataSave
354 public function testSaveByUrl($input, $save, $url)
356 $configMock = \Mockery::mock(IManageConfigValues::class);
357 $configMock->shouldReceive('get')->with('config', 'hostname')->andReturn($input['hostname']);
358 $configMock->shouldReceive('get')->with('system', 'urlpath')->andReturn($input['urlPath']);
359 $configMock->shouldReceive('get')->with('system', 'ssl_policy')->andReturn($input['sslPolicy']);
360 $configMock->shouldReceive('get')->with('system', 'url')->andReturn($input['url']);
361 $configMock->shouldReceive('get')->with('system', 'force_ssl')->andReturn($input['force_ssl']);
363 $baseUrl = new BaseURL($configMock, []);
365 if (isset($save['hostname'])) {
366 $configMock->shouldReceive('set')->with('config', 'hostname', $save['hostname'])->andReturn(true)->once();
369 if (isset($save['urlPath'])) {
370 $configMock->shouldReceive('set')->with('system', 'urlpath', $save['urlPath'])->andReturn(true)->once();
373 if (isset($save['sslPolicy'])) {
374 $configMock->shouldReceive('set')->with('system', 'ssl_policy', $save['sslPolicy'])->andReturn(true)->once();
377 $configMock->shouldReceive('set')->with('system', 'url', $url)->andReturn(true)->once();
379 $baseUrl->saveByURL($url);
381 self::assertEquals($url, $baseUrl->get());
384 public function dataGetBaseUrl()
388 'sslPolicy' => BaseURL::DEFAULT_SSL_SCHEME,
390 'url' => 'http://friendica.local/new/test',
391 'assert' => 'http://friendica.local/new/test',
393 'DefaultWithSSL' => [
394 'sslPolicy' => BaseURL::DEFAULT_SSL_SCHEME,
396 'url' => 'http://friendica.local/new/test',
397 'assert' => 'https://friendica.local/new/test',
399 'SSLFullWithSSL' => [
400 'sslPolicy' => BaseURL::SSL_POLICY_FULL,
402 'url' => 'http://friendica.local/new/test',
403 'assert' => 'http://friendica.local/new/test',
405 'SSLFullWithoutSSL' => [
406 'sslPolicy' => BaseURL::SSL_POLICY_FULL,
408 'url' => 'https://friendica.local/new/test',
409 'assert' => 'https://friendica.local/new/test',
412 'sslPolicy' => BaseURL::SSL_POLICY_NONE,
414 'url' => 'http://friendica.local/new/test',
415 'assert' => 'http://friendica.local/new/test',
417 'NoSSLWithoutSSL' => [
418 'sslPolicy' => BaseURL::SSL_POLICY_NONE,
420 'url' => 'http://friendica.local/new/test',
421 'assert' => 'http://friendica.local/new/test',
427 * Test the get() method
428 * @dataProvider dataGetBaseUrl
430 public function testGetURL($sslPolicy, $ssl, $url, $assert)
432 $configMock = \Mockery::mock(IManageConfigValues::class);
433 $configMock->shouldReceive('get')->with('config', 'hostname')->andReturn('friendica.local');
434 $configMock->shouldReceive('get')->with('system', 'urlpath')->andReturn('new/test');
435 $configMock->shouldReceive('get')->with('system', 'ssl_policy')->andReturn($sslPolicy);
436 $configMock->shouldReceive('get')->with('system', 'url')->andReturn($url);
438 $baseUrl = new BaseURL($configMock, []);
440 self::assertEquals($assert, $baseUrl->get($ssl));
443 public function dataCheckRedirectHTTPS()
448 'REQUEST_METHOD' => 'GET',
452 'sslPolicy' => BaseURL::DEFAULT_SSL_SCHEME,
453 'url' => 'https://friendica.local',
458 'REQUEST_METHOD' => 'GET',
461 'sslPolicy' => BaseURL::DEFAULT_SSL_SCHEME,
462 'url' => 'https://friendica.local',
465 'forceSSLWithSSLPolicy' => [
468 'sslPolicy' => BaseURL::SSL_POLICY_FULL,
469 'url' => 'https://friendica.local',
472 'forceSSLWithSSLPolicyAndGet' => [
474 'REQUEST_METHOD' => 'GET',
477 'sslPolicy' => BaseURL::SSL_POLICY_FULL,
478 'url' => 'https://friendica.local',
485 * Test the checkRedirectHTTPS() method
486 * @dataProvider dataCheckRedirectHTTPS
488 public function testCheckRedirectHTTPS($server, $forceSSL, $sslPolicy, $url, $redirect)
490 $configMock = \Mockery::mock(IManageConfigValues::class);
491 $configMock->shouldReceive('get')->with('config', 'hostname')->andReturn('friendica.local');
492 $configMock->shouldReceive('get')->with('system', 'urlpath')->andReturn('new/test');
493 $configMock->shouldReceive('get')->with('system', 'ssl_policy')->andReturn($sslPolicy);
494 $configMock->shouldReceive('get')->with('system', 'url')->andReturn($url);
495 $configMock->shouldReceive('get')->with('system', 'force_ssl')->andReturn($forceSSL);
497 $baseUrl = new BaseURL($configMock, $server);
499 self::assertEquals($redirect, $baseUrl->checkRedirectHttps());
502 public function dataWrongSave()
506 'fail' => 'hostname',
508 'wrongSSLPolicy' => [
509 'fail' => 'sslPolicy',
521 * Test the save() method with wrong parameters
522 * @dataProvider dataWrongSave
524 public function testWrongSave($fail)
526 $configMock = \Mockery::mock(IManageConfigValues::class);
527 $configMock->shouldReceive('get')->with('config', 'hostname')->andReturn('friendica.local');
528 $configMock->shouldReceive('get')->with('system', 'urlpath')->andReturn('new/test');
529 $configMock->shouldReceive('get')->with('system', 'ssl_policy')->andReturn(BaseURL::DEFAULT_SSL_SCHEME);
530 $configMock->shouldReceive('get')->with('system', 'url')->andReturn('http://friendica.local/new/test');
534 $configMock->shouldReceive('set')->with('config', 'hostname', \Mockery::any())->andReturn(false)->once();
537 $configMock->shouldReceive('set')->with('config', 'hostname', \Mockery::any())->andReturn(true)->twice();
538 $configMock->shouldReceive('set')->with('system', 'ssl_policy', \Mockery::any())->andReturn(false)->once();
541 $configMock->shouldReceive('set')->with('config', 'hostname', \Mockery::any())->andReturn(true)->twice();
542 $configMock->shouldReceive('set')->with('system', 'ssl_policy', \Mockery::any())->andReturn(true)->twice();
543 $configMock->shouldReceive('set')->with('system', 'urlpath', \Mockery::any())->andReturn(false)->once();
546 $configMock->shouldReceive('set')->with('config', 'hostname', \Mockery::any())->andReturn(true)->twice();
547 $configMock->shouldReceive('set')->with('system', 'ssl_policy', \Mockery::any())->andReturn(true)->twice();
548 $configMock->shouldReceive('set')->with('system', 'urlpath', \Mockery::any())->andReturn(true)->twice();
549 $configMock->shouldReceive('set')->with('system', 'url', \Mockery::any())->andReturn(false)->once();
553 $baseUrl = new BaseURL($configMock, []);
554 self::assertFalse($baseUrl->save('test', 10, 'nope'));
556 // nothing should have changed because we never successfully saved anything
557 self::assertEquals('friendica.local', $baseUrl->getHostname());
558 self::assertEquals('new/test', $baseUrl->getUrlPath());
559 self::assertEquals(BaseURL::DEFAULT_SSL_SCHEME, $baseUrl->getSSLPolicy());
560 self::assertEquals('http://friendica.local/new/test', $baseUrl->get());