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\App;
24 use Friendica\Core\Config\Capability\IManageConfigValues;
25 use Friendica\Core\System;
26 use Friendica\Util\Strings;
27 use Friendica\Network\HTTPException;
28 use GuzzleHttp\Psr7\ServerRequest;
29 use GuzzleHttp\Psr7\Uri;
30 use Psr\Http\Message\UriInterface;
31 use Psr\Log\LoggerInterface;
34 * A class which checks and contains the basic
35 * environment for the BaseURL (url, urlpath, ssl_policy, hostname, scheme)
37 class BaseURL extends Uri implements UriInterface
39 public function __construct(IManageConfigValues $config, LoggerInterface $logger, array $server = [])
41 $url = $config->get('system', 'url');
43 $logger->critical('Invalid config - Missing system.url');
44 $url = ServerRequest::getUriFromGlobals()
46 ->withPath($this->determineURLPath($server));
49 parent::__construct($url);
53 * Figure out if we are running at the top of a domain or in a subdirectory
55 private function determineURLPath(array $server): string
57 /* Relative script path to the web server root
58 * Not all of those $_SERVER properties can be present, so we do by inverse priority order
61 ($server['REDIRECT_URL'] ?? '') ?:
62 ($server['REDIRECT_URI'] ?? '') ?:
63 ($server['REDIRECT_SCRIPT_URL'] ?? '') ?:
64 ($server['SCRIPT_URL'] ?? '') ?:
65 $server['REQUEST_URI'] ?? '';
67 /* $relativeScriptPath gives /relative/path/to/friendica/module/parameter
68 * QUERY_STRING gives pagename=module/parameter
70 * To get /relative/path/to/friendica we perform dirname() for as many levels as there are slashes in the QUERY_STRING
72 if (!empty($relativeScriptPath)) {
74 if (!empty($server['QUERY_STRING'])) {
75 return trim(dirname($relativeScriptPath, substr_count(trim($server['QUERY_STRING'], '/'), '/') + 1), '/');
78 $scriptPathParts = explode('?', $relativeScriptPath, 2);
79 return trim($scriptPathParts[0], '/');
87 * Removes the base url from an url. This avoids some mixed content problems.
89 * @param string $origURL
91 * @return string The cleaned url
93 public function remove(string $origURL): string
95 // Remove the hostname from the url if it is an internal link
96 $nurl = Strings::normaliseLink($origURL);
97 $base = Strings::normaliseLink($this->__toString());
98 $url = str_replace($base . '/', '', $nurl);
100 // if it is an external link return the original value
101 if ($url === $nurl) {
109 * Redirects to another module relative to the current Friendica base URL.
110 * If you want to redirect to a external URL, use System::externalRedirectTo()
112 * @param string $toUrl The destination URL (Default is empty, which is the default page of the Friendica node)
113 * @param bool $ssl if true, base URL will try to get called with https:// (works just for relative paths)
115 * @throws HTTPException\FoundException
116 * @throws HTTPException\MovedPermanentlyException
117 * @throws HTTPException\TemporaryRedirectException
119 * @throws HTTPException\InternalServerErrorException In Case the given URL is not relative to the Friendica node
121 public function redirect(string $toUrl = '', bool $ssl = false)
123 if (!empty(parse_url($toUrl, PHP_URL_SCHEME))) {
124 throw new HTTPException\InternalServerErrorException("$toUrl is not a relative path, please use System::externalRedirectTo");
127 $redirectTo = $this->__toString() . '/' . ltrim($toUrl, '/');
128 System::externalRedirect($redirectTo);