summaryrefslogtreecommitdiffstats
path: root/inc
diff options
context:
space:
mode:
authorSimon Rettberg2014-10-09 16:01:11 +0200
committerSimon Rettberg2014-10-09 16:01:11 +0200
commite1dc0d3c99217504de2ac8467156274786efc0bd (patch)
tree130d7fed1fff8aaaffe5942cf2a3d6bb1dad03c8 /inc
parentMinor fixes and improvements (diff)
downloadslx-admin-e1dc0d3c99217504de2ac8467156274786efc0bd.tar.gz
slx-admin-e1dc0d3c99217504de2ac8467156274786efc0bd.tar.xz
slx-admin-e1dc0d3c99217504de2ac8467156274786efc0bd.zip
Big load of changes
- Added callback functionality for taskmanager tasks. You can launch a task and define a callback function to be run when the task finished. This requires activating the cronjob - Added cron functionality: Add cronjob that calls the cron api every 5 minutes to use it. (See cron.inc.php) - Added eventlog - Added missing translations - Merged main-menu-login and main-menu-logout
Diffstat (limited to 'inc')
-rw-r--r--inc/configmodule.inc.php24
-rw-r--r--inc/database.inc.php2
-rw-r--r--inc/defaultdata.inc.php21
-rw-r--r--inc/event.inc.php96
-rw-r--r--inc/eventlog.inc.php23
-rw-r--r--inc/permission.inc.php7
-rw-r--r--inc/property.inc.php27
-rw-r--r--inc/taskmanager.inc.php23
-rw-r--r--inc/taskmanagercallback.inc.php43
-rw-r--r--inc/trigger.inc.php93
-rw-r--r--inc/user.inc.php41
-rw-r--r--inc/validator.inc.php50
12 files changed, 362 insertions, 88 deletions
diff --git a/inc/configmodule.inc.php b/inc/configmodule.inc.php
index c0838b5c..1788a53a 100644
--- a/inc/configmodule.inc.php
+++ b/inc/configmodule.inc.php
@@ -5,13 +5,13 @@ class ConfigModule
public static function insertAdConfig($title, $server, $searchbase, $binddn, $bindpw, $home)
{
- // TODO: Lock table, race condition if about 500 admins insert a config at the same time
+ Database::exec("LOCK TABLE configtgz_module WRITE");
Database::exec("INSERT INTO configtgz_module (title, moduletype, filepath, contents) "
. " VALUES (:title, 'AD_AUTH', '', '')", array('title' => $title));
$id = Database::lastInsertId();
if (!is_numeric($id)) Util::traceError('Inserting new AD config to DB did not yield a numeric insert id');
// Entry created, now try to get a free port for the proxy
- $res = Database::simpleQuery("SELECT moduleid, contents FROM configtgz_module");
+ $res = Database::simpleQuery("SELECT moduleid, contents FROM configtgz_module WHERE moduletype = 'AD_AUTH'");
$ports = array();
while ($row = $res->fetch(PDO::FETCH_ASSOC)) {
if ($row['moduleid'] == $id) {
@@ -42,12 +42,32 @@ class ConfigModule
'filename' => $moduleTgz,
'contents' => $data
));
+ Database::exec("UNLOCK TABLES");
// Add archive file name to array before returning it
$ownEntry['moduleid'] = $id;
$ownEntry['filename'] = $moduleTgz;
return $ownEntry;
}
+ /**
+ * Get all existing AD proxy configs.
+ *
+ * @return array array of ad configs in DB with fields:
+ * moduleid, filename, server, searchbase, binddn, bindpw, home, proxyport
+ */
+ public static function getAdConfigs()
+ {
+ $res = Database::simpleQuery("SELECT moduleid, filepath, contents FROM configtgz_module WHERE moduletype = 'AD_AUTH'");
+ $mods = array();
+ while ($row = $res->fetch(PDO::FETCH_ASSOC)) {
+ $data = json_decode($row['contents'], true);
+ $data['moduleid'] = $row['moduleid'];
+ $data['filename'] = $row['filepath'];
+ $mods[] = $data;
+ }
+ return $mods;
+ }
+
public static function insertBrandingModule($title, $archive)
{
Database::exec("INSERT INTO configtgz_module (title, moduletype, filepath, contents) "
diff --git a/inc/database.inc.php b/inc/database.inc.php
index 0d48c23c..72b7d0d7 100644
--- a/inc/database.inc.php
+++ b/inc/database.inc.php
@@ -16,7 +16,7 @@ class Database
*/
public static function getExpectedSchemaVersion()
{
- return 5;
+ return 6;
}
public static function needSchemaUpdate()
diff --git a/inc/defaultdata.inc.php b/inc/defaultdata.inc.php
index 12a304f6..abc857bb 100644
--- a/inc/defaultdata.inc.php
+++ b/inc/defaultdata.inc.php
@@ -25,6 +25,7 @@ class DefaultData
2 => 20, // Internet access
3 => 100, // Timesync
4 => 10, // System config
+ 5 => 15, // Public Shared folder
);
foreach ($cats as $cat => $sort) {
Database::exec("INSERT IGNORE INTO cat_setting (catid, sortval) VALUES (:catid, :sortval)", array(
@@ -94,7 +95,7 @@ class DefaultData
'catid' => '2',
'defaultvalue' => 'off',
'permissions' => '2',
- 'validator' => 'list:off|on|auto|wpad'
+ 'validator' => 'list:off|on|auto'
),
array(
'setting' => 'SLX_PROXY_PORT',
@@ -137,11 +138,25 @@ class DefaultData
'defaultvalue' => '1200',
'permissions' => '2',
'validator' => 'regex:/^\d*$/'
- )
+ ),
+ array(
+ 'setting' => 'SLX_COMMON_SHARE_PATH',
+ 'catid' => '5',
+ 'defaultvalue' => '',
+ 'permissions' => '2',
+ 'validator' => 'function:networkShare'
+ ),
+ array(
+ 'setting' => 'SLX_COMMON_SHARE_AUTH',
+ 'catid' => '5',
+ 'defaultvalue' => 'guest',
+ 'permissions' => '2',
+ 'validator' => 'list:guest|user'
+ ),
);
foreach ($data as $entry) {
Database::exec("INSERT IGNORE INTO setting (setting, catid, defaultvalue, permissions, validator)"
- . "VALUES (:setting, :catid, :defaultvalue, :permissions, :validator)");
+ . "VALUES (:setting, :catid, :defaultvalue, :permissions, :validator)", $entry);
}
}
diff --git a/inc/event.inc.php b/inc/event.inc.php
new file mode 100644
index 00000000..6689e12f
--- /dev/null
+++ b/inc/event.inc.php
@@ -0,0 +1,96 @@
+<?php
+
+/**
+ * Class with static functions that are called when a specific event
+ * took place, like the server has been booted, or the interface address
+ * has been changed.
+ * In contrast to the trigger class, this class should contain functions
+ * for things that happen semi-automatically in reaction to something else
+ * (which in turn might have been triggered explicitly).
+ */
+class Event
+{
+
+ /**
+ * Called when the system (re)booted. Could be implemented
+ * by a @reboot entry in crontab (running as the same user php does)
+ */
+ public static function systemBooted()
+ {
+ EventLog::info('System boot...');
+ $everythingFine = true;
+
+ DefaultData::populate();
+
+ // Tasks: fire away
+ $mountId = Trigger::mount();
+ $autoIp = Trigger::autoUpdateServerIp();
+ $ldadpId = Trigger::ldadp();
+ $ipxeId = Trigger::ipxe();
+
+ // Check status of all tasks
+ // Mount vm store
+ if ($mountId === false) {
+ EventLog::info('No VM store type defined.');
+ $everythingFine = false;
+ } else {
+ $res = Taskmanager::waitComplete($mountId, 5000);
+ if (Taskmanager::isFailed($res)) {
+ EventLog::failure('Mounting VM store failed', $res['data']['messages']);
+ $everythingFine = false;
+ }
+ }
+ // LDAP AD Proxy
+ if ($ldadpId === false) {
+ EventLog::failure('Cannot start LDAP-AD-Proxy: Taskmanager unreachable!');
+ $everythingFine = false;
+ } else {
+ $res = Taskmanager::waitComplete($ldadpId, 5000);
+ if (Taskmanager::isFailed($res)) {
+ EventLog::failure('Starting LDAP-AD-Proxy failed', $res['data']['messages']);
+ $everythingFine = false;
+ }
+ }
+ // Primary IP address
+ if (!$autoIp) {
+ EventLog::failure("The server's IP address could not be determined automatically, and there is no valid address configured.");
+ $everythingFine = false;
+ }
+ // iPXE generation
+ if ($ipxeId === false) {
+ EventLog::failure('Cannot generate PXE menu: Taskmanager unreachable!');
+ $everythingFine = false;
+ } else {
+ $res = Taskmanager::waitComplete($ipxeId, 5000);
+ if (Taskmanager::isFailed($res)) {
+ EventLog::failure('Update PXE Menu failed', $res['data']['error']);
+ $everythingFine = false;
+ }
+ }
+
+ // Just so we know booting is done (and we don't expect any more errors from booting up)
+ if ($everythingFine) {
+ EventLog::info('Bootup finished without errors.');
+ } else {
+ EventLog::info('There were errors during bootup. Maybe the server is not fully configured yet.');
+ }
+ }
+
+ /**
+ * Server's primary IP address changed.
+ */
+ public static function serverIpChanged()
+ {
+ Trigger::rebuildAdModules();
+ }
+
+ /**
+ * The activated configuration changed.
+ */
+ public static function activeConfigChanged()
+ {
+ $task = Trigger::ldadp();
+ TaskmanagerCallback::addCallback($task, 'ldadpStartup');
+ }
+
+}
diff --git a/inc/eventlog.inc.php b/inc/eventlog.inc.php
index dadccdd7..181f8d38 100644
--- a/inc/eventlog.inc.php
+++ b/inc/eventlog.inc.php
@@ -3,28 +3,31 @@
class EventLog
{
- private static function log($type, $message)
+ private static function log($type, $message, $details)
{
- Database::exec("INSERT INTO eventlog (dateline, logtypeid, description)"
- . " VALUES (UNIX_TIMESTAMP(), :type, :message)", array(
+ Database::exec("INSERT INTO eventlog (dateline, logtypeid, description, extra)"
+ . " VALUES (UNIX_TIMESTAMP(), :type, :message, :details)", array(
'type' => $type,
- 'message' => $message
+ 'message' => $message,
+ 'details' => $details
));
}
- public static function failure($message)
+ public static function failure($message, $details = '')
{
- self::log('failure', $message);
+ self::log('failure', $message, $details);
}
- public static function warning($message)
+ public static function warning($message, $details = '')
{
- self::log('warning', $message);
+ self::log('warning', $message, $details);
+ Property::setLastWarningId(Database::lastInsertId());
}
- public static function info($message)
+ public static function info($message, $details = '')
{
- self::log('info', $message);
+ self::log('info', $message, $details);
+ Property::setLastWarningId(Database::lastInsertId());
}
}
diff --git a/inc/permission.inc.php b/inc/permission.inc.php
index f90319a4..d04e3c3b 100644
--- a/inc/permission.inc.php
+++ b/inc/permission.inc.php
@@ -3,9 +3,10 @@
class Permission
{
private static $permissions = array(
- 'superadmin' => 1,
- 'baseconfig_global' => 2,
- 'baseconfig_local' => 4,
+ 'superadmin' => 1, // Can do everything
+ 'baseconfig_global' => 2, // Change configuration globally
+ 'baseconfig_local' => 4, // Change configuration for specifig groups/rooms
+ 'translation' => 8, // Can edit translations
);
public static function get($permission)
diff --git a/inc/property.inc.php b/inc/property.inc.php
index 605d901d..e4b4340b 100644
--- a/inc/property.inc.php
+++ b/inc/property.inc.php
@@ -19,11 +19,11 @@ class Property
private static function get($key, $default = false)
{
if (self::$cache === false) {
- if (mt_rand(1, 20) === 10) {
- Database::exec("DELETE FROM property WHERE dateline <> 0 AND dateline < UNIX_TIMESTAMP()");
- }
- $res = Database::simpleQuery("SELECT name, value FROM property");
+ $NOW = time();
+ $res = Database::simpleQuery("SELECT name, dateline, value FROM property");
while ($row = $res->fetch(PDO::FETCH_ASSOC)) {
+ if ($row['dateline'] != 0 && $row['dateline'] < $NOW)
+ continue;
self::$cache[$row['name']] = $row['value'];
}
}
@@ -37,7 +37,7 @@ class Property
*
* @param string $key key of value to set
* @param type $value the value to store for $key
- * @param int minage how long to keep this entry around at least, in minutes. 0 for infinite
+ * @param int $minage how long to keep this entry around at least, in minutes. 0 for infinite
*/
private static function set($key, $value, $minage = 0)
{
@@ -59,6 +59,8 @@ class Property
public static function setServerIp($value)
{
+ if ($value !== self::getServerIp())
+ Event::serverIpChanged();
self::set('server-ip', $value);
}
@@ -113,6 +115,7 @@ class Property
{
return json_decode(self::get('vmstore-config'), true);
}
+
public static function getVmStoreUrl()
{
$store = self::getVmStoreConfig();
@@ -136,15 +139,25 @@ class Property
{
return self::get('dl-' . $name);
}
-
+
public static function setDownloadTask($name, $taskId)
{
self::set('dl-' . $name, $taskId, 5);
}
-
+
public static function getCurrentSchemaVersion()
{
return self::get('webif-version');
}
+ public static function setLastWarningId($id)
+ {
+ self::set('last-warn-event-id', $id);
+ }
+
+ public static function getLastWarningId()
+ {
+ return self::get('last-warn-event-id', 0);
+ }
+
}
diff --git a/inc/taskmanager.inc.php b/inc/taskmanager.inc.php
index 5813164a..528b3f78 100644
--- a/inc/taskmanager.inc.php
+++ b/inc/taskmanager.inc.php
@@ -28,7 +28,7 @@ class Taskmanager
* @param string $task name of task to start
* @param array $data data to pass to the task. the structure depends on the task.
* @param boolean $async if true, the function will not wait for the reply of the taskmanager, which means
- * the return value is just true (and you won't know if the task could acutally be started)
+ * the return value is just true (and you won't know if the task could acutally be started)
* @return array struct representing the task status, or result of submit, false on communication error
*/
public static function submit($task, $data = false, $async = false)
@@ -49,8 +49,7 @@ class Taskmanager
if ($async)
return true;
$reply = self::readReply($seq);
- if ($reply === false || !is_array($reply) || !isset($reply['id'])
- || (isset($reply['statusCode']) && $reply['statusCode'] === NO_SUCH_TASK)) {
+ if ($reply === false || !is_array($reply) || !isset($reply['id']) || (isset($reply['statusCode']) && $reply['statusCode'] === NO_SUCH_TASK)) {
self::addErrorMessage($reply);
return false;
}
@@ -117,7 +116,7 @@ class Taskmanager
/**
* Check whether the given task can be considered failed.
*
- * @param mixed $task task id or struct representing task
+ * @param array $task struct representing task, obtained by ::status
* @return boolean true if task failed, false if finished successfully or still waiting/running
*/
public static function isFailed($task)
@@ -129,6 +128,22 @@ class Taskmanager
return false;
}
+ /**
+ * Check whether the given task is finished, i.e. either failed or succeeded,
+ * but is not running, still waiting for execution or simply unknown.
+ *
+ * @param array $task struct representing task, obtained by ::status
+ * @return boolean true if task failed or finished, false if waiting for execution or currently executing, no valid task, etc.
+ */
+ public static function isFinished($task)
+ {
+ if (!is_array($task) || !isset($task['statusCode']) || !isset($task['id']))
+ return false;
+ if ($task['statusCode'] === TASK_ERROR || $task['statusCode'] === TASK_FINISHED)
+ return true;
+ return false;
+ }
+
public static function addErrorMessage($task)
{
static $failure = false;
diff --git a/inc/taskmanagercallback.inc.php b/inc/taskmanagercallback.inc.php
new file mode 100644
index 00000000..3ef4745c
--- /dev/null
+++ b/inc/taskmanagercallback.inc.php
@@ -0,0 +1,43 @@
+<?php
+
+/**
+ * Contains all callbacks for detached taskmanager tasks.
+ */
+class TaskmanagerCallback
+{
+
+ /**
+ * Add a callback for given task id. This is the only exception in this class,
+ * as this is not a callback, but a function to define one :)
+ *
+ * @param string|array $task Task or Task ID to define callback for
+ * @param string $callback name of callback function, must be a static method in this class
+ */
+ public static function addCallback($task, $callback)
+ {
+ if (!call_user_func_array('method_exists', array('TaskmanagerCallback', $callback))) {
+ EventLog::warning("addCallback: Invalid callback function: $callback");
+ return;
+ }
+ if (is_array($task) && isset($task['id']))
+ $task = $task['id'];
+ if (!is_string($task)) {
+ EventLog::warning("addCallback: Not a valid task id: $task");
+ return;
+ }
+ Database::exec("INSERT INTO callback (taskid, dateline, cbfunction) VALUES (:task, UNIX_TIMESTAMP(), :callback)", array(
+ 'task' => $task,
+ 'callback' => $callback
+ ));
+ }
+
+ /**
+ * Result of trying to (re)launch ldadp.
+ */
+ public static function ldadpStartup($task)
+ {
+ if (Taskmanager::isFailed($task))
+ EventLog::warning("Could not start/stop LDAP-AD-Proxy instances", $task['data']['messages']);
+ }
+
+}
diff --git a/inc/trigger.inc.php b/inc/trigger.inc.php
index 0b31c7b3..73ad6ce8 100644
--- a/inc/trigger.inc.php
+++ b/inc/trigger.inc.php
@@ -10,7 +10,7 @@
*/
class Trigger
{
-
+
/**
* Compile iPXE pxelinux menu. Needs to be done whenever the server's IP
* address changes.
@@ -26,7 +26,7 @@ class Trigger
return false;
return $task['id'];
}
-
+
/**
* Try to automatically determine the primary IP address of the server.
* This only works if the server has either one public IPv4 address (and potentially
@@ -84,53 +84,53 @@ class Trigger
public static function ldadp($parent = NULL)
{
$res = Database::simpleQuery("SELECT moduleid, configtgz.filepath FROM configtgz_module"
- . " INNER JOIN configtgz_x_module USING (moduleid)"
- . " INNER JOIN configtgz USING (configid)"
- . " WHERE moduletype = 'AD_AUTH'");
+ . " INNER JOIN configtgz_x_module USING (moduleid)"
+ . " INNER JOIN configtgz USING (configid)"
+ . " WHERE moduletype = 'AD_AUTH'");
// TODO: Multiconfig support
$id = array();
while ($row = $res->fetch(PDO::FETCH_ASSOC)) {
if (readlink('/srv/openslx/www/boot/default/config.tgz') === $row['filepath']) {
- $id[] = (int)$row['moduleid'];
+ $id[] = (int) $row['moduleid'];
break;
}
}
$task = Taskmanager::submit('LdadpLauncher', array(
- 'ids' => $id,
- 'parentTask' => $parent,
- 'failOnParentFail' => false
+ 'ids' => $id,
+ 'parentTask' => $parent,
+ 'failOnParentFail' => false
));
if (!isset($task['id']))
return false;
return $task['id'];
}
-
+
/**
* To be called if the server ip changes, as it's embedded in the AD module configs.
* This will then recreate all AD tgz modules.
*/
public static function rebuildAdModules()
{
- $res = Database::simpleQuery("SELECT moduleid, filepath, content FROM configtgz_module"
- . " WHERE moduletype = 'AD_AUTH'");
- if ($res->rowCount() === 0)
- return;
-
$task = Taskmanager::submit('LdadpLauncher', array('ids' => array())); // Stop all running instances
+ $ads = ConfigModule::getAdConfigs();
+ if (empty($ads))
+ return;
+
$parent = isset($task['id']) ? $task['id'] : NULL;
- while ($row = $res->fetch(PDO::FETCH_ASSOC)) {
- $config = json_decode($row['contents']);
- $config['proxyip'] = Property::getServerIp();
- $config['moduleid'] = $row['moduleid'];
- $config['filename'] = $row['filepath'];
- $config['parentTask'] = $parent;
- $config['failOnParentFail'] = false;
- $task = Taskmanager::submit('CreateAdConfig', $config);
- $parent = isset($task['id']) ? $task['id'] : NULL;
+ foreach ($ads as $ad) {
+ $ad['parentTask'] = $parent;
+ $ad['failOnParentFail'] = false;
+ $task = Taskmanager::submit('CreateAdConfig', $ad);
+ if (isset($task['id']))
+ $parent = $task['id'];
+ }
+ if (Taskmanager::waitComplete($parent, 2000) === false) {
+ EventLog::warning('Rebuilding LDAP-AD-Proxy config failed. AD Auth might not work properly.');
+ sleep(1);
}
-
+ Trigger::ldadp();
}
-
+
/**
* Mount the VM store into the server.
*
@@ -139,17 +139,42 @@ class Trigger
public static function mount()
{
$vmstore = Property::getVmStoreConfig();
- if (!is_array($vmstore)) return false;
+ if (!is_array($vmstore))
+ return false;
$storetype = $vmstore['storetype'];
- if ($storetype === 'nfs') $addr = $vmstore['nfsaddr'];
- if ($storetype === 'cifs') $addr = $vmstore['cifsaddr'];
- if ($storetype === 'internal') $addr = 'null';
+ if ($storetype === 'nfs')
+ $addr = $vmstore['nfsaddr'];
+ if ($storetype === 'cifs')
+ $addr = $vmstore['cifsaddr'];
+ if ($storetype === 'internal')
+ $addr = 'null';
return Taskmanager::submit('MountVmStore', array(
- 'address' => $addr,
- 'type' => 'images',
- 'username' => $vmstore['cifsuser'],
- 'password' => $vmstore['cifspasswd']
+ 'address' => $addr,
+ 'type' => 'images',
+ 'username' => $vmstore['cifsuser'],
+ 'password' => $vmstore['cifspasswd']
));
}
+
+ /**
+ * Check and process all callbacks
+ */
+ public static function checkCallbacks()
+ {
+ $res = Database::simpleQuery("SELECT taskid, cbfunction FROM callback");
+ while ($row = $res->fetch(PDO::FETCH_ASSOC)) {
+ $status = Taskmanager::status($row['taskid']);
+ if (Taskmanager::isFailed($status) || Taskmanager::isFinished($status))
+ Database::exec("DELETE FROM callback WHERE taskid = :task AND cbfunction = :cb LIMIT 1", array('task' => $row['taskid'], 'cb' => $row['cbfunction']));
+ if (Taskmanager::isFinished($status)) {
+ $func = array('TaskmanagerCallback', preg_replace('/\W/', '', $row['cbfunction']));
+ if (!call_user_func_array('method_exists', $func)) {
+ Eventlog::warning("Callback {$row['cbfunction']} doesn't exist.");
+ } else {
+ call_user_func($func, $status);
+ }
+ }
+ }
+ }
}
diff --git a/inc/user.inc.php b/inc/user.inc.php
index 19d17753..111849fe 100644
--- a/inc/user.inc.php
+++ b/inc/user.inc.php
@@ -4,6 +4,7 @@ require_once('inc/session.inc.php');
class User
{
+
private static $user = false;
public static function isLoggedIn()
@@ -13,26 +14,29 @@ class User
public static function getName()
{
- if (self::$user === false) return false;
+ if (!self::isLoggedIn())
+ return false;
return self::$user['fullname'];
}
public static function hasPermission($permission)
{
- if (self::$user === false) return false;
+ if (!self::isLoggedIn())
+ return false;
return (self::$user['permissions'] & Permission::get($permission)) != 0;
}
public static function load()
{
- if (self::isLoggedIn()) {
+ if (self::isLoggedIn())
return true;
- }
if (Session::load()) {
$uid = Session::get('uid');
- if ($uid === false || $uid < 1) self::logout();
+ if ($uid === false || $uid < 1)
+ self::logout();
self::$user = Database::queryFirst('SELECT * FROM user WHERE userid = :uid LIMIT 1', array(':uid' => $uid));
- if (self::$user === false) self::logout();
+ if (self::$user === false)
+ self::logout();
return true;
}
return false;
@@ -41,8 +45,10 @@ class User
public static function login($user, $pass)
{
$ret = Database::queryFirst('SELECT userid, passwd FROM user WHERE login = :user LIMIT 1', array(':user' => $user));
- if ($ret === false) return false;
- if (!Crypto::verify($pass, $ret['passwd'])) return false;
+ if ($ret === false)
+ return false;
+ if (!Crypto::verify($pass, $ret['passwd']))
+ return false;
Session::create();
Session::set('uid', $ret['userid']);
Session::set('token', md5(rand() . time() . rand() . $_SERVER['REMOTE_ADDR'] . rand() . $_SERVER['REMOTE_PORT'] . rand() . $_SERVER['HTTP_USER_AGENT']));
@@ -57,5 +63,22 @@ class User
exit(0);
}
-}
+ public static function setLastSeenEvent($eventid)
+ {
+ if (!self::isLoggedIn())
+ return;
+ Database::exec("UPDATE user SET lasteventid = :eventid WHERE userid = :userid LIMIT 1", array(
+ 'eventid' => $eventid,
+ 'userid' => self::$user['userid']
+ ));
+ self::$user['lasteventid'] = $eventid;
+ }
+ public static function getLastSeenEvent()
+ {
+ if (!self::isLoggedIn())
+ return false;
+ return self::$user['lasteventid'];
+ }
+
+}
diff --git a/inc/validator.inc.php b/inc/validator.inc.php
index 88be14f2..944ac2ef 100644
--- a/inc/validator.inc.php
+++ b/inc/validator.inc.php
@@ -12,18 +12,20 @@ class Validator
public static function validate($condition, $value)
{
- if (empty($condition)) return $value;
+ if (empty($condition))
+ return $value;
$data = explode(':', $condition, 2);
switch ($data[0]) {
- case 'regex':
- if (preg_match($data[1], $value)) return $value;
- return false;
- case 'list':
- return self::validateList($data[1], $value);
- case 'function':
- return self::$data[1]($value);
- default:
- Util::traceError('Unknown validation method: ' . $data[0]);
+ case 'regex':
+ if (preg_match($data[1], $value))
+ return $value;
+ return false;
+ case 'list':
+ return self::validateList($data[1], $value);
+ case 'function':
+ return self::$data[1]($value);
+ default:
+ Util::traceError('Unknown validation method: ' . $data[0]);
}
}
@@ -36,11 +38,29 @@ class Validator
*/
private static function linuxPassword($value)
{
- if (empty($value)) return '';
- if (preg_match('/^\$6\$.+\$./', $value)) return $value;
+ if (empty($value))
+ return '';
+ if (preg_match('/^\$6\$.+\$./', $value))
+ return $value;
return Crypto::hash6($value);
}
-
+
+ /**
+ * "Fix" network share path for SMB shares where a backslash
+ * is used instead of a slash.
+ * @param string $value network path
+ * @return string cleaned up path
+ */
+ private static function networkShare($value)
+ {
+ $value = trim($value);
+ if (substr($value, 0, 2) === '\\\\')
+ $value = str_replace('\\', '/', $value);
+ if (substr($value, 0, 2) === '//')
+ $value = str_replace(' ', '\\040', $value);
+ return $value;
+ }
+
/**
* Validate value against list.
* @param string $list The list as a string of items, separated by "|"
@@ -50,9 +70,9 @@ class Validator
private static function validateList($list, $value)
{
$list = explode('|', $list);
- if (in_array($value, $list)) return $value;
+ if (in_array($value, $list))
+ return $value;
return false;
}
}
-