Create own base URL class which holds the whole base url business logic
authorPhilipp Holzer <admin@philipp.info>
Mon, 8 Apr 2019 19:12:10 +0000 (21:12 +0200)
committerPhilipp Holzer <admin@philipp.info>
Tue, 9 Apr 2019 06:31:16 +0000 (08:31 +0200)
16 files changed:
boot.php
config/defaults.config.php
mod/admin.php
src/App.php
src/Core/Authentication.php
src/Core/Session.php
src/Core/System.php
src/Core/Update.php
src/Factory/DependencyFactory.php
src/Model/Contact.php
src/Network/Probe.php
src/Protocol/DFRN.php
src/Util/BaseURL.php [new file with mode: 0644]
src/Util/Config/ConfigFileSaver.php [deleted file]
src/Util/Network.php
tests/src/Util/Config/ConfigFileSaverTest.php [deleted file]

index e75b2ab..dfedcdb 100644 (file)
--- a/boot.php
+++ b/boot.php
@@ -82,17 +82,6 @@ define('MAX_IMAGE_LENGTH',        -1);
  */
 define('DEFAULT_DB_ENGINE',  'InnoDB');
 
-/**
- * @name SSL Policy
- *
- * SSL redirection policies
- * @{
- */
-define('SSL_POLICY_NONE',         0);
-define('SSL_POLICY_FULL',         1);
-define('SSL_POLICY_SELFSIGN',     2);
-/* @}*/
-
 /** @deprecated since version 2019.03, please use \Friendica\Module\Register::CLOSED instead */
 define('REGISTER_CLOSED',        \Friendica\Module\Register::CLOSED);
 /** @deprecated since version 2019.03, please use \Friendica\Module\Register::APPROVE instead */
