First attempt at switching to symfony/yaml for config files (WIP)

This commit is contained in:
Cyril 2019-10-14 12:21:28 +02:00
parent da45175200
commit 6ba9c6879f
20 changed files with 222 additions and 428 deletions

View file

@ -73,33 +73,32 @@ class Tools {
#}
# Asserting config file exists
if (!file_exists(PROJECT_PATH_SPECIFIC . "config.php")) {
throw new \Exception("Specific/config.php does not exist. Please use the Install tool to create it.");
if (!file_exists(PROJECT_PATH_CONFIG . "config.yaml")) {
throw new \Exception("config/config.yaml does not exist. Please use the Install tool to create it or duplicate config.yaml.dist.");
}
# Asserting config file is readable
if (!is_readable(PROJECT_PATH_SPECIFIC . "config.php")) {
throw new \Exception("Specific/config.php is not readable. Please give read permissions to httpd user on file 'Specific/config.php'.");
if (!is_readable(PROJECT_PATH_CONFIG . "config.yaml")) {
throw new \Exception("config/config.yaml is not readable. Please give read permissions to httpd user on file 'config/config.yaml'.");
}
# Asserting config file is writable
if (!is_writable(PROJECT_PATH_SPECIFIC . "config.php")) {
throw new \Exception("Specific/config.php is not writable. Please give write permissions to httpd user on file 'Specific/config.php'.");
if (!is_writable(PROJECT_PATH_CONFIG . "config.yaml")) {
throw new \Exception("config/config.yaml is not writable. Please give write permissions to httpd user on file 'config/config.yaml'.");
}
# Asserting config file exists
if (!file_exists(PROJECT_PATH_CONFIG . "system.yaml")) {
throw new \Exception("config/system.yaml does not exist. Please use the Install tool to create it or duplicate system.yaml.dist.");
}
# Asserting system config file exists
if (!file_exists(PROJECT_PATH_SPECIFIC . "config.system.php")) {
throw new \Exception("Specific/config.system.php does not exist. Please use the Install tool to create it.");
# Asserting config file is readable
if (!is_readable(PROJECT_PATH_CONFIG . "system.yaml")) {
throw new \Exception("config/system.yaml is not readable. Please give read permissions to httpd user on file 'config/system.yaml'.");
}
# Asserting system config file is readable
if (!is_readable(PROJECT_PATH_SPECIFIC . "config.system.php")) {
throw new \Exception("Specific/config.system.php is not readable. Please give read permissions to httpd user on file 'Specific/config.system.php'.");
}
# Asserting system config file is writable
if (!is_writable(PROJECT_PATH_SPECIFIC . "config.system.php")) {
throw new \Exception("Specific/config.system.php is not writable. Please give write permissions to httpd user on file 'Specific/config.system.php'.");
# Asserting config file is writable
if (!is_writable(PROJECT_PATH_CONFIG . "system.yaml")) {
throw new \Exception("config/system.yaml is not writable. Please give write permissions to httpd user on file 'config/system.yaml'.");
}
}

View file

@ -27,6 +27,8 @@
namespace Baikal;
use Symfony\Component\Yaml\Yaml;
class Framework extends \Flake\Core\Framework {
static function installTool() {
@ -51,29 +53,30 @@ class Framework extends \Flake\Core\Framework {
# Check that a config file exists
if (
!file_exists(PROJECT_PATH_SPECIFIC . "config.php") ||
!file_exists(PROJECT_PATH_SPECIFIC . "config.system.php")
!file_exists(PROJECT_PATH_CONFIG . "config.yaml") ||
!file_exists(PROJECT_PATH_CONFIG . "system.yaml")
) {
self::installTool();
} else {
require_once(PROJECT_PATH_SPECIFIC . "config.php");
require_once(PROJECT_PATH_SPECIFIC . "config.system.php");
date_default_timezone_set(PROJECT_TIMEZONE);
$config = Yaml::parseFile(PROJECT_PATH_CONFIG . "config.yaml");
$configSystem = Yaml::parseFile(PROJECT_PATH_CONFIG . "system.yaml");
date_default_timezone_set($config['parameters']['PROJECT_TIMEZONE']);
# Check that Baïkal is already configured
if (!defined("BAIKAL_CONFIGURED_VERSION")) {
if (!isset($configSystem['parameters']['BAIKAL_CONFIGURED_VERSION'])) {
self::installTool();
} else {
# Check that running version matches configured version
if (version_compare(BAIKAL_VERSION, BAIKAL_CONFIGURED_VERSION) > 0) {
if (version_compare(BAIKAL_VERSION, $configSystem['parameters']['BAIKAL_CONFIGURED_VERSION']) > 0) {
self::installTool();
} else {
# Check that admin password is set
if (!defined("BAIKAL_ADMIN_PASSWORDHASH")) {
if (!$config['parameters']['BAIKAL_ADMIN_PASSWORDHASH']) {
self::installTool();
}

View file

@ -27,18 +27,25 @@
namespace Baikal\Model;
use Symfony\Component\Yaml\Yaml;
abstract class Config extends \Flake\Core\Model\NoDb {
protected $sConfigFilePath = "";
protected $aConstants = [];
protected $aData = [];
function __construct($sConfigFilePath) {
# Note: no call to parent::__construct() to avoid erasing $this->aData
$this->sConfigFilePath = $sConfigFilePath;
$aConfig = $this->parseConfig(
$this->getConfigAsString()
);
try {
$config = Yaml::parseFile($this->sConfigFilePath);
$aConfig = $config['parameters'];
} catch(\Exception $e) {
$aConfig = static::getDefaultConfig();
}
foreach (array_keys($this->aData) as $sProp) {
if (array_key_exists($sProp, $aConfig)) {
@ -49,79 +56,12 @@ abstract class Config extends \Flake\Core\Model\NoDb {
protected function getConfigAsString() {
if (file_exists($this->sConfigFilePath)) {
$sContent = file_get_contents($this->sConfigFilePath);
return str_replace(LF . CR, LF, $sContent);
return Yaml::parseFile($this->sConfigFilePath);
} else {
$sConfig = "<?php\n" . \Baikal\Core\Tools::getCopyrightNotice() . "\n\n";
$sConfig .= static::getDefaultConfig();
return $sConfig;
return static::getDefaultConfig();
}
}
protected function parseConfig($sString) {
$aRes = [];
foreach (array_keys($this->aConstants) as $sConstant) {
$aConstant = $this->aConstants[$sConstant];
$aMatches = [];
$sPattern = '/\s*define\(\s*["|\']' . $sConstant . '["|\']\s*\,\s*(.*?)\s*\);\s*/ix';
$iNbRes = preg_match_all(
$sPattern,
$sString,
$aMatches
);
if ($iNbRes === 1) {
# Exactly one match
# O would be not enough, and > 1, to much to handle properly
$sValue = $aMatches[1][0]; # first capture (.*?), first occurence (anyway, we asserted that there's only one)
switch ($aConstant["type"]) {
case "string": {
$sValue = substr($sValue, 1, -1); # Strip quotes
break;
}
case "integer": {
$sValue = intval($sValue); # Integer
break;
}
case "boolean": {
if (in_array(strtoupper(trim($sValue)), ["1", "TRUE"])) {
$sValue = true;
} else {
$sValue = false;
}
break;
}
case "litteral": {
$sValue = trim($sValue);
break;
}
default: {
# nothing
break;
}
}
$aRes[$sConstant] = $sValue;
} elseif ($iNbRes > 1) {
throw new \Exception("Baikal\Model\Config->parseConfig(): constant '" . $sConstant . "' has been found multiple times in the config file; stopping execution");
} else {
# $iNbRes === 0
# We do nothing, to keep the default value (the one already set in $aData)
}
}
reset($aRes);
return $aRes;
}
function writable() {
return (
@file_exists($this->sConfigFilePath) &&
@ -147,89 +87,10 @@ abstract class Config extends \Flake\Core\Model\NoDb {
}
function persist() {
$aLines = explode(LF, $this->getConfigAsString());
$iLines = count($aLines);
foreach (array_keys($this->aData) as $prop) {
$sPattern = '/\s*define\(\s*["|\']' . $prop . '["|\']\s*\,\s*(.*?)\s*\);\s*/ix';
$sValue = $this->aData[$prop];
# We replace value by it's native PHP notation
switch ($this->aConstants[$prop]["type"]) {
case "string": {
$sValue = var_export($sValue, true); # Add quotes, and escape " and all string-termination chars
break;
}
case "integer": {
$sValue = intval($sValue); # Cast as integer
break;
}
case "boolean": {
if (intval($sValue) === 1) { # Note as a BOOLEAN PHP constant
$sValue = "TRUE";
} else {
$sValue = "FALSE";
}
break;
}
case "litteral": {
$sValue = trim($sValue);
break;
}
default: {
$sValue = "''";
break;
}
}
$mFound = false;
for ($k = ($iLines - 1); $k >= 0; $k--) {
if (preg_match($sPattern, $aLines[$k])) {
# Found the last matching line
$mFound = $k;
break;
}
}
if ($mFound === false) {
# Adding line at the end of the file
$aLines[] = "\n" . "# " . $this->aConstants[$prop]["comment"] . "\ndefine(\"" . $prop . "\", " . $sValue . ");";
} else {
$aLines[$mFound] = "define(\"" . $prop . "\", " . $sValue . ");";
}
}
$sLines = implode("\n", $aLines);
$sSandboxedCode = str_replace(["<?php", "<?", "?>"], "", $sLines);
$sRand = (string)rand();
$sCode = "if(0) {" . $sSandboxedCode . "\n}; echo '" . $sRand . "';";
ob_start();
eval($sCode);
$sRes = ob_get_contents();
ob_end_clean();
if ($sRes !== $sRand) {
echo "<pre>" . htmlspecialchars($sLines) . "</pre>";
throw new \Exception("Parse error in new config file. Aborting, nothing has been changed.");
}
# We asserted that the syntax is OK;
# We now check that all the constants are present, and with the right value
$aNewConfig = $this->parseConfig($sLines);
$aWrittenConfig = $this->aData;
asort($aNewConfig);
asort($aWrittenConfig);
if ($aNewConfig != $aWrittenConfig) {
throw new \Exception("New config does not correspond to expected config. Aborting, nothing has been changed.");
}
file_put_contents($this->sConfigFilePath, $sLines);
$yaml = Yaml::dump([
'parameters' => $this->aData
]);
file_put_contents($this->sConfigFilePath, $yaml);
}
function destroy() {

View file

@ -58,7 +58,7 @@ class Database extends \Baikal\Model\Config {
# Default values
protected $aData = [
"PROJECT_SQLITE_FILE" => 'PROJECT_PATH_SPECIFIC . "db/db.sqlite"',
"PROJECT_SQLITE_FILE" => PROJECT_PATH_SPECIFIC . "db/db.sqlite",
"PROJECT_DB_MYSQL" => false,
"PROJECT_DB_MYSQL_HOST" => "",
"PROJECT_DB_MYSQL_DBNAME" => "",

View file

@ -27,6 +27,8 @@
namespace Baikal\Model\Config;
use Symfony\Component\Yaml\Yaml;
class Standard extends \Baikal\Model\Config {
protected $aConstants = [
@ -63,7 +65,8 @@ class Standard extends \Baikal\Model\Config {
"BAIKAL_CAL_ENABLED" => true,
"BAIKAL_INVITE_FROM" => "",
"BAIKAL_DAV_AUTH_TYPE" => "Digest",
"BAIKAL_ADMIN_PASSWORDHASH" => ""
"BAIKAL_ADMIN_PASSWORDHASH" => "",
"BAIKAL_AUTH_REALM" => "BaikalDAV"
];
function formMorphologyForThisModelInstance() {
@ -110,7 +113,11 @@ class Standard extends \Baikal\Model\Config {
"validation" => "sameas:BAIKAL_ADMIN_PASSWORDHASH",
]));
if (!defined("BAIKAL_ADMIN_PASSWORDHASH") || trim(BAIKAL_ADMIN_PASSWORDHASH) === "") {
try {
$config = Yaml::parseFile(PROJECT_PATH_CONFIG . "system.yaml");
} catch(\Exception $e) {}
if (!isset($config['parameters']["BAIKAL_ADMIN_PASSWORDHASH"]) || trim($config['parameters']["BAIKAL_ADMIN_PASSWORDHASH"]) === "") {
# No password set (Form is used in install tool), so password is required as it has to be defined
$oMorpho->element("BAIKAL_ADMIN_PASSWORDHASH")->setOption("validation", "required");
@ -152,52 +159,16 @@ class Standard extends \Baikal\Model\Config {
return parent::get($sProp);
}
protected function createDefaultConfigFilesIfNeeded() {
# Create empty config.php if needed
if (!file_exists(PROJECT_PATH_SPECIFIC . "config.php")) {
@touch(PROJECT_PATH_SPECIFIC . "config.php");
$sContent = "<?php\n" . \Baikal\Core\Tools::getCopyrightNotice() . "\n\n";
$sContent .= $this->getDefaultConfig();
file_put_contents(PROJECT_PATH_SPECIFIC . "config.php", $sContent);
}
# Create empty config.system.php if needed
if (!file_exists(PROJECT_PATH_SPECIFIC . "config.system.php")) {
@touch(PROJECT_PATH_SPECIFIC . "config.system.php");
$sContent = "<?php\n" . \Baikal\Core\Tools::getCopyrightNotice() . "\n\n";
$sContent .= $this->getDefaultSystemConfig();
file_put_contents(PROJECT_PATH_SPECIFIC . "config.system.php", $sContent);
}
}
protected static function getDefaultConfig() {
$sCode = <<<CODE
##############################################################################
# Required configuration
# You *have* to review these settings for Baïkal to run properly
#
# Timezone of your users, if unsure, check http://en.wikipedia.org/wiki/List_of_tz_database_time_zones
define("PROJECT_TIMEZONE", "Europe/Paris");
# CardDAV ON/OFF switch; default TRUE
define("BAIKAL_CARD_ENABLED", TRUE);
# CalDAV ON/OFF switch; default TRUE
define("BAIKAL_CAL_ENABLED", TRUE);
# CalDAV invite From: mail address (comment or leave blank to disable notifications)
define("BAIKAL_INVITE_FROM", "noreply@$_SERVER[SERVER_NAME]");
# WebDAV authentication type; default Digest
define("BAIKAL_DAV_AUTH_TYPE", "Digest");
# Baïkal Web admin password hash; Set via Baïkal Web Admin
define("BAIKAL_ADMIN_PASSWORDHASH", "");
CODE;
$sCode = trim($sCode);
return $sCode;
return [
"PROJECT_TIMEZONE" => "Europe/Paris",
"BAIKAL_CARD_ENABLED" => true,
"BAIKAL_CAL_ENABLED" => true,
"BAIKAL_INVITE_FROM" => "noreply@" . $_SERVER['SERVER_NAME'],
"BAIKAL_DAV_AUTH_TYPE" => "Digest",
"BAIKAL_ADMIN_PASSWORDHASH" => "",
"BAIKAL_AUTH_REALM" => "BaikalDAV",
];
}
}

View file

@ -30,22 +30,6 @@ namespace Baikal\Model\Config;
class System extends \Baikal\Model\Config {
protected $aConstants = [
"BAIKAL_AUTH_REALM" => [
"type" => "string",
"comment" => "If you change this value, you'll have to re-generate passwords for all your users",
],
"BAIKAL_CARD_BASEURI" => [
"type" => "litteral",
"comment" => 'Should begin and end with a "/"',
],
"BAIKAL_CAL_BASEURI" => [
"type" => "litteral",
"comment" => 'Should begin and end with a "/"',
],
"BAIKAL_DAV_BASEURI" => [
"type" => "litteral",
"comment" => 'Should begin and end with a "/"',
],
"PROJECT_SQLITE_FILE" => [
"type" => "litteral",
"comment" => "Define path to Baïkal Database SQLite file",
@ -82,11 +66,7 @@ class System extends \Baikal\Model\Config {
# Default values
protected $aData = [
"BAIKAL_AUTH_REALM" => "BaikalDAV",
"BAIKAL_CARD_BASEURI" => 'PROJECT_BASEURI . "card.php/"',
"BAIKAL_CAL_BASEURI" => 'PROJECT_BASEURI . "cal.php/"',
"BAIKAL_DAV_BASEURI" => 'PROJECT_BASEURI . "dav.php/"',
"PROJECT_SQLITE_FILE" => 'PROJECT_PATH_SPECIFIC . "db/db.sqlite"',
"PROJECT_SQLITE_FILE" => "db/db.sqlite",
"PROJECT_DB_MYSQL" => false,
"PROJECT_DB_MYSQL_HOST" => "",
"PROJECT_DB_MYSQL_DBNAME" => "",
@ -99,49 +79,6 @@ class System extends \Baikal\Model\Config {
function formMorphologyForThisModelInstance() {
$oMorpho = new \Formal\Form\Morphology();
$oMorpho->add(new \Formal\Element\Text([
"prop" => "BAIKAL_CAL_BASEURI",
"label" => "CalDAV base URI",
"validation" => "required",
"help" => "The absolute web path to cal.php",
"popover" => [
"title" => "CalDAV base URI",
"content" => "If Baïkal is hosted in a subfolder, this path should reflect it.<br /><strong>Whatever happens, it should begin and end with a slash.</strong>",
]
]));
$oMorpho->add(new \Formal\Element\Text([
"prop" => "BAIKAL_CARD_BASEURI",
"label" => "CardDAV base URI",
"validation" => "required",
"help" => "The absolute web path to card.php",
"popover" => [
"title" => "CardDAV base URI",
"content" => "If Baïkal is hosted in a subfolder, this path should reflect it.<br /><strong>Whatever happens, it should begin and end with a slash.</strong>"
]
]));
$oMorpho->add(new \Formal\Element\Text([
"prop" => "BAIKAL_DAV_BASEURI",
"label" => "CalDAV/CardDAV base URI",
"validation" => "required",
"help" => "The absolute web path to dav.php",
"popover" => [
"title" => "DAV base URI",
"content" => "If Baïkal is hosted in a subfolder, this path should reflect it.<br /><strong>Whatever happens, it should begin and end with a slash.</strong>"
]
]));
$oMorpho->add(new \Formal\Element\Text([
"prop" => "BAIKAL_AUTH_REALM",
"label" => "Auth realm",
"validation" => "required",
"help" => "Token used in authentication process.<br />If you change this, you'll have to reset all your users passwords.<br />You'll also loose access to this admin interface.",
"popover" => [
"title" => "Auth realm",
"content" => "If you change this, you'll loose your access to this interface.<br />In other words: <strong>you should not change this, unless YKWYD.</strong>"
]
]));
$oMorpho->add(new \Formal\Element\Text([
"prop" => "PROJECT_SQLITE_FILE",
"label" => "SQLite file path",
@ -187,56 +124,15 @@ class System extends \Baikal\Model\Config {
protected static function getDefaultConfig() {
$sBaikalVersion = BAIKAL_VERSION;
$sCode = <<<CODE
##############################################################################
# System configuration
# Should not be changed, unless YNWYD
#
# RULES
# 0. All folder pathes *must* be suffixed by "/"
# 1. All URIs *must* be suffixed by "/" if pointing to a folder
#
# If you change this value, you'll have to re-generate passwords for all your users
define("BAIKAL_AUTH_REALM", "BaikalDAV");
# Should begin and end with a "/"
define("BAIKAL_CARD_BASEURI", PROJECT_BASEURI . "card.php/");
# Should begin and end with a "/"
define("BAIKAL_CAL_BASEURI", PROJECT_BASEURI . "cal.php/");
# Should begin and end with a "/"
define("BAIKAL_DAV_BASEURI", PROJECT_BASEURI . "dav.php/");
# Define path to Baïkal Database SQLite file
define("PROJECT_SQLITE_FILE", PROJECT_PATH_SPECIFIC . "db/db.sqlite");
# MySQL > Use MySQL instead of SQLite ?
define("PROJECT_DB_MYSQL", FALSE);
# MySQL > Host, including ':portnumber' if port is not the default one (3306)
define("PROJECT_DB_MYSQL_HOST", "");
# MySQL > Database name
define("PROJECT_DB_MYSQL_DBNAME", "");
# MySQL > Username
define("PROJECT_DB_MYSQL_USERNAME", "");
# MySQL > Password
define("PROJECT_DB_MYSQL_PASSWORD", "");
# A random 32 bytes key that will be used to encrypt data
define("BAIKAL_ENCRYPTION_KEY", "");
# The currently configured Baïkal version
define("BAIKAL_CONFIGURED_VERSION", "{$sBaikalVersion}");
CODE;
$sCode = trim($sCode);
return $sCode;
return [
"PROJECT_SQLITE_FILE" => "db/db.sqlite",
"PROJECT_DB_MYSQL" => false,
"PROJECT_DB_MYSQL_HOST" => "",
"PROJECT_DB_MYSQL_DBNAME" => "",
"PROJECT_DB_MYSQL_USERNAME" => "",
"PROJECT_DB_MYSQL_PASSWORD" => "",
"BAIKAL_ENCRYPTION_KEY" => "",
"BAIKAL_CONFIGURED_VERSION" => BAIKAL_VERSION
];
}
}

View file

@ -279,6 +279,11 @@ class User extends \Flake\Core\Model\Db {
}
function getPasswordHashForPassword($sPassword) {
return md5($this->get("username") . ':' . BAIKAL_AUTH_REALM . ':' . $sPassword);
try {
$config = Yaml::parseFile(PROJECT_PATH_CONFIG . "system.yaml");
} catch(\Exception $e) {}
return md5($this->get("username") . ':' . $config['parameters']['BAIKAL_AUTH_REALM'] . ':' . $sPassword);
}
}

View file

@ -27,18 +27,23 @@
namespace BaikalAdmin\Controller;
use Symfony\Component\Yaml\Yaml;
class Dashboard extends \Flake\Core\Controller {
function execute() {
}
function render() {
$config = Yaml::parseFile(PROJECT_PATH_CONFIG . "config.yaml");
$oView = new \BaikalAdmin\View\Dashboard();
$oView->setData("BAIKAL_VERSION", BAIKAL_VERSION);
# Services status
$oView->setData("BAIKAL_CAL_ENABLED", BAIKAL_CAL_ENABLED);
$oView->setData("BAIKAL_CARD_ENABLED", BAIKAL_CARD_ENABLED);
$oView->setData("BAIKAL_CAL_ENABLED", $config['parameters']['BAIKAL_CAL_ENABLED']);
$oView->setData("BAIKAL_CARD_ENABLED", $config['parameters']['BAIKAL_CARD_ENABLED']);
# Statistics: Users
$iNbUsers = \Baikal\Model\User::getBaseRequester()->count();

View file

@ -27,6 +27,8 @@
namespace BaikalAdmin\Controller\Install;
use Symfony\Component\Yaml\Yaml;
class Database extends \Flake\Core\Controller {
protected $aMessages = [];
@ -34,7 +36,7 @@ class Database extends \Flake\Core\Controller {
protected $oForm; # \Formal\Form
function execute() {
$this->oModel = new \Baikal\Model\Config\Database(PROJECT_PATH_SPECIFIC . "config.system.php");
$this->oModel = new \Baikal\Model\Config\Database(PROJECT_PATH_CONFIG . "system.yaml");
$this->oForm = $this->oModel->formForThisModelInstance([
"close" => false,
@ -198,7 +200,10 @@ class Database extends \Flake\Core\Controller {
if ($oForm->submitted()) {
$bMySQL = (intval($oForm->postValue("PROJECT_DB_MYSQL")) === 1);
} else {
$bMySQL = PROJECT_DB_MYSQL;
try {
$configSystem = Yaml::parseFile(PROJECT_PATH_CONFIG . "system.yaml");
} catch (\Exception $e) {}
$bMySQL = $configSystem['parameters']['PROJECT_DB_MYSQL'] ?? true;
}
if ($bMySQL === true) {

View file

@ -45,7 +45,7 @@ class Initialize extends \Flake\Core\Controller {
$this->createHtaccessFilesIfNeeded();
$this->oModel = new \Baikal\Model\Config\Standard(PROJECT_PATH_SPECIFIC . "config.php");
$this->oModel = new \Baikal\Model\Config\Standard(PROJECT_PATH_CONFIG . "config.yaml");
$this->oForm = $this->oModel->formForThisModelInstance([
"close" => false
@ -57,7 +57,7 @@ class Initialize extends \Flake\Core\Controller {
if ($this->oForm->persisted()) {
# Creating system config, and initializing BAIKAL_ENCRYPTION_KEY
$oSystemConfig = new \Baikal\Model\Config\System(PROJECT_PATH_SPECIFIC . "config.system.php");
$oSystemConfig = new \Baikal\Model\Config\System(PROJECT_PATH_CONFIG . "system.yaml");
$oSystemConfig->set("BAIKAL_ENCRYPTION_KEY", md5(microtime() . rand()));
# Default: PDO::SQLite or PDO::MySQL ?

View file

@ -27,6 +27,8 @@
namespace BaikalAdmin\Controller\Install;
use Symfony\Component\Yaml\Yaml;
class UpgradeConfirmation extends \Flake\Core\Controller {
function execute() {
@ -35,10 +37,14 @@ class UpgradeConfirmation extends \Flake\Core\Controller {
function render() {
$oView = new \BaikalAdmin\View\Install\UpgradeConfirmation();
if (BAIKAL_CONFIGURED_VERSION === BAIKAL_VERSION) {
$sMessage = "Your system is configured to use version <strong>" . BAIKAL_CONFIGURED_VERSION . "</strong>.<br />There's no upgrade to be done.";
try {
$config = Yaml::parseFile(PROJECT_PATH_CONFIG . "config.yaml");
} catch (\Exception $e) {}
if (isset($config['parameters']['BAIKAL_CONFIGURED_VERSION']) && $config['parameters']['BAIKAL_CONFIGURED_VERSION'] === BAIKAL_VERSION) {
$sMessage = "Your system is configured to use version <strong>" . $config['parameters']['BAIKAL_CONFIGURED_VERSION'] . "</strong>.<br />There's no upgrade to be done.";
} else {
$sMessage = "Upgrading Baïkal from version <strong>" . BAIKAL_CONFIGURED_VERSION . "</strong> to version <strong>" . BAIKAL_VERSION . "</strong>";
$sMessage = "Upgrading Baïkal from version <strong>" . "Unknown" . "</strong> to version <strong>" . BAIKAL_VERSION . "</strong>";
}
$oView->setData("message", $sMessage);

View file

@ -27,6 +27,8 @@
namespace BaikalAdmin\Controller\Install;
use Symfony\Component\Yaml\Yaml;
class VersionUpgrade extends \Flake\Core\Controller {
protected $aMessages = [];

View file

@ -30,7 +30,7 @@ namespace BaikalAdmin\Controller\Settings;
class Standard extends \Flake\Core\Controller {
function execute() {
$this->oModel = new \Baikal\Model\Config\Standard(PROJECT_PATH_SPECIFIC . "config.php");
$this->oModel = new \Baikal\Model\Config\Standard(PROJECT_PATH_CONFIG . "config.yaml");
# Assert that config file is writable
if (!$this->oModel->writable()) {

View file

@ -27,14 +27,16 @@
namespace BaikalAdmin\Controller\Settings;
use Symfony\Component\Yaml\Yaml;
class System extends \Flake\Core\Controller {
function execute() {
$this->oModel = new \Baikal\Model\Config\System(PROJECT_PATH_SPECIFIC . "config.system.php");
$this->oModel = new \Baikal\Model\Config\System(PROJECT_PATH_CONFIG . "system.yaml");
# Assert that config file is writable
if (!$this->oModel->writable()) {
throw new \Exception("System config file is not writable;" . __FILE__ . " > " . __LINE__);
throw new \Exception("Config file is not writable;" . __FILE__ . " > " . __LINE__);
}
$this->oForm = $this->oModel->formForThisModelInstance([
@ -66,7 +68,10 @@ class System extends \Flake\Core\Controller {
if ($oForm->submitted()) {
$bMySQL = (intval($oForm->postValue("PROJECT_DB_MYSQL")) === 1);
} else {
$bMySQL = PROJECT_DB_MYSQL;
try {
$config = Yaml::parseFile(PROJECT_PATH_CONFIG . "system.yaml");
} catch(\Exception $e) {}
$bMySQL = $config['parameters']['PROJECT_DB_MYSQL'] ?? true;
}
if ($bMySQL === true) {

View file

@ -27,9 +27,14 @@
namespace BaikalAdmin\Core;
use Symfony\Component\Yaml\Yaml;
class Auth {
static function isAuthenticated() {
if (isset($_SESSION["baikaladminauth"]) && $_SESSION["baikaladminauth"] === md5(BAIKAL_ADMIN_PASSWORDHASH)) {
$config = Yaml::parseFile(PROJECT_PATH_CONFIG . "config.yaml");
if (isset($_SESSION["baikaladminauth"]) && $_SESSION["baikaladminauth"] === md5($config['parameters']['BAIKAL_ADMIN_PASSWORDHASH'])) {
return true;
}
@ -46,9 +51,13 @@ class Auth {
$sPass = \Flake\Util\Tools::POST("password");
$sPassHash = self::hashAdminPassword($sPass);
try {
$config = Yaml::parseFile(PROJECT_PATH_CONFIG . "config.yaml");
} catch (\Exception $e) {
if ($sUser === "admin" && $sPassHash === BAIKAL_ADMIN_PASSWORDHASH) {
$_SESSION["baikaladminauth"] = md5(BAIKAL_ADMIN_PASSWORDHASH);
}
if ($sUser === "admin" && $sPassHash === $config['parameters']['BAIKAL_ADMIN_PASSWORDHASH']) {
$_SESSION["baikaladminauth"] = md5($config['parameters']['BAIKAL_ADMIN_PASSWORDHASH']);
return true;
}
@ -61,11 +70,13 @@ class Auth {
}
static function hashAdminPassword($sPassword) {
if (defined("BAIKAL_AUTH_REALM")) {
$sAuthRealm = BAIKAL_AUTH_REALM;
} else {
$sAuthRealm = "BaikalDAV"; # Fallback to default value; useful when initializing App, as all constants are not set yet
}
try {
$config = Yaml::parseFile(PROJECT_PATH_CONFIG . "config.yaml");
} catch (\Exception $e) { }
# Fallback to default value; useful when initializing App, as all constants are not set yet
$sAuthRealm = $config['parameters']['BAIKAL_AUTH_REALM'] ?? "BaikalDAV";
return md5('admin:' . $sAuthRealm . ':' . $sPassword);
}

View file

@ -24,6 +24,8 @@
* This copyright notice MUST APPEAR in all copies of the script!
***************************************************************/
use Symfony\Component\Yaml\Yaml;
ini_set("session.cookie_httponly", 1);
ini_set("log_errors", 1);
$maxtime = ini_get('max_execution_time');
@ -65,15 +67,22 @@ $oPage->setBaseUrl(PROJECT_URI);
$oPage->zone("navbar")->addBlock(new \BaikalAdmin\Controller\Navigation\Topbar\Install());
if (!defined("BAIKAL_CONFIGURED_VERSION")) {
try {
$config = Yaml::parseFile(PROJECT_PATH_CONFIG . "config.yaml");
} catch (\Exception $e) { $config = null; }
try {
$configSystem = Yaml::parseFile(PROJECT_PATH_CONFIG . "system.yaml");
} catch (\Exception $e) { $configSystem = null; }
if (!$configSystem || !isset($configSystem['parameters']["BAIKAL_CONFIGURED_VERSION"])) {
# we have to upgrade Baïkal (existing installation)
$oPage->zone("Payload")->addBlock(new \BaikalAdmin\Controller\Install\Initialize());
} elseif (!defined("BAIKAL_ADMIN_PASSWORDHASH")) {
} elseif (!$config || !isset($config['parameters']["BAIKAL_ADMIN_PASSWORDHASH"])) {
# we have to set an admin password
$oPage->zone("Payload")->addBlock(new \BaikalAdmin\Controller\Install\Initialize());
} else {
if (BAIKAL_CONFIGURED_VERSION !== BAIKAL_VERSION) {
if ($configSystem['parameters']["BAIKAL_CONFIGURED_VERSION"] !== BAIKAL_VERSION) {
# we have to upgrade Baïkal
if (\Flake\Util\Tools::GET("upgradeConfirmed")) {
$oPage->zone("Payload")->addBlock(new \BaikalAdmin\Controller\Install\VersionUpgrade());

View file

@ -27,6 +27,8 @@
namespace Flake;
use Symfony\Component\Yaml\Yaml;
class Framework extends \Flake\Core\Framework {
static function rmBeginSlash($sString) {
@ -150,6 +152,7 @@ class Framework extends \Flake\Core\Framework {
define("PROJECT_PATH_CORE", PROJECT_PATH_ROOT . "Core/");
define("PROJECT_PATH_CORERESOURCES", PROJECT_PATH_CORE . "Resources/");
define("PROJECT_PATH_SPECIFIC", PROJECT_PATH_ROOT . "Specific/");
define("PROJECT_PATH_CONFIG", PROJECT_PATH_ROOT . "config/");
define("PROJECT_PATH_FRAMEWORKS", PROJECT_PATH_CORE . "Frameworks/");
define("PROJECT_PATH_WWWROOT", PROJECT_PATH_CORE . "WWWRoot/");
@ -206,88 +209,75 @@ class Framework extends \Flake\Core\Framework {
define("FLAKE_URIPATH", \Flake\Util\Tools::stripBeginSlash($aUrlInfo["path"]));
unset($aUrlInfo);
# Include Project config
# NOTE: DB initialization and App config files inclusion
# do not break execution if not properly executed, as
# these errors will have to be caught later in the process
# notably by the App install tool, if available; breaking right now
# would forbid such install tool forwarding, for instance
$sConfigPath = PROJECT_PATH_SPECIFIC . "config.php";
$sConfigSystemPath = PROJECT_PATH_SPECIFIC . "config.system.php";
if (file_exists($sConfigPath)) {
require_once($sConfigPath);
}
if (file_exists($sConfigSystemPath)) {
require_once($sConfigSystemPath);
}
self::initDb();
}
protected static function initDb() {
# Dont init db on install, but in normal mode and when upgrading
if (defined("BAIKAL_CONTEXT_INSTALL") && (!defined('BAIKAL_CONFIGURED_VERSION') || BAIKAL_CONFIGURED_VERSION === BAIKAL_VERSION)) {
try {
$config = Yaml::parseFile(PROJECT_PATH_CONFIG . "system.yaml");
} catch(\Exception $e) {
return true;
}
if (defined("PROJECT_DB_MYSQL") && PROJECT_DB_MYSQL === true) {
self::initDbMysql();
# Dont init db on install, but in normal mode and when upgrading
if (defined("BAIKAL_CONTEXT_INSTALL") && (!isset($config['parameters']['BAIKAL_CONFIGURED_VERSION']) || $config['parameters']['BAIKAL_CONFIGURED_VERSION'] === BAIKAL_VERSION)) {
return true;
}
if ($config['parameters']['PROJECT_DB_MYSQL'] === true) {
self::initDbMysql($config);
} else {
self::initDbSqlite();
self::initDbSqlite($config);
}
}
protected static function initDbSqlite() {
protected static function initDbSqlite(array $config) {
# Asserting DB filepath is set
if (!defined("PROJECT_SQLITE_FILE")) {
if (!$config['parameters']['PROJECT_SQLITE_FILE']) {
return false;
}
# Asserting DB file is writable
if (file_exists(PROJECT_SQLITE_FILE) && !is_writable(PROJECT_SQLITE_FILE)) {
die("<h3>DB file is not writable. Please give write permissions on file '<span style='font-family: monospace; background: yellow;'>" . PROJECT_SQLITE_FILE . "</span>'</h3>");
if (file_exists($config['parameters']['PROJECT_SQLITE_FILE']) && !is_writable($config['parameters']['PROJECT_SQLITE_FILE'])) {
die("<h3>DB file is not writable. Please give write permissions on file '<span style='font-family: monospace; background: yellow;'>" . $config['parameters']['PROJECT_SQLITE_FILE'] . "</span>'</h3>");
}
# Asserting DB directory is writable
if (!is_writable(dirname(PROJECT_SQLITE_FILE))) {
die("<h3>The <em>FOLDER</em> containing the DB file is not writable, and it has to.<br />Please give write permissions on folder '<span style='font-family: monospace; background: yellow;'>" . dirname(PROJECT_SQLITE_FILE) . "</span>'</h3>");
if (!is_writable(dirname($config['parameters']['PROJECT_SQLITE_FILE']))) {
die("<h3>The <em>FOLDER</em> containing the DB file is not writable, and it has to.<br />Please give write permissions on folder '<span style='font-family: monospace; background: yellow;'>" . dirname($config['parameters']['PROJECT_SQLITE_FILE']) . "</span>'</h3>");
}
if (file_exists(PROJECT_SQLITE_FILE) && is_readable(PROJECT_SQLITE_FILE) && !isset($GLOBALS["DB"])) {
$GLOBALS["DB"] = new \Flake\Core\Database\Sqlite(PROJECT_SQLITE_FILE);
if (file_exists($config['parameters']['PROJECT_SQLITE_FILE']) && is_readable($config['parameters']['PROJECT_SQLITE_FILE']) && !isset($GLOBALS["DB"])) {
$GLOBALS["DB"] = new \Flake\Core\Database\Sqlite($config['parameters']['PROJECT_SQLITE_FILE']);
return true;
}
return false;
}
protected static function initDbMysql() {
protected static function initDbMysql(array $config) {
if (!defined("PROJECT_DB_MYSQL_HOST")) {
if (!$config['parameters']['PROJECT_DB_MYSQL_HOST']) {
die("<h3>The constant PROJECT_DB_MYSQL_HOST, containing the MySQL host name, is not set.<br />You should set it in Specific/config.system.php</h3>");
}
if (!defined("PROJECT_DB_MYSQL_DBNAME")) {
if (!$config['parameters']['PROJECT_DB_MYSQL_DBNAME']) {
die("<h3>The constant PROJECT_DB_MYSQL_DBNAME, containing the MySQL database name, is not set.<br />You should set it in Specific/config.system.php</h3>");
}
if (!defined("PROJECT_DB_MYSQL_USERNAME")) {
if (!$config['parameters']['PROJECT_DB_MYSQL_USERNAME']) {
die("<h3>The constant PROJECT_DB_MYSQL_USERNAME, containing the MySQL database username, is not set.<br />You should set it in Specific/config.system.php</h3>");
}
if (!defined("PROJECT_DB_MYSQL_PASSWORD")) {
if (!$config['parameters']['PROJECT_DB_MYSQL_PASSWORD']) {
die("<h3>The constant PROJECT_DB_MYSQL_PASSWORD, containing the MySQL database password, is not set.<br />You should set it in Specific/config.system.php</h3>");
}
try {
$GLOBALS["DB"] = new \Flake\Core\Database\Mysql(
PROJECT_DB_MYSQL_HOST,
PROJECT_DB_MYSQL_DBNAME,
PROJECT_DB_MYSQL_USERNAME,
PROJECT_DB_MYSQL_PASSWORD
$config['parameters']['PROJECT_DB_MYSQL_HOST'],
$config['parameters']['PROJECT_DB_MYSQL_DBNAME'],
$config['parameters']['PROJECT_DB_MYSQL_USERNAME'],
$config['parameters']['PROJECT_DB_MYSQL_PASSWORD']
);
# We now setup t6he connexion to use UTF8

View file

@ -24,6 +24,8 @@
* This copyright notice MUST APPEAR in all copies of the script!
***************************************************************/
use Symfony\Component\Yaml\Yaml;
ini_set("session.cookie_httponly", 1);
ini_set("display_errors", 0);
ini_set("log_errors", 1);
@ -47,19 +49,26 @@ require PROJECT_PATH_ROOT . 'vendor/autoload.php';
# Bootstraping Flake
\Flake\Framework::bootstrap();
# Bootstrapping Baïkal
\Baikal\Framework::bootstrap();
if (!defined("BAIKAL_CAL_ENABLED") || BAIKAL_CAL_ENABLED !== true) {
try {
$config = Yaml::parseFile(PROJECT_PATH_CONFIG . "config.yaml");
} catch (\Exception $e) {
die('<h1>Incomplete installation</h1><p>Ba&iuml;kal is missing its configuration file, or its configuration file is unreadable.');
}
if (!isset($config['parameters']["BAIKAL_CAL_ENABLED"]) || $config['parameters']["BAIKAL_CAL_ENABLED"] !== true) {
throw new ErrorException("Baikal CalDAV is disabled.", 0, 255, __FILE__, __LINE__);
}
$server = new \Baikal\Core\Server(
BAIKAL_CAL_ENABLED,
BAIKAL_CARD_ENABLED,
BAIKAL_DAV_AUTH_TYPE,
BAIKAL_AUTH_REALM,
$config['parameters']["BAIKAL_CAL_ENABLED"],
$config['parameters']["BAIKAL_CARD_ENABLED"],
$config['parameters']["BAIKAL_DAV_AUTH_TYPE"],
$config['parameters']["BAIKAL_AUTH_REALM"],
$GLOBALS['DB']->getPDO(),
BAIKAL_CAL_BASEURI
PROJECT_BASEURI . 'cal.php/'
);
$server->start();

View file

@ -24,6 +24,8 @@
* This copyright notice MUST APPEAR in all copies of the script!
***************************************************************/
use Symfony\Component\Yaml\Yaml;
ini_set("session.cookie_httponly", 1);
ini_set("display_errors", 0);
ini_set("log_errors", 1);
@ -51,16 +53,23 @@ require PROJECT_PATH_ROOT . 'vendor/autoload.php';
# Bootstrapping Baïkal
\Baikal\Framework::bootstrap();
if (!defined("BAIKAL_CARD_ENABLED") || BAIKAL_CARD_ENABLED !== true) {
try {
$config = Yaml::parseFile(PROJECT_PATH_CONFIG . "config.yaml");
} catch (\Exception $e) {
die('<h1>Incomplete installation</h1><p>Ba&iuml;kal is missing its configuration file, or its configuration file is unreadable.');
}
if (!isset($config['parameters']["BAIKAL_CARD_ENABLED"]) || $config['parameters']["BAIKAL_CARD_ENABLED"] !== true) {
throw new ErrorException("Baikal CardDAV is disabled.", 0, 255, __FILE__, __LINE__);
}
$server = new \Baikal\Core\Server(
BAIKAL_CAL_ENABLED,
BAIKAL_CARD_ENABLED,
BAIKAL_DAV_AUTH_TYPE,
BAIKAL_AUTH_REALM,
$config['parameters']["BAIKAL_CAL_ENABLED"],
$config['parameters']["BAIKAL_CARD_ENABLED"],
$config['parameters']["BAIKAL_DAV_AUTH_TYPE"],
$config['parameters']["BAIKAL_AUTH_REALM"],
$GLOBALS['DB']->getPDO(),
BAIKAL_CARD_BASEURI
PROJECT_BASEURI . 'card.php/'
);
$server->start();

View file

@ -24,6 +24,8 @@
* This copyright notice MUST APPEAR in all copies of the script!
***************************************************************/
use Symfony\Component\Yaml\Yaml;
ini_set("session.cookie_httponly", 1);
ini_set("display_errors", 0);
ini_set("log_errors", 1);
@ -50,12 +52,18 @@ require PROJECT_PATH_ROOT . 'vendor/autoload.php';
# Bootstrapping Baïkal
\Baikal\Framework::bootstrap();
try {
$config = Yaml::parseFile(PROJECT_PATH_CONFIG . "config.yaml");
} catch (\Exception $e) {
die('<h1>Incomplete installation</h1><p>Ba&iuml;kal is missing its configuration file, or its configuration file is unreadable.');
}
$server = new \Baikal\Core\Server(
BAIKAL_CAL_ENABLED,
BAIKAL_CARD_ENABLED,
BAIKAL_DAV_AUTH_TYPE,
BAIKAL_AUTH_REALM,
$config['parameters']["BAIKAL_CAL_ENABLED"],
$config['parameters']["BAIKAL_CARD_ENABLED"],
$config['parameters']["BAIKAL_DAV_AUTH_TYPE"],
$config['parameters']["BAIKAL_AUTH_REALM"],
$GLOBALS['DB']->getPDO(),
BAIKAL_DAV_BASEURI
PROJECT_BASEURI . 'dav.php/'
);
$server->start();