summaryrefslogtreecommitdiffstats
path: root/modules-available
diff options
context:
space:
mode:
authorJannik Schönartz2017-12-28 15:55:49 +0100
committerJannik Schönartz2017-12-28 15:55:49 +0100
commit086c7458fe2c59dbb907755648362917c615404e (patch)
treea0ddf550223e628e70bcf9fe33096c1f000d2742 /modules-available
parent[usb-lock-off] Switched to the _hw db structure. Adding a device and db contr... (diff)
parent[sysconfig] Restore long lost ajax functionality (diff)
downloadslx-admin-086c7458fe2c59dbb907755648362917c615404e.tar.gz
slx-admin-086c7458fe2c59dbb907755648362917c615404e.tar.xz
slx-admin-086c7458fe2c59dbb907755648362917c615404e.zip
Merge branch 'origin/master' into usb-lock-off
Diffstat (limited to 'modules-available')
-rw-r--r--modules-available/backup/lang/de/permissions.json4
-rw-r--r--modules-available/backup/lang/en/permissions.json4
-rw-r--r--modules-available/backup/page.inc.php44
-rw-r--r--modules-available/backup/permissions/permissions.json4
-rw-r--r--modules-available/backup/style.css7
-rw-r--r--modules-available/backup/templates/_page.html4
-rw-r--r--modules-available/backup/templates/restore.html3
-rw-r--r--modules-available/baseconfig/inc/baseconfigutil.inc.php12
-rw-r--r--modules-available/baseconfig/inc/validator.inc.php2
-rw-r--r--modules-available/baseconfig/page.inc.php5
-rw-r--r--modules-available/baseconfig/templates/_page.html2
-rw-r--r--modules-available/baseconfig_bwidm/hooks/translation.inc.php8
-rw-r--r--modules-available/baseconfig_bwlp/baseconfig/settings.json6
-rw-r--r--modules-available/baseconfig_bwlp/hooks/translation.inc.php8
-rw-r--r--modules-available/baseconfig_bwlp/lang/de/config-variable-categories.json1
-rw-r--r--modules-available/baseconfig_bwlp/lang/de/config-variables.json1
-rw-r--r--modules-available/baseconfig_bwlp/lang/en/config-variables.json3
-rw-r--r--modules-available/dnbd3/page.inc.php2
-rw-r--r--modules-available/dnbd3/templates/page-server-locations.html9
-rw-r--r--modules-available/dozmod/inc/pagedozmodlog.inc.php15
-rw-r--r--modules-available/dozmod/inc/pagedozmodusers.inc.php5
-rw-r--r--modules-available/dozmod/inc/pagemailtemplates.inc.php14
-rw-r--r--modules-available/dozmod/lang/de/permissions.json14
-rw-r--r--modules-available/dozmod/lang/en/permissions.json14
-rw-r--r--modules-available/dozmod/page.inc.php18
-rw-r--r--modules-available/dozmod/permissions/permissions.json26
-rw-r--r--modules-available/dozmod/templates/actionlog-log.html4
-rw-r--r--modules-available/dozmod/templates/images-delete.html2
-rw-r--r--modules-available/dozmod/templates/mailconfig.html4
-rw-r--r--modules-available/dozmod/templates/orglist.html15
-rw-r--r--modules-available/dozmod/templates/runtimeconfig.html2
-rw-r--r--modules-available/dozmod/templates/templates.html4
-rw-r--r--modules-available/dozmod/templates/userlist.html1
-rw-r--r--modules-available/exams/page.inc.php6
-rw-r--r--modules-available/exams/templates/page-exams-vis.html1
-rw-r--r--modules-available/internetaccess/lang/de/permissions.json3
-rw-r--r--modules-available/internetaccess/lang/en/permissions.json3
-rw-r--r--modules-available/internetaccess/permissions/permissions.json6
-rw-r--r--modules-available/locationinfo/api.inc.php26
-rw-r--r--modules-available/locationinfo/frontend/frontendscript.js2
-rw-r--r--modules-available/locationinfo/inc/coursebackend/coursebackend_dummy.inc.php2
-rw-r--r--modules-available/locationinfo/inc/infopanel.inc.php3
-rw-r--r--modules-available/locationinfo/inc/locationinfo.inc.php2
-rw-r--r--modules-available/locationinfo/lang/de/template-tags.json5
-rw-r--r--modules-available/locationinfo/lang/en/template-tags.json3
-rw-r--r--modules-available/locationinfo/page.inc.php81
-rwxr-xr-xmodules-available/locationinfo/templates/frontend-default.html1
-rw-r--r--modules-available/locationinfo/templates/frontend-summary.html32
-rw-r--r--modules-available/locationinfo/templates/page-locations.html6
-rw-r--r--modules-available/locationinfo/templates/page-panels.html14
-rw-r--r--modules-available/locations/lang/de/permissions.json9
-rw-r--r--modules-available/locations/lang/en/permissions.json9
-rw-r--r--modules-available/locations/permissions/permissions.json18
-rw-r--r--modules-available/main/hooks/translation.inc.php3
-rw-r--r--modules-available/news/lang/de/permissions.json6
-rw-r--r--modules-available/news/lang/en/permissions.json6
-rw-r--r--modules-available/news/page.inc.php38
-rw-r--r--modules-available/news/permissions/permissions.json12
-rw-r--r--modules-available/permissionmanager/clientscript.js6
-rw-r--r--modules-available/permissionmanager/inc/permissionutil.inc.php8
-rw-r--r--modules-available/permissionmanager/style.css9
-rw-r--r--modules-available/permissionmanager/templates/roleeditor.html2
-rw-r--r--modules-available/permissionmanager/templates/rolestable.html4
-rw-r--r--modules-available/permissionmanager/templates/userstable.html9
-rw-r--r--modules-available/rebootcontrol/inc/rebootqueries.inc.php1
-rw-r--r--modules-available/rebootcontrol/page.inc.php1
-rw-r--r--modules-available/roomplanner/clientscript.js14
-rw-r--r--modules-available/roomplanner/inc/pvsgenerator.inc.php1
-rw-r--r--modules-available/roomplanner/js/lib/jquery-collision.js27
-rw-r--r--modules-available/serversetup-bwlp/inc/ipxe.inc.php102
-rw-r--r--modules-available/statistics/api.inc.php36
-rw-r--r--modules-available/statistics/inc/parser.inc.php3
-rw-r--r--modules-available/statistics/page.inc.php120
-rw-r--r--modules-available/statistics/pages/projectors.inc.php58
-rw-r--r--modules-available/statistics/templates/filterbox.html7
-rw-r--r--modules-available/statistics/templates/machine-main.html4
-rw-r--r--modules-available/statistics/templates/page-replace.html104
-rw-r--r--modules-available/statistics/templates/projector-list.html2
-rw-r--r--modules-available/statistics_reporting/inc/queries.inc.php4
-rw-r--r--modules-available/statistics_reporting/inc/remotereport.inc.php2
-rw-r--r--modules-available/statistics_reporting/lang/de/permissions.json10
-rw-r--r--modules-available/statistics_reporting/lang/en/permissions.json10
-rw-r--r--modules-available/statistics_reporting/page.inc.php12
-rw-r--r--modules-available/statistics_reporting/permissions/permissions.json20
-rw-r--r--modules-available/sysconfig/addconfig.inc.php4
-rw-r--r--modules-available/sysconfig/addmodule.inc.php3
-rw-r--r--modules-available/sysconfig/addmodule_adauth.inc.php92
-rw-r--r--modules-available/sysconfig/addmodule_branding.inc.php6
-rw-r--r--modules-available/sysconfig/addmodule_ldapauth.inc.php23
-rw-r--r--modules-available/sysconfig/clientscript.js2
-rw-r--r--modules-available/sysconfig/inc/configmodule.inc.php12
-rw-r--r--modules-available/sysconfig/inc/configmodulebaseldap.inc.php11
-rw-r--r--modules-available/sysconfig/inc/configtgz.inc.php10
-rw-r--r--modules-available/sysconfig/inc/ldap.inc.php6
-rw-r--r--modules-available/sysconfig/inc/ppd.inc.php5
-rw-r--r--modules-available/sysconfig/page.inc.php36
-rw-r--r--modules-available/sysconfig/templates/ad-selfsearch.html2
-rw-r--r--modules-available/sysconfignew/page.inc.php1
-rw-r--r--modules-available/systemstatus/lang/de/template-tags.json2
-rw-r--r--modules-available/systemstatus/lang/en/template-tags.json2
-rw-r--r--modules-available/systemstatus/page.inc.php7
-rw-r--r--modules-available/systemstatus/templates/_page.html8
-rw-r--r--modules-available/translation/page.inc.php37
-rw-r--r--modules-available/vmstore/lang/de/template-tags.json14
-rw-r--r--modules-available/vmstore/lang/en/template-tags.json8
-rw-r--r--modules-available/vmstore/templates/page-vmstore.html38
-rw-r--r--modules-available/webinterface/lang/de/permissions.json5
-rw-r--r--modules-available/webinterface/lang/en/permissions.json5
-rw-r--r--modules-available/webinterface/page.inc.php11
-rw-r--r--modules-available/webinterface/permissions/permissions.json5
-rw-r--r--modules-available/webinterface/style.css7
-rw-r--r--modules-available/webinterface/templates/customization.html2
-rw-r--r--modules-available/webinterface/templates/https.html2
-rw-r--r--modules-available/webinterface/templates/passwords.html2
114 files changed, 1041 insertions, 467 deletions
diff --git a/modules-available/backup/lang/de/permissions.json b/modules-available/backup/lang/de/permissions.json
new file mode 100644
index 00000000..e5f189b8
--- /dev/null
+++ b/modules-available/backup/lang/de/permissions.json
@@ -0,0 +1,4 @@
+{
+ "create": "Eine Sicherung erstellen und herunterladen.",
+ "restore": "Eine Sicherung hochladen und wiederherstellen."
+} \ No newline at end of file
diff --git a/modules-available/backup/lang/en/permissions.json b/modules-available/backup/lang/en/permissions.json
new file mode 100644
index 00000000..ee1d87cb
--- /dev/null
+++ b/modules-available/backup/lang/en/permissions.json
@@ -0,0 +1,4 @@
+{
+ "create": "Create and download a backup.",
+ "restore": "Upload and restore a backup."
+} \ No newline at end of file
diff --git a/modules-available/backup/page.inc.php b/modules-available/backup/page.inc.php
index 77d677c7..949cd7f3 100644
--- a/modules-available/backup/page.inc.php
+++ b/modules-available/backup/page.inc.php
@@ -11,21 +11,21 @@ class Page_Backup extends Page
protected function doPreprocess()
{
User::load();
- if (!User::hasPermission('superadmin')) {
+ if (!User::isLoggedIn()) {
Message::addError('main.no-permission');
Util::redirect('?do=Main');
}
$this->action = Request::post('action');
- if ($this->action === 'backup') {
+ if ($this->action === 'backup' && User::hasPermission("create")) {
$this->backup();
- } elseif ($this->action === 'restore') {
+ } elseif ($this->action === 'restore' && User::hasPermission("restore")) {
$this->restore();
}
}
protected function doRender()
{
- if ($this->action === 'restore') {
+ if ($this->action === 'restore' && User::hasPermission("restore")) {
Render::addTemplate('restore', $this->templateData);
} else {
$lastBackup = (int)Property::get(self::LAST_BACKUP_PROP, 0);
@@ -34,7 +34,9 @@ class Page_Backup extends Page
} else {
$lastBackup = date('d.m.Y', $lastBackup);
}
- Render::addTemplate('_page', ['last_backup' => $lastBackup]);
+ Render::addTemplate('_page', ['last_backup' => $lastBackup,
+ "createAllowed" => User::hasPermission("create"),
+ "restoreAllowed" => User::hasPermission("restore")]);
}
}
@@ -137,35 +139,5 @@ class Page_Backup extends Page
if (isset($task['id']))
$this->templateData['rebootid'] = $task['id'];
}
- private function stopDaemons($parent)
- {
- $task = Taskmanager::submit('SyncdaemonLauncher', array(
- 'operation' => 'stop',
- 'parentTask' => $parent,
- 'failOnParentFail' => false
- ));
- if (isset($task['id'])) {
- $this->templateData['syncid'] = $task['id'];
- $parent = $task['id'];
- }
- $task = Taskmanager::submit('DozmodLauncher', array(
- 'operation' => 'stop',
- 'parentTask' => $parent,
- 'failOnParentFail' => false
- ));
- if (isset($task['id'])) {
- $this->templateData['dmsdid'] = $task['id'];
- $parent = $task['id'];
- }
- $task = Taskmanager::submit('LdadpLauncher', array(
- 'ids' => array(),
- 'parentTask' => $parent,
- 'failOnParentFail' => false
- ));
- if (isset($task['id'])) {
- $this->templateData['ldadpid'] = $task['id'];
- $parent = $task['id'];
- }
- return $parent;
- }
+
}
diff --git a/modules-available/backup/permissions/permissions.json b/modules-available/backup/permissions/permissions.json
new file mode 100644
index 00000000..feeffe33
--- /dev/null
+++ b/modules-available/backup/permissions/permissions.json
@@ -0,0 +1,4 @@
+[
+ "create",
+ "restore"
+] \ No newline at end of file
diff --git a/modules-available/backup/style.css b/modules-available/backup/style.css
new file mode 100644
index 00000000..7b86af56
--- /dev/null
+++ b/modules-available/backup/style.css
@@ -0,0 +1,7 @@
+.disabledPanel {
+ cursor: not-allowed;
+}
+.disabledPanel > .panel-body {
+ pointer-events: none;
+ opacity: 0.8;
+}
diff --git a/modules-available/backup/templates/_page.html b/modules-available/backup/templates/_page.html
index 88815897..41e73091 100644
--- a/modules-available/backup/templates/_page.html
+++ b/modules-available/backup/templates/_page.html
@@ -3,7 +3,7 @@
<form action="?do=Backup" method="post">
<input type="hidden" name="token" value="{{token}}">
<input type="hidden" name="action" value="backup">
- <div class="panel panel-default">
+ <div class="panel panel-default {{^createAllowed}}disabledPanel{{/createAllowed}}">
<div class="panel-heading">{{lang_backup}}</div>
<div class="panel-body">
<p>{{lang_backupDescription}}</p>
@@ -20,7 +20,7 @@
<form action="?do=Backup" method="post" enctype="multipart/form-data">
<input type="hidden" name="token" value="{{token}}">
<input type="hidden" name="action" value="restore">
- <div class="panel panel-default">
+ <div class="panel panel-default {{^restoreAllowed}}disabledPanel{{/restoreAllowed}}">
<div class="panel-heading">{{lang_restore}}</div>
<div class="panel-body">
<p>{{lang_restoreDescription}}</p>
diff --git a/modules-available/backup/templates/restore.html b/modules-available/backup/templates/restore.html
index 4494a993..5de7d1cc 100644
--- a/modules-available/backup/templates/restore.html
+++ b/modules-available/backup/templates/restore.html
@@ -2,8 +2,8 @@
<div class="panel-heading">{{lang_backup}}</div>
<div class="panel-body">
<div id="zeug">
- <div data-tm-id="{{syncid}}" data-tm-log="messages">{{lang_stopping}} syncdaemon</div>
<div data-tm-id="{{dmsdid}}" data-tm-log="messages">{{lang_stopping}} dmsd</div>
+ <div data-tm-id="{{dnbd3id}}" data-tm-log="messages">{{lang_stopping}} DNBD3</div>
<div data-tm-id="{{ldadpid}}" data-tm-log="messages">{{lang_stopping}} ldadp</div>
<div data-tm-id="{{mountid}}" data-tm-log="messages">{{lang_stopping}} vmstore</div>
<div data-tm-id="{{restoreid}}" data-tm-log="messages" data-tm-callback="restoreCb">{{lang_restoreConfig}}</div>
@@ -19,6 +19,7 @@
</div>
<script type="text/javascript">
+ var slxDotInterval = false;
function restoreCb(task)
{
if (!task || !task.statusCode)
diff --git a/modules-available/baseconfig/inc/baseconfigutil.inc.php b/modules-available/baseconfig/inc/baseconfigutil.inc.php
index 3039ea12..a48eb93b 100644
--- a/modules-available/baseconfig/inc/baseconfigutil.inc.php
+++ b/modules-available/baseconfig/inc/baseconfigutil.inc.php
@@ -37,12 +37,18 @@ class BaseConfigUtil
return $settings;
}
+ /**
+ * Get configuration categories for given module, or all modules if false is passed.
+ *
+ * @param \Module $module
+ * @return array
+ */
public static function getCategories($module = false)
{
$categories = array();
if ($module === false) {
$module = '*';
- } else {
+ } elseif (is_object($module)) {
$module = $module->getIdentifier();
}
foreach (glob("modules/{$module}/baseconfig/categories.json", GLOB_NOSORT) as $file) {
@@ -61,8 +67,8 @@ class BaseConfigUtil
/**
* Mark variables that would be shadowed according to the given values.
*
- * @param $vars list of vars as obtained from BaseConfigUtil::getVariables()
- * @param $values key-value-pairs of variable assignments to work with
+ * @param array $vars list of vars as obtained from BaseConfigUtil::getVariables()
+ * @param array $values key-value-pairs of variable assignments to work with
*/
public static function markShadowedVars(&$vars, $values) {
foreach ($vars as $key => &$var) {
diff --git a/modules-available/baseconfig/inc/validator.inc.php b/modules-available/baseconfig/inc/validator.inc.php
index d65b592c..2dfeed7c 100644
--- a/modules-available/baseconfig/inc/validator.inc.php
+++ b/modules-available/baseconfig/inc/validator.inc.php
@@ -99,7 +99,7 @@ class Validator
return $displayValue;
}
- private static function validateMultiInput(&$list, &$displayValue)
+ private static function validateMultiInput($list, &$displayValue)
{
return $displayValue;
}
diff --git a/modules-available/baseconfig/page.inc.php b/modules-available/baseconfig/page.inc.php
index 366a1238..426d3fdd 100644
--- a/modules-available/baseconfig/page.inc.php
+++ b/modules-available/baseconfig/page.inc.php
@@ -30,11 +30,14 @@ class Page_BaseConfig extends Page
$qry_values = ', :enabled';
$qry_update = ', enabled = :enabled';
$params = array();
+ $delExtra = '';
} elseif (empty($this->qry_extra['field'])) {
// Module specific, but module doesn't have an extra field
$qry_insert = '';
$qry_values = '';
$qry_update = '';
+ $params = array();
+ $delExtra = '';
} else {
// Module with extra field
$qry_insert = ', ' . $this->qry_extra['field'];
@@ -290,7 +293,7 @@ class Page_BaseConfig extends Page
/**
* Create html snippet for setting, based on given validator
- * @param type $validator
+ * @param string $validator
* @return boolean
*/
private function makeInput($validator, $setting, $current, $shadows)
diff --git a/modules-available/baseconfig/templates/_page.html b/modules-available/baseconfig/templates/_page.html
index f2dfd17b..89caf9f2 100644
--- a/modules-available/baseconfig/templates/_page.html
+++ b/modules-available/baseconfig/templates/_page.html
@@ -127,7 +127,7 @@ document.addEventListener("DOMContentLoaded", function () {
});
/* data-shadowing bindings */
- $allShadowingFields = $('[data-shadows]');
+ var $allShadowingFields = $('[data-shadows]');
$allShadowingFields.on('change', function (event) { updateShadows(event.target); });
$allShadowingFields.each(function (idx, elem) { updateShadows(elem); });
});
diff --git a/modules-available/baseconfig_bwidm/hooks/translation.inc.php b/modules-available/baseconfig_bwidm/hooks/translation.inc.php
index 00898075..5ccafbc4 100644
--- a/modules-available/baseconfig_bwidm/hooks/translation.inc.php
+++ b/modules-available/baseconfig_bwidm/hooks/translation.inc.php
@@ -15,7 +15,9 @@ $HANDLER['subsections'] = array(
*/
/**
- * Configuration categories
+ * Configuration categories.
+ * @param \Module $module
+ * @return array
*/
$HANDLER['grep_config-variable-categories'] = function($module) {
if (!$module->activate())
@@ -28,7 +30,9 @@ $HANDLER['grep_config-variable-categories'] = function($module) {
};
/**
- * Configuration variables
+ * Configuration variables.
+ * @param \Module $module
+ * @return array
*/
$HANDLER['grep_config-variables'] = function($module) {
if (!$module->activate())
diff --git a/modules-available/baseconfig_bwlp/baseconfig/settings.json b/modules-available/baseconfig_bwlp/baseconfig/settings.json
index 18e87ab6..0d4db4d4 100644
--- a/modules-available/baseconfig_bwlp/baseconfig/settings.json
+++ b/modules-available/baseconfig_bwlp/baseconfig/settings.json
@@ -79,6 +79,12 @@
"permissions": "2",
"validator": "list:no|yes"
},
+ "SLX_JUMBO_FRAMES": {
+ "catid": "networking",
+ "defaultvalue": "no",
+ "permissions": "2",
+ "validator": "list:no|yes"
+ },
"SLX_REMOTE_LOG_SESSIONS": {
"catid": "other",
"defaultvalue": "anonymous",
diff --git a/modules-available/baseconfig_bwlp/hooks/translation.inc.php b/modules-available/baseconfig_bwlp/hooks/translation.inc.php
index 00898075..5ccafbc4 100644
--- a/modules-available/baseconfig_bwlp/hooks/translation.inc.php
+++ b/modules-available/baseconfig_bwlp/hooks/translation.inc.php
@@ -15,7 +15,9 @@ $HANDLER['subsections'] = array(
*/
/**
- * Configuration categories
+ * Configuration categories.
+ * @param \Module $module
+ * @return array
*/
$HANDLER['grep_config-variable-categories'] = function($module) {
if (!$module->activate())
@@ -28,7 +30,9 @@ $HANDLER['grep_config-variable-categories'] = function($module) {
};
/**
- * Configuration variables
+ * Configuration variables.
+ * @param \Module $module
+ * @return array
*/
$HANDLER['grep_config-variables'] = function($module) {
if (!$module->activate())
diff --git a/modules-available/baseconfig_bwlp/lang/de/config-variable-categories.json b/modules-available/baseconfig_bwlp/lang/de/config-variable-categories.json
index d8d7e91f..a08a8c12 100644
--- a/modules-available/baseconfig_bwlp/lang/de/config-variable-categories.json
+++ b/modules-available/baseconfig_bwlp/lang/de/config-variable-categories.json
@@ -1,5 +1,4 @@
{
- "cat_5": "Gemeinsames Netzlaufwerk",
"networking": "Netzwerk-\/Internetzugriff",
"other": "Unkategorisiert",
"power": "Inaktivit\u00e4t und Abschaltung",
diff --git a/modules-available/baseconfig_bwlp/lang/de/config-variables.json b/modules-available/baseconfig_bwlp/lang/de/config-variables.json
index a1ef4bab..ad2abc8d 100644
--- a/modules-available/baseconfig_bwlp/lang/de/config-variables.json
+++ b/modules-available/baseconfig_bwlp/lang/de/config-variables.json
@@ -5,6 +5,7 @@
"SLX_BIOS_CLOCK": "Legt fest, ob und wie die interne Uhr des Rechners im Bezug auf die Systemzeit des \/MiniLinux\/ gesetzt werden soll.\r\n*off* = Die interne Uhr des Rechners wird nicht ver\u00e4ndert.\r\n*local* = Die interne Uhr wird auf die Lokalzeit gesetzt. Bevorzugt wenn z.B. noch eine native Windows-Installation auf dem PC vorhanden ist.\r\n*utc* = Die interne Uhr wird auf die \/Koordinierte Weltzeit\/ gesetzt. Dies ist die g\u00e4ngige Einstellung in einem reinen Linux-Umfeld.",
"SLX_BRIDGE_OTHER_NICS": "Sofern ein Client mehrere Netzwerkkarten besitzt, k\u00f6nnen Sie mittels dieser Option alle weiteren gefundenen Karten in die VM durchreichen.",
"SLX_DEMO_PASS": "Passwort f\u00fcr den eingebauten *demo*-Account. Leer lassen, um das Einloggen zu verbieten.\r\nDas Passwort wird wie das root-Passwort nur gehasht an den Client \u00fcbertragen.",
+ "SLX_JUMBO_FRAMES": "Setzt die MTU auf den Clients auf 9000, statt wie \u00fcblich 1500. Da dies mit alten\/schlechten Routern oder Switches zu Problemen f\u00fchren k\u00f6nnte, ist diese Option standardm\u00e4\u00dfig deaktiviert.",
"SLX_LOGOUT_TIMEOUT": "Zeit in Sekunden, die eine Benutzersitzung ohne Aktion sein darf, bevor sie beendet wird.Feld leer lassen, um die Funktion zu deaktivieren.",
"SLX_NET_DOMAIN": "DNS-Dom\u00e4ne, in die sich die Clients eingliedern, sofern der DHCP Server keine solche vorgibt.",
"SLX_NET_SEARCH": "Per Leerzeichen getrennte Liste von Suchdom\u00e4nen, die der Client verwenden soll, sofern der DHCP-Server keine Vorgabe macht.",
diff --git a/modules-available/baseconfig_bwlp/lang/en/config-variables.json b/modules-available/baseconfig_bwlp/lang/en/config-variables.json
index 3e33cbef..c56f171d 100644
--- a/modules-available/baseconfig_bwlp/lang/en/config-variables.json
+++ b/modules-available/baseconfig_bwlp/lang/en/config-variables.json
@@ -5,6 +5,7 @@
"SLX_BIOS_CLOCK": "Specifies whether and how the internal clock of the computer should be set in relation to the system time of the \/MiniLinux\/.\r\n*off* = The internal clock of the computer is not changed.\r\n*local* = The internal clock is set to local time. Preferably if, for example, there is still a native Windows installation available on the PC.\r\n*utc* = The internal clock is set to the \/Coordinated Universal Time\/. This is the most common setup in a pure Linux environment.",
"SLX_BRIDGE_OTHER_NICS": "If enabled, additional network cards installed in the Client will be bridged to the VM. ",
"SLX_DEMO_PASS": "Password for the *demo* account. Leave empty to disallow logging in as the demo user.\r\nLike the root password, the demo user's password will be sent to the client in its hashed form.",
+ "SLX_JUMBO_FRAMES": "Increases the MTU on the clients from 1500 to 9000. As this can lead to issues with old\/bad routers and switches, this option is disabled by default.",
"SLX_LOGOUT_TIMEOUT": "Time in seconds, in which a user session may remain without action before it is terminated.Leave field blank to disable the function.",
"SLX_NET_DOMAIN": "DNS domain in which the client integrate, provided the DHCP server does not specifies such.",
"SLX_NET_SEARCH": "Space separated list of DNS search domains to use in case the DHCP server doesn't supply any.",
@@ -29,4 +30,4 @@
"SLX_VMCHOOSER_TEMPLATES": "Defines how lectures that link to template VMs are treated wrt sorting.\r\n*IGNORE*: Sort among regular lectures\r\n*BUMP*: Move to top of list",
"SLX_VMCHOOSER_TIMEOUT": "Timeout in seconds after which the session will be closed if the user doesn't make any selection in vmChooser. Mouse or keyboard activity resets this timeout.",
"SLX_WAKEUP_SCHEDULE": "Fixed time to turn on the computer. At the moment this feature takes effect on every day - also at the weekend. Several times can be specified, separated by spaces.\r\n\r\nNote that some hardware might not properly support wakeup. It's recommended to only enable this feature for rooms where it's known that the hardware supports it."
-}
+} \ No newline at end of file
diff --git a/modules-available/dnbd3/page.inc.php b/modules-available/dnbd3/page.inc.php
index 39500f83..1fa38805 100644
--- a/modules-available/dnbd3/page.inc.php
+++ b/modules-available/dnbd3/page.inc.php
@@ -230,7 +230,7 @@ class Page_Dnbd3 extends Page
$stats['bytesReceived_s'] = Util::readableFileSize($stats['bytesReceived']);
$stats['uptime_s'] = floor($stats['uptime'] / 86400) . 'd ' . gmdate('H:i:s', $stats['uptime']);
Render::addTemplate('page-proxy-stats', $stats);
- $images = Dnbd3Rpc::query($server['ip'], 5003,false, false, true);
+ // TODO $images = Dnbd3Rpc::query($server['ip'], 5003,false, false, true);
$confAlts = Dnbd3Rpc::query($server['ip'], 5003,false, false, false, false, true, true);
$ips = array();
$sort = array();
diff --git a/modules-available/dnbd3/templates/page-server-locations.html b/modules-available/dnbd3/templates/page-server-locations.html
index 7d7ddaf1..9ab0e973 100644
--- a/modules-available/dnbd3/templates/page-server-locations.html
+++ b/modules-available/dnbd3/templates/page-server-locations.html
@@ -6,13 +6,6 @@
<input type="hidden" name="token" value="{{token}}">
<input type="hidden" name="server" value="{{serverid}}">
- <div class="buttonbar text-right">
- <button type="submit" class="btn btn-primary" name="action" value="savelocations">
- <span class="glyphicon glyphicon-floppy-disk"></span>
- {{lang_save}}
- </button>
- </div>
-
<div class="row">
<div class="col-md-6">
<h3>{{lang_allowedSubnets}}</h3>
@@ -93,4 +86,4 @@ document.addEventListener('DOMContentLoaded', function() {
$('.loc-check').change(updateLocations);
updateLocations();
});
-//--></script> \ No newline at end of file
+//--></script>
diff --git a/modules-available/dozmod/inc/pagedozmodlog.inc.php b/modules-available/dozmod/inc/pagedozmodlog.inc.php
index f31edf5b..80441cd1 100644
--- a/modules-available/dozmod/inc/pagedozmodlog.inc.php
+++ b/modules-available/dozmod/inc/pagedozmodlog.inc.php
@@ -29,9 +29,13 @@ class Page_dozmod_log extends Page
. " LEFT JOIN sat.lecture l ON (l.lectureid = targetid)"
. " ORDER BY al.dateline DESC LIMIT 500", array(), true, true);
} elseif ($this->action === 'showuser') {
- $this->listUser();
+ if (User::hasPermission("log.showuser")) {
+ $this->listUser();
+ }
} else {
- $this->listTarget();
+ if (User::hasPermission("log.showtarget")) {
+ $this->listTarget();
+ }
}
}
@@ -44,7 +48,7 @@ class Page_dozmod_log extends Page
. ' WHERE userid = :uuid'
. ' LIMIT 1', array('uuid' => $this->uuid));
if ($user === false) {
- Message:addError('unknown-userid', $this->uuid);
+ Message::addError('unknown-userid', $this->uuid);
Util::redirect('?do=dozmod&section=actionlog');
}
// Mangle date and render
@@ -66,7 +70,7 @@ class Page_dozmod_log extends Page
// We have to guess what kind of target it is
if (!$this->addImageHeader()
&& !$this->addLectureHeader()) {
- Message:addError('unknown-targetid', $this->uuid);
+ Message::addError('unknown-targetid', $this->uuid);
// Keep going, there might still be log entries for a deleted uuid
}
@@ -150,6 +154,9 @@ class Page_dozmod_log extends Page
if ($showTarget) {
$data['showTarget'] = true;
}
+
+ $data['allowedShowUser'] = User::hasPermission("log.showuser");
+ $data['allowedShowTarget'] = User::hasPermission("log.showtarget");
Render::addTemplate('actionlog-log', $data);
}
diff --git a/modules-available/dozmod/inc/pagedozmodusers.inc.php b/modules-available/dozmod/inc/pagedozmodusers.inc.php
index 621f7d34..f4ac852b 100644
--- a/modules-available/dozmod/inc/pagedozmodusers.inc.php
+++ b/modules-available/dozmod/inc/pagedozmodusers.inc.php
@@ -22,15 +22,10 @@ class Page_dozmod_users extends Page
if ($action === 'setmail' || $action === 'setsu' || $action == 'setlogin') {
if (User::hasPermission("users.".$action)) {
$this->setUserOption($action);
- } else {
- die("No permission.");
}
-
} elseif ($action === 'setorglogin') {
if (User::hasPermission("users.orglogin")) {
$this->setOrgOption($action);
- } else {
- die("No permission.");
}
} else {
die('No such action');
diff --git a/modules-available/dozmod/inc/pagemailtemplates.inc.php b/modules-available/dozmod/inc/pagemailtemplates.inc.php
index 90734a50..ff47977f 100644
--- a/modules-available/dozmod/inc/pagemailtemplates.inc.php
+++ b/modules-available/dozmod/inc/pagemailtemplates.inc.php
@@ -15,16 +15,10 @@ class Page_mail_templates extends Page
} elseif ($action === 'save') {
if (User::hasPermission("templates.save")) {
$this->handleSave();
- } else {
- Message::addError('main.no-permission');
- Util::redirect('?do=dozmod&section=templates');
}
} elseif ($action === 'reset') {
if(User::hasPermission("templates.reset")) {
$this->handleReset();
- } else {
- Message::addError('main.no-permission');
- Util::redirect('?do=dozmod&section=templates');
}
} else {
Message::addError('main.invalid-action', $action);
@@ -65,12 +59,16 @@ class Page_mail_templates extends Page
$t['modified'] = !$t['original'];
$t['conflict'] = !$t['original'] && $t['edit_version'] < $t['version'];
}
-
}
+
protected function doRender()
{
$this->enrichHtml();
- Render::addTemplate('templates', ['templates' => $this->templates]);
+ Render::addTemplate('templates', [
+ 'templates' => $this->templates,
+ 'allowedReset' => User::hasPermission("templates.reset"),
+ 'allowedSave' => User::hasPermission("templates.save"),
+ ]);
}
private function forcmp($string)
diff --git a/modules-available/dozmod/lang/de/permissions.json b/modules-available/dozmod/lang/de/permissions.json
new file mode 100644
index 00000000..07158a1d
--- /dev/null
+++ b/modules-available/dozmod/lang/de/permissions.json
@@ -0,0 +1,14 @@
+{
+ "images.delete": "Zur Löschung vorgemerkete Abbilder löschen.",
+ "mail.save": "Änderungen an der SMTP-Konfiguration zum Versenden von Mails speichern.",
+ "mail.testmail": "Eine Test E-Mail verschicken.",
+ "runtimeconfig.save": "Änderungen an der Laufzeit-Konfiguration speichern.",
+ "templates.save": "E-Mail Templates speichern.",
+ "templates.reset": "E-Mail Templates zurücksetzen.",
+ "users.setmail": "E-Mail Benachrichtigungen für einzelne Benutzer aktivieren/deaktivieren.",
+ "users.setlogin": "Anmeldungen für einzelne Benutzer aktivieren/deaktivieren.",
+ "users.setsu": "Benutzer zu SuperUser ernennen.",
+ "users.orglogin": "Anmeldungen für Benutzer von bestimmten Einrichtungen aktivieren/deaktivieren.",
+ "log.showuser": "User Data im Aktions-Log anzeigen.",
+ "log.showtarget": "Target Data im Aktions-Log anzeigen."
+} \ No newline at end of file
diff --git a/modules-available/dozmod/lang/en/permissions.json b/modules-available/dozmod/lang/en/permissions.json
new file mode 100644
index 00000000..923a8461
--- /dev/null
+++ b/modules-available/dozmod/lang/en/permissions.json
@@ -0,0 +1,14 @@
+{
+ "images.delete": "Delete images marked for deletion.",
+ "mail.save": "Save SMTP configuration for sending mails.",
+ "mail.testmail": "Send a testmail.",
+ "runtimeconfig.save": "Save limits and defaults of a runtime configuration.",
+ "templates.save": "Save email templates.",
+ "templates.reset": "Reset email templates.",
+ "users.setmail": "Enable/Disable Email Notification.",
+ "users.setlogin": "Enable/Disable Login.",
+ "users.setsu": "Set User to superuser.",
+ "users.orglogin": "Enalbe/Disable Login for Users from certain organisations.",
+ "log.showuser": "Show User Data in Log.",
+ "log.showtarget": "Show Target Data in Log."
+} \ No newline at end of file
diff --git a/modules-available/dozmod/page.inc.php b/modules-available/dozmod/page.inc.php
index 93d38f48..b58d57aa 100644
--- a/modules-available/dozmod/page.inc.php
+++ b/modules-available/dozmod/page.inc.php
@@ -52,16 +52,10 @@ class Page_DozMod extends Page
if ($action === 'mail') {
if (User::hasPermission("mail.save")) {
$this->mailHandler();
- } else {
- Message::addError('main.no-permission');
- Util::redirect('?do=dozmod&section=mailconfig');
}
} elseif ($action === 'runtime') {
if (User::hasPermission("runtimeconfig.save")) {
$this->runtimeHandler();
- } else {
- Message::addError('main.no-permission');
- Util::redirect('?do=dozmod&section=runtimeconfig');
}
} elseif ($action === 'delimages') {
if (User::hasPermission("images.delete")) {
@@ -70,9 +64,6 @@ class Page_DozMod extends Page
Message::addInfo('delete-images', $result);
}
Util::redirect('?do=DozMod');
- } else {
- Message::addError('main.no-permission');
- Util::redirect('?do=dozmod');
}
} elseif ($action !== false) {
Util::traceError('Invalid action: ' . $action);
@@ -102,7 +93,7 @@ class Page_DozMod extends Page
if (empty($expiredImages)) {
Message::addSuccess('no-expired-images');
} else {
- Render::addTemplate('images-delete', array('images' => $expiredImages));
+ Render::addTemplate('images-delete', array('images' => $expiredImages, 'allowedDelete' => User::hasPermission("images.delete")));
}
}
if ($section === 'mailconfig') {
@@ -114,6 +105,8 @@ class Page_DozMod extends Page
$mailConf['set_' . $mailConf['ssl']] = 'selected="selected"';
}
}
+ $mailConf['allowedSave'] = User::hasPermission('mail.save');
+ $mailConf['allowedTest'] = User::hasPermission('mail.testmail');
Render::addTemplate('mailconfig', $mailConf);
}
if ($section === 'runtimeconfig') {
@@ -146,6 +139,7 @@ class Page_DozMod extends Page
$runtimeConf['allowLoginByDefault'] = 'checked';
}
}
+ $runtimeConf['allowedSave'] = User::hasPermission("runtimeconfig.save");
Render::addTemplate('runtimeconfig', $runtimeConf);
}
if ($section === 'blockstats') {
@@ -231,14 +225,10 @@ class Page_DozMod extends Page
if ($action === 'mail') {
if (User::hasPermission("mail.testmail")) {
$this->handleTestMail();
- } else {
- die('No permission');
}
} elseif ($action === 'delimages') {
if (User::hasPermission("images.delete")) {
die($this->handleDeleteImages());
- } else {
- die('No permission');
}
} elseif ($action === 'getblockinfo') {
$this->ajaxGetBlockInfo();
diff --git a/modules-available/dozmod/permissions/permissions.json b/modules-available/dozmod/permissions/permissions.json
index 8295d0f0..e8dfb558 100644
--- a/modules-available/dozmod/permissions/permissions.json
+++ b/modules-available/dozmod/permissions/permissions.json
@@ -1,12 +1,14 @@
-{
- "images.delete": "Delete images marked for deletion.",
- "mail.save": "Save SMTP configuration for sending mails.",
- "mail.testmail": "Send a testmail.",
- "runtimeconfig.save": "Save limits and defaults of a runtime configuration.",
- "templates.save": "Save email templates",
- "templates.reset": "Reset email templates",
- "users.setmail": "Enable/Disable Email Notification",
- "users.setlogin": "Enable/Disable Login",
- "users.setsu": "Set User to superuser",
- "users.orglogin": "Enalbe/Disable Login for Users from certain organisations."
-} \ No newline at end of file
+[
+ "images.delete",
+ "mail.save",
+ "mail.testmail",
+ "runtimeconfig.save",
+ "templates.save",
+ "templates.reset",
+ "users.setmail",
+ "users.setlogin",
+ "users.setsu",
+ "users.orglogin",
+ "log.showuser",
+ "log.showtarget"
+] \ No newline at end of file
diff --git a/modules-available/dozmod/templates/actionlog-log.html b/modules-available/dozmod/templates/actionlog-log.html
index 09f3a183..8aa57207 100644
--- a/modules-available/dozmod/templates/actionlog-log.html
+++ b/modules-available/dozmod/templates/actionlog-log.html
@@ -18,7 +18,7 @@
{{#showActor}}
<td style="min-width:140px">
{{#uuserid}}
- <a href="?do=dozmod&amp;section=actionlog&amp;action=showuser&amp;uuid={{uuserid}}">{{ulastname}}, {{ufirstname}}</a>
+ {{#allowedShowUser}}<a href="?do=dozmod&amp;section=actionlog&amp;action=showuser&amp;uuid={{uuserid}}">{{/allowedShowUser}} {{ulastname}}, {{ufirstname}}{{#allowedShowUser}}</a>{{/allowedShowUser}}
{{/uuserid}}
{{^uuserid}}
{{lang_system}}
@@ -28,7 +28,7 @@
{{#showTarget}}
<td style="word-wrap: break-word">
{{#targeturl}}
- <a href="{{targeturl}}">{{targetname}}</a>
+ {{#allowedShowTarget}}<a href="{{targeturl}}">{{/allowedShowTarget}}{{targetname}}{{#allowedShowTarget}}</a>{{/allowedShowTarget}}
{{/targeturl}}
{{^targeturl}}
{{targetname}}
diff --git a/modules-available/dozmod/templates/images-delete.html b/modules-available/dozmod/templates/images-delete.html
index dd4c61bc..ed75a0d2 100644
--- a/modules-available/dozmod/templates/images-delete.html
+++ b/modules-available/dozmod/templates/images-delete.html
@@ -45,7 +45,7 @@
{{/images}}
</tbody>
</table>
- <button style="margin-left: 20px" id="delbtn" class="btn btn-danger pull-right" type="submit" name="button" value="save"><span class="glyphicon glyphicon-trash"></span> {{lang_delButton}}</button>
+ <button {{^allowedDelete}}disabled{{/allowedDelete}} style="margin-left: 20px" id="delbtn" class="btn btn-danger pull-right" type="submit" name="button" value="save"><span class="glyphicon glyphicon-trash"></span> {{lang_delButton}}</button>
</form>
<pre style="display:none" id="deloutput"></pre>
</div>
diff --git a/modules-available/dozmod/templates/mailconfig.html b/modules-available/dozmod/templates/mailconfig.html
index 6edc65ae..d5d4db29 100644
--- a/modules-available/dozmod/templates/mailconfig.html
+++ b/modules-available/dozmod/templates/mailconfig.html
@@ -55,10 +55,10 @@
</div>
<br>
<div class="text-right">
- <button class="btn btn-warning" type="button" id="test-button" name="button" value="test" onclick="slxTestConfig()"><span class="glyphicon glyphicon-envelope"></span> {{lang_test}}</button>
+ <button {{^allowedTest}}disabled{{/allowedTest}} class="btn btn-warning" type="button" id="test-button" name="button" value="test" onclick="slxTestConfig()"><span class="glyphicon glyphicon-envelope"></span> {{lang_test}}</button>
<span id="test-spin" style="display:none"><span class="glyphicon glyphicon-refresh slx-rotation"></span></span>
<pre id="test-output" style="display:none"></pre>
- <button class="btn btn-primary" type="submit" name="button" value="save"><span class="glyphicon glyphicon-floppy-disk"></span> {{lang_save}}</button>
+ <button {{^allowedSave}}disabled{{/allowedSave}} class="btn btn-primary" type="submit" name="button" value="save"><span class="glyphicon glyphicon-floppy-disk"></span> {{lang_save}}</button>
<br>
<input type="hidden" name="token" value="{{token}}">
<input type="hidden" name="action" value="mail">
diff --git a/modules-available/dozmod/templates/orglist.html b/modules-available/dozmod/templates/orglist.html
index 361421c5..33db955a 100644
--- a/modules-available/dozmod/templates/orglist.html
+++ b/modules-available/dozmod/templates/orglist.html
@@ -33,6 +33,7 @@
function seto(action, el, orgid) {
var box = $(el);
+ var $notification;
box = box.parent();
var v = el.checked ? '1' : '0';
var old = el.checked == true;
@@ -41,7 +42,19 @@ function seto(action, el, orgid) {
if (data !== '1' && data !== '0') {
el.checked = !old;
- box.parent().css('background-color', 'red !important');
+ box.parent().css('background-color', '');
+ /* show success notification */
+ $notification = $('<span></span>')
+ .addClass('glyphicon glyphicon-remove')
+ .css('color', 'red')
+ .css('width', '0px')
+ .css('position', 'relative')
+ .css('right', '20px')
+ .hide();
+ box.before($notification);
+ $notification.fadeIn('fast', function () {
+ $notification.fadeOut('slow', function () { $notification.remove() });
+ });
} else {
el.checked = (data == 1);
box.parent().css('background-color', '');
diff --git a/modules-available/dozmod/templates/runtimeconfig.html b/modules-available/dozmod/templates/runtimeconfig.html
index a1992631..1d4cc6cb 100644
--- a/modules-available/dozmod/templates/runtimeconfig.html
+++ b/modules-available/dozmod/templates/runtimeconfig.html
@@ -117,7 +117,7 @@
<input type="hidden" name="token" value="{{token}}">
<input type="hidden" name="action" value="runtime">
<div class="text-right">
- <button class="btn btn-primary" type="submit" name="button" value="save"><span class="glyphicon glyphicon-floppy-disk"></span> {{lang_save}}</button>
+ <button {{^allowedSave}}disabled{{/allowedSave}} class="btn btn-primary" type="submit" name="button" value="save"><span class="glyphicon glyphicon-floppy-disk"></span> {{lang_save}}</button>
</div>
</form>
</div>
diff --git a/modules-available/dozmod/templates/templates.html b/modules-available/dozmod/templates/templates.html
index 4764c0e9..3ee0ccbc 100644
--- a/modules-available/dozmod/templates/templates.html
+++ b/modules-available/dozmod/templates/templates.html
@@ -80,12 +80,12 @@
{{/templates}}
</div>
- <button type="submit" onclick="return validateForm()" class="btn btn-primary pull-right"><span class="glyphicon glyphicon-floppy-disk"></span> {{lang_save}}</button>
+ <button {{^allowedSave}}disabled{{/allowedSave}} type="submit" onclick="return validateForm()" class="btn btn-primary pull-right"><span class="glyphicon glyphicon-floppy-disk"></span> {{lang_save}}</button>
</form>
<form method="POST" action="?do=dozmod&amp;section=templates">
<input type="hidden" name="token" value="{{token}}">
<div>
- <button type="button" data-toggle="modal" data-target="#resetTemplatesModal" class="btn btn-danger">{{lang_loadDefaults}}</button>
+ <button {{^allowedReset}}disabled{{/allowedReset}} type="button" data-toggle="modal" data-target="#resetTemplatesModal" class="btn btn-danger">{{lang_loadDefaults}}</button>
</div>
<div id="resetTemplatesModal" class="modal fade" role="dialog">
diff --git a/modules-available/dozmod/templates/userlist.html b/modules-available/dozmod/templates/userlist.html
index 378a2be1..b8080b44 100644
--- a/modules-available/dozmod/templates/userlist.html
+++ b/modules-available/dozmod/templates/userlist.html
@@ -56,6 +56,7 @@
function setu(action, el, uid) {
var box = $(el);
+ var $notification;
box = box.parent();
var v = el.checked ? '1' : '0';
var old = el.checked == true;
diff --git a/modules-available/exams/page.inc.php b/modules-available/exams/page.inc.php
index a6bd7e16..75fb6a0b 100644
--- a/modules-available/exams/page.inc.php
+++ b/modules-available/exams/page.inc.php
@@ -330,9 +330,9 @@ class Page_Exams extends Page
die('delete only works with a post request');
}
$examid = Request::post('examid');
- $res = Database::exec("DELETE FROM exams WHERE examid = :examid;", compact('examid'));
- $res = Database::exec("DELETE FROM exams_x_location WHERE examid = :examid;", compact('examid'));
- if ($res === false) {
+ $res1 = Database::exec("DELETE FROM exams WHERE examid = :examid;", compact('examid'));
+ $res2 = Database::exec("DELETE FROM exams_x_location WHERE examid = :examid;", compact('examid'));
+ if ($res1 === false || $res2 === false) {
Message::addError('exam-not-deleted-error');
} else {
Message::addInfo('exam-deleted-success');
diff --git a/modules-available/exams/templates/page-exams-vis.html b/modules-available/exams/templates/page-exams-vis.html
index caf4aea2..5c14c4a6 100644
--- a/modules-available/exams/templates/page-exams-vis.html
+++ b/modules-available/exams/templates/page-exams-vis.html
@@ -11,6 +11,7 @@
+<!--suppress JSDeprecatedSymbols -->
<script type="application/javascript"><!--
diff --git a/modules-available/internetaccess/lang/de/permissions.json b/modules-available/internetaccess/lang/de/permissions.json
new file mode 100644
index 00000000..78d9e67c
--- /dev/null
+++ b/modules-available/internetaccess/lang/de/permissions.json
@@ -0,0 +1,3 @@
+{
+ "configuration.safe": "Konfiguration speichern."
+} \ No newline at end of file
diff --git a/modules-available/internetaccess/lang/en/permissions.json b/modules-available/internetaccess/lang/en/permissions.json
new file mode 100644
index 00000000..afe8325d
--- /dev/null
+++ b/modules-available/internetaccess/lang/en/permissions.json
@@ -0,0 +1,3 @@
+{
+ "configuration.safe": "Safe configuration."
+} \ No newline at end of file
diff --git a/modules-available/internetaccess/permissions/permissions.json b/modules-available/internetaccess/permissions/permissions.json
index 6d88ccc5..67998da7 100644
--- a/modules-available/internetaccess/permissions/permissions.json
+++ b/modules-available/internetaccess/permissions/permissions.json
@@ -1,3 +1,3 @@
-{
- "configuration.safe": "Safe new configuration."
-} \ No newline at end of file
+[
+ "configuration.safe"
+] \ No newline at end of file
diff --git a/modules-available/locationinfo/api.inc.php b/modules-available/locationinfo/api.inc.php
index ceaf04c0..ad71de8b 100644
--- a/modules-available/locationinfo/api.inc.php
+++ b/modules-available/locationinfo/api.inc.php
@@ -49,15 +49,11 @@ function HandleParameters()
/**
* Get last config modification timestamp for given panel.
- * This was planned to be smart and check the involved locations,
- * even going up the location tree if the opening time schedule
- * is inherited, but this would still be incomplete by design, as
- * it wouldn't react to the linked room plan being considered
- * for changes, or added/removed PCs etc. So rather than giving
- * an incomplete "clever" design for detecting changes, we only
- * consider direct editing of the panel now. So the advice would
- * simply be "if you want the panel to reload automatically, hit
- * the edit button and click save". Might even add a shortcut
+ * This is incomplete however, as it wouldn't react to the
+ * linked room plan being edited, or added/removed PCs
+ * etc. So the advice would simply be "if you want the
+ * panel to reload automatically, hit the edit button
+ * and click save". Might even add a shortcut
* reload-button to the list of panels at some point.
*
* @param string $paneluuid panels uuid
@@ -65,13 +61,21 @@ function HandleParameters()
*/
function getLastChangeTs($paneluuid)
{
- $panel = Database::queryFirst('SELECT lastchange FROM locationinfo_panel WHERE paneluuid = :paneluuid',
+ $panel = Database::queryFirst('SELECT lastchange, locationids FROM locationinfo_panel WHERE paneluuid = :paneluuid',
compact('paneluuid'));
if ($panel === false) {
http_response_code(404);
die('Panel not found');
}
- return (int)$panel['lastchange'];
+ $lastChange = array((int)$panel['lastchange']);
+ if (!empty($panel['locationids'])) {
+ $res = Database::simpleQuery('SELECT lastchange FROM locationinfo_locationconfig
+ WHERE locationid IN (:locs)', array('locs' => explode(',', $panel['locationids'])));
+ while (($lc = $res->fetchColumn()) !== false) {
+ $lastChange[] = (int)$lc;
+ }
+ }
+ return max($lastChange);
}
/**
diff --git a/modules-available/locationinfo/frontend/frontendscript.js b/modules-available/locationinfo/frontend/frontendscript.js
index cc5c6827..bad6a8ed 100644
--- a/modules-available/locationinfo/frontend/frontendscript.js
+++ b/modules-available/locationinfo/frontend/frontendscript.js
@@ -45,7 +45,7 @@ function toInt(str) {
* @param {Array} globalConfig
* @returns {string} printable time
*/
-function GetTimeDiferenceAsString(a, b, globalConfig = null) {
+function GetTimeDiferenceAsString(a, b, globalConfig) {
if (!a || !b) {
return "";
}
diff --git a/modules-available/locationinfo/inc/coursebackend/coursebackend_dummy.inc.php b/modules-available/locationinfo/inc/coursebackend/coursebackend_dummy.inc.php
index adff8b1b..94c967de 100644
--- a/modules-available/locationinfo/inc/coursebackend/coursebackend_dummy.inc.php
+++ b/modules-available/locationinfo/inc/coursebackend/coursebackend_dummy.inc.php
@@ -137,5 +137,3 @@ class CourseBackend_Dummy extends CourseBackend
}
}
-
-?>
diff --git a/modules-available/locationinfo/inc/infopanel.inc.php b/modules-available/locationinfo/inc/infopanel.inc.php
index 12b6aec7..edeb9ccf 100644
--- a/modules-available/locationinfo/inc/infopanel.inc.php
+++ b/modules-available/locationinfo/inc/infopanel.inc.php
@@ -12,7 +12,7 @@ class InfoPanel
*/
public static function getConfig($paneluuid, &$config)
{
- $panel = Database::queryFirst('SELECT panelname, panelconfig, paneltype, locationids, lastchange FROM locationinfo_panel WHERE paneluuid = :paneluuid',
+ $panel = Database::queryFirst('SELECT panelname, panelconfig, paneltype, locationids FROM locationinfo_panel WHERE paneluuid = :paneluuid',
compact('paneluuid'));
if ($panel === false) {
@@ -68,7 +68,6 @@ class InfoPanel
}
self::appendOpeningTimes($config['locations'], $lids);
- $config['ts'] = (int)$panel['lastchange'];
$config['locations'] = array_values($config['locations']);
$config['time'] = date('Y-n-j-G-') . (int)date('i') . '-' . (int)(date('s'));
diff --git a/modules-available/locationinfo/inc/locationinfo.inc.php b/modules-available/locationinfo/inc/locationinfo.inc.php
index 2ed3622d..e3d7db3d 100644
--- a/modules-available/locationinfo/inc/locationinfo.inc.php
+++ b/modules-available/locationinfo/inc/locationinfo.inc.php
@@ -11,9 +11,7 @@ class LocationInfo
*/
public static function getPcState($pc)
{
- $logintime = (int)$pc['logintime'];
$lastseen = (int)$pc['lastseen'];
- $lastboot = (int)$pc['lastboot'];
$NOW = time();
if ($pc['state'] === 'OFFLINE' && $NOW - $lastseen > 21 * 86400) {
diff --git a/modules-available/locationinfo/lang/de/template-tags.json b/modules-available/locationinfo/lang/de/template-tags.json
index be2814d6..b305f800 100644
--- a/modules-available/locationinfo/lang/de/template-tags.json
+++ b/modules-available/locationinfo/lang/de/template-tags.json
@@ -10,8 +10,6 @@
"lang_checkConnection": "Verbindung pr\u00fcfen",
"lang_closed": "Geschlossen",
"lang_closingTime": "Schlie\u00dfungszeit",
- "lang_config": "Einstellungen",
- "lang_configupdateTooltip": "Zeit nach der die Einstellungen aktualisiert werden (in Minuten)",
"lang_createPanel": "Panel anlegen",
"lang_credentials": "Anmeldung",
"lang_day": "Tag",
@@ -25,8 +23,8 @@
"lang_ecoMode": "E-Ink Modus",
"lang_ecoTooltip": "Anstelle der Farb-basierten PC-Status Bilder, werden Symbol-basierte PC Bilder verwendet",
"lang_editDefaultPanelHints": "Hier k\u00f6nnen Sie ein Panel (z.B. digitales T\u00fcrschild) in Aussehen und Funktionsweise definieren. Um im Kalender \u00d6ffnungszeiten anzeigen zu k\u00f6nnen, m\u00fcssen Sie im Tab \"Raum-\/Ortsbezogene Einstellungen\" f\u00fcr den ausgew\u00e4hlten Raum entsprechend \u00d6ffnungszeiten eintragen. Damit im Kalender Veranstaltungen und andere Termine angezeigt werden k\u00f6nnen, muss ein funktionierendes Backend konfiguriert und den ausgew\u00e4hlten R\u00e4umen zugewiesen worden sein.",
- "lang_editSummaryPanelHints": "Hier k\u00f6nnen Sie ein Summary-Panel definieren. Das Panel zeigt eine Übersicht der in den R\u00e4umen enthalten PCs.",
"lang_editPanel": "Panel bearbeiten",
+ "lang_editSummaryPanelHints": "Hier k\u00f6nnen Sie ein Summary-Panel definieren. Das Panel zeigt eine \u00dcbersicht der in den R\u00e4umen enthalten PCs.",
"lang_editUrlPanelHints": "Hier k\u00f6nnen Sie konfigurieren, welche URL das Panel aufrufen soll. Dies erm\u00f6glicht Ihnen z.B. in Eingangsbereichen aktuelle Meldungen der Hochschule oder sonstige Webseiten anzuzeigen.",
"lang_entryName": "Name",
"lang_error": "Fehler",
@@ -38,6 +36,7 @@
"lang_insecureSsl": "Unsicheres SSL",
"lang_language": "Sprache",
"lang_languageTooltip": "Legt die Sprache der angezeigten Oberfl\u00e4che fest",
+ "lang_lastCalendarUpdate": "Kalender Update",
"lang_locationName": "Name",
"lang_locationSettings": "Raum-\/Ortsbezogene Einstellungen",
"lang_locations": "Orte",
diff --git a/modules-available/locationinfo/lang/en/template-tags.json b/modules-available/locationinfo/lang/en/template-tags.json
index be927ee4..5679e8b8 100644
--- a/modules-available/locationinfo/lang/en/template-tags.json
+++ b/modules-available/locationinfo/lang/en/template-tags.json
@@ -10,8 +10,6 @@
"lang_checkConnection": "Check connection",
"lang_closed": "Closed",
"lang_closingTime": "Closing time",
- "lang_config": "Config",
- "lang_configupdateTooltip": "Time interval the config gets updated (in minutes)",
"lang_createPanel": "Create panel",
"lang_credentials": "Login",
"lang_day": "Day",
@@ -38,6 +36,7 @@
"lang_insecureSsl": "Insecure SSL",
"lang_language": "Language",
"lang_languageTooltip": "The language the frontend uses",
+ "lang_lastCalendarUpdate": "Calendar update",
"lang_locationName": "Name",
"lang_locationSettings": "Location specific settings",
"lang_locations": "Locations",
diff --git a/modules-available/locationinfo/page.inc.php b/modules-available/locationinfo/page.inc.php
index c6aa0860..22a21951 100644
--- a/modules-available/locationinfo/page.inc.php
+++ b/modules-available/locationinfo/page.inc.php
@@ -129,8 +129,8 @@ class Page_LocationInfo extends Page
}
$serverlocationid = Request::post('serverlocationid', '', 'string');
- $recursive = (Request::post('recursive', '', 'string') !== '');
- if (empty($serverlocationid) && !$recursive) {
+ $changeServerRecursive = (Request::post('recursive', '', 'string') !== '');
+ if (empty($serverlocationid) && !$changeServerRecursive) {
$insertServerId = null;
$ignoreServer = 1;
} else {
@@ -170,12 +170,16 @@ class Page_LocationInfo extends Page
$mangled[] = $entry;
}
if (empty($mangled)) {
- $openingtimes = '';
+ $openingtimes = null;
} else {
$openingtimes = json_encode($mangled);
}
}
}
+ $NOW = time();
+ // Check if openingtimes changed
+ $res = Database::queryFirst('SELECT openingtime FROM locationinfo_locationconfig WHERE locationid = :locationid', compact('locationid'));
+ $otChanged = $res === false || $res['openingtime'] !== $openingtimes;
Database::exec("INSERT INTO `locationinfo_locationconfig` (locationid, serverid, serverlocationid, openingtime, lastcalendarupdate, lastchange)
VALUES (:id, :insertserverid, :serverlocationid, :openingtimes, 0, :now)
@@ -187,27 +191,66 @@ class Page_LocationInfo extends Page
'openingtimes' => $openingtimes,
'serverlocationid' => $serverlocationid,
'ignore_server' => $ignoreServer,
- 'now' => time(),
+ 'now' => $NOW,
));
- if (!$recursive)
- return true;
-
- // Recursive overwriting of serverid
- $children = Location::getRecursiveFlat($locationid);
- $array = array();
- foreach ($children as $loc) {
- $array[] = $loc['locationid'];
+ if ($otChanged) {
+ $tree = Location::getLocationsAssoc();
+ $todo = array();
+ $done = array();
+ foreach ($tree as $l) {
+ if ($l['parentlocationid'] == $locationid) {
+ $todo[] = $l['locationid'];
+ }
+ }
+ while (!empty($todo)) {
+ $loc = array_pop($todo);
+ if (in_array($loc, $done))
+ continue;
+ $done[] = $loc;
+ // See if this one inherits
+ $res = Database::queryFirst('SELECT openingtime FROM locationinfo_locationconfig WHERE locationid = :loc', compact('loc'));
+ if ($res === false) {
+ $res = Database::exec('INSERT INTO locationinfo_locationconfig (locationid, lastchange)
+ VALUES (:locationid, :now) ON DUPLICATE KEY UPDATE lastchange = :now',
+ array('locationid' => $loc, 'now' => $NOW));
+ } elseif (strlen($res['openingtime']) < 5) {
+ $res = Database::exec('UPDATE locationinfo_locationconfig SET lastchange = :now, openingtime = NULL
+ WHERE locationid = :locationid',
+ array('locationid' => $loc, 'now' => $NOW));
+ } else {
+ $res = 0;
+ }
+ if ($res > 0) {
+ // Row was updated, which means the openingtime column was empty, which means the openingtime is inherited, descend further
+ $todo = array_merge($todo, $tree[$loc]['children']);
+ foreach ($tree as $l) {
+ if ($l['parentlocationid'] == $loc) {
+ $todo[] = $l['locationid'];
+ }
+ }
+ }
+ }
}
- if (!empty($array)) {
- Database::exec("UPDATE locationinfo_locationconfig
+
+ if ($changeServerRecursive) {
+ // Recursive overwriting of serverid
+ $children = Location::getRecursiveFlat($locationid);
+ $array = array();
+ foreach ($children as $loc) {
+ $array[] = $loc['locationid'];
+ }
+ if (!empty($array)) {
+ Database::exec("UPDATE locationinfo_locationconfig
SET serverid = :serverid, lastcalendarupdate = IF(serverid <> :serverid, 0, lastcalendarupdate), lastchange = :now
WHERE locationid IN (:locations)", array(
'serverid' => $serverid,
'locations' => $array,
- 'now' => time(),
- ));
+ 'now' => $NOW,
+ ));
+ }
}
+
return true;
}
@@ -392,7 +435,7 @@ class Page_LocationInfo extends Page
$credentialsOk = $serverInstance->setCredentials($serverid, json_decode($dbresult['credentials'], true));
if ($credentialsOk) {
- $connectionOk = $serverInstance->checkConnection();
+ $serverInstance->checkConnection();
}
LocationInfo::setServerError($serverid, $serverInstance->getError());
@@ -465,7 +508,7 @@ class Page_LocationInfo extends Page
$locations[$locid] += array(
'openingGlyph' => $glyph,
'backend' => $backend,
- 'lastCalendarUpdate' => $row['lastcalendarupdate'], // TODO
+ 'lastCalendarUpdate' => Util::prettyTime($row['lastcalendarupdate']), // TODO
'backendMissing' => !CourseBackend::exists($row['servertype']),
);
}
@@ -478,8 +521,8 @@ class Page_LocationInfo extends Page
$depth--;
}
while ($location['depth'] > $depth) {
+ array_push($stack, empty($location['openingGlyph']) && ($depth === -1 || empty($stack[$depth])) ? '' : 'arrow-up');
$depth++;
- array_push($stack, empty($location['openingGlyph']) ? '' : 'arrow-up');
}
if ($depth > 0 && empty($location['openingGlyph'])) {
$location['openingGlyph'] = $stack[$depth - 1];
diff --git a/modules-available/locationinfo/templates/frontend-default.html b/modules-available/locationinfo/templates/frontend-default.html
index 92cad055..e457f68d 100755
--- a/modules-available/locationinfo/templates/frontend-default.html
+++ b/modules-available/locationinfo/templates/frontend-default.html
@@ -369,6 +369,7 @@ optional:
</div>
</body>
+<!--suppress RedundantIfStatementJS -->
<script type="text/javascript">
var rooms = {};
var lastRoomUpdate = 0;
diff --git a/modules-available/locationinfo/templates/frontend-summary.html b/modules-available/locationinfo/templates/frontend-summary.html
index ec5d8aab..4105dd16 100644
--- a/modules-available/locationinfo/templates/frontend-summary.html
+++ b/modules-available/locationinfo/templates/frontend-summary.html
@@ -226,8 +226,8 @@
queryRooms();
nextUpdate = 1000;
}
- for (property in rooms) {
- upDateRoomState(rooms[property]);
+ if (nextUpdate !== 1000) {
+ queryPanelChange();
}
clearTimeout(timeout);
setTimeout(update, nextUpdate);
@@ -267,7 +267,9 @@
}
ComputeCurrentState(rooms[json[i].id]);
}
- update();
+ for (property in rooms) {
+ upDateRoomState(rooms[property]);
+ }
}
/**
@@ -765,6 +767,30 @@
});
}
+ /**
+ * Checks whether the panel has been edited and reloads
+ * the entire page if so.
+ */
+ function queryPanelChange() {
+ $.ajax({
+ url: "{{dirprefix}}api.php?do=locationinfo&get=timestamp&uuid={{uuid}}",
+ dataType: 'json',
+ cache: false,
+ timeout: 5000,
+ success: function (result) {
+ if (!result || !result.ts) {
+ console.log('Warning: get=timestamp didnt return json with ts field');
+ return;
+ }
+ if (config.ts && config.ts !== result.ts) {
+ // Change
+ window.location.reload(true);
+ }
+ config.ts = result.ts;
+ }
+ })
+ }
+
</script>
</head>
<body>
diff --git a/modules-available/locationinfo/templates/page-locations.html b/modules-available/locationinfo/templates/page-locations.html
index de8dab7e..b30ef2ed 100644
--- a/modules-available/locationinfo/templates/page-locations.html
+++ b/modules-available/locationinfo/templates/page-locations.html
@@ -7,6 +7,7 @@
<tr>
<th>{{lang_locationName}}</th>
<th>{{lang_backend}}</th>
+ <th>{{lang_lastCalendarUpdate}}</th>
<th>{{lang_openingtimes}}</th>
</tr>
</thead>
@@ -25,6 +26,11 @@
{{backend}}
</td>
<td>
+ {{#backend}}
+ {{lastCalendarUpdate}}
+ {{/backend}}
+ </td>
+ <td>
<span class="glyphicon glyphicon-{{openingGlyph}}"></span>
</td>
</tr>
diff --git a/modules-available/locationinfo/templates/page-panels.html b/modules-available/locationinfo/templates/page-panels.html
index f374e456..e17b6584 100644
--- a/modules-available/locationinfo/templates/page-panels.html
+++ b/modules-available/locationinfo/templates/page-panels.html
@@ -11,8 +11,8 @@
{{#hasRunmode}}
<th class="slx-smallcol">{{lang_runmodeTHead}}</th>
{{/hasRunmode}}
- <th class="slx-smallcol"></th>
- <th class="slx-smallcol"></th>
+ <th class="slx-smallcol">{{lang_edit}}</th>
+ <th class="slx-smallcol">{{lang_delete}}</th>
</tr>
</thead>
<tbody>
@@ -43,13 +43,11 @@
<td>
<a class="btn btn-default btn-xs" href="?do=locationinfo&amp;show=edit-panel&amp;uuid={{paneluuid}}">
<span class="glyphicon glyphicon-cog"></span>
- {{lang_edit}}
</a>
</td>
<td>
<button type="submit" name="uuid" value="{{paneluuid}}" class="btn btn-danger btn-xs">
<span class="glyphicon glyphicon-trash"></span>
- {{lang_delete}}
</button>
</td>
</tr>
@@ -58,16 +56,16 @@
</tbody>
</table>
-<div>
- <a class="btn btn-sm btn-success" href="?do=locationinfo&amp;show=edit-panel&amp;uuid=new-default">
+<div class="buttonbar text-right">
+ <a class="btn btn-success" href="?do=locationinfo&amp;show=edit-panel&amp;uuid=new-default">
<span class="glyphicon glyphicon-plus"></span>
{{lang_defaultPanel}}
</a>
- <a class="btn btn-sm btn-success" href="?do=locationinfo&amp;show=edit-panel&amp;uuid=new-summary">
+ <a class="btn btn-success" href="?do=locationinfo&amp;show=edit-panel&amp;uuid=new-summary">
<span class="glyphicon glyphicon-plus"></span>
{{lang_summaryPanel}}
</a>
- <a class="btn btn-sm btn-success" href="?do=locationinfo&amp;show=edit-panel&amp;uuid=new-url">
+ <a class="btn btn-success" href="?do=locationinfo&amp;show=edit-panel&amp;uuid=new-url">
<span class="glyphicon glyphicon-plus"></span>
{{lang_urlPanel}}
</a>
diff --git a/modules-available/locations/lang/de/permissions.json b/modules-available/locations/lang/de/permissions.json
new file mode 100644
index 00000000..46dea864
--- /dev/null
+++ b/modules-available/locations/lang/de/permissions.json
@@ -0,0 +1,9 @@
+{
+ "location.view": "Räume anschauen.",
+ "location.edit": "Räume bearbeiten.",
+ "location.add": "Räume hinzufügen.",
+ "location.delete": "Räume löschen.",
+ "subnet.edit": "Subnetze bearbeiten.",
+ "subnet.add": "Subnetze hinzufügen.",
+ "subnet.delete": "Subnetze löschen."
+} \ No newline at end of file
diff --git a/modules-available/locations/lang/en/permissions.json b/modules-available/locations/lang/en/permissions.json
new file mode 100644
index 00000000..db0ac5f6
--- /dev/null
+++ b/modules-available/locations/lang/en/permissions.json
@@ -0,0 +1,9 @@
+{
+ "location.view": "View locations.",
+ "location.edit": "Edit locations.",
+ "location.add": "Add locations.",
+ "location.delete": "Delete locations.",
+ "subnet.edit": "Edit subnets.",
+ "subnet.add": "Add subnets.",
+ "subnet.delete": "Delete subnets."
+} \ No newline at end of file
diff --git a/modules-available/locations/permissions/permissions.json b/modules-available/locations/permissions/permissions.json
index db0ac5f6..609a673a 100644
--- a/modules-available/locations/permissions/permissions.json
+++ b/modules-available/locations/permissions/permissions.json
@@ -1,9 +1,9 @@
-{
- "location.view": "View locations.",
- "location.edit": "Edit locations.",
- "location.add": "Add locations.",
- "location.delete": "Delete locations.",
- "subnet.edit": "Edit subnets.",
- "subnet.add": "Add subnets.",
- "subnet.delete": "Delete subnets."
-} \ No newline at end of file
+[
+ "location.view",
+ "location.edit",
+ "location.add",
+ "location.delete",
+ "subnet.edit",
+ "subnet.add",
+ "subnet.delete"
+] \ No newline at end of file
diff --git a/modules-available/main/hooks/translation.inc.php b/modules-available/main/hooks/translation.inc.php
index 03fa5f79..7590dcb6 100644
--- a/modules-available/main/hooks/translation.inc.php
+++ b/modules-available/main/hooks/translation.inc.php
@@ -18,6 +18,9 @@ $HANDLER['subsections'] = array(
* Global tags.
* This just returns the union of global tags of all languages, as there is no
* way to define a definite set of required global tags.
+ *
+ * @param Module $module
+ * @return array dem tags
*/
$HANDLER['grep_global-tags'] = function($module) {
$want = array();
diff --git a/modules-available/news/lang/de/permissions.json b/modules-available/news/lang/de/permissions.json
new file mode 100644
index 00000000..b2c6fb1b
--- /dev/null
+++ b/modules-available/news/lang/de/permissions.json
@@ -0,0 +1,6 @@
+{
+ "news.save": "Änderungen am News Text speichern.",
+ "news.delete": "Alte News Texte löschen.",
+ "help.save": "Änderungen am Hilfe Text speichern.",
+ "help.delete": "Alte Hilfe Texte löschen."
+} \ No newline at end of file
diff --git a/modules-available/news/lang/en/permissions.json b/modules-available/news/lang/en/permissions.json
new file mode 100644
index 00000000..90d07aef
--- /dev/null
+++ b/modules-available/news/lang/en/permissions.json
@@ -0,0 +1,6 @@
+{
+ "news.save": "Save new news.",
+ "news.delete": "Delete old news.",
+ "help.save": "Save new help texts.",
+ "help.delete": "Delete old help texts"
+} \ No newline at end of file
diff --git a/modules-available/news/page.inc.php b/modules-available/news/page.inc.php
index 5ad79b0e..399fc307 100644
--- a/modules-available/news/page.inc.php
+++ b/modules-available/news/page.inc.php
@@ -2,21 +2,29 @@
class Page_News extends Page
{
- /**
- * Member variables needed to represent a news entry.
- *
- * @var newsId int ID of the news entry attributed by the database.
- * @var string Title of the entry.
- * $newsContent string Content as text. (TODO: html-Support?)
- * $newsDate string Unix epoch date of the news' creation.
- */
- private $newsId = false;
- private $newsTitle = false;
- private $newsContent = false;
- private $newsDate = false;
- private $helpContent = '';
- private $editHelp = false;
- private $hasSummernote = false;
+ /*
+ * Member variables needed to represent a news entry.
+ */
+
+ /**
+ * @var int ID of the news entry attributed by the database.
+ */
+ private $newsId = false;
+ /**
+ * @var string Title of the entry.
+ */
+ private $newsTitle = false;
+ /**
+ * @var string Content as text. (TODO: html-Support?)
+ */
+ private $newsContent = false;
+ /**
+ * @var int Unix epoch date of the news' creation.
+ */
+ private $newsDate = false;
+ private $helpContent = '';
+ private $editHelp = false;
+ private $hasSummernote = false;
/**
* Implementation of the abstract doPreprocess function.
diff --git a/modules-available/news/permissions/permissions.json b/modules-available/news/permissions/permissions.json
index 90d07aef..321e73ea 100644
--- a/modules-available/news/permissions/permissions.json
+++ b/modules-available/news/permissions/permissions.json
@@ -1,6 +1,6 @@
-{
- "news.save": "Save new news.",
- "news.delete": "Delete old news.",
- "help.save": "Save new help texts.",
- "help.delete": "Delete old help texts"
-} \ No newline at end of file
+[
+ "news.save",
+ "news.delete",
+ "help.save",
+ "help.delete"
+] \ No newline at end of file
diff --git a/modules-available/permissionmanager/clientscript.js b/modules-available/permissionmanager/clientscript.js
index 700ebc11..65065e6e 100644
--- a/modules-available/permissionmanager/clientscript.js
+++ b/modules-available/permissionmanager/clientscript.js
@@ -42,6 +42,12 @@ document.addEventListener("DOMContentLoaded", function() {
});
}
+ $("tr").on('click', function (e) {
+ if (e.target.type !== "checkbox") {
+ $(this).find("input:checkbox").trigger("click");
+ }
+ });
+
$("form input").keydown(function(e) {
if (e.keyCode === 13) e.preventDefault();
});
diff --git a/modules-available/permissionmanager/inc/permissionutil.inc.php b/modules-available/permissionmanager/inc/permissionutil.inc.php
index 391cd047..6fc33ad1 100644
--- a/modules-available/permissionmanager/inc/permissionutil.inc.php
+++ b/modules-available/permissionmanager/inc/permissionutil.inc.php
@@ -73,10 +73,9 @@ class PermissionUtil
if (!is_array($data))
continue;
preg_match('#^modules/([^/]+)/#', $file, $out);
- $newData = array();
- foreach( $data as $k => $v ) {
- $newData[] = $v;
- $permissions = self::putInPermissionTree($out[1].".".$k, $v, $permissions);
+ foreach( $data as $p ) {
+ $description = Dictionary::translateFileModule($out[1], "permissions", $p);
+ $permissions = self::putInPermissionTree($out[1].".".$p, $description, $permissions);
}
}
ksort($permissions);
@@ -102,7 +101,6 @@ class PermissionUtil
$tree =& $tree[$subPermission];
}
}
- $tree = $description;
return $original;
}
} \ No newline at end of file
diff --git a/modules-available/permissionmanager/style.css b/modules-available/permissionmanager/style.css
index bb03d153..49d631a8 100644
--- a/modules-available/permissionmanager/style.css
+++ b/modules-available/permissionmanager/style.css
@@ -13,6 +13,11 @@
margin-left: 10px;
}
+.missingInput {
+ border-color: rgba(255, 0, 0, 0.8);
+ box-shadow: 0 1px 1px rgba(255, 0, 0, 0.075) inset, 0 0 8px rgba(255, 0, 0, 0.6);
+}
+
.table {
margin-top: 20px;
}
@@ -41,6 +46,10 @@
margin-bottom: 20px;
}
+.selectize-input {
+ overflow: visible;
+}
+
.tree-container .selected {
background-color: rgba(0, 182, 41, 0.23);
diff --git a/modules-available/permissionmanager/templates/roleeditor.html b/modules-available/permissionmanager/templates/roleeditor.html
index 14839ee2..b07e2112 100644
--- a/modules-available/permissionmanager/templates/roleeditor.html
+++ b/modules-available/permissionmanager/templates/roleeditor.html
@@ -64,7 +64,7 @@
$('form').submit(function () {
var name = $.trim($('#rolename').val());
if (name === '') {
- alert('{{lang_emptyNameWarning}}');
+ $("#rolename").addClass("missingInput");
return false;
}
});
diff --git a/modules-available/permissionmanager/templates/rolestable.html b/modules-available/permissionmanager/templates/rolestable.html
index 99401624..992feca1 100644
--- a/modules-available/permissionmanager/templates/rolestable.html
+++ b/modules-available/permissionmanager/templates/rolestable.html
@@ -3,11 +3,13 @@
<div class="row">
<div class="col-md-4">
- <button class="btn btn-success" type="button" onclick="openRoleEditor()"><span class="glyphicon glyphicon-plus"></span> {{lang_newRole}}</button>
</div>
<div class="col-md-4">
<input type="text" class="form-control" id="roleNameSearchField" onkeyup="searchFieldFunction()" placeholder="{{lang_searchPlaceholder}}">
</div>
+ <div class="col-md-4 text-right">
+ <button class="btn btn-success" type="button" onclick="openRoleEditor()"><span class="glyphicon glyphicon-plus"></span> {{lang_newRole}}</button>
+ </div>
</div>
<div class="row">
diff --git a/modules-available/permissionmanager/templates/userstable.html b/modules-available/permissionmanager/templates/userstable.html
index bd48d16d..9f684e99 100644
--- a/modules-available/permissionmanager/templates/userstable.html
+++ b/modules-available/permissionmanager/templates/userstable.html
@@ -3,10 +3,8 @@
<div class="row">
<div class="col-md-4">
- <button class="btn btn-success" type="button" data-toggle="modal" data-target="#addRoleToUserModal"><span class="glyphicon glyphicon-share-alt"></span> {{lang_addRole}}</button>
- <button class="btn btn-danger" type="button" data-toggle="modal" data-target="#removeRoleFromUserModal"><span class="glyphicon glyphicon-trash"></span> {{lang_removeRole}}</button>
</div>
- <div class="col-md-4 text-left">
+ <div class="col-md-4">
<select multiple name="roles[]" id="select-role">
<option value>{{lang_selectizePlaceholder}}</option>
{{#roles}}
@@ -14,6 +12,10 @@
{{/roles}}
</select>
</div>
+ <div class="col-md-4 text-right">
+ <button class="btn btn-success" type="button" data-toggle="modal" data-target="#addRoleToUserModal"><span class="glyphicon glyphicon-share-alt"></span> {{lang_addRole}}</button>
+ <button class="btn btn-danger" type="button" data-toggle="modal" data-target="#removeRoleFromUserModal"><span class="glyphicon glyphicon-trash"></span> {{lang_removeRole}}</button>
+ </div>
</div>
<div class="row">
@@ -152,6 +154,7 @@
});
});
+
// if remove-Role button is clicked, uncheck all checkboxes in add-role modal so they aren't submitted too
function clearAddRoleModal () {
$('#addRoleToUserModal')
diff --git a/modules-available/rebootcontrol/inc/rebootqueries.inc.php b/modules-available/rebootcontrol/inc/rebootqueries.inc.php
index 1bdcb9a2..3dc3183f 100644
--- a/modules-available/rebootcontrol/inc/rebootqueries.inc.php
+++ b/modules-available/rebootcontrol/inc/rebootqueries.inc.php
@@ -27,7 +27,6 @@ class RebootQueries
$leftJoin
WHERE $where AND machine.lastseen > :cutoff", $queryArgs);
$ret = $res->fetchAll(PDO::FETCH_ASSOC);
- $NOW = time();
foreach ($ret as &$row) {
if ($row['state'] === 'IDLE' || $row['state'] === 'OCCUPIED') {
$row['status'] = 1;
diff --git a/modules-available/rebootcontrol/page.inc.php b/modules-available/rebootcontrol/page.inc.php
index db7882d9..fc3ded8f 100644
--- a/modules-available/rebootcontrol/page.inc.php
+++ b/modules-available/rebootcontrol/page.inc.php
@@ -33,7 +33,6 @@ class Page_RebootControl extends Page
}
$shutdown = $this->action === "startShutdown";
$minutes = Request::post('minutes', 0, 'int');
- $privKey = SSHKey::getPrivateKey();
$list = RebootQueries::getMachinesByUuid($clients);
if (count($list) !== count($clients)) {
diff --git a/modules-available/roomplanner/clientscript.js b/modules-available/roomplanner/clientscript.js
index 722e3909..bd29c06c 100644
--- a/modules-available/roomplanner/clientscript.js
+++ b/modules-available/roomplanner/clientscript.js
@@ -11,6 +11,9 @@ var selectMachinInitialized = false;
var placedMachines = [];
+var $modal, $selectizeSearch;
+var currentCallback = false;
+
function makeCombinedFieldSingle(item)
{
item.combined = (item.machineuuid + " " + item.hostname + " " + item.clientip + " " + item.macaddr + " " + item.macaddr.replace(/-/g, ':')).toLocaleLowerCase();
@@ -174,9 +177,14 @@ function onBtnSelect() {
}
function onPcDelete(muuid) {
- var bySubnet = machineCache[muuid];
- var bySearch = machineCache[muuid];
- var value = !bySubnet ? bySearch : bySubnet;
+ var value = machineCache[muuid];
+ if (!value) {
+ subnetMachines.forEach(function (v, i, a) {
+ if (subnetMachines[i] && subnetMachines[i].machineuuid === muuid) {
+ value = subnetMachines[i];
+ }
+ });
+ }
value.fixedlocationid = null;
makeCombinedFieldSingle(value);
}
diff --git a/modules-available/roomplanner/inc/pvsgenerator.inc.php b/modules-available/roomplanner/inc/pvsgenerator.inc.php
index 292441d4..cda32fce 100644
--- a/modules-available/roomplanner/inc/pvsgenerator.inc.php
+++ b/modules-available/roomplanner/inc/pvsgenerator.inc.php
@@ -54,7 +54,6 @@ class PvsGenerator
/* collect names and build room blocks - filter empty rooms while at it */
$roomNames = array();
$roomBlocks = '';
- $overrides = [];
foreach ($rooms as $room) {
if (is_null($room['notnull']) || isset($room['skip'])) // Not leaf
continue;
diff --git a/modules-available/roomplanner/js/lib/jquery-collision.js b/modules-available/roomplanner/js/lib/jquery-collision.js
index 98e37882..eae7ef85 100644
--- a/modules-available/roomplanner/js/lib/jquery-collision.js
+++ b/modules-available/roomplanner/js/lib/jquery-collision.js
@@ -175,11 +175,8 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
{
if( ! inclusive ) inclusive = false;
var epsilon = ( inclusive ? -1 : +1 ) * CollisionCoords.EPSILON;
- if( ( x > ( this.x1 + epsilon ) && x < ( this.x2 - epsilon ) ) &&
- ( y > ( this.y1 + epsilon ) && y < ( this.y2 - epsilon ) ) )
- return true;
- else
- return false;
+ return (x > (this.x1 + epsilon) && x < (this.x2 - epsilon)) &&
+ (y > (this.y1 + epsilon) && y < (this.y2 - epsilon));
};
CollisionCoords.prototype.overlaps = function( other, inclusive )
@@ -189,16 +186,16 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
hit = other._overlaps( this, inclusive );
if( hit.length > 0 )
{
- hit[0].dir = hit[0].dir == "Inside" ? "Outside" :
- hit[0].dir == "Outside" ? "Inside" :
- hit[0].dir == "N" ? "S" :
- hit[0].dir == "S" ? "N" :
- hit[0].dir == "W" ? "E" :
- hit[0].dir == "E" ? "W" :
- hit[0].dir == "NE" ? "SW" :
- hit[0].dir == "SW" ? "NE" :
- hit[0].dir == "SE" ? "NW" :
- hit[0].dir == "NW" ? "SE" :
+ hit[0].dir = hit[0].dir === "Inside" ? "Outside" :
+ hit[0].dir === "Outside" ? "Inside" :
+ hit[0].dir === "N" ? "S" :
+ hit[0].dir === "S" ? "N" :
+ hit[0].dir === "W" ? "E" :
+ hit[0].dir === "E" ? "W" :
+ hit[0].dir === "NE" ? "SW" :
+ hit[0].dir === "SW" ? "NE" :
+ hit[0].dir === "SE" ? "NW" :
+ hit[0].dir === "NW" ? "SE" :
undefined;
}
return hit || [];
diff --git a/modules-available/serversetup-bwlp/inc/ipxe.inc.php b/modules-available/serversetup-bwlp/inc/ipxe.inc.php
new file mode 100644
index 00000000..abeea748
--- /dev/null
+++ b/modules-available/serversetup-bwlp/inc/ipxe.inc.php
@@ -0,0 +1,102 @@
+<?php
+
+
+class Ipxe
+{
+
+ public static function parsePxeLinux($input)
+ {
+ /*
+ LABEL openslx-debug
+ MENU LABEL ^bwLehrpool-Umgebung starten (nosplash, debug)
+ KERNEL http://IPADDR/boot/default/kernel
+ INITRD http://IPADDR/boot/default/initramfs-stage31
+ APPEND slxbase=boot/default
+ IPAPPEND 3
+ */
+ $propMap = [
+ 'menu label' => ['string', 'title'],
+ 'menu default' => ['true', 'isDefault'],
+ 'menu hide' => ['true', 'isHidden'],
+ 'kernel' => ['string', 'kernel'],
+ 'initrd' => ['string', 'initrd'],
+ 'append' => ['string', 'append'],
+ 'ipappend' => ['int', 'ipAppend'],
+ 'localboot' => ['int', 'localBoot'],
+ ];
+ $sections = array();
+ $lines = preg_split('/[\r\n]+/', $input);
+ $section = null;
+ foreach ($lines as $line) {
+ if (!preg_match('/^\s*([^m\s]+|menu\s+\S+)\s+(.*?)\s*$/i', $line, $out))
+ continue;
+ $key = strtolower($out[1]);
+ $key = preg_replace('/\s+/', ' ', $key);
+ if ($key === 'label') {
+ if ($section !== null) {
+ $sections[] = $section;
+ }
+ $section = new PxeSection($out[2]);
+ } elseif ($section === null) {
+ continue;
+ } elseif (isset($propMap[$key])) {
+ $opt = $propMap[$key];
+ if ($opt[0] === 'true') {
+ $val = true;
+ } else {
+ $val = $out[2];
+ settype($val, $opt[0]);
+ }
+ $section->{$opt[1]} = $val;
+ }
+ }
+ if ($section !== null) {
+ $sections[] = $section;
+ }
+ return $sections;
+ }
+
+}
+
+class PxeMenu
+{
+ public $title;
+ public $timeoutMs;
+ public $totalTimeoutMs;
+ public $timeoutLabel;
+}
+
+class PxeSection
+{
+ /**
+ * @var string label used internally in PXEMENU definition to address this entry
+ */
+ public $label;
+ /**
+ * @var string MENU LABEL of PXEMENU - title of entry displayed to the user
+ */
+ public $title;
+ public $kernel;
+ public $initrd;
+ public $append;
+ /**
+ * @var int IPAPPEND from PXEMENU. Bitmask of valid options 1 and 2.
+ */
+ public $ipAppend;
+ public $passwd;
+ /**
+ * @var bool whether this section is marked as default (booted after timeout)
+ */
+ public $isDefault = false;
+ /**
+ * @var bool Menu entry is not visible (can only be triggered by timeout)
+ */
+ public $isHidden = false;
+ /**
+ * @var int Value of the LOCALBOOT field
+ */
+ public $localBoot;
+
+ public function __construct($label) { $this->label = $label; }
+}
+
diff --git a/modules-available/statistics/api.inc.php b/modules-available/statistics/api.inc.php
index a614658a..a7a636b3 100644
--- a/modules-available/statistics/api.inc.php
+++ b/modules-available/statistics/api.inc.php
@@ -263,6 +263,7 @@ if ($type{0} === '~') {
// `devicetype`, `devicename`, `subid`, `machineuuid`
// Make sure all screens are in the general hardware table
$hwids = array();
+ $keepPair = array();
foreach ($screens as $port => $screen) {
if (!array_key_exists('name', $screen))
continue;
@@ -274,6 +275,7 @@ if ($type{0} === '~') {
$hwids[$screen['name']] = $hwid;
}
// Now add new entries
+ $keepPair[] = array($hwid, $port);
$machinehwid = Database::insertIgnore('machine_x_hw', 'machinehwid', array(
'hwid' => $hwid,
'machineuuid' => $uuid,
@@ -302,30 +304,30 @@ if ($type{0} === '~') {
Database::exec("DELETE FROM machine_x_hw_prop WHERE machinehwid = :machinehwid AND prop NOT LIKE '@%'",
array('machinehwid' => $machinehwid));
} else {
- $qs = '?' . str_repeat(',?', count($validProps) - 1);
- array_unshift($validProps, $machinehwid);
- Database::exec("DELETE FROM machine_x_hw_prop"
- . " WHERE machinehwid = ? AND prop NOT LIKE '@%' AND prop NOT IN ($qs)",
- $validProps);
+ Database::exec("DELETE FROM machine_x_hw_prop
+ WHERE machinehwid = :mhwid AND prop NOT LIKE '@%' AND prop NOT IN (:props)", array(
+ 'mhwid' => $machinehwid,
+ 'props' => array_values($validProps),
+ ));
}
}
// Remove/disable stale entries
- if (empty($hwids)) {
+ if (empty($keepPair)) {
// No screens connected at all, purge all screen entries for this machine
- Database::exec("UPDATE machine_x_hw x, statistic_hw h"
- . " SET x.disconnecttime = UNIX_TIMESTAMP()"
- . " WHERE x.machineuuid = :uuid AND x.hwid = h.hwid AND h.hwtype = :type AND x.disconnecttime = 0",
+ Database::exec("UPDATE machine_x_hw x, statistic_hw h
+ SET x.disconnecttime = UNIX_TIMESTAMP()
+ WHERE x.machineuuid = :uuid AND x.hwid = h.hwid AND h.hwtype = :type AND x.disconnecttime = 0",
array('uuid' => $uuid, 'type' => DeviceType::SCREEN));
} else {
// Some screens connected, make sure old entries get removed
- $params = array_values($hwids);
- array_unshift($params, $uuid);
- array_unshift($params, DeviceType::SCREEN);
- $qs = '?' . str_repeat(',?', count($hwids) - 1);
- Database::exec("UPDATE machine_x_hw x, statistic_hw h"
- . " SET x.disconnecttime = UNIX_TIMESTAMP()"
- . " WHERE h.hwid = x.hwid AND x.disconnecttime = 0 AND h.hwtype = ? AND x.machineuuid = ? AND x.hwid NOT IN ($qs)", $params);
-
+ Database::exec("UPDATE machine_x_hw x, statistic_hw h
+ SET x.disconnecttime = UNIX_TIMESTAMP()
+ WHERE (x.hwid, x.devpath) NOT IN (:pairs) AND x.disconnecttime = 0 AND h.hwtype = :type
+ AND x.machineuuid = :uuid", array(
+ 'pairs' => $keepPair,
+ 'uuid' => $uuid,
+ 'type' => DeviceType::SCREEN,
+ ));
}
}
} else if ($type === '~suspend') {
diff --git a/modules-available/statistics/inc/parser.inc.php b/modules-available/statistics/inc/parser.inc.php
index acf6ebd4..679055a7 100644
--- a/modules-available/statistics/inc/parser.inc.php
+++ b/modules-available/statistics/inc/parser.inc.php
@@ -99,8 +99,8 @@ class Parser {
$hdds = array();
// Could have more than one disk - linear scan
$lines = preg_split("/[\r\n]+/", $data);
- $dev = false;
$i = 0;
+ $mbrToMbFactor = $sectorToMbFactor = 0;
foreach ($lines as $line) {
if (preg_match('/^Disk (\S+):.* (\d+) bytes/i', $line, $out)) {
// --- Beginning of MBR disk ---
@@ -260,7 +260,6 @@ class Parser {
public static function parseSmartctl(&$hdds, $data)
{
$lines = preg_split("/[\r\n]+/", $data);
- $i = 0;
foreach ($lines as $line) {
if (preg_match('/^NEXTHDD=(.+)$/', $line, $out)) {
unset($dev);
diff --git a/modules-available/statistics/page.inc.php b/modules-available/statistics/page.inc.php
index c3ecf52b..ea5b6f03 100644
--- a/modules-available/statistics/page.inc.php
+++ b/modules-available/statistics/page.inc.php
@@ -21,6 +21,11 @@ class Page_Statistics extends Page
private $query;
+ /**
+ * @var bool whether we have a SubPage from the pages/ subdir
+ */
+ private $haveSubpage;
+
/* PHP sucks, no static, const array definitions... Or am I missing something? */
public function initConstants()
{
@@ -125,53 +130,6 @@ class Page_Statistics extends Page
/* TODO ... */
}
- /*
- * TODO: Move to separate unit... hardware configurator?
- */
-
- protected function handleProjector($action)
- {
- $hwid = Request::post('hwid', false, 'int');
- if ($hwid === false) {
- Util::traceError('Param hwid missing');
- }
- if ($action === 'addprojector') {
- Database::exec('INSERT INTO statistic_hw_prop (hwid, prop, value)'
- . ' VALUES (:hwid, :prop, :value)', array(
- 'hwid' => $hwid,
- 'prop' => 'projector',
- 'value' => 'true',
- ));
- } else {
- Database::exec('DELETE FROM statistic_hw_prop WHERE hwid = :hwid AND prop = :prop', array(
- 'hwid' => $hwid,
- 'prop' => 'projector',
- ));
- }
- if (Module::isAvailable('sysconfig')) {
- ConfigTgz::rebuildAllConfigs();
- }
- Util::redirect('?do=statistics&show=projectors');
- }
-
- protected function showProjectors()
- {
- $res = Database::simpleQuery('SELECT h.hwname, h.hwid FROM statistic_hw h'
- . " INNER JOIN statistic_hw_prop p ON (h.hwid = p.hwid AND p.prop = :projector)"
- . " WHERE h.hwtype = :screen ORDER BY h.hwname ASC", array(
- 'projector' => 'projector',
- 'screen' => DeviceType::SCREEN,
- ));
- $data = array(
- 'projectors' => $res->fetchAll(PDO::FETCH_ASSOC)
- );
- Render::addTemplate('projector-list', $data);
- }
-
- /*
- * End TODO
- */
-
protected function doPreprocess()
{
$this->initConstants();
@@ -180,24 +138,42 @@ class Page_Statistics extends Page
Message::addError('main.no-permission');
Util::redirect('?do=Main');
}
- $action = Request::post('action');
- if ($action === 'setnotes') {
- $uuid = Request::post('uuid', '', 'string');
- $text = Request::post('content', '', 'string');
- if (empty($text)) {
- $text = null;
+
+ $show = Request::any('show', 'stat', 'string');
+ $show = preg_replace('/[^a-z0-9_\-]/', '', $show);
+
+ if (file_exists('modules/statistics/pages/' . $show . '.inc.php')) {
+
+ require_once 'modules/statistics/pages/' . $show . '.inc.php';
+ $this->haveSubpage = true;
+ SubPage::doPreprocess();
+
+ } else {
+
+ $action = Request::post('action');
+ if ($action === 'setnotes') {
+ $uuid = Request::post('uuid', '', 'string');
+ $text = Request::post('content', '', 'string');
+ if (empty($text)) {
+ $text = null;
+ }
+ Database::exec('UPDATE machine SET notes = :text WHERE machineuuid = :uuid', array(
+ 'uuid' => $uuid,
+ 'text' => $text,
+ ));
+ Message::addSuccess('notes-saved');
+ Util::redirect('?do=Statistics&uuid=' . $uuid);
+ } elseif ($action === 'delmachines') {
+ $this->deleteMachines();
+ Util::redirect('?do=statistics', true);
}
- Database::exec('UPDATE machine SET notes = :text WHERE machineuuid = :uuid', array(
- 'uuid' => $uuid,
- 'text' => $text,
- ));
- Message::addSuccess('notes-saved');
- Util::redirect('?do=Statistics&uuid=' . $uuid);
- } elseif ($action === 'addprojector' || $action === 'delprojector') {
- $this->handleProjector($action);
- } elseif ($action === 'delmachines') {
- $this->deleteMachines();
- Util::redirect('?do=statistics', true);
+
+ }
+
+ if (Request::isPost()) {
+ // Make sure we don't render any content for POST requests - should be handled above and then
+ // redirected properly
+ Util::redirect('?do=statistics');
}
}
@@ -229,6 +205,11 @@ class Page_Statistics extends Page
protected function doRender()
{
+ if ($this->haveSubpage) {
+ SubPage::doRender();
+ return;
+ }
+
$uuid = Request::get('uuid', false, 'string');
if ($uuid !== false) {
$this->showMachine($uuid);
@@ -236,10 +217,6 @@ class Page_Statistics extends Page
}
$show = Request::get('show', 'stat', 'string');
- if ($show === 'projectors') {
- $this->showProjectors();
- return;
- }
/* read filter */
$this->query = Request::any('filters', false);
@@ -622,7 +599,6 @@ class Page_Statistics extends Page
. ' badsectors ' . $xtra . ' FROM machine'
. " $join WHERE $where $sort", $args);
$rows = array();
- $NOW = time();
$singleMachine = 'none';
while ($row = $res->fetch(PDO::FETCH_ASSOC)) {
if ($singleMachine === 'none') {
@@ -894,7 +870,7 @@ class Page_Statistics extends Page
continue; // Don't differentiate between session and idle for non-clients
if ($first && $row['dateline'] > $cutoff && $client['lastboot'] > $cutoff) {
// Special case: offline before
- $spans['graph'] .= '<div style="background:#444;left:0%;width:' . round((min($row['dateline'], $client['lastboot']) - $cutoff) * $scale, 2) . '%">&nbsp;</div>';
+ $spans['graph'] .= '<div style="background:#444;left:0;width:' . round((min($row['dateline'], $client['lastboot']) - $cutoff) * $scale, 2) . '%">&nbsp;</div>';
}
$first = false;
if ($row['dateline'] + $row['data'] < $cutoff || $row['data'] > 864000) {
@@ -931,10 +907,10 @@ class Page_Statistics extends Page
}
if ($first && $client['lastboot'] > $cutoff) {
// Special case: offline before
- $spans['graph'] .= '<div style="background:#444;left:0%;width:' . round(($client['lastboot'] - $cutoff) * $scale, 2) . '%">&nbsp;</div>';
+ $spans['graph'] .= '<div style="background:#444;left:0;width:' . round(($client['lastboot'] - $cutoff) * $scale, 2) . '%">&nbsp;</div>';
} elseif ($first) {
// Not seen in last two weeks
- $spans['graph'] .= '<div style="background:#444;left:0%;width:100%">&nbsp;</div>';
+ $spans['graph'] .= '<div style="background:#444;left:0;width:100%">&nbsp;</div>';
}
if (isset($client['state_occupied'])) {
$spans['graph'] .= '<div style="background:#e99;left:' . round(($client['logintime'] - $cutoff) * $scale, 2) . '%;width:' . round(($NOW - $client['logintime'] + 900) * $scale, 2) . '%">&nbsp;</div>';
diff --git a/modules-available/statistics/pages/projectors.inc.php b/modules-available/statistics/pages/projectors.inc.php
new file mode 100644
index 00000000..cde542c6
--- /dev/null
+++ b/modules-available/statistics/pages/projectors.inc.php
@@ -0,0 +1,58 @@
+<?php
+
+class SubPage
+{
+
+ public static function doPreprocess()
+ {
+ $action = Request::post('action', false, 'string');
+ if ($action !== false) {
+ self::handleProjector($action);
+ }
+ }
+
+ private static function handleProjector($action)
+ {
+ $hwid = Request::post('hwid', false, 'int');
+ if ($hwid === false) {
+ Util::traceError('Param hwid missing');
+ }
+ if ($action === 'addprojector') {
+ Database::exec('INSERT INTO statistic_hw_prop (hwid, prop, value)'
+ . ' VALUES (:hwid, :prop, :value)', array(
+ 'hwid' => $hwid,
+ 'prop' => 'projector',
+ 'value' => 'true',
+ ));
+ } else {
+ Database::exec('DELETE FROM statistic_hw_prop WHERE hwid = :hwid AND prop = :prop', array(
+ 'hwid' => $hwid,
+ 'prop' => 'projector',
+ ));
+ }
+ if (Module::isAvailable('sysconfig')) {
+ ConfigTgz::rebuildAllConfigs();
+ }
+ Util::redirect('?do=statistics&show=projectors');
+ }
+
+ public static function doRender()
+ {
+ self::showProjectors();
+ }
+
+ private static function showProjectors()
+ {
+ $res = Database::simpleQuery('SELECT h.hwname, h.hwid FROM statistic_hw h'
+ . " INNER JOIN statistic_hw_prop p ON (h.hwid = p.hwid AND p.prop = :projector)"
+ . " WHERE h.hwtype = :screen ORDER BY h.hwname ASC", array(
+ 'projector' => 'projector',
+ 'screen' => DeviceType::SCREEN,
+ ));
+ $data = array(
+ 'projectors' => $res->fetchAll(PDO::FETCH_ASSOC)
+ );
+ Render::addTemplate('projector-list', $data);
+ }
+
+} \ No newline at end of file
diff --git a/modules-available/statistics/templates/filterbox.html b/modules-available/statistics/templates/filterbox.html
index 31daabc6..32464031 100644
--- a/modules-available/statistics/templates/filterbox.html
+++ b/modules-available/statistics/templates/filterbox.html
@@ -105,6 +105,7 @@ var slxFilterNames = {
slxLocations = {{{locations}}};
var slxFilterDel = '{{delimiter}}';
+var $modal, $queryForm;
document.addEventListener("DOMContentLoaded", function () {
@@ -217,7 +218,7 @@ function popupFilter(field) {
function addFilterFromForm() {
var argument1 = $('#argumentInput').val();
var argument2 = $('#argumentSelect').val();
- var argument = argument1 == '' ? argument2 : argument1;
+ var argument = argument1 ? argument1 : argument2;
var col = $('#columnSelect').val();
var op = $('#operatorSelect').val();
@@ -246,8 +247,8 @@ function toggleSort(field) {
/* equal sign should always be first, the rest doesn't matter*/
function myOpSort(a,b) {
- if (a == '=') { return -1; }
- else if (a == b) {return 0}
+ if (a === '=') { return -1; }
+ else if (a === b) {return 0}
else { return 1;}
}
diff --git a/modules-available/statistics/templates/machine-main.html b/modules-available/statistics/templates/machine-main.html
index 19deb8b3..d8f2c521 100644
--- a/modules-available/statistics/templates/machine-main.html
+++ b/modules-available/statistics/templates/machine-main.html
@@ -144,11 +144,11 @@
<tr>
<td class="text-nowrap">{{lang_screens}}</td>
<td>
- <form method="post" action="?do=statistics" id="delprojector">
+ <form method="post" action="?do=statistics&amp;show=projectors" id="delprojector">
<input type="hidden" name="token" value="{{token}}">
<input type="hidden" name="action" value="delprojector">
</form>
- <form method="post" action="?do=statistics" id="addprojector">
+ <form method="post" action="?do=statistics&amp;show=projectors" id="addprojector">
<input type="hidden" name="token" value="{{token}}">
<input type="hidden" name="action" value="addprojector">
</form>
diff --git a/modules-available/statistics/templates/page-replace.html b/modules-available/statistics/templates/page-replace.html
new file mode 100644
index 00000000..f87610a2
--- /dev/null
+++ b/modules-available/statistics/templates/page-replace.html
@@ -0,0 +1,104 @@
+<h1>{{lang_replaceMachinesHeading}}</h1>
+
+<style>
+ .reptable {
+ border-collapse: separate;
+ border-spacing: 2px;
+ }
+ .reptable td.a {
+ padding: 2px;
+ border:1px solid #ccc;
+ border-radius: 3px;
+ background: #eee;
+ vertical-align: top;
+ }
+ .reptable td.b {
+ font-size: 300%;
+ }
+</style>
+
+<form method="post" action="?do=statistics&amp;show=replace">
+ <input type="hidden" name="token" value="{{token}}">
+ <table class="reptable">
+ <thead>
+ <tr>
+ <th>{{lang_replaceOld}}</th>
+ <th></th>
+ <th>{{lang_replaceNew}}</th>
+ <th></th>
+ </tr>
+ </thead>
+ <tbody>
+ {{#pairs}}
+ <tr>
+ <td class="a">
+ <div><b>{{oldhost}}</b> {{oldip}}</div>
+ <div class="slx-bold">{{oldmodel}}</div>
+ <div class="small">{{oldmac}} – {{olduuid}}</div>
+ <div>{{lang_lastSeen}}: {{oldlastseen_s}}</div>
+ </td>
+ <td class="b">&rightarrow;</td>
+ <td class="a">
+ <div><b>{{newhost}}</b> {{newip}}</div>
+ <div class="slx-bold">{{newmodel}}</div>
+ <div class="small">{{newmac}} – {{newuuid}}</div>
+ <div>{{lang_firstSeen}}: {{newfirstseen_s}}</div>
+ </td>
+ <td>
+ <div class="checkbox checkbox-inline">
+ <input type="checkbox" name="replace[]" value="{{olduuid}}x{{newuuid}}">
+ <label></label>
+ </div>
+ </td>
+ </tr>
+ {{/pairs}}
+ </tbody>
+ </table>
+
+ <div class="text-right">
+ <button type="button" class="btn btn-danger" name="action" value="replace" data-toggle="modal" data-target="#confirm-dialog">
+ <span class="glyphicon glyphicon-floppy-disk"></span>
+ {{lang_replace}}
+ (<span id="rep-count">0</span>)
+ </button>
+ </div>
+
+ <div class="modal fade" id="confirm-dialog" tabindex="-1" role="dialog" aria-labelledby="myModalLabel">
+ <div class="modal-dialog" role="document">
+ <div class="modal-content">
+ <div class="modal-header">
+ <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
+ <h4 class="modal-title" id="myModalLabel">{{lang_replace}}</h4>
+ </div>
+ <div class="modal-body">
+ {{lang_sureReplaceNoUndo}}
+ </div>
+ <div class="modal-footer">
+ <button type="button" class="btn btn-default" data-dismiss="modal">{{lang_cancel}}</button>
+ <button type="submit" name="action" value="replace" class="btn btn-danger">
+ <span class="glyphicon glyphicon-floppy-disk"></span>
+ {{lang_replace}}
+ </button>
+ </div>
+ </div>
+ </div>
+ </div>
+</form>
+
+<script type="application/javascript"><!--
+ document.addEventListener('DOMContentLoaded', function () {
+ $('td.a').click(function () {
+ var $cb = $(this).parent().find('input:checkbox');
+ $cb.prop('checked', !$cb.is(':checked'));
+ cbChanged();
+ });
+ $('input:checkbox').change(function () {
+ cbChanged();
+ });
+ function cbChanged() {
+ var cnt = $('input:checkbox:checked').length;
+ $('#rep-count').text(cnt).parent().prop('disabled', cnt === 0);
+ }
+ cbChanged();
+ });
+//--></script> \ No newline at end of file
diff --git a/modules-available/statistics/templates/projector-list.html b/modules-available/statistics/templates/projector-list.html
index bc9ecdbd..c33aae09 100644
--- a/modules-available/statistics/templates/projector-list.html
+++ b/modules-available/statistics/templates/projector-list.html
@@ -1,7 +1,7 @@
<div class="panel panel-default">
<div class="panel-heading">{{lang_projectors}}</div>
<div class="panel-body">
- <form method="post" action="?do=statistics" id="delprojector">
+ <form method="post" action="?do=statistics&amp;show=projectors" id="delprojector">
<input type="hidden" name="token" value="{{token}}">
<input type="hidden" name="action" value="delprojector">
<p>{{lang_thoseAreProjectors}}</p>
diff --git a/modules-available/statistics_reporting/inc/queries.inc.php b/modules-available/statistics_reporting/inc/queries.inc.php
index 1a125c9e..bd8eb72e 100644
--- a/modules-available/statistics_reporting/inc/queries.inc.php
+++ b/modules-available/statistics_reporting/inc/queries.inc.php
@@ -5,7 +5,7 @@ class Queries
{
// Client Data: Name, Time Online, Median Time Online, Time Offline, last start, last logout, Last Time Booted, Number of Sessions > 60Sec, Number of Sessions < 60Sec, name of location, id of location (anonymized), machine uuid (anonymized)
- public static function getClientStatistics($from, $to, $lowerTimeBound = 0, $upperTimeBound = 24, $excludeToday = false) {
+ public static function getClientStatistics($from, $to, $lowerTimeBound = 0, $upperTimeBound = 24) {
$notassigned = Dictionary::translate('notAssigned', true);
Database::exec("SET SESSION group_concat_max_len = 1000000000");
$res = Database::simpleQuery("SELECT t2.name AS clientName, timeSum, medianSessionLength, offlineSum, IFNULL(lastStart, 0) as lastStart, IFNULL(lastLogout, 0) as lastLogout, longSessions, shortSessions, t2.locId, t2.locName, MD5(CONCAT(t2.locId, :salt)) AS locHash, MD5(CONCAT(t2.uuid, :salt)) AS clientHash FROM (
@@ -27,7 +27,7 @@ class Queries
}
// Location Data: Name, ID (anonymized), Time Online, Median Time Online, Time Offline, Number of Sessions > 60Sec, Number of Sessions < 60Sec
- public static function getLocationStatistics($from, $to, $lowerTimeBound = 0, $upperTimeBound = 24, $excludeToday = false) {
+ public static function getLocationStatistics($from, $to, $lowerTimeBound = 0, $upperTimeBound = 24) {
$notassigned = Dictionary::translate('notAssigned', true);
Database::exec("SET SESSION group_concat_max_len = 1000000000");
$res = Database::simpleQuery("SELECT t2.locId, t2.locName, MD5(CONCAT(t2.locId, :salt)) AS locHash, timeSum, medianSessionLength, offlineSum, longSessions, shortSessions FROM (
diff --git a/modules-available/statistics_reporting/inc/remotereport.inc.php b/modules-available/statistics_reporting/inc/remotereport.inc.php
index e94e9b93..98af8888 100644
--- a/modules-available/statistics_reporting/inc/remotereport.inc.php
+++ b/modules-available/statistics_reporting/inc/remotereport.inc.php
@@ -96,7 +96,7 @@ class RemoteReport
return $result;
}
- private function getLocalHardware()
+ private static function getLocalHardware()
{
$cpuInfo = file_get_contents('/proc/cpuinfo');
$uptime = file_get_contents('/proc/uptime');
diff --git a/modules-available/statistics_reporting/lang/de/permissions.json b/modules-available/statistics_reporting/lang/de/permissions.json
new file mode 100644
index 00000000..f90de252
--- /dev/null
+++ b/modules-available/statistics_reporting/lang/de/permissions.json
@@ -0,0 +1,10 @@
+{
+ "table.view.total": "Gesamt Tabelle anschauen.",
+ "table.view.location": "Orte Tabelle anschauen.",
+ "table.view.client": "Client Tabelle anschauen.",
+ "table.view.user": "Benutzer Tabelle anschauen.",
+ "table.view.vm": "Veranstaltungen Tabelle anschauen.",
+ "table.export": "Tabellen als JSON/CSV/XML exportieren. Dazu werden die Rechte um die jeweiligen Tabllen anzuschauen benötigt.",
+ "reporting.download": "Wöchentlichen Report herunterladen.",
+ "reporting.change": "Einstellungen zu dem wöchentlichen Report ändern."
+} \ No newline at end of file
diff --git a/modules-available/statistics_reporting/lang/en/permissions.json b/modules-available/statistics_reporting/lang/en/permissions.json
new file mode 100644
index 00000000..e6e550eb
--- /dev/null
+++ b/modules-available/statistics_reporting/lang/en/permissions.json
@@ -0,0 +1,10 @@
+{
+ "table.view.total": "View total table.",
+ "table.view.location": "View location table.",
+ "table.view.client": "View client table.",
+ "table.view.user": "View user table.",
+ "table.view.vm": "View lecture table.",
+ "table.export": "Export tables as JSON/CSV/XML. Needs the permission to view the table to export it.",
+ "reporting.download": "Download weekly report.",
+ "reporting.change": "Change weekly reporting settings."
+} \ No newline at end of file
diff --git a/modules-available/statistics_reporting/page.inc.php b/modules-available/statistics_reporting/page.inc.php
index 5d586b6c..863715d4 100644
--- a/modules-available/statistics_reporting/page.inc.php
+++ b/modules-available/statistics_reporting/page.inc.php
@@ -8,7 +8,18 @@ class Page_Statistics_Reporting extends Page
private $type;
// "Constants"
+ /**
+ * @var int
+ */
private $days;
+ /**
+ * @var int
+ */
+ private $lower;
+ /**
+ * @var int
+ */
+ private $upper;
/**
* @var array Names of columns that are being used by the various tables
@@ -306,6 +317,7 @@ class Page_Statistics_Reporting extends Page
case 'vm':
return GetData::perVM($flags);
}
+ return false;
}
}
diff --git a/modules-available/statistics_reporting/permissions/permissions.json b/modules-available/statistics_reporting/permissions/permissions.json
index e6e550eb..d967b75d 100644
--- a/modules-available/statistics_reporting/permissions/permissions.json
+++ b/modules-available/statistics_reporting/permissions/permissions.json
@@ -1,10 +1,10 @@
-{
- "table.view.total": "View total table.",
- "table.view.location": "View location table.",
- "table.view.client": "View client table.",
- "table.view.user": "View user table.",
- "table.view.vm": "View lecture table.",
- "table.export": "Export tables as JSON/CSV/XML. Needs the permission to view the table to export it.",
- "reporting.download": "Download weekly report.",
- "reporting.change": "Change weekly reporting settings."
-} \ No newline at end of file
+[
+ "table.view.total",
+ "table.view.location",
+ "table.view.client",
+ "table.view.user",
+ "table.view.vm",
+ "table.export",
+ "reporting.download",
+ "reporting.change"
+] \ No newline at end of file
diff --git a/modules-available/sysconfig/addconfig.inc.php b/modules-available/sysconfig/addconfig.inc.php
index f66bc508..55944cfa 100644
--- a/modules-available/sysconfig/addconfig.inc.php
+++ b/modules-available/sysconfig/addconfig.inc.php
@@ -22,7 +22,6 @@ abstract class AddConfig_Base
/**
*
* @param string $step
- * @return \AddConfig_Base
*/
public static function setStep($step)
{
@@ -186,6 +185,9 @@ class AddConfig_Start extends AddConfig_Base
*/
class AddConfig_Finish extends AddConfig_Base
{
+ /**
+ * @var ConfigTgz
+ */
private $config = false;
protected function preprocessInternal()
diff --git a/modules-available/sysconfig/addmodule.inc.php b/modules-available/sysconfig/addmodule.inc.php
index 30ca1d2c..1f78de81 100644
--- a/modules-available/sysconfig/addmodule.inc.php
+++ b/modules-available/sysconfig/addmodule.inc.php
@@ -21,8 +21,7 @@ abstract class AddModule_Base
/**
*
- * @param type $step
- * @return \AddModule_Base
+ * @param string $step name of class representing the current step
*/
public static function setStep($step)
{
diff --git a/modules-available/sysconfig/addmodule_adauth.inc.php b/modules-available/sysconfig/addmodule_adauth.inc.php
index 07806061..df7f385d 100644
--- a/modules-available/sysconfig/addmodule_adauth.inc.php
+++ b/modules-available/sysconfig/addmodule_adauth.inc.php
@@ -31,7 +31,7 @@ class AdAuth_Start extends AddModule_Base
if (isset($data['server']) && preg_match('/^(.*)\:(636|3269|389|3268)$/', $data['server'], $out)) {
$data['server'] = $out[1];
}
- if (isset($data['homeattr']) && !isset($data['mapping']['homemount'])) {
+ if (isset($data['homeattr']) && !isset($data['mapping']['homemount']) && strtolower($data['homeattr']) !== 'homedirectory') {
$data['mapping']['homemount'] = $data['homeattr'];
}
$data['step'] = 'AdAuth_CheckConnection';
@@ -59,13 +59,18 @@ class AdAuth_CheckConnection extends AddModule_Base
$this->server = Request::post('server');
$binddn = Request::post('binddn');
$ssl = Request::post('ssl', 'off') === 'on';
- if (empty($this->server) || empty($binddn)) {
- Message::addError('main.empty-field');
+ if (empty($this->server)) {
+ Message::addError('main.parameter-empty', 'server');
+ AddModule_Base::setStep('AdAuth_Start'); // Continues with AdAuth_Start for render()
+ return;
+ }
+ if (empty($binddn)) {
+ Message::addError('main.parameter-empty', 'binddn');
AddModule_Base::setStep('AdAuth_Start'); // Continues with AdAuth_Start for render()
return;
}
if ((preg_match(AD_AT_REGEX, $this->bindDn) > 0) && (strlen($this->searchBase) < 2)) {
- Message::addError('main.empty-field', 'searchBase');
+ Message::addError('main.parameter-empty', 'searchBase');
AddModule_Base::setStep('AdAuth_Start'); // Continues with AdAuth_Start for render()
return;
}
@@ -91,6 +96,7 @@ class AdAuth_CheckConnection extends AddModule_Base
protected function renderInternal()
{
+ $mapping = Request::post('mapping', false, 'array');
$data = array(
'edit' => Request::post('edit'),
'title' => Request::post('title'),
@@ -99,17 +105,16 @@ class AdAuth_CheckConnection extends AddModule_Base
'binddn' => $this->bindDn,
'bindpw' => Request::post('bindpw'),
'home' => Request::post('home'),
- 'homeattr' => Request::post('homeattr'),
'ssl' => Request::post('ssl'),
'fixnumeric' => Request::post('fixnumeric'),
'certificate' => Request::post('certificate', ''),
'taskid' => $this->scanTask['id'],
- 'mapping' => ConfigModuleBaseLdap::getMapping(Request::post('mapping', false, 'array')),
+ 'mapping' => ConfigModuleBaseLdap::getMapping($mapping),
);
$data['prev'] = 'AdAuth_Start';
if ((preg_match(AD_BOTH_REGEX, $this->bindDn) > 0) || (strlen($this->searchBase) < 2)) {
$data['next'] = 'AdAuth_SelfSearch';
- } elseif (empty($data['homeattr'])) {
+ } elseif (empty($mapping['homemount'])) {
$data['next'] = 'AdAuth_HomeAttrCheck';
} else {
$data['next'] = 'AdAuth_CheckCredentials';
@@ -127,10 +132,8 @@ class AdAuth_SelfSearch extends AddModule_Base
protected function preprocessInternal()
{
- $server = Request::post('server');
- $port = Request::post('port');
+ $server = $binddn = $port = null;
$searchbase = Request::post('searchbase', '');
- $binddn = Request::post('binddn');
$bindpw = Request::post('bindpw');
$ssl = Request::post('ssl', 'off') === 'on';
if ($ssl && !Request::post('fingerprint')) {
@@ -138,10 +141,13 @@ class AdAuth_SelfSearch extends AddModule_Base
AddModule_Base::setStep('AdAuth_Start'); // Continues with AdAuth_Start for render()
return;
}
- if (empty($server) || empty($binddn) || empty($port)) {
- Message::addError('main.empty-field');
- AddModule_Base::setStep('AdAuth_Start'); // Continues with AdAuth_Start for render()
- return;
+ foreach (['server', 'binddn', 'port'] as $var) {
+ $$var = Request::post($var, null);
+ if (empty($$var)) {
+ Message::addError('main.parameter-empty', $var);
+ AddModule_Base::setStep('AdAuth_Start'); // Continues with AdAuth_Start for render()
+ return;
+ }
}
$this->originalBindDn = '';
// Fix bindDN if short name given
@@ -190,6 +196,7 @@ class AdAuth_SelfSearch extends AddModule_Base
protected function renderInternal()
{
+ $mapping = Request::post('mapping', false, 'array');
$data = array(
'edit' => Request::post('edit'),
'title' => Request::post('title'),
@@ -199,16 +206,15 @@ class AdAuth_SelfSearch extends AddModule_Base
'binddn' => Request::post('binddn'),
'bindpw' => Request::post('bindpw'),
'home' => Request::post('home'),
- 'homeattr' => Request::post('homeattr'),
'ssl' => Request::post('ssl') === 'on',
'fixnumeric' => Request::post('fixnumeric'),
'fingerprint' => Request::post('fingerprint'),
'certificate' => Request::post('certificate', ''),
'originalbinddn' => $this->originalBindDn,
- 'mapping' => ConfigModuleBaseLdap::getMapping(Request::post('mapping', false, 'array')),
+ 'mapping' => ConfigModuleBaseLdap::getMapping($mapping),
'prev' => 'AdAuth_Start'
);
- if (empty($data['homeattr'])) {
+ if (empty($mapping['homemount'])) {
$data['next'] = 'AdAuth_HomeAttrCheck';
} else {
$data['next'] = 'AdAuth_CheckCredentials';
@@ -226,10 +232,8 @@ class AdAuth_HomeAttrCheck extends AddModule_Base
protected function preprocessInternal()
{
- $server = Request::post('server');
- $port = Request::post('port');
+ $server = $binddn = $port = null;
$searchbase = Request::post('searchbase', '');
- $binddn = Request::post('binddn');
$bindpw = Request::post('bindpw');
$ssl = Request::post('ssl', 'off') === 'on';
if ($ssl && !Request::post('fingerprint')) {
@@ -237,10 +241,13 @@ class AdAuth_HomeAttrCheck extends AddModule_Base
AddModule_Base::setStep('AdAuth_Start'); // Continues with AdAuth_Start for render()
return;
}
- if (empty($server) || empty($binddn) || empty($port)) {
- Message::addError('main.empty-field');
- AddModule_Base::setStep('AdAuth_Start'); // Continues with AdAuth_Start for render()
- return;
+ foreach (['server', 'binddn', 'port'] as $var) {
+ $$var = Request::post($var, null);
+ if (empty($$var)) {
+ Message::addError('main.parameter-empty', $var);
+ AddModule_Base::setStep('AdAuth_Start'); // Continues with AdAuth_Start for render()
+ return;
+ }
}
if ($ssl) {
$uri = "ldaps://$server:$port/";
@@ -276,7 +283,6 @@ class AdAuth_HomeAttrCheck extends AddModule_Base
'binddn' => Request::post('binddn'),
'bindpw' => Request::post('bindpw'),
'home' => Request::post('home'),
- 'homeattr' => Request::post('homeattr'),
'ssl' => Request::post('ssl') === 'on',
'fixnumeric' => Request::post('fixnumeric'),
'fingerprint' => Request::post('fingerprint'),
@@ -299,10 +305,8 @@ class AdAuth_CheckCredentials extends AddModule_Base
protected function preprocessInternal()
{
- $server = Request::post('server');
- $port = Request::post('port');
+ $server = $binddn = $port = null;
$searchbase = Request::post('searchbase', '');
- $binddn = Request::post('binddn');
$bindpw = Request::post('bindpw');
$ssl = Request::post('ssl', 'off') === 'on';
if ($ssl && !Request::post('fingerprint')) {
@@ -310,10 +314,13 @@ class AdAuth_CheckCredentials extends AddModule_Base
AddModule_Base::setStep('AdAuth_Start'); // Continues with AdAuth_Start for render()
return;
}
- if (empty($server) || empty($binddn) || empty($port)) {
- Message::addError('main.empty-field');
- AddModule_Base::setStep('AdAuth_Start'); // Continues with AdAuth_Start for render()
- return;
+ foreach (['server', 'binddn', 'port'] as $var) {
+ $$var = Request::post($var, null);
+ if (empty($$var)) {
+ Message::addError('main.parameter-empty', $var);
+ AddModule_Base::setStep('AdAuth_Start'); // Continues with AdAuth_Start for render()
+ return;
+ }
}
// Test query 4 users
if ($ssl) {
@@ -502,8 +509,7 @@ class AdAuth_Finish extends AddModule_Base
Message::addError('main.value-invalid', 'any', 'any');
$tgz = false;
} else {
- $parent = $this->stopOldInstance();
- $tgz = $module->generate($this->edit === false, $parent);
+ $tgz = $module->generate($this->edit === false);
}
if ($tgz === false) {
AddModule_Base::setStep('AdAuth_Start'); // Continues with AdAuth_Start for render()
@@ -514,24 +520,6 @@ class AdAuth_Finish extends AddModule_Base
);
}
- private function stopOldInstance()
- {
- if ($this->edit === false)
- return NULL;
- $list = ConfigTgz::getAllForModule($this->edit->id());
- if (!is_array($list))
- return NULL;
- $parent = NULL;
- foreach ($list as $tgz) {
- if (!$tgz->isActive())
- continue;
- $task = Trigger::ldadp($tgz->id(), $parent);
- if (isset($task['id']))
- $parent = $task['id'];
- }
- return $parent;
- }
-
protected function renderInternal()
{
Render::addDialog(Dictionary::translateFile('config-module', 'adAuth_title'), false, 'ad-finish', $this->taskIds);
diff --git a/modules-available/sysconfig/addmodule_branding.inc.php b/modules-available/sysconfig/addmodule_branding.inc.php
index c2f9e690..6e628926 100644
--- a/modules-available/sysconfig/addmodule_branding.inc.php
+++ b/modules-available/sysconfig/addmodule_branding.inc.php
@@ -116,8 +116,10 @@ class Branding_ProcessFile extends AddModule_Base
// [wikipedia] Try to be nice and detect links that might give a hint where the svg can be found
if (preg_match_all('#href="([^"]*upload.wikimedia.org/[^"]*/[^"]*/[^"]*\.svg|[^"]+/[^"]+:[^"]+\.svg[^"]*)"#', $content, $out, PREG_PATTERN_ORDER)) {
- if ($title === false && preg_match('#<title>([^<]*)</title>#i', $content, $tout))
+ if ($title === false && preg_match('#<title>([^<]*)</title>#i', $content, $tout)) {
$title = trim(preg_replace('/\W*Wikipedia.*/', '', $tout[1]));
+ }
+ $new = false;
foreach ($out[1] as $res) {
if (strpos($res, 'action=edit') !== false)
continue;
@@ -125,7 +127,7 @@ class Branding_ProcessFile extends AddModule_Base
if ($new !== $url)
break;
}
- if ($new === $url)
+ if ($new === $url || $new === false)
break;
$url = $new;
continue;
diff --git a/modules-available/sysconfig/addmodule_ldapauth.inc.php b/modules-available/sysconfig/addmodule_ldapauth.inc.php
index a193f779..1db6cb51 100644
--- a/modules-available/sysconfig/addmodule_ldapauth.inc.php
+++ b/modules-available/sysconfig/addmodule_ldapauth.inc.php
@@ -23,7 +23,7 @@ class LdapAuth_Start extends AddModule_Base
if (isset($data['server']) && preg_match('/^(.*)\:(636|389)$/', $data['server'], $out)) {
$data['server'] = $out[1];
}
- if (isset($data['homeattr']) && !isset($data['mapping']['homemount'])) {
+ if (isset($data['homeattr']) && !isset($data['mapping']['homemount']) && strtolower($data['homeattr']) !== 'homedirectory') {
$data['mapping']['homemount'] = $data['homeattr'];
}
$data['step'] = 'LdapAuth_CheckConnection';
@@ -281,8 +281,7 @@ class LdapAuth_Finish extends AddModule_Base
Message::addError('main.value-invalid', 'any', 'any');
$tgz = false;
} else {
- $parent = $this->stopOldInstance();
- $tgz = $module->generate($this->edit === false, $parent);
+ $tgz = $module->generate($this->edit === false);
}
if ($tgz === false) {
AddModule_Base::setStep('LdapAuth_Start'); // Continues with LdapAuth_Start for render()
@@ -293,24 +292,6 @@ class LdapAuth_Finish extends AddModule_Base
);
}
- private function stopOldInstance()
- {
- if ($this->edit === false)
- return NULL;
- $list = ConfigTgz::getAllForModule($this->edit->id());
- if (!is_array($list))
- return NULL;
- $parent = NULL;
- foreach ($list as $tgz) {
- if (!$tgz->isActive())
- continue;
- $task = Trigger::ldadp($tgz->id(), $parent);
- if (isset($task['id']))
- $parent = $task['id'];
- }
- return $parent;
- }
-
protected function renderInternal()
{
Render::addDialog(Dictionary::translateFile('config-module', 'ldapAuth_title'), false, 'ldap-finish', $this->taskIds);
diff --git a/modules-available/sysconfig/clientscript.js b/modules-available/sysconfig/clientscript.js
index f3a47824..1553d678 100644
--- a/modules-available/sysconfig/clientscript.js
+++ b/modules-available/sysconfig/clientscript.js
@@ -98,7 +98,7 @@ function checkBuildStatus() {
confs.push($(this).val());
});
if (mods.length === 0 && confs.length === 0) return;
- if (++statusChecks < 10) setTimeout(checkBuildStatus, 200 + 50 * statusChecks);
+ if (++statusChecks < 10) setTimeout(checkBuildStatus, 150 + 100 * statusChecks);
$.post('?do=SysConfig', { mods: mods.join(), confs: confs.join(), token: TOKEN, action: 'status' }, function (data) {
if (typeof data === 'undefined') return;
if (typeof data.mods === 'object') updateButtonColor($(".refmod.btn-primary"), data.mods);
diff --git a/modules-available/sysconfig/inc/configmodule.inc.php b/modules-available/sysconfig/inc/configmodule.inc.php
index 54d06afe..2cee37a9 100644
--- a/modules-available/sysconfig/inc/configmodule.inc.php
+++ b/modules-available/sysconfig/inc/configmodule.inc.php
@@ -135,7 +135,7 @@ abstract class ConfigModule
* Get module instances from module type.
*
* @param int $moduleType module type to get
- * @return \ConfigModule[] The requested modules from DB, or false on error
+ * @return \ConfigModule[]|false The requested modules from DB, or false on error
*/
public static function getAll($moduleType = false)
{
@@ -412,6 +412,9 @@ abstract class ConfigModule
$this->markFailed();
return false;
}
+ } elseif (!file_exists($tmpTgz)) {
+ EventLog::warning('ConfigModule::markUpdated for tmpTgz="' . $this->moduleTitle . '" called which doesn\'t exist. Doing nothing.');
+ return true;
} else {
$task = Taskmanager::submit('MoveFile', array(
'source' => $tmpTgz,
@@ -419,10 +422,11 @@ abstract class ConfigModule
));
$task = Taskmanager::waitComplete($task, 5000);
if (Taskmanager::isFailed($task) || !Taskmanager::isFinished($task)) {
- if (!API && !AJAX)
+ if (!API && !AJAX) {
Taskmanager::addErrorMessage($task);
- else
- EventLog::failure('Could not move ' . $tmpTgz . ' to ' . $this->moduleArchive . ' while generating "' . $this->moduleTitle . '"');
+ } else {
+ EventLog::failure('Could not move ' . $tmpTgz . ' to ' . $this->moduleArchive . ' while generating "' . $this->moduleTitle . '"', print_r($task, true));
+ }
$this->markFailed();
return false;
}
diff --git a/modules-available/sysconfig/inc/configmodulebaseldap.inc.php b/modules-available/sysconfig/inc/configmodulebaseldap.inc.php
index d8a41a8b..d6fc3ed9 100644
--- a/modules-available/sysconfig/inc/configmodulebaseldap.inc.php
+++ b/modules-available/sysconfig/inc/configmodulebaseldap.inc.php
@@ -33,7 +33,10 @@ abstract class ConfigModuleBaseLdap extends ConfigModule
protected function generateInternal($tgz, $parent)
{
- Trigger::ldadp($this->id(), $parent);
+ $np = Trigger::ldadp($this->id(), $parent);
+ if ($np !== false) {
+ $parent = $np;
+ }
$config = $this->moduleData;
if (isset($config['certificate']) && !is_string($config['certificate'])) {
unset($config['certificate']);
@@ -64,7 +67,11 @@ abstract class ConfigModuleBaseLdap extends ConfigModule
$config['fixnumeric'] = 's';
}
$this->preTaskmanagerHook($config);
- return Taskmanager::submit('CreateLdapConfig', $config);
+ $task = Taskmanager::submit('CreateLdapConfig', $config);
+ if (is_array($task) && isset($task['id'])) {
+ Trigger::ldadp(null, $task['id']);
+ }
+ return $task;
}
/**
diff --git a/modules-available/sysconfig/inc/configtgz.inc.php b/modules-available/sysconfig/inc/configtgz.inc.php
index dbf1bc99..17c9f35d 100644
--- a/modules-available/sysconfig/inc/configtgz.inc.php
+++ b/modules-available/sysconfig/inc/configtgz.inc.php
@@ -157,7 +157,6 @@ class ConfigTgz
{
if ($this->configId === 0)
Util::traceError('ConfigTgz::markUpdated called with invalid config id!');
- Event::activeConfigChanged();
if ($this->areAllModulesUpToDate())
return $this->mark('OK');
return $this->mark('OUTDATED');
@@ -232,6 +231,11 @@ class ConfigTgz
self::recompress([], SysConfig::GLOBAL_MINIMAL_CONFIG);
}
+ /**
+ * @param string $title Title of config
+ * @param int[] $moduleIds Modules to include in config
+ * @return false|ConfigTgz The module instance, false on error
+ */
public static function insert($title, $moduleIds)
{
if (!is_array($moduleIds))
@@ -287,6 +291,10 @@ class ConfigTgz
return $instance;
}
+ /**
+ * @param int $moduleId ID of config module
+ * @return ConfigTgz[]|false
+ */
public static function getAllForModule($moduleId)
{
$res = Database::simpleQuery("SELECT configid, title, filepath FROM configtgz_x_module "
diff --git a/modules-available/sysconfig/inc/ldap.inc.php b/modules-available/sysconfig/inc/ldap.inc.php
index 23b24885..349a662e 100644
--- a/modules-available/sysconfig/inc/ldap.inc.php
+++ b/modules-available/sysconfig/inc/ldap.inc.php
@@ -12,11 +12,7 @@ class Ldap
{
// To find ourselves we try to figure out the proper search base, since the given one
// might be just for users, not for functional or utility accounts
- if (preg_match('/,(OU=.*DC=.*)$/i', Ldap::normalizeDn($binddn), $out)) {
- // Get OU from binddn; works if not given short form of DOMAIN\user or user@domain.fqdn.com
- $searchbase = $out[1];
- } elseif (preg_match('/,(DC=.*)$/i', Ldap::normalizeDn($searchbase), $out)) {
- // Otherwise, shorten search base enough to only consider the DC=..,DC=.. part at the end
+ if (preg_match('/^\w+=[^=]+,(.*)$/i', Ldap::normalizeDn($binddn), $out)) {
$searchbase = $out[1];
}
return $searchbase;
diff --git a/modules-available/sysconfig/inc/ppd.inc.php b/modules-available/sysconfig/inc/ppd.inc.php
index aa2e0e5a..5ccdbd53 100644
--- a/modules-available/sysconfig/inc/ppd.inc.php
+++ b/modules-available/sysconfig/inc/ppd.inc.php
@@ -413,6 +413,8 @@ class Ppd
// StringValue
$value = $vMatch[1];
$valueTranslation = isset($vMatch[2]) ? $this->unhexTranslation($no, substr($vMatch[2], 1)) : $value;
+ } else {
+ $valueTranslation = $value;
}
// Key-value-pair parsed, now the fun part
// Special cases for openening closing certain groups
@@ -691,6 +693,7 @@ class Ppd
$chars = array_reduce(array_unique($array), function ($carry, $item) {
return $carry . '\x' . dechex(ord($item));
}, '');
+ return $chars;
}
private function unhexTranslation($lineNo, $translation)
@@ -703,7 +706,7 @@ class Ppd
}
$string = preg_replace('/[^a-fA-F0-9]/', '', $match[0]);
if (strlen($string) % 2 !== 0) {
- $this->warn('Odd number of hex digits in hex substring');
+ $this->warn($lineNo, 'Odd number of hex digits in hex substring');
$string = substr($string, 0, -1);
}
return pack('H*', $string);
diff --git a/modules-available/sysconfig/page.inc.php b/modules-available/sysconfig/page.inc.php
index 043645df..30271514 100644
--- a/modules-available/sysconfig/page.inc.php
+++ b/modules-available/sysconfig/page.inc.php
@@ -343,6 +343,9 @@ class Page_SysConfig extends Page
Message::addError('main.empty-field');
Util::redirect('?do=sysconfig&locationid=' . $this->currentLoc);
}
+ // Validate that either the configid is valid (in case we override for a specific location)
+ // or that if the locationid is 0 (=global) that the configid exists, because it's not allowed
+ // to unset the global config
if ($this->currentLoc === 0 || $configid !== 0) {
$row = Database::queryFirst("SELECT title, filepath FROM configtgz WHERE configid = :configid LIMIT 1", array('configid' => $configid));
if ($row === false) {
@@ -358,6 +361,7 @@ class Page_SysConfig extends Page
Database::exec("INSERT INTO configtgz_location (locationid, configid) VALUES (:locationid, :configid)"
. " ON DUPLICATE KEY UPDATE configid = :configid", compact('locationid', 'configid'));
}
+ Event::activeConfigChanged();
Util::redirect('?do=sysconfig&locationid=' . $this->currentLoc);
}
@@ -475,4 +479,36 @@ class Page_SysConfig extends Page
AddConfig_Base::setStep($step);
}
+ /**
+ * If modules need updates (blue refresh buttons), we query their state
+ * via ajax, in case they are about to generate. This happens for example
+ * if you edit a module and a bunch of configs depend on it and will be
+ * rebuilt.
+ */
+ protected function doAjax()
+ {
+ if (Request::post('action') === 'status') {
+ $mods = Request::post('mods');
+ $confs = Request::post('confs');
+ $outMods = array();
+ $outConfs = array();
+ $mods = explode(',', $mods);
+ $confs = explode(',', $confs);
+ // Mods
+ $res = Database::simpleQuery("SELECT moduleid FROM configtgz_module
+ WHERE moduleid in (:mods) AND status = 'OK'", compact('mods'));
+ while ($row = $res->fetch(PDO::FETCH_ASSOC)) {
+ $outMods[] = $row['moduleid'];
+ }
+ // Confs
+ $res = Database::simpleQuery("SELECT configid FROM configtgz
+ WHERE configid in (:confs) AND status = 'OK'", compact('confs'));
+ while ($row = $res->fetch(PDO::FETCH_ASSOC)) {
+ $outConfs[] = $row['configid'];
+ }
+ Header('Content-Type: application/json');
+ die(json_encode(array('mods' => $outMods, 'confs' => $outConfs)));
+ }
+ }
+
}
diff --git a/modules-available/sysconfig/templates/ad-selfsearch.html b/modules-available/sysconfig/templates/ad-selfsearch.html
index 6b85b9ed..64e181b2 100644
--- a/modules-available/sysconfig/templates/ad-selfsearch.html
+++ b/modules-available/sysconfig/templates/ad-selfsearch.html
@@ -54,7 +54,7 @@
<input name="server" value="{{server}}" type="hidden">
<input name="port" value="{{port}}" type="hidden">
<input id="searchbase" name="searchbase" value="{{searchbase}}" type="hidden">
- <input id="fulldn" name="binddn" value="" type="hidden">
+ <input id="fulldn" name="binddn" value="{{binddn}}" type="hidden">
<input id="givendn" name="originalbinddn" value="{{originalbinddn}}" type="hidden">
<input name="bindpw" value="{{bindpw}}" type="hidden">
<input id="home" name="home" value="{{home}}" type="hidden">
diff --git a/modules-available/sysconfignew/page.inc.php b/modules-available/sysconfignew/page.inc.php
index 44b385b6..c8cdb3cd 100644
--- a/modules-available/sysconfignew/page.inc.php
+++ b/modules-available/sysconfignew/page.inc.php
@@ -73,6 +73,7 @@ class Page_SysConfigNew extends Page
);
}
+ $ret = '';
foreach ($modules as $module) {
$class = ($module['chosen']) ? "select-item select-item-selected" : "select-item";
$ret .= "<button type='button' class='" . $class . "' onclick='select(this)' >";
diff --git a/modules-available/systemstatus/lang/de/template-tags.json b/modules-available/systemstatus/lang/de/template-tags.json
index fcf836ec..89066257 100644
--- a/modules-available/systemstatus/lang/de/template-tags.json
+++ b/modules-available/systemstatus/lang/de/template-tags.json
@@ -1,7 +1,7 @@
{
"lang_OK": "OK",
"lang_addressConfiguration": "Adresskonfiguration",
- "lang_areYouSureNoUndo": "Sind Sie sicher? Diese Aktion kann nicht r\u00fcckg\u00e4ngig gemacht werden.",
+ "lang_areYouSureReboot": "Server jetzt neustarten?",
"lang_attention": "Achtung!",
"lang_average": "Durchschnitt",
"lang_capacity": "Kapazit\u00e4t",
diff --git a/modules-available/systemstatus/lang/en/template-tags.json b/modules-available/systemstatus/lang/en/template-tags.json
index 159ae59d..5f6ad898 100644
--- a/modules-available/systemstatus/lang/en/template-tags.json
+++ b/modules-available/systemstatus/lang/en/template-tags.json
@@ -1,7 +1,7 @@
{
"lang_OK": "OK",
"lang_addressConfiguration": "Address Configuration",
- "lang_areYouSureNoUndo": "Are you sure? This cannot be undone!",
+ "lang_areYouSureReboot": "Reboot server now?",
"lang_attention": "Attention!",
"lang_average": "Average",
"lang_capacity": "Capacity",
diff --git a/modules-available/systemstatus/page.inc.php b/modules-available/systemstatus/page.inc.php
index c1c52af0..8a0e5f87 100644
--- a/modules-available/systemstatus/page.inc.php
+++ b/modules-available/systemstatus/page.inc.php
@@ -231,7 +231,12 @@ class Page_SystemStatus extends Page
$data = array('services' => array());
$tasks = array();
- foreach (['dmsd', 'dnbd3-server', 'atftpd'] as $svc) {
+ $todo = ['dmsd', 'atftpd'];
+ if (Module::isAvailable('dnbd3') && Dnbd3::isEnabled()) {
+ $todo[] = 'dnbd3-server';
+ }
+
+ foreach ($todo as $svc) {
$tasks[] = array(
'name' => $svc,
'task' => Taskmanager::submit('Systemctl', ['service' => $svc, 'operation' => 'is-active'])
diff --git a/modules-available/systemstatus/templates/_page.html b/modules-available/systemstatus/templates/_page.html
index ca3e6fd2..0de94cad 100644
--- a/modules-available/systemstatus/templates/_page.html
+++ b/modules-available/systemstatus/templates/_page.html
@@ -92,12 +92,16 @@
<div class ="modal fade" id="rebootServerModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel">
<div class="modal-dialog" style="width: 400px" role="document">
<div class="modal-content">
+ <div class="modal-header">
+ <button type="button" class="close" data-dismiss="modal">&times;</button>
+ <b>{{lang_serverReboot}}</b>
+ </div>
<div class="modal-body">
- {{lang_areYouSureNoUndo}}
+ {{lang_areYouSureReboot}}
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">{{lang_cancel}}</button>
- <button type="submit" class="btn btn-sm btn-warning"><span class="glyphicon glyphicon-repeat"></span> {{lang_serverReboot}}</button>
+ <button type="submit" class="btn btn-warning"><span class="glyphicon glyphicon-repeat"></span> {{lang_serverReboot}}</button>
</div>
</div>
</div>
diff --git a/modules-available/translation/page.inc.php b/modules-available/translation/page.inc.php
index acc0d6e8..a5cdebed 100644
--- a/modules-available/translation/page.inc.php
+++ b/modules-available/translation/page.inc.php
@@ -132,8 +132,6 @@ class Page_Translation extends Page
protected function doRender()
{
- $langs = Dictionary::getLanguages(true);
-
// Overview (list of modules)
if ($this->module === false) {
$this->showListOfModules();
@@ -466,7 +464,7 @@ class Page_Translation extends Page
/**
* Get all module tags used/required.
*
- * @param type $module
+ * @param string $module
* @return array of array(tagname => (bool)required)
*/
private function loadUsedModuleTags($module = false)
@@ -507,7 +505,16 @@ class Page_Translation extends Page
}
return $want;
}
-
+
+ /**
+ * Return list of existing tags needing translation. This calls
+ * the function defined by the module. which is expected to return
+ * an array serving as a list, where the KEYS are the tags expected,
+ * the value of each entry can be false if the tag is optional.
+ *
+ * @param string $subsection Name of subsection
+ * @return array|false List of tags as KEYS of array
+ */
private function loadUsedCustomTags($subsection)
{
if (!isset($this->customHandler['grep_'.$subsection]))
@@ -534,10 +541,10 @@ class Page_Translation extends Page
/**
* Get missing and unused counters for given module's templates.
*
- * @param type $lang lang to use
- * @param type $tags
- * @param type $module
- * @return array list(missingCount, unusedCount)
+ * @param string $lang lang to use
+ * @param array $tags Array of tags, where the tag names are the keys
+ * @param \Module|false $module the module to work with, defaults to the currently edited module
+ * @return array [missingCount, unusedCount]
*/
private function getModuleTemplateStatus($lang, $tags = false, $module = false)
{
@@ -553,8 +560,8 @@ class Page_Translation extends Page
* @param string $file the name of the translation file to load for checking
* @param boolean $fallback whether to check the global-tags of the main module as fallback
* @param array $tags list of tags that are expected to exist. Tags are the array keys!
- * @param \Module $module the module to work with, defaults to the currently edited module
- * @return array list(missingCount, unusedCount)
+ * @param \Module|false $module the module to work with, defaults to the currently edited module
+ * @return array [missingCount, unusedCount]
*/
private function getModuleTranslationStatus($lang, $file, $fallback, $tags, $module = false)
{
@@ -663,8 +670,6 @@ class Page_Translation extends Page
private function loadTemplateEditArray()
{
$tags = $this->loadUsedTemplateTags();
- if ($tags === false)
- return false;
$table = $this->buildTranslationTable('template-tags', array_keys($tags), true);
$global = Dictionary::getArray($this->module->getIdentifier(), 'global-tags', $this->destLang);
foreach ($table as &$entry) {
@@ -833,6 +838,12 @@ class Page_Translation extends Page
return $tags;
}
+ /**
+ * @param string $file Source dictionary
+ * @param string[]|false $requiredTags Tags that are considered required
+ * @param bool $findAlreadyTranslated If true, try to find a translation for this string in another language
+ * @return array numeric array suitable for passing to mustache
+ */
private function buildTranslationTable($file, $requiredTags = false, $findAlreadyTranslated = false)
{
$tags = array();
@@ -891,7 +902,7 @@ class Page_Translation extends Page
* user selected, then english, then everything else.
*
* @param string $file translation unit
- * @param type $tags list of tags, formatted as used in buildTranslationTable()
+ * @param array $tags list of tags, formatted as used in buildTranslationTable()
*/
private function findTranslationSamples($file, &$tags)
{
diff --git a/modules-available/vmstore/lang/de/template-tags.json b/modules-available/vmstore/lang/de/template-tags.json
index a7840aa7..16414809 100644
--- a/modules-available/vmstore/lang/de/template-tags.json
+++ b/modules-available/vmstore/lang/de/template-tags.json
@@ -1,8 +1,13 @@
{
+ "lang_cifsHelp1": "Ben\u00f6tigt wird ein CIFS-Share, z.B. von einem Windows Server, der f\u00fcr\r\nden Satellitenserver schreibbar, und f\u00fcr die Arbeitsstationen lesbar\r\nist.",
+ "lang_cifsHelp2": "Geben Sie f\u00fcr den Satellitenserver einen User mit Lese- und\r\nSchreibberechtigungen an. F\u00fcr die Clients sollte ein User angegeben\r\nwerden, der nur Leseberechtigungen auf dem Share besitzt. Am einfachsten\r\nerreichen Sie dies, indem Sie passwortlosen Gastzugriff mit Leserechten\r\nauf die Freigabe erlauben.",
+ "lang_cifsHelp3": "Wenn exklusiv DNBD3 verwendet wird, k\u00f6nnen Sie den passwortlosen\r\nGastzugriff deaktivieren und die Zeile \"Nur-Lese-Zugangsdaten\" leer\r\nlassen. Dies erh\u00f6ht die Sicherheit.",
"lang_configure": "Konfigurieren",
"lang_intern": "Intern",
"lang_nfsHelp1": "Ben\u00f6tigt wird ein NFSv4\/3-Share, der f\u00fcr den Satelliten-Server schreibbar, und f\u00fcr die Arbeitsstationen lesbar ist. Beispielkonfiguration auf dem NFS-Server, wenn der Satelliten-Server die Adresse 1.2.3.4 hat:",
- "lang_nfsHelp2": "Alternative Konfiguration mittels all_sqash. In diesem Fall muss das Verzeichnis auf dem Server dem Benutzer mit der uid 1234 geh\u00f6ren:",
+ "lang_nfsHelp2": "Alternative Konfiguration mittels all_squash. In diesem Fall muss das Verzeichnis auf dem Server dem Benutzer mit der uid 1234 geh\u00f6ren:",
+ "lang_nfsHelp3": "Die erste Zeile erlaubt den Lese- und Schreibzugriff des\r\nSatellitenservers. Die zweite Zeile erteilt allen anderen Rechnern\r\nausschlie\u00dflich Lesezugriff. Sie k\u00f6nnen dies nat\u00fcrlich auch auf\r\nspezielle Subnetze oder IP-Bereiche beschr\u00e4nken.",
+ "lang_nfsHelp4": "Wenn exklusiv DNBD3 verwendet wird, kann die zweite Zeile ausgelassen\r\nwerden. Dies erh\u00f6ht die Sicherheit.",
"lang_noAdditionalInformation": "Keine weitere Konfiguration notwendig",
"lang_password": "Passwort",
"lang_readOnly": "Nur-Lese-Zugangsdaten",
@@ -11,7 +16,8 @@
"lang_vmLocation": "VM Speicherort",
"lang_vmLocationChoose": "Bitte w\u00e4hlen Sie, wo die Images der Virtuellen Maschinen gespeichert werden sollen.",
"lang_vmLocationConfiguration": "VM Speicherort wird konfiguriert",
- "lang_vmLocationHelp1": "F\u00fcr Testzwecke k\u00f6nnen die VMs direkt auf dem Satellitenserver gespeichert werden. Sofern Sie jedoch die ausgelieferte Satelliten-vmdk betreiben bedenken Sie bitte, dass Sie dann nur ca. 100GB Speicher zur Verf\u00fcgung haben.",
- "lang_vmLocationHelp2": "Im Produktivbetrieb bietet es sich an, hierf\u00fcr einen performanten Netzwerkspeicher zu benutzen. Dieser Netzwerkspeicher kann per NFS oder CIFS\/SMB eingebunden werden. In jedem Fall muss sichergestellt werden, dass der Satellitenserver zum Hinzuf\u00fcgen neuer Virtueller Maschinen Schreibzugriff auf diesen Netzwerkspeicher hat. Bei der Nutzung von NFSv3 kann dies IP-Basiert eingerichtet werden, f\u00fcr die Nutzung von CIFS\/SMB k\u00f6nnen Sie Zugangsdaten angaben, die zum Schreiben berechtigen.",
- "lang_vmLocationHelp3": "Die bwLehrpool-Clients brauchen lediglich Lesezugriff auf den Netzwerkspeicher (und sollten aus Sicherheitsgr\u00fcnden auch wirklich nur lesen k\u00f6nnen). Bei CIFS\/SMB erreichen Sie dies am einfachsten, indem Sie passwortlosen Gastzugriff mit Leserechten auf die Freigabe erlauben."
+ "lang_vmLocationHelp1": "F\u00fcr Testzwecke k\u00f6nnen VMs direkt auf dem Satellitenserver gespeichert\r\nwerden. Sofern Sie den Satellitenserver ohne Anpassung der Virtuellen\r\nFestplatte betreiben, bedenken Sie bitte, dass nur ca. 40GB Speicher zur\r\nVerf\u00fcgung stehen.",
+ "lang_vmLocationHelp2": "Im Produktivbetrieb bietet es sich an, hierf\u00fcr einen performanten\r\nNetzwerkspeicher zu benutzen. Dieser Netzwerkspeicher kann per NFS oder\r\nCIFS\/SMB eingebunden werden. In jedem Fall muss sichergestellt werden,\r\ndass der Satellitenserver zum Hinzuf\u00fcgen neuer Virtueller Maschinen\r\nSchreibzugriff auf diesen Netzwerkspeicher hat. Bei der Nutzung von\r\nNFSv3 kann dies IP-Basiert eingerichtet werden, f\u00fcr die Nutzung von\r\nCIFS\/SMB k\u00f6nnen Sie Zugangsdaten angeben, die zum Schreiben\r\nberechtigen.",
+ "lang_vmLocationHelp3": "Im Fall von NFS und CIFS ben\u00f6tigen die bwLehrpool-Clients\r\nausschlie\u00dflich Lesezugriff auf den Netzwerkspeicher (und sollten aus\r\nSicherheitsgr\u00fcnden auch wirklich nur lesen k\u00f6nnen). Wenn Sie exklusiv\r\nDNBD3 verwenden, sind f\u00fcr die Clients keine Freigaben oder\r\nBerechtigungen notwendig, da der Zugriff \u00fcber den Sallitenserver\r\nstattfindet.",
+ "lang_vmLocationHelp4": "Sie k\u00f6nnen DNBD3 entweder exklusiv oder mit Fallback auf NFS\/CIFS verwenden. Im exklusiven Modus wird der Zugriff der Clients auf den kompletten VM-Speicher verhindert bzw. erschwert. Die Clients ben\u00f6tigen keinerlei Berechtigungen auf dem konfigurierten Share. Wenn Sie den Fallback Modus nutzen, werden f\u00fcr die Clients weiterhin Leseberechtigungen ben\u00f6tigt."
} \ No newline at end of file
diff --git a/modules-available/vmstore/lang/en/template-tags.json b/modules-available/vmstore/lang/en/template-tags.json
index b56cdd23..1072f10e 100644
--- a/modules-available/vmstore/lang/en/template-tags.json
+++ b/modules-available/vmstore/lang/en/template-tags.json
@@ -1,8 +1,13 @@
{
+ "lang_cifsHelp1": "Requires a CIFS\/SMB share that's writable for the satellite server and read-only for the clients (if not using DNBD3).",
+ "lang_cifsHelp2": "Please provide user credentials with read\/write permissions which will be used by the server. For the clients, user credentials that allow read-only access is required. You could also enable passwordless guest login for read-only access.",
+ "lang_cifsHelp3": "If you want to use DNBD3 in exclusive mode, you can leave the read only credentials empty, to prevent people from browsing the share.",
"lang_configure": "Configure",
"lang_intern": "Intern",
"lang_nfsHelp1": "An NFSv4\/3-Share is required. It should be readable by all the workstations, and writable for the satellite server. An example, assuming the satellite server has IP address 1.2.3.4:",
"lang_nfsHelp2": "Alternate configuration using all_squash. The exported directory should be owned (and be writable) by the user with uid 1234.",
+ "lang_nfsHelp3": "The first line allows read\/write access for the satellite server. The second line grants read-only access for every other IP address. You could limit the second line to specific IP ranges only if desired.",
+ "lang_nfsHelp4": "If using DNBD3 in exclusive mode, you can remove the second line completely, so only the satellite server has access to the NFS store.",
"lang_noAdditionalInformation": "No additional cofiguration required",
"lang_password": "Password",
"lang_readOnly": "Read-only Access",
@@ -13,5 +18,6 @@
"lang_vmLocationConfiguration": "VM location is configured",
"lang_vmLocationHelp1": "For test purposes, the VMs can be stored directly on the Satellite server. However, if you operate the delivered satellite vmdk please remember that you have only about 100GB of memory.",
"lang_vmLocationHelp2": "In productive operation, it makes sense for this to use a high-performance network storage. This network storage can be integrated via NFS or CIFS \/ SMB. In any case, it must be ensured that the satellite server has write access to this network storage to add a new Virtual Machine . When using NFSv3 this can be set up IP-based, for the use of CIFS \/ SMB, you can access data disclosures that would entitle them to write.",
- "lang_vmLocationHelp3": "The bwLehrpool clients only need read access to the network storage (and for security reasons, really can only read). In CIFS \/ SMB You can do this most easily by allowing passwordless guest access with read access to the share."
+ "lang_vmLocationHelp3": "The bwLehrpool clients only need read access to the network storage (and for security reasons, really can only read). In CIFS \/ SMB You can do this most easily by allowing passwordless guest access with read access to the share.",
+ "lang_vmLocationHelp4": "You can use DNBD3 exclusively or with NFS\/CIFS as fallback. In exclusive mode, you can deny direct access to the NFS\/CIFS store for clients, to prevent anyone from browsing the VM store directly. In fallback mode, the clients first try to use DNBD3 to run a VM and if that fails, they use NFS\/CIFS directly."
} \ No newline at end of file
diff --git a/modules-available/vmstore/templates/page-vmstore.html b/modules-available/vmstore/templates/page-vmstore.html
index 4a508e74..6156597b 100644
--- a/modules-available/vmstore/templates/page-vmstore.html
+++ b/modules-available/vmstore/templates/page-vmstore.html
@@ -39,10 +39,11 @@
<div class="panel panel-default">
<div class="panel-heading">
- <div class="radio">
+ <div class="radio radio-inline">
<input type="radio" name="storetype" value="cifs" {{pre-cifs}} id="id-cifs">
<label for="id-cifs">CIFS</label>
</div>
+ <a class="btn btn-default btn-sm" data-toggle="modal" data-target="#help-cifs"><span class="glyphicon glyphicon-question-sign"></span></a>
</div>
<div class="panel-body">
<label for="cifsaddr">UNC-Pfad</label>
@@ -73,7 +74,9 @@
</div>
</div>
</div>
- <button class="btn btn-primary pull-right" type="submit"><span class="glyphicon glyphicon-floppy-disk"></span> {{lang_save}}</button>
+ <div class="text-right">
+ <button class="btn btn-primary" type="submit"><span class="glyphicon glyphicon-floppy-disk"></span> {{lang_save}}</button>
+ </div>
</form>
@@ -94,6 +97,9 @@
<p>
{{lang_vmLocationHelp3}}
</p>
+ <p>
+ {{lang_vmLocationHelp4}}
+ </p>
</div>
</div>
</div>
@@ -121,6 +127,34 @@
/mnt/images 1.2.3.4(rw,all_squash,anonuid=1234,async)
/mnt/images *(ro,async)
</pre>
+ <p>
+ {{lang_nfsHelp3}}
+ </p>
+ <p>
+ {{lang_nfsHelp4}}
+ </p>
+ </div>
+ </div>
+ </div>
+</div>
+
+<div class="modal fade" id="help-cifs" tabindex="-1" role="dialog">
+ <div class="modal-dialog">
+ <div class="modal-content">
+ <div class="modal-header">
+ <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
+ CIFS/SMB
+ </div>
+ <div class="modal-body">
+ <p>
+ {{lang_cifsHelp1}}
+ </p>
+ <p>
+ {{lang_cifsHelp2}}
+ </p>
+ <p>
+ {{lang_cifsHelp3}}
+ </p>
</div>
</div>
</div>
diff --git a/modules-available/webinterface/lang/de/permissions.json b/modules-available/webinterface/lang/de/permissions.json
new file mode 100644
index 00000000..ee96810a
--- /dev/null
+++ b/modules-available/webinterface/lang/de/permissions.json
@@ -0,0 +1,5 @@
+{
+ "edit.https": "HTTPS Einstellungen bearbeiten.",
+ "edit.password": "Ändern, ob Passwortfelder in der Web-Schnittstelle maskiert werden sollen.",
+ "edit.design": "Seitentitel und Hintergrundfarbe des Logos bearbeiten."
+} \ No newline at end of file
diff --git a/modules-available/webinterface/lang/en/permissions.json b/modules-available/webinterface/lang/en/permissions.json
new file mode 100644
index 00000000..caf6d0cb
--- /dev/null
+++ b/modules-available/webinterface/lang/en/permissions.json
@@ -0,0 +1,5 @@
+{
+ "edit.https": "Edit HTTPS settings.",
+ "edit.password": "Change whether password fields should be masked or not.",
+ "edit.design": "Edit page title and logo background color."
+} \ No newline at end of file
diff --git a/modules-available/webinterface/page.inc.php b/modules-available/webinterface/page.inc.php
index 6dfc9faa..41636c19 100644
--- a/modules-available/webinterface/page.inc.php
+++ b/modules-available/webinterface/page.inc.php
@@ -10,19 +10,19 @@ class Page_WebInterface extends Page
protected function doPreprocess()
{
User::load();
- if (!User::hasPermission('superadmin')) {
+ if (!User::isLoggedIn()) {
Message::addError('main.no-permission');
Util::redirect('?do=Main');
}
switch (Request::post('action')) {
case 'https':
- $this->actionConfigureHttps();
+ if (User::hasPermission("edit.https")) $this->actionConfigureHttps();
break;
case 'password':
- $this->actionShowHidePassword();
+ if (User::hasPermission("edit.password")) $this->actionShowHidePassword();
break;
case 'customization':
- $this->actionCustomization();
+ if (User::hasPermission("edit.design")) $this->actionCustomization();
break;
}
}
@@ -123,6 +123,7 @@ class Page_WebInterface extends Page
}
}
$data[$type . 'Selected'] = true;
+ $data["editAllowed"] = User::hasPermission("edit.https");
Render::addTemplate('https', $data);
//
// Password fields
@@ -132,6 +133,7 @@ class Page_WebInterface extends Page
$data['selected_show'] = 'checked';
else
$data['selected_hide'] = 'checked';
+ $data["editAllowed"] = User::hasPermission("edit.password");
Render::addTemplate('passwords', $data);
$data = array('prefix' => Property::get('page-title-prefix'));
$data['colors'] = array_map(function ($i) { return array('color' => $i ? '#' . $i : '', 'text' => Render::readableColor($i)); },
@@ -148,6 +150,7 @@ class Page_WebInterface extends Page
if ($color) {
$data['colors'][] = array('color' => $color, 'selected' => 'selected');
}
+ $data["editAllowed"] = User::hasPermission("edit.design");
Render::addTemplate('customization', $data);
}
diff --git a/modules-available/webinterface/permissions/permissions.json b/modules-available/webinterface/permissions/permissions.json
new file mode 100644
index 00000000..45b5395d
--- /dev/null
+++ b/modules-available/webinterface/permissions/permissions.json
@@ -0,0 +1,5 @@
+[
+ "edit.https",
+ "edit.password",
+ "edit.design"
+] \ No newline at end of file
diff --git a/modules-available/webinterface/style.css b/modules-available/webinterface/style.css
new file mode 100644
index 00000000..7b86af56
--- /dev/null
+++ b/modules-available/webinterface/style.css
@@ -0,0 +1,7 @@
+.disabledPanel {
+ cursor: not-allowed;
+}
+.disabledPanel > .panel-body {
+ pointer-events: none;
+ opacity: 0.8;
+}
diff --git a/modules-available/webinterface/templates/customization.html b/modules-available/webinterface/templates/customization.html
index c949c1f2..ad57eea7 100644
--- a/modules-available/webinterface/templates/customization.html
+++ b/modules-available/webinterface/templates/customization.html
@@ -1,7 +1,7 @@
<form action="?do=WebInterface" method="post">
<input type="hidden" name="token" value="{{token}}">
<input type="hidden" name="action" value="customization">
- <div class="panel panel-default">
+ <div class="panel panel-default {{^editAllowed}}disabledPanel{{/editAllowed}}">
<div class="panel-heading">{{lang_customization}}</div>
<div class="panel-body">
<p>{{lang_customizationDesc}}</p>
diff --git a/modules-available/webinterface/templates/https.html b/modules-available/webinterface/templates/https.html
index f0accb57..a212cce3 100644
--- a/modules-available/webinterface/templates/https.html
+++ b/modules-available/webinterface/templates/https.html
@@ -1,7 +1,7 @@
<form action="?do=WebInterface" method="post">
<input type="hidden" name="token" value="{{token}}">
<input type="hidden" name="action" value="https">
- <div class="panel panel-default">
+ <div class="panel panel-default {{^editAllowed}}disabledPanel{{/editAllowed}}">
<div class="panel-heading">{{lang_httpsSettings}}</div>
<div class="panel-body">
<p>{{lang_httpsDescription}}</p>
diff --git a/modules-available/webinterface/templates/passwords.html b/modules-available/webinterface/templates/passwords.html
index e190bb72..1d73c172 100644
--- a/modules-available/webinterface/templates/passwords.html
+++ b/modules-available/webinterface/templates/passwords.html
@@ -1,7 +1,7 @@
<form action="?do=WebInterface" method="post">
<input type="hidden" name="token" value="{{token}}">
<input type="hidden" name="action" value="password">
- <div class="panel panel-default">
+ <div class="panel panel-default {{^editAllowed}}disabledPanel{{/editAllowed}}">
<div class="panel-heading">{{lang_passwordFields}}</div>
<div class="panel-body">
<p>{{lang_passwordsDescription}}</p>