]> git.mxchange.org Git - friendica.git/blob - src/App/BaseURL.php
[frio] Add Mute Author Server button to post actions
[friendica.git] / src / App / BaseURL.php
1 <?php
2 /**
3  * @copyright Copyright (C) 2010-2023, the Friendica project
4  *
5  * @license GNU AGPL version 3 or any later version
6  *
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.
11  *
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.
16  *
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/>.
19  *
20  */
21
22 namespace Friendica\App;
23
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;
32
33 /**
34  * A class which checks and contains the basic
35  * environment for the BaseURL (url, urlpath, ssl_policy, hostname, scheme)
36  */
37 class BaseURL extends Uri implements UriInterface
38 {
39         public function __construct(IManageConfigValues $config, LoggerInterface $logger, array $server = [])
40         {
41                 $url = $config->get('system', 'url');
42                 if (empty($url)) {
43                         $logger->critical('Invalid config - Missing system.url');
44                         $url = ServerRequest::getUriFromGlobals()
45                                                                 ->withQuery('')
46                                                                 ->withPath($this->determineURLPath($server));
47                 }
48
49                 parent::__construct($url);
50         }
51
52         /**
53          * Figure out if we are running at the top of a domain or in a subdirectory
54          */
55         private function determineURLPath(array $server): string
56         {
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
59                  */
60                 $relativeScriptPath =
61                         ($server['REDIRECT_URL'] ?? '') ?:
62                                 ($server['REDIRECT_URI'] ?? '') ?:
63                                         ($server['REDIRECT_SCRIPT_URL'] ?? '') ?:
64                                                 ($server['SCRIPT_URL'] ?? '') ?:
65                                                         $server['REQUEST_URI'] ?? '';
66
67                 /* $relativeScriptPath gives /relative/path/to/friendica/module/parameter
68                  * QUERY_STRING gives pagename=module/parameter
69                  *
70                  * To get /relative/path/to/friendica we perform dirname() for as many levels as there are slashes in the QUERY_STRING
71                  */
72                 if (!empty($relativeScriptPath)) {
73                         // Module
74                         if (!empty($server['QUERY_STRING'])) {
75                                 return trim(dirname($relativeScriptPath, substr_count(trim($server['QUERY_STRING'], '/'), '/') + 1), '/');
76                         } else {
77                                 // Root page
78                                 $scriptPathParts = explode('?', $relativeScriptPath, 2);
79                                 return trim($scriptPathParts[0], '/');
80                         }
81                 }
82
83                 return '';
84         }
85
86         /**
87          * Removes the base url from an url. This avoids some mixed content problems.
88          *
89          * @param string $origURL
90          *
91          * @return string The cleaned url
92          */
93         public function remove(string $origURL): string
94         {
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);
99
100                 // if it is an external link return the original value
101                 if ($url === $nurl) {
102                         return $origURL;
103                 } else {
104                         return $url;
105                 }
106         }
107
108         /**
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()
111          *
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)
114          *
115          * @throws HTTPException\FoundException
116          * @throws HTTPException\MovedPermanentlyException
117          * @throws HTTPException\TemporaryRedirectException
118          *
119          * @throws HTTPException\InternalServerErrorException In Case the given URL is not relative to the Friendica node
120          */
121         public function redirect(string $toUrl = '', bool $ssl = false)
122         {
123                 if (!empty(parse_url($toUrl, PHP_URL_SCHEME))) {
124                         throw new HTTPException\InternalServerErrorException("$toUrl is not a relative path, please use System::externalRedirectTo");
125                 }
126
127                 $redirectTo = $this->__toString() . '/' . ltrim($toUrl, '/');
128                 System::externalRedirect($redirectTo);
129         }
130
131         public function isLocalUrl(string $url): bool
132         {
133                 return strpos(Strings::normaliseLink($url), Strings::normaliseLink((string)$this)) === 0;
134         }
135
136         public function isLocalUri(UriInterface $uri): bool
137         {
138                 return $this->isLocalUrl((string)$uri);
139         }
140 }