X-Git-Url: https://jfr.im/git/irc/unrealircd/unrealircd-webpanel.git/blobdiff_plain/2b418d6e87b856aed377f7b23803069b46e605a2..79e2577da34044027989cd8b16f976e5ba768e70:/common.php diff --git a/common.php b/common.php index d685538..b666395 100644 --- a/common.php +++ b/common.php @@ -8,8 +8,239 @@ if (version_compare(PHP_VERSION, '8.0.0', '<')) "You may also need to choose again the PHP module to load in apache via a2enmod php8.2"); define('UPATH', dirname(__FILE__)); -require_once UPATH . "/config.php"; -if (!defined('BASE_URL')) die("You need to define BASE_URL in config.php (see config.php.sample for documentation)"); + +function get_config($setting) +{ + GLOBAL $config; + + $item = $config; + foreach(explode("::", $setting) as $x) + { + if (isset($item[$x])) + $item = $item[$x]; + else + return NULL; + } + return $item; +} + +function page_requires_no_config() +{ + if (str_ends_with($_SERVER['SCRIPT_FILENAME'],"install.php") || + str_ends_with($_SERVER['SCRIPT_FILENAME'],"installation.php")) + { + return TRUE; + } + return FALSE; +} + +function page_requires_no_login() +{ + if (str_ends_with($_SERVER['SCRIPT_FILENAME'],"login/index.php") || + page_requires_no_config()) + { + return TRUE; + } + return FALSE; +} + +function read_config_file() +{ + GLOBAL $config; + GLOBAL $config_transition_unreal_server; + + $config = Array(); + if (!file_exists(UPATH."/config/config.php") && file_exists(UPATH."/config.php")) + { + require_once UPATH . "/config.php"; + require_once UPATH . "/config/compat.php"; + } + if ((@include(UPATH . "/config/config.php")) !== 1) + return false; + if (isset($config['unrealircd'])) + $config_transition_unreal_server = true; + return true; +} + +function read_config_db() +{ + GLOBAL $config; + + if (page_requires_no_config()) + return; + + $merge = DbSettings::get(); + /* DB settings overwrite config.php keys: */ + $config = array_merge($config, $merge); +} + +function config_is_file_item($name) +{ + if (($name == "plugins") || + ($name == "mysql") || + ($name == "base_url")) + { + return true; + } + return false; +} + +function write_config_file() +{ + GLOBAL $config; + + $file_settings = []; + foreach($config as $k=>$v) + { + if (config_is_file_item($k)) + $file_settings[$k] = $v; + } + + $cfg_filename = UPATH.'/config/config.php'; + $tmpfile = UPATH.'/config/config.tmp.'.bin2hex(random_bytes(8)).'.php'; + $fd = fopen($tmpfile, "w"); + if (!$fd) + die("Could not write to temporary config file $tmpfile.
We need write permissions on the config/ directory!
"); + + $str = var_export($file_settings, true); + if ($str === null) + die("Error while running write_config_file() -- weird!"); + if (!fwrite($fd, ""); + } + if (!fclose($fd)) + die("Error writing to config file $tmpfile (on close).
"); + /* Now atomically rename the file */ + if (!rename($tmpfile, $cfg_filename)) + die("Could not write (rename) to file ".$cfg_filename."
"); + opcache_invalidate($cfg_filename); + + /* Do not re-read config, as it would reinitialize config + * without having the DB settings read. (And it also + * serves no purpose) + */ + return true; +} + +// XXX: handle unsetting of config items :D - explicit unset function ? + +function write_config($setting = null) +{ + GLOBAL $config; + + /* Specific request? Easy, write only this setting to the DB (never used for file) */ + if ($setting !== null) + { + return DbSettings::set($setting, $config[$setting]); + } + + /* Otherwise write the whole config. + * TODO: avoid writing settings file if unneeded, + * as it is more noisy than db settings. + */ + $db_settings = []; + + foreach($config as $k=>$v) + { + if (!config_is_file_item($k)) + $db_settings[$k] = $v; + } + + if (!write_config_file()) + return false; + + foreach($db_settings as $k=>$v) + { + $ret = DbSettings::set($k, $v); + if (!$ret) + return $ret; + } + + return true; +} + +function get_version() +{ + $fd = @fopen(UPATH."/.git/FETCH_HEAD", "r"); + if ($fd === false) + return "unknown"; + $line = fgets($fd, 512); + fclose($fd); + $commit = substr($line, 0, 8); + return $commit; /* short git commit id */ +} + +function upgrade_check() +{ + GLOBAL $config_transition_unreal_server; + GLOBAL $config; + + /* Moving of a config.php item to DB: */ + if ($config_transition_unreal_server) + write_config(); + + $version = get_version(); + if (!isset($config['webpanel_version'])) + $config['webpanel_version'] = ''; + if ($version != $config['webpanel_version']) + { + $versioninfo = [ + "old_version" => $config['webpanel_version'], + "new_version" => $version + ]; + Hook::run(HOOKTYPE_UPGRADE, $versioninfo); + /* And set the new version now that the upgrade is "done" */ + $config['webpanel_version'] = $version; + write_config("webpanel_version"); + } +} + +function panel_start_session($user = false) +{ + if (!isset($_SESSION)) + { + session_set_cookie_params(86400); // can't set this to session_timeout due to catch-22 + session_start(); + } + + if ($user === false) + { + $user = unreal_get_current_user(); + if ($user === false) + return false; + } + + $timeout = 3600; + if (isset($user->user_meta['session_timeout'])) + $timeout = (INT)$user->user_meta['session_timeout']; + + if (!isset($_SESSION['session_timeout'])) + $_SESSION['session_timeout'] = $timeout; + + $_SESSION['last-activity'] = time(); + return true; +} + +/* Now read the config, and redirect to install screen if we don't have it */ +$config_transition_unreal_server = false; +if (!read_config_file()) +{ + if (page_requires_no_config()) + { + /* Allow empty conf */ + } else + if (!file_exists(UPATH."/config/config.php") && !file_exists(UPATH."/config.php")) + { + header("Location: settings/install.php"); + die(); + } +} + require_once "Classes/class-hook.php"; if (!is_dir(UPATH . "/vendor")) die("The vendor/ directory is missing. Most likely the admin forgot to run 'composer install'\n"); @@ -27,6 +258,20 @@ require_once UPATH . "/Classes/class-rpc.php"; require_once UPATH . "/Classes/class-paneluser.php"; require_once UPATH . "/plugins.php"; +/* Do various checks and reading, except during setup step 1. */ +if (!page_requires_no_config()) +{ + /* Now that plugins are loaded, read config from DB */ + read_config_db(); + + /* Check if anything needs upgrading (eg on panel version change) */ + upgrade_check(); + + /* And a check... */ + if (!get_config("base_url")) + die("The base_url was not found in your config. Setup went wrong?"); +} + $pages = [ "Overview" => "", "Users" => "users", @@ -48,9 +293,18 @@ $pages = [ "News" => "news.php", ]; -if (is_auth_provided()) +if (!panel_start_session()) { - $pages["Settings"]["Panel Access"] = "settings"; + if (!page_requires_no_login()) + { + if (!is_auth_provided()) + die("No authentication plugin loaded. You must load either sql_auth, file_auth, or a similar auth plugin!"); + $current_page = $_SERVER['REQUEST_URI']; + header("Location: ".get_config("base_url")."login/?redirect=".urlencode($current_page)); + die; + } +} else { + $pages["Settings"]["Accounts"] = "settings"; $user = unreal_get_current_user(); if ($user) @@ -59,6 +313,7 @@ if (is_auth_provided()) $pages["Logout"] = "login/?logout=true"; } } + Hook::run(HOOKTYPE_NAVBAR, $pages); /* Example to add new menu item: