Added first implementation of admin web interface

This commit is contained in:
Jérôme Schneider 2012-03-12 13:20:49 +01:00
parent 4f5dba7121
commit c79a62443b
13 changed files with 541 additions and 3 deletions

1
.gitignore vendored Normal file
View file

@ -0,0 +1 @@
Specific/ENABLE_ADMIN

View file

@ -0,0 +1,75 @@
<?php
/***************************************************************
* Copyright notice
*
* (c) 2012 Jérôme Schneider <mail@jeromeschneider.fr>
* All rights reserved
*
* http://baikal.codr.fr
*
* This script is part of the Baïkal Server project. The Baïkal
* Server project is free software; you can redistribute it
* and/or modify it under the terms of the GNU General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* The GNU General Public License can be found at
* http://www.gnu.org/copyleft/gpl.html.
*
* This script is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* This copyright notice MUST APPEAR in all copies of the script!
***************************************************************/
require_once(BAIKAL_PATH_FRAMEWORKS . "Tabulator/Tabulator.html.php");
class BaikalAdmin {
static function assertEnabled() {
if(!defined("BAIKAL_ADMIN_ENABLED") || BAIKAL_ADMIN_ENABLED !== TRUE) {
die("<h1>Baïkal Admin is disabled.</h1>To enable it, set BAIKAL_ADMIN_ENABLED to TRUE in <b>Specific/config.php</b>");
}
$bLocked = TRUE;
$sEnableFile = BAIKAL_PATH_SPECIFIC . "ENABLE_ADMIN";
if(file_exists($sEnableFile)) {
clearstatcache();
$iTime = intval(filemtime($sEnableFile));
if((time() - $iTime) < 3600) {
// file has been created more than an hour ago
// delete and declare locked
$bLocked = FALSE;
} else {
if(!@unlink($sEnableFile)) {
die("<h1>Baïkal Admin is locked.</h1>To unlock it, delete and re-create an empty file named ENABLE_ADMIN in <b>Specific/config.php</b>");
}
}
}
if($bLocked) {
die("<h1>Baïkal Admin is locked.</h1>To unlock it, create an empty file named ENABLE_ADMIN in <b>Specific/config.php</b>");
} else {
// update filemtime
@touch($sEnableFile);
}
}
static function displayUsers() {
$aUsers = BaikalTools::getUsers();
$oTabulator = new TabulatorHtml();
$oTabulator->addColumn(self::makeColumn("id", "Id", "numeric"));
$oTabulator->addColumn(self::makeColumn("username", "Username"));
$oTabulator->render($aUsers);
}
function &makeColumn($sName, $sHeader = "", $sType = "text") {
$oColumn = new TabulatorColumnHtml($sName, $sHeader, $sType);
return $oColumn;
}
}

View file

@ -0,0 +1,46 @@
<?php
/***************************************************************
* Copyright notice
*
* (c) 2012 Jérôme Schneider <mail@jeromeschneider.fr>
* All rights reserved
*
* http://baikal.codr.fr
*
* This script is part of the Baïkal Server project. The Baïkal
* Server project is free software; you can redistribute it
* and/or modify it under the terms of the GNU General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* The GNU General Public License can be found at
* http://www.gnu.org/copyleft/gpl.html.
*
* This script is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* This copyright notice MUST APPEAR in all copies of the script!
***************************************************************/
class BaikalTools {
public static function &db() {
return $GLOBALS["pdo"];
}
public static function getUsers() {
$aUsers = array();
# Fetching user
$stmt = BaikalTools::db()->prepare("SELECT * FROM users");
$stmt->execute();
while(($user = $stmt->fetch(PDO::FETCH_ASSOC, PDO::FETCH_ORI_FIRST)) !== FALSE) {
$aUsers[] = $user;
}
reset($aUsers);
return $aUsers;
}
}

View file

@ -58,6 +58,7 @@ if(@file_exists($sTemp) && (@is_dir($sTemp . "Core") || @is_link($sTemp . "Core"
define("BAIKAL_PATH_CORE", BAIKAL_PATH_ROOT . "Core/");
define("BAIKAL_PATH_SPECIFIC", BAIKAL_PATH_ROOT . "Specific/");
define("BAIKAL_PATH_FRAMEWORKS", BAIKAL_PATH_CORE . "Frameworks/");
require_once(BAIKAL_PATH_SPECIFIC . "config.php");
@ -72,15 +73,17 @@ if(!file_exists(BAIKAL_SQLITE_FILE)) {
$pdo = new PDO('sqlite:' . BAIKAL_SQLITE_FILE);
$pdo->setAttribute(PDO::ATTR_ERRMODE,PDO::ERRMODE_EXCEPTION);
$bShouldCheckEnv = ((!defined("BAIKAL_CONTEXT_CLI") || BAIKAL_CONTEXT_CLI === FALSE) && (!defined("BAIKAL_CONTEXT_ADMIN") || BAIKAL_CONTEXT_ADMIN === FALSE));
# Check if at least one user exists
if(!defined("BAIKAL_CONTEXT_CLI") || BAIKAL_CONTEXT_CLI === FALSE) {
if($bShouldCheckEnv === TRUE) {
if(($iNbUsers = intval($pdo->query('SELECT count(*) FROM users')->fetchColumn())) === 0) {
die("No users are defined.<br />To create a user, you can use the helper <b>Core/Scripts/adduser.php</b> (requires command line access)");
}
}
if(!defined("BAIKAL_CONTEXT_CLI") || BAIKAL_CONTEXT_CLI === FALSE) {
if($bShouldCheckEnv === TRUE) {
# Mapping PHP errors to exceptions
function exception_error_handler($errno, $errstr, $errfile, $errline) {
throw new ErrorException($errstr, 0, $errno, $errfile, $errline);

View file

@ -0,0 +1 @@
Versions/Tabulator.0.0.1

View file

@ -0,0 +1,63 @@
<?php
class Colorize {
private static $foreground_colors = array(
"black" => "1;30",
"dark_gray" => "1;30",
"blue" => "0;34",
"light_blue" => "1;34",
"green" => "0;32",
"light_green" => "1;32",
"cyan" => "0;36",
"light_cyan" => "1;36",
"red" => "0;31",
"light_red" => "1;31",
"purple" => "0;35",
"light_purple" => "1;35",
"brown" => "0;33",
"yellow" => "1;33",
"light_gray" => "0;37",
"white" => "1;37"
);
private static $background_colors = array(
"black" => "40",
"red" => "41",
"green" => "42",
"yellow" => "43",
"blue" => "44",
"magenta" => "45",
"cyan" => "46",
"light_gray" => "47"
);
// Returns colored string
public function getColoredString($string, $foreground_color = null, $background_color = null) {
$colored_string = "";
// Check if given foreground color found
if (isset(self::$foreground_colors[$foreground_color])) {
$colored_string .= "\033[" . self::$foreground_colors[$foreground_color] . "m";
}
// Check if given background color found
if (isset(self::$background_colors[$background_color])) {
$colored_string .= "\033[" . self::$background_colors[$background_color] . "m";
}
// Add string and end coloring
$colored_string .= $string . "\033[0m";
return $colored_string;
}
// Returns all foreground color names
public function getForegroundColors() {
return array_keys(self::$foreground_colors);
}
// Returns all background color names
public function getBackgroundColors() {
return array_keys(self::$background_colors);
}
}

View file

@ -0,0 +1,81 @@
<?php
$sDir = realpath(dirname(__FILE__)) . "/";
require_once($sDir . "Colorize.php");
require_once($sDir . "TabulatorColumn.php");
require_once($sDir . "Tabulator.php");
class TabulatorColumnCli extends TabulatorColumn {
protected $iLen = 0;
public function addValue($sValue) {
parent::addValue($sValue);
$iLen = mb_strlen($sValue, "utf8");
if($iLen > $this->iLen) {
$this->iLen = $iLen;
}
}
protected function wrap($sString) {
if($this->getType() === "numeric") {
$sPadType = STR_PAD_LEFT;
} else {
$sPadType = STR_PAD_RIGHT;
}
return $this->mb_str_pad($sString, $this->iLen, " ", $sPadType);
}
public function renderUnderline() {
return $this->wrap(str_repeat("-", $this->iLen));
}
protected function mb_str_pad($input, $pad_length, $pad_string=' ', $pad_type=STR_PAD_RIGHT) {
$diff = intval(mb_strlen($input, "latin1") - mb_strlen($input, "utf8"));
return str_pad($input, $pad_length+$diff, $pad_string, $pad_type);
}
}
class TabulatorCli extends Tabulator {
public function getSep() {
return " ";
}
public function repeatHeadersEvery() {
return 10;
}
protected function wrapHeaders($sHeaders) {
$aHeaderUnderline = array();
reset($this->aColumns);
while(list($sName,) = each($this->aColumns)) {
$aHeaderUnderline[] = $this->aColumns[$sName]->renderUnderline();
}
$sHeaders = Colorize::getColoredString($sHeaders, "white", "red");
#$sUnderline = Colorize::getColoredString(implode($this->getSep(), $aHeaderUnderline), "white", "red");
#return "\n" . $sHeaders . "\n" . $sUnderline . "\n";
return "\n" . $sHeaders . "\n";
}
protected function wrapValues($sValues, $iRowNum) {
if(($iRowNum % 2) === 0) {
return Colorize::getColoredString($sValues, "light_gray") . "\n";
}
return $sValues . "\n";
}
function renderOpen() {
return "";
}
function renderClose() {
return "";
}
}

View file

@ -0,0 +1,50 @@
<?php
$sDir = realpath(dirname(__FILE__)) . "/";
require_once($sDir . "TabulatorColumn.php");
require_once($sDir . "Tabulator.php");
class TabulatorColumnHtml extends TabulatorColumn {
protected function wrap($sString) {
if(in_array($this->getType(), array("numeric", "duration"))) {
$sAlign = "right";
} else {
$sAlign = "left";
}
return "<td class=\"col-" . $this->getName() . " align-" . $sAlign . "\">" . $sString . "</td>";
}
public function renderUnderline() {
return $this->wrap(str_repeat("-", $this->iLen));
}
}
class TabulatorHtml extends Tabulator {
public function getSep() {
return "";
}
protected function wrapHeaders($sHeaders) {
return "<tr class=\"headers\">" . $sHeaders . "</tr>";
}
protected function wrapValues($sValues, $iRowNum) {
$sClass = (($iRowNum % 2) === 0) ? "even" : "odd";
return "<tr class=\"values " . $sClass . "\">" . $sValues . "</tr>";
}
function renderOpen() {
return "<table class=\"books\">";
}
function renderClose() {
return "</table>";
}
public function repeatHeadersEvery() {
return 30;
}
}

View file

@ -0,0 +1,79 @@
<?php
abstract class Tabulator {
protected $aColumns = array();
protected $iNbValues = 0;
public function addColumn(TabulatorColumn $oColumn) {
$this->aColumns[$oColumn->getName()] = $oColumn;
}
public function hasColumn($sName) {
return array_key_exists($sName, $this->aColumns);
}
public function &getColumn($sName) {
return $this->aColumns[$sName];
}
protected function renderHeader() {
$aHeaderLine = array();
# on rend les entêtes
reset($this->aColumns);
while(list($sName,) = each($this->aColumns)) {
$aHeaderLine[] = $this->aColumns[$sName]->renderHeader();
}
return $this->wrapHeaders(implode($this->getSep(), $aHeaderLine));
}
protected function renderValues() {
$aRes = array();
for($k = 0; $k < $this->iNbValues; $k++) {
$aLine = array();
reset($this->aColumns);
while(list($sName,) = each($this->aColumns)) {
$aLine[] = $this->aColumns[$sName]->renderValueAtIndex($k);
}
$aRes[] = $this->wrapValues(implode($this->getSep(), $aLine), $k);
if((($k+1) % $this->repeatHeadersEvery()) === 0 && ($k+1 < $this->iNbValues)) {
$aRes[] = $this->renderHeader();
}
}
return implode("", $aRes) . "\n";
}
public function render($aValues) {
$this->iNbValues = count($aValues);
reset($aValues);
while(list($iRow,) = each($aValues)) {
reset($aValues[$iRow]);
while(list($sColumnName,) = each($aValues[$iRow])) {
if($this->hasColumn($sColumnName)) {
$this->getColumn($sColumnName)->addValue($aValues[$iRow][$sColumnName]);
}
}
}
echo $this->renderOpen();
echo $this->renderHeader();
echo $this->renderValues();
echo $this->renderClose();
}
abstract protected function getSep();
abstract protected function wrapHeaders($sHeaders);
abstract protected function wrapValues($sValues, $iRowNum);
abstract protected function renderOpen();
abstract protected function renderClose();
abstract protected function repeatHeadersEvery();
}

View file

@ -0,0 +1,96 @@
<?php
abstract class TabulatorColumn {
private $sHeader = "";
private $sName = "";
private $sType = "text";
private $aValues = array();
protected $aCallbacks = array();
public function __construct($sName, $sHeader = "", $sType = "text") {
$this->sHeader = $sHeader;
$this->iLen = mb_strlen($sHeader, "utf8");
$this->sName = $sName;
$this->sType = $sType;
}
public function getName() {
return $this->sName;
}
public function getHeader() {
return $this->sHeader;
}
public function getType() {
return $this->sType;
}
public function getValueAtIndex($iIndex) {
if($this->getType() === "duration") {
return $this->humanDuration(
$this->aValues[$iIndex] * 60
);
}
return $this->aValues[$iIndex];
}
public function addValue($sValue) {
$this->aValues[] = $sValue;
}
public function renderValueAtIndex($iIndex) {
return $this->wrap($this->getValueAtIndex($iIndex));
}
public function renderHeader() {
$sString = $this->getHeader();
if(array_key_exists("headerinnerwrap", $this->aCallbacks)) {
$sString = call_user_func($this->aCallbacks["headerinnerwrap"], $this, $sString);
}
return $this->wrapHeader($sString);
}
public function humanDuration($iSeconds) {
$units = array(
# "w" => 7*24*3600,
# "j" => 24*3600,
"h" => 3600,
"m" => 60,
"s" => 1,
);
// specifically handle zero
if($iSeconds == 0) {
return "0 second";
}
$s = "";
foreach ( $units as $name => $divisor ) {
if ( $quot = intval($iSeconds / $divisor) ) {
$s .= $quot . $name;
#$s .= (abs($quot) > 1 ? "s" : "") . "";
$iSeconds -= $quot * $divisor;
}
}
return $s;
#return substr($s, 0, -2);
}
public function setHeaderInnerWrapCallback($aCallback) {
$this->aCallbacks["headerinnerwrap"] = $aCallback;
}
protected function wrapHeader($sString) {
return $this->wrap($sString);
}
abstract protected function wrap($sString);
abstract public function renderUnderline();
}

View file

@ -0,0 +1,39 @@
<?php
/***************************************************************
* Copyright notice
*
* (c) 2012 Jérôme Schneider <mail@jeromeschneider.fr>
* All rights reserved
*
* http://baikal.codr.fr
*
* This script is part of the Baïkal Server project. The Baïkal
* Server project is free software; you can redistribute it
* and/or modify it under the terms of the GNU General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* The GNU General Public License can be found at
* http://www.gnu.org/copyleft/gpl.html.
*
* This script is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* This copyright notice MUST APPEAR in all copies of the script!
***************************************************************/
ini_set("display_errors", 1);
error_reporting(E_ALL);
define("BAIKAL_CONTEXT", TRUE);
define("BAIKAL_CONTEXT_ADMIN", TRUE);
require_once("../Core/Bootstrap.php");
require_once(BAIKAL_PATH_CORE . "BaikalAdmin.php");
require_once(BAIKAL_PATH_CORE . "BaikalTools.php");
BaikalAdmin::assertEnabled();
echo "<h1>Baïkal Admin</h1>";
BaikalAdmin::displayUsers();

View file

@ -11,6 +11,9 @@ define("BAIKAL_TIMEZONE", "Europe/Paris");
# WEB absolute URI
define("BAIKAL_BASEURI", "http://dav.mydomain.com/");
# WEB absolute URI
define("BAIKAL_ADMIN_ENABLED", TRUE);
##############################################################################
# In this section: Optional configuration: you *may* customize these settings
@ -34,7 +37,7 @@ define("BAIKAL_CAL_ENABLED", TRUE);
#
# PATH to SabreDAV
define("BAIKAL_PATH_SABREDAV", BAIKAL_PATH_CORE . "Frameworks/SabreDAV/lib/Sabre/");
define("BAIKAL_PATH_SABREDAV", BAIKAL_PATH_FRAMEWORKS . "SabreDAV/lib/Sabre/");
# If you change this value, you'll have to re-generate passwords for all your users
define("BAIKAL_AUTH_REALM", "BaikalDAV");

1
html/admin.php Symbolic link
View file

@ -0,0 +1 @@
../Core/WWWRoot/admin.php