subPage !== false) return; /* different pages for different sections */ $section = Request::any('section', 'mailconfig', 'string'); /* instantiate sub pages */ if ($section === 'templates') { $this->subPage = new Page_mail_templates(); } if ($section === 'users') { $this->subPage = new Page_dozmod_users(); } if ($section === 'actionlog') { $this->subPage = new Page_dozmod_log(); } } protected function doPreprocess() { User::load(); if (!User::isLoggedIn()) { Message::addError('main.no-permission'); Util::redirect('?do=Main'); } /* add sub-menus */ Dashboard::addSubmenu('?do=dozmod§ion=expiredimages', Dictionary::translate('submenu_expiredimages', true)); Dashboard::addSubmenu('?do=dozmod§ion=mailconfig', Dictionary::translate('submenu_mailconfig', true)); Dashboard::addSubmenu('?do=dozmod§ion=templates', Dictionary::translate('submenu_templates', true)); Dashboard::addSubmenu('?do=dozmod§ion=runtimeconfig', Dictionary::translate('submenu_runtime', true)); Dashboard::addSubmenu('?do=dozmod§ion=users', Dictionary::translate('submenu_users', true)); Dashboard::addSubmenu('?do=dozmod§ion=actionlog', Dictionary::translate('submenu_actionlog', true)); $this->setupSubPage(); if ($this->subPage !== false) { $this->subPage->doPreprocess(); return; } /* execute actions */ $action = Request::post('action', false, 'string'); if ($action === 'mail') { if (User::hasPermission("mail.save")) { $this->mailHandler(); } } elseif ($action === 'runtime') { if (User::hasPermission("runtimeconfig.save")) { $this->runtimeHandler(); } } elseif ($action === 'delimages') { if (User::hasPermission("images.delete")) { $result = $this->handleDeleteImages(); if (!empty($result)) { Message::addInfo('delete-images', $result); } Util::redirect('?do=DozMod'); } } elseif ($action !== false) { Util::traceError('Invalid action: ' . $action); } } protected function doRender() { /* different pages for different sections */ if ($this->subPage !== false) { $this->subPage->doRender(); return; } $section = Request::get('section', false, 'string'); if ($section === false || $section === 'expiredimages') { $expiredImages = $this->loadExpiredImages(); if ($section === false && empty($expiredImages)) { $section = 'mailconfig'; } else { $section = 'expiredimages'; } } if ($section === 'expiredimages') { if (empty($expiredImages)) { Message::addSuccess('no-expired-images'); } else { Render::addTemplate('images-delete', array('images' => $expiredImages, 'allowedDelete' => User::hasPermission("images.delete"))); } } if ($section === 'mailconfig') { // 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"'; } } $mailConf['allowedSave'] = User::hasPermission('mail.save'); $mailConf['allowedTest'] = User::hasPermission('mail.testmail'); Render::addTemplate('mailconfig', $mailConf); } if ($section === 'runtimeconfig') { // 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); } if ($section === 'blockstats') { $this->showBlockStats(); } } private function showBlockStats() { $res = Database::simpleQuery("SELECT blocksha1, blocksize, Count(*) AS blockcount FROM sat.imageblock" . " GROUP BY blocksha1, blocksize HAVING blockcount > 1 ORDER BY blockcount DESC, blocksha1 ASC"); $data = array('hashes' => array()); $spaceWasted = 0; while ($row = $res->fetch(PDO::FETCH_ASSOC)) { $row['hash_hex'] = bin2hex($row['blocksha1']); $row['blocksize_s'] = Util::readableFileSize($row['blocksize']); $data['hashes'][] = $row; $spaceWasted += $row['blocksize'] * ($row['blockcount'] - 1); } $data['spacewasted'] = Util::readableFileSize($spaceWasted); Render::addTemplate('blockstats', $data); } private 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; } private 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; } protected function doAjax() { User::load(); $this->setupSubPage(); if ($this->subPage !== false) { $this->subPage->doAjax(); return; } $action = Request::post('action'); if ($action === 'mail') { if (User::hasPermission("mail.testmail")) { $this->handleTestMail(); } } elseif ($action === 'delimages') { if (User::hasPermission("images.delete")) { die($this->handleDeleteImages()); } } elseif ($action === 'getblockinfo') { $this->ajaxGetBlockInfo(); } } private function ajaxGetBlockInfo() { $hash = Request::any('hash', false, 'string'); $size = Request::any('size', false, 'string'); if ($hash === false || $size === false) { die('Missing parameter'); } if (!is_numeric($size) || strlen($hash) !== 40 || !preg_match('/^[a-f0-9]+$/i', $hash)) { die('Malformed parameter'); } $res = Database::simpleQuery("SELECT i.displayname, v.createtime, v.filesize, Count(*) AS blockcount FROM sat.imageblock ib" . " INNER JOIN sat.imageversion v USING (imageversionid)" . " INNER JOIN sat.imagebase i USING (imagebaseid)" . " WHERE ib.blocksha1 = :hash AND ib.blocksize = :size" . " GROUP BY ib.imageversionid" . " ORDER BY i.displayname ASC, v.createtime ASC", array('hash' => hex2bin($hash), 'size' => $size), true); if ($res === false) { die('Database error: ' . Database::lastError()); } $data = array('rows' => array()); while ($row = $res->fetch(PDO::FETCH_ASSOC)) { $row['createtime_s'] = date('d.m.Y H:i', $row['createtime']); $row['filesize_s'] = Util::readableFileSize($row['filesize']); $data['rows'][] = $row; } die(Render::parse('blockstats-details', $data)); } private 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 function handleTestMail() { $do = Request::post('button'); if ($do === 'test') { // Prepare array $data = $this->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); } } private function mailHandler() { // Check action $do = Request::post('button'); if ($do === 'save') { // Prepare array $data = $this->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§ion=mailconfig'); } private 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§ion=runtimeconfig'); } }