summaryrefslogtreecommitdiffstats
path: root/modules-available/dozmod/pages
diff options
context:
space:
mode:
Diffstat (limited to 'modules-available/dozmod/pages')
-rw-r--r--modules-available/dozmod/pages/actionlog.inc.php163
-rw-r--r--modules-available/dozmod/pages/expiredimages.inc.php97
-rw-r--r--modules-available/dozmod/pages/ldapfilters.inc.php119
-rw-r--r--modules-available/dozmod/pages/mailconfig.inc.php96
-rw-r--r--modules-available/dozmod/pages/networkrules.inc.php98
-rw-r--r--modules-available/dozmod/pages/networkshares.inc.php108
-rw-r--r--modules-available/dozmod/pages/runscripts.inc.php133
-rw-r--r--modules-available/dozmod/pages/runtimeconfig.inc.php112
-rw-r--r--modules-available/dozmod/pages/templates.inc.php139
-rw-r--r--modules-available/dozmod/pages/users.inc.php128
10 files changed, 1193 insertions, 0 deletions
diff --git a/modules-available/dozmod/pages/actionlog.inc.php b/modules-available/dozmod/pages/actionlog.inc.php
new file mode 100644
index 00000000..a014ddf7
--- /dev/null
+++ b/modules-available/dozmod/pages/actionlog.inc.php
@@ -0,0 +1,163 @@
+<?php
+
+class SubPage
+{
+
+ private static $action;
+ private static $uuid;
+
+ public static function doPreprocess()
+ {
+ User::assertPermission("actionlog.view");
+ self::$action = Request::get('action', '', 'string');
+ if (self::$action !== '' && self::$action !== 'showtarget' && self::$action !== 'showuser') {
+ Util::traceError('Invalid action for actionlog: "' . self::$action . '"');
+ }
+ self::$uuid = Request::get('uuid', '', 'string');
+ }
+
+ public static function doRender()
+ {
+ Render::addTemplate('actionlog-header');
+ if (self::$action === '') {
+ self::generateLog("SELECT al.dateline, al.targetid, al.description,"
+ . " img.displayname AS imgname, tu.firstname AS tfirstname, tu.lastname AS tlastname, l.displayname AS lecturename,"
+ . " al.userid AS uuserid, usr.firstname AS ufirstname, usr.lastname AS ulastname"
+ . " FROM sat.actionlog al"
+ . " LEFT JOIN sat.imagebase img ON (img.imagebaseid = targetid)"
+ . " LEFT JOIN sat.user usr ON (usr.userid = al.userid)"
+ . " LEFT JOIN sat.user tu ON (tu.userid = al.targetid)"
+ . " LEFT JOIN sat.lecture l ON (l.lectureid = targetid)"
+ . " ORDER BY al.dateline DESC LIMIT 500", array(), true, true);
+ } elseif (self::$action === 'showuser') {
+ self::listUser();
+ } else {
+ self::listTarget();
+ }
+ }
+
+ private static function listUser()
+ {
+ // Query user
+ $user = Database::queryFirst('SELECT userid, firstname, lastname, email, lastlogin,'
+ . ' organization.displayname AS orgname FROM sat.user'
+ . ' LEFT JOIN sat.organization USING (organizationid)'
+ . ' WHERE userid = :uuid'
+ . ' LIMIT 1', array('uuid' => self::$uuid));
+ if ($user === false) {
+ Message::addError('unknown-userid', self::$uuid);
+ Util::redirect('?do=dozmod&section=actionlog');
+ }
+ // Mangle date and render
+ $user['lastlogin_s'] = date('d.m.Y H:i', $user['lastlogin']);
+ Render::addTemplate('actionlog-user', $user);
+ // Finally add the actionlog
+ self::generateLog("SELECT al.dateline, al.targetid, al.description,"
+ . " img.displayname AS imgname, usr.firstname AS tfirstname, usr.lastname AS tlastname, l.displayname AS lecturename"
+ . " FROM sat.actionlog al"
+ . " LEFT JOIN sat.imagebase img ON (img.imagebaseid = targetid)"
+ . " LEFT JOIN sat.user usr ON (usr.userid = targetid)"
+ . " LEFT JOIN sat.lecture l ON (l.lectureid = targetid)"
+ . " WHERE al.userid = :uuid"
+ . " ORDER BY al.dateline DESC LIMIT 500", array('uuid' => self::$uuid), false, true);
+ }
+
+ private static function listTarget()
+ {
+ // We have to guess what kind of target it is
+ if (!self::addImageHeader()
+ && !self::addLectureHeader()) {
+ Message::addError('unknown-targetid', self::$uuid);
+ // Keep going, there might still be log entries for a deleted uuid
+ }
+
+ // Finally add the actionlog
+ self::generateLog("SELECT al.dateline, al.userid AS uuserid, al.description,"
+ . " usr.firstname AS ufirstname, usr.lastname AS ulastname"
+ . " FROM sat.actionlog al"
+ . " LEFT JOIN sat.user usr ON (usr.userid = al.userid)"
+ . " WHERE al.targetid = :uuid"
+ . " ORDER BY al.dateline DESC LIMIT 500", array('uuid' => self::$uuid), true, false);
+ }
+
+ private static function addImageHeader()
+ {
+ $image = Database::queryFirst('SELECT o.userid AS ouserid, o.firstname AS ofirstname, o.lastname AS olastname,'
+ . ' u.userid AS uuserid, u.firstname AS ufirstname, u.lastname AS ulastname,'
+ . ' img.displayname, img.description, img.createtime, img.updatetime,'
+ . ' os.displayname AS osname'
+ . ' FROM sat.imagebase img'
+ . ' LEFT JOIN sat.user o ON (img.ownerid = o.userid)'
+ . ' LEFT JOIN sat.user u ON (img.updaterid = u.userid)'
+ . ' LEFT JOIN sat.operatingsystem os ON (img.osid = os.osid)'
+ . ' WHERE img.imagebaseid = :uuid'
+ . ' LIMIT 1', array('uuid' => self::$uuid));
+ if ($image !== false) {
+ // Mangle date and render
+ $image['createtime_s'] = date('d.m.Y H:i', $image['createtime']);
+ $image['updatetime_s'] = date('d.m.Y H:i', $image['updatetime']);
+ $image['descriptionHtml'] = nl2br(htmlspecialchars($image['description']));
+ Render::addTemplate('actionlog-image', $image);
+ }
+ return $image !== false;
+ }
+
+ private static function addLectureHeader()
+ {
+ $lecture = Database::queryFirst('SELECT o.userid AS ouserid, o.firstname AS ofirstname, o.lastname AS olastname,'
+ . ' u.userid AS uuserid, u.firstname AS ufirstname, u.lastname AS ulastname,'
+ . ' l.displayname, l.description, l.createtime, l.updatetime,'
+ . ' img.displayname AS imgname, img.imagebaseid'
+ . ' FROM sat.lecture l'
+ . ' LEFT JOIN sat.user o ON (l.ownerid = o.userid)'
+ . ' LEFT JOIN sat.user u ON (l.updaterid = u.userid)'
+ . ' LEFT JOIN sat.imageversion ver ON (ver.imageversionid = l.imageversionid)'
+ . ' LEFT JOIN sat.imagebase img ON (img.imagebaseid = ver.imagebaseid)'
+ . ' WHERE l.lectureid = :uuid'
+ . ' LIMIT 1', array('uuid' => self::$uuid));
+ if ($lecture !== false) {
+ // Mangle date and render
+ $lecture['createtime_s'] = date('d.m.Y H:i', $lecture['createtime']);
+ $lecture['updatetime_s'] = date('d.m.Y H:i', $lecture['updatetime']);
+ $lecture['descriptionHtml'] = nl2br(htmlspecialchars($lecture['description']));
+ Render::addTemplate('actionlog-lecture', $lecture);
+ }
+ return $lecture !== false;
+ }
+
+ private static function generateLog($query, $params, $showActor, $showTarget)
+ {
+ // query action log
+ $res = Database::simpleQuery($query, $params);
+ $events = array();
+ while ($row = $res->fetch(PDO::FETCH_ASSOC)) {
+ $row['dateline_s'] = date('d.m.Y H:i', $row['dateline']);
+ if (isset($row['imgname'])) {
+ $row['targeturl'] = '?do=dozmod&section=actionlog&action=showtarget&uuid=' . $row['targetid'];
+ $row['targetname'] = $row['imgname'];
+ } elseif (isset($row['tlastname'])) {
+ $row['targeturl'] = '?do=dozmod&section=actionlog&action=showuser&uuid=' . $row['targetid'];
+ $row['targetname'] = $row['tlastname'] . ', ' . $row['tfirstname'];
+ } elseif (isset($row['lecturename'])) {
+ $row['targeturl'] = '?do=dozmod&section=actionlog&action=showtarget&uuid=' . $row['targetid'];
+ $row['targetname'] = $row['lecturename'];
+ }
+ $events[] = $row;
+ }
+ $data = array('events' => $events);
+ if ($showActor) {
+ $data['showActor'] = true;
+ }
+ if ($showTarget) {
+ $data['showTarget'] = true;
+ }
+
+ Render::addTemplate('actionlog-log', $data);
+ }
+
+ public static function doAjax()
+ {
+
+ }
+
+} \ No newline at end of file
diff --git a/modules-available/dozmod/pages/expiredimages.inc.php b/modules-available/dozmod/pages/expiredimages.inc.php
new file mode 100644
index 00000000..2b5a2274
--- /dev/null
+++ b/modules-available/dozmod/pages/expiredimages.inc.php
@@ -0,0 +1,97 @@
+<?php
+
+class SubPage
+{
+
+ public static function doPreprocess()
+ {
+ $action = Request::post('action', false, 'string');
+
+ if ($action === 'delimages') {
+ if (User::hasPermission("expiredimages.delete")) {
+ $result = self::handleDeleteImages();
+ if (!empty($result)) {
+ Message::addInfo('delete-images', $result);
+ }
+ Util::redirect('?do=DozMod');
+ }
+ }
+ }
+
+ private static function handleDeleteImages()
+ {
+ $images = Request::post('images', false);
+ if (is_array($images)) {
+ foreach ($images as $image => $val) {
+ if (strtolower($val) !== 'on')
+ continue;
+ Database::exec("UPDATE sat.imageversion SET deletestate = 'WANT_DELETE'"
+ . " WHERE deletestate = 'SHOULD_DELETE' AND imageversionid = :imageversionid", array(
+ 'imageversionid' => $image
+ ));
+ }
+ if (!empty($images)) {
+ $ret = Download::asStringPost('http://127.0.0.1:9080/do/delete-images', false, 10, $code);
+ if ($code == 999) {
+ $ret .= "\nConnection to DMSD failed.";
+ }
+ return $ret;
+ }
+ }
+ return false;
+ }
+
+ private static function loadExpiredImages()
+ {
+ $res = Database::simpleQuery("SELECT b.displayname,"
+ . " own.firstname, own.lastname, own.email,"
+ . " v.imageversionid, v.createtime, v.filesize, v.deletestate,"
+ . " lat.expiretime AS latexptime, lat.deletestate AS latdelstate"
+ . " FROM sat.imageversion v"
+ . " INNER JOIN sat.imagebase b ON (b.imagebaseid = v.imagebaseid)"
+ . " INNER JOIN sat.user own ON (b.ownerid = own.userid)"
+ . " LEFT JOIN sat.imageversion lat ON (b.latestversionid = lat.imageversionid)"
+ . " WHERE v.deletestate <> 'KEEP'"
+ . " ORDER BY b.displayname ASC, v.createtime ASC");
+ $NOW = time();
+ $rows = array();
+ while ($row = $res->fetch(PDO::FETCH_ASSOC)) {
+ if ($row['latexptime'] > $NOW && $row['latdelstate'] === 'KEEP') {
+ $row['hasNewerClass'] = 'glyphicon-ok green';
+ $row['checked'] = 'checked';
+ } else {
+ $row['hasNewerClass'] = 'glyphicon-remove red';
+ }
+ if ($row['deletestate'] === 'WANT_DELETE') {
+ $row['name_extra_class'] = 'slx-strike';
+ }
+ $row['version'] = date('d.m.Y H:i:s', $row['createtime']);
+ $row['rawfilesize'] = $row['filesize'];
+ $row['filesize'] = Util::readableFileSize($row['filesize']);
+ $rows[] = $row;
+ }
+ return $rows;
+ }
+
+ public static function doRender()
+ {
+ $expiredImages = self::loadExpiredImages();
+
+ if (empty($expiredImages)) {
+ Message::addSuccess('no-expired-images');
+ } else {
+ Render::addTemplate('images-delete', array('images' => $expiredImages, 'allowedDelete' => User::hasPermission("expiredimages.delete")));
+ }
+ }
+
+ public static function doAjax()
+ {
+ $action = Request::post('action');
+ if ($action === 'delimages') {
+ User::assertPermission("expiredimages.delete");
+ die(self::handleDeleteImages());
+ }
+ die('Huh?');
+ }
+
+}
diff --git a/modules-available/dozmod/pages/ldapfilters.inc.php b/modules-available/dozmod/pages/ldapfilters.inc.php
new file mode 100644
index 00000000..d0ae41b8
--- /dev/null
+++ b/modules-available/dozmod/pages/ldapfilters.inc.php
@@ -0,0 +1,119 @@
+<?php
+
+class SubPage
+{
+ private static $show;
+
+ public static function doPreprocess()
+ {
+ self::$show = Request::any('show', false, 'string');
+ $action = Request::post('action');
+
+ if ($action === 'deleteFilter') {
+ User::assertPermission("ldapfilters.save");
+ self::deleteLdapFilter();
+ } else if ($action === 'saveFilter') {
+ User::assertPermission("ldapfilters.save");
+ self::saveLdapFilter();
+ }
+ User::assertPermission("ldapfilters.view");
+ }
+
+ public static function doRender()
+ {
+ if (self::$show === false) {
+ // Get all ldapfilters from the sat db.
+ $ldapfilters = Database::queryAll("SELECT filterid, filtername, filterkey, filtervalue FROM sat.presetlecturefilter
+ WHERE filtertype ='LDAP' ORDER BY filtername ASC");
+
+ $data = array(
+ 'ldapfilters' => $ldapfilters,
+ 'hasEditPermission' => User::hasPermission('ldapfilters.save')
+ );
+
+ Render::addTemplate('ldapfilters', $data);
+ } else if (self::$show === 'edit') {
+ $filterid = Request::get('filterid', false, 'int');
+
+ if ($filterid === false) {
+ Render::addTemplate('ldapfilter-add', array(
+ 'filterid' => 0
+ ));
+ } else {
+ $ldapfilter = Database::queryFirst("SELECT filterid, filtername, filterkey, filtervalue FROM sat.presetlecturefilter
+ WHERE filterid = :id AND filtertype = 'LDAP'", array( 'id' => $filterid));
+ // TODO: Show error if not exists
+
+ Render::addTemplate('ldapfilter-add', $ldapfilter);
+ }
+ }
+ }
+
+ private static function deleteLdapFilter() {
+ User::assertPermission('ldapfilters.save');
+ $filterid = Request::post('filterid', false, 'int');
+ if ($filterid === false) {
+ Message::addError('ldap-filter-id-missing');
+ return;
+ }
+ $res = Database::exec("DELETE FROM sat.presetlecturefilter WHERE filterid = :id AND filtertype = 'LDAP'", array('id' => $filterid));
+ if ($res !== 1) {
+ Message::addWarning('ldap-invalid-filter-id', $filterid);
+ } else {
+ Message::addSuccess('ldap-filter-deleted');
+ }
+ }
+
+ private static function saveLdapFilter() {
+ $filterid = Request::post('filterid', '', 'int');
+ $filtername = Request::post('filtername', false, 'string');
+ $filterattribute = Request::post('attribute', false, 'string');
+ $filtervalue = Request::post('value', false, 'string');
+
+ if ($filtername === false || $filterattribute === false || $filtervalue === false) {
+ Message::addError('ldap-filter-save-missing-information');
+ return;
+ }
+
+ if ($filterid === 0) {
+ // Insert filter in the db.
+ $res = Database::exec("INSERT INTO sat.presetlecturefilter (filtertype, filtername, filterkey, filtervalue)
+ VALUES ('LDAP', :filtername, :attribute, :value)", array(
+ 'filtername' => $filtername,
+ 'attribute' => $filterattribute,
+ 'value' => $filtervalue
+ ));
+
+ if ($res !== 1) {
+ Message::addError('ldap-filter-insert-failed');
+ } else {
+ Message::addSuccess('ldap-filter-created');
+ }
+
+ } else {
+ // Update filter in the db.
+ $res = Database::exec("UPDATE sat.presetlecturefilter SET
+ filtername = :filtername, filterkey = :attribute, filtervalue = :value
+ WHERE filterid = :filterid AND filtertype = 'LDAP'", array(
+ 'filterid' => $filterid,
+ 'filtername' => $filtername,
+ 'attribute' => $filterattribute,
+ 'value' => $filtervalue
+ ));
+
+ if ($res !== 1) {
+ Message::addError('ldap-filter-insert-failed');
+ } else {
+ Message::addSuccess('ldap-filter-saved');
+ }
+
+ }
+ Util::redirect("?do=dozmod&section=ldapfilters");
+ }
+
+ public static function doAjax()
+ {
+
+ }
+
+} \ No newline at end of file
diff --git a/modules-available/dozmod/pages/mailconfig.inc.php b/modules-available/dozmod/pages/mailconfig.inc.php
new file mode 100644
index 00000000..08205f2e
--- /dev/null
+++ b/modules-available/dozmod/pages/mailconfig.inc.php
@@ -0,0 +1,96 @@
+<?php
+
+class SubPage
+{
+
+ public static function doPreprocess()
+ {
+ $action = Request::post('action', false, 'string');
+
+ if ($action === 'mail') {
+ User::assertPermission("mailconfig.save");
+ self::mailHandler();
+ }
+ }
+
+ private static function mailHandler()
+ {
+ // Check action
+ $do = Request::post('button');
+ if ($do === 'save') {
+ // Prepare array
+ $data = self::cleanMailArray();
+ $data = json_encode($data);
+ Database::exec('INSERT INTO sat.configuration (parameter, value)'
+ . ' VALUES (:param, :value)'
+ . ' ON DUPLICATE KEY UPDATE value = VALUES(value)', array(
+ 'param' => 'mailconfig',
+ 'value' => $data
+ ));
+ Message::addSuccess('mail-config-saved');
+ } else {
+ Message::addError('main.invalid-action', $do);
+ }
+ Util::redirect('?do=DozMod&section=mailconfig');
+ }
+
+ private static function cleanMailArray()
+ {
+ $keys = array('host', 'port', 'ssl', 'senderAddress', 'replyTo', 'username', 'password', 'serverName');
+ $data = array();
+ foreach ($keys as $key) {
+ $data[$key] = Request::post($key, '');
+ settype($data[$key], 'string');
+ if (is_numeric($data[$key])) {
+ settype($data[$key], 'int');
+ }
+ }
+ return $data;
+ }
+
+ public static function doRender()
+ {
+ // Mail config
+ $mailConf = Database::queryFirst('SELECT value FROM sat.configuration WHERE parameter = :param', array('param' => 'mailconfig'));
+ if ($mailConf != null) {
+ $mailConf = @json_decode($mailConf['value'], true);
+ if (is_array($mailConf)) {
+ $mailConf['set_' . $mailConf['ssl']] = 'selected="selected"';
+ }
+ }
+ Permission::addGlobalTags($mailConf['perms'], null, ['mailconfig.save']);
+ Render::addTemplate('mailconfig', $mailConf);
+ }
+
+ public static function doAjax()
+ {
+ User::assertPermission("mailconfig.save");
+ $action = Request::post('action');
+ if ($action === 'mail') {
+ self::handleTestMail();
+ }
+ }
+
+ private static function handleTestMail()
+ {
+ $do = Request::post('button');
+ if ($do === 'test') {
+ // Prepare array
+ $data = self::cleanMailArray();
+ Header('Content-Type: text/plain; charset=utf-8');
+ $data['recipient'] = Request::post('recipient', '');
+ if (!preg_match('/.+@.+\..+/', $data['recipient'])) {
+ $result = 'No recipient given!';
+ } else {
+ $result = Download::asStringPost('http://127.0.0.1:9080/do/mailtest', $data, 10, $code);
+ if ($code == 999) {
+ $result .= "\nTimeout.";
+ } elseif ($code != 200) {
+ $result .= "\nReturn code $code";
+ }
+ }
+ die($result);
+ }
+ }
+
+}
diff --git a/modules-available/dozmod/pages/networkrules.inc.php b/modules-available/dozmod/pages/networkrules.inc.php
new file mode 100644
index 00000000..6011e3ff
--- /dev/null
+++ b/modules-available/dozmod/pages/networkrules.inc.php
@@ -0,0 +1,98 @@
+<?php
+
+class SubPage
+{
+
+ public static function doPreprocess()
+ {
+ $action = Request::post('action', '', 'string');
+
+ if ($action === 'delete') {
+ User::assertPermission('networkrules.save');
+ $ruleid = Request::post('ruleid', false, 'int');
+ if ($ruleid !== false) {
+ $res = Database::exec('DELETE FROM sat.presetnetworkrules WHERE ruleid = :ruleid', ['ruleid' => $ruleid]);
+ if ($res !== false) {
+ Message::addSuccess('networkrule-deleted');
+ }
+ }
+ } else if ($action === 'save') {
+ User::assertPermission('networkrules.save');
+ $ruleid = Request::post('ruleid', 0, 'int');
+ $rulename = Request::post('rulename', '', 'string');
+ $host = Request::post('host', '', 'string');
+ $port = Request::post('port', '', 'string');
+ $direction = Request::post('direction', '', 'string');
+
+ if (!in_array($direction, ['IN', 'OUT'], true)) {
+ Message::addError('networkrule-invalid-direction', $direction);
+ } elseif (empty($host)) {
+ Message::addError('networkrule-missing-host');
+ } elseif (empty($port)) {
+ Message::addError('networkrule-missing-port');
+ } else {
+ $data = json_encode([
+ 'host' => $host,
+ 'port' => $port,
+ 'direction' => $direction
+ ]);
+ if ($ruleid !== 0) {
+ Database::exec('UPDATE sat.presetnetworkrules SET rulename = :rulename, ruledata = :data'
+ .' WHERE ruleid = :ruleid', compact('ruleid', 'rulename', 'data'));
+ } else {
+ Database::exec('INSERT INTO sat.presetnetworkrules (rulename, ruledata)'
+ .' VALUES (:rulename, :data)', compact('rulename', 'data'));
+ }
+ Message::addSuccess('networkrule-saved');
+ }
+ }
+ if (Request::isPost()) {
+ Util::redirect('?do=dozmod&section=networkrules');
+ }
+ User::assertPermission('networkrules.view');
+ }
+
+ public static function doRender()
+ {
+ $show = Request::get('show', 'list', 'string');
+ if ($show === 'list') {
+ $res = Database::simpleQuery('SELECT ruleid, rulename, ruledata
+ FROM sat.presetnetworkrules ORDER BY rulename ASC');
+ $rows = array();
+ while ($row = $res->fetch(PDO::FETCH_ASSOC)) {
+ $dec = json_decode($row['ruledata'], true);
+ if (!is_array($dec)) {
+ $dec = [];
+ }
+ $rows[] = $row + $dec;
+ }
+ Render::addTemplate('networkrules', [
+ 'networkrules' => $rows,
+ 'hasEditPermissions' => User::hasPermission('networkrules.save')
+ ]);
+ } else if ($show === 'edit') {
+ $ruleid = Request::get('ruleid', 0, 'int');
+ if ($ruleid === 0) {
+ $data = [];
+ } else {
+ $data = Database::queryFirst('SELECT ruleid, rulename, ruledata
+ FROM sat.presetnetworkrules WHERE ruleid = :ruleid', ['ruleid' => $ruleid]);
+ if ($data === false) {
+ Message::addError('networkrule-invalid-ruleid', $ruleid);
+ Util::redirect('?do=dozmod&section=networkrules');
+ }
+ $dec = json_decode($data['ruledata'], true);
+ if (is_array($dec)) {
+ $data += $dec;
+ }
+ if ($data['direction'] === 'IN') {
+ $data['inSelected'] = 'selected';
+ } else {
+ $data['outSelected'] = 'selected';
+ }
+ }
+ Render::addTemplate('networkrules-edit', $data);
+ }
+ }
+
+}
diff --git a/modules-available/dozmod/pages/networkshares.inc.php b/modules-available/dozmod/pages/networkshares.inc.php
new file mode 100644
index 00000000..659321b4
--- /dev/null
+++ b/modules-available/dozmod/pages/networkshares.inc.php
@@ -0,0 +1,108 @@
+<?php
+
+class SubPage
+{
+
+ public static function doPreprocess()
+ {
+ $action = Request::post('action', '', 'string');
+
+ if ($action === 'delete') {
+ User::assertPermission('networkshares.save');
+ $shareid = Request::post('shareid', false, 'int');
+ if ($shareid !== false) {
+ $res = Database::exec('DELETE FROM sat.presetnetworkshare WHERE shareid = :shareid', ['shareid' => $shareid]);
+ if ($res !== false) {
+ Message::addSuccess('networkshare-deleted');
+ }
+ }
+ } else if ($action === 'save') {
+ User::assertPermission('networkshares.save');
+ $shareid = Request::post('shareid', 0, 'int');
+ $sharename = Request::post('sharename', '', 'string');
+ $path = Request::post('path', false, 'string');
+ $target = Request::post('target', '', 'string');
+ $authType = Request::post('auth', '', 'string');
+ $username = Request::post('username', '', 'string');
+ $password = Request::post('password', '', 'string');
+ if (!in_array($authType, ['LOGIN_USER', 'OTHER_USER'], true)) {
+ Message::addError('networkshare-invalid-auth-type', $authType);
+ } elseif (empty($path)) {
+ Message::addError('networkshare-missing-path');
+ } else {
+ $data = json_encode([
+ 'auth' => $authType,
+ 'path' => $path,
+ 'displayname' => $sharename,
+ 'mountpoint' => $target,
+ 'username' => $username,
+ 'password' => $password,
+ ]);
+ if ($shareid !== 0) {
+ Database::exec('UPDATE sat.presetnetworkshare SET sharename = :sharename, sharedata = :data'
+ .' WHERE shareid = :shareid', compact('shareid', 'sharename', 'data'));
+ } else {
+ Database::exec('INSERT INTO sat.presetnetworkshare (sharename, sharedata, active)'
+ .' VALUES (:sharename, :data, 1)', compact('sharename', 'data'));
+ }
+ Message::addSuccess('networkshare-saved');
+ }
+ } else if ($action === 'activate' || $action === 'deactivate') {
+ User::assertPermission('networkshares.save');
+ $shareid = Request::post('shareid', false, 'int');
+ $active = ($action === 'activate' ? 1 : 0);
+ Database::exec('UPDATE sat.presetnetworkshare SET active = :active WHERE shareid = :shareid', compact('active', 'shareid'));
+ }
+ if (Request::isPost()) {
+ Util::redirect('?do=dozmod&section=networkshares');
+ }
+ User::assertPermission('networkshares.view');
+ }
+
+ public static function doRender()
+ {
+ $show = Request::get('show', 'list', 'string');
+ if ($show === 'list') {
+ $res = Database::simpleQuery('SELECT shareid, sharename, sharedata, active
+ FROM sat.presetnetworkshare ORDER BY sharename ASC');
+ $rows = array();
+ while ($row = $res->fetch(PDO::FETCH_ASSOC)) {
+ $dec = json_decode($row['sharedata'], true);
+ if (!is_array($dec)) {
+ $dec = [];
+ }
+ if ($dec['auth'] === 'LOGIN_USER') {
+ $row['loginAsUser'] = true;
+ }
+ $rows[] = $row + $dec;
+ }
+ Render::addTemplate('networkshares', [
+ 'networkshares' => $rows,
+ 'hasEditPermissions' => User::hasPermission('networkshares.save')
+ ]);
+ } else if ($show === 'edit') {
+ $shareid = Request::get('shareid', 0, 'int');
+ if ($shareid === 0) {
+ $data = [];
+ } else {
+ $data = Database::queryFirst('SELECT shareid, sharename, sharedata
+ FROM sat.presetnetworkshare WHERE shareid = :shareid', ['shareid' => $shareid]);
+ if ($data === false) {
+ Message::addError('networkshare-invalid-shareid', $shareid);
+ Util::redirect('?do=dozmod&section=networkshares');
+ }
+ $dec = json_decode($data['sharedata'], true);
+ if (is_array($dec)) {
+ $data += $dec;
+ }
+ if ($data['auth'] === 'LOGIN_USER') {
+ $data['loggedInUser_selected'] = 'selected';
+ } else {
+ $data['specificUser_selected'] = 'selected';
+ }
+ }
+ Render::addTemplate('networkshares-edit', $data);
+ }
+ }
+
+}
diff --git a/modules-available/dozmod/pages/runscripts.inc.php b/modules-available/dozmod/pages/runscripts.inc.php
new file mode 100644
index 00000000..c6566c13
--- /dev/null
+++ b/modules-available/dozmod/pages/runscripts.inc.php
@@ -0,0 +1,133 @@
+<?php
+
+class SubPage
+{
+
+ public static function doPreprocess()
+ {
+ /* execute actions */
+ $action = Request::post('action', false, 'string');
+
+ if ($action === 'save') {
+ User::assertPermission("runscripts.save");
+ self::saveScript();
+ }
+
+ if (Request::isPost()) {
+ Util::redirect('?do=dozmod&section=runscripts');
+ }
+ User::assertPermission('runscripts.view');
+ }
+
+ private static function saveScript()
+ {
+ $id = Request::post('runscriptid', false, 'int');
+ $scriptname = Request::post('scriptname', '', 'string');
+ if ($id === false) {
+ Message::addError('main.parameter-missing', 'runscriptid');
+ return;
+ }
+ $data = [
+ 'scriptname' => $scriptname,
+ 'content' => Request::post('content', '', 'string'),
+ 'visibility' => Request::post('visibility', 1, 'int'),
+ 'extension' => preg_replace('/[^a-z0-9_\-~\!\$\=]/i', '', Request::post('extension', '', 'string')),
+ 'passcreds' => Request::post('passcreds', 0, 'int') !== 0,
+ 'isglobal' => Request::post('isglobal', 0, 'int') !== 0,
+ ];
+ if ($id === 0) {
+ // New entry
+ $ret = Database::exec('INSERT INTO sat.presetrunscript
+ (scriptname, content, extension, visibility, passcreds, isglobal) VALUES
+ (:scriptname, :content, :extension, :visibility, :passcreds, :isglobal)', $data);
+ $id = Database::lastInsertId();
+ } else {
+ // Edit entry
+ $data['id'] = $id;
+ Database::exec('UPDATE sat.presetrunscript SET
+ scriptname = :scriptname, content = :content, extension = :extension, visibility = :visibility,
+ passcreds = :passcreds, isglobal = :isglobal
+ WHERE runscriptid = :id', $data);
+ }
+ $oslist = Request::post('osid', false, 'array');
+ if (is_array($oslist)) {
+ $oslist = array_filter($oslist, 'is_numeric');
+ $query = Database::prepare('INSERT INTO sat.presetrunscript_x_operatingsystem
+ (runscriptid, osid) VALUES (:id, :osid)');
+ foreach ($oslist as $osid) {
+ $query->execute(['id' => $id, 'osid' => $osid]);
+ }
+ $query->closeCursor();
+ Database::exec('DELETE FROM sat.presetrunscript_x_operatingsystem
+ WHERE runscriptid = :id AND osid NOT IN (:oslist)', ['id' => $id, 'oslist' => $oslist]);
+ }
+ Message::addSuccess('runscript-saved');
+ }
+
+ public static function doRender()
+ {
+ $show = Request::get('show', 'list', 'string');
+ if ($show === 'list') {
+ $res = Database::simpleQuery('SELECT runscriptid, scriptname, extension, visibility, passcreds, isglobal
+ FROM sat.presetrunscript
+ ORDER BY scriptname ASC');
+ $rows = [];
+ while ($row = $res->fetch(PDO::FETCH_ASSOC)) {
+ if ($row['visibility'] == 0) {
+ $row['visibility'] = 'eye-close';
+ } elseif ($row['visibility'] == 1) {
+ $row['visibility'] = 'eye-open';
+ } else {
+ $row['visibility'] = 'arrow-down';
+ }
+ $rows[] = $row;
+ }
+ Render::addTemplate('runscripts-list', ['list' => $rows, 'hasEditPermission' => User::hasPermission('runscripts.save')]);
+ } elseif ($show === 'edit') {
+ // Edit
+ $id = Request::get('runscriptid', false, 'int');
+ if ($id === false) {
+ Message::addError('main.parameter-missing', 'runscriptid');
+ Util::redirect('?do=dozmod&section=runscripts');
+ }
+ if ($id === 0) {
+ $row = [
+ 'runscriptid' => 0,
+ 'visibility_1_checked' => 'checked',
+ 'isglobal_1_checked' => 'checked',
+ ];
+ } else {
+ $row = Database::queryFirst('SELECT runscriptid, scriptname, content, extension, visibility, passcreds, isglobal
+ FROM sat.presetrunscript
+ WHERE runscriptid = :runscriptid', ['runscriptid' => $id]);
+ $row['visibility_' . $row['visibility'] . '_selected'] = 'selected';
+ $row['passcreds_checked'] = $row['passcreds'] ? 'checked' : '';
+ $row['isglobal_' . $row['isglobal'] . '_checked'] = 'checked';
+ if ($row === false) {
+ Message::addError('runscript-invalid-id', $id);
+ Util::redirect('?do=dozmod&section=runscripts');
+ }
+ }
+ // Get OS
+ $row['oslist'] = [];
+ $res = Database::simpleQuery('SELECT o.osid, o.displayname, pxo.osid AS isvalid FROM sat.operatingsystem o
+ LEFT JOIN sat.presetrunscript_x_operatingsystem pxo ON (o.osid = pxo.osid AND pxo.runscriptid = :runscriptid)
+ ORDER BY o.displayname ASC', ['runscriptid' => $id]);
+ while ($osrow = $res->fetch(PDO::FETCH_ASSOC)) {
+ $row['oslist'][] = [
+ 'osid' => $osrow['osid'],
+ 'displayname' => $osrow['displayname'],
+ 'checked' => $osrow['isvalid'] ? 'checked' : '',
+ ];
+ }
+ // Output
+ Render::addTemplate('runscripts-edit', $row);
+ }
+ }
+
+ public static function doAjax()
+ {
+
+ }
+
+}
diff --git a/modules-available/dozmod/pages/runtimeconfig.inc.php b/modules-available/dozmod/pages/runtimeconfig.inc.php
new file mode 100644
index 00000000..63ba4650
--- /dev/null
+++ b/modules-available/dozmod/pages/runtimeconfig.inc.php
@@ -0,0 +1,112 @@
+<?php
+
+class SubPage
+{
+
+ public static function doPreprocess()
+ {
+ /* execute actions */
+ $action = Request::post('action', false, 'string');
+
+ if ($action === 'runtime') {
+ User::assertPermission("runtimeconfig.save");
+ self::runtimeHandler();
+ }
+ }
+
+ private static function runtimeHandler()
+ {
+ // Check action
+ $do = Request::post('button');
+ if ($do === 'save') {
+ $data = [];
+ $data['defaultLecturePermissions'] = Request::post('defaultLecturePermissions', NULL, "array");
+ $data['defaultImagePermissions'] = Request::post('defaultImagePermissions', NULL, "array");
+
+ $params = [
+ 'int' => [
+ 'maxImageValidityDays' => array('min' => 7, 'max' => 9999),
+ 'maxLectureValidityDays' => array('min' => 7, 'max' => 9999),
+ 'maxLocationsPerLecture' => array('min' => 0, 'max' => 999),
+ 'maxTransfers' => array('min' => 1, 'max' => 10),
+ ],
+ 'bool' => [
+ 'allowLoginByDefault' => array('default' => true)
+ ],
+ ];
+ 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 */
+ settype($data['defaultLecturePermissions']['edit'], 'boolean');
+ settype($data['defaultLecturePermissions']['admin'], 'boolean');
+ settype($data['defaultImagePermissions']['edit'], 'boolean');
+ settype($data['defaultImagePermissions']['admin'], 'boolean');
+ settype($data['defaultImagePermissions']['link'], 'boolean');
+ settype($data['defaultImagePermissions']['download'], 'boolean');
+
+ $data = json_encode($data);
+ Database::exec('INSERT INTO sat.configuration (parameter, value)'
+ . ' VALUES (:param, :value)'
+ . ' ON DUPLICATE KEY UPDATE value = VALUES(value)', array(
+ 'param' => 'runtimelimits',
+ 'value' => $data
+ ));
+ Message::addSuccess('runtimelimits-config-saved');
+ }
+ Util::redirect('?do=DozMod&section=runtimeconfig');
+ }
+
+ public static function doRender()
+ {
+ // Runtime config
+ $runtimeConf = Database::queryFirst('SELECT value FROM sat.configuration WHERE parameter = :param', array('param' => 'runtimelimits'));
+ if ($runtimeConf !== false) {
+ $runtimeConf = json_decode($runtimeConf['value'], true);
+
+ /* convert some value to corresponding "selected" texts */
+ if ($runtimeConf['defaultLecturePermissions']['edit']) {
+ $runtimeConf['defaultLecturePermissions']['edit'] = 'checked';
+ }
+ if ($runtimeConf['defaultLecturePermissions']['admin']) {
+ $runtimeConf['defaultLecturePermissions']['admin'] = 'checked';
+ }
+ if ($runtimeConf['defaultImagePermissions']['edit']) {
+ $runtimeConf['defaultImagePermissions']['edit'] = 'checked';
+ }
+ if ($runtimeConf['defaultImagePermissions']['admin']) {
+ $runtimeConf['defaultImagePermissions']['admin'] = 'checked';
+ }
+ if ($runtimeConf['defaultImagePermissions']['link']) {
+ $runtimeConf['defaultImagePermissions']['link'] = 'checked';
+ }
+ if ($runtimeConf['defaultImagePermissions']['download']) {
+ $runtimeConf['defaultImagePermissions']['download'] = 'checked';
+ }
+
+ if ($runtimeConf['allowLoginByDefault']) {
+ $runtimeConf['allowLoginByDefault'] = 'checked';
+ }
+ }
+ $runtimeConf['allowedSave'] = User::hasPermission("runtimeconfig.save");
+ Render::addTemplate('runtimeconfig', $runtimeConf);
+ }
+
+ public static function doAjax()
+ {
+
+ }
+
+}
diff --git a/modules-available/dozmod/pages/templates.inc.php b/modules-available/dozmod/pages/templates.inc.php
new file mode 100644
index 00000000..b857115f
--- /dev/null
+++ b/modules-available/dozmod/pages/templates.inc.php
@@ -0,0 +1,139 @@
+<?php
+
+class SubPage
+{
+
+ private static $templates = [];
+
+ public static function doPreprocess()
+ {
+ $action = Request::post('action', 'show', 'string');
+ if ($action === 'show') {
+ self::fetchTemplates();
+ } elseif ($action === 'save') {
+ if (User::hasPermission("templates.save")) {
+ self::handleSave();
+ }
+ } elseif ($action === 'reset') {
+ if(User::hasPermission("templates.reset")) {
+ self::handleReset();
+ }
+ } else {
+ Message::addError('main.invalid-action', $action);
+ Util::redirect('?do=dozmod&section=templates');
+ }
+ }
+
+ private static function enrichHtml() {
+ /* for each template */
+ foreach (self::$templates as &$t) {
+ $lis = "";
+ $optManVars = "";
+ $optVars = "";
+ foreach ($t['mandatory_variables'] as $var) {
+ $optManVars .= "<option selected=\"selected\" value=\"$var\">$var</option>";
+ $lis .= "<li><strong>$var</strong></li>";
+ }
+ foreach($t['optional_variables'] as $var) {
+ $optVars .= "<option selected=\"selected\" value=\"$var\">$var</option>";
+ $lis .= "<li>$var</li>";
+ }
+ /* also options for hidden inputs */
+
+ $t['html_availableVariables'] = $lis;
+ $t['html_mandatoryVariables'] = $optManVars;
+ $t['html_optionalVariables'] = $optVars;
+
+ /* also for javascript */
+ $t['list_mandatoryVariables'] =
+ implode(',', $t['mandatory_variables']);
+
+ $t['list_optionalVariables'] =
+ implode(',', $t['optional_variables']);
+
+ settype($t['original'], 'bool');
+ settype($t['edit_version'], 'int');
+ settype($t['version'], 'int');
+ $t['modified'] = !$t['original'];
+ $t['conflict'] = !$t['original'] && $t['edit_version'] < $t['version'];
+ }
+ }
+
+ public static function doRender()
+ {
+ self::enrichHtml();
+ Render::addTemplate('templates', [
+ 'templates' => self::$templates,
+ 'allowedReset' => User::hasPermission("templates.reset"),
+ 'allowedSave' => User::hasPermission("templates.save"),
+ ]);
+ }
+
+ private static function forcmp($string)
+ {
+ return trim(str_replace("\r\n", "\n", $string));
+ }
+
+ private static function handleSave()
+ {
+ $data = Request::post('templates');
+ if (is_array($data)) {
+ self::fetchTemplates();
+ foreach (self::$templates as &$template) {
+ if (isset($data[$template['name']])) {
+ if (self::forcmp($template['template']) !== self::forcmp($data[$template['name']]['template'])) {
+ if (empty($template['original_template'])) {
+ $template['original_template'] = $template['template'];
+ }
+ $template['edit_version'] = $template['version'];
+ }
+ $template['original'] = (empty($template['original_template']) && $template['original'])
+ || self::forcmp($template['original_template']) === self::forcmp($data[$template['name']]['template']);
+ if ($template['original']) {
+ $template['original_template'] = '';
+ }
+ $template['template'] = $data[$template['name']]['template'];
+ }
+ }
+ unset($template);
+ $data = json_encode(array('templates' => self::$templates));
+ Database::exec("UPDATE sat.configuration SET value = :value WHERE parameter = 'templates'", array('value' => $data));
+ Message::addSuccess('templates-saved');
+ } else {
+ Message::addError('nothing-submitted');
+ }
+ Util::redirect('?do=dozmod&section=templates');
+ }
+
+ private static function handleReset()
+ {
+ $result = Download::asStringPost('http://127.0.0.1:9080/do/reset-mail-templates', array(), 10, $code);
+ if ($code == 999) {
+ Message::addError('timeout');
+ } elseif ($code != 200) {
+ Message::addError('dozmod-error', $code);
+ } else {
+ Message::addSuccess('all-templates-reset', $result);
+ }
+ Util::redirect('?do=dozmod&section=templates');
+ }
+
+ private static function fetchTemplates() {
+ $templates= Database::queryFirst('SELECT value FROM sat.configuration WHERE parameter = :param', array('param' => 'templates'));
+ if ($templates != null) {
+ $templates = @json_decode($templates['value'], true);
+ if (is_array($templates)) {
+ $names = array_map(static function ($e) { return $e['name']; }, $templates['templates']);
+ array_multisort($names, SORT_ASC, $templates['templates']);
+ self::$templates = $templates['templates'];
+ }
+ }
+
+ }
+
+ public static function doAjax()
+ {
+
+ }
+
+}
diff --git a/modules-available/dozmod/pages/users.inc.php b/modules-available/dozmod/pages/users.inc.php
new file mode 100644
index 00000000..50f0f763
--- /dev/null
+++ b/modules-available/dozmod/pages/users.inc.php
@@ -0,0 +1,128 @@
+<?php
+
+class SubPage
+{
+
+ public static function doPreprocess()
+ {
+ // Currently there's only one view, actions are ajax
+ User::assertPermission('users.view');
+ }
+
+ public static function doRender()
+ {
+ self::listUsers();
+ self::listOrganizations();
+ }
+
+ public static function doAjax()
+ {
+ User::load();
+
+ $action = Request::post('action', '', 'string');
+ if ($action === 'setmail' || $action === 'setsu' || $action == 'setlogin') {
+ if (User::hasPermission("users.".$action)) {
+ self::setUserOption($action);
+ }
+ } elseif ($action === 'setorglogin') {
+ if (User::hasPermission("users.setorglogin")) {
+ self::setOrgOption($action);
+ }
+ } else {
+ die('No such action');
+ }
+ }
+
+ // Helpers
+
+ private static function listUsers()
+ {
+ $res = Database::simpleQuery('SELECT userid, firstname, lastname, email, lastlogin, user.canlogin, issuperuser, emailnotifications,'
+ . ' organization.displayname AS orgname FROM sat.user'
+ . ' LEFT JOIN sat.organization USING (organizationid)'
+ . ' ORDER BY lastname ASC, firstname ASC');
+ $rows = array();
+ while ($row = $res->fetch(PDO::FETCH_ASSOC)) {
+ settype($row['lastlogin'], 'int');
+ $row['canlogin'] = self::checked($row['canlogin']);
+ $row['issuperuser'] = self::checked($row['issuperuser']);
+ $row['emailnotifications'] = self::checked($row['emailnotifications']);
+ if ($row['lastlogin'] !== 0) {
+ $row['lastlogin_s'] = date('d.m.Y', $row['lastlogin']);
+ }
+ $rows[] = $row;
+ }
+ Render::addTemplate('userlist', array(
+ 'users' => $rows,
+ 'nameTag' => User::hasPermission('actionlog.view') ? 'a' : 'span',
+ ));
+ }
+
+ private static function listOrganizations()
+ {
+ $res = Database::simpleQuery('SELECT organizationid, displayname, canlogin FROM sat.organization'
+ . ' ORDER BY displayname ASC');
+ $rows = array();
+ while ($row = $res->fetch(PDO::FETCH_ASSOC)) {
+ $row['canlogin'] = self::checked($row['canlogin']);
+ $rows[] = $row;
+ }
+ Render::addTemplate('orglist', array('organizations' => $rows));
+ }
+
+ private static function checked($val)
+ {
+ if ($val)
+ return 'checked="checked"';
+ return '';
+ }
+
+ private static function setUserOption($option)
+ {
+ $val = (string) Request::post('value', '-');
+ if ($val !== '1' && $val !== '0')
+ die('Nein');
+ if ($option === 'setmail') {
+ $field = 'emailnotifications';
+ } elseif ($option === 'setsu') {
+ $field = 'issuperuser';
+ } elseif ($option === 'setlogin') {
+ $field = 'canlogin';
+ } else {
+ die('Unknown');
+ }
+ $user = (string) Request::post('userid', '?');
+ $ret = Database::exec("UPDATE sat.user SET $field = :onoff WHERE userid = :userid", array(
+ 'userid' => $user,
+ 'onoff' => $val
+ ));
+ error_log("Setting $field to $val for $user - affected: $ret");
+ if ($ret === false)
+ die('Error');
+ if ($ret === 0)
+ die(1 - $val);
+ die($val);
+ }
+
+ private static function setOrgOption($option)
+ {
+ $val = (string) Request::post('value', '-');
+ if ($val !== '1' && $val !== '0')
+ die('Nein');
+ if ($option === 'setorglogin') {
+ $field = 'canlogin';
+ } else {
+ die('Unknown');
+ }
+ $ret = Database::exec("UPDATE sat.organization SET $field = :onoff WHERE organizationid = :organizationid", array(
+ 'organizationid' => (string) Request::post('organizationid', ''),
+ 'onoff' => $val
+ ));
+ if ($ret === false)
+ die('Error');
+ if ($ret === 0)
+ die(1 - $val);
+ die($val);
+ }
+
+}