Merge pull request #899 from ByteHamster/rework-configuration

Rework configuration
This commit is contained in:
H. Lehmann 2020-03-24 14:13:10 +01:00 committed by GitHub
commit a16151eb46
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
31 changed files with 471 additions and 624 deletions

9
.gitignore vendored
View file

@ -2,8 +2,7 @@
logs
# Specific
Specific/config.php
Specific/config.system.php
config/baikal.yaml
Specific/INSTALL_DISABLED
# Composer stuff
@ -15,3 +14,9 @@ vendor
# Vim
.*.swp
# Others
.DS_Store
# IDE
nbproject

View file

@ -1,6 +1,12 @@
ChangeLog
=========
0.7.0 (2019-10-14)
------------------
* Changed to YAML configuration files
* Minor configuration improvements
0.6.1 (2019-11-13)
------------------

View file

@ -24,5 +24,5 @@
# This copyright notice MUST APPEAR in all copies of the script!
#################################################################
define("BAIKAL_VERSION", "0.6.1");
define("BAIKAL_VERSION", "0.7.0");
define("BAIKAL_HOMEPAGE", "http://sabre.io/baikal/");

View file

@ -28,6 +28,7 @@
namespace Baikal\Core;
use PDO;
use Symfony\Component\Yaml\Yaml;
/**
* The Baikal Server
@ -131,6 +132,12 @@ class Server {
*/
protected function initServer() {
try {
$config = Yaml::parseFile(PROJECT_PATH_CONFIG . "baikal.yaml");
} catch (\Exception $e) {
error_log('Error reading baikal.yaml file : ' . $e->getMessage());
}
if ($this->authType === 'Basic') {
$authBackend = new \Baikal\Core\PDOBasicAuth($this->pdo, $this->authRealm);
} else {
@ -171,8 +178,8 @@ class Server {
$this->server->addPlugin(new \Sabre\CalDAV\Schedule\Plugin());
$this->server->addPlugin(new \Sabre\DAV\Sharing\Plugin());
$this->server->addPlugin(new \Sabre\CalDAV\SharingPlugin());
if (defined("BAIKAL_INVITE_FROM") && BAIKAL_INVITE_FROM !== "") {
$this->server->addPlugin(new \Sabre\CalDAV\Schedule\IMipPlugin(BAIKAL_INVITE_FROM));
if (isset($config['system']["invite_from"]) && $config['system']["invite_from"] !== "") {
$this->server->addPlugin(new \Sabre\CalDAV\Schedule\IMipPlugin($config['system']["invite_from"]));
}
}
if ($this->enableCardDAV) {

View file

@ -73,33 +73,18 @@ 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 . "baikal.yaml")) {
throw new \Exception("config/baikal.yaml does not exist. Please use the Install tool to create it or duplicate baikal.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 . "baikal.yaml")) {
throw new \Exception("config/baikal.yaml is not readable. Please give read permissions to httpd user on file 'config/baikal.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'.");
}
# 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 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'.");
if (!is_writable(PROJECT_PATH_CONFIG . "baikal.yaml")) {
throw new \Exception("config/baikal.yaml is not writable. Please give write permissions to httpd user on file 'config/baikal.yaml'.");
}
}

View file

@ -27,6 +27,8 @@
namespace Baikal;
use Symfony\Component\Yaml\Yaml;
class Framework extends \Flake\Core\Framework {
static function installTool() {
@ -50,30 +52,24 @@ class Framework extends \Flake\Core\Framework {
\Baikal\Core\Tools::configureEnvironment();
# Check that a config file exists
if (
!file_exists(PROJECT_PATH_SPECIFIC . "config.php") ||
!file_exists(PROJECT_PATH_SPECIFIC . "config.system.php")
) {
if (!file_exists(PROJECT_PATH_CONFIG . "baikal.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 . "baikal.yaml");
date_default_timezone_set($config['system']['timezone']);
# Check that Baïkal is already configured
if (!defined("BAIKAL_CONFIGURED_VERSION")) {
if (!isset($config['system']['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, $config['system']['configured_version']) > 0) {
self::installTool();
} else {
# Check that admin password is set
if (!defined("BAIKAL_ADMIN_PASSWORDHASH")) {
if (!$config['system']['admin_passwordhash']) {
self::installTool();
}

View file

@ -27,6 +27,8 @@
namespace Baikal\Model;
use Symfony\Component\Yaml\Yaml;
class Calendar extends \Flake\Core\Model\Db {
const DATATABLE = "calendarinstances";
const PRIMARYKEY = "id";
@ -39,11 +41,21 @@ class Calendar extends \Flake\Core\Model\Db {
"description" => "",
"calendarorder" => 0,
"calendarcolor" => "",
"timezone" => PROJECT_TIMEZONE,
"timezone" => null,
"calendarid" => 0
];
protected $oCalendar; # Baikal\Model\Calendar\Calendar
function __construct($sPrimary = false) {
parent::__construct($sPrimary);
try {
$config = Yaml::parseFile(PROJECT_PATH_CONFIG . "baikal.yaml");
$this->set("timezone", $config['system']["timezone"]);
} catch (\Exception $e) {
error_log('Error reading baikal.yaml file : ' . $e->getMessage());
}
}
protected function initFloating() {
parent::initFloating();
$this->oCalendar = new Calendar\Calendar();

View file

@ -27,106 +27,44 @@
namespace Baikal\Model;
use Symfony\Component\Yaml\Yaml;
abstract class Config extends \Flake\Core\Model\NoDb {
protected $sConfigFilePath = "";
protected $aConstants = [];
protected $sConfigFileSection = "";
protected $aData = [];
function __construct($sConfigFilePath) {
function __construct($sConfigFileSection) {
# Note: no call to parent::__construct() to avoid erasing $this->aData
$this->sConfigFilePath = $sConfigFilePath;
$aConfig = $this->parseConfig(
$this->getConfigAsString()
);
$this->sConfigFileSection = $sConfigFileSection;
foreach (array_keys($this->aData) as $sProp) {
if (array_key_exists($sProp, $aConfig)) {
$this->aData[$sProp] = $aConfig[$sProp];
try {
$config = Yaml::parseFile(PROJECT_PATH_CONFIG . "baikal.yaml");
$aConfig = $config[$sConfigFileSection];
foreach (array_keys($this->aData) as $sProp) {
if (array_key_exists($sProp, $aConfig)) {
$this->aData[$sProp] = $aConfig[$sProp];
}
}
} catch (\Exception $e) {
error_log('Error reading baikal.yaml file : ' . $e->getMessage());
// Keep default values in $aData
}
}
protected function getConfigAsString() {
if (file_exists($this->sConfigFilePath)) {
$sContent = file_get_contents($this->sConfigFilePath);
return str_replace(LF . CR, LF, $sContent);
if (file_exists(PROJECT_PATH_CONFIG . "baikal.yaml")) {
return Yaml::parseFile(PROJECT_PATH_CONFIG . "baikal.yaml")[$this->sConfigFileSection];
} else {
$sConfig = "<?php\n" . \Baikal\Core\Tools::getCopyrightNotice() . "\n\n";
$sConfig .= static::getDefaultConfig();
return $sConfig;
return $this->aData;
}
}
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) &&
@is_file($this->sConfigFilePath) &&
@is_writable($this->sConfigFilePath)
@file_exists(PROJECT_PATH_CONFIG . "baikal.yaml") &&
@is_file(PROJECT_PATH_CONFIG . "baikal.yaml") &&
@is_writable(PROJECT_PATH_CONFIG . "baikal.yaml")
);
}
@ -147,95 +85,18 @@ 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 . ");";
}
if (file_exists(PROJECT_PATH_CONFIG . "baikal.yaml")) {
$config = Yaml::parseFile(PROJECT_PATH_CONFIG . "baikal.yaml");
} else {
$config = [];
}
$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);
$config[$this->sConfigFileSection] = $this->aData;
$yaml = Yaml::dump($config);
file_put_contents(PROJECT_PATH_CONFIG . "baikal.yaml", $yaml);
}
function destroy() {
}
protected static function getDefaultConfig() {
}
}

View file

@ -30,27 +30,27 @@ namespace Baikal\Model\Config;
class Database extends \Baikal\Model\Config {
protected $aConstants = [
"PROJECT_SQLITE_FILE" => [
"sqlite_file" => [
"type" => "litteral",
"comment" => "Define path to Baïkal Database SQLite file",
],
"PROJECT_DB_MYSQL" => [
"mysql" => [
"type" => "boolean",
"comment" => "MySQL > Use MySQL instead of SQLite ?",
],
"PROJECT_DB_MYSQL_HOST" => [
"mysql_host" => [
"type" => "string",
"comment" => "MySQL > Host, including ':portnumber' if port is not the default one (3306)",
],
"PROJECT_DB_MYSQL_DBNAME" => [
"mysql_dbname" => [
"type" => "string",
"comment" => "MySQL > Database name",
],
"PROJECT_DB_MYSQL_USERNAME" => [
"mysql_username" => [
"type" => "string",
"comment" => "MySQL > Username",
],
"PROJECT_DB_MYSQL_PASSWORD" => [
"mysql_password" => [
"type" => "string",
"comment" => "MySQL > Password",
],
@ -58,19 +58,23 @@ class Database extends \Baikal\Model\Config {
# Default values
protected $aData = [
"PROJECT_SQLITE_FILE" => 'PROJECT_PATH_SPECIFIC . "db/db.sqlite"',
"PROJECT_DB_MYSQL" => false,
"PROJECT_DB_MYSQL_HOST" => "",
"PROJECT_DB_MYSQL_DBNAME" => "",
"PROJECT_DB_MYSQL_USERNAME" => "",
"PROJECT_DB_MYSQL_PASSWORD" => "",
"sqlite_file" => PROJECT_PATH_SPECIFIC . "db/db.sqlite",
"mysql" => false,
"mysql_host" => "",
"mysql_dbname" => "",
"mysql_username" => "",
"mysql_password" => "",
];
function __construct() {
parent::__construct("database");
}
function formMorphologyForThisModelInstance() {
$oMorpho = new \Formal\Form\Morphology();
$oMorpho->add(new \Formal\Element\Text([
"prop" => "PROJECT_SQLITE_FILE",
"prop" => "sqlite_file",
"label" => "SQLite file path",
"validation" => "required",
"inputclass" => "input-xxlarge",
@ -78,30 +82,30 @@ class Database extends \Baikal\Model\Config {
]));
$oMorpho->add(new \Formal\Element\Checkbox([
"prop" => "PROJECT_DB_MYSQL",
"prop" => "mysql",
"label" => "Use MySQL",
"help" => "If checked, Baïkal will use MySQL instead of SQLite.",
"refreshonchange" => true,
]));
$oMorpho->add(new \Formal\Element\Text([
"prop" => "PROJECT_DB_MYSQL_HOST",
"prop" => "mysql_host",
"label" => "MySQL host",
"help" => "Host ip or name, including <strong>':portnumber'</strong> if port is not the default one (3306)"
]));
$oMorpho->add(new \Formal\Element\Text([
"prop" => "PROJECT_DB_MYSQL_DBNAME",
"prop" => "mysql_dbname",
"label" => "MySQL database name",
]));
$oMorpho->add(new \Formal\Element\Text([
"prop" => "PROJECT_DB_MYSQL_USERNAME",
"prop" => "mysql_username",
"label" => "MySQL username",
]));
$oMorpho->add(new \Formal\Element\Password([
"prop" => "PROJECT_DB_MYSQL_PASSWORD",
"prop" => "mysql_password",
"label" => "MySQL password",
]));
@ -111,8 +115,4 @@ class Database extends \Baikal\Model\Config {
function label() {
return "Baïkal Database Settings";
}
protected static function getDefaultConfig() {
throw new \Exception("Should never reach getDefaultConfig() on \Baikal\Model\Config\Database");
}
}

View file

@ -27,30 +27,32 @@
namespace Baikal\Model\Config;
use Symfony\Component\Yaml\Yaml;
class Standard extends \Baikal\Model\Config {
protected $aConstants = [
"PROJECT_TIMEZONE" => [
"timezone" => [
"type" => "string",
"comment" => "Timezone of the server; if unsure, check http://en.wikipedia.org/wiki/List_of_tz_database_time_zones",
],
"BAIKAL_CARD_ENABLED" => [
"card_enabled" => [
"type" => "boolean",
"comment" => "CardDAV ON/OFF switch; default TRUE",
],
"BAIKAL_CAL_ENABLED" => [
"cal_enabled" => [
"type" => "boolean",
"comment" => "CalDAV ON/OFF switch; default TRUE",
],
"BAIKAL_INVITE_FROM" => [
"invite_from" => [
"type" => "string",
"comment" => "CalDAV invite From: mail address (comment or leave blank to disable notifications)",
],
"BAIKAL_DAV_AUTH_TYPE" => [
"dav_auth_type" => [
"type" => "string",
"comment" => "HTTP authentication type for WebDAV; default Digest"
],
"BAIKAL_ADMIN_PASSWORDHASH" => [
"admin_passwordhash" => [
"type" => "string",
"comment" => "Baïkal Web admin password hash; Set via Baïkal Web Admin",
]
@ -58,19 +60,25 @@ class Standard extends \Baikal\Model\Config {
# Default values
protected $aData = [
"PROJECT_TIMEZONE" => "Europe/Paris",
"BAIKAL_CARD_ENABLED" => true,
"BAIKAL_CAL_ENABLED" => true,
"BAIKAL_INVITE_FROM" => "",
"BAIKAL_DAV_AUTH_TYPE" => "Digest",
"BAIKAL_ADMIN_PASSWORDHASH" => ""
];
"configured_version" => BAIKAL_VERSION,
"timezone" => "Europe/Paris",
"card_enabled" => true,
"cal_enabled" => true,
"dav_auth_type" => "Digest",
"admin_passwordhash" => "",
"auth_realm" => "BaikalDAV"
];
function __construct() {
$this->aData["invite_from"] = "noreply@" . $_SERVER['SERVER_NAME']; // Default value
parent::__construct("system");
}
function formMorphologyForThisModelInstance() {
$oMorpho = new \Formal\Form\Morphology();
$oMorpho->add(new \Formal\Element\Listbox([
"prop" => "PROJECT_TIMEZONE",
"prop" => "timezone",
"label" => "Server Time zone",
"validation" => "required",
"options" => \Baikal\Core\Tools::timezones(),
@ -78,46 +86,52 @@ class Standard extends \Baikal\Model\Config {
$oMorpho->add(new \Formal\Element\Checkbox([
"prop" => "BAIKAL_CARD_ENABLED",
"prop" => "card_enabled",
"label" => "Enable CardDAV"
]));
$oMorpho->add(new \Formal\Element\Checkbox([
"prop" => "BAIKAL_CAL_ENABLED",
"prop" => "cal_enabled",
"label" => "Enable CalDAV"
]));
$oMorpho->add(new \Formal\Element\Text([
"prop" => "BAIKAL_INVITE_FROM",
"prop" => "invite_from",
"label" => "Email invite sender address",
"help" => "Leave empty to disable sending invite emails"
]));
$oMorpho->add(new \Formal\Element\Listbox([
"prop" => "BAIKAL_DAV_AUTH_TYPE",
"prop" => "dav_auth_type",
"label" => "WebDAV authentication type",
"options" => ["Digest", "Basic"]
]));
$oMorpho->add(new \Formal\Element\Password([
"prop" => "BAIKAL_ADMIN_PASSWORDHASH",
"prop" => "admin_passwordhash",
"label" => "Admin password",
]));
$oMorpho->add(new \Formal\Element\Password([
"prop" => "BAIKAL_ADMIN_PASSWORDHASH_CONFIRM",
"prop" => "admin_passwordhash_confirm",
"label" => "Admin password, confirmation",
"validation" => "sameas:BAIKAL_ADMIN_PASSWORDHASH",
"validation" => "sameas:admin_passwordhash",
]));
if (!defined("BAIKAL_ADMIN_PASSWORDHASH") || trim(BAIKAL_ADMIN_PASSWORDHASH) === "") {
try {
$config = Yaml::parseFile(PROJECT_PATH_CONFIG . "baikal.yaml");
} catch (\Exception $e) {
error_log('Error reading baikal.yaml file : ' . $e->getMessage());
}
if (!isset($config['system']["admin_passwordhash"]) || trim($config['system']["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");
$oMorpho->element("admin_passwordhash")->setOption("validation", "required");
} else {
$sNotice = "-- Leave empty to keep current password --";
$oMorpho->element("BAIKAL_ADMIN_PASSWORDHASH")->setOption("placeholder", $sNotice);
$oMorpho->element("BAIKAL_ADMIN_PASSWORDHASH_CONFIRM")->setOption("placeholder", $sNotice);
$oMorpho->element("admin_passwordhash")->setOption("placeholder", $sNotice);
$oMorpho->element("admin_passwordhash_confirm")->setOption("placeholder", $sNotice);
}
return $oMorpho;
@ -128,12 +142,12 @@ class Standard extends \Baikal\Model\Config {
}
function set($sProp, $sValue) {
if ($sProp === "BAIKAL_ADMIN_PASSWORDHASH" || $sProp === "BAIKAL_ADMIN_PASSWORDHASH_CONFIRM") {
if ($sProp === "admin_passwordhash" || $sProp === "admin_passwordhash_confirm") {
# Special handling for password and passwordconfirm
if ($sProp === "BAIKAL_ADMIN_PASSWORDHASH" && $sValue !== "") {
if ($sProp === "admin_passwordhash" && $sValue !== "") {
parent::set(
"BAIKAL_ADMIN_PASSWORDHASH",
"admin_passwordhash",
\BaikalAdmin\Core\Auth::hashAdminPassword($sValue)
);
}
@ -145,59 +159,10 @@ class Standard extends \Baikal\Model\Config {
}
function get($sProp) {
if ($sProp === "BAIKAL_ADMIN_PASSWORDHASH" || $sProp === "BAIKAL_ADMIN_PASSWORDHASH_CONFIRM") {
if ($sProp === "admin_passwordhash" || $sProp === "admin_passwordhash_confirm") {
return "";
}
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;
}
}

View file

@ -30,51 +30,35 @@ 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" => [
"sqlite_file" => [
"type" => "litteral",
"comment" => "Define path to Baïkal Database SQLite file",
],
"PROJECT_DB_MYSQL" => [
"mysql" => [
"type" => "boolean",
"comment" => "MySQL > Use MySQL instead of SQLite ?",
],
"PROJECT_DB_MYSQL_HOST" => [
"mysql_host" => [
"type" => "string",
"comment" => "MySQL > Host, including ':portnumber' if port is not the default one (3306)",
],
"PROJECT_DB_MYSQL_DBNAME" => [
"mysql_dbname" => [
"type" => "string",
"comment" => "MySQL > Database name",
],
"PROJECT_DB_MYSQL_USERNAME" => [
"mysql_username" => [
"type" => "string",
"comment" => "MySQL > Username",
],
"PROJECT_DB_MYSQL_PASSWORD" => [
"mysql_password" => [
"type" => "string",
"comment" => "MySQL > Password",
],
"BAIKAL_ENCRYPTION_KEY" => [
"baikal_encryption_key" => [
"type" => "string",
"comment" => "A random 32 bytes key that will be used to encrypt data",
],
"BAIKAL_CONFIGURED_VERSION" => [
"baikal_configured_version" => [
"type" => "string",
"comment" => "The currently configured Baïkal version",
],
@ -82,68 +66,25 @@ 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_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" => "",
"sqlite_file" => PROJECT_PATH_SPECIFIC . "db/db.sqlite",
"mysql" => false,
"mysql_host" => "",
"mysql_dbname" => "",
"mysql_username" => "",
"mysql_password" => "",
"encryption_key" => "",
"configured_version" => "",
];
function __construct() {
parent::__construct("database");
}
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",
"prop" => "sqlite_file",
"label" => "SQLite file path",
"validation" => "required",
"inputclass" => "input-xxlarge",
@ -151,30 +92,30 @@ class System extends \Baikal\Model\Config {
]));
$oMorpho->add(new \Formal\Element\Checkbox([
"prop" => "PROJECT_DB_MYSQL",
"prop" => "mysql",
"label" => "Use MySQL",
"help" => "If checked, Baïkal will use MySQL instead of SQLite.",
"refreshonchange" => true,
]));
$oMorpho->add(new \Formal\Element\Text([
"prop" => "PROJECT_DB_MYSQL_HOST",
"prop" => "mysql_host",
"label" => "MySQL host",
"help" => "Host ip or name, including ':portnumber' if port is not the default one (3306)"
]));
$oMorpho->add(new \Formal\Element\Text([
"prop" => "PROJECT_DB_MYSQL_DBNAME",
"prop" => "mysql_dbname",
"label" => "MySQL database name",
]));
$oMorpho->add(new \Formal\Element\Text([
"prop" => "PROJECT_DB_MYSQL_USERNAME",
"prop" => "mysql_username",
"label" => "MySQL username",
]));
$oMorpho->add(new \Formal\Element\Password([
"prop" => "PROJECT_DB_MYSQL_PASSWORD",
"prop" => "mysql_password",
"label" => "MySQL password",
]));
@ -184,59 +125,4 @@ class System extends \Baikal\Model\Config {
function label() {
return "Baïkal Settings";
}
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;
}
}

View file

@ -27,6 +27,8 @@
namespace Baikal\Model;
use Symfony\Component\Yaml\Yaml;
class User extends \Flake\Core\Model\Db {
const DATATABLE = "users";
const PRIMARYKEY = "id";
@ -279,6 +281,13 @@ 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 . "baikal.yaml");
} catch (\Exception $e) {
error_log('Error reading baikal.yaml file : ' . $e->getMessage());
}
return md5($this->get("username") . ':' . $config['system']['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 . "baikal.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['system']['cal_enabled']);
$oView->setData("baikal_card_enabled", $config['system']['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,18 @@ 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\System();
if (file_exists(PROJECT_PATH_SPECIFIC . "config.system.php")) {
require_once(PROJECT_PATH_SPECIFIC . "config.system.php");
$this->oModel->set('sqlite_file', PROJECT_SQLITE_FILE);
$this->oModel->set('mysql', PROJECT_DB_MYSQL);
$this->oModel->set('mysql_host', PROJECT_DB_MYSQL_HOST);
$this->oModel->set('mysql_dbname', PROJECT_DB_MYSQL_DBNAME);
$this->oModel->set('mysql_username', PROJECT_DB_MYSQL_USERNAME);
$this->oModel->set('mysql_password', PROJECT_DB_MYSQL_PASSWORD);
$this->oModel->set('encryption_key', BAIKAL_ENCRYPTION_KEY);
}
$this->oForm = $this->oModel->formForThisModelInstance([
"close" => false,
@ -46,6 +59,9 @@ class Database extends \Flake\Core\Controller {
$this->oForm->execute();
if ($this->oForm->persisted()) {
if (file_exists(PROJECT_PATH_SPECIFIC . "config.system.php")) {
@unlink(PROJECT_PATH_SPECIFIC . "config.system.php");
}
touch(PROJECT_PATH_SPECIFIC . '/INSTALL_DISABLED');
}
}
@ -60,7 +76,7 @@ class Database extends \Flake\Core\Controller {
if ($this->oForm->persisted()) {
$sMessage = "<p>Baïkal is now installed, and it's database properly configured. <strong>For security reasons, this installation wizard is now disabled.</strong></p>";
$sMessage = "<p>Baïkal is now installed, and its database properly configured. <strong>For security reasons, this installation wizard is now disabled.</strong></p>";
$sMessage . "<p>&nbsp;</p>";
$sMessage .= "<p><a class='btn btn-success' href='" . PROJECT_URI . "admin/'>Start using Baïkal</a></p>";
$sForm = "";
@ -79,14 +95,14 @@ class Database extends \Flake\Core\Controller {
if ($oForm->refreshed()){
return true;
}
$bMySQLEnabled = $oMorpho->element("PROJECT_DB_MYSQL")->value();
$bMySQLEnabled = $oMorpho->element("mysql")->value();
if ($bMySQLEnabled) {
$sHost = $oMorpho->element("PROJECT_DB_MYSQL_HOST")->value();
$sDbname = $oMorpho->element("PROJECT_DB_MYSQL_DBNAME")->value();
$sUsername = $oMorpho->element("PROJECT_DB_MYSQL_USERNAME")->value();
$sPassword = $oMorpho->element("PROJECT_DB_MYSQL_PASSWORD")->value();
$sHost = $oMorpho->element("mysql_host")->value();
$sDbname = $oMorpho->element("mysql_dbname")->value();
$sUsername = $oMorpho->element("mysql_username")->value();
$sPassword = $oMorpho->element("mysql_password")->value();
try {
$oDb = new \Flake\Core\Database\Mysql(
@ -107,7 +123,7 @@ class Database extends \Flake\Core\Controller {
$sMessage .= "<br /><p>Nothing has been saved. <strong>Please, add these tables to the database before pursuing Baïkal initialization.</strong></p>";
$oForm->declareError(
$oMorpho->element("PROJECT_DB_MYSQL"),
$oMorpho->element("mysql"),
$sMessage
);
} else {
@ -120,35 +136,29 @@ class Database extends \Flake\Core\Controller {
return true;
} catch (\Exception $e) {
$oForm->declareError($oMorpho->element("PROJECT_DB_MYSQL"),
$oForm->declareError($oMorpho->element("mysql"),
"Baïkal was not able to establish a connexion to the MySQL database as configured.<br />MySQL says: " . $e->getMessage());
$oForm->declareError($oMorpho->element("PROJECT_DB_MYSQL_HOST"));
$oForm->declareError($oMorpho->element("PROJECT_DB_MYSQL_DBNAME"));
$oForm->declareError($oMorpho->element("PROJECT_DB_MYSQL_USERNAME"));
$oForm->declareError($oMorpho->element("PROJECT_DB_MYSQL_PASSWORD"));
$oForm->declareError($oMorpho->element("mysql_host"));
$oForm->declareError($oMorpho->element("mysql_dbname"));
$oForm->declareError($oMorpho->element("mysql_username"));
$oForm->declareError($oMorpho->element("mysql_password"));
}
} else {
$sFile = $oMorpho->element("PROJECT_SQLITE_FILE")->value();
$sFile = $oMorpho->element("sqlite_file")->value();
try {
// not sure yet how to better address this
// yup! this is mental, but even if we don't use eval, effectively these
// config settings are eval'ed because they are written as raw php files.
// We'll have to clean this up later.
$sFile = eval('return ' . $sFile . ';');
# Asserting DB file is writable
if (file_exists($sFile) && !is_writable($sFile)) {
$sMessage = "DB file is not writable. Please give write permissions on file <span style='font-family: monospace'>" . $sFile . "</span>";
$oForm->declareError($oMorpho->element("PROJECT_SQLITE_FILE"), $sMessage);
$oForm->declareError($oMorpho->element("sqlite_file"), $sMessage);
return false;
}
# Asserting DB directory is writable
if (!is_writable(dirname($sFile))) {
$sMessage = "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'>" . dirname($sFile) . "</span>";
$oForm->declareError($oMorpho->element("PROJECT_SQLITE_FILE"), $sMessage);
$oForm->declareError($oMorpho->element("sqlite_file"), $sMessage);
return false;
}
@ -168,7 +178,7 @@ class Database extends \Flake\Core\Controller {
$sMessage .= "<br /><p>Nothing has been saved. <strong>Please, add these tables to the database before pursuing Baïkal initialization.</strong></p>";
$oForm->declareError(
$oMorpho->element("PROJECT_SQLITE_FILE"),
$oMorpho->element("sqlite_file"),
$sMessage
);
} else {
@ -185,7 +195,7 @@ class Database extends \Flake\Core\Controller {
return true;
} catch (\Exception $e) {
$oForm->declareError(
$oMorpho->element("PROJECT_SQLITE_FILE"),
$oMorpho->element("sqlite_file"),
"Baïkal was not able to establish a connexion to the SQLite database as configured.<br />SQLite says: " . $e->getMessage() . (string)$e
);
}
@ -196,19 +206,24 @@ class Database extends \Flake\Core\Controller {
function hideMySQLFieldWhenNeeded(\Formal\Form $oForm, \Formal\Form\Morphology $oMorpho) {
if ($oForm->submitted()) {
$bMySQL = (intval($oForm->postValue("PROJECT_DB_MYSQL")) === 1);
$bMySQL = (intval($oForm->postValue("mysql")) === 1);
} else {
$bMySQL = PROJECT_DB_MYSQL;
try {
$configSystem = Yaml::parseFile(PROJECT_PATH_CONFIG . "baikal.yaml");
} catch (\Exception $e) {
error_log('Error reading baikal.yaml file : ' . $e->getMessage());
}
$bMySQL = $configSystem['database']['mysql'] ?? true;
}
if ($bMySQL === true) {
$oMorpho->remove("PROJECT_SQLITE_FILE");
$oMorpho->remove("sqlite_file");
} else {
$oMorpho->remove("PROJECT_DB_MYSQL_HOST");
$oMorpho->remove("PROJECT_DB_MYSQL_DBNAME");
$oMorpho->remove("PROJECT_DB_MYSQL_USERNAME");
$oMorpho->remove("PROJECT_DB_MYSQL_PASSWORD");
$oMorpho->remove("mysql_host");
$oMorpho->remove("mysql_dbname");
$oMorpho->remove("mysql_username");
$oMorpho->remove("mysql_password");
}
}
}

View file

@ -36,16 +36,26 @@ class Initialize extends \Flake\Core\Controller {
function execute() {
# Assert that /Specific is writable
if (!file_exists(PROJECT_PATH_SPECIFIC) || !is_dir(PROJECT_PATH_SPECIFIC) || !is_writable(PROJECT_PATH_SPECIFIC)) {
$message = "<h1>Error - Insufficient permissions on the <span style='background-color: yellow;'>Specific/</span> folder</h1><p>";
$message .= "<p>In order to work properly, Baïkal needs to have write permissions in the <strong>Specific/</strong> folder.</p>";
if (!file_exists(PROJECT_PATH_SPECIFIC) || !is_dir(PROJECT_PATH_SPECIFIC) || !is_writable(PROJECT_PATH_SPECIFIC) || !file_exists(PROJECT_PATH_CONFIG) || !is_dir(PROJECT_PATH_CONFIG) || !is_writable(PROJECT_PATH_CONFIG)) {
$message = "<h1>Error - Insufficient permissions on the configuration folders</h1><p>";
$message .= "<p>In order to work properly, Baïkal needs to have write permissions in the <strong>Specific/</strong> and <strong>config/</strong> folder.</p>";
die($message);
}
$this->createHtaccessFilesIfNeeded();
$this->oModel = new \Baikal\Model\Config\Standard(PROJECT_PATH_SPECIFIC . "config.php");
$this->oModel = new \Baikal\Model\Config\Standard();
// If we come from pre-0.7.0, we need to get the values from the config.php and config.system.php files
if (file_exists(PROJECT_PATH_SPECIFIC . "config.php")) {
require_once(PROJECT_PATH_SPECIFIC . "config.php");
$this->oModel->set('timezone', PROJECT_TIMEZONE);
$this->oModel->set('card_enabled', BAIKAL_CARD_ENABLED);
$this->oModel->set('cal_enabled', BAIKAL_CAL_ENABLED);
$this->oModel->set('invite_from', BAIKAL_INVITE_FROM);
$this->oModel->set('dav_auth_type', BAIKAL_DAV_AUTH_TYPE);
}
$this->oForm = $this->oModel->formForThisModelInstance([
"close" => false
@ -56,14 +66,22 @@ class Initialize extends \Flake\Core\Controller {
if ($this->oForm->persisted()) {
// If we come from pre-0.7.0, we need to remove the INSTALL_DISABLED file so we go to the next step
if (file_exists(PROJECT_PATH_SPECIFIC . '/INSTALL_DISABLED')) {
@unlink(PROJECT_PATH_SPECIFIC . '/INSTALL_DISABLED');
}
if (file_exists(PROJECT_PATH_SPECIFIC . "config.php")) {
@unlink(PROJECT_PATH_SPECIFIC . "config.php");
}
# Creating system config, and initializing BAIKAL_ENCRYPTION_KEY
$oSystemConfig = new \Baikal\Model\Config\System(PROJECT_PATH_SPECIFIC . "config.system.php");
$oSystemConfig->set("BAIKAL_ENCRYPTION_KEY", md5(microtime() . rand()));
$oSystemConfig = new \Baikal\Model\Config\System("system");
$oSystemConfig->set("encryption_key", md5(microtime() . rand()));
# Default: PDO::SQLite or PDO::MySQL ?
$aPDODrivers = \PDO::getAvailableDrivers();
if (!in_array('sqlite', $aPDODrivers)) { # PDO::MySQL is already asserted in \Baikal\Core\Tools::assertEnvironmentIsOk()
$oSystemConfig->set("PROJECT_DB_MYSQL", true);
$oSystemConfig->set("mysql", true);
}
$oSystemConfig->persist();
@ -79,6 +97,11 @@ class Initialize extends \Flake\Core\Controller {
$oView = new \BaikalAdmin\View\Install\Initialize();
$oView->setData("baikalversion", BAIKAL_VERSION);
// If we come from pre-0.7.0 (old config files are still present),
// we need to tell the installer page to show a warning message.
$oView->setData("oldConfigSystem", file_exists(PROJECT_PATH_SPECIFIC . "config.system.php"));
if ($this->oForm->persisted()) {
$sLink = PROJECT_URI . "admin/install/?/database";
\Flake\Util\Tools::redirect($sLink);

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,16 @@ 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 . "baikal.yaml");
} catch (\Exception $e) {
error_log('Error reading baikal.yaml file : ' . $e->getMessage());
}
if (isset($config['system']['configured_version']) && $config['system']['configured_version'] === BAIKAL_VERSION) {
$sMessage = "Your system is configured to use version <strong>" . $config['system']['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 = [];
@ -40,11 +42,18 @@ class VersionUpgrade extends \Flake\Core\Controller {
}
function render() {
try {
$config = Yaml::parseFile(PROJECT_PATH_CONFIG . "baikal.yaml");
} catch (\Exception $e) {
error_log('Error reading baikal.yaml file : ' . $e->getMessage());
}
$sBigIcon = "glyph2x-magic";
$sBaikalVersion = BAIKAL_VERSION;
$sBaikalConfiguredVersion = BAIKAL_CONFIGURED_VERSION;
$sBaikalConfiguredVersion = $config['system']['configured_version'];
if (BAIKAL_CONFIGURED_VERSION === BAIKAL_VERSION) {
if ($config['system']['configured_version'] === BAIKAL_VERSION) {
$sMessage = "Your system is configured to use version <strong>" . $sBaikalConfiguredVersion . "</strong>.<br />There's no upgrade to be done.";
} else {
$sMessage = "Upgrading Baïkal from version <strong>" . $sBaikalConfiguredVersion . "</strong> to version <strong>" . $sBaikalVersion . "</strong>";
@ -58,7 +67,7 @@ class VersionUpgrade extends \Flake\Core\Controller {
HTML;
try {
$bSuccess = $this->upgrade(BAIKAL_CONFIGURED_VERSION, BAIKAL_VERSION);
$bSuccess = $this->upgrade($config['system']['configured_version'], BAIKAL_VERSION);
} catch (\Exception $e) {
$bSuccess = false;
$this->aErrors[] = 'Uncaught exception during upgrade: ' . (string)$e;
@ -521,26 +530,17 @@ SQL
}
protected function updateConfiguredVersion($sVersionTo) {
# Create new settings
$oConfig = new \Baikal\Model\Config\Standard(PROJECT_PATH_SPECIFIC . "config.php");
$oConfig->persist();
# Update BAIKAL_CONFIGURED_VERSION
$oConfig = new \Baikal\Model\Config\System(PROJECT_PATH_SPECIFIC . "config.system.php");
$oConfig->set("BAIKAL_CONFIGURED_VERSION", $sVersionTo);
$oConfig = new \Baikal\Model\Config\System();
$oConfig->set("baikal_configured_version", $sVersionTo);
$oConfig->persist();
}
protected function assertConfigWritable() {
# Parsing the config also makes sure that it is not malformed
$oConfig = new \Baikal\Model\Config\Standard(PROJECT_PATH_SPECIFIC . "config.php");
$oConfig = new \Baikal\Model\Config\System();
if ($oConfig->writable() === false) {
throw new \Exception(PROJECT_PATH_SPECIFIC . "config.php is not writable");
}
$oConfig = new \Baikal\Model\Config\System(PROJECT_PATH_SPECIFIC . "config.system.php");
if ($oConfig->writable() === false) {
throw new \Exception(PROJECT_PATH_SPECIFIC . "config.system.php is not writable");
throw new \Exception(PROJECT_PATH_CONFIG . "baikal.yaml is not writable");
}
}
}

View file

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

View file

@ -27,6 +27,8 @@
namespace BaikalAdmin\Controller\Settings;
use Symfony\Component\Yaml\Yaml;
class System extends \Flake\Core\Controller {
/**
@ -40,11 +42,11 @@ class System extends \Flake\Core\Controller {
private $oForm;
function execute() {
$this->oModel = new \Baikal\Model\Config\System(PROJECT_PATH_SPECIFIC . "config.system.php");
$this->oModel = new \Baikal\Model\Config\System();
# 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([
@ -74,19 +76,24 @@ class System extends \Flake\Core\Controller {
function morphologyHook(\Formal\Form $oForm, \Formal\Form\Morphology $oMorpho) {
if ($oForm->submitted()) {
$bMySQL = (intval($oForm->postValue("PROJECT_DB_MYSQL")) === 1);
$bMySQL = (intval($oForm->postValue("mysql")) === 1);
} else {
$bMySQL = PROJECT_DB_MYSQL;
try {
$config = Yaml::parseFile(PROJECT_PATH_CONFIG . "baikal.yaml");
} catch (\Exception $e) {
error_log('Error reading baikal.yaml file : ' . $e->getMessage());
}
$bMySQL = $config['database']['mysql'] ?? true;
}
if ($bMySQL === true) {
$oMorpho->remove("PROJECT_SQLITE_FILE");
$oMorpho->remove("sqlite_file");
} else {
$oMorpho->remove("PROJECT_DB_MYSQL_HOST");
$oMorpho->remove("PROJECT_DB_MYSQL_DBNAME");
$oMorpho->remove("PROJECT_DB_MYSQL_USERNAME");
$oMorpho->remove("PROJECT_DB_MYSQL_PASSWORD");
$oMorpho->remove("mysql_host");
$oMorpho->remove("mysql_dbname");
$oMorpho->remove("mysql_username");
$oMorpho->remove("mysql_password");
}
}
@ -94,13 +101,13 @@ class System extends \Flake\Core\Controller {
if ($oForm->refreshed()){
return true;
}
if (intval($oForm->modelInstance()->get("PROJECT_DB_MYSQL")) === 1) {
if (intval($oForm->modelInstance()->get("mysql")) === 1) {
# We have to check the MySQL connection
$sHost = $oForm->modelInstance()->get("PROJECT_DB_MYSQL_HOST");
$sDbName = $oForm->modelInstance()->get("PROJECT_DB_MYSQL_DBNAME");
$sUsername = $oForm->modelInstance()->get("PROJECT_DB_MYSQL_USERNAME");
$sPassword = $oForm->modelInstance()->get("PROJECT_DB_MYSQL_PASSWORD");
$sHost = $oForm->modelInstance()->get("mysql_host");
$sDbName = $oForm->modelInstance()->get("mysql_dbname");
$sUsername = $oForm->modelInstance()->get("mysql_username");
$sPassword = $oForm->modelInstance()->get("mysql_password");
try {
$oDB = new \Flake\Core\Database\Mysql(
@ -112,10 +119,10 @@ class System extends \Flake\Core\Controller {
} catch (\Exception $e) {
$sMessage = "<strong>MySQL error:</strong> " . $e->getMessage();
$sMessage .= "<br /><strong>Nothing has been saved</strong>";
$oForm->declareError($oMorpho->element("PROJECT_DB_MYSQL_HOST"), $sMessage);
$oForm->declareError($oMorpho->element("PROJECT_DB_MYSQL_DBNAME"));
$oForm->declareError($oMorpho->element("PROJECT_DB_MYSQL_USERNAME"));
$oForm->declareError($oMorpho->element("PROJECT_DB_MYSQL_PASSWORD"));
$oForm->declareError($oMorpho->element("mysql_host"), $sMessage);
$oForm->declareError($oMorpho->element("mysql_dbname"));
$oForm->declareError($oMorpho->element("mysql_username"));
$oForm->declareError($oMorpho->element("mysql_password"));
return;
}
@ -124,31 +131,24 @@ class System extends \Flake\Core\Controller {
$sMessage .= "You may want create these tables using the file <strong>Core/Resources/Db/MySQL/db.sql</strong>";
$sMessage .= "<br /><br /><strong>Nothing has been saved</strong>";
$oForm->declareError($oMorpho->element("PROJECT_DB_MYSQL"), $sMessage);
$oForm->declareError($oMorpho->element("mysql"), $sMessage);
return;
}
} else {
$sFile = $oMorpho->element("PROJECT_SQLITE_FILE")->value();
$sFile = $oMorpho->element("sqlite_file")->value();
try {
// not sure yet how to better address this
// yup! this is mental, but even if we don't use eval, effectively these
// config settings are eval'ed because they are written as raw php files.
// We'll have to clean this up later.
$sFile = eval('return ' . $sFile . ';');
# Asserting DB file is writable
if (file_exists($sFile) && !is_writable($sFile)) {
$sMessage = "DB file is not writable. Please give write permissions on file <span style='font-family: monospace'>" . $sFile . "</span>";
$oForm->declareError($oMorpho->element("PROJECT_SQLITE_FILE"), $sMessage);
$oForm->declareError($oMorpho->element("sqlite_file"), $sMessage);
return;
}
# Asserting DB directory is writable
if (!is_writable(dirname($sFile))) {
$sMessage = "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'>" . dirname($sFile) . "</span>";
$oForm->declareError($oMorpho->element("PROJECT_SQLITE_FILE"), $sMessage);
$oForm->declareError($oMorpho->element("sqlite_file"), $sMessage);
return;
}
@ -164,14 +164,14 @@ class System extends \Flake\Core\Controller {
$sMessage .= "<br /><p>Nothing has been saved. <strong>Please, add these tables to the database before pursuing Baïkal initialization.</strong></p>";
$oForm->declareError(
$oMorpho->element("PROJECT_SQLITE_FILE"),
$oMorpho->element("sqlite_file"),
$sMessage
);
}
return;
} catch (\Exception $e) {
$oForm->declareError(
$oMorpho->element("PROJECT_SQLITE_FILE"),
$oMorpho->element("sqlite_file"),
"Baïkal was not able to establish a connexion to the SQLite database as configured.<br />SQLite says: " . $e->getMessage() . (string)$e
);
}

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 . "baikal.yaml");
if (isset($_SESSION["baikaladminauth"]) && $_SESSION["baikaladminauth"] === md5($config['system']['admin_passwordhash'])) {
return true;
}
@ -46,9 +51,13 @@ class Auth {
$sPass = \Flake\Util\Tools::POST("password");
$sPassHash = self::hashAdminPassword($sPass);
if ($sUser === "admin" && $sPassHash === BAIKAL_ADMIN_PASSWORDHASH) {
$_SESSION["baikaladminauth"] = md5(BAIKAL_ADMIN_PASSWORDHASH);
try {
$config = Yaml::parseFile(PROJECT_PATH_CONFIG . "baikal.yaml");
} catch (\Exception $e) {
error_log('Error reading baikal.yaml file : ' . $e->getMessage());
}
if ($sUser === "admin" && $sPassHash === $config['system']['admin_passwordhash']) {
$_SESSION["baikaladminauth"] = md5($config['system']['admin_passwordhash']);
return true;
}
@ -61,13 +70,17 @@ 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 . "baikal.yaml");
} catch (\Exception $e) {
error_log('Error reading baikal.yaml file : ' . $e->getMessage());
}
return md5('admin:' . $sAuthRealm . ':' . $sPassword);
# Fallback to default value; useful when initializing App, as all constants are not set yet
$sAuthRealm = $config['system']['auth_realm'] ?? "BaikalDAV";
return hash('sha256', 'admin:' . $sAuthRealm . ':' . $sPassword);
}
}

View file

@ -38,7 +38,7 @@
</div>
<div class="span3">
<h2>Services</h2>
{% if BAIKAL_CAL_ENABLED %}
{% if cal_enabled %}
{% set caldavclass = 'label-success' %}
{% set caldavtext = 'On' %}
{% else %}
@ -46,7 +46,7 @@
{% set caldavtext = 'Off' %}
{% endif %}
{% if BAIKAL_CARD_ENABLED %}
{% if card_enabled %}
{% set carddavclass = 'label-success' %}
{% set carddavtext = 'On' %}
{% else %}

View file

@ -2,6 +2,15 @@
<header class="jumbotron subhead" id="overview">
<h1><i class="glyph2x-magic"></i>Baïkal initialization wizard</h1>
<p class="lead">Configure your new Baïkal <strong>{{ baikalversion }}</strong> installation.</p>
{% if oldConfigSystem %}
<div class="alert">
<strong>With the 0.7.0 release, our configuration format was updated to use YAML files.</strong><br/>
You need to go through this installer again but we pre-filled most values with the ones from your old installation.<br/>
As we updated our hashing algorithm for the admin interface password, you need to enter it again.<br/>
The database with your contacts and events stays untouched. We still recommend that you make a full backup of your data before proceeding, as a safety measure.
</div>
{% endif %}
</header>
<a id="formid"></a>

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 . "baikal.yaml");
} catch (\Exception $e) {
$config = null;
error_log('Error reading baikal.yaml file : ' . $e->getMessage());
}
if (!$config || !isset($config['system']["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 (!isset($config['system']["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 ($config['system']["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,94 +209,82 @@ 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 . "baikal.yaml");
} catch (\Exception $e) {
error_log('Error reading baikal.yaml file : ' . $e->getMessage());
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['system']['configured_version']) || $config['system']['configured_version'] === BAIKAL_VERSION)) {
return true;
}
if ($config['database']['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['database']['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['database']['sqlite_file']) && !is_writable($config['database']['sqlite_file'])) {
die("<h3>DB file is not writable. Please give write permissions on file '<span style='font-family: monospace; background: yellow;'>" . $config['database']['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['database']['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['database']['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['database']['sqlite_file']) && is_readable($config['database']['sqlite_file']) && !isset($GLOBALS["DB"])) {
$GLOBALS["DB"] = new \Flake\Core\Database\Sqlite($config['database']['sqlite_file']);
return true;
}
return false;
}
protected static function initDbMysql() {
protected static function initDbMysql(array $config) {
if (!defined("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 (!$config['database']['mysql_host']) {
die("<h3>The constant PROJECT_DB_MYSQL_HOST, containing the MySQL host name, is not set.<br />You should set it in config/baikal.yaml</h3>");
}
if (!defined("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 (!$config['database']['mysql_dbname']) {
die("<h3>The constant PROJECT_DB_MYSQL_DBNAME, containing the MySQL database name, is not set.<br />You should set it in config/baikal.yaml</h3>");
}
if (!defined("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 (!$config['database']['mysql_username']) {
die("<h3>The constant PROJECT_DB_MYSQL_USERNAME, containing the MySQL database username, is not set.<br />You should set it in config/baikal.yaml</h3>");
}
if (!defined("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>");
if (!$config['database']['mysql_password']) {
die("<h3>The constant PROJECT_DB_MYSQL_PASSWORD, containing the MySQL database password, is not set.<br />You should set it in config/baikal.yaml</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['database']['mysql_host'],
$config['database']['mysql_dbname'],
$config['database']['mysql_username'],
$config['database']['mysql_password']
);
# We now setup t6he connexion to use UTF8
$GLOBALS["DB"]->query("SET NAMES UTF8");
} catch (\Exception $e) {
die("<h3>Baïkal was not able to establish a connexion to the configured MySQL database (as configured in Specific/config.system.php).</h3>");
die("<h3>Baïkal was not able to establish a connexion to the configured MySQL database (as configured in config/baikal.yaml).</h3>");
}
return true;

View file

@ -9,8 +9,9 @@ VERSION=$(shell php -r "include 'Core/Distrib.php'; echo BAIKAL_VERSION;")
dist: vendor/autoload.php
# Building Baikal $(VERSION)
rm -r $(BUILD_DIR); true
mkdir -p $(BUILD_DIR) $(BUILD_DIR)/Specific $(BUILD_DIR)/Specific/db
mkdir -p $(BUILD_DIR) $(BUILD_DIR)/Specific $(BUILD_DIR)/Specific/db $(BUILD_DIR)/config
touch $(BUILD_DIR)/Specific/db/.empty
touch $(BUILD_DIR)/config/.empty
rsync -av \
$(BUILD_FILES) \
--exclude="*.swp" \
@ -31,4 +32,4 @@ composer.lock: composer.json
clean:
# Wipe out all local data, and go back to a clean install
rm Specific/config.php Specific/config.system.php Specific/db/db.sqlite; true
rm config/baikal.yaml Specific/db/db.sqlite; true

View file

@ -1,6 +1,6 @@
{
"name": "fruux/baikal",
"description": "Baïkal is a lightweight CalDAV + CardDAV server based on PHP, SQLite and SabreDAV",
"description": "Baïkal is a lightweight CalDAV + CardDAV server based on PHP, SQLite or MySQL, and SabreDAV",
"keywords": ["Framework", "WebDAV", "CalDAV", "CardDAV", "iCalendar"],
"homepage": "http://sabre.io/baikal/",
"license" : "GPL-3.0",
@ -15,7 +15,8 @@
"require": {
"php" : "^7.1",
"sabre/dav" : "~4.1.0",
"twig/twig" : "~1.8.0"
"twig/twig" : "~1.8.0",
"symfony/yaml" : "^3.4"
},
"require-dev" : {
"sabre/cs" : "~0.0.6"
@ -31,6 +32,6 @@
}
},
"support" : {
"source" : "https://github.com/fruux/Baikal"
"source" : "https://github.com/sabre-io/Baikal"
}
}

17
config/baikal.yaml.dist Normal file
View file

@ -0,0 +1,17 @@
system:
configured_version: '0.7.0'
timezone: 'Europe/Paris'
card_enabled: true
cal_enabled: true
invite_from: 'noreply@localhost'
dav_auth_type: 'Digest'
admin_passwordhash: 5fe794627e1f841f8debba065e2c807a
auth_realm: BaikalDAV
database:
encryption_key: 5d3f0fa0192e3058ea70f1bb20924add
sqlite_file: "absolute/path/to/Specific/db/db.sqlite"
mysql: true
mysql_host: 'localhost'
mysql_dbname: 'baikal'
mysql_username: 'baikal'
mysql_password: 'baikal'

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 . "baikal.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['system']["cal_enabled"]) || $config['system']["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['system']["cal_enabled"],
$config['system']["card_enabled"],
$config['system']["dav_auth_type"],
$config['system']["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 . "baikal.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['system']["card_enabled"]) || $config['system']["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['system']["cal_enabled"],
$config['system']["card_enabled"],
$config['system']["dav_auth_type"],
$config['system']["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 . "baikal.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['system']["cal_enabled"],
$config['system']["card_enabled"],
$config['system']["dav_auth_type"],
$config['system']["auth_realm"],
$GLOBALS['DB']->getPDO(),
BAIKAL_DAV_BASEURI
PROJECT_BASEURI . 'dav.php/'
);
$server->start();

View file

@ -8,9 +8,6 @@ parameters:
-
message: '#Instantiated class Flake\\Core\\Exception not found.#'
path: Core/Frameworks/Flake/Util/Frameworks.php
-
message: '#Call to an undefined method Baikal\\Model\\Config\\Standard::getDefaultSystemConfig\(\).#'
path: Core/Frameworks/Baikal/Model/Config/Standard.php
-
message: '#Call to static method compileCss\(\) on an unknown class Frameworks\\LessPHP\\Delegate.#'
path: Core/Frameworks/Flake/Controller/Page.php