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));
48 parent::__construct((string)$url);
50 parent::__construct($url);
55 * Figure out if we are running at the top of a domain or in a subdirectory
57 private function determineURLPath(array $server): string
59 /* Relative script path to the web server root
60 * Not all of those $_SERVER properties can be present, so we do by inverse priority order
63 ($server['REDIRECT_URL'] ?? '') ?:
64 ($server['REDIRECT_URI'] ?? '') ?:
65 ($server['REDIRECT_SCRIPT_URL'] ?? '') ?:
66 ($server['SCRIPT_URL'] ?? '') ?:
67 $server['REQUEST_URI'] ?? '';
69 /* $relativeScriptPath gives /relative/path/to/friendica/module/parameter
70 * QUERY_STRING gives pagename=module/parameter
72 * To get /relative/path/to/friendica we perform dirname() for as many levels as there are slashes in the QUERY_STRING
74 if (!empty($relativeScriptPath)) {
76 if (!empty($server['QUERY_STRING'])) {
77 return trim(dirname($relativeScriptPath, substr_count(trim($server['QUERY_STRING'], '/'), '/') + 1), '/');
80 $scriptPathParts = explode('?', $relativeScriptPath, 2);
81 return trim($scriptPathParts[0], '/');
89 * Removes the base url from an url. This avoids some mixed content problems.
91 * @param string $origURL
93 * @return string The cleaned url
95 public function remove(string $origURL): string
97 // Remove the hostname from the url if it is an internal link
98 $nurl = Strings::normaliseLink($origURL);
99 $base = Strings::normaliseLink($this->__toString());
100 $url = str_replace($base . '/', '', $nurl);
102 // if it is an external link return the original value
103 if ($url === $nurl) {
111 * Redirects to another module relative to the current Friendica base URL.
112 * If you want to redirect to a external URL, use System::externalRedirectTo()
114 * @param string $toUrl The destination URL (Default is empty, which is the default page of the Friendica node)
115 * @param bool $ssl if true, base URL will try to get called with https:// (works just for relative paths)
117 * @throws HTTPException\FoundException
118 * @throws HTTPException\MovedPermanentlyException
119 * @throws HTTPException\TemporaryRedirectException
121 * @throws HTTPException\InternalServerErrorException In Case the given URL is not relative to the Friendica node
123 public function redirect(string $toUrl = '', bool $ssl = false)
125 if (!empty(parse_url($toUrl, PHP_URL_SCHEME))) {
126 throw new HTTPException\InternalServerErrorException("$toUrl is not a relative path, please use System::externalRedirectTo");
129 $redirectTo = $this->__toString() . '/' . ltrim($toUrl, '/');
130 System::externalRedirect($redirectTo);