index 0d9e55c..b42bc8c 100644 (file)
@@ -377,11 +377,6 @@ return [
                // Maximum number of posts that a user can send per month with the API. 0 to disable monthly throttling.
                'throttle_limit_month' => 0,
 
-               // urlpath (String)
-               // If you are using a subdirectory of your domain you will need to put the relative path (from the root of your domain) here.
-               // For instance if your URL is 'http://example.com/directory/subdirectory', set urlpath to 'directory/subdirectory'.
-               'urlpath' => '',
-
                // username_min_length (Integer)
                // The minimum character length a username can be.
                // This length is check once the username has been trimmed and multiple spaces have been collapsed into one.
index 0df907c..db8bb40 100644 (file)
@@ -32,6 +32,7 @@ use Friendica\Module\Tos;
 use Friendica\Protocol\PortableContact;
 use Friendica\Util\Arrays;
 use Friendica\Util\BasePath;
+use Friendica\Util\BaseURL;
 use Friendica\Util\DateTimeFormat;
 use Friendica\Util\Network;
 use Friendica\Util\Strings;
@@ -1041,9 +1042,6 @@ function admin_page_site_post(App $a)
                update_table($a, "gcontact", ['connect', 'addr'], $old_host, $new_host);
 
                // update config
-               $configFileSaver = new \Friendica\Util\Config\ConfigFileSaver($a->getBasePath());
-               $configFileSaver->addConfigValue('config', 'hostname', parse_url($new_url, PHP_URL_HOST));
-               $configFileSaver->saveToConfigFile();
                Config::set('system', 'url', $new_url);
                $a->setBaseURL($new_url);
 
@@ -1199,7 +1197,7 @@ function admin_page_site_post(App $a)
                $diaspora_enabled = false;
        }
        if ($ssl_policy != intval(Config::get('system', 'ssl_policy'))) {
-               if ($ssl_policy == SSL_POLICY_FULL) {
+               if ($ssl_policy == BaseURL::SSL_POLICY_FULL) {
                        q("UPDATE `contact` SET
                                `url`     = REPLACE(`url`    , 'http:' , 'https:'),
                                `photo`   = REPLACE(`photo`  , 'http:' , 'https:'),
@@ -1217,7 +1215,7 @@ function admin_page_site_post(App $a)
                                `thumb`   = REPLACE(`thumb`  , 'http:' , 'https:')
                                WHERE 1 "
                        );
-               } elseif ($ssl_policy == SSL_POLICY_SELFSIGN) {
+               } elseif ($ssl_policy == BaseURL::SSL_POLICY_SELFSIGN) {
                        q("UPDATE `contact` SET
                                `url`     = REPLACE(`url`    , 'https:' , 'http:'),
                                `photo`   = REPLACE(`photo`  , 'https:' , 'http:'),
@@ -1473,9 +1471,9 @@ function admin_page_site(App $a)
        ];
 
        $ssl_choices = [
-               SSL_POLICY_NONE => L10n::t("No SSL policy, links will track page SSL state"),
-               SSL_POLICY_FULL => L10n::t("Force all links to use SSL"),
-               SSL_POLICY_SELFSIGN => L10n::t("Self-signed certificate, use SSL for local links only \x28discouraged\x29")
+               BaseURL::SSL_POLICY_NONE => L10n::t("No SSL policy, links will track page SSL state"),
+               BaseURL::SSL_POLICY_FULL => L10n::t("Force all links to use SSL"),
+               BaseURL::SSL_POLICY_SELFSIGN => L10n::t("Self-signed certificate, use SSL for local links only \x28discouraged\x29")
        ];
 
        $check_git_version_choices = [
index 2576cc5..3e1dc14 100644 (file)
@@ -8,7 +8,6 @@ use Detection\MobileDetect;
 use DOMDocument;
 use DOMXPath;
 use Exception;
-use FastRoute\RouteCollector;
 use Friendica\Core\Config\Cache\IConfigCache;
 use Friendica\Core\Config\Configuration;
 use Friendica\Core\Hook;
@@ -16,6 +15,7 @@ use Friendica\Core\Theme;
 use Friendica\Database\DBA;
 use Friendica\Model\Profile;
 use Friendica\Network\HTTPException\InternalServerErrorException;
+use Friendica\Util\BaseURL;
 use Friendica\Util\Config\ConfigFileLoader;
 use Friendica\Util\HTTPSignature;
 use Friendica\Util\Profiler;
@@ -84,9 +84,9 @@ class App
        private $router;
 
        /**
-        * @var string The App URL path
+        * @var BaseURL
         */
-       private $urlPath;
+       private $baseURL;
 
        /**
         * @var bool true, if the call is from the Friendica APP, otherwise false
@@ -178,6 +178,11 @@ class App
                return $this->mode;
        }
 
+       /**
+        * Returns the router of the Application
+        *
+        * @return App\Router
+        */
        public function getRouter()
        {
                return $this->router;
@@ -220,8 +225,6 @@ class App
        }
 
        public $queue;
-       private $scheme;
-       private $hostname;
 
        /**
         * @brief App constructor.
@@ -229,19 +232,21 @@ class App
         * @param Configuration    $config    The Configuration
         * @param App\Mode         $mode      The mode of this Friendica app
         * @param App\Router       $router    The router of this Friendica app
+        * @param BaseURL          $baseURL   The full base URL of this Friendica app
         * @param LoggerInterface  $logger    The current app logger
         * @param Profiler         $profiler  The profiler of this application
         * @param bool             $isBackend Whether it is used for backend or frontend (Default true=backend)
         *
         * @throws Exception if the Basepath is not usable
         */
-       public function __construct(Configuration $config, App\Mode $mode, App\Router $router, LoggerInterface $logger, Profiler $profiler, $isBackend = true)
+       public function __construct(Configuration $config, App\Mode $mode, App\Router $router, BaseURL $baseURL, LoggerInterface $logger, Profiler $profiler, $isBackend = true)
        {
                BaseObject::setApp($this);
 
                $this->config   = $config;
                $this->mode     = $mode;
                $this->router   = $router;
+               $this->baseURL  = $baseURL;
                $this->profiler = $profiler;
                $this->logger   = $logger;
 
@@ -257,26 +262,6 @@ class App
                // This has to be quite large to deal with embedded private photos
                ini_set('pcre.backtrack_limit', 500000);
 
-               $this->scheme = 'http';
-
-               if (!empty($_SERVER['HTTPS']) ||
-                       !empty($_SERVER['HTTP_FORWARDED']) && preg_match('/proto=https/', $_SERVER['HTTP_FORWARDED']) ||
-                       !empty($_SERVER['HTTP_X_FORWARDED_PROTO']) && $_SERVER['HTTP_X_FORWARDED_PROTO'] == 'https' ||
-                       !empty($_SERVER['HTTP_X_FORWARDED_SSL']) && $_SERVER['HTTP_X_FORWARDED_SSL'] == 'on' ||
-                       !empty($_SERVER['FRONT_END_HTTPS']) && $_SERVER['FRONT_END_HTTPS'] == 'on' ||
-                       !empty($_SERVER['SERVER_PORT']) && (intval($_SERVER['SERVER_PORT']) == 443) // XXX: reasonable assumption, but isn't this hardcoding too much?
-               ) {
-                       $this->scheme = 'https';
-               }
-
-               if (!empty($_SERVER['SERVER_NAME'])) {
-                       $this->hostname = $_SERVER['SERVER_NAME'];
-
-                       if (!empty($_SERVER['SERVER_PORT']) && $_SERVER['SERVER_PORT'] != 80 && $_SERVER['SERVER_PORT'] != 443) {
-                               $this->hostname .= ':' . $_SERVER['SERVER_PORT'];
-                       }
-               }
-
                set_include_path(
                        get_include_path() . PATH_SEPARATOR
                        . $this->getBasePath() . DIRECTORY_SEPARATOR . 'include' . PATH_SEPARATOR
@@ -354,8 +339,6 @@ class App
         */
        public function reload()
        {
-               $this->determineURLPath();
-
                $this->getMode()->determine($this->getBasePath());
 
                if ($this->getMode()->has(App\Mode::DBAVAILABLE)) {
@@ -398,97 +381,28 @@ class App
        }
 
        /**
-        * Figure out if we are running at the top of a domain or in a sub-directory and adjust accordingly
+        * Returns the scheme of the current call
+        * @return string
+        *
+        * @deprecated 2019.06 - use BaseURL->getScheme() instead
         */
-       private function determineURLPath()
-       {
-               /*
-                * The automatic path detection in this function is currently deactivated,
-                * see issue https://github.com/friendica/friendica/issues/6679
-                *
-                * The problem is that the function seems to be confused with some url.
-                * These then confuses the detection which changes the url path.
-                */
-
-               /* Relative script path to the web server root
-                * Not all of those $_SERVER properties can be present, so we do by inverse priority order
-                */
-/*
-               $relative_script_path = '';
-               $relative_script_path = defaults($_SERVER, 'REDIRECT_URL'       , $relative_script_path);
-               $relative_script_path = defaults($_SERVER, 'REDIRECT_URI'       , $relative_script_path);
-               $relative_script_path = defaults($_SERVER, 'REDIRECT_SCRIPT_URL', $relative_script_path);
-               $relative_script_path = defaults($_SERVER, 'SCRIPT_URL'         , $relative_script_path);
-               $relative_script_path = defaults($_SERVER, 'REQUEST_URI'        , $relative_script_path);
-*/
-               $this->urlPath = $this->config->get('system', 'urlpath');
-
-               /* $relative_script_path gives /relative/path/to/friendica/module/parameter
-                * QUERY_STRING gives pagename=module/parameter
-                *
-                * To get /relative/path/to/friendica we perform dirname() for as many levels as there are slashes in the QUERY_STRING
-                */
-/*
-               if (!empty($relative_script_path)) {
-                       // Module
-                       if (!empty($_SERVER['QUERY_STRING'])) {
-                               $path = trim(rdirname($relative_script_path, substr_count(trim($_SERVER['QUERY_STRING'], '/'), '/') + 1), '/');
-                       } else {
-                               // Root page
-                               $path = trim($relative_script_path, '/');
-                       }
-
-                       if ($path && $path != $this->urlPath) {
-                               $this->urlPath = $path;
-                       }
-               }
-*/
-       }
-
        public function getScheme()
        {
-               return $this->scheme;
+               return $this->baseURL->getScheme();
        }
 
        /**
-        * @brief Retrieves the Friendica instance base URL
+        * Retrieves the Friendica instance base URL
         *
-        * This function assembles the base URL from multiple parts:
-        * - Protocol is determined either by the request or a combination of
-        * system.ssl_policy and the $ssl parameter.
-        * - Host name is determined either by system.hostname or inferred from request
-        * - Path is inferred from SCRIPT_NAME
+        * @param bool $ssl Whether to append http or https under BaseURL::SSL_POLICY_SELFSIGN
         *
-        * Note: $ssl parameter value doesn't directly correlate with the resulting protocol
-        *
-        * @param bool $ssl Whether to append http or https under SSL_POLICY_SELFSIGN
         * @return string Friendica server base URL
-        * @throws InternalServerErrorException
+        *
+        * @deprecated 2019.06 - use BaseURL->get($ssl) instead
         */
        public function getBaseURL($ssl = false)
        {
-               $scheme = $this->scheme;
-
-               if ($this->config->get('system', 'ssl_policy') == SSL_POLICY_FULL) {
-                       $scheme = 'https';
-               }
-
-               //      Basically, we have $ssl = true on any links which can only be seen by a logged in user
-               //      (and also the login link). Anything seen by an outsider will have it turned off.
-
-               if ($this->config->get('system', 'ssl_policy') == SSL_POLICY_SELFSIGN) {
-                       if ($ssl) {
-                               $scheme = 'https';
-                       } else {
-                               $scheme = 'http';
-                       }
-               }
-
-               if ($this->config->get('config', 'hostname') != '') {
-                       $this->hostname = $this->config->get('config', 'hostname');
-               }
-
-               return $scheme . '://' . $this->hostname . (!empty($this->getURLPath()) ? '/' . $this->getURLPath() : '' );
+               return $this->baseURL->get($ssl);
        }
 
        /**
@@ -497,55 +411,36 @@ class App
         * Clears the baseurl cache to prevent inconsistencies
         *
         * @param string $url
-        * @throws InternalServerErrorException
+        *
+        * @deprecated 2019.06 - use BaseURL->saveByURL($url) instead
         */
        public function setBaseURL($url)
        {
-               $parsed = @parse_url($url);
-               $hostname = '';
-
-               if (!empty($parsed)) {
-                       if (!empty($parsed['scheme'])) {
-                               $this->scheme = $parsed['scheme'];
-                       }
-
-                       if (!empty($parsed['host'])) {
-                               $hostname = $parsed['host'];
-                       }
-
-                       if (!empty($parsed['port'])) {
-                               $hostname .= ':' . $parsed['port'];
-                       }
-                       if (!empty($parsed['path'])) {
-                               $this->urlPath = trim($parsed['path'], '\\/');
-                       }
-
-                       if (file_exists($this->getBasePath() . '/.htpreconfig.php')) {
-                               include $this->getBasePath() . '/.htpreconfig.php';
-                       }
-
-                       if ($this->config->get('config', 'hostname') != '') {
-                               $this->hostname = $this->config->get('config', 'hostname');
-                       }
-
-                       if (!isset($this->hostname) || ($this->hostname == '')) {
-                               $this->hostname = $hostname;
-                       }
-               }
+               $this->baseURL->saveByURL($url);
        }
 
+       /**
+        * Returns the current hostname
+        *
+        * @return string
+        *
+        * @deprecated 2019.06 - use BaseURL->getHostname() instead
+        */
        public function getHostName()
        {
-               if ($this->config->get('config', 'hostname') != '') {
-                       $this->hostname = $this->config->get('config', 'hostname');
-               }
-
-               return $this->hostname;
+               return $this->baseURL->getHostname();
        }
 
+       /**
+        * Returns the sub-path of the full URL
+        *
+        * @return string
+        *
+        * @deprecated 2019.06 - use BaseURL->getUrlPath() instead
+        */
        public function getURLPath()
        {
-               return $this->urlPath;
+               return $this->baseURL->getUrlPath();
        }
 
        /**
@@ -1120,7 +1015,7 @@ class App
                if (!$this->getMode()->isInstall()) {
                        // Force SSL redirection
                        if ($this->config->get('system', 'force_ssl') && ($this->getScheme() == "http")
-                               && intval($this->config->get('system', 'ssl_policy')) == SSL_POLICY_FULL
+                               && intval($this->config->get('system', 'ssl_policy')) == BaseURL::SSL_POLICY_FULL
                                && strpos($this->getBaseURL(), 'https://') === 0
                                && $_SERVER['REQUEST_METHOD'] == 'GET') {
                                header('HTTP/1.1 302 Moved Temporarily');
@@ -1458,7 +1353,7 @@ class App
                header("X-Friendica-Version: " . FRIENDICA_VERSION);
                header("Content-type: text/html; charset=utf-8");
 
-               if ($this->config->get('system', 'hsts') && ($this->config->get('system', 'ssl_policy') == SSL_POLICY_FULL)) {
+               if ($this->config->get('system', 'hsts') && ($this->config->get('system', 'ssl_policy') == BaseUrl::SSL_POLICY_FULL)) {
                        header("Strict-Transport-Security: max-age=31536000");
                }
 
index 106ba2a..1963d34 100644 (file)
@@ -8,6 +8,7 @@ namespace Friendica\Core;
 use Friendica\BaseObject;
 use Friendica\Database\DBA;
 use Friendica\Model\User;
+use Friendica\Util\BaseURL;
 use Friendica\Util\DateTimeFormat;
 
 /**
@@ -51,7 +52,7 @@ class Authentication extends BaseObject
                        $value = "";
                }
 
-               setcookie("Friendica", $value, $time, "/", "", (Config::get('system', 'ssl_policy') == SSL_POLICY_FULL), true);
+               setcookie("Friendica", $value, $time, "/", "", (Config::get('system', 'ssl_policy') == BaseUrl::SSL_POLICY_FULL), true);
        }
 
        /**
index d9143c8..f1da864 100644 (file)
@@ -7,6 +7,7 @@ namespace Friendica\Core;
 
 use Friendica\Core\Session\CacheSessionHandler;
 use Friendica\Core\Session\DatabaseSessionHandler;
+use Friendica\Util\BaseURL;
 
 /**
  * High-level Session service class
@@ -24,7 +25,7 @@ class Session
                ini_set('session.use_only_cookies', 1);
                ini_set('session.cookie_httponly', 1);
 
-               if (Config::get('system', 'ssl_policy') == SSL_POLICY_FULL) {
+               if (Config::get('system', 'ssl_policy') == BaseUrl::SSL_POLICY_FULL) {
                        ini_set('session.cookie_secure', 1);
                }
 
index 45a88fe..83c3dc9 100644 (file)
@@ -23,7 +23,7 @@ class System extends BaseObject
        /**
         * @brief Retrieves the Friendica instance base URL
         *
-        * @param bool $ssl Whether to append http or https under SSL_POLICY_SELFSIGN
+        * @param bool $ssl Whether to append http or https under BaseURL::SSL_POLICY_SELFSIGN
         * @return string Friendica server base URL
         * @throws InternalServerErrorException
         */
index d2bbc23..328938f 100644 (file)
@@ -3,12 +3,8 @@
 namespace Friendica\Core;
 
 use Friendica\App;
-use Friendica\Core\Config\Cache\IConfigCache;
 use Friendica\Database\DBA;
 use Friendica\Database\DBStructure;
-use Friendica\Util\BasePath;
-use Friendica\Util\Config\ConfigFileLoader;
-use Friendica\Util\Config\ConfigFileSaver;
 use Friendica\Util\Strings;
 
 class Update
@@ -32,7 +28,7 @@ class Update
                }
 
                // Check if the config files are set correctly
-               self::checkConfigFile($basePath, $mode);
+               self::checkBaseSettings($_SERVER);
 
                // Don't check the status if the last update was failed
                if (Config::get('system', 'update', Update::SUCCESS, true) == Update::FAILED) {
@@ -229,142 +225,9 @@ class Update
                }
        }
 
-       /**
-        * Checks the config settings and saves given config values into the config file
-        *
-        * @param string    $basePath The basepath of Friendica
-        * @param App\Mode  $mode     The current App mode
-        *
-        * @return bool True, if something has been saved
-        */
-       public static function checkConfigFile($basePath, App\Mode $mode)
+       public static function checkBaseSettings(array $server)
        {
-               if (empty($basePath)) {
-                       $basePath = BasePath::create(dirname(__DIR__, 2));
-               }
-
-               $config = [
-                       'config' => [
-                               'hostname' => [
-                                       'allowEmpty' => false,
-                                       'default' => '',
-                               ],
-                       ],
-                       'system' => [
-                               'basepath' => [
-                                       'allowEmpty' => false,
-                                       'default' => $basePath,
-                               ],
-                       ]
-               ];
-
-               $configFileLoader = new ConfigFileLoader($basePath, $mode);
-               $configCache = new Config\Cache\ConfigCache();
-               $configFileLoader->setupCache($configCache, true);
-
-               // checks if something is to update, otherwise skip this function at all
-               $missingConfig = $configCache->keyDiff($config);
-               if (empty($missingConfig)) {
-                       return true;
-               }
-
-               // We just want one update process
-               if (Lock::acquire('config_update')) {
-                       $configFileSaver = new ConfigFileSaver($basePath);
-
-                       $updated = false;
-                       $toDelete = [];
-
-                       foreach ($missingConfig as $category => $keys) {
-                               foreach ($keys as $key => $value) {
-                                       if (self::updateConfigEntry($configCache, $configFileSaver, $category, $key, $value['allowEmpty'], $value['default'])) {
-                                               $toDelete[] = ['cat' => $category, 'key' => $key];
-                                               $updated = true;
-                                       };
-                               }
-                       }
-
-                       // In case there is nothing to do, skip the update
-                       if (!$updated) {
-                               Lock::release('config_update');
-                               return true;
-                       }
-
-                       if (!$configFileSaver->saveToConfigFile()) {
-                               Logger::alert('Config entry update failed - maybe wrong permission?');
-                               Lock::release('config_update');
-                               return false;
-                       }
-
-                       // After the successful save, remove the db values
-                       foreach ($toDelete as $delete) {
-                               DBA::delete('config', ['cat' => $delete['cat'], 'k' => $delete['key']]);
-                       }
-
-                       Lock::release('config_update');
-               }
 
-               return true;
-       }
-
-       /**
-        * Adds a value to the ConfigFileSave in case it isn't already updated
-        *
-        * @param IConfigCache    $configCache     The cached config file
-        * @param ConfigFileSaver $configFileSaver The config file saver
-        * @param string          $cat             The config category
-        * @param string          $key             The config key
-        * @param bool            $allowEmpty      If true, empty values are valid (Default there has to be a variable)
-        * @param string          $default         A default value, if none of the settings are valid
-        *
-        * @return boolean True, if a value was updated
-        *
-        * @throws \Exception if DBA or Logger doesn't work
-        */
-       private static function updateConfigEntry(
-               IConfigCache $configCache,
-               ConfigFileSaver $configFileSaver,
-               $cat,
-               $key,
-               $allowEmpty = false,
-               $default = '')
-       {
-
-               // check if the config file differs from the whole configuration (= The db contains other values)
-               $fileValue = $configCache->get($cat, $key);
-               $dbConfig  = DBA::selectFirst('config', ['v'], ['cat' => $cat, 'k' => $key]);
-
-               if (DBA::isResult($dbConfig)) {
-                       $dbValue = $dbConfig['v'];
-               } else {
-                       $dbValue = null;
-               }
-
-               // If the db contains a config value, check it
-               if ((
-                               ($allowEmpty && isset($dbValue)) ||
-                               (!$allowEmpty && !empty($dbValue))
-                       ) &&
-                       $fileValue !== $dbValue) {
-                       Logger::info('Difference in config found', ['cat' => $cat, 'key' => $key, 'file' => $fileValue, 'db' => $dbValue]);
-                       $configFileSaver->addConfigValue($cat, $key, $dbValue);
-                       return true;
-
-               // If both config values are not set, use the default value
-               } elseif (
-                       ($allowEmpty && !isset($fileValue) && !isset($dbValue)) ||
-                       (!$allowEmpty && empty($fileValue) && empty($dbValue) && !empty($default))) {
-
-                       Logger::info('Using default for config', ['cat' => $cat, 'key' => $key, 'value' => $default]);
-                       $configFileSaver->addConfigValue($cat, $key, $default);
-                       return true;
-
-               // If either the file config value isn't empty or the db value is the same as the
-               // file config value, skip it
-               } else {
-                       Logger::debug('No Difference in config found', ['cat' => $cat, 'key' => $key, 'value' => $fileValue, 'db' => $dbValue]);
-                       return false;
-               }
        }
 
        /**
index 0f33e09..e55a52d 100644 (file)
@@ -5,6 +5,7 @@ namespace Friendica\Factory;
 use Friendica\App;
 use Friendica\Factory;
 use Friendica\Util\BasePath;
+use Friendica\Util\BaseURL;
 use Friendica\Util\Config;
 
 class DependencyFactory
@@ -34,7 +35,8 @@ class DependencyFactory
                Factory\ConfigFactory::createPConfig($configCache);
                $logger = Factory\LoggerFactory::create($channel, $config, $profiler);
                Factory\LoggerFactory::createDev($channel, $config, $profiler);
+               $baseURL = new BaseURL($config, $_SERVER);
 
-               return new App($config, $mode, $router, $logger, $profiler, $isBackend);
+               return new App($config, $mode, $router, $baseURL, $logger, $profiler, $isBackend);
        }
 }
index fe373ae..b197834 100644 (file)
@@ -22,6 +22,7 @@ use Friendica\Protocol\Diaspora;
 use Friendica\Protocol\OStatus;
 use Friendica\Protocol\PortableContact;
 use Friendica\Protocol\Salmon;
+use Friendica\Util\BaseURL;
 use Friendica\Util\DateTimeFormat;
 use Friendica\Util\Network;
 use Friendica\Util\Strings;
@@ -1938,7 +1939,7 @@ class Contact extends BaseObject
        public static function updateSslPolicy(array $contact, $new_policy)
        {
                $ssl_changed = false;
-               if ((intval($new_policy) == SSL_POLICY_SELFSIGN || $new_policy === 'self') && strstr($contact['url'], 'https:')) {
+               if ((intval($new_policy) == BaseURL::SSL_POLICY_SELFSIGN || $new_policy === 'self') && strstr($contact['url'], 'https:')) {
                        $ssl_changed = true;
                        $contact['url']     =   str_replace('https:', 'http:', $contact['url']);
                        $contact['request'] =   str_replace('https:', 'http:', $contact['request']);
@@ -1948,7 +1949,7 @@ class Contact extends BaseObject
                        $contact['poco']    =   str_replace('https:', 'http:', $contact['poco']);
                }
 
-               if ((intval($new_policy) == SSL_POLICY_FULL || $new_policy === 'full') && strstr($contact['url'], 'http:')) {
+               if ((intval($new_policy) == BaseURL::SSL_POLICY_FULL || $new_policy === 'full') && strstr($contact['url'], 'http:')) {
                        $ssl_changed = true;
                        $contact['url']     =   str_replace('http:', 'https:', $contact['url']);
                        $contact['request'] =   str_replace('http:', 'https:', $contact['request']);
index 008106e..b0d2630 100644 (file)
@@ -10,6 +10,7 @@ namespace Friendica\Network;
  */
 
 use DOMDocument;
+use DomXPath;
 use Friendica\Core\Cache;
 use Friendica\Core\Config;
 use Friendica\Core\Logger;
@@ -18,15 +19,14 @@ use Friendica\Core\System;
 use Friendica\Database\DBA;
 use Friendica\Model\Contact;
 use Friendica\Model\Profile;
+use Friendica\Protocol\ActivityPub;
 use Friendica\Protocol\Email;
 use Friendica\Protocol\Feed;
-use Friendica\Protocol\ActivityPub;
 use Friendica\Util\Crypto;
 use Friendica\Util\DateTimeFormat;
 use Friendica\Util\Network;
 use Friendica\Util\Strings;
 use Friendica\Util\XML;
-use DomXPath;
 
 /**
  * @brief This class contain functions for probing URL
@@ -510,30 +510,6 @@ class Probe
                return $data;
        }
 
-       /**
-        * @brief Switch the scheme of an url between http and https
-        *
-        * @param string $url URL
-        *
-        * @return string switched URL
-        */
-       private static function switchScheme($url)
-       {
-               $parts = parse_url($url);
-
-               if (!isset($parts['scheme'])) {
-                       return $url;
-               }
-
-               if ($parts['scheme'] == 'http') {
-                       $url = str_replace('http://', 'https://', $url);
-               } elseif ($parts['scheme'] == 'https') {
-                       $url = str_replace('https://', 'http://', $url);
-               }
-
-               return $url;
-       }
-
        /**
         * @brief Checks if a profile url should be OStatus but only provides partial information
         *
@@ -566,7 +542,7 @@ class Probe
                        return $webfinger;
                }
 
-               $url = self::switchScheme($webfinger['subject']);
+               $url = Network::switchScheme($webfinger['subject']);
                $path = str_replace('{uri}', urlencode($url), $lrdd);
                $webfinger2 = self::webfinger($path, $type);
 
index 8433801..b625265 100644 (file)
@@ -29,6 +29,7 @@ use Friendica\Model\PermissionSet;
 use Friendica\Model\Profile;
 use Friendica\Model\User;
 use Friendica\Object\Image;
+use Friendica\Util\BaseURL;
 use Friendica\Util\Crypto;
 use Friendica\Util\DateTimeFormat;
 use Friendica\Util\Network;
@@ -1208,13 +1209,13 @@ class DFRN
                $ssl_val = intval(Config::get('system', 'ssl_policy'));
 
                switch ($ssl_val) {
-                       case SSL_POLICY_FULL:
+                       case BaseURL::SSL_POLICY_FULL:
                                $ssl_policy = 'full';
                                break;
-                       case SSL_POLICY_SELFSIGN:
+                       case BaseURL::SSL_POLICY_SELFSIGN:
                                $ssl_policy = 'self';
                                break;
-                       case SSL_POLICY_NONE:
+                       case BaseURL::SSL_POLICY_NONE:
                        default:
                                $ssl_policy = 'none';
                                break;
diff --git a/src/Util/BaseURL.php b/src/Util/BaseURL.php
new file mode 100644 (file)
index 0000000..a9bed2b
--- /dev/null
@@ -0,0 +1,344 @@
+<?php
+
+namespace Friendica\Util;
+
+use Friendica\Core\Config\Configuration;
+
+/**
+ * A class which checks and contains the basic
+ * environment for the BaseURL (url, urlpath, ssl_policy, hostname)
+ */
+class BaseURL
+{
+       /**
+        * No SSL necessary
+        */
+       const SSL_POLICY_NONE = 0;
+
+       /**
+        * SSL is necessary
+        */
+       const SSL_POLICY_FULL = 1;
+
+       /**
+        * SSL is optional, but preferred
+        */
+       const SSL_POLICY_SELFSIGN = 2;
+
+       /**
+        * The Friendica Config
+        * @var Configuration
+        */
+       private $config;
+
+       /**
+        * The server side variables
+        * @var array
+        */
+       private $server;
+
+       /**
+        * The hostname of the Base URL
+        * @var string
+        */
+       private $hostname;
+
+       /**
+        * The SSL_POLICY of the Base URL
+        * @var int
+        */
+       private $sslPolicy;
+
+       /**
+        * The URL sub-path of the Base URL
+        * @var string
+        */
+       private $urlPath;
+
+       /**
+        * The full URL
+        * @var string
+        */
+       private $url;
+
+       /**
+        * The current scheme of this call
+        * @var string
+        */
+       private $scheme;
+
+       /**
+        * Returns the hostname of this node
+        * @return string
+        */
+       public function getHostname()
+       {
+               return $this->hostname;
+       }
+
+       /**
+        * Returns the current scheme of this call
+        * @return string
+        */
+       public function getScheme()
+       {
+               return $this->scheme;
+       }
+
+       /**
+        * Returns the SSL policy of this node
+        * @return int
+        */
+       public function getSSLPolicy()
+       {
+               return $this->sslPolicy;
+       }
+
+       /**
+        * Returns the sub-path of this URL
+        * @return string
+        */
+       public function getUrlPath()
+       {
+               return $this->urlPath;
+       }
+
+       /**
+        * Returns the full URL of this call
+        *
+        * Note: $ssl parameter value doesn't directly correlate with the resulting protocol
+        *
+        * @param bool $ssl True, if ssl should get used
+        *
+        * @return string
+        */
+       public function get($ssl = false)
+       {
+               return (!$ssl ? $this->url : $this->returnBaseURL($ssl));
+       }
+
+       /**
+        * Save current parts of the base Url
+        *
+        * @param string? $hostname
+        * @param int?    $sslPolicy
+        * @param string? $urlPath
+        *
+        * @return bool true, if successful
+        */
+       public function save($hostname = null, $sslPolicy = null, $urlPath = null)
+       {
+               $success = true;
+
+               if (!empty($hostname)) {
+                       $this->hostname  = $hostname;
+                       if (!$this->config->set('config', 'hostname', $this->hostname)) {
+                               $success = false;
+                       }
+               }
+
+               if (isset($sslPolicy)) {
+                       $this->sslPolicy = $sslPolicy;
+                       if (!$this->config->set('system', 'ssl_policy', $this->sslPolicy)) {
+                               $success = false;
+                       }
+               }
+
+               if (isset($urlPath)) {
+                       $this->urlPath   = $urlPath;
+                       if (!$this->config->set('system', 'urlpath', $this->urlPath)) {
+                               $success = false;
+                       }
+               }
+
+               $this->determineBaseUrl();
+               if (!$this->config->set('system', 'url', $this->url)) {
+                       $success = false;
+               }
+
+               return $success;
+       }
+
+       /**
+        * Save the current url as base URL
+        *
+        * @param $url
+        *
+        * @return bool true, if the save was successful
+        */
+       public function saveByURL($url)
+       {
+               $parsed = @parse_url($url);
+
+               if (empty($parsed)) {
+                       return false;
+               }
+
+               $hostname = $parsed['host'];
+               if (!empty($hostname) && !empty($parsed['port'])) {
+                       $hostname .= ':' . $parsed['port'];
+               }
+
+               $urlPath = null;
+               if (!empty($parsed['path'])) {
+                       $urlPath = trim($parsed['path'], '\\/');
+               }
+
+               return $this->save($hostname, null, $urlPath);
+       }
+
+       /**
+        * @param Configuration $config The Friendica configuration
+        * @param array         $server The $_SERVER array
+        */
+       public function __construct(Configuration $config, array $server)
+       {
+               $this->config = $config;
+               $this->server = $server;
+
+               $this->checkConfig();
+               $this->determineSchema();
+       }
+
+       /**
+        * Check the current config during loading
+        */
+       public function checkConfig()
+       {
+               $this->hostname  = $this->config->get('config', 'hostname', null);
+               $this->urlPath   = $this->config->get('system', 'urlpath', null);
+               $this->sslPolicy = $this->config->get('system', 'ssl_policy', null);
+               $this->url       = $this->config->get('system', 'url', null);
+
+               if (empty($this->hostname)) {
+                       $this->determineHostname();
+
+                       if (!empty($this->hostname)) {
+                               $this->config->set('config', 'hostname', $this->hostname);
+                       }
+               }
+
+               if (!isset($this->urlPath)) {
+                       $this->determineURLPath();
+                       $this->config->set('system', 'urlpath', $this->urlPath);
+               }
+
+               if (!isset($this->sslPolicy)) {
+                       $this->sslPolicy = self::SSL_POLICY_NONE;
+                       $this->config->set('system', 'ssl_policy', $this->sslPolicy);
+               }
+
+               if (empty($this->url)) {
+                       $this->determineBaseUrl();
+
+                       if (!empty($url)) {
+                               $this->config->set('system', 'url', $this->url);
+                       }
+               }
+       }
+
+       /**
+        * Determines the hostname of this node if not set already
+        */
+       private function determineHostname()
+       {
+               $this->hostname = '';
+
+               if (!empty($this->server['SERVER_NAME'])) {
+                       $this->hostname = $this->server['SERVER_NAME'];
+
+                       if (!empty($this->server['SERVER_PORT']) && $this->server['SERVER_PORT'] != 80 && $this->server['SERVER_PORT'] != 443) {
+                               $this->hostname .= ':' . $this->server['SERVER_PORT'];
+                       }
+               }
+       }
+
+       /**
+        * Figure out if we are running at the top of a domain or in a sub-directory
+        */
+       private function determineURLPath()
+       {
+               $this->urlPath = '';
+
+               /*
+                * The automatic path detection in this function is currently deactivated,
+                * see issue https://github.com/friendica/friendica/issues/6679
+                *
+                * The problem is that the function seems to be confused with some url.
+                * These then confuses the detection which changes the url path.
+                */
+
+               /* Relative script path to the web server root
+                * Not all of those $_SERVER properties can be present, so we do by inverse priority order
+                */
+               $relative_script_path = '';
+               $relative_script_path = defaults($this->server, 'REDIRECT_URL', $relative_script_path);
+               $relative_script_path = defaults($this->server, 'REDIRECT_URI', $relative_script_path);
+               $relative_script_path = defaults($this->server, 'REDIRECT_SCRIPT_URL', $relative_script_path);
+               $relative_script_path = defaults($this->server, 'SCRIPT_URL', $relative_script_path);
+               $relative_script_path = defaults($this->server, 'REQUEST_URI', $relative_script_path);
+
+               /* $relative_script_path gives /relative/path/to/friendica/module/parameter
+                * QUERY_STRING gives pagename=module/parameter
+                *
+                * To get /relative/path/to/friendica we perform dirname() for as many levels as there are slashes in the QUERY_STRING
+                */
+               if (!empty($relative_script_path)) {
+                       // Module
+                       if (!empty($this->server['QUERY_STRING'])) {
+                               $this->urlPath = trim(rdirname($relative_script_path, substr_count(trim($this->server['QUERY_STRING'], '/'), '/') + 1), '/');
+                       } else {
+                               // Root page
+                               $this->urlPath = trim($relative_script_path, '/');
+                       }
+               }
+       }
+
+       /**
+        * Determine the full URL based on all parts
+        */
+       private function determineBaseUrl()
+       {
+               $scheme = 'http';
+
+               if ($this->sslPolicy == self::SSL_POLICY_FULL) {
+                       $scheme = 'https';
+               }
+
+               $this->url = $scheme . '://' . $this->hostname . (!empty($this->urlPath) ? '/' . $this->urlPath : '' );
+       }
+
+       /**
+        * Determine the scheme of the current used link
+        */
+       private function determineSchema()
+       {
+               $this->scheme = 'http';
+
+               if (!empty($this->server['HTTPS']) ||
+                       !empty($this->server['HTTP_FORWARDED']) && preg_match('/proto=https/', $this->server['HTTP_FORWARDED']) ||
+                       !empty($this->server['HTTP_X_FORWARDED_PROTO']) && $this->server['HTTP_X_FORWARDED_PROTO'] == 'https' ||
+                       !empty($this->server['HTTP_X_FORWARDED_SSL']) && $this->server['HTTP_X_FORWARDED_SSL'] == 'on' ||
+                       !empty($this->server['FRONT_END_HTTPS']) && $this->server['FRONT_END_HTTPS'] == 'on' ||
+                       !empty($this->server['SERVER_PORT']) && (intval($this->server['SERVER_PORT']) == 443) // XXX: reasonable assumption, but isn't this hardcoding too much?
+               ) {
+                       $this->scheme = 'https';
+               }
+       }
+
+       /**
+        * Returns the URL based on the current used ssl setting
+        *
+        * @param bool $ssl true, if ssl should be used
+        *
+        * @return string
+        */
+       private function returnBaseURL($ssl)
+       {
+               if ($this->sslPolicy == self::SSL_POLICY_SELFSIGN && $ssl) {
+                       return Network::switchScheme($this->url);
+               }
+
+               return $this->url;
+       }
+}
diff --git a/src/Util/Config/ConfigFileSaver.php b/src/Util/Config/ConfigFileSaver.php
deleted file mode 100644 (file)
index e32e11a..0000000
+++ /dev/null
@@ -1,341 +0,0 @@
-<?php
-
-namespace Friendica\Util\Config;
-
-/**
- * The ConfigFileSaver saves specific variables into the config-files
- *
- * It is capable of loading the following config files:
- * - *.config.php   (current)
- * - *.ini.php      (deprecated)
- * - *.htconfig.php (deprecated)
- */
-class ConfigFileSaver extends ConfigFileManager
-{
-       /**
-        * The standard indentation for config files
-        * @var string
-        */
-       const INDENT = "\t";
-
-       /**
-        * The settings array to save to
-        * @var array
-        */
-       private $settings = [];
-
-       /**
-        * Adds a given value to the config file
-        * Either it replaces the current value or it will get added
-        *
-        * @param string $cat   The configuration category
-        * @param string $key   The configuration key
-        * @param string $value The new value
-        */
-       public function addConfigValue($cat, $key, $value)
-       {
-               $settingsCount = count(array_keys($this->settings));
-
-               for ($i = 0; $i < $settingsCount; $i++) {
-                       // if already set, overwrite the value
-                       if ($this->settings[$i]['cat'] === $cat &&
-                               $this->settings[$i]['key'] === $key) {
-                               $this->settings[$i] = ['cat' => $cat, 'key' => $key, 'value' => $value];
-                               return;
-                       }
-               }
-
-               $this->settings[] = ['cat' => $cat, 'key' => $key, 'value' => $value];
-       }
-
-       /**
-        * Resetting all added configuration entries so far
-        */
-       public function reset()
-       {
-               $this->settings = [];
-       }
-
-       /**
-        * Save all added configuration entries to the given config files
-        * After updating the config entries, all configuration entries will be reseted
-        *
-        * @param string $name The name of the configuration file (default is empty, which means the default name each type)
-        *
-        * @return bool true, if at least one configuration file was successfully updated or nothing to do
-        */
-       public function saveToConfigFile($name = '')
-       {
-               // If no settings et, return true
-               if (count(array_keys($this->settings)) === 0) {
-                       return true;
-               }
-
-               $saved = false;
-
-               // Check for the *.config.php file inside the /config/ path
-               list($reading, $writing) = $this->openFile($this->getConfigFullName($name));
-               if (isset($reading) && isset($writing)) {
-                       $this->saveConfigFile($reading, $writing);
-                       // Close the current file handler and rename them
-                       if ($this->closeFile($this->getConfigFullName($name), $reading, $writing)) {
-                               // just return true, if everything went fine
-                               $saved = true;
-                       }
-               }
-
-               // Check for the *.ini.php file inside the /config/ path
-               list($reading, $writing) = $this->openFile($this->getIniFullName($name));
-               if (isset($reading) && isset($writing)) {
-                       $this->saveINIConfigFile($reading, $writing);
-                       // Close the current file handler and rename them
-                       if ($this->closeFile($this->getIniFullName($name), $reading, $writing)) {
-                               // just return true, if everything went fine
-                               $saved = true;
-                       }
-               }
-
-               // Check for the *.php file (normally .htconfig.php) inside the / path
-               list($reading, $writing) = $this->openFile($this->getHtConfigFullName($name));
-               if (isset($reading) && isset($writing)) {
-                       $this->saveToLegacyConfig($reading, $writing);
-                       // Close the current file handler and rename them
-                       if ($this->closeFile($this->getHtConfigFullName($name), $reading, $writing)) {
-                               // just return true, if everything went fine
-                               $saved = true;
-                       }
-               }
-
-               $this->reset();
-
-               return $saved;
-       }
-
-       /**
-        * Opens a config file and returns two handler for reading and writing
-        *
-        * @param string $fullName The full name of the current config
-        *
-        * @return array An array containing the two reading and writing handler
-        */
-       private function openFile($fullName)
-       {
-               if (empty($fullName)) {
-                       return [null, null];
-               }
-
-               try {
-                       $reading = fopen($fullName, 'r');
-               } catch (\Exception $exception) {
-                       return [null, null];
-               }
-
-               if (!$reading) {
-                       return [null, null];
-               }
-
-               try {
-                       $writing = fopen($fullName . '.tmp', 'w');
-               } catch (\Exception $exception) {
-                       fclose($reading);
-                       return [null, null];
-               }
-
-               if (!$writing) {
-                       fclose($reading);
-                       return [null, null];
-               }
-
-               return [$reading, $writing];
-       }
-
-       /**
-        * Close and rename the config file
-        *
-        * @param string   $fullName The full name of the current config
-        * @param resource $reading  The reading resource handler
-        * @param resource $writing  The writing resource handler
-        *
-        * @return bool True, if the close was successful
-        */
-       private function closeFile($fullName, $reading, $writing)
-       {
-               fclose($reading);
-               fclose($writing);
-
-               try {
-                       $renamed = rename($fullName, $fullName . '.old');
-               } catch (\Exception $exception) {
-                       return false;
-               }
-
-               if (!$renamed) {
-                       return false;
-               }
-
-               try {
-                       $renamed = rename($fullName . '.tmp', $fullName);
-               } catch (\Exception $exception) {
-                       // revert the move of the current config file to have at least the old config
-                       rename($fullName . '.old', $fullName);
-                       return false;
-               }
-
-               if (!$renamed) {
-                       // revert the move of the current config file to have at least the old config
-                       rename($fullName . '.old', $fullName);
-                       return false;
-               }
-
-               return true;
-       }
-
-       /**
-        * Saves all configuration values to a config file
-        *
-        * @param resource $reading The reading handler
-        * @param resource $writing The writing handler
-        */
-       private function saveConfigFile($reading, $writing)
-       {
-               $settingsCount = count(array_keys($this->settings));
-               $categoryFound = array_fill(0, $settingsCount, false);
-               $categoryBracketFound = array_fill(0, $settingsCount, false);;
-               $lineFound = array_fill(0, $settingsCount, false);;
-               $lineArrowFound = array_fill(0, $settingsCount, false);;
-
-               while (!feof($reading)) {
-
-                       $line = fgets($reading);
-
-                       // check for each added setting if we have to replace a config line
-                       for ($i = 0; $i < $settingsCount; $i++) {
-
-                               // find the first line like "'system' =>"
-                               if (!$categoryFound[$i] && stristr($line, sprintf('\'%s\'', $this->settings[$i]['cat']))) {
-                                       $categoryFound[$i] = true;
-                               }
-
-                               // find the first line with a starting bracket ( "[" )
-                               if ($categoryFound[$i] && !$categoryBracketFound[$i] && stristr($line, '[')) {
-                                       $categoryBracketFound[$i] = true;
-                               }
-
-                               // find the first line with the key like "'value'"
-                               if ($categoryBracketFound[$i] && !$lineFound[$i] && stristr($line, sprintf('\'%s\'', $this->settings[$i]['key']))) {
-                                       $lineFound[$i] = true;
-                               }
-
-                               // find the first line with an arrow ("=>") after finding the key
-                               if ($lineFound[$i] && !$lineArrowFound[$i] && stristr($line, '=>')) {
-                                       $lineArrowFound[$i] = true;
-                               }
-
-                               // find the current value and replace it
-                               if ($lineArrowFound[$i] && preg_match_all('/\'(.*?)\'/', $line, $matches, PREG_SET_ORDER)) {
-                                       $lineVal = end($matches)[0];
-                                       $line = str_replace($lineVal, '\'' . $this->settings[$i]['value'] . '\'', $line);
-                                       $categoryFound[$i] = false;
-                                       $categoryBracketFound[$i] = false;
-                                       $lineFound[$i] = false;
-                                       $lineArrowFound[$i] = false;
-                                       // if a line contains a closing bracket for the category ( "]" ) and we didn't find the key/value pair,
-                                       // add it as a new line before the closing bracket
-                               } elseif ($categoryBracketFound[$i] && !$lineArrowFound[$i] && stristr($line, ']')) {
-                                       $categoryFound[$i] = false;
-                                       $categoryBracketFound[$i] = false;
-                                       $lineFound[$i] = false;
-                                       $lineArrowFound[$i] = false;
-                                       $newLine = sprintf(self::INDENT . self::INDENT . '\'%s\' => \'%s\',' . PHP_EOL, $this->settings[$i]['key'], $this->settings[$i]['value']);
-                                       $line = $newLine . $line;
-                               }
-                       }
-
-                       fputs($writing, $line);
-               }
-       }
-
-       /**
-        * Saves a value to a ini file
-        *
-        * @param resource $reading The reading handler
-        * @param resource $writing The writing handler
-        */
-       private function saveINIConfigFile($reading, $writing)
-       {
-               $settingsCount = count(array_keys($this->settings));
-               $categoryFound = array_fill(0, $settingsCount, false);
-
-               while (!feof($reading)) {
-
-                       $line = fgets($reading);
-
-                       // check for each added setting if we have to replace a config line
-                       for ($i = 0; $i < $settingsCount; $i++) {
-
-                               // find the category of the current setting
-                               if (!$categoryFound[$i] && stristr($line, sprintf('[%s]', $this->settings[$i]['cat']))) {
-                                       $categoryFound[$i] = true;
-
-                               // check the current value
-                               } elseif ($categoryFound[$i] && preg_match_all('/^' . $this->settings[$i]['key'] . '\s*=\s*(.*?)$/', $line, $matches, PREG_SET_ORDER)) {
-                                       $line = $this->settings[$i]['key'] . ' = ' . $this->settings[$i]['value'] . PHP_EOL;
-                                       $categoryFound[$i] = false;
-
-                               // If end of INI file, add the line before the INI end
-                               } elseif ($categoryFound[$i] && (preg_match_all('/^\[.*?\]$/', $line) || preg_match_all('/^INI;.*$/', $line))) {
-                                       $categoryFound[$i] = false;
-                                       $newLine = $this->settings[$i]['key'] . ' = ' . $this->settings[$i]['value'] . PHP_EOL;
-                                       $line = $newLine . $line;
-                               }
-                       }
-
-                       fputs($writing, $line);
-               }
-       }
-
-       /**
-        * Saves a value to a .php file (normally .htconfig.php)
-        *
-        * @param resource $reading The reading handler
-        * @param resource $writing The writing handler
-        */
-       private function saveToLegacyConfig($reading, $writing)
-       {
-               $settingsCount = count(array_keys($this->settings));
-               $found  = array_fill(0, $settingsCount, false);
-               while (!feof($reading)) {
-
-                       $line = fgets($reading);
-
-                       // check for each added setting if we have to replace a config line
-                       for ($i = 0; $i < $settingsCount; $i++) {
-
-                               // check for a non plain config setting (use category too)
-                               if ($this->settings[$i]['cat'] !== 'config' && preg_match_all('/^\$a\-\>config\[\'' . $this->settings[$i]['cat'] . '\'\]\[\'' . $this->settings[$i]['key'] . '\'\]\s*=\s\'*(.*?)\';$/', $line, $matches, PREG_SET_ORDER)) {
-                                       $line = '$a->config[\'' . $this->settings[$i]['cat'] . '\'][\'' . $this->settings[$i]['key'] . '\'] = \'' . $this->settings[$i]['value'] . '\';' . PHP_EOL;
-                                       $found[$i] = true;
-
-                               // check for a plain config setting (don't use a category)
-                               } elseif ($this->settings[$i]['cat'] === 'config' && preg_match_all('/^\$a\-\>config\[\'' . $this->settings[$i]['key'] . '\'\]\s*=\s\'*(.*?)\';$/', $line, $matches, PREG_SET_ORDER)) {
-                                       $line = '$a->config[\'' . $this->settings[$i]['key'] . '\'] = \'' . $this->settings[$i]['value'] . '\';' . PHP_EOL;
-                                       $found[$i] = true;
-                               }
-                       }
-
-                       fputs($writing, $line);
-               }
-
-               for ($i = 0; $i < $settingsCount; $i++) {
-                       if (!$found[$i]) {
-                               if ($this->settings[$i]['cat'] !== 'config') {
-                                       $line = '$a->config[\'' . $this->settings[$i]['cat'] . '\'][\'' . $this->settings[$i]['key'] . '\'] = \'' . $this->settings[$i]['value'] . '\';' . PHP_EOL;
-                               } else {
-                                       $line = '$a->config[\'' . $this->settings[$i]['key'] . '\'] = \'' . $this->settings[$i]['value'] . '\';' . PHP_EOL;
-                               }
-
-                               fputs($writing, $line);
-                       }
-               }
-       }
-}
index 3574464..b534a55 100644 (file)
@@ -835,4 +835,26 @@ class Network
                        (strlen($query) ? "?".$query : '') .
                        (strlen($fragment) ? "#".$fragment : '');
        }
+
+
+       /**
+        * @brief Switch the scheme of an url between http and https
+        *
+        * @param string $url URL
+        *
+        * @return string switched URL
+        */
+       public static function switchScheme($url)
+       {
+               $parts = parse_url($url, PHP_URL_SCHEME);
+               if (!isset($parts['scheme'])) {
+                       return $url;
+               }
+               if ($parts['scheme'] == 'http') {
+                       $url = str_replace('http://', 'https://', $url);
+               } elseif ($parts['scheme'] == 'https') {
+                       $url = str_replace('https://', 'http://', $url);
+               }
+               return $url;
+       }
 }
diff --git a/tests/src/Util/Config/ConfigFileSaverTest.php b/tests/src/Util/Config/ConfigFileSaverTest.php
deleted file mode 100644 (file)
index 04adf60..0000000
+++ /dev/null
@@ -1,189 +0,0 @@
-<?php
-
-namespace Friendica\Test\src\Util\Config;
-
-use Friendica\App;
-use Friendica\Core\Config\Cache\ConfigCache;
-use Friendica\Test\MockedTest;
-use Friendica\Test\Util\VFSTrait;
-use Friendica\Util\Config\ConfigFileLoader;
-use Friendica\Util\Config\ConfigFileSaver;
-use Mockery\MockInterface;
-use org\bovigo\vfs\vfsStream;
-
-class ConfigFileSaverTest extends MockedTest
-{
-       use VFSTrait;
-
-       /**
-        * @var App\Mode|MockInterface
-        */
-       private $mode;
-
-       protected function setUp()
-       {
-               parent::setUp();
-               $this->setUpVfsDir();
-               $this->mode = \Mockery::mock(App\Mode::class);
-               $this->mode->shouldReceive('isInstall')->andReturn(true);
-       }
-
-       public function dataConfigFiles()
-       {
-               return [
-                       'config' => [
-                               'fileName' => 'local.config.php',
-                               'filePath' => dirname(__DIR__) . DIRECTORY_SEPARATOR .
-                                       '..' . DIRECTORY_SEPARATOR .
-                                       '..' . DIRECTORY_SEPARATOR .
-                                       'datasets' . DIRECTORY_SEPARATOR .
-                                       'config',
-                               'relativePath' => 'config',
-                       ],
-                       'ini' => [
-                               'fileName' => 'local.ini.php',
-                               'filePath' => dirname(__DIR__) . DIRECTORY_SEPARATOR .
-                                       '..' . DIRECTORY_SEPARATOR .
-                                       '..' . DIRECTORY_SEPARATOR .
-                                       'datasets' . DIRECTORY_SEPARATOR .
-                                       'config',
-                               'relativePath' => 'config',
-                       ],
-                       'htconfig' => [
-                               'fileName' => '.htconfig.php',
-                               'filePath' => dirname(__DIR__) . DIRECTORY_SEPARATOR .
-                                       '..' . DIRECTORY_SEPARATOR .
-                                       '..' . DIRECTORY_SEPARATOR .
-                                       'datasets' . DIRECTORY_SEPARATOR .
-                                       'config',
-                               'relativePath' => '',
-                       ],
-               ];
-       }
-
-       /**
-        * Test the saveToConfigFile() method
-        * @dataProvider dataConfigFiles
-        *
-        * @todo 20190324 [nupplaphil] for ini-configs, it isn't possible to use $ or ! inside values
-        */
-       public function testSaveToConfig($fileName, $filePath, $relativePath)
-       {
-               $this->delConfigFile('local.config.php');
-
-               if (empty($relativePath)) {
-                       $root = $this->root;
-                       $relativeFullName = $fileName;
-               } else {
-                       $root = $this->root->getChild($relativePath);
-                       $relativeFullName = $relativePath . DIRECTORY_SEPARATOR . $fileName;
-               }
-
-               vfsStream::newFile($fileName)
-                       ->at($root)
-                       ->setContent(file_get_contents($filePath . DIRECTORY_SEPARATOR . $fileName));
-
-               $configFileSaver = new ConfigFileSaver($this->root->url());
-               $configFileLoader = new ConfigFileLoader($this->root->url(), $this->mode);
-               $configCache = new ConfigCache();
-               $configFileLoader->setupCache($configCache);
-
-               $this->assertEquals('admin@test.it', $configCache->get('config', 'admin_email'));
-               $this->assertEquals('frio', $configCache->get('system', 'theme'));
-               $this->assertNull($configCache->get('config', 'test_val'));
-               $this->assertNull($configCache->get('system', 'test_val2'));
-
-               // update values (system and config value)
-               $configFileSaver->addConfigValue('config', 'admin_email', 'new@mail.it');
-               $configFileSaver->addConfigValue('system', 'theme', 'vier');
-
-               // insert values (system and config value)
-               $configFileSaver->addConfigValue('config', 'test_val', 'Testingwith@all.we can');
-               $configFileSaver->addConfigValue('system', 'test_val2', 'TestIt First');
-
-               // overwrite value
-               $configFileSaver->addConfigValue('system', 'test_val2', 'TestIt Now');
-
-               // save it
-               $this->assertTrue($configFileSaver->saveToConfigFile());
-
-               $newConfigCache = new ConfigCache();
-               $configFileLoader->setupCache($newConfigCache);
-
-               $this->assertEquals('new@mail.it', $newConfigCache->get('config', 'admin_email'));
-               $this->assertEquals('Testingwith@all.we can', $newConfigCache->get('config', 'test_val'));
-               $this->assertEquals('vier', $newConfigCache->get('system', 'theme'));
-               $this->assertEquals('TestIt Now', $newConfigCache->get('system', 'test_val2'));
-
-               $this->assertTrue($this->root->hasChild($relativeFullName));
-               $this->assertTrue($this->root->hasChild($relativeFullName . '.old'));
-               $this->assertFalse($this->root->hasChild($relativeFullName . '.tmp'));
-
-               $this->assertEquals(file_get_contents($filePath . DIRECTORY_SEPARATOR . $fileName), file_get_contents($this->root->getChild($relativeFullName . '.old')->url()));
-       }
-
-       /**
-        * Test the saveToConfigFile() method without permissions
-        * @dataProvider dataConfigFiles
-        */
-       public function testNoPermission($fileName, $filePath, $relativePath)
-       {
-               $this->delConfigFile('local.config.php');
-
-               if (empty($relativePath)) {
-                       $root = $this->root;
-                       $relativeFullName = $fileName;
-               } else {
-                       $root = $this->root->getChild($relativePath);
-                       $relativeFullName = $relativePath . DIRECTORY_SEPARATOR . $fileName;
-               }
-
-               $root->chmod(000);
-
-               vfsStream::newFile($fileName)
-                       ->at($root)
-                       ->setContent(file_get_contents($filePath . DIRECTORY_SEPARATOR . $fileName));
-
-               $configFileSaver = new ConfigFileSaver($this->root->url());
-
-               $configFileSaver->addConfigValue('system', 'test_val2', 'TestIt Now');
-
-               // wrong mod, so return false if nothing to write
-               $this->assertFalse($configFileSaver->saveToConfigFile());
-       }
-
-       /**
-        * Test the saveToConfigFile() method with nothing to do
-        * @dataProvider dataConfigFiles
-        */
-       public function testNothingToDo($fileName, $filePath, $relativePath)
-       {
-               $this->delConfigFile('local.config.php');
-
-               if (empty($relativePath)) {
-                       $root = $this->root;
-                       $relativeFullName = $fileName;
-               } else {
-                       $root = $this->root->getChild($relativePath);
-                       $relativeFullName = $relativePath . DIRECTORY_SEPARATOR . $fileName;
-               }
-
-               vfsStream::newFile($fileName)
-                       ->at($root)
-                       ->setContent(file_get_contents($filePath . DIRECTORY_SEPARATOR . $fileName));
-
-               $configFileSaver = new ConfigFileSaver($this->root->url());
-               $configFileLoader = new ConfigFileLoader($this->root->url(), $this->mode);
-               $configCache = new ConfigCache();
-               $configFileLoader->setupCache($configCache);
-
-               // save nothing
-               $this->assertTrue($configFileSaver->saveToConfigFile());
-
-               $this->assertTrue($this->root->hasChild($relativeFullName));
-               $this->assertFalse($this->root->hasChild($relativeFullName . '.old'));
-               $this->assertFalse($this->root->hasChild($relativeFullName . '.tmp'));
-
-               $this->assertEquals(file_get_contents($filePath . DIRECTORY_SEPARATOR . $fileName), file_get_contents($this->root->getChild($relativeFullName)->url()));
-       }
-}