summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--apis/cron.inc.php51
-rw-r--r--inc/property.inc.php58
-rw-r--r--inc/render.inc.php1
-rw-r--r--inc/taskmanager.inc.php2
-rw-r--r--modules-available/baseconfig_bwlp/lang/de/config-variables.json5
-rw-r--r--modules-available/baseconfig_bwlp/lang/en/config-variables.json5
-rw-r--r--modules-available/dozmod/lang/de/template-tags.json3
-rw-r--r--modules-available/dozmod/lang/en/template-tags.json3
-rw-r--r--modules-available/dozmod/page.inc.php49
-rw-r--r--modules-available/dozmod/templates/runtimeconfig.html35
-rw-r--r--modules-available/locations/inc/autolocation.inc.php35
-rw-r--r--modules-available/locations/page.inc.php34
-rw-r--r--modules-available/main/hooks/cron.inc.php15
-rw-r--r--modules-available/main/install.inc.php8
-rw-r--r--modules-available/roomplanner/inc/pvsgenerator.inc.php19
-rw-r--r--modules-available/statistics/install.inc.php8
-rw-r--r--modules-available/sysconfig/addmodule_adauth.inc.php14
-rw-r--r--modules-available/sysconfig/addmodule_custommodule.inc.php2
-rw-r--r--modules-available/sysconfig/addmodule_ldapauth.inc.php3
-rw-r--r--modules-available/sysconfig/hooks/cron.inc.php3
-rw-r--r--modules-available/sysconfig/inc/configmodulebaseldap.inc.php3
-rw-r--r--modules-available/sysconfig/inc/ldap.inc.php14
-rw-r--r--modules-available/sysconfig/lang/de/template-tags.json8
-rw-r--r--modules-available/sysconfig/lang/en/template-tags.json8
-rw-r--r--modules-available/sysconfig/templates/ad_ldap-homedir.html60
-rw-r--r--modules-available/sysconfig/templates/branding-check.html7
-rw-r--r--modules-available/systemstatus/page.inc.php40
-rw-r--r--modules-available/systemstatus/templates/_page.html9
-rw-r--r--script/install.js6
29 files changed, 377 insertions, 131 deletions
diff --git a/apis/cron.inc.php b/apis/cron.inc.php
index 8068eb2e..30d6d452 100644
--- a/apis/cron.inc.php
+++ b/apis/cron.inc.php
@@ -10,29 +10,54 @@
if (!isLocalExecution())
exit(0);
+define('CRON_KEY_STATUS', 'cron.key.status');
+
+function getJobStatus($id)
+{
+ // Re fetch from D on every call as some jobs could take longer
+ // and we don't want to work with stale data
+ $activeList = Property::getList(CRON_KEY_STATUS);
+ foreach ($activeList as $item) {
+ $entry = explode('|', $item, 2);
+ if (count($entry) !== 2 || $id !== $entry[0])
+ continue;
+ return array('start' => $entry[1], 'string' => $item);
+ }
+ return false;
+}
+
// Hooks by other modules
function handleModule($file)
{
include_once $file;
}
-foreach (glob('modules/*/hooks/cron.inc.php') as $file) {
+foreach (glob('modules/*/hooks/cron.inc.php', GLOB_NOSORT) as $file) {
preg_match('#^modules/([^/]+)/#', $file, $out);
$mod = Module::get($out[1]);
if ($mod === false)
continue;
+ $id = $mod->getIdentifier();
+ // Check if job is still running, or should be considered crashed
+ $status = getJobStatus($id);
+ if ($status !== false) {
+ $runtime = (time() - $status['start']);
+ if ($runtime < 0) {
+ // Clock skew
+ Property::removeFromList(CRON_KEY_STATUS, $status['string']);
+ } elseif ($runtime < 900) {
+ // Allow up to 15 minutes for a job to complete before we complain...
+ continue;
+ } else {
+ // Consider job crashed
+ Property::removeFromList(CRON_KEY_STATUS, $status['string']);
+ EventLog::failure('Cronjob for module ' . $id . ' seems to be stuck or has crashed. Check the php or web server error log.');
+ continue;
+ }
+ }
+ $now = time();
+ Property::addToList(CRON_KEY_STATUS, "$id|$now", 1800);
$mod->activate();
handleModule($file);
+ Property::removeFromList(CRON_KEY_STATUS, "$id|$now");
}
-
-switch (mt_rand(1, 10)) {
-case 3:
- Database::exec("DELETE FROM property WHERE dateline <> 0 AND dateline < UNIX_TIMESTAMP()");
- break;
-case 4:
- Database::exec("DELETE FROM callback WHERE (UNIX_TIMESTAMP() - dateline) > 86400");
- break;
-}
-
-Trigger::checkCallbacks();
-Trigger::ldadp();
diff --git a/inc/property.inc.php b/inc/property.inc.php
index 9adfbda3..b3d8081a 100644
--- a/inc/property.inc.php
+++ b/inc/property.inc.php
@@ -36,7 +36,7 @@ class Property
* Set value in property store.
*
* @param string $key key of value to set
- * @param type $value the value to store for $key
+ * @param string $value the value to store for $key
* @param int $maxAgeMinutes how long to keep this entry around at least, in minutes. 0 for infinite
*/
public static function set($key, $value, $maxAgeMinutes = 0)
@@ -54,6 +54,61 @@ class Property
}
}
+ /**
+ * Retrieve property list from the store.
+ *
+ * @param string $key Key of list to get all items for
+ * @return array All the items matching the key
+ */
+ public static function getList($key)
+ {
+ $res = Database::simpleQuery("SELECT dateline, value FROM property_list WHERE name = :key", compact('key'));
+ $NOW = time();
+ $return = array();
+ while ($row = $res->fetch(PDO::FETCH_ASSOC)) {
+ if ($row['dateline'] != 0 && $row['dateline'] < $NOW)
+ continue;
+ $return[] = $row['value'];
+ }
+ return $return;
+ }
+
+ /**
+ * Add item to property list.
+ *
+ * @param string $key key of value to set
+ * @param string $value the value to add for $key
+ * @param int $maxAgeMinutes how long to keep this entry around at least, in minutes. 0 for infinite
+ */
+ public static function addToList($key, $value, $maxAgeMinutes = 0)
+ {
+ Database::exec("INSERT INTO property_list (name, value, dateline) VALUES (:key, :value, :dateline)", array(
+ 'key' => $key,
+ 'value' => $value,
+ 'dateline' => ($maxAgeMinutes === 0 ? 0 : time() + ($maxAgeMinutes * 60))
+ ));
+ }
+
+ /**
+ * Remove given item from property list. If the list contains this item
+ * multiple times, they will all be removed.
+ *
+ * @param string $key Key of list
+ * @param string $value item to remove
+ * @return int number of items removed
+ */
+ public static function removeFromList($key, $value)
+ {
+ return Database::exec("DELETE FROM property_list WHERE name = :key AND value = :value", array(
+ 'key' => $key,
+ 'value' => $value,
+ ));
+ }
+
+ /*
+ * Legacy getters/setters
+ */
+
public static function getServerIp()
{
return self::get('server-ip', 'none');
@@ -185,7 +240,6 @@ class Property
return self::get('password-type', 'password');
}
-
public static function getIpxeDefault()
{
return self::get('default-ipxe');
diff --git a/inc/render.inc.php b/inc/render.inc.php
index 10419d6f..5515c659 100644
--- a/inc/render.inc.php
+++ b/inc/render.inc.php
@@ -88,6 +88,7 @@ class Render
<script src="script/bootstrap.min.js"></script>
<script src="script/taskmanager.js"></script>
<script src="script/fileselect.js"></script>
+ <script src="script/collapse.js"></script>
';
foreach ($modules as $module) {
$file = $module->getDir() . '/clientscript.js';
diff --git a/inc/taskmanager.inc.php b/inc/taskmanager.inc.php
index bd60e8ae..1920190f 100644
--- a/inc/taskmanager.inc.php
+++ b/inc/taskmanager.inc.php
@@ -100,7 +100,7 @@ class Taskmanager
* @param int $timeout maximum time in ms to wait for completion of task
* @return array result/status of task, or false if it couldn't be queried
*/
- public static function waitComplete($task, $timeout = 1500)
+ public static function waitComplete($task, $timeout = 2500)
{
if (is_array($task) && isset($task['id'])) {
if ($task['statusCode'] !== TASK_PROCESSING && $task['statusCode'] !== TASK_WAITING) {
diff --git a/modules-available/baseconfig_bwlp/lang/de/config-variables.json b/modules-available/baseconfig_bwlp/lang/de/config-variables.json
index 0252c377..63ddf280 100644
--- a/modules-available/baseconfig_bwlp/lang/de/config-variables.json
+++ b/modules-available/baseconfig_bwlp/lang/de/config-variables.json
@@ -11,11 +11,12 @@
"SLX_PROXY_MODE": "Legt fest, ob zum Zugriff aufs Internet ein Proxy-Server ben\u00f6tigt wird.\r\n*off* = keinen Proxy benutzen.\r\n*on* = Proxy immer benutzen.\r\n*auto* = Proxy nur benutzen, wenn sich der Client-PC in einem privaten Adressbereich befindet.",
"SLX_PROXY_PORT": "Der Port des zu verwendenden Proxy Servers.",
"SLX_PROXY_TYPE": "Art des Proxys: *socks4*, *socks5*, *http-connect* (HTTP Proxy mit Unterst\u00fctzung der CONNECT-Methode), *http-relay* (Klassischer HTTP Proxy)",
+ "SLX_REBOOT_SCHEDULE": "Feste Uhrzeit, zu der sich die Rechner neustarten, auch wenn noch ein Benutzer aktiv ist.\r\nMehrere Zeitpunkte k\u00f6nnen durch Leerzeichen getrennt angegeben werden.",
"SLX_REMOTE_LOG_SESSIONS": "Legt fest, ob Logins und Logouts der Benutzer an den Satelliten gemeldet werden sollen.\r\n*yes* = Mit Benutzerkennung loggen\r\n*anonymous* = Anonym loggen\r\n*no* = Nicht loggen",
"SLX_ROOT_PASS": "Das root-Passwort des Grundsystems. Wird nur f\u00fcr Diagnosezwecke am Client ben\u00f6tigt.\r\nFeld leer lassen, um root-Logins zu verbieten.\r\n\/Hinweis\/: Das Passwort wird im Klartext in der lokalen Datenbank hinterlegt, jedoch immer gehasht an die Clients \u00fcbermittelt (SHA-512 mit Salt). Wenn Sie das Passwort auch im Satelliten nicht im Klartext speichern wollen, k\u00f6nnen Sie hier auch ein vorgehashtes Passwort eintragen (im *$6$....*-Format).",
"SLX_SCREEN_STANDBY_TIMEOUT": "Zeit in Sekunden, nach der der Bildschirm bei Inaktivit\u00e4t des Rechners in den Standby-Modus versetzt wird.",
- "SLX_SHUTDOWN_SCHEDULE": "Feste Uhrzeit, zu der sich die Rechner ausschalten, auch wenn noch ein Benutzer aktiv ist.Mehrere Zeitpunkte k\u00f6nnen durch Leerzeichen getrennt angegeben werden.",
- "SLX_SHUTDOWN_TIMEOUT": "Zeit in Sekunden, nach dem ein Rechner abgeschaltet wird, sofern kein Benutzer angemeldet ist.Feld leer lassen, um die Funktion zu deaktivieren.",
+ "SLX_SHUTDOWN_SCHEDULE": "Feste Uhrzeit, zu der sich die Rechner ausschalten, auch wenn noch ein Benutzer aktiv ist.\r\nMehrere Zeitpunkte k\u00f6nnen durch Leerzeichen getrennt angegeben werden.",
+ "SLX_SHUTDOWN_TIMEOUT": "Zeit in Sekunden, nach dem ein Rechner abgeschaltet wird, sofern kein Benutzer angemeldet ist.\r\nFeld leer lassen, um die Funktion zu deaktivieren.",
"SLX_VMCHOOSER_FORLOCATION": "Legt das Verhalten fest, wenn es Veranstaltungen gibt, die an einen bestimmten Ort\/Raum gebunden sind.\r\n*IGNORE*: Mit den restlichen, globalen Veranstaltungen alphabetisch sortiert auflisten.\r\n*BUMP*: Die spezifischen Veranstaltungen oben auflisten, die globalen darunter.\r\n*EXCLUSIVE*: Spezifische Veranstaltungen oben auflisten, globale Veranstaltungen zun\u00e4chst ausblenden. Die globalen Veranstaltungen befinden sich unter einem eingeklappten Listenknoten.",
"SLX_VMCHOOSER_TAB": "Bestimmt, welcher Karteireiter im vmchooser standardm\u00e4\u00dfig ausgew\u00e4hlt wird.\r\n*0*: Native Linux-Sessions\r\n*1*: Nutzerspezifische Kurse\r\n*2*: Alle Kurse\r\n*AUTO*: Hat der Rechner beschr\u00e4nkte Ressourcen, werden die Linux-Sitzungen angezeigt, sonst alle Kurse\r\n\r\nHat der Benutzer ein persistentes Home-Verzeichnis, wirkt sich diese Einstellung nur beim ersten Anmelden aus. Bei sp\u00e4teren Sitzungen markiert der vmchooser die zuletzt gestartete Sitzung und wechselt zum entsprechenden Karteireiter.",
"SLX_VMCHOOSER_TEMPLATES": "Legt fest, wie Veranstaltungen in der Sortierung behandelt werden, welche auf eine VM linken, die eine Vorlage ist.\r\n*IGNORE*: Wie regul\u00e4re Veranstaltungen behandeln\r\n*BUMP*: Weiter oben in der Liste einsortieren"
diff --git a/modules-available/baseconfig_bwlp/lang/en/config-variables.json b/modules-available/baseconfig_bwlp/lang/en/config-variables.json
index 0d31dd62..ad1601c3 100644
--- a/modules-available/baseconfig_bwlp/lang/en/config-variables.json
+++ b/modules-available/baseconfig_bwlp/lang/en/config-variables.json
@@ -11,11 +11,12 @@
"SLX_PROXY_MODE": "Determines whether a proxy server is required to access the Internet.\r\n*off* = do not use a Proxy.\r\n*on* = Always use proxy.\r\n*auto* = Only use proxy when the client PC is in a private address space.",
"SLX_PROXY_PORT": "The port to use for the proxy server.",
"SLX_PROXY_TYPE": "Type of the proxy.*socks4*, *socks5*, *http-connect* (HTTP proxy with support from the CONNECT method), *http-relay* (Classic HTTP proxy)",
+ "SLX_REBOOT_SCHEDULE": "Fixed time to reboot the computer, even if there is a user active.\r\nSeveral times can be specified, separated by spaces.",
"SLX_REMOTE_LOG_SESSIONS": "Determines whether logins and logouts of the users should be reported to the satellite.\r\n*yes* = log with user ID\r\n*anonymous* = anonymous logging\r\n*no* = no logging",
"SLX_ROOT_PASS": "The root password of the client system. Only required for diagnostic purposes on the client.Leave field blank to disallow root logins.\r\n\/Hint\/: The password SHA-512-with-salt hashed before it's being sent to the client. It's only stored in clear text on the Satellite Server. If you want to have it hashed on the server too, you can supply a pre-hashed passoword in \/$6$...$...\/-format.",
"SLX_SCREEN_STANDBY_TIMEOUT": "Time in seconds after which the screen will enter power saving mode, if the client is not in use.",
- "SLX_SHUTDOWN_SCHEDULE": "Fixed time to turn off the computer, even if there is a user active.Several times can be specified, separated by spaces.",
- "SLX_SHUTDOWN_TIMEOUT": "Time in seconds after which a computer is switched off, if no user is logged on.Leave blank to disable the function.",
+ "SLX_SHUTDOWN_SCHEDULE": "Fixed time to turn off the computer, even if there is a user active.\r\nSeveral times can be specified, separated by spaces.",
+ "SLX_SHUTDOWN_TIMEOUT": "Time in seconds after which a computer is switched off, if no user is logged on.\r\nLeave blank to disable the function.",
"SLX_VMCHOOSER_FORLOCATION": "Defines how lectures special to the user's location are handled in the vmchooser.\r\n*IGNORE*: Sort them alphabetically among the global lectures.\r\n*BUMP*: Put them atop the global lectures.\r\n*EXCLUSIVE*: Put them atop the global lectures and aditionally collapse the node which contains the global lectures.",
"SLX_VMCHOOSER_TAB": "Defines which tab is show by default, if the user doesn't have stored a last used session on his persistent home directory.\r\n*0*: Native Linux sessions\r\n*1*: User specific lectures\r\n*2*: All lectures\r\n*AUTO*: If the computer has low system specs, show the Linux sessions, otherwise, show all lectures",
"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"
diff --git a/modules-available/dozmod/lang/de/template-tags.json b/modules-available/dozmod/lang/de/template-tags.json
index a7a91e11..b980e011 100644
--- a/modules-available/dozmod/lang/de/template-tags.json
+++ b/modules-available/dozmod/lang/de/template-tags.json
@@ -1,5 +1,7 @@
{
"lang_actionTarget": "Aktionsziel",
+ "lang_allowLoginByDefault": "Login standardm\u00e4\u00dfig erlauben",
+ "lang_allowLoginDescription": "Wenn diese Option aktiviert ist, k\u00f6nnen sich alle Mitarbeiter der Einrichtung \u00fcber die bwLehrpool-Suite anmelden und VMs\/Veranstaltungen verwalten. Wenn Sie diese Option deaktivieren, m\u00fcssen Sie in der Untersektion \"Benutzer und Berechtigungen\" jeden Benutzer nach dem ersten Loginversuch manuell freischalten.",
"lang_asteriskRequired": "Felder mit (*) sind erforderlich",
"lang_blockCount": "Anzahl Bl\u00f6cke",
"lang_canLogin": "Nutzer dieser Einrichtung k\u00f6nnen sich am Satelliten anmelden",
@@ -42,6 +44,7 @@
"lang_maxImageValidity": "G\u00fcltigkeitsdauer neuer VM-Versionen (Tage)",
"lang_maxLectureVisibility": "Sp\u00e4testes Enddatum einer Veranstaltung (Tage in der Zukunft)",
"lang_maxTransfers": "Maximale Zahl gleichzeitiger Up-\/Downloads pro Benutzer",
+ "lang_miscOptions": "Verschiedene Einstellungen",
"lang_name": "Name",
"lang_organization": "Einrichtung",
"lang_organizationList": "Liste der Einrichtungen",
diff --git a/modules-available/dozmod/lang/en/template-tags.json b/modules-available/dozmod/lang/en/template-tags.json
index 6e1a3996..0dfd1825 100644
--- a/modules-available/dozmod/lang/en/template-tags.json
+++ b/modules-available/dozmod/lang/en/template-tags.json
@@ -1,5 +1,7 @@
{
"lang_actionTarget": "Action target",
+ "lang_allowLoginByDefault": "Allow all staff members to login and use the bwLehrpool-Suite",
+ "lang_allowLoginDescription": "If this option is enabled, all members of the organization marked as staff or employee are allowed to login to this server and manage VMs\/courses. Otherwise, new users need to be individually allowed access after their first login attempt by visiting the sub page \"users and permissions\" in this web interface.",
"lang_asteriskRequired": "Fields marked with (*) are required",
"lang_blockCount": "Block count",
"lang_canLogin": "Members of this organization can login",
@@ -42,6 +44,7 @@
"lang_maxImageValidity": "New VM validity (days)",
"lang_maxLectureVisibility": "Max time lecture end date may lie in the future (days)",
"lang_maxTransfers": "Max concurrent transfers per user",
+ "lang_miscOptions": "Misc options",
"lang_name": "Name",
"lang_organization": "Organization",
"lang_organizationList": "List of organizations",
diff --git a/modules-available/dozmod/page.inc.php b/modules-available/dozmod/page.inc.php
index 6c0c8a6b..7f1e6ee3 100644
--- a/modules-available/dozmod/page.inc.php
+++ b/modules-available/dozmod/page.inc.php
@@ -89,29 +89,32 @@ class Page_DozMod extends Page
if ($section === 'runtimeconfig') {
// Runtime config
$runtimeConf = Database::queryFirst('SELECT value FROM sat.configuration WHERE parameter = :param', array('param' => 'runtimelimits'));
- if ($runtimeConf != null) {
+ if ($runtimeConf !== false) {
$runtimeConf = json_decode($runtimeConf['value'], true);
/* convert some value to corresponding "selected" texts */
if ($runtimeConf['defaultLecturePermissions']['edit']) {
- $runtimeConf['defaultLecturePermissions']['edit'] = 'checked="checked"';
+ $runtimeConf['defaultLecturePermissions']['edit'] = 'checked';
}
if ($runtimeConf['defaultLecturePermissions']['admin']) {
- $runtimeConf['defaultLecturePermissions']['admin'] = 'checked="checked"';
+ $runtimeConf['defaultLecturePermissions']['admin'] = 'checked';
}
if ($runtimeConf['defaultImagePermissions']['edit']) {
- $runtimeConf['defaultImagePermissions']['edit'] = 'checked="checked"';
+ $runtimeConf['defaultImagePermissions']['edit'] = 'checked';
}
if ($runtimeConf['defaultImagePermissions']['admin']) {
- $runtimeConf['defaultImagePermissions']['admin'] = 'checked="checked"';
+ $runtimeConf['defaultImagePermissions']['admin'] = 'checked';
}
if ($runtimeConf['defaultImagePermissions']['link']) {
- $runtimeConf['defaultImagePermissions']['link'] = 'checked="checked"';
+ $runtimeConf['defaultImagePermissions']['link'] = 'checked';
}
if ($runtimeConf['defaultImagePermissions']['download']) {
- $runtimeConf['defaultImagePermissions']['download'] = 'checked="checked"';
+ $runtimeConf['defaultImagePermissions']['download'] = 'checked';
}
+ if ($runtimeConf['allowLoginByDefault']) {
+ $runtimeConf['allowLoginByDefault'] = 'checked';
+ }
}
Render::addTemplate('runtimeconfig', $runtimeConf);
}
@@ -310,14 +313,29 @@ class Page_DozMod extends Page
$data['defaultLecturePermissions'] = Request::post('defaultLecturePermissions', NULL, "array");
$data['defaultImagePermissions'] = Request::post('defaultImagePermissions', NULL, "array");
- $intParams = [
- 'maxImageValidityDays' => array('min' => 7, 'max' => 999),
- 'maxLectureValidityDays' => array('min' => 7, 'max' => 999),
- 'maxTransfers' => array('min' => 1, 'max' => 10),
+ $params = [
+ 'int' => [
+ 'maxImageValidityDays' => array('min' => 7, 'max' => 999),
+ 'maxLectureValidityDays' => array('min' => 7, 'max' => 999),
+ 'maxTransfers' => array('min' => 1, 'max' => 10),
+ ],
+ 'bool' => [
+ 'allowLoginByDefault' => array('default' => true)
+ ],
];
- foreach($intParams as $field => $limits) {
- $value = Request::post($field, 0, 'int');
- $data[$field] = max(min($value, $limits['max']), $limits['min']);
+ foreach ($params as $type => $list) {
+ foreach ($list as $field => $limits) {
+ $default = isset($limits['default']) ? $limits['default'] : false;
+ $value = Request::post($field, $default);
+ settype($value, $type);
+ if (isset($limits['min']) && $value < $limits['min']) {
+ $value = $limits['min'];
+ }
+ if (isset($limits['max']) && $value > $limits['max']) {
+ $value = $limits['max'];
+ }
+ $data[$field] = $value;
+ }
}
/* ensure types */
@@ -327,9 +345,6 @@ class Page_DozMod extends Page
settype($data['defaultImagePermissions']['admin'], 'boolean');
settype($data['defaultImagePermissions']['link'], 'boolean');
settype($data['defaultImagePermissions']['download'], 'boolean');
- settype($data['maxImageValidityDays'], 'int');
- settype($data['maxLectureValidityDays'], 'int');
- settype($data['maxTransfers'], 'int');
$data = json_encode($data);
Database::exec('INSERT INTO sat.configuration (parameter, value)'
diff --git a/modules-available/dozmod/templates/runtimeconfig.html b/modules-available/dozmod/templates/runtimeconfig.html
index e538dee8..9bdc44b0 100644
--- a/modules-available/dozmod/templates/runtimeconfig.html
+++ b/modules-available/dozmod/templates/runtimeconfig.html
@@ -91,6 +91,17 @@
</table>
</fieldset>
+ <fieldset>
+ <h3>{{lang_miscOptions}}</h3>
+ <div class="checkbox">
+ <input type="hidden" name="allowLoginByDefault" value="0">
+ <input type="checkbox" name="allowLoginByDefault" value="1" {{allowLoginByDefault}} id ="allowLoginByDefault" class="form-control">
+ <label>
+ {{lang_allowLoginByDefault}}
+ </label>
+ <p><i>{{lang_allowLoginDescription}}</i></p>
+ </div>
+ </fieldset>
<br>
<input type="hidden" name="token" value="{{token}}">
@@ -99,27 +110,3 @@
</form>
</div>
</div>
-
-<script type="text/javascript"><!--
-function slxTestConfig() {
- $('#test-button').prop('disabled', true);
- $('#test-spin').css('display', '');
- var str = $('#mailconf').serialize();
- str += '&button=test';
- console.log(str);
- $.post('?do=DozMod', str).done(function(data) {
- console.log('Success');
- console.log(data);
- checkRes(data);
- }).fail(function() {
- checkRes('DozMod refused the connection');
- }).always(function() {
- $('#test-button').prop('disabled', false);
- $('#test-spin').css('display', 'none');
- });
- }
-
- function checkRes(text) {
- $('#test-output').css('display', '').text(text);
- }
-// --> </script>
diff --git a/modules-available/locations/inc/autolocation.inc.php b/modules-available/locations/inc/autolocation.inc.php
new file mode 100644
index 00000000..cccfe9b1
--- /dev/null
+++ b/modules-available/locations/inc/autolocation.inc.php
@@ -0,0 +1,35 @@
+<?php
+
+class AutoLocation
+{
+
+ public static function rebuildAll()
+ {
+ if (Module::get('statistics') === false)
+ return; // Nothing to do
+ $res = Database::simpleQuery("SELECT machineuuid, clientip FROM machine");
+ $updates = array();
+ $nulls = array();
+ while ($row = $res->fetch(PDO::FETCH_ASSOC)) {
+ $loc = Location::mapIpToLocation($row['clientip']);
+ if ($loc === false) {
+ $nulls[] = $row['machineuuid'];
+ } else {
+ if (!isset($updates[$loc])) {
+ $updates[$loc] = array();
+ }
+ $updates[$loc][] = $row['machineuuid'];
+ }
+ }
+ if (!empty($nulls)) {
+ $qs = '?' . str_repeat(',?', count($nulls) - 1);
+ Database::exec("UPDATE machine SET subnetlocationid = NULL WHERE machineuuid IN ($qs)", $nulls);
+ }
+ foreach ($updates as $lid => $machines) {
+ $qs = '?' . str_repeat(',?', count($machines) - 1);
+ $lid = (int)$lid;
+ Database::exec("UPDATE machine SET subnetlocationid = $lid WHERE machineuuid IN ($qs)", $machines);
+ }
+ }
+
+}
diff --git a/modules-available/locations/page.inc.php b/modules-available/locations/page.inc.php
index 26612099..20af7b63 100644
--- a/modules-available/locations/page.inc.php
+++ b/modules-available/locations/page.inc.php
@@ -26,36 +26,6 @@ class Page_Locations extends Page
}
}
- private function updateAutoLocationId()
- {
- if (Module::get('statistics') === false)
- return; // Nothing to do
- $res = Database::simpleQuery("SELECT machineuuid, clientip FROM machine");
- $updates = array();
- $nulls = array();
- while ($row = $res->fetch(PDO::FETCH_ASSOC)) {
- $loc = Location::mapIpToLocation($row['clientip']);
- if ($loc === false) {
- $nulls[] = $row['machineuuid'];
- } else {
- if (!isset($updates[$loc])) {
- $updates[$loc] = array();
- }
- $updates[$loc][] = $row['machineuuid'];
- }
- }
- error_log(print_r($updates, true));
- if (!empty($nulls)) {
- $qs = '?' . str_repeat(',?', count($nulls) - 1);
- Database::exec("UPDATE machine SET subnetlocationid = NULL WHERE machineuuid IN ($qs)", $nulls);
- }
- foreach ($updates as $lid => $machines) {
- $qs = '?' . str_repeat(',?', count($machines) - 1);
- $lid = (int)$lid;
- Database::exec("UPDATE machine SET subnetlocationid = $lid WHERE machineuuid IN ($qs)", $machines);
- }
- }
-
private function updateSubnets()
{
$count = 0;
@@ -85,7 +55,7 @@ class Page_Locations extends Page
$count += $stmt->rowCount();
}
}
- $this->updateAutoLocationId();
+ AutoLocation::rebuildAll();
Message::addSuccess('subnets-updated', $count);
Util::redirect('?do=Locations');
}
@@ -156,7 +126,7 @@ class Page_Locations extends Page
$change |= $this->updateLocationData($location);
if ($change) {
// In case subnets or tree layout changed, recalc this
- $this->updateAutoLocationId();
+ AutoLocation::rebuildAll();
}
Util::redirect('?do=Locations');
}
diff --git a/modules-available/main/hooks/cron.inc.php b/modules-available/main/hooks/cron.inc.php
new file mode 100644
index 00000000..bab27287
--- /dev/null
+++ b/modules-available/main/hooks/cron.inc.php
@@ -0,0 +1,15 @@
+<?php
+
+switch (mt_rand(1, 10)) {
+case 2:
+ Database::exec("DELETE FROM property_list WHERE dateline <> 0 AND dateline < UNIX_TIMESTAMP()");
+ break;
+case 3:
+ Database::exec("DELETE FROM property WHERE dateline <> 0 AND dateline < UNIX_TIMESTAMP()");
+ break;
+case 4:
+ Database::exec("DELETE FROM callback WHERE (UNIX_TIMESTAMP() - dateline) > 86400");
+ break;
+}
+
+Trigger::checkCallbacks();
diff --git a/modules-available/main/install.inc.php b/modules-available/main/install.inc.php
index 4c9d4baa..e364a905 100644
--- a/modules-available/main/install.inc.php
+++ b/modules-available/main/install.inc.php
@@ -26,6 +26,14 @@ $res[] = tableCreate('property', "
KEY `dateline` (`dateline`)
");
+$res[] = tableCreate('property_list', "
+ `name` varchar(50) NOT NULL,
+ `dateline` int(10) unsigned NOT NULL DEFAULT '0',
+ `value` text NOT NULL,
+ KEY (`name`),
+ KEY `dateline` (`dateline`)
+");
+
$res[] = tableCreate('user', "
`userid` int(10) unsigned NOT NULL AUTO_INCREMENT,
`login` varchar(100) NOT NULL,
diff --git a/modules-available/roomplanner/inc/pvsgenerator.inc.php b/modules-available/roomplanner/inc/pvsgenerator.inc.php
index c00d5439..d61e826b 100644
--- a/modules-available/roomplanner/inc/pvsgenerator.inc.php
+++ b/modules-available/roomplanner/inc/pvsgenerator.inc.php
@@ -16,6 +16,8 @@ class PvsGenerator
/* get all rooms */
$rooms = array();
+ // Use left joins everywhere so we still have the complete list of locations below
+ // for figuring out which locations are leafs and which aren't
$ret = Database::simpleQuery(
'SELECT l.locationid, l.parentlocationid, l.locationname, lr.locationid AS notnull, lr.managerip, lr.tutoruuid, m.clientip as tutorip '
. 'FROM location l '
@@ -27,12 +29,27 @@ class PvsGenerator
settype($row['parentlocationid'], 'int');
$rooms[$row['locationid']] = $row;
}
+ // Mark all non-leafs as skip
foreach ($rooms as &$room) {
if ($room['parentlocationid'] > 0 && isset($rooms[$room['parentlocationid']])) {
$rooms[$room['parentlocationid']]['skip'] = true; // Don't just unset, might be wrong order
}
}
- unset($room); // refd!
+ // Now un-mark all where there's at least one child without valid room plan
+ foreach ($rooms as &$room) {
+ if (!isset($room['skip']) && (is_null($room['notnull']) || empty($room['managerip']))) {
+ $room['skip'] = true;
+ $r2 =& $room;
+ while ($r2['parentlocationid'] > 0) {
+ $r2 =& $rooms[$r2['parentlocationid']];
+ if (!(is_null($room['notnull']) || empty($room['managerip']))) {
+ unset($r2['skip']);
+ break;
+ }
+ }
+ }
+ }
+ unset($room, $r2); // refd!
/* collect names and build room blocks - filter empty rooms while at it */
$roomNames = array();
diff --git a/modules-available/statistics/install.inc.php b/modules-available/statistics/install.inc.php
index 0729d676..7baf046e 100644
--- a/modules-available/statistics/install.inc.php
+++ b/modules-available/statistics/install.inc.php
@@ -155,6 +155,14 @@ if ($addTrigger) {
if ($ret === false) {
finalResponse(UPDATE_FAILED, 'Adding locationid trigger to machine failed: ' . Database::lastError());
}
+ // This might be an update - calculate all subnetlocationid values (if location module is installed yet)
+ if (Module::isAvailable('locations')) {
+ if (tableExists('subnet')) {
+ AutoLocation::rebuildAll();
+ } else {
+ finalResponse(UPDATE_RETRY, 'Locations module not installed yet, retry later');
+ }
+ }
}
// Create response
diff --git a/modules-available/sysconfig/addmodule_adauth.inc.php b/modules-available/sysconfig/addmodule_adauth.inc.php
index 666c36d1..82df5bad 100644
--- a/modules-available/sysconfig/addmodule_adauth.inc.php
+++ b/modules-available/sysconfig/addmodule_adauth.inc.php
@@ -140,10 +140,12 @@ class AdAuth_SelfSearch extends AddModule_Base
} else {
$uri = "ldap://$server:3268/";
}
+
+ $selfSearchBase = Ldap::getSelfSearchBase($binddn, $searchbase);
// Set up selfSearch task
$taskData = array(
'server' => $uri,
- 'searchbase' => $searchbase,
+ 'searchbase' => $selfSearchBase,
'bindpw' => $bindpw,
);
if (preg_match(AD_SHORT_REGEX, $binddn, $out) && !empty($out[2])) {
@@ -153,12 +155,12 @@ class AdAuth_SelfSearch extends AddModule_Base
$this->originalBindDn = $binddn;
$taskData['filter'] = 'sAMAccountName=' . $out[1];
} elseif (preg_match('/^cn\=([^\=]+),.*?,dc\=([^\=]+),/i', Ldap::normalizeDn($binddn), $out)) {
- if (empty($searchbase)) {
+ if (empty($selfSearchBase)) {
$this->originalBindDn = $out[2] . '\\' . $out[1];
$taskData['filter'] = 'sAMAccountName=' . $out[1];
} else {
$this->originalBindDn = $binddn;
- $taskData['filter'] = "distinguishedName=$binddn";
+ $taskData['filter'] = 'distinguishedName=' . Ldap::normalizeDn($binddn);
}
} else {
Message::addError('could-not-determine-binddn', $binddn);
@@ -232,11 +234,12 @@ class AdAuth_HomeAttrCheck extends AddModule_Base
} else {
$uri = "ldap://$server:$port/";
}
+ $selfSearchBase = Ldap::getSelfSearchBase($binddn, $searchbase);
preg_match('#^(\w+\=[^\=]+),#', $binddn, $out);
$filter = $out[1];
$data = array(
'server' => $uri,
- 'searchbase' => $searchbase,
+ 'searchbase' => $selfSearchBase,
'binddn' => $binddn,
'bindpw' => $bindpw,
'filter' => $filter
@@ -425,7 +428,8 @@ class AdAuth_HomeDir extends AddModule_Base
public static function getAttributes()
{
- return array('shareRemapMode', 'shareRemapCreate', 'shareDocuments', 'shareDownloads', 'shareDesktop', 'shareMedia', 'shareOther', 'shareHomeDrive');
+ return array('shareRemapMode', 'shareRemapCreate', 'shareDocuments', 'shareDownloads', 'shareDesktop',
+ 'shareMedia', 'shareOther', 'shareHomeDrive', 'shareDomain', 'credentialPassthrough');
}
}
diff --git a/modules-available/sysconfig/addmodule_custommodule.inc.php b/modules-available/sysconfig/addmodule_custommodule.inc.php
index 3f112c95..7c3ccf0f 100644
--- a/modules-available/sysconfig/addmodule_custommodule.inc.php
+++ b/modules-available/sysconfig/addmodule_custommodule.inc.php
@@ -123,7 +123,7 @@ class CustomModule_CompressModule extends AddModule_Base
'inputFiles' => array($tempfile),
'outputFile' => $destFile
), true);
- $status = Taskmanager::waitComplete($this->taskId);
+ $status = Taskmanager::waitComplete($this->taskId, 5000);
unlink($tempfile);
if (!isset($status['statusCode'])) {
$this->tmError();
diff --git a/modules-available/sysconfig/addmodule_ldapauth.inc.php b/modules-available/sysconfig/addmodule_ldapauth.inc.php
index 2bd4b584..c61c710c 100644
--- a/modules-available/sysconfig/addmodule_ldapauth.inc.php
+++ b/modules-available/sysconfig/addmodule_ldapauth.inc.php
@@ -212,7 +212,8 @@ class LdapAuth_HomeDir extends AddModule_Base
public static function getAttributes()
{
- return array('shareRemapMode', 'shareRemapCreate', 'shareDocuments', 'shareDownloads', 'shareDesktop', 'shareMedia', 'shareOther', 'shareHomeDrive');
+ return array('shareRemapMode', 'shareRemapCreate', 'shareDocuments', 'shareDownloads', 'shareDesktop',
+ 'shareMedia', 'shareOther', 'shareHomeDrive', 'shareDomain', 'credentialPassthrough');
}
}
diff --git a/modules-available/sysconfig/hooks/cron.inc.php b/modules-available/sysconfig/hooks/cron.inc.php
new file mode 100644
index 00000000..d1f91437
--- /dev/null
+++ b/modules-available/sysconfig/hooks/cron.inc.php
@@ -0,0 +1,3 @@
+<?php
+
+Trigger::ldadp(); \ No newline at end of file
diff --git a/modules-available/sysconfig/inc/configmodulebaseldap.inc.php b/modules-available/sysconfig/inc/configmodulebaseldap.inc.php
index 760593e1..8e42478e 100644
--- a/modules-available/sysconfig/inc/configmodulebaseldap.inc.php
+++ b/modules-available/sysconfig/inc/configmodulebaseldap.inc.php
@@ -7,7 +7,8 @@ abstract class ConfigModuleBaseLdap extends ConfigModule
private static $REQUIRED_FIELDS = array('server', 'searchbase');
private static $OPTIONAL_FIELDS = array('binddn', 'bindpw', 'home', 'ssl', 'fingerprint', 'certificate', 'homeattr',
- 'shareRemapMode', 'shareRemapCreate', 'shareDocuments', 'shareDownloads', 'shareDesktop', 'shareMedia', 'shareOther', 'shareHomeDrive');
+ 'shareRemapMode', 'shareRemapCreate', 'shareDocuments', 'shareDownloads', 'shareDesktop', 'shareMedia',
+ 'shareOther', 'shareHomeDrive', 'shareDomain', 'credentialPassthrough');
protected function generateInternal($tgz, $parent)
{
diff --git a/modules-available/sysconfig/inc/ldap.inc.php b/modules-available/sysconfig/inc/ldap.inc.php
index ed471f31..23b24885 100644
--- a/modules-available/sysconfig/inc/ldap.inc.php
+++ b/modules-available/sysconfig/inc/ldap.inc.php
@@ -8,4 +8,18 @@ class Ldap
return trim(preg_replace('/[,;]\s*/', ',', $dn));
}
+ public static function getSelfSearchBase($binddn, $searchbase)
+ {
+ // 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
+ $searchbase = $out[1];
+ }
+ return $searchbase;
+ }
+
}
diff --git a/modules-available/sysconfig/lang/de/template-tags.json b/modules-available/sysconfig/lang/de/template-tags.json
index b2d5dfd0..4618aa08 100644
--- a/modules-available/sysconfig/lang/de/template-tags.json
+++ b/modules-available/sysconfig/lang/de/template-tags.json
@@ -28,6 +28,8 @@
"lang_confirmDeleteQuestion": "Wollen Sie dieses Element wirklich l\u00f6schen?",
"lang_connectionWait": "\u00dcberpr\u00fcfe Verbindung, bitte warten",
"lang_continueAnyway": "Trotzdem weiter",
+ "lang_credPassingNotes": "Wenn Sie diese Option aktivieren, werden Nutzername und Passwort des angemeldeten Benutzers an das Startskript der gew\u00e4hlten Veranstaltung \u00fcbergeben. Somit kann der Ersteller der Veranstaltung mit seinem Script beim Start der VM automatisiert weitere Dienste ansteuern, die eine Authentifizierung erfordern. Sie sollten diese Funktion nur aktivieren, wenn Sie der Personengruppe, die Veranstaltungen bearbeiten kann, entsprechend vertrauen.",
+ "lang_credentialPassing": "Zugangsdaten des Nutzers an das Startscript der Veranstaltung \u00fcbergeben.",
"lang_customCertificate": "Zur Validierung zus\u00e4tzlich erforderliche (Intermediate-)Zertifikate",
"lang_customModuleInfo1": "\u00dcber ein benutzerdefiniertes Modul ist es m\u00f6glich, beliebige Dateien zum Linux-Grundsystem, das auf den Clients gebootet wird, hinzuzuf\u00fcgen. Dazu kann ein Archiv mit einer Dateisystemstruktur hochgeladen werden, die in dieser Form 1:1 in das gebootete Linux extrahiert wird.",
"lang_customModuleInfo2": "Beispiel: Enth\u00e4lt das hochgeladene Archiv eine Datei etc\/beispiel.conf, so wird auf einem gebooteten Client diese Datei als \/etc\/beispiel.conf zu finden sein.",
@@ -36,11 +38,12 @@
"lang_dnLookup": "Ermitteln der Bind-DN",
"lang_download": "Herunterladen",
"lang_downloadLong": "Dieses Modul \"so wie es ist\" herunterladen.",
+ "lang_driveLetterNote": "WICHTIG: Bitte w\u00e4hlen Sie einen Laufwerksbuchstaben, der in den eingesetzten VMs verf\u00fcgbar ist, da ansonsten auf einen anderen Buchstaben ausgewichen werden muss.",
"lang_editLong": "Modul oder Konfiguration bearbeiten.",
"lang_editingLocationInfo": "Sie setzen die Konfiguration eines bestimmten Raums\/Orts, nicht die globale Konfiguration",
"lang_folderRedirection": "Folder Redirection",
"lang_generateModule": "Modul erzeugen",
- "lang_handlingNotes": "Hier k\u00f6nnen Sie festlegen, wie Netzwerk-Shares (inkl. des Home-Verzeichnisses) an Virtuelle Maschinen durchgereicht werden. In \u00e4lteren Versionen von bwLehrpool wurden die VMware Shared Folders genutzt, was mit bestimmten file servern Probleme verursachen konnte. Der neue native Modus funktioniert deutlich besser, ist aber bei Windows-G\u00e4sten darauf angewiesen, dass (1) der file server smb\/cifs spricht (z.B. Windows Server, Samba unter Linux) und (2) die openslx.exe im Autostart eingebunden ist (bei den bwLehrpool Vorlagen bereits der Fall). Der native Modus mit Fallback auf VMware ist experimentell und kann dazu f\u00fchren, dass die VM in regelm\u00e4\u00dfigen Abst\u00e4nden H\u00e4nger hat. WICHTIG: Bitte w\u00e4hlen Sie einen Laufwerksbuchstaben, der in den eingesetzten VMs verf\u00fcgbar ist, da ansonsten auf einen anderen Buchstaben ausgewichen werden muss.",
+ "lang_handlingNotes": "Hier k\u00f6nnen Sie festlegen, wie Netzwerk-Shares (inkl. des Home-Verzeichnisses) an Virtuelle Maschinen durchgereicht werden. In \u00e4lteren Versionen von bwLehrpool wurden die VMware Shared Folders genutzt, was mit bestimmten file servern Probleme verursachen konnte. Der neue native Modus funktioniert deutlich besser, ist aber bei Windows-G\u00e4sten darauf angewiesen, dass (1) der file server smb\/cifs spricht (z.B. Windows Server, Samba unter Linux) und (2) die openslx.exe im Autostart eingebunden ist (bei den bwLehrpool Vorlagen bereits der Fall).",
"lang_helpHomeAttrHead": "Name des Home-Verzeichnis-Attributs",
"lang_helpHomeAttrText": "Hier k\u00f6nnen Sie alternativ zum fest vorgegebenem Template des Home-Verzeichnis Servers den Attributsnamen im Active Directory angeben, der diesen Pfad bereitstellt. Normalerweise ist dies \"homeDirectory\". Wird das Feld leer gelassen, versucht der Assistent, das Attribut selbstst\u00e4ndig zu ermitteln. Falls das Einbinden der Home-Verzeichnisse anschlie\u00dfend nicht funktioniert, \u00fcberpr\u00fcfen Sie bitte den Client-Log (Status->Client Log) und den LDAP-Proxy-Log (Status->Server Status).",
"lang_helpModuleConfiguration": "Konfigurationsmodule sind die Bausteine, aus denen eine Systemkonfiguration erstellt wird. Hier lassen sich sowohl generische Module durch einen Wizard anlegen, als auch komplett eigene Module erstellen (fortgeschritten, Linuxkenntnisse erforderlich).",
@@ -87,10 +90,13 @@
"lang_selfSignedNote": "Das Zertifikat des Servers scheint selbst signiert zu sein. Wenn Sie fortfahren wird versucht, die Zertifikatskette vom Server abzufragen. Dies ist in den meisten F\u00e4llen erfolgreich, sollte aber nur getan werden wenn Sie wissen, dass das Zertifikat des Servers von einer unbekannten CA signiert wurde. Falls die Authentifizierung anschlie\u00dfend nicht funktioniert, \u00fcberpr\u00fcfen Sie die LDAP-Proxy Logs auf der Serverstatus-Seite.",
"lang_shareDesktop": "Desktop (Achtung: Vom Dozent angelegte Verkn\u00fcpfungen nicht sichtbar!)",
"lang_shareDocuments": "Eigene Dokumente",
+ "lang_shareDomainLabel": "Dom\u00e4nenname",
+ "lang_shareDomainNote": "Der Dom\u00e4nenname wird beim Einbinden des Home-Verzeichnisses dem Benutzernamen vorangestellt (DOMAIN\\user). Normalerweise wird der Dom\u00e4nenname automatisch ermittelt, er l\u00e4sst sich hiermit aber explizit \u00fcberschreiben.",
"lang_shareDownloads": "Downloads",
"lang_shareHomeDrive": "Home-Verzeichnis Buchstabe (Windows)",
"lang_shareMapCreate": "Ordner auf dem Netzlaufwerk bei Bedarf anlegen",
"lang_shareMedia": "Eigene Musik, Videos, Bilder",
+ "lang_shareModeNote": "\"Nativer Modus mit Fallback auf VMware\" ist experimentell und kann dazu f\u00fchren, dass die VM in regelm\u00e4\u00dfigen Abst\u00e4nden H\u00e4nger hat.",
"lang_shareOther": "Andere (Saved Games, Kontakte, Favoriten, ...)",
"lang_shareRemapMode": "Einbindemodus",
"lang_show": "Ansehen",
diff --git a/modules-available/sysconfig/lang/en/template-tags.json b/modules-available/sysconfig/lang/en/template-tags.json
index 15516bf2..9b399f04 100644
--- a/modules-available/sysconfig/lang/en/template-tags.json
+++ b/modules-available/sysconfig/lang/en/template-tags.json
@@ -28,6 +28,8 @@
"lang_confirmDeleteQuestion": "Are you sure you want to delete this entry?",
"lang_connectionWait": "Checking connection, please wait",
"lang_continueAnyway": "Continue anyway",
+ "lang_credPassingNotes": "If you enable this option, the username and password of the logged in user will be passed to the start script inside the VM, which is supplied by the tutor who created the lecture. This can be used to automatically authenticate the user to additional services by script. You should only enable this option if you trust the group of users eligible to edit lectures.",
+ "lang_credentialPassing": "Pass user credentials to start script.",
"lang_customCertificate": "Additional (intermediate) certificates required for certificate validation",
"lang_customModuleInfo1": "About a custom module, it is possible to add arbitrary files to a Linux system that is booted clients. For this purpose, an archive can be uploaded using a file system structure that is extracted in this form 1:1 in the booted Linux.",
"lang_customModuleInfo2": "Example: If the uploaded archive is the file etc\/example.conf, this file will be located as \/etc\/example.conf to a booted client.",
@@ -36,11 +38,12 @@
"lang_dnLookup": "Looking up bind dn",
"lang_download": "Download",
"lang_downloadLong": "Download module \"as is\".",
+ "lang_driveLetterNote": "IMPORTANT: Pick a drive letter for the home directory that will be free in the Virtual Machines. Otherwise, a random letter will be assigned.",
"lang_editLong": "Edit module or configuration.",
"lang_editingLocationInfo": "You're setting the configuration for a specific location, not the global one",
"lang_folderRedirection": "Folder Redirection",
"lang_generateModule": "Generating module",
- "lang_handlingNotes": "Here you can configure how network shares (like the user's home directory) are mapped inside the VM. Old Versions of bwLehrpool used the VMware Shared Folder technique, which could cause problems with certain file servers. The new \"native mode\" works much better, but on Windows guests, it requires that you (1) use an smb\/cifs file server (Windows Server, Linux with Samba) and (2) have openslx.exe setup to autorun in the VM (this is already configured for bwLehrpool templates). Native mode with fallback is experimental and known to cause temporary freezes with some VMs. Use with care. IMPORTANT: Pick a drive letter for the home directory that will be free in the Virtual Machines. Otherwise, a random letter will be assigned.",
+ "lang_handlingNotes": "Here you can configure how network shares (like the user's home directory) are mapped inside the VM. Old Versions of bwLehrpool used the VMware Shared Folder technique, which could cause problems with certain file servers. The new \"native mode\" works much better, but on Windows guests, it requires that you (1) use an smb\/cifs file server (Windows Server, Linux with Samba) and (2) have openslx.exe setup to autorun in the VM (this is already configured for bwLehrpool templates).",
"lang_helpHomeAttrHead": "Name of the home directory attribute",
"lang_helpHomeAttrText": "Here you can specify the name of the attribute on the Active Directory that contains the path of the home directory server. Usually this is \"homeDirectory\". If you leave this blank, the wiszard will try to determine the attribute name automatically. If home directories don't work, check the client log (Status->Client log) and the LDAP proxy log (Status->Server status).",
"lang_helpModuleConfiguration": "Configuration modules are the building blocks from which a system configuration is created. Here you can create both generic modules by a wizard, as well as create completely custom modules (advanced Linux knowledge required).",
@@ -87,10 +90,13 @@
"lang_selfSignedNote": "The certificate of this server cannot be verified using the builtin trust store. If you know that the server's certificate was signed by an unknown CA, you can try to proceed. The chain will then be extracted from the server, which should be successful in most cases. If the authentication module does not work afterwards, check the LDAP-proxy logs on the server status page.",
"lang_shareDesktop": "Desktop (Might hide shortcuts created by the tutor)",
"lang_shareDocuments": "My Documents",
+ "lang_shareDomainLabel": "Domain name",
+ "lang_shareDomainNote": "The user name will be prefixed by the domain when trying to mount home directories (DOMAIN\\user). Usually this will be determined automatically, but you can always override it here.",
"lang_shareDownloads": "Downloads",
"lang_shareHomeDrive": "Home drive letter (Windows)",
"lang_shareMapCreate": "Create folders on network share if they don't exist",
"lang_shareMedia": "My Music, Videos, Pictures",
+ "lang_shareModeNote": "\"Native mode with fallback\" is experimental and known to cause temporary freezes with some VMs. Use with care.",
"lang_shareOther": "Other (Saved Games, Contacts, Favorites, ...)",
"lang_shareRemapMode": "Mapping mode",
"lang_show": "Show",
diff --git a/modules-available/sysconfig/templates/ad_ldap-homedir.html b/modules-available/sysconfig/templates/ad_ldap-homedir.html
index de64e49e..2ced563d 100644
--- a/modules-available/sysconfig/templates/ad_ldap-homedir.html
+++ b/modules-available/sysconfig/templates/ad_ldap-homedir.html
@@ -1,8 +1,3 @@
-<div class="slx-bold">
- {{lang_homedirHandling}}
-</div>
-<div><i>{{lang_handlingNotes}}</i></div>
-
<!-- 'shareRemapMode', 'shareRemapCreate', 'shareDocuments', 'shareDownloads', 'shareDesktop', 'shareMedia', 'shareOther' -->
<form method="post" class="form-horizontal" action="?do=SysConfig&amp;action=addmodule&amp;step={{next}}">
@@ -21,6 +16,17 @@
{{/ssl}}
<input name="fingerprint" value="{{fingerprint}}" type="hidden">
+ <div class="slx-bold">{{lang_credentialPassing}}</div>
+ <div class="checkbox">
+ <input type="checkbox" class="form-control" id="inputcredentialPassthrough" name="credentialPassthrough">
+ <label for="inputcredentialPassthrough">{{lang_credentialPassing}}</label>
+ </div>
+ <div><i>{{lang_credPassingNotes}}</i></div>
+
+ <hr>
+ <div class="slx-bold">{{lang_homedirHandling}}</div>
+ <div><i>{{lang_handlingNotes}}</i></div>
+
<div class="form-group row">
<label for="inputshareRemapMode" class="control-label col-xs-4">{{lang_shareRemapMode}}</label>
<div class="col-xs-8">
@@ -30,6 +36,14 @@
<option value="3" {{shareRemapMode_3}}>{{lang_mapModeVmware}}</option>
<option value="2" {{shareRemapMode_2}}>{{lang_mapModeNativeFallback}}</option>
</select>
+ <p><i>{{lang_shareModeNote}}</i></p>
+ </div>
+ </div>
+ <div class="form-group row">
+ <label for="inputshareDomain" class="control-label col-xs-4">{{lang_shareDomainLabel}}</label>
+ <div class="col-xs-8">
+ <input type="text" class="form-control" id="inputshareDomain" name="shareDomain">
+ <p><i>{{lang_shareDomainNote}}</i></p>
</div>
</div>
<div class="form-group row">
@@ -40,31 +54,37 @@
<option {{selected}}>{{drive}}</option>
{{/drives}}
</select>
+ <p><i>{{lang_driveLetterNote}}</i></p>
</div>
</div>
+
<hr>
<div class="slx-bold">{{lang_folderRedirection}}</div>
<div><i>{{lang_redirectionWarning}}</i></div>
- <div>
- <label class="control-label"><input type="checkbox" name="shareDocuments" {{shareDocuments_c}}> {{lang_shareDocuments}}</label>
+
+ <div class="checkbox">
+ <input id="shareDocuments" type="checkbox" class="form-control" name="shareDocuments" {{shareDocuments_c}}>
+ <label for="shareDocuments">{{lang_shareDocuments}}</label>
</div>
- <div>
- <label class="control-label"><input type="checkbox" name="shareDownloads" {{shareDownloads_c}}> {{lang_shareDownloads}}</label>
+ <div class="checkbox">
+ <input id="shareDownloads" type="checkbox" class="form-control" name="shareDownloads" {{shareDownloads_c}}>
+ <label for="shareDownloads">{{lang_shareDownloads}}</label>
</div>
- <div>
- <label class="control-label"><input type="checkbox" name="shareDesktop" {{shareDesktop_c}}> {{lang_shareDesktop}}</label>
+ <div class="checkbox">
+ <input id="shareDesktop" type="checkbox" class="form-control" name="shareDesktop" {{shareDesktop_c}}>
+ <label for="shareDesktop">{{lang_shareDesktop}}</label>
</div>
- <div>
- <label class="control-label"><input type="checkbox" name="shareMedia" {{shareMedia_c}}> {{lang_shareMedia}}</label>
+ <div class="checkbox">
+ <input id="shareMedia" type="checkbox" class="form-control" name="shareMedia" {{shareMedia_c}}>
+ <label for="shareMedia">{{lang_shareMedia}}</label>
</div>
- <div>
- <label class="control-label"><input type="checkbox" name="shareOther" {{shareOther_c}}> {{lang_shareOther}}</label>
+ <div class="checkbox">
+ <input id="shareOther" type="checkbox" class="form-control" name="shareOther" {{shareOther_c}}>
+ <label for="shareOther">{{lang_shareOther}}</label>
</div>
- <div class="row">
- <div class="col-xs-2"></div>
- <div class="col-xs-10">
- <label class="control-label"><input type="checkbox" name="shareRemapCreate" {{shareRemapCreate_c}}> {{lang_shareMapCreate}}</label>
- </div>
+ <div class="checkbox">
+ <input id="shareRemapCreate" type="checkbox" class="form-control" name="shareRemapCreate" {{shareRemapCreate_c}}>
+ <label for="shareRemapCreate">{{lang_shareMapCreate}}</label>
</div>
<div class="pull-right">
<button type="submit" class="btn btn-primary">{{lang_next}} &raquo;</button>
diff --git a/modules-available/sysconfig/templates/branding-check.html b/modules-available/sysconfig/templates/branding-check.html
index 8f6ef055..1a021309 100644
--- a/modules-available/sysconfig/templates/branding-check.html
+++ b/modules-available/sysconfig/templates/branding-check.html
@@ -21,6 +21,11 @@
<label for="title-id">{{lang_title}}</label>
<input type="text" name="title" value="{{title}}" id ="title-id" class="form-control" placeholder="Name des Moduls">
</div>
- <button type="submit" class="btn btn-primary">{{lang_save}}</button>
+ <div class="btn-group">
+ <a class="btn btn-default" href="?do=SysConfig&action=addmodule&step=Branding_Start">{{lang_cancel}}</a>
+ </div>
+ <div class="btn-group pull-right">
+ <button type="submit" class="btn btn-primary">{{lang_save}}</button>
+ </div>
</form>
</div>
diff --git a/modules-available/systemstatus/page.inc.php b/modules-available/systemstatus/page.inc.php
index bcce816b..b9fef0fd 100644
--- a/modules-available/systemstatus/page.inc.php
+++ b/modules-available/systemstatus/page.inc.php
@@ -266,7 +266,39 @@ class Page_SystemStatus extends Page
} else {
$start = strpos($data, "\n") + 1;
}
- echo '<pre>', htmlspecialchars(substr($data, $start)), '</pre>';
+ echo '<pre>', htmlspecialchars(substr($data, $start), ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8'), '</pre>';
+ }
+
+ protected function ajaxLighttpdLog()
+ {
+ $fh = @fopen('/var/log/lighttpd/error.log', 'r');
+ if ($fh === false) {
+ echo 'Error opening log file';
+ return;
+ }
+ fseek($fh, -6000, SEEK_END);
+ $data = fread($fh, 6000);
+ @fclose($fh);
+ if ($data === false) {
+ echo 'Error reading from log file';
+ return;
+ }
+ // If we could read less, try the .1 file too
+ $amount = 6000 - strlen($data);
+ if ($amount > 100) {
+ $fh = @fopen('/var/log/lighttpd/error.log.1', 'r');
+ if ($fh !== false) {
+ fseek($fh, -$amount, SEEK_END);
+ $data = fread($fh, $amount) . $data;
+ @fclose($fh);
+ }
+ }
+ if (strlen($data) < 5990) {
+ $start = 0;
+ } else {
+ $start = strpos($data, "\n") + 1;
+ }
+ echo '<pre>', htmlspecialchars(substr($data, $start), ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8'), '</pre>';
}
protected function ajaxLdadpLog()
@@ -303,7 +335,7 @@ class Page_SystemStatus extends Page
} else {
$start = strpos($data, "\n") + 1;
}
- echo '<pre>', htmlspecialchars(substr($data, $start)), '</pre>';
+ echo '<pre>', htmlspecialchars(substr($data, $start), ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8'), '</pre>';
}
}
@@ -319,7 +351,7 @@ class Page_SystemStatus extends Page
else
$data = 'Taskmanager error';
- echo '<pre>', htmlspecialchars($data), '</pre>';
+ echo '<pre>', htmlspecialchars($data, ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8'), '</pre>';
}
protected function ajaxPsList()
@@ -334,7 +366,7 @@ class Page_SystemStatus extends Page
else
$data = 'Taskmanager error';
- echo '<pre>', htmlspecialchars($data), '</pre>';
+ echo '<pre>', htmlspecialchars($data, ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8'), '</pre>';
}
private function usageColor($percent)
diff --git a/modules-available/systemstatus/templates/_page.html b/modules-available/systemstatus/templates/_page.html
index 51aa5b55..0573a20c 100644
--- a/modules-available/systemstatus/templates/_page.html
+++ b/modules-available/systemstatus/templates/_page.html
@@ -97,6 +97,14 @@
</div>
<div class="panel panel-default">
<div class="panel-heading">
+ {{lang_lighttpdLog}}
+ </div>
+ <div class="panel-body" id="lighttpd-log">
+ <span class="glyphicon glyphicon-refresh slx-rotation"></span>
+ </div>
+</div>
+<div class="panel panel-default">
+ <div class="panel-heading">
netstat -tulpn
</div>
<div class="panel-body" id="netstat">
@@ -124,6 +132,7 @@
$('#netstat').load('?do=SystemStatus&action=Netstat');
$('#pslist').load('?do=SystemStatus&action=PsList');
$('#ldadp-log').load('?do=SystemStatus&action=LdadpLog');
+ $('#lighttpd-log').load('?do=SystemStatus&action=LighttpdLog');
}, 300);
}, false);
</script>
diff --git a/script/install.js b/script/install.js
index a85f869c..9738f1a2 100644
--- a/script/install.js
+++ b/script/install.js
@@ -77,7 +77,7 @@ var slxTrigger = function (elem, moduleName) {
//alert('always: ' + moduleName + ', status: ' + slxModules[moduleName] + ', current: ' + slxCurrent);
if (slxModules[moduleName] === 'WORKING') {
slxModules[moduleName] = 'UPDATE_FAILED';
- $('#mod-' + moduleName).text('UPDATE_FAILED (No response from server)');
+ $('#mod-' + moduleName).text('UPDATE_FAILED (No response from server)').css('color', '#c00');
}
if (slxCurrent === moduleName) {
slxCurrent = false;
@@ -112,7 +112,9 @@ function slxRunNext(lastModule) {
slxRun(next);
} else {
slxCancelTimer();
- alert('Done.');
+ setTimeout(function() {
+ alert('Done.');
+ }, 10);
}
}