summaryrefslogtreecommitdiffstats
path: root/modules-available/sysconfig
diff options
context:
space:
mode:
Diffstat (limited to 'modules-available/sysconfig')
-rw-r--r--modules-available/sysconfig/addconfig.inc.php54
-rw-r--r--modules-available/sysconfig/addmodule.inc.php58
-rw-r--r--modules-available/sysconfig/addmodule_adauth.inc.php45
-rw-r--r--modules-available/sysconfig/addmodule_branding.inc.php83
-rw-r--r--modules-available/sysconfig/addmodule_custommodule.inc.php32
-rw-r--r--modules-available/sysconfig/addmodule_ldapauth.inc.php32
-rw-r--r--modules-available/sysconfig/addmodule_screensaver.inc.php57
-rw-r--r--modules-available/sysconfig/addmodule_sshconfig.inc.php23
-rw-r--r--modules-available/sysconfig/addmodule_sshkey.inc.php12
-rw-r--r--modules-available/sysconfig/api.inc.php8
-rw-r--r--modules-available/sysconfig/hooks/bootup.inc.php3
-rw-r--r--modules-available/sysconfig/hooks/locations-column.inc.php57
-rw-r--r--modules-available/sysconfig/inc/configmodule.inc.php225
-rw-r--r--modules-available/sysconfig/inc/configmodule/branding.inc.php20
-rw-r--r--modules-available/sysconfig/inc/configmodule/customodule.inc.php20
-rw-r--r--modules-available/sysconfig/inc/configmodule/ldapauth.inc.php2
-rw-r--r--modules-available/sysconfig/inc/configmodule/screensaver.inc.php29
-rw-r--r--modules-available/sysconfig/inc/configmodule/sshconfig.inc.php8
-rw-r--r--modules-available/sysconfig/inc/configmodule/sshkey.inc.php8
-rw-r--r--modules-available/sysconfig/inc/configmodulebaseldap.inc.php26
-rw-r--r--modules-available/sysconfig/inc/configtgz.inc.php188
-rw-r--r--modules-available/sysconfig/inc/ldap.inc.php2
-rw-r--r--modules-available/sysconfig/inc/ppd.inc.php249
-rw-r--r--modules-available/sysconfig/inc/sysconfig.inc.php4
-rw-r--r--modules-available/sysconfig/install.inc.php35
-rw-r--r--modules-available/sysconfig/lang/de/module.json17
-rw-r--r--modules-available/sysconfig/lang/en/module.json17
-rw-r--r--modules-available/sysconfig/page.inc.php21
-rw-r--r--modules-available/sysconfig/templates/ad-start.html2
-rw-r--r--modules-available/sysconfig/templates/branding-check.html2
-rw-r--r--modules-available/sysconfig/templates/branding-start.html2
-rw-r--r--modules-available/sysconfig/templates/cfg-start.html2
-rw-r--r--modules-available/sysconfig/templates/custom-fileselect.html3
-rw-r--r--modules-available/sysconfig/templates/ldap-start.html2
-rw-r--r--modules-available/sysconfig/templates/sshconfig-start.html2
-rw-r--r--modules-available/sysconfig/templates/sshkey-start.html5
36 files changed, 711 insertions, 644 deletions
diff --git a/modules-available/sysconfig/addconfig.inc.php b/modules-available/sysconfig/addconfig.inc.php
index a22cdc46..27af31e8 100644
--- a/modules-available/sysconfig/addconfig.inc.php
+++ b/modules-available/sysconfig/addconfig.inc.php
@@ -9,21 +9,17 @@ abstract class AddConfig_Base
/**
* Holds the instance for the currently executing step
- * @var \AddConfig_Base
+ * @var AddConfig_Base
*/
- private static $instance = false;
+ private static $instance = null;
/**
* Config being edited (if any)
- * @var \ConfigTgz
+ * @var ?ConfigTgz
*/
- protected $edit = false;
+ protected $edit = null;
- /**
- *
- * @param string $step
- */
- public static function setStep($step)
+ public static function setStep(string $step)
{
if (empty($step) || !class_exists($step) || get_parent_class($step) !== 'AddConfig_Base') {
Message::addError('invalid-action', $step);
@@ -32,18 +28,12 @@ abstract class AddConfig_Base
self::$instance = new $step();
if (($editId = Request::any('edit', 0, 'int')) !== 0) {
self::$instance->edit = ConfigTgz::get($editId);
- if (self::$instance->edit === false)
- Util::traceError('Invalid config id for editing');
+ if (self::$instance->edit === null)
+ ErrorHandler::traceError('Invalid config id for editing');
Util::addRedirectParam('edit', self::$instance->edit->id());
}
}
- protected function tmError()
- {
- Message::addError('main.taskmanager-error');
- Util::redirect('?do=SysConfig');
- }
-
/**
* Called before any HTML rendering happens, so you can
* prepare stuff, validate input, and optionally redirect
@@ -73,25 +63,25 @@ abstract class AddConfig_Base
public static function preprocess()
{
- if (self::$instance === false) {
- Util::traceError('No step instance yet');
+ if (self::$instance === null) {
+ ErrorHandler::traceError('No step instance yet');
}
self::$instance->preprocessInternal();
}
public static function render()
{
- if (self::$instance === false)
- Util::traceError('No step instance yet');
- if (self::$instance->edit !== false)
+ if (self::$instance === null)
+ ErrorHandler::traceError('No step instance yet');
+ if (self::$instance->edit !== null)
Message::addInfo('replacing-config', self::$instance->edit->title());
self::$instance->renderInternal();
}
public static function ajax()
{
- if (self::$instance === false) {
- Util::traceError('No step instance yet');
+ if (self::$instance === null) {
+ ErrorHandler::traceError('No step instance yet');
}
self::$instance->ajaxInternal();
}
@@ -110,7 +100,7 @@ class AddConfig_Start extends AddConfig_Base
$mods = ConfigModule::getList();
$res = Database::simpleQuery("SELECT moduleid, title, moduletype, filepath FROM configtgz_module"
. " ORDER BY title ASC"); // Move to ConfigModule
- if ($this->edit === false) {
+ if ($this->edit === null) {
$active = array();
} else {
$active = $this->edit->getModuleIds();
@@ -122,7 +112,7 @@ class AddConfig_Start extends AddConfig_Base
$modGroups[$mod['group']] =& $mod;
}
unset($mod);
- while ($row = $res->fetch(PDO::FETCH_ASSOC)) {
+ foreach ($res as $row) {
if (!isset($mods[$row['moduletype']])) {
$mods[$row['moduletype']] = array(
'unique' => false,
@@ -140,7 +130,7 @@ class AddConfig_Start extends AddConfig_Base
$row['active'] = in_array($row['moduleid'], $active);
$group['modules'][] = $row;
}
- if ($this->edit !== false) {
+ if ($this->edit !== null) {
$title = $this->edit->title();
} else {
$title = Request::any('title', '', 'string');
@@ -162,7 +152,7 @@ class AddConfig_Start extends AddConfig_Base
'step' => 'AddConfig_Finish',
'groups' => array_values($modGroups),
'title' => $title,
- 'edit' => ($this->edit !== false ? $this->edit->id() : false)
+ 'edit' => $this->edit === null ? null : $this->edit->id(),
));
}
@@ -174,9 +164,9 @@ class AddConfig_Start extends AddConfig_Base
class AddConfig_Finish extends AddConfig_Base
{
/**
- * @var ConfigTgz
+ * @var ?ConfigTgz
*/
- private $config = false;
+ private $config = null;
protected function preprocessInternal()
{
@@ -186,13 +176,13 @@ class AddConfig_Finish extends AddConfig_Base
Message::addError('missing-file');
Util::redirect('?do=SysConfig&action=addconfig');
}
- if ($this->edit === false) {
+ if ($this->edit === null) {
$this->config = ConfigTgz::insert($title, $modules);
} else {
$this->edit->update($title, $modules);
$this->config = $this->edit;
}
- if ($this->config === false || $this->config->generate(true, 150) === false) {
+ if ($this->config->generate(true, 150) === false) {
Message::addError('unsuccessful-action');
Util::redirect('?do=SysConfig&action=addconfig');
}
diff --git a/modules-available/sysconfig/addmodule.inc.php b/modules-available/sysconfig/addmodule.inc.php
index 91fee45d..4564537e 100644
--- a/modules-available/sysconfig/addmodule.inc.php
+++ b/modules-available/sysconfig/addmodule.inc.php
@@ -9,34 +9,39 @@ abstract class AddModule_Base
/**
* Holds the instance for the currently executing step
- * @var \AddModule_Base
+ *
+ * @var AddModule_Base
*/
private static $instance = false;
/**
* Instance of ConfigModule we're editing. False if not editing but creating.
- * @var \ConfigModule
+ *
+ * @var ?ConfigModule
*/
- protected $edit = false;
+ protected $edit = null;
/**
*
* @param string $step name of class representing the current step
* @param int $editId (optional) overwrite for the request parameter 'edit'
*/
- public static function setStep($step, $editId = false)
+ public static function setStep(string $step, int $editId = null): void
{
if (empty($step) || !class_exists($step) || get_parent_class($step) !== 'AddModule_Base') {
Message::addError('invalid-action', $step);
Util::redirect('?do=SysConfig');
}
self::$instance = new $step();
- if ($editId = $editId ? $editId : Request::any('edit')) {
+ if ($editId === null) {
+ $editId = Request::any('edit', 0, 'int');
+ }
+ if ($editId !== 0) {
self::$instance->edit = ConfigModule::get($editId);
- if (self::$instance->edit === false)
- Util::traceError('Invalid module id for editing');
+ if (self::$instance->edit === null)
+ ErrorHandler::traceError('Invalid module id for editing');
if ($step !== 'AddModule_Assign' && !preg_match('/^' . self::$instance->edit->moduleType() . '_/', $step))
- Util::traceError('Module to edit is of different type!');
+ ErrorHandler::traceError('Module to edit is of different type!');
Util::addRedirectParam('edit', self::$instance->edit->id());
}
}
@@ -90,7 +95,7 @@ abstract class AddModule_Base
public static function preprocess()
{
if (self::$instance === false) {
- Util::traceError('No step instance yet');
+ ErrorHandler::traceError('No step instance yet');
}
self::$instance->preprocessInternal();
}
@@ -98,9 +103,9 @@ abstract class AddModule_Base
public static function render()
{
if (self::$instance === false) {
- Util::traceError('No step instance yet');
+ ErrorHandler::traceError('No step instance yet');
}
- if (get_class(self::$instance) !== 'AddModule_Assign' && self::$instance->edit !== false) {
+ if (get_class(self::$instance) !== 'AddModule_Assign' && self::$instance->edit !== null) {
Message::addInfo('replacing-module', self::$instance->edit->title());
}
self::$instance->renderInternal();
@@ -109,7 +114,7 @@ abstract class AddModule_Base
public static function ajax()
{
if (self::$instance === false) {
- Util::traceError('No step instance yet');
+ ErrorHandler::traceError('No step instance yet');
}
self::$instance->ajaxInternal();
}
@@ -155,7 +160,7 @@ class AddModule_Assign extends AddModule_Base
if (ConfigModule::getList()[$moduleType]['unique']) {
$moduleIds = [];
- foreach (ConfigModule::getAll($moduleType) as $module) {
+ foreach (ConfigModule::getAll($moduleType) ?? [] as $module) {
$moduleIds[] = $module->id();
}
@@ -209,41 +214,26 @@ class AddModule_Assign extends AddModule_Base
* Helper functions to set/get a batch of vars from/to post variables or a module
*/
-/**
- *
- * @param \ConfigModule $module
- * @param array $array
- * @param array $keys
- */
-function moduleToArray($module, &$array, $keys)
+function moduleToArray(ConfigModule $module, array &$array, array $keys): void
{
foreach ($keys as $key) {
$array[$key] = $module->getData($key);
}
}
-/**
- *
- * @param \ConfigModule $module
- * @param array $array
- * @param array $keys
- */
-function arrayToModule($module, $array, $keys)
+function arrayToModule(ConfigModule $module, array $array, array $keys): void
{
foreach ($keys as $key) {
$module->setData($key, $array[$key]);
}
}
-/**
- *
- * @param array $array
- * @param array $keys
- */
-function postToArray(&$array, $keys, $ignoreMissing = false)
+
+function postToArray(array &$array, array $keys, $ignoreMissing = false): void
{
foreach ($keys as $key) {
$val = Request::post($key, '--not-in-post');
- if ($ignoreMissing && $val === '--not-in-post') continue;
+ if ($ignoreMissing && $val === '--not-in-post')
+ continue;
$array[$key] = $val;
}
}
diff --git a/modules-available/sysconfig/addmodule_adauth.inc.php b/modules-available/sysconfig/addmodule_adauth.inc.php
index f2ac206e..42187171 100644
--- a/modules-available/sysconfig/addmodule_adauth.inc.php
+++ b/modules-available/sysconfig/addmodule_adauth.inc.php
@@ -15,7 +15,7 @@ class AdAuth_Start extends AddModule_Base
{
$ADAUTH_COMMON_FIELDS = array('title', 'server', 'searchbase', 'binddn', 'bindpw', 'home', 'homeattr', 'ssl', 'genuid', 'certificate', 'mapping', 'nohomewarn');
$data = array();
- if ($this->edit !== false) {
+ if ($this->edit !== null) {
moduleToArray($this->edit, $data, $ADAUTH_COMMON_FIELDS);
$data['title'] = $this->edit->title();
$data['edit'] = $this->edit->id();
@@ -35,7 +35,7 @@ class AdAuth_Start extends AddModule_Base
}
$data['step'] = 'AdAuth_CheckConnection';
$data['map_empty'] = true;
- $data['mapping'] = ConfigModuleBaseLdap::getMapping(isset($data['mapping']) ? $data['mapping'] : false, $data['map_empty']);
+ $data['mapping'] = ConfigModuleBaseLdap::getMapping($data['mapping'] ?? null, $data['map_empty']);
Render::addDialog(Dictionary::translateFile('config-module', 'adAuth_title'), false, 'ad-start', $data);
}
@@ -89,13 +89,12 @@ class AdAuth_CheckConnection extends AddModule_Base
));
if (!isset($this->scanTask['id'])) {
AddModule_Base::setStep('AdAuth_Start'); // Continues with AdAuth_Start for render()
- return;
}
}
protected function renderInternal()
{
- $mapping = Request::post('mapping', false, 'array');
+ $mapping = Request::post('mapping', null, 'array');
$data = array(
'edit' => Request::post('edit'),
'title' => Request::post('title'),
@@ -131,7 +130,7 @@ class AdAuth_SelfSearch extends AddModule_Base
protected function preprocessInternal()
{
- $server = $binddn = $port = null;
+ $server = $binddn = null;
$searchbase = Request::post('searchbase', '');
$bindpw = Request::post('bindpw');
$ssl = Request::post('ssl', 'off') === 'on';
@@ -140,14 +139,8 @@ class AdAuth_SelfSearch extends AddModule_Base
AddModule_Base::setStep('AdAuth_Start'); // Continues with AdAuth_Start for render()
return;
}
- foreach (['server', 'binddn', 'port'] as $var) {
- $$var = Request::post($var, null);
- if (empty($$var)) {
- Message::addError('main.parameter-empty', $var);
- AddModule_Base::setStep('AdAuth_Start'); // Continues with AdAuth_Start for render()
- return;
- }
- }
+ $server = Request::post('server', Request::REQUIRED, 'string');
+ $binddn = Request::post('binddn', Request::REQUIRED, 'string');
$this->originalBindDn = '';
// Fix bindDN if short name given
//
@@ -195,7 +188,7 @@ class AdAuth_SelfSearch extends AddModule_Base
protected function renderInternal()
{
- $mapping = Request::post('mapping', false, 'array');
+ $mapping = Request::post('mapping', null, 'array');
$data = array(
'edit' => Request::post('edit'),
'title' => Request::post('title'),
@@ -288,7 +281,7 @@ class AdAuth_HomeAttrCheck extends AddModule_Base
'certificate' => Request::post('certificate', ''),
'originalbinddn' => Request::post('originalbinddn'),
'tryHomeAttr' => true,
- 'mapping' => ConfigModuleBaseLdap::getMapping(Request::post('mapping', false, 'array')),
+ 'mapping' => ConfigModuleBaseLdap::getMapping(Request::post('mapping', null, 'array')),
'prev' => 'AdAuth_Start',
'next' => 'AdAuth_CheckCredentials'
))
@@ -359,7 +352,7 @@ class AdAuth_CheckCredentials extends AddModule_Base
'fingerprint' => Request::post('fingerprint'),
'certificate' => Request::post('certificate', ''),
'originalbinddn' => Request::post('originalbinddn'),
- 'mapping' => ConfigModuleBaseLdap::getMapping(Request::post('mapping', false, 'array')),
+ 'mapping' => ConfigModuleBaseLdap::getMapping(Request::post('mapping', null, 'array')),
'prev' => 'AdAuth_Start',
'next' => 'AdAuth_HomeDir'
))
@@ -423,11 +416,11 @@ class AdAuth_HomeDir extends AddModule_Base
'fingerprint' => Request::post('fingerprint'),
'certificate' => Request::post('certificate', ''),
'originalbinddn' => Request::post('originalbinddn'),
- 'mapping' => ConfigModuleBaseLdap::getMapping(Request::post('mapping', false, 'array')),
+ 'mapping' => ConfigModuleBaseLdap::getMapping(Request::post('mapping', null, 'array')),
'prev' => 'AdAuth_Start',
'next' => 'AdAuth_Finish'
);
- if ($this->edit !== false) {
+ if ($this->edit !== null) {
foreach (self::getAttributes() as $key) {
if ($this->edit->getData($key)) {
$data[$key . '_c'] = 'checked="checked"';
@@ -448,13 +441,13 @@ class AdAuth_HomeDir extends AddModule_Base
foreach (range('D', 'Z') as $l) {
$data['drives'][] = array(
'drive' => $l . ':',
- 'selected' => (strtoupper($letter{0}) === $l) ? 'selected="selected"' : ''
+ 'selected' => (strtoupper($letter[0]) === $l) ? 'selected="selected"' : ''
);
}
Render::addDialog(Dictionary::translateFile('config-module', 'adAuth_title'), false, 'ad_ldap-homedir', $data);
}
- public static function getAttributes()
+ public static function getAttributes(): array
{
return array('shareRemapMode', 'shareRemapCreate', 'shareDocuments', 'shareDownloads', 'shareDesktop',
'shareMedia', 'shareOther', 'shareHomeDrive', 'shareDomain', 'credentialPassthrough');
@@ -472,10 +465,11 @@ class AdAuth_Finish extends AddModule_Base
$title = Request::post('title');
if (empty($title))
$title = 'AD: ' . Request::post('server');
- if ($this->edit === false)
+ if ($this->edit === null) {
$module = ConfigModule::getInstance('AdAuth');
- else
+ } else {
$module = $this->edit;
+ }
$ssl = Request::post('ssl', 'off') === 'on';
foreach (['searchbase', 'binddn', 'server', 'bindpw', 'home', 'nohomewarn', 'homeattr', 'certificate', 'genuid',
'ldapAttrMountOpts', 'shareHomeMountOpts'] as $key) {
@@ -499,7 +493,7 @@ class AdAuth_Finish extends AddModule_Base
} else {
$module->setData('fingerprint', '');
}
- if ($this->edit !== false)
+ if ($this->edit !== null)
$ret = $module->update($title);
else
$ret = $module->insert($title);
@@ -507,7 +501,7 @@ class AdAuth_Finish extends AddModule_Base
Message::addError('main.value-invalid', 'any', 'any');
$tgz = false;
} else {
- $tgz = $module->generate($this->edit === false);
+ $tgz = $module->generate($this->edit === null);
}
if ($tgz === false) {
AddModule_Base::setStep('AdAuth_Start'); // Continues with AdAuth_Start for render()
@@ -517,9 +511,8 @@ class AdAuth_Finish extends AddModule_Base
'tm-config' => $tgz,
);
- if ($this->edit === false) {
+ if ($this->edit === null) {
AddModule_Base::setStep('AddModule_Assign', $module->id());
- return;
}
}
diff --git a/modules-available/sysconfig/addmodule_branding.inc.php b/modules-available/sysconfig/addmodule_branding.inc.php
index d941a7a7..54b2ad57 100644
--- a/modules-available/sysconfig/addmodule_branding.inc.php
+++ b/modules-available/sysconfig/addmodule_branding.inc.php
@@ -11,7 +11,7 @@ class Branding_Start extends AddModule_Base
{
Render::addDialog(Dictionary::translateFile('config-module', 'branding_title'), false, 'branding-start', array(
'step' => 'Branding_ProcessFile',
- 'edit' => $this->edit ? $this->edit->id() : false
+ 'edit' => $this->edit == null ? null : $this->edit->id(),
));
}
@@ -22,7 +22,6 @@ class Branding_ProcessFile extends AddModule_Base
private $task;
private $svgFile;
- private $tarFile;
protected function preprocessInternal()
{
@@ -48,14 +47,16 @@ class Branding_ProcessFile extends AddModule_Base
if (strpos($url, '://') === false)
$url = "http://$url";
$title = false;
- if (!$this->downloadSvg($this->svgFile, $url, $title))
+ if (!Branding_ProcessFile::downloadSvg($this->svgFile, $url, $title)) {
+ @unlink($this->svgFile);
Util::redirect('?do=SysConfig&action=addmodule&step=Branding_Start');
+ }
Session::set('logo_name', $title);
}
chmod($this->svgFile, 0644);
- $this->tarFile = '/tmp/bwlp-' . time() . '-' . mt_rand() . '.tgz';
+ $tarFile = '/tmp/bwlp-' . time() . '-' . mt_rand() . '.tgz';
$this->task = Taskmanager::submit('BrandingGenerator', array(
- 'tarFile' => $this->tarFile,
+ 'tarFile' => $tarFile,
'svgFile' => $this->svgFile
));
$this->task = Taskmanager::waitComplete($this->task, 5000);
@@ -64,8 +65,7 @@ class Branding_ProcessFile extends AddModule_Base
Taskmanager::addErrorMessage($this->task);
Util::redirect('?do=SysConfig&action=addmodule&step=Branding_Start');
}
- Session::set('logo_tgz', $this->tarFile);
- Session::save();
+ Session::set('logo_tgz', $tarFile);
}
protected function renderInternal()
@@ -75,13 +75,13 @@ class Branding_ProcessFile extends AddModule_Base
$png = base64_encode(file_get_contents($this->task['data']['pngFile']));
if (filesize($this->svgFile) < 1000000)
$svg = base64_encode(file_get_contents($this->svgFile));
- Render::addDialog(Dictionary::translate('config-module', 'branding_title'), false, 'branding-check', array(
+ Render::addDialog(Dictionary::translateFile('config-module', 'branding_title'), false, 'branding-check', array(
'png' => $png,
'svg' => $svg,
- 'error' => $this->task['data']['error'],
+ 'error' => $this->task['data']['error'] ?? $this->task['statusCode'],
'step' => 'Branding_Finish',
- 'edit' => $this->edit ? $this->edit->id() : false,
- 'title' => $this->edit ? $this->edit->title() : false
+ 'edit' => $this->edit === null ? null : $this->edit->id(),
+ 'title' => $this->edit === null ? null : $this->edit->title(),
)
);
@unlink($this->svgFile);
@@ -96,39 +96,56 @@ class Branding_ProcessFile extends AddModule_Base
* @return boolean true of download succeeded, false on download error (also returns true if downloaded file doesn't
* seem to be svg!)
*/
- private function downloadSvg($svgName, $url, &$title)
+ private static function downloadSvg(string $svgName, string $url, &$title): bool
{
$title = false;
- // [wikipedia] Did someone paste a link to a thumbnail of the svg? Let's fix that...
- if (preg_match('#^(.*)/thumb/(.*\.svg)/.*\.svg#', $url, $out)) {
- $url = $out[1] . '/' . $out[2];
- }
for ($i = 0; $i < 5; ++$i) {
+ // [wikipedia] Did someone paste a link to a thumbnail of the svg? Let's fix that...
+ if (preg_match('#^(.*)/thumb/(.*\.svg)/.*\.svg#', $url, $out)) {
+ $url = $out[1] . '/' . $out[2];
+ }
$code = 400;
if (!Download::toFile($svgName, $url, 3, $code) || $code < 200 || $code > 299) {
Message::addError('remote-timeout', $url, $code);
return false;
}
- $content = FileUtil::readFile($svgName, 25000);
+ $content = FileUtil::readFile($svgName, 250000);
// Is svg file?
if (strpos($content, '<svg') !== false)
return true; // Found an svg tag - don't try to find links to the actual image
// [wikipedia] Try to be nice and detect links that might give a hint where the svg can be found
- if (preg_match_all('#href="([^"]*upload.wikimedia.org/[^"]*/[^"]*/[^"]*\.svg|[^"]+/[^"]+:[^"]+\.svg[^"]*)"#', $content, $out, PREG_PATTERN_ORDER)) {
+ $out1 = $out2 = $out3 = null;
+ if (preg_match_all('#href="([^"]*upload.wikimedia.org/[^"]*/[^"]*/[^"]*\.svg)"#', $content, $out1, PREG_PATTERN_ORDER)
+ || preg_match_all('#src="([^"]*upload.wikimedia.org/[^"]*/thumb/[^"]*\.svg/[^"]+\.svg[^"]*)"#', $content, $out2, PREG_PATTERN_ORDER)
+ || preg_match_all('#href="([^"]+/[^"]+:[^"]+\.svg)"#', $content, $out3, PREG_PATTERN_ORDER)) {
if ($title === false && preg_match('#<title>([^<]*)</title>#i', $content, $tout)) {
$title = trim(preg_replace('/\W*Wikipedia.*/', '', $tout[1]));
}
$new = false;
- foreach ($out[1] as $res) {
+ $out = [];
+ if (isset($out1[1])) {
+ $out += $out1[1];
+ }
+ if (isset($out2[1])) {
+ $out += $out2[1];
+ }
+ if (isset($out3[1])) {
+ $out += $out3[1];
+ }
+ foreach ($out as $res) {
+ error_log("Match '$res'");
+ if (!preg_match('/hochschule|univers|logo|siegel/i', $res))
+ continue;
if (strpos($res, 'action=edit') !== false)
continue;
- $new = $this->internetCombineUrl($url, html_entity_decode($res, ENT_COMPAT, 'UTF-8'));
+ $new = Branding_ProcessFile::internetCombineUrl($url, html_entity_decode($res, ENT_COMPAT, 'UTF-8'));
if ($new !== $url)
break;
}
if ($new === $url || $new === false)
break;
+ error_log("New: '$new'");
$url = $new;
continue;
}
@@ -145,7 +162,7 @@ class Branding_ProcessFile extends AddModule_Base
* @param string $relative relative url that will be converted to an absolute url
* @return string combined absolute url
*/
- private function internetCombineUrl($absolute, $relative)
+ private static function internetCombineUrl(string $absolute, string $relative): string
{
$p = parse_url($relative);
if (!empty($p["scheme"]))
@@ -154,8 +171,8 @@ class Branding_ProcessFile extends AddModule_Base
$parsed = parse_url($absolute);
$path = dirname($parsed['path']);
- if ($relative{0} === '/') {
- if ($relative{1} === '/')
+ if ($relative[0] === '/') {
+ if ($relative[1] === '/')
return "{$parsed['scheme']}:$relative";
$cparts = array_filter(explode("/", $relative));
} else {
@@ -197,9 +214,9 @@ class Branding_Finish extends AddModule_Base
protected function preprocessInternal()
{
$title = Request::post('title');
- if ($title === false || empty($title))
+ if (empty($title))
$title = Session::get('logo_name');
- if ($title === false || empty($title)) {
+ if (empty($title)) {
Message::addError('missing-title'); // TODO: Ask for title again instead of starting over
Util::redirect('?do=SysConfig&action=addmodule&step=Branding_Start');
}
@@ -208,30 +225,26 @@ class Branding_Finish extends AddModule_Base
Message::addError('main.error-read', $tgz);
Util::redirect('?do=SysConfig&action=addmodule&step=Branding_Start');
}
- if ($this->edit === false)
+ if ($this->edit === null) {
$module = ConfigModule::getInstance('Branding');
- else
+ } else {
$module = $this->edit;
- if ($module === false) {
- Message::addError('main.error-read', 'branding.inc.php');
- Util::redirect('?do=SysConfig&action=addmodule&step=Branding_Start');
}
$module->setData('tmpFile', $tgz);
- if ($this->edit !== false)
+ if ($this->edit !== null)
$ret = $module->update($title);
else
$ret = $module->insert($title);
if (!$ret)
Util::redirect('?do=SysConfig&action=addmodule&step=Branding_Start');
- elseif ($module->generate($this->edit === false, NULL, 200) === false)
+ elseif ($module->generate($this->edit === null, NULL, 200) === false)
Util::redirect('?do=SysConfig&action=addmodule&step=Branding_Start');
Session::set('logo_tgz', false);
Session::set('logo_name', false);
- Session::save();
// Yay
- if ($this->edit !== false)
+ if ($this->edit !== null) {
Message::addSuccess('module-edited');
- else {
+ } else {
Message::addSuccess('module-added');
AddModule_Base::setStep('AddModule_Assign', $module->id());
return;
diff --git a/modules-available/sysconfig/addmodule_custommodule.inc.php b/modules-available/sysconfig/addmodule_custommodule.inc.php
index f7ab863e..3afdad0a 100644
--- a/modules-available/sysconfig/addmodule_custommodule.inc.php
+++ b/modules-available/sysconfig/addmodule_custommodule.inc.php
@@ -14,7 +14,7 @@ class CustomModule_Start extends AddModule_Base
Session::set('mod_temp', false);
Render::addDialog(Dictionary::translateFile('config-module', 'custom_title'), false, 'custom-upload', array(
'step' => 'CustomModule_ProcessUpload',
- 'edit' => $this->edit ? $this->edit->id() : false
+ 'edit' => $this->edit === null ? null : $this->edit->id(),
));
}
@@ -55,7 +55,7 @@ class CustomModule_ProcessUpload extends AddModule_Base
protected function renderInternal()
{
- $status = Taskmanager::waitComplete($this->taskId);
+ $status = Taskmanager::waitComplete($this->taskId, 7500);
Taskmanager::release($this->taskId);
$userGroupWarn = false;
$tempfile = Session::get('mod_temp');
@@ -69,21 +69,20 @@ class CustomModule_ProcessUpload extends AddModule_Base
}
$list = SysConfig::archiveContentsFromTask($status, $userGroupWarn);
- if ($this->edit !== false) {
+ if ($this->edit !== null) {
$title = $this->edit->title();
} else if (isset($_FILES['modulefile']['name'])) {
$title = basename($_FILES['modulefile']['name']);
} else {
$title = '';
}
- Render::addDialog(Dictionary::translate('config-module', 'custom_title'), false, 'custom-fileselect', array(
+ Render::addDialog(Dictionary::translateFile('config-module', 'custom_title'), false, 'custom-fileselect', array(
'step' => 'CustomModule_CompressModule',
'files' => $list,
- 'edit' => $this->edit ? $this->edit->id() : false,
+ 'edit' => $this->edit === null ? null : $this->edit->id(),
'title' => $title,
'userGroupWarn' => $userGroupWarn,
));
- Session::save();
}
}
@@ -108,7 +107,7 @@ class CustomModule_CompressModule extends AddModule_Base
'outputFile' => $destFile,
'forceRoot' => Request::post('force-owner', 0, 'int') !== 0,
), true);
- $status = Taskmanager::waitComplete($taskId, 5000);
+ $status = Taskmanager::waitComplete($taskId, 10000);
unlink($tempfile);
if (!isset($status['statusCode'])) {
$this->tmError();
@@ -117,29 +116,26 @@ class CustomModule_CompressModule extends AddModule_Base
$this->taskError($status);
}
// Seems ok, create entry
- if ($this->edit === false)
+ if ($this->edit === null) {
$module = ConfigModule::getInstance('CustomModule');
- else
+ } else {
$module = $this->edit;
- if ($module === false) {
- Message::addError('main.error-read', 'custommodule.inc.php');
- Util::redirect('?do=SysConfig&action=addmodule&step=CustomModule_Start');
}
$module->setData('tmpFile', $destFile);
- if ($this->edit !== false)
+ if ($this->edit !== null) {
$ret = $module->update($title);
- else
+ } else {
$ret = $module->insert($title);
+ }
if (!$ret)
Util::redirect('?do=SysConfig&action=addmodule&step=CustomModule_Start');
- elseif (!$module->generate($this->edit === false, NULL, 200))
+ elseif (!$module->generate($this->edit === null, NULL, 200))
Util::redirect('?do=SysConfig&action=addmodule&step=CustomModule_Start');
Session::set('mod_temp', false);
- Session::save();
// Yay
- if ($this->edit !== false)
+ if ($this->edit !== null) {
Message::addSuccess('module-edited');
- else {
+ } else {
Message::addSuccess('module-added');
AddModule_Base::setStep('AddModule_Assign', $module->id());
return;
diff --git a/modules-available/sysconfig/addmodule_ldapauth.inc.php b/modules-available/sysconfig/addmodule_ldapauth.inc.php
index 606ce381..6a385d9c 100644
--- a/modules-available/sysconfig/addmodule_ldapauth.inc.php
+++ b/modules-available/sysconfig/addmodule_ldapauth.inc.php
@@ -11,7 +11,7 @@ class LdapAuth_Start extends AddModule_Base
{
$LDAPAUTH_COMMON_FIELDS = array('title', 'server', 'searchbase', 'binddn', 'bindpw', 'home', 'homeattr', 'ssl', 'genuid', 'certificate', 'mapping', 'nohomewarn');
$data = array();
- if ($this->edit !== false) {
+ if ($this->edit !== null) {
moduleToArray($this->edit, $data, $LDAPAUTH_COMMON_FIELDS);
$data['title'] = $this->edit->title();
$data['edit'] = $this->edit->id();
@@ -27,7 +27,7 @@ class LdapAuth_Start extends AddModule_Base
}
$data['step'] = 'LdapAuth_CheckConnection';
$data['map_empty'] = true;
- $data['mapping'] = ConfigModuleBaseLdap::getMapping(isset($data['mapping']) ? $data['mapping'] : false, $data['map_empty']);
+ $data['mapping'] = ConfigModuleBaseLdap::getMapping($data['mapping'] ?? null, $data['map_empty']);
Render::addDialog(Dictionary::translateFile('config-module', 'ldapAuth_title'), false, 'ldap-start', $data);
}
@@ -64,7 +64,6 @@ class LdapAuth_CheckConnection extends AddModule_Base
));
if (!isset($this->scanTask['id'])) {
AddModule_Base::setStep('LdapAuth_Start'); // Continues with LdapAuth_Start for render()
- return;
}
}
@@ -82,7 +81,7 @@ class LdapAuth_CheckConnection extends AddModule_Base
'genuid' => Request::post('genuid'),
'certificate' => Request::post('certificate', ''),
'taskid' => $this->scanTask['id'],
- 'mapping' => ConfigModuleBaseLdap::getMapping(Request::post('mapping', false, 'array')),
+ 'mapping' => ConfigModuleBaseLdap::getMapping(Request::post('mapping', null, 'array')),
);
$data['prev'] = 'LdapAuth_Start';
$data['next'] = 'LdapAuth_CheckCredentials';
@@ -153,7 +152,7 @@ class LdapAuth_CheckCredentials extends AddModule_Base
'genuid' => Request::post('genuid'),
'fingerprint' => Request::post('fingerprint'),
'certificate' => Request::post('certificate', ''),
- 'mapping' => ConfigModuleBaseLdap::getMapping(Request::post('mapping', false, 'array')),
+ 'mapping' => ConfigModuleBaseLdap::getMapping(Request::post('mapping', null, 'array')),
'prev' => 'LdapAuth_Start',
'next' => 'LdapAuth_HomeDir',
))
@@ -194,11 +193,11 @@ class LdapAuth_HomeDir extends AddModule_Base
'fingerprint' => Request::post('fingerprint'),
'certificate' => Request::post('certificate', ''),
'originalbinddn' => Request::post('originalbinddn'),
- 'mapping' => ConfigModuleBaseLdap::getMapping(Request::post('mapping', false, 'array')),
+ 'mapping' => ConfigModuleBaseLdap::getMapping(Request::post('mapping', null, 'array')),
'prev' => 'LdapAuth_Start',
'next' => 'LdapAuth_Finish',
);
- if ($this->edit !== false) {
+ if ($this->edit !== null) {
foreach (self::getAttributes() as $key) {
if ($this->edit->getData($key)) {
$data[$key . '_c'] = 'checked="checked"';
@@ -219,13 +218,13 @@ class LdapAuth_HomeDir extends AddModule_Base
foreach (range('D', 'Z') as $l) {
$data['drives'][] = array(
'drive' => $l . ':',
- 'selected' => (strtoupper($letter{0}) === $l) ? 'selected="selected"' : ''
+ 'selected' => (strtoupper($letter[0]) === $l) ? 'selected="selected"' : ''
);
}
Render::addDialog(Dictionary::translateFile('config-module', 'ldapAuth_title'), false, 'ad_ldap-homedir', $data);
}
- public static function getAttributes()
+ public static function getAttributes(): array
{
return array('shareRemapMode', 'shareRemapCreate', 'shareDocuments', 'shareDownloads', 'shareDesktop',
'shareMedia', 'shareOther', 'shareHomeDrive', 'shareDomain', 'credentialPassthrough');
@@ -243,10 +242,11 @@ class LdapAuth_Finish extends AddModule_Base
$title = Request::post('title');
if (empty($title))
$title = 'LDAP: ' . Request::post('server');
- if ($this->edit === false)
+ if ($this->edit === null) {
$module = ConfigModule::getInstance('LdapAuth');
- else
+ } else {
$module = $this->edit;
+ }
$ssl = Request::post('ssl', 'off') === 'on';
foreach (['searchbase', 'binddn', 'server', 'bindpw', 'home', 'nohomewarn', 'certificate', 'genuid',
'ldapAttrMountOpts', 'shareHomeMountOpts'] as $key) {
@@ -270,15 +270,16 @@ class LdapAuth_Finish extends AddModule_Base
} else {
$module->setData('fingerprint', '');
}
- if ($this->edit !== false)
+ if ($this->edit !== null) {
$ret = $module->update($title);
- else
+ } else {
$ret = $module->insert($title);
+ }
if (!$ret) {
Message::addError('main.value-invalid', 'any', 'any');
$tgz = false;
} else {
- $tgz = $module->generate($this->edit === false);
+ $tgz = $module->generate($this->edit === null);
}
if ($tgz === false) {
AddModule_Base::setStep('LdapAuth_Start'); // Continues with LdapAuth_Start for render()
@@ -288,9 +289,8 @@ class LdapAuth_Finish extends AddModule_Base
'tm-config' => $tgz,
);
- if ($this->edit === false) {
+ if ($this->edit === null) {
AddModule_Base::setStep('AddModule_Assign', $module->id());
- return;
}
}
diff --git a/modules-available/sysconfig/addmodule_screensaver.inc.php b/modules-available/sysconfig/addmodule_screensaver.inc.php
index 8e5c5d28..7b6d0afb 100644
--- a/modules-available/sysconfig/addmodule_screensaver.inc.php
+++ b/modules-available/sysconfig/addmodule_screensaver.inc.php
@@ -14,7 +14,7 @@ class Screensaver_Start extends AddModule_Base
if (Request::get('back', 'false', 'string') !== 'false')
/* If coming via the back button, load the session data */
$this->session_data = Session::get('data');
- elseif ($this->edit !== false) {
+ elseif ($this->edit !== null) {
$this->session_data = array(
'title' => $this->edit->title(),
'qss' => $this->edit->getData('qss'),
@@ -24,22 +24,22 @@ class Screensaver_Start extends AddModule_Base
} else {
$this->session_data = array(
'title' => '',
- 'qss' => Dictionary::translate('saver_QssDefault', true),
+ 'qss' => Dictionary::translate('saver_QssDefault'),
'messages' => array(
'General' => array(
- 'shutdown' => Dictionary::translate('saver_MessageDefaultShutdown', true),
- 'shutdown-locked' => Dictionary::translate('saver_MessageDefaultShutdownLocked', true),
- 'idle-kill' => Dictionary::translate('saver_MessageDefaultIdleKill', true),
- 'idle-kill-locked' => Dictionary::translate('saver_MessageDefaultIdleKillLocked', true),
- 'no-timeout' => Dictionary::translate('saver_MessageDefaultNoTimeout', true),
- 'no-timeout-locked' => Dictionary::translate('saver_MessageDefaultNoTimeoutLocked', true),
+ 'shutdown' => Dictionary::translate('saver_MessageDefaultShutdown'),
+ 'shutdown-locked' => Dictionary::translate('saver_MessageDefaultShutdownLocked'),
+ 'idle-kill' => Dictionary::translate('saver_MessageDefaultIdleKill'),
+ 'idle-kill-locked' => Dictionary::translate('saver_MessageDefaultIdleKillLocked'),
+ 'no-timeout' => Dictionary::translate('saver_MessageDefaultNoTimeout'),
+ 'no-timeout-locked' => Dictionary::translate('saver_MessageDefaultNoTimeoutLocked'),
)
),
'texts' => array(
- 'text-shutdown' => Dictionary::translate('saver_TextDefaultShutdown', true),
+ 'text-shutdown' => Dictionary::translate('saver_TextDefaultShutdown'),
'text-shutdown-locked' => '',
- 'text-idle-kill' => Dictionary::translate('saver_TextDefaultIdleKill', true),
- 'text-idle-kill-locked' => Dictionary::translate('saver_TextDefaultIdleKillLocked', true),
+ 'text-idle-kill' => Dictionary::translate('saver_TextDefaultIdleKill'),
+ 'text-idle-kill-locked' => Dictionary::translate('saver_TextDefaultIdleKillLocked'),
'text-no-timeout' => '',
'text-no-timeout-locked' => '',
),
@@ -47,7 +47,6 @@ class Screensaver_Start extends AddModule_Base
}
$this->session_data['next'] = 'idle-kill';
Session::set('data', $this->session_data);
- Session::save();
}
protected function renderInternal()
@@ -57,7 +56,7 @@ class Screensaver_Start extends AddModule_Base
Render::addDialog(Dictionary::translateFile('config-module', 'screensaver_title'), false, 'screensaver-start', array(
'step' => 'Screensaver_Text',
'next' => 'idle-kill',
- 'edit' => $this->edit ? $this->edit->id() : 0,
+ 'edit' => $this->edit !== null ? $this->edit->id() : 0,
'id' => 'start',
'title' => $this->session_data['title'],
'qss' => $this->session_data['qss'],
@@ -68,24 +67,22 @@ class Screensaver_Start extends AddModule_Base
class Screensaver_Text extends AddModule_Base
{
private $session_data;
- private $id;
protected function preprocessInternal()
{
/* Load session data */
$this->session_data = Session::get('data');
- $this->id = Request::post('id', '', 'string');
+ $id = Request::post('id', '', 'string');
- if ($this->id === 'start') {
+ if ($id === 'start') {
Screensaver_Helper::processQssData($this->session_data);
- } elseif ($this->id !== '') {
- Screensaver_Helper::processScreensaverText($this->session_data, $this->id);
+ } elseif ($id !== '') {
+ Screensaver_Helper::processScreensaverText($this->session_data, $id);
}
$next = Request::post('next', $this->session_data['next'], 'string');
$this->session_data['next'] = $next;
Session::set('data', $this->session_data);
- Session::save();
if ($next === 'finish')
@@ -101,7 +98,7 @@ class Screensaver_Text extends AddModule_Base
$next = $this->session_data['next'];
$data = array(
- 'edit' => $this->edit ? $this->edit->id() : 0,
+ 'edit' => $this->edit !== null ? $this->edit->id() : 0,
);
/* Prepare and translate labels for the frontend */
@@ -117,8 +114,8 @@ class Screensaver_Text extends AddModule_Base
* Dictionary::translate('saver_TitleShutdown');
* Dictionary::translate('saver_DescriptionShutdown');
*/
- $data['title'] = Dictionary::translate('saver_Title' . $tag, true);
- $data['description'] = Dictionary::translate('saver_Description' . $tag, true);;
+ $data['title'] = Dictionary::translate('saver_Title' . $tag);
+ $data['description'] = Dictionary::translate('saver_Description' . $tag);
$data['msg_value'] = $this->session_data['messages']['General'][$next];
$data['msg_locked_value'] = $this->session_data['messages']['General'][$next . '-locked'];
$data['text_value'] = $this->session_data['texts']['text-' . $next];
@@ -153,14 +150,14 @@ class Screensaver_Finish extends AddModule_Base
if (empty($session_data['title'])) {
Message::addError('missing-title');
Util::redirect('?do=SysConfig');
- return;
}
/* Only create an instance, if it's a new one */
- if ($this->edit !== false)
+ if ($this->edit !== null) {
$module = $this->edit;
- else
+ } else {
$module = ConfigModule::getInstance('Screensaver');
+ }
/* Set all the data to the module instance */
$module->setData('qss', $session_data['qss']);
@@ -168,15 +165,16 @@ class Screensaver_Finish extends AddModule_Base
$module->setData('texts', $session_data['texts']);
/* Insert or update database entries */
- if ($this->edit !== false)
+ if ($this->edit !== null) {
$module->update($session_data['title']);
- else
+ } else {
$module->insert($session_data['title']);
+ }
- $task = $module->generate($this->edit === false);
+ $task = $module->generate($this->edit === null);
// Yay
- if ($task !== false && $this->edit !== false)
+ if ($task !== false && $this->edit !== null)
Message::addSuccess('module-edited');
elseif ($task !== false) {
Message::addSuccess('module-added');
@@ -195,7 +193,6 @@ class Screensaver_Helper
if (empty($session_data['title'])) {
Message::addError('missing-title');
Util::redirect('?do=SysConfig');
- return;
}
$session_data['qss'] = Request::post('qss', $session_data['qss'], 'string');
$helperMode = Request::post('helper_mode', 'false', 'string');
diff --git a/modules-available/sysconfig/addmodule_sshconfig.inc.php b/modules-available/sysconfig/addmodule_sshconfig.inc.php
index 4a75d77e..2447f9be 100644
--- a/modules-available/sysconfig/addmodule_sshconfig.inc.php
+++ b/modules-available/sysconfig/addmodule_sshconfig.inc.php
@@ -9,8 +9,8 @@ class SshConfig_Start extends AddModule_Base
protected function renderInternal()
{
- if ($this->edit !== false) {
- $data = $this->edit->getData(false) + array(
+ if ($this->edit !== null) {
+ $data = $this->edit->getData(null) + array(
'title' => $this->edit->title(),
'edit' => $this->edit->id(),
'PWD_' . strtoupper($this->edit->getData('allowPasswordLogin')) . '_selected' => 'selected',
@@ -40,10 +40,11 @@ class SshConfig_Finish extends AddModule_Base
return;
}
// Seems ok, create entry
- if ($this->edit === false)
+ if ($this->edit === null) {
$module = ConfigModule::getInstance('SshConfig');
- else
+ } else {
$module = $this->edit;
+ }
if ($module === false) {
Message::addError('main.error-read', 'sshconfig.inc.php');
Util::redirect('?do=SysConfig&action=addmodule&step=SshConfig_Start');
@@ -59,18 +60,20 @@ class SshConfig_Finish extends AddModule_Base
Util::redirect('?do=SysConfig&action=addmodule&step=SshConfig_Start');
}
$module->setData('publicKey', false);
- if ($this->edit !== false)
+ if ($this->edit !== null) {
$ret = $module->update($title);
- else
+ } else {
$ret = $module->insert($title);
- if (!$ret)
+ }
+ if (!$ret) {
Util::redirect('?do=SysConfig&action=addmodule&step=SshConfig_Start');
- elseif (!$module->generate($this->edit === false, NULL, 200))
+ } elseif (!$module->generate($this->edit === null, NULL, 200)) {
Util::redirect('?do=SysConfig&action=addmodule&step=SshConfig_Start');
+ }
// Yay
- if ($this->edit !== false)
+ if ($this->edit !== null) {
Message::addSuccess('module-edited');
- else {
+ } else {
Message::addSuccess('module-added');
AddModule_Base::setStep('AddModule_Assign', $module->id());
return;
diff --git a/modules-available/sysconfig/addmodule_sshkey.inc.php b/modules-available/sysconfig/addmodule_sshkey.inc.php
index b5ab4ad6..9f5bd1d3 100644
--- a/modules-available/sysconfig/addmodule_sshkey.inc.php
+++ b/modules-available/sysconfig/addmodule_sshkey.inc.php
@@ -9,8 +9,8 @@ class SshKey_Start extends AddModule_Base
protected function renderInternal()
{
- if ($this->edit !== false) {
- $data = $this->edit->getData(false) + array(
+ if ($this->edit !== null) {
+ $data = $this->edit->getData(null) + array(
'title' => $this->edit->title(),
'edit' => $this->edit->id(),
);
@@ -35,7 +35,7 @@ class SshKey_Finish extends AddModule_Base
return;
}
// Seems ok, create entry
- if ($this->edit === false) {
+ if ($this->edit === null) {
$module = ConfigModule::getInstance('SshKey');
} else {
$module = $this->edit;
@@ -48,18 +48,18 @@ class SshKey_Finish extends AddModule_Base
Message::addError('main.value-invalid', 'pubkey', Request::post('publicKey'));
Util::redirect('?do=SysConfig&action=addmodule&step=SshKey_Start');
}
- if ($this->edit !== false) {
+ if ($this->edit !== null) {
$ret = $module->update($title);
} else {
$ret = $module->insert($title);
}
if (!$ret) {
Util::redirect('?do=SysConfig&action=addmodule&step=SshKey_Start');
- } elseif (!$module->generate($this->edit === false, NULL, 200)) {
+ } elseif (!$module->generate($this->edit === null, NULL, 200)) {
Util::redirect('?do=SysConfig&action=addmodule&step=SshKey_Start');
}
// Yay
- if ($this->edit !== false) {
+ if ($this->edit !== null) {
Message::addSuccess('module-edited');
} else {
Message::addSuccess('module-added');
diff --git a/modules-available/sysconfig/api.inc.php b/modules-available/sysconfig/api.inc.php
index 983c6dcb..e7be3029 100644
--- a/modules-available/sysconfig/api.inc.php
+++ b/modules-available/sysconfig/api.inc.php
@@ -11,9 +11,9 @@ if (substr($ip, 0, 7) === '::ffff:') {
$ip = substr($ip, 7);
}
-$uuid = Request::any('uuid', false, 'string');
-if ($uuid !== false && strlen($uuid) !== 36) {
- $uuid = false;
+$uuid = Request::any('uuid', null, 'string');
+if ($uuid !== null && strlen($uuid) !== 36) {
+ $uuid = null;
}
// What we do if we can't supply the requested config
@@ -46,7 +46,7 @@ $res = Database::simpleQuery("SELECT c.title, c.filepath, c.status, cl.locationi
$best = 1000;
$row = false;
-while ($r = $res->fetch(PDO::FETCH_ASSOC)) {
+foreach ($res as $r) {
settype($r['locationid'], 'int');
$index = array_search($r['locationid'], $locationChain);
if ($index === false || $index > $best)
diff --git a/modules-available/sysconfig/hooks/bootup.inc.php b/modules-available/sysconfig/hooks/bootup.inc.php
new file mode 100644
index 00000000..8e445dc4
--- /dev/null
+++ b/modules-available/sysconfig/hooks/bootup.inc.php
@@ -0,0 +1,3 @@
+<?php
+
+ConfigModuleBaseLdap::ldadp(); \ No newline at end of file
diff --git a/modules-available/sysconfig/hooks/locations-column.inc.php b/modules-available/sysconfig/hooks/locations-column.inc.php
new file mode 100644
index 00000000..8042b51c
--- /dev/null
+++ b/modules-available/sysconfig/hooks/locations-column.inc.php
@@ -0,0 +1,57 @@
+<?php
+
+if (!User::hasPermission('.sysconfig.config.*') || !Module::isAvailable('sysconfig'))
+ return null;
+
+class SysconfigLocationColumn extends AbstractLocationColumn
+{
+
+ private $lookup = [];
+
+ public function __construct()
+ {
+ $confs = SysConfig::getAll();
+ foreach ($confs as $conf) {
+ if (!isset($conf['locs']) || strlen($conf['locs']) === 0)
+ continue;
+ $confLocs = explode(',', $conf['locs']);
+ foreach ($confLocs as $locId) {
+ $this->lookup[$locId] = $conf['title'];
+ }
+ }
+ }
+
+ public function getColumnHtml(int $locationId): string
+ {
+ return htmlspecialchars($this->lookup[$locationId] ?? '');
+ }
+
+ public function getEditUrl(int $locationId): string
+ {
+ if (!User::hasPermission('.sysconfig.config.assign', $locationId))
+ return '';
+ return '?do=sysconfig&locationid=' . $locationId;
+ }
+
+ public function header(): string
+ {
+ return Dictionary::translateFileModule('sysconfig', 'module', 'location-column-header');
+ }
+
+ public function priority(): int
+ {
+ return 2000;
+ }
+
+ public function propagateColumn(): bool
+ {
+ return true;
+ }
+
+ public function propagateDefaultHtml(): string
+ {
+ return htmlspecialchars($this->lookup[0] ?? '');
+ }
+}
+
+return new SysconfigLocationColumn(); \ No newline at end of file
diff --git a/modules-available/sysconfig/inc/configmodule.inc.php b/modules-available/sysconfig/inc/configmodule.inc.php
index 580c15a0..729cb959 100644
--- a/modules-available/sysconfig/inc/configmodule.inc.php
+++ b/modules-available/sysconfig/inc/configmodule.inc.php
@@ -7,18 +7,23 @@ abstract class ConfigModule
{
/**
- * @var array list of known module types
+ * @var ?array{'title': string,
+ * 'description': string,
+ * 'group': string,
+ * 'unique': bool,
+ * 'sortOrder': int,
+ * 'moduleClass': string,
+ * 'wizardClass': string}[] list of known module types
*/
- private static $moduleTypes = false;
+ private static $moduleTypes = null;
private $moduleId = 0;
- private $moduleArchive = false;
- private $moduleTitle = false;
- private $moduleStatus = false;
- /**
- * @var int
- */
+ private $moduleArchive = '';
+ private $moduleTitle = '';
+ private $moduleStatus = 'MISSING';
+ /** @var int */
private $dateline = 0;
+ /** @var int */
private $currentVersion = 0;
/**
* @var false|array Data of module, false if not initialized
@@ -33,9 +38,9 @@ abstract class ConfigModule
*/
public static function loadDb()
{
- if (self::$moduleTypes !== false)
+ if (self::$moduleTypes !== null)
return;
- self::$moduleTypes = array();
+ self::$moduleTypes = [];
Module::isAvailable('sysconfig');
foreach (glob(dirname(__FILE__) . '/configmodule/*.inc.php', GLOB_NOSORT) as $file) {
require_once $file;
@@ -44,10 +49,16 @@ abstract class ConfigModule
/**
* Get all known config module types.
- *
- * @return array list of modules
+ * @return array{'title': string,
+ * 'description': string,
+ * 'group': string,
+ * 'unique': bool,
+ * 'sortOrder': int,
+ * 'moduleClass': string,
+ * 'wizardClass': string}[] list of known module types
+ * /
*/
- public static function getList()
+ public static function getList(): array
{
self::loadDb();
return self::$moduleTypes;
@@ -63,20 +74,20 @@ abstract class ConfigModule
* @param string $description Description for this module type
* @param string $group Title for group this module type belongs to
* @param bool $unique Can only one such module be added to a config?
- * @param int $sortOrder Lower comes first, alphabetical ordering otherwiese
+ * @param int $sortOrder Lower comes first, alphabetical ordering otherwise
*/
- public static function registerModule($id, $title, $description, $group, $unique, $sortOrder = 0)
+ public static function registerModule(string $id, string $title, string $description, string $group, bool $unique, int $sortOrder = 0): void
{
if (isset(self::$moduleTypes[$id])) {
- Util::traceError("Config Module $id already registered!");
+ ErrorHandler::traceError("Config Module $id already registered!");
}
$moduleClass = 'ConfigModule_' . $id;
$wizardClass = $id . '_Start';
if (!class_exists($moduleClass)) {
- Util::traceError("Class $moduleClass does not exist!");
+ ErrorHandler::traceError("Class $moduleClass does not exist!");
}
if (!is_subclass_of($moduleClass, 'ConfigModule')) {
- Util::traceError("$moduleClass does not have ConfigModule as its parent!");
+ ErrorHandler::traceError("$moduleClass does not have ConfigModule as its parent!");
}
self::$moduleTypes[$id] = array(
'title' => $title,
@@ -93,21 +104,33 @@ abstract class ConfigModule
* Get fresh instance of ConfigModule subclass for given module type.
*
* @param string $moduleType name of module type
- * @return false|\ConfigModule module instance
+ * @return ConfigModule module instance
*/
- public static function getInstance($moduleType)
+ public static function getInstance(string $moduleType): ConfigModule
+ {
+ $ret = self::getInstanceOrNull($moduleType);
+ if ($ret === null) {
+ Message::addError('main.error-read', $moduleType . '.inc.php');
+ Util::redirect('?do=sysconfig');
+ }
+ return $ret;
+ }
+
+ public static function getInstanceOrNull(string $moduleType): ?ConfigModule
{
self::loadDb();
if (!isset(self::$moduleTypes[$moduleType])) {
error_log('Unknown module type: ' . $moduleType);
- return false;
+ return null;
}
return new self::$moduleTypes[$moduleType]['moduleClass'];
}
- public static function instanceFromDbRow($dbRow)
+ private static function instanceFromDbRow(array $dbRow): ?ConfigModule
{
- $instance = self::getInstance($dbRow['moduletype']);
+ $instance = self::getInstanceOrNull($dbRow['moduletype']);
+ if ($instance === null)
+ return null;
$instance->currentVersion = $dbRow['version'];
$instance->moduleArchive = $dbRow['filepath'];
$instance->moduleData = json_decode($dbRow['contents'], true);
@@ -125,37 +148,37 @@ abstract class ConfigModule
* Get module instance from id.
*
* @param int $moduleId module id to get
- * @return false|\ConfigModule The requested module from DB, or false on error
+ * @return ?ConfigModule The requested module from DB, or null on error
*/
- public static function get($moduleId)
+ public static function get(int $moduleId): ?ConfigModule
{
$ret = Database::queryFirst("SELECT moduleid, title, moduletype, filepath, contents, version, status, dateline FROM configtgz_module "
. " WHERE moduleid = :moduleid LIMIT 1", array('moduleid' => $moduleId));
if ($ret === false)
- return false;
+ return null;
return self::instanceFromDbRow($ret);
}
/**
* Get module instances from module type.
*
- * @param int $moduleType module type to get
- * @return \ConfigModule[]|false The requested modules from DB, or false on error
+ * @param string $moduleType module type to get
+ * @return ?ConfigModule[] The requested modules from DB, or null on error
*/
- public static function getAll($moduleType = false)
+ public static function getAll(string $moduleType = null): ?array
{
- if ($moduleType === false) {
+ if ($moduleType === null) {
$ret = Database::simpleQuery("SELECT moduleid, title, moduletype, filepath, contents, version, status, dateline FROM configtgz_module");
} else {
$ret = Database::simpleQuery("SELECT moduleid, title, moduletype, filepath, contents, version, status, dateline FROM configtgz_module "
. " WHERE moduletype = :moduletype", array('moduletype' => $moduleType));
}
if ($ret === false)
- return false;
+ return null;
$list = array();
- while ($row = $ret->fetch(PDO::FETCH_ASSOC)) {
+ foreach ($ret as $row) {
$instance = self::instanceFromDbRow($row);
- if ($instance === false)
+ if ($instance === null)
continue;
$list[] = $instance;
}
@@ -167,37 +190,37 @@ abstract class ConfigModule
*
* @return int module version
*/
- protected abstract function moduleVersion();
+ protected abstract function moduleVersion(): int;
/**
* Validate the module's configuration.
*
- * @return boolean ok or not
+ * @return bool ok or not
*/
- protected abstract function validateConfig();
+ protected abstract function validateConfig(): bool;
/**
* Set module specific data.
*
* @param string $key key, name or id of data being set
* @param mixed $value Module specific data
- * @return boolean true if data was successfully set, false otherwise (i.e. invalid data being set)
+ * @return bool true if data was successfully set, false otherwise (i.e. invalid data being set)
*/
- public abstract function setData($key, $value);
+ public abstract function setData(string $key, $value): bool;
/**
* Get module specific data.
* Can be overridden by modules.
*
- * @param string $key key, name or id of data to get, or false to get the raw moduleData array
+ * @param ?string $key key, name or id of data to get, or null to get the raw moduleData array
* @return mixed Module specific data
*/
- public function getData($key)
+ public function getData(?string $key)
{
- if ($key === false)
+ if ($key === null)
return $this->moduleData;
if (!is_array($this->moduleData) || !isset($this->moduleData[$key]))
- return false;
+ return null;
return $this->moduleData[$key];
}
@@ -205,25 +228,25 @@ abstract class ConfigModule
* Module specific version of generate.
*
* @param string $tgz File name of tgz module to write final output to
- * @param string $parent Parent task of this task
+ * @param string|null $parent Parent task of this task
* @return array|boolean true if generation is completed immediately,
* a task struct if some task needs to be run for generation,
* false on error
*/
- protected abstract function generateInternal($tgz, $parent);
+ protected abstract function generateInternal(string $tgz, ?string $parent);
- private final function createFileName()
+ private function createFileName(): string
{
return CONFIG_TGZ_LIST_DIR . '/modules/'
. $this->moduleType() . '_id-' . $this->moduleId . '__' . mt_rand() . '-' . time() . '.tgz';
}
- public function allowDownload()
+ public function allowDownload(): bool
{
return false;
}
- public function needRebuild()
+ public function needRebuild(): bool
{
return $this->moduleStatus !== 'OK' || $this->currentVersion < $this->moduleVersion();
}
@@ -233,17 +256,15 @@ abstract class ConfigModule
*
* @return int id
*/
- public final function id()
+ public final function id(): int
{
return $this->moduleId;
}
/**
* Get module title.
- *
- * @return string
*/
- public final function title()
+ public final function title(): string
{
return $this->moduleTitle;
}
@@ -253,17 +274,17 @@ abstract class ConfigModule
*
* @return string tgz file absolute path
*/
- public final function archive()
+ public final function archive(): string
{
return $this->moduleArchive;
}
- public final function status()
+ public final function status(): string
{
return $this->moduleStatus;
}
- public final function currentVersion()
+ public final function currentVersion(): int
{
return $this->currentVersion;
}
@@ -273,14 +294,13 @@ abstract class ConfigModule
*
* @return string module type
*/
- public final function moduleType()
+ public final function moduleType(): string
{
+ // Yes, need to pass $this, otherwise we get ConfigModule, the base class this function is part of
$name = get_class($this);
- if ($name === false)
- Util::traceError('ConfigModule::moduleType: get_class($this) returned false!');
// ConfigModule_*
if (!preg_match('/^ConfigModule_(\w+)$/', $name, $out))
- Util::traceError('ConfigModule::moduleType: get_class($this) returned "' . $name . '"');
+ ErrorHandler::traceError('ConfigModule::moduleType: get_class($this) returned "' . $name . '"');
return $out[1];
}
@@ -292,10 +312,10 @@ abstract class ConfigModule
* @param string $title display name of the module
* @return boolean true if inserted successfully, false if module config is invalid
*/
- public final function insert($title)
+ public final function insert(string $title): bool
{
if ($this->moduleId !== 0)
- Util::traceError('ConfigModule::insert called when moduleId != 0');
+ ErrorHandler::traceError('ConfigModule::insert called when moduleId != 0');
if (!$this->validateConfig())
return false;
$this->moduleTitle = $title;
@@ -311,7 +331,7 @@ abstract class ConfigModule
));
$this->moduleId = Database::lastInsertId();
if (!is_numeric($this->moduleId))
- Util::traceError('Inserting new config module into DB did not yield a numeric insert id');
+ ErrorHandler::traceError('Inserting new config module into DB did not yield a numeric insert id');
$this->moduleArchive = $this->createFileName();
Database::exec("UPDATE configtgz_module SET filepath = :path WHERE moduleid = :moduleid LIMIT 1", array(
'path' => $this->moduleArchive,
@@ -326,10 +346,10 @@ abstract class ConfigModule
*
* @return boolean true on success, false otherwise
*/
- public final function update($title = '')
+ public final function update(string $title = ''): bool
{
if ($this->moduleId === 0)
- Util::traceError('ConfigModule::update called when moduleId == 0');
+ ErrorHandler::traceError('ConfigModule::update called when moduleId == 0');
if (!empty($title)) {
$this->moduleTitle = $title;
}
@@ -353,16 +373,16 @@ abstract class ConfigModule
* Updating the database etc. will happen later through a callback.
*
* @param boolean $deleteOnError if true, the db entry will be deleted if generation failed
- * @param string $parent Parent task of this task
+ * @param string|null $parent Parent task of this task
* @param int $timeoutMs maximum time in milliseconds we wait for completion
* @return string|boolean task id if deferred generation was started,
* true if generation succeeded (without using a task or within $timeoutMs)
* false on error
*/
- public final function generate($deleteOnError, $parent = NULL, $timeoutMs = 0)
+ public final function generate(bool $deleteOnError, string $parent = NULL, int $timeoutMs = 0)
{
- if ($this->moduleId === 0 || $this->moduleTitle === false)
- Util::traceError('ConfigModule::generateAsync called on uninitialized/uninserted module!');
+ if ($this->moduleId === 0 || empty($this->moduleTitle))
+ ErrorHandler::traceError('ConfigModule::generateAsync called on uninitialized/uninserted module!');
$tmpTgz = '/tmp/bwlp-id-' . $this->moduleId . '_' . mt_rand() . '_' . time() . '.tgz';
$ret = $this->generateInternal($tmpTgz, $parent);
// Wait for generation if requested
@@ -395,10 +415,10 @@ abstract class ConfigModule
/**
* Delete the module.
*/
- public final function delete()
+ public final function delete(): void
{
if ($this->moduleId === 0)
- Util::traceError('ConfigModule::delete called with invalid module id!');
+ ErrorHandler::traceError('ConfigModule::delete called with invalid module id!');
$ret = Database::exec("DELETE FROM configtgz_module WHERE moduleid = :moduleid LIMIT 1", array(
'moduleid' => $this->moduleId
), true) !== false;
@@ -410,17 +430,19 @@ abstract class ConfigModule
$this->moduleTitle = false;
$this->moduleArchive = false;
}
- return $ret;
}
- private final function markUpdated($tmpTgz)
+ /**
+ * @param ?string $tmpTgz new tar archive to use for this module, or null if the old one is still valid
+ */
+ private function markUpdated(?string $tmpTgz): bool
{
if ($this->moduleId === 0)
- Util::traceError('ConfigModule::markUpdated called with invalid module id!');
- if ($this->moduleArchive === false)
+ ErrorHandler::traceError('ConfigModule::markUpdated called with invalid module id!');
+ if ($this->moduleArchive === null)
$this->moduleArchive = $this->createFileName();
// Move file
- if ($tmpTgz === false) {
+ if ($tmpTgz === null) {
if (!file_exists($this->moduleArchive)) {
EventLog::failure('ConfigModule::markUpdated for "' . $this->moduleTitle . '" called with no tmpTgz and no existing tgz!');
$this->markFailed();
@@ -460,24 +482,26 @@ abstract class ConfigModule
return $retval;
}
- private final function markFailed()
+ private function markFailed(): void
{
if ($this->moduleId === 0)
- Util::traceError('ConfigModule::markFailed called with invalid module id!');
- if ($this->moduleArchive === false)
+ ErrorHandler::traceError('ConfigModule::markFailed called with invalid module id!');
+ if ($this->moduleArchive === '') {
$this->moduleArchive = $this->createFileName();
- if (!file_exists($this->moduleArchive))
+ }
+ if (!file_exists($this->moduleArchive)) {
$status = 'MISSING';
- else
+ } else {
$status = 'OUTDATED';
- return Database::exec("UPDATE configtgz_module SET filepath = :filename, status = :status WHERE moduleid = :id LIMIT 1", array(
+ }
+ Database::exec("UPDATE configtgz_module SET filepath = :filename, status = :status WHERE moduleid = :id LIMIT 1", array(
'id' => $this->moduleId,
'filename' => $this->moduleArchive,
'status' => $status
- )) !== false;
+ ));
}
- public function dateline_s()
+ public function dateline_s(): string
{
return Util::prettyTime($this->dateline);
}
@@ -489,7 +513,7 @@ abstract class ConfigModule
* Override this if you need to handle this, otherwise
* the base implementation does nothing.
*/
- public function event_serverIpChanged()
+ public function event_serverIpChanged(): void
{
// Do::Nothing()
}
@@ -500,11 +524,10 @@ abstract class ConfigModule
* Will be called if the server's IP address changes. The event will be propagated
* to all config module classes so action can be taken if appropriate.
*/
- public static function serverIpChanged()
+ public static function serverIpChanged(): void
{
self::loadDb();
- $list = self::getAll();
- foreach ($list as $mod) {
+ foreach (self::getAll() ?? [] as $mod) {
$mod->event_serverIpChanged();
}
}
@@ -513,53 +536,51 @@ abstract class ConfigModule
* Called when (re)generating a config module failed, so we can
* update the status in the DB and add a server log entry.
*
- * @param array $task
- * @param array $args contains 'moduleid' and optionally 'deleteOnError' and 'tmpTgz'
+ * @param array $args contains 'moduleid' and optionally 'deleteOnError'
*/
- public static function generateFailed($task, $args)
+ public static function generateFailed(array $task, array $args): void
{
if (!isset($args['moduleid']) || !is_numeric($args['moduleid'])) {
EventLog::warning('Ignoring generateFailed event as it has no moduleid assigned.');
return;
}
$module = self::get($args['moduleid']);
- if ($module === false) {
+ if ($module === null) {
EventLog::warning('generateFailed callback for module id ' . $args['moduleid'] . ', but no instance could be generated.');
return;
}
- if (isset($task['data']['error']))
+ if (isset($task['data']['error'])) {
$error = $task['data']['error'];
- elseif (isset($task['data']['messages']))
+ } elseif (isset($task['data']['messages'])) {
$error = $task['data']['messages'];
- else
+ } else {
$error = '';
+ }
EventLog::failure("Generating module '" . $module->moduleTitle . "' failed.", $error);
- if ($args['deleteOnError'])
+ if ($args['deleteOnError'] ?? false) {
$module->delete();
- else
+ } else {
$module->markFailed();
+ }
}
/**
* (Re)generating a config module succeeded. Update db entry.
*
- * @param array $args contains 'moduleid' and optionally 'deleteOnError' and 'tmpTgz'
+ * @param array $args contains 'moduleid' and optionally 'tmpTgz'
*/
- public static function generateSucceeded($args)
+ public static function generateSucceeded(array $args): void
{
if (!isset($args['moduleid']) || !is_numeric($args['moduleid'])) {
EventLog::warning('Ignoring generateSucceeded event as it has no moduleid assigned.');
return;
}
$module = self::get($args['moduleid']);
- if ($module === false) {
+ if ($module === null) {
EventLog::warning('generateSucceeded callback for module id ' . $args['moduleid'] . ', but no instance could be generated.');
return;
}
- if (isset($args['tmpTgz']))
- $module->markUpdated($args['tmpTgz']);
- else
- $module->markUpdated(false);
+ $module->markUpdated($args['tmpTgz'] ?? null);
}
}
diff --git a/modules-available/sysconfig/inc/configmodule/branding.inc.php b/modules-available/sysconfig/inc/configmodule/branding.inc.php
index 8990dbec..7013e3ae 100644
--- a/modules-available/sysconfig/inc/configmodule/branding.inc.php
+++ b/modules-available/sysconfig/inc/configmodule/branding.inc.php
@@ -14,34 +14,34 @@ class ConfigModule_Branding extends ConfigModule
const MODID = 'Branding';
const VERSION = 1;
-
+
+ /** @var false|string */
private $tmpFile = false;
- protected function generateInternal($tgz, $parent)
+ protected function generateInternal(string $tgz, ?string $parent)
{
if (!$this->validateConfig()) {
- return $this->archive() !== false && file_exists($this->archive()); // No new temp file given, old archive still exists, pretend it worked...
+ return !empty($this->archive()) && file_exists($this->archive()); // No new temp file given, old archive still exists, pretend it worked...
}
- $task = Taskmanager::submit('MoveFile', array(
+ return Taskmanager::submit('MoveFile', array(
'source' => $this->tmpFile,
'destination' => $tgz,
'parentTask' => $parent,
'failOnParentFail' => false
));
- return $task;
}
- protected function moduleVersion()
+ protected function moduleVersion(): int
{
return self::VERSION;
}
- protected function validateConfig()
+ protected function validateConfig(): bool
{
return $this->tmpFile !== false && file_exists($this->tmpFile);
}
- public function setData($key, $value)
+ public function setData(string $key, $value): bool
{
if ($key !== 'tmpFile' || !is_string($value) || !file_exists($value))
return false;
@@ -49,12 +49,12 @@ class ConfigModule_Branding extends ConfigModule
return true;
}
- public function getData($key)
+ public function getData(?string $key): bool
{
return false;
}
- public function allowDownload()
+ public function allowDownload(): bool
{
return true;
}
diff --git a/modules-available/sysconfig/inc/configmodule/customodule.inc.php b/modules-available/sysconfig/inc/configmodule/customodule.inc.php
index 8b968336..0b8e38d2 100644
--- a/modules-available/sysconfig/inc/configmodule/customodule.inc.php
+++ b/modules-available/sysconfig/inc/configmodule/customodule.inc.php
@@ -13,15 +13,16 @@ class ConfigModule_CustomModule extends ConfigModule
{
const MODID = 'CustomModule';
const VERSION = 2;
-
+
+ /** @var false|string */
private $tmpFile = false;
- protected function generateInternal($tgz, $parent)
+ protected function generateInternal(string $tgz, ?string $parent)
{
if (!$this->validateConfig()) {
// No temp file given from wizard
// Old archive still exists? pretend it worked...
- if ($this->archive() === false || !file_exists($this->archive()))
+ if ($this->archive() === '' || !file_exists($this->archive()))
return false;
if ($this->currentVersion() == 1) {
// Need an upgrade
@@ -34,26 +35,25 @@ class ConfigModule_CustomModule extends ConfigModule
// Nothing to do
return true;
}
- $task = Taskmanager::submit('MoveFile', array(
+ return Taskmanager::submit('MoveFile', array(
'source' => $this->tmpFile,
'destination' => $tgz,
'parentTask' => $parent,
'failOnParentFail' => false
));
- return $task;
}
- protected function moduleVersion()
+ protected function moduleVersion(): int
{
return self::VERSION;
}
- protected function validateConfig()
+ protected function validateConfig(): bool
{
return $this->tmpFile !== false && file_exists($this->tmpFile);
}
- public function setData($key, $value)
+ public function setData(string $key, $value): bool
{
// Sets the temp file from the wizard, where it stored the processed archive
if ($key !== 'tmpFile' || !file_exists($value))
@@ -62,12 +62,12 @@ class ConfigModule_CustomModule extends ConfigModule
return true;
}
- public function getData($key)
+ public function getData(?string $key): bool
{
return false;
}
- public function allowDownload()
+ public function allowDownload(): bool
{
return true;
}
diff --git a/modules-available/sysconfig/inc/configmodule/ldapauth.inc.php b/modules-available/sysconfig/inc/configmodule/ldapauth.inc.php
index 7af4671e..64af4c0e 100644
--- a/modules-available/sysconfig/inc/configmodule/ldapauth.inc.php
+++ b/modules-available/sysconfig/inc/configmodule/ldapauth.inc.php
@@ -5,7 +5,7 @@ class ConfigModule_LdapAuth extends ConfigModuleBaseLdap
const MODID = 'LdapAuth';
- protected function preTaskmanagerHook(&$config)
+ protected function preTaskmanagerHook(array &$config)
{
// Just set the flag so the taskmanager job knows we're dealing with a normal ldap server,
// not AD scheme
diff --git a/modules-available/sysconfig/inc/configmodule/screensaver.inc.php b/modules-available/sysconfig/inc/configmodule/screensaver.inc.php
index ed97941e..1797331c 100644
--- a/modules-available/sysconfig/inc/configmodule/screensaver.inc.php
+++ b/modules-available/sysconfig/inc/configmodule/screensaver.inc.php
@@ -14,7 +14,7 @@ class ConfigModule_Screensaver extends ConfigModule
const MODID = 'Screensaver';
const VERSION = 1;
- protected function generateInternal($tgz, $parent)
+ protected function generateInternal(string $tgz, ?string $parent)
{
/* Validate if all data are available */
if (!$this->validateConfig())
@@ -23,30 +23,27 @@ class ConfigModule_Screensaver extends ConfigModule
/* Give the Taskmanager the job and create the tgz */
$taskId = 'xscreensaver' . mt_rand() . '-' . microtime(true);
- $task = Taskmanager::submit('MakeTarball', array(
+ return Taskmanager::submit('MakeTarball', array(
'id' => $taskId,
'files' => $this->getFileArray(),
'destination' => $tgz,
), false);
-
- return $task;
}
- protected function moduleVersion()
+ protected function moduleVersion(): int
{
return self::VERSION;
}
- protected function validateConfig()
+ protected function validateConfig(): bool
{
- return isset($this->moduleData['qss']) &&
- isset($this->moduleData['texts']) &&
- isset($this->moduleData['texts']['text-idle-kill']) &&
- isset($this->moduleData['texts']['text-no-timeout']) &&
- isset($this->moduleData['texts']['text-shutdown']);
+ return isset($this->moduleData['texts']['text-no-timeout'])
+ && isset($this->moduleData['texts']['text-idle-kill'])
+ && isset($this->moduleData['texts']['text-shutdown'])
+ && isset($this->moduleData['qss']);
}
- public function setData($key, $value)
+ public function setData(string $key, $value): bool
{
switch ($key) {
case 'qss':
@@ -60,17 +57,15 @@ class ConfigModule_Screensaver extends ConfigModule
return true;
}
- public function allowDownload()
+ public function allowDownload(): bool
{
return false;
}
/**
* Creates a map with filepath => file content
- *
- * @return array in the form of Map<String, byte[]>
*/
- private function getFileArray()
+ private function getFileArray(): array
{
$files = array(
'/opt/openslx/xscreensaver/style.qss' => $this->moduleData['qss'],
@@ -100,7 +95,7 @@ class ConfigModule_Screensaver extends ConfigModule
return $files;
}
- private function wrapHtmlTags($text_name)
+ private function wrapHtmlTags(string $text_name): string
{
return '<html><body>' . $this->moduleData['texts'][$text_name] . '</body></html>';
}
diff --git a/modules-available/sysconfig/inc/configmodule/sshconfig.inc.php b/modules-available/sysconfig/inc/configmodule/sshconfig.inc.php
index b5ab20e4..a62d1035 100644
--- a/modules-available/sysconfig/inc/configmodule/sshconfig.inc.php
+++ b/modules-available/sysconfig/inc/configmodule/sshconfig.inc.php
@@ -14,7 +14,7 @@ class ConfigModule_SshConfig extends ConfigModule
const MODID = 'SshConfig';
const VERSION = 1;
- protected function generateInternal($tgz, $parent)
+ protected function generateInternal(string $tgz, ?string $parent)
{
if (!$this->validateConfig())
return false;
@@ -26,12 +26,12 @@ class ConfigModule_SshConfig extends ConfigModule
return Taskmanager::submit('SshdConfigGenerator', $config);
}
- protected function moduleVersion()
+ protected function moduleVersion(): int
{
return self::VERSION;
}
- protected function validateConfig()
+ protected function validateConfig(): bool
{
// UPGRADE
if (isset($this->moduleData['allowPasswordLogin']) && !isset($this->moduleData['allowedUsersLogin'])) {
@@ -45,7 +45,7 @@ class ConfigModule_SshConfig extends ConfigModule
&& isset($this->moduleData['listenPort']);
}
- public function setData($key, $value)
+ public function setData(string $key, $value): bool
{
switch ($key) {
case 'publicKey':
diff --git a/modules-available/sysconfig/inc/configmodule/sshkey.inc.php b/modules-available/sysconfig/inc/configmodule/sshkey.inc.php
index 2d212d25..e4a55ad7 100644
--- a/modules-available/sysconfig/inc/configmodule/sshkey.inc.php
+++ b/modules-available/sysconfig/inc/configmodule/sshkey.inc.php
@@ -14,7 +14,7 @@ class ConfigModule_SshKey extends ConfigModule
const MODID = 'SshKey';
const VERSION = 1;
- protected function generateInternal($tgz, $parent)
+ protected function generateInternal(string $tgz, ?string $parent)
{
if (!$this->validateConfig())
return false;
@@ -30,17 +30,17 @@ class ConfigModule_SshKey extends ConfigModule
return Taskmanager::submit('MakeTarball', $config);
}
- protected function moduleVersion()
+ protected function moduleVersion(): int
{
return self::VERSION;
}
- protected function validateConfig()
+ protected function validateConfig(): bool
{
return isset($this->moduleData['publicKey']);
}
- public function setData($key, $value)
+ public function setData(string $key, $value): bool
{
switch ($key) {
case 'publicKey':
diff --git a/modules-available/sysconfig/inc/configmodulebaseldap.inc.php b/modules-available/sysconfig/inc/configmodulebaseldap.inc.php
index b6498aed..770a40e6 100644
--- a/modules-available/sysconfig/inc/configmodulebaseldap.inc.php
+++ b/modules-available/sysconfig/inc/configmodulebaseldap.inc.php
@@ -11,7 +11,7 @@ abstract class ConfigModuleBaseLdap extends ConfigModule
'shareOther', 'shareHomeDrive', 'shareDomain', 'credentialPassthrough', 'mapping', 'genuid',
'ldapAttrMountOpts', 'shareHomeMountOpts', 'nohomewarn');
- public static function getMapping($config = false, &$empty = true)
+ public static function getMapping(array $config = null, ?bool &$empty = true): array
{
$list = array(
['name' => 'uid', 'field' => 'uid', 'ad' => 'sAMAccountName'],
@@ -46,10 +46,10 @@ abstract class ConfigModuleBaseLdap extends ConfigModule
*
* @param string $command start, restart, check
* @param bool|int|int[] $ids list of IDs to run command on, or false meaning "all"
- * @param string $parent if not NULL, this will be the parent task of the launch-task
+ * @param string|null $parent if not NULL, this will be the parent task of the launch-task
* @return boolean|string false on error, id of task otherwise
*/
- public static function ldadp($command = 'start', $ids = false, $parent = null)
+ public static function ldadp(string $command = 'start', $ids = false, string $parent = null)
{
if ($ids === false) {
$ids = self::getActiveModuleIds();
@@ -67,7 +67,7 @@ abstract class ConfigModuleBaseLdap extends ConfigModule
return $task['id'];
}
- protected function generateInternal($tgz, $parent)
+ protected function generateInternal(string $tgz, ?string $parent)
{
$config = $this->moduleData;
if (isset($config['certificate']) && !is_string($config['certificate'])) {
@@ -96,8 +96,8 @@ abstract class ConfigModuleBaseLdap extends ConfigModule
$config['shareHomeDrive'] = 'H:';
}
// This is now always on, as we mask it transparently in our lightdm greeter
- $config['fixnumeric'] = 'yes';
- $config['genuid'] = isset($config['genuid']) && !empty($config['genuid']);
+ $config['fixnumeric'] = 'true';
+ $config['genuid'] = !empty($config['genuid']);
$config['nohomewarn'] = isset($config['nohomewarn']) ? (int)$config['nohomewarn'] : 0;
$this->preTaskmanagerHook($config);
$task = Taskmanager::submit('CreateLdapConfig', $config);
@@ -111,25 +111,23 @@ abstract class ConfigModuleBaseLdap extends ConfigModule
* Hook called before running CreateLdapConfig task with the
* configuration to be passed to the task. Passed by reference
* so it can be modified.
- *
- * @param array $config
*/
- protected function preTaskmanagerHook(&$config)
+ protected function preTaskmanagerHook(array &$config)
{
}
- protected function moduleVersion()
+ protected function moduleVersion(): int
{
return self::VERSION;
}
- protected function validateConfig()
+ protected function validateConfig(): bool
{
// Check if required fields are filled
- return Util::hasAllKeys($this->moduleData, self::$REQUIRED_FIELDS);
+ return ArrayUtil::hasAllKeys($this->moduleData, self::$REQUIRED_FIELDS);
}
- public function setData($key, $value)
+ public function setData(string $key, $value): bool
{
if (!in_array($key, self::$REQUIRED_FIELDS) && !in_array($key, self::$OPTIONAL_FIELDS))
return false;
@@ -142,7 +140,7 @@ abstract class ConfigModuleBaseLdap extends ConfigModule
/**
* Server IP changed - rebuild all AD modules.
*/
- public function event_serverIpChanged()
+ public function event_serverIpChanged(): void
{
$this->generate(false);
}
diff --git a/modules-available/sysconfig/inc/configtgz.inc.php b/modules-available/sysconfig/inc/configtgz.inc.php
index 98f29753..8ac87908 100644
--- a/modules-available/sysconfig/inc/configtgz.inc.php
+++ b/modules-available/sysconfig/inc/configtgz.inc.php
@@ -4,29 +4,28 @@ class ConfigTgz
{
private $configId = 0;
- private $configTitle = false;
- private $file = false;
+ private $configTitle = '';
+ private $file = '';
private $modules = array();
private function __construct()
{
- ;
}
- public function id()
+ public function id(): int
{
return $this->configId;
}
- public function title()
+ public function title(): string
{
return $this->configTitle;
}
- public function areAllModulesUpToDate()
+ public function areAllModulesUpToDate(): bool
{
if (!$this->configId > 0)
- Util::traceError('ConfigTgz::areAllModulesUpToDate called on un-inserted config.tgz!');
+ ErrorHandler::traceError('ConfigTgz::areAllModulesUpToDate called on un-inserted config.tgz!');
foreach ($this->modules as $module) {
if (!empty($module['filepath']) && file_exists($module['filepath'])) {
if ($module['status'] !== 'OK')
@@ -38,24 +37,29 @@ class ConfigTgz
return true;
}
- public function isActive()
+ public function isActive(): bool
{
return readlink(CONFIG_HTTP_DIR . '/default/config.tgz') === $this->file;
}
-
- public function getModuleIds()
+
+ /**
+ * @return int[]
+ */
+ public function getModuleIds(): array
{
- $ret = array();
+ $ret = [];
foreach ($this->modules as $module) {
- $ret[] = $module['moduleid'];
+ $ret[] = (int)$module['moduleid'];
}
return $ret;
}
-
- public function update($title, $moduleIds)
+
+ /**
+ * @param string $title New title for module
+ * @param int[] $moduleIds List of modules to include in this config
+ */
+ public function update(string $title, array $moduleIds): void
{
- if (!is_array($moduleIds))
- return false;
if (!empty($title)) {
$this->configTitle = $title;
}
@@ -69,7 +73,7 @@ class ConfigTgz
// Delete old connections
Database::exec("DELETE FROM configtgz_x_module WHERE configid = :configid", array('configid' => $this->configId));
// Make connection
- while ($row = $res->fetch(PDO::FETCH_ASSOC)) {
+ foreach ($res as $row) {
Database::exec("INSERT INTO configtgz_x_module (configid, moduleid) VALUES (:configid, :moduleid)", array(
'configid' => $this->configId,
'moduleid' => $row['moduleid']
@@ -83,20 +87,19 @@ class ConfigTgz
'status' => 'OUTDATED',
'now' => time(),
));
- return true;
}
/**
*
- * @param bool $deleteOnError
- * @param int $timeoutMs
- * @param string|null $parentTask parent task to order this rebuild after
+ * @param bool $deleteOnError Delete this config in case of error?
+ * @param int $timeoutMs max time to wait for completion
+ * @param string|null $parentTask parent task to order this (re)build after
* @return string|bool true=success, false=error, string=taskid, still running
*/
- public function generate($deleteOnError = false, $timeoutMs = 0, $parentTask = null)
+ public function generate(bool $deleteOnError = false, int $timeoutMs = 0, ?string $parentTask = null)
{
- if (!($this->configId > 0) || !is_array($this->modules) || $this->file === false)
- Util::traceError ('configId <= 0 or modules not array in ConfigTgz::rebuild()');
+ if (!($this->configId > 0) || empty($this->file))
+ ErrorHandler::traceError('configId <= 0 or no file in ConfigTgz::rebuild()');
$files = array();
// Get all config modules for system config
foreach ($this->modules as $module) {
@@ -134,33 +137,34 @@ class ConfigTgz
return $task['id'];
}
- public function delete()
+ public function delete(): bool
{
if ($this->configId === 0)
- Util::traceError('ConfigTgz::delete called with invalid config id!');
+ ErrorHandler::traceError('ConfigTgz::delete called with invalid config id!');
$ret = Database::exec("DELETE FROM configtgz WHERE configid = :configid LIMIT 1",
['configid' => $this->configId], true);
if ($ret !== false) {
- if ($this->file !== false)
+ if (!empty($this->file)) {
Taskmanager::submit('DeleteFile', array('file' => $this->file), true);
+ }
$this->configId = 0;
- $this->modules = false;
- $this->file = false;
+ $this->modules = [];
+ $this->file = '';
}
return $ret !== false;
}
- public function markOutdated()
+ public function markOutdated(): void
{
if ($this->configId === 0)
- Util::traceError('ConfigTgz::markOutdated called with invalid config id!');
- return $this->mark('OUTDATED');
+ ErrorHandler::traceError('ConfigTgz::markOutdated called with invalid config id!');
+ $this->mark('OUTDATED');
}
- private function markUpdated($task)
+ private function markUpdated(array $task): void
{
if ($this->configId === 0)
- Util::traceError('ConfigTgz::markUpdated called with invalid config id!');
+ ErrorHandler::traceError('ConfigTgz::markUpdated called with invalid config id!');
if ($this->areAllModulesUpToDate()) {
if (empty($task['data']['warnings'])) {
$warnings = '';
@@ -170,7 +174,7 @@ class ConfigTgz
// Get mapping of moduleid to module name for prettier log display
$res = Database::simpleQuery('SELECT moduleid, title FROM configtgz_module');
$mods = [];
- while ($row = $res->fetch(PDO::FETCH_ASSOC)) {
+ foreach ($res as $row) {
$mods[$row['moduleid']] = $row['title'];
}
// Now extract module id from filename and if applicable, replace filename by module name
@@ -186,27 +190,28 @@ class ConfigTgz
'status' => 'OK',
'warnings' => $warnings,
]);
- return 'OK';
+ return;
}
- return $this->mark('OUTDATED');
+ $this->mark('OUTDATED');
}
- private function markFailed()
+ private function markFailed(): void
{
if ($this->configId === 0)
- Util::traceError('ConfigTgz::markFailed called with invalid config id!');
- if ($this->file === false || !file_exists($this->file))
- return $this->mark('MISSING');
- return $this->mark('OUTDATED');
+ ErrorHandler::traceError('ConfigTgz::markFailed called with invalid config id!');
+ if (empty($this->file) || !file_exists($this->file)) {
+ $this->mark('MISSING');
+ } else {
+ $this->mark('OUTDATED');
+ }
}
- private function mark($status)
+ private function mark($status): void
{
Database::exec("UPDATE configtgz SET status = :status WHERE configid = :configid LIMIT 1", [
'configid' => $this->configId,
'status' => $status,
]);
- return $status;
}
/*
@@ -218,12 +223,12 @@ class ConfigTgz
* @param string $destFile where to store final result
* @return false|array taskmanager task
*/
- private static function recompress($files, $destFile, $parentTask = null)
+ private static function recompress(array $files, string $destFile, $parentTask = null)
{
// Get stuff other modules want to inject
$handler = function($hook) {
include $hook->file;
- return isset($file) ? $file : false;
+ return $file ?? false;
};
foreach (Hook::load('config-tgz') as $hook) {
$file = $handler($hook);
@@ -246,15 +251,15 @@ class ConfigTgz
* on each one. This mostly makes sense to call if a global module
* that is injected via a hook has changed.
*/
- public static function rebuildAllConfigs()
+ public static function rebuildAllConfigs(): void
{
Database::exec("UPDATE configtgz SET status = :status", array(
'status' => 'OUTDATED'
));
$res = Database::simpleQuery("SELECT configid FROM configtgz");
- while ($row = $res->fetch(PDO::FETCH_ASSOC)) {
+ foreach ($res as $row) {
$configTgz = self::get($row['configid']);
- if ($configTgz !== false) {
+ if ($configTgz !== null) {
$configTgz->generate();
}
}
@@ -263,12 +268,10 @@ class ConfigTgz
/**
* @param string $title Title of config
* @param int[] $moduleIds Modules to include in config
- * @return false|ConfigTgz The module instance, false on error
+ * @return ConfigTgz The module instance
*/
- public static function insert($title, $moduleIds)
+ public static function insert(string $title, array $moduleIds): ConfigTgz
{
- if (!is_array($moduleIds))
- return false;
$instance = new ConfigTgz;
$instance->configTitle = $title;
// Create output file name (config.tgz)
@@ -290,7 +293,7 @@ class ConfigTgz
}
$res = Database::simpleQuery("SELECT moduleid, moduletype, filepath, status FROM configtgz_module WHERE moduleid IN ($idstr)");
// Make connection
- while ($row = $res->fetch(PDO::FETCH_ASSOC)) {
+ foreach ($res as $row) {
Database::exec("INSERT INTO configtgz_x_module (configid, moduleid) VALUES (:configid, :moduleid)", array(
'configid' => $instance->configId,
'moduleid' => $row['moduleid']
@@ -300,53 +303,53 @@ class ConfigTgz
return $instance;
}
- public static function get($configId)
+ /**
+ * @param array{configid: int, title: string, filepath: string} $row Input data, fields mandatory
+ */
+ private static function instanceFromRow(array $row): ConfigTgz
{
- $ret = Database::queryFirst("SELECT configid, title, filepath FROM configtgz WHERE configid = :configid", array(
- 'configid' => $configId
- ));
- if ($ret === false)
- return false;
$instance = new ConfigTgz;
- $instance->configId = $ret['configid'];
- $instance->configTitle = $ret['title'];
- $instance->file = $ret['filepath'];
- $ret = Database::simpleQuery("SELECT moduleid, moduletype, filepath, status FROM configtgz_x_module "
+ $instance->configId = $row['configid'];
+ $instance->configTitle = $row['title'];
+ $instance->file = $row['filepath'];
+ $innerRes = Database::simpleQuery("SELECT moduleid, moduletype, filepath, status FROM configtgz_x_module "
. " INNER JOIN configtgz_module USING (moduleid) "
. " WHERE configid = :configid", array('configid' => $instance->configId));
$instance->modules = array();
- while ($row = $ret->fetch(PDO::FETCH_ASSOC)) {
- $instance->modules[] = $row;
+ foreach ($innerRes as $innerRow) {
+ $instance->modules[] = $innerRow;
}
return $instance;
}
+ public static function get(int $configId): ?ConfigTgz
+ {
+ $ret = Database::queryFirst("SELECT configid, title, filepath FROM configtgz WHERE configid = :configid", array(
+ 'configid' => $configId
+ ));
+ if ($ret === false)
+ return null;
+ return self::instanceFromRow($ret);
+ }
+
/**
* @param int $moduleId ID of config module
- * @return ConfigTgz[]|false
+ * @return ConfigTgz[]
*/
- public static function getAllForModule($moduleId)
+ public static function getAllForModule(int $moduleId): array
{
$res = Database::simpleQuery("SELECT configid, title, filepath FROM configtgz_x_module "
. " INNER JOIN configtgz USING (configid) "
. " WHERE moduleid = :moduleid", array(
'moduleid' => $moduleId
));
- if ($res === false)
- return false;
+ if ($res === false) {
+ EventLog::warning('ConfigTgz::getAllForModule failed: ' . Database::lastError());
+ return [];
+ }
$list = array();
- while ($row = $res->fetch(PDO::FETCH_ASSOC)) {
- $instance = new ConfigTgz;
- $instance->configId = $row['configid'];
- $instance->configTitle = $row['title'];
- $instance->file = $row['filepath'];
- $innerRes = Database::simpleQuery("SELECT moduleid, moduletype, filepath, status FROM configtgz_x_module "
- . " INNER JOIN configtgz_module USING (moduleid) "
- . " WHERE configid = :configid", array('configid' => $instance->configId));
- $instance->modules = array();
- while ($innerRow = $innerRes->fetch(PDO::FETCH_ASSOC)) {
- $instance->modules[] = $innerRow;
- }
+ foreach ($res as $row) {
+ $instance = self::instanceFromRow($row);
$list[] = $instance;
}
return $list;
@@ -356,31 +359,32 @@ class ConfigTgz
* Called when (re)generating a config tgz failed, so we can
* update the status in the DB and add a server log entry.
*
- * @param array $task
* @param array $args contains 'configid' and optionally 'deleteOnError'
*/
- public static function generateFailed($task, $args)
+ public static function generateFailed(array $task, array $args): void
{
if (!isset($args['configid']) || !is_numeric($args['configid'])) {
EventLog::warning('Ignoring generateFailed event as it has no configid assigned.');
return;
}
$config = self::get($args['configid']);
- if ($config === false) {
+ if ($config === null) {
EventLog::warning('generateFailed callback for config id ' . $args['configid'] . ', but no instance could be generated.');
return;
}
- if (isset($task['data']['error']))
+ if (isset($task['data']['error'])) {
$error = $task['data']['error'];
- elseif (isset($task['data']['messages']))
+ } elseif (isset($task['data']['messages'])) {
$error = $task['data']['messages'];
- else
+ } else {
$error = '';
+ }
EventLog::failure("Generating config.tgz '" . $config->configTitle . "' failed.", $error);
- if ($args['deleteOnError'])
+ if ($args['deleteOnError']) {
$config->delete();
- else
+ } else {
$config->markFailed();
+ }
}
/**
@@ -389,14 +393,14 @@ class ConfigTgz
* @param array $task the task object
* @param array $args contains 'configid' and optionally 'deleteOnError'
*/
- public static function generateSucceeded($task, $args)
+ public static function generateSucceeded(array $task, array $args): void
{
if (!isset($args['configid']) || !is_numeric($args['configid'])) {
EventLog::warning('Ignoring generateSucceeded event as it has no configid assigned.');
return;
}
$config = self::get($args['configid']);
- if ($config === false) {
+ if ($config === null) {
EventLog::warning('generateSucceeded callback for config id ' . $args['configid'] . ', but no instance could be generated.');
return;
}
diff --git a/modules-available/sysconfig/inc/ldap.inc.php b/modules-available/sysconfig/inc/ldap.inc.php
index 349a662e..e974a8a3 100644
--- a/modules-available/sysconfig/inc/ldap.inc.php
+++ b/modules-available/sysconfig/inc/ldap.inc.php
@@ -3,7 +3,7 @@
class Ldap
{
- public static function normalizeDn($dn)
+ public static function normalizeDn(string $dn): string
{
return trim(preg_replace('/[,;]\s*/', ',', $dn));
}
diff --git a/modules-available/sysconfig/inc/ppd.inc.php b/modules-available/sysconfig/inc/ppd.inc.php
index 9bd5d171..c28e0355 100644
--- a/modules-available/sysconfig/inc/ppd.inc.php
+++ b/modules-available/sysconfig/inc/ppd.inc.php
@@ -247,8 +247,8 @@ class Ppd
private $data;
private $dataLen;
- private $error;
- private $warnings;
+ private $error = null;
+ private $warnings = [];
private $knownKeywordMalformed;
@@ -301,16 +301,16 @@ class Ppd
$this->dataLen = strlen($this->data);
$this->encoder = false;
$this->sourceEncoding = false;
- $this->error = false;
+ $this->error = null;
$this->warnings = array();
$this->knownKeywordMalformed = false;
$this->settings = array();
$this->requiredKeywords = array();
// Parse
- /* @var $rawOption \PpdOption */
- /* @var $currentBlock \PpdBlockInternal */
- $currentBlock = false;
+ /* @var PpdOption $rawOption */
+ /* @var ?PpdBlockInternal $currentBlock */
+ $currentBlock = null;
$inRawBlock = false; // True if in a multi-line InvocationValue or QuotedValue (3.6: Parsing Summary for Values)
$wantsEnd = false;
// For now we ignore values mostly while parsing. The spec says that InvocationValues must only contain printable
@@ -318,9 +318,9 @@ class Ppd
$lStart = -1;
$lEnd = -1;
$no = 0;
- while ($lStart < $this->dataLen && $lEnd !== false) {
+ while ($lStart < $this->dataLen) {
unset($mainKeyword, $optionKeyword, $optionTranslation, $option, $value, $valueTranslation);
- if ($no !== 0 && $this->data{$lEnd} === "\r" && $this->data{$lEnd + 1} === "\n") {
+ if ($no !== 0 && $this->data[$lEnd] === "\r" && $this->data[$lEnd + 1] === "\n") {
$lEnd++;
}
if ($no === 1) {
@@ -332,6 +332,8 @@ class Ppd
}
$lStart = $lEnd + 1;
$lEnd = $this->nextLineEnd($lStart);
+ if ($lEnd === null)
+ break;
$no++;
// Validate
$len = $lEnd - $lStart;
@@ -343,7 +345,7 @@ class Ppd
$this->warn($no, 'Exceeds length of 255');
}
if (!$inRawBlock && preg_match_all('/[^\x09\x0A\x0D\x20-\xFF]/', $line, $out)) {
- $chars = $this->escapeBinaryArray($out[0]);
+ $chars = self::escapeBinaryArray($out[0]);
$this->warn($no, 'Contains invalid character(s) ' . $chars);
}
// Handle
@@ -373,13 +375,13 @@ class Ppd
}
}
// 3) Handle "key [option]: value"
- if ($line{0} === '*') {
- if ($line{1} === '%') {
+ if ($line[0] === '*') {
+ if ($line[1] === '%') {
// Skip comment
continue;
}
$parts = preg_split('/\s*:\s*/', $line, 2); // TODO: UIConstrains
- if (count($parts) !== 2) {
+ if (!is_array($parts) || count($parts) !== 2) {
$this->warn($no, 'No colon found; not in "key [option]: value" format, ignoring line');
continue;
}
@@ -390,11 +392,12 @@ class Ppd
continue;
}
$mainKeyword = $out[1];
- $optionKeyword = isset($out[3]) ? $out[3] : false;
+ $optionKeyword = $out[3] ?? null;
$optionTranslation = isset($out[4]) ? $this->unhexTranslation($no, substr($out[4], 1)) : $optionKeyword; // If no translation given, fallback to option
// 3b) Handle value
+ /** @var string $value */
$value = $parts[1];
- if ($value{0} === '"') {
+ if ($value[0] === '"') {
// Start of InvocationValue or QuotedValue
if (preg_match(',^"([^"]*)"(/.*)?$,', $value, $vMatch)) {
// Single line
@@ -419,28 +422,23 @@ class Ppd
// Key-value-pair parsed, now the fun part
// Special cases for opening closing certain groups
if ($mainKeyword === 'OpenGroup') {
- if ($currentBlock !== false) {
+ if ($currentBlock !== null) {
$this->error = 'Line ' . $no . ': OpenGroup while other block (type=' . $currentBlock->type
. ', id=' . $currentBlock->id . ') was not closed yet';
return;
}
// TODO: Check unique
- $nb = new PpdBlockInternal($value, $valueTranslation, 'Group', $currentBlock, $lStart);
- if ($currentBlock !== false) {
- $currentBlock->childBlocks[] = $nb;
- }
+ $nb = new PpdBlockInternal($value, $valueTranslation, 'Group', null, $lStart);
$currentBlock = $nb;
continue;
} elseif ($mainKeyword === 'OpenSubGroup') {
- if ($currentBlock === false || $currentBlock->type !== 'Group') {
+ if ($currentBlock === null || $currentBlock->type !== 'Group') {
$this->error = 'Line ' . $no . ': OpenSubGroup with no preceding OpenGroup';
return;
}
// TODO: Check unique
$nb = new PpdBlockInternal($value, $valueTranslation, 'SubGroup', $currentBlock, $lStart);
- if ($currentBlock !== false) {
- $currentBlock->childBlocks[] = $nb;
- }
+ $currentBlock->childBlocks[] = $nb;
$currentBlock = $nb;
continue;
} elseif ($mainKeyword === 'OpenUI' || $mainKeyword === 'JCLOpenUI') {
@@ -450,23 +448,24 @@ class Ppd
} else {
$type = substr($type, 4);
}
- if ($currentBlock !== false && $currentBlock->isUi()) {
+ if ($currentBlock !== null && $currentBlock->isUi()) {
$this->error = 'Line ' . $no . ': ' . $mainKeyword . ' while previous ' . $type . ' "'
. $currentBlock->id . '" was not closed yet';
return;
}
- if ($optionKeyword === false) {
+ if ($optionKeyword === null) {
$this->error = 'Line ' . $no . ': ' . $mainKeyword . ' with no option keyword';
return;
}
- if ($optionKeyword{0} !== '*') {
+ if ($optionKeyword[0] !== '*') {
$this->error = 'Line ' . $no . ': ' . $mainKeyword . " with option keyword that doesn't start with asterisk (*).";
return;
}
// TODO: Check unique
- $nb = new PpdBlockInternal($optionKeyword, $optionTranslation, $type, $currentBlock, $lStart);
+ $nb = new PpdBlockInternal($optionKeyword, $optionTranslation ?? $optionKeyword,
+ $type, $currentBlock, $lStart);
$nb->value = $value;
- if ($currentBlock !== false) {
+ if ($currentBlock !== null) {
$currentBlock->childBlocks[] = $nb;
}
$currentBlock = $nb;
@@ -481,7 +480,7 @@ class Ppd
} else {
$type = substr($type, 5);
}
- if ($currentBlock === false) {
+ if ($currentBlock === null) {
$this->error = 'Line ' . $no . ': ' . $mainKeyword . ' with no Open' . $type;
return;
}
@@ -498,7 +497,7 @@ class Ppd
$currentBlock = $currentBlock->parent;
continue;
} elseif ($mainKeyword === 'OrderDependency') {
- if ($currentBlock === false || $currentBlock->isUi()) {
+ if ($currentBlock === null || $currentBlock->isUi()) {
$this->warn($no, 'OrderDependency outside OpenUI/CloseUI block');
}
continue;
@@ -521,9 +520,10 @@ class Ppd
$this->warn($no, 'Required keyword ' . $mainKeyword . ' declared twice, ignoring');
continue;
}
+ } else {
+ $this->requiredKeywords[$mainKeyword] = array($value);
}
- $this->requiredKeywords[$mainKeyword] = array($value);
- if (($err = $this->validateLine($this->REQUIRED_KEYWORDS[$mainKeyword], $optionKeyword, $value)) !== true) {
+ if (($err = Ppd::validateLine($this->REQUIRED_KEYWORDS[$mainKeyword], $optionKeyword, $value)) !== true) {
$this->warn($no, 'Required main keyword ' . $mainKeyword . ': ' . $err);
$this->knownKeywordMalformed = true;
}
@@ -531,7 +531,7 @@ class Ppd
}
// Other well known keywords
if (isset($this->KNOWN_KEYWORDS[$mainKeyword])) {
- if (($err = $this->validateLine($this->KNOWN_KEYWORDS[$mainKeyword], $optionKeyword, $value)) !== true) {
+ if (($err = Ppd::validateLine($this->KNOWN_KEYWORDS[$mainKeyword], $optionKeyword, $value)) !== true) {
$this->warn($no, 'Known main keyword ' . $mainKeyword . ': ' . $err);
$this->knownKeywordMalformed = true;
}
@@ -541,17 +541,18 @@ class Ppd
$option = $this->getOption(substr($mainKeyword, 7), $currentBlock);
$option->default = new PpdOption($lStart, $len, $value, $valueTranslation);
continue;
- } elseif (substr($mainKeyword, 0, 17) === 'FoomaticRIPOption') {
- if ($optionKeyword === false) {
+ }
+ if (substr($mainKeyword, 0, 17) === 'FoomaticRIPOption') {
+ if ($optionKeyword === null) {
$this->warn($no, "$mainKeyword with no option keyword");
- } elseif ($currentBlock !== false && isset($this->settings[$optionKeyword])) {
+ } elseif ($currentBlock !== null && isset($this->settings[$optionKeyword])) {
$option = $this->getOption($optionKeyword, $currentBlock);
$option->foomatic[substr($mainKeyword, 11)] = new PpdOption($lStart, $len, $value, $valueTranslation);
} else {
$this->warn($no, 'TODO: ' . $line);
}
} elseif (substr($mainKeyword, 0, 6) === 'Custom') {
- if ($optionKeyword === false) {
+ if ($optionKeyword === null) {
$this->warn($no, "$mainKeyword with no option keyword");
} elseif ($optionKeyword !== 'True') {
$this->warn($no, "$mainKeyword with option keyword other than 'True'; ignored");
@@ -560,7 +561,7 @@ class Ppd
$option->custom = new PpdOption($lStart, $len, $value, $valueTranslation);
}
} elseif (substr($mainKeyword, 0, 11) === 'ParamCustom') {
- if ($optionKeyword === false) {
+ if ($optionKeyword === null) {
$this->warn($no, "$mainKeyword with no option keyword");
} elseif (substr($mainKeyword, 11) !== $optionKeyword) {
$this->warn($no, "Don't know how to handle $mainKeyword with option keyword $optionKeyword "
@@ -569,20 +570,20 @@ class Ppd
$option = $this->getOption($optionKeyword, $currentBlock);
$option->customParam = new PpdOption($lStart, $len, $value, $valueTranslation);
}
- } elseif ($mainKeyword{0} === '?') {
+ } elseif ($mainKeyword[0] === '?') {
// Ignoring option query for now
- } elseif ($optionKeyword === false && !isset($this->KNOWN_KEYWORDS[$mainKeyword])) {
+ } elseif ($optionKeyword === null && !isset($this->KNOWN_KEYWORDS[$mainKeyword])) {
// Must be a definition for an option
$this->warn($no, "Don't know how to handle line with main keyword '$mainKeyword', no option keyword found.");
} else {
// Some option for some option ;)
- if ($optionKeyword === false) {
+ if ($optionKeyword === null) {
// We know that this is a known main keyword otherwise we would have hit the previous elseif block
$optionKeyword = $value;
$optionTranslation = $valueTranslation;
}
$option = $this->getOption($mainKeyword, $currentBlock);
- $optionInstance = new PpdOption($lStart, $len, $optionKeyword, $optionTranslation);
+ $optionInstance = new PpdOption($lStart, $len, $optionKeyword, $optionTranslation ?? $optionKeyword);
if ($this->binary_in_array($mainKeyword, $this->REPEATED_KEYWORDS)) {
// This can occur multiple times, just pile them up
$option->values[] = $optionInstance;
@@ -603,9 +604,9 @@ class Ppd
} elseif (strlen(trim($line)) !== 0) {
$this->warn($no, 'Invalid format; not empty and not starting with asterisk (*)');
}
- }
+ } // end while loop over ppd contents
//
- if ($currentBlock !== false) {
+ if ($currentBlock !== null) {
$this->error = 'Block ' . $currentBlock->id . ' (' . $currentBlock->type . ') was never closed.';
return;
}
@@ -615,11 +616,11 @@ class Ppd
$this->error = 'One or more required keywords missing';
}
}
- if ($this->error !== false) {
+ if ($this->error !== null) {
return;
}
// All required keywords exist
- if (preg_match('/utf\-?8/i', $this->requiredKeywords['LanguageEncoding'][0])) {
+ if (preg_match('/utf-?8/i', $this->requiredKeywords['LanguageEncoding'][0])) {
$this->sourceEncoding = false; // Would be a NOOP
} elseif (isset($this->ENCODINGS[$this->requiredKeywords['LanguageEncoding'][0]])) {
$this->sourceEncoding = $this->ENCODINGS[$this->requiredKeywords['LanguageEncoding'][0]];
@@ -669,12 +670,12 @@ class Ppd
}
}
- private function nextLineEnd($start)
+ private function nextLineEnd(int $start): ?int
{
if ($start >= $this->dataLen)
- return false;
+ return null;
while ($start < $this->dataLen) {
- $char = $this->data{$start};
+ $char = $this->data[$start];
if ($char === "\r" || $char === "\n")
return $start;
++$start;
@@ -682,27 +683,26 @@ class Ppd
return $this->dataLen;
}
- private function warn($lineNo, $message)
+ private function warn(int $lineNo, string $message): void
{
$line = 'Line ' . $lineNo . ': ' . $message;
$this->warnings[] = $line;
}
- private function escapeBinaryArray($array)
+ private static function escapeBinaryArray(array $array): string
{
- $chars = array_reduce(array_unique($array), function ($carry, $item) {
+ return array_reduce(array_unique($array), function ($carry, $item) {
return $carry . '\x' . dechex(ord($item));
}, '');
- return $chars;
}
- private function unhexTranslation($lineNo, $translation)
+ private function unhexTranslation(int $lineNo, string $translation): string
{
if (strpos($translation, '<') === false)
return $translation;
return preg_replace_callback('/<[^>]*>/', function ($match) use ($lineNo) {
if (preg_match_all('/[^a-fA-F0-9\<\>\s]/', $match[0], $out)) {
- $this->warn($lineNo, 'Invalid character(s) in hex substring: ' . $this->escapeBinaryArray($out[0]));
+ $this->warn($lineNo, 'Invalid character(s) in hex substring: ' . self::escapeBinaryArray($out[0]));
}
$string = preg_replace('/[^a-fA-F0-9]/', '', $match[0]);
if (strlen($string) % 2 !== 0) {
@@ -713,7 +713,7 @@ class Ppd
}, $translation);
}
- private function hexTranslation($translation)
+ private function hexTranslation(string $translation): string
{
return preg_replace_callback('/[\x00-\x1f\x7b-\xff\:\<\>]+/', function ($match) {
return '<' . unpack('H*', $match[0])[1] . '>';
@@ -724,23 +724,23 @@ class Ppd
* Get option object
*
* @param string $name option name
- * @param \PpdBlockInternal $block which block this option is defined in
- * @return \PpdSettingInternal the option object
+ * @param ?PpdBlockInternal $block which block this option is defined in
+ * @return PpdSettingInternal the option object
*/
- private function getOption($name, $block = false)
+ private function getOption(string $name, ?PpdBlockInternal $block = null): PpdSettingInternal
{
if (!isset($this->settings[$name])) {
$this->settings[$name] = new PpdSettingInternal();
$this->settings[$name]->block = $block;
- } elseif ($block !== false) {
- if ($this->settings[$name]->block === false || $block->isChildOf($this->settings[$name]->block)) {
+ } elseif ($block !== null) {
+ if ($this->settings[$name]->block === null || $block->isChildOf($this->settings[$name]->block)) {
$this->settings[$name]->block = $block;
}
}
return $this->settings[$name];
}
- private function binary_in_array($elem, $array)
+ private function binary_in_array($elem, $array): bool
{
$top = sizeof($array) - 1;
$bot = 0;
@@ -755,7 +755,7 @@ class Ppd
return false;
}
- private function validateLine($validator, $option, $value)
+ private static function validateLine($validator, ?string $option, string $value)
{
if (is_array($validator)) {
$oExp = $validator[0];
@@ -780,7 +780,7 @@ class Ppd
return true;
}
- private function getEolChar()
+ private function getEolChar(): string
{
$rn = substr_count("\r\n", $this->data);
$r = substr_count("\r", $this->data) - $rn;
@@ -799,21 +799,21 @@ class Ppd
*
*/
- public function getError()
+ public function getError(): ?string
{
return $this->error;
}
- public function getWarnings()
+ public function getWarnings(): array
{
return $this->warnings;
}
- public function getUISettings()
+ public function getUISettings(): array
{
$result = array();
foreach ($this->settings as $mk => $option) {
- $isUi = ($option->block !== false && $option->block->isUi()) || isset($this->UI_KEYWORDS[$mk]);
+ $isUi = ($option->block !== null && $option->block->isUi()) || isset($this->UI_KEYWORDS[$mk]);
if ($isUi) {
$result[] = $mk;
}
@@ -821,30 +821,30 @@ class Ppd
return $result;
}
- public function getSetting($name)
+ public function getSetting(string $name): ?PpdSetting
{
if (!isset($this->settings[$name]))
- return false;
+ return null;
return new PpdSetting($this->settings[$name], isset($this->UI_KEYWORDS[$name]), $this->encoder);
}
- public function removeSetting($name)
+ public function removeSetting(string $name): bool
{
if (!isset($this->settings[$name]))
return false;
$setting = $this->settings[$name];
$ranges = array();
- $this->mergeRanges($ranges, $setting->default);
- $this->mergeRanges($ranges, $setting->custom);
- $this->mergeRanges($ranges, $setting->customParam);
+ Ppd::mergeRangesFromOption($ranges, $setting->default);
+ Ppd::mergeRangesFromOption($ranges, $setting->custom);
+ Ppd::mergeRangesFromOption($ranges, $setting->customParam);
foreach ($setting->foomatic as $obj) {
- $this->mergeRanges($ranges, $obj);
+ Ppd::mergeRangesFromOption($ranges, $obj);
}
foreach ($setting->values as $obj) {
- $this->mergeRanges($ranges, $obj);
+ Ppd::mergeRangesFromOption($ranges, $obj);
}
- if ($setting->block !== false && $setting->block->isUi()) {
- $this->mergeRanges($ranges, $setting->block->start, $setting->block->end);
+ if ($setting->block !== null && $setting->block->isUi()) {
+ Ppd::mergeRanges($ranges, $setting->block->start, $setting->block->end);
}
$tmp = array_map(function ($e) { return $e[0]; }, $ranges);
array_multisort($tmp, SORT_NUMERIC, $ranges);
@@ -853,20 +853,20 @@ class Ppd
foreach ($ranges as $range) {
$new .= substr($this->data, $last, $range[0] - $last);
$last = $range[1];
- if ($this->data{$last} === "\r") {
+ if ($this->data[$last] === "\r") {
$last++;
}
- if ($this->data{$last} === "\n") {
+ if ($this->data[$last] === "\n") {
$last++;
}
}
$new .= substr($this->data, $last);
$this->data = $new;
$this->parse();
- return $this->error === false;
+ return $this->error === null;
}
- public function addEmptyOption($settingName, $option, $translation = false, $prepend = true)
+ public function addEmptyOption(string $settingName, string $option, string $translation = null, bool $prepend = true): bool
{
if (!isset($this->settings[$settingName]))
return false;
@@ -874,15 +874,15 @@ class Ppd
$pos = false;
if (!empty($setting->values)) {
if ($prepend) {
- $pos = array_reduce($setting->values, function ($carry, $option) { return min($carry, $option->lineOffset); }, PHP_INT_MAX);
+ $pos = array_reduce($setting->values, function (int $carry, PpdOption $option) { return min($carry, $option->lineOffset); }, PHP_INT_MAX);
} else {
- $pos = array_reduce($setting->values, function ($carry, $option) { return max($carry, $option->lineOffset); }, 0);
+ $pos = array_reduce($setting->values, function (int $carry, PpdOption $option) { return max($carry, $option->lineOffset); }, 0);
}
- } elseif ($setting->default !== false) {
+ } elseif ($setting->default !== null) {
$pos = $setting->default->lineOffset;
- } elseif ($setting->block !== false && $setting->block->isUi()) {
+ } elseif ($setting->block !== null && $setting->block->isUi()) {
$pos = $this->nextLineEnd($setting->block->start);
- while ($pos !== false && $pos < $this->dataLen && ($this->data{$pos} === "\r" || $this->data{$pos} === "\n")) {
+ while ($pos !== null && $pos < $this->dataLen && ($this->data[$pos] === "\r" || $this->data[$pos] === "\n")) {
$pos++;
}
}
@@ -890,23 +890,23 @@ class Ppd
return false;
}
$line = '*' . $settingName . ' ' . $option;
- if ($translation !== false) {
+ if ($translation !== null) {
$line .= '/' . $this->hexTranslation(($this->encoder)($translation, true));
}
$eol = $this->getEolChar();
$line .= ': ""' . $eol;
$this->data = substr($this->data, 0, $pos) . $line . substr($this->data, $pos);
$this->parse();
- return $this->error === false;
+ return $this->error === null;
}
- public function setDefaultOption($settingName, $optionName)
+ public function setDefaultOption($settingName, $optionName): bool
{
if (!isset($this->settings[$settingName]))
return false;
$setting = $this->settings[$settingName];
$line = '*Default' . $settingName . ': ' . $optionName;
- if ($setting->default !== false) {
+ if ($setting->default !== null) {
$start = $setting->default->lineOffset;
$end = $start + $setting->default->lineLen;
} elseif (empty($setting->values)) {
@@ -918,22 +918,21 @@ class Ppd
}
$this->data = substr($this->data, 0, $start) . $line . substr($this->data, $end);
$this->parse();
- return $this->error === false;
+ return $this->error === null;
}
- public function write($file)
+ public function write(string $file)
{
return file_put_contents($file, $this->data);
}
- private function mergeRanges(&$ranges, $start, $end = false)
+ private static function mergeRangesFromOption(array &$ranges, PpdOption $option): void
+ {
+ self::mergeRanges($ranges, $option->lineOffset, $option->lineOffset + $option->lineLen);
+ }
+
+ private static function mergeRanges(array &$ranges, int $start, int $end): void
{
- if (is_object($start) && get_class($start) === 'PpdOption') {
- $end = $start->lineOffset + $start->lineLen;
- $start = $start->lineOffset;
- }
- if ($start === false || $end === false)
- return;
if ($start >= $end)
return; // Don't even bother
foreach (array_keys($ranges) as $key) {
@@ -956,7 +955,7 @@ class Ppd
// $start must lie before range start, otherwise we'd have hit the case above
$end = $ranges[$key][1];
unset($ranges[$key]);
- continue;
+ //continue;
}
}
$ranges[] = array($start, $end);
@@ -965,7 +964,7 @@ class Ppd
/**
* @return bool whether there was at least one known option with format restriction violated.
*/
- public function hasInvalidOption()
+ public function hasInvalidOption(): bool
{
return $this->knownKeywordMalformed;
}
@@ -1013,15 +1012,13 @@ class PpdSetting
/**
* PpdSetting constructor.
- *
- * @param \PpdSettingInternal $setting
*/
- public function __construct($setting, $isUi, $enc)
+ public function __construct(PpdSettingInternal $setting, bool $isUi, callable $enc)
{
- if ($setting->default !== false) {
+ if ($setting->default !== null) {
$this->default = $setting->default->option;
}
- if ($setting->block !== false && $setting->block->isUi()) {
+ if ($setting->block !== null && $setting->block->isUi()) {
$this->uiOptionType = $setting->block->value;
$this->uiOptionTranslation = $enc($setting->block->translation);
$this->isUi = true;
@@ -1055,9 +1052,9 @@ class PpdSetting
class PpdSettingInternal
{
/**
- * @var \PpdOption
+ * @var ?PpdOption
*/
- public $default = false;
+ public $default = null;
/**
* @var \PpdOption[]
*/
@@ -1067,17 +1064,17 @@ class PpdSettingInternal
*/
public $foomatic = array();
/**
- * @var \PpdOption
+ * @var ?PpdOption
*/
- public $custom = false;
+ public $custom = null;
/**
- * @var \PpdOption
+ * @var ?PpdOption
*/
- public $customParam = false;
+ public $customParam = null;
/**
- * @var \PpdBlockInternal the innermost block this option resides in
+ * @var ?PpdBlockInternal the innermost block this option resides in
*/
- public $block = false;
+ public $block = null;
}
class PpdOption
@@ -1088,7 +1085,7 @@ class PpdOption
public $lineLen;
public $multiLine = false;
- public function __construct($lineOffset, $lineLen, $option, $optionTranslation)
+ public function __construct(int $lineOffset, int $lineLen, string $option, string $optionTranslation)
{
$this->option = $option;
$this->optionTranslation = $optionTranslation;
@@ -1106,13 +1103,13 @@ class PpdBlockInternal
public $translation;
public $type;
/**
- * @var \PpdBlockInternal[]
+ * @var PpdBlockInternal[]
*/
public $childBlocks = array();
/**
- * @var \PpdBlockInternal
+ * @var ?PpdBlockInternal
*/
- public $parent;
+ public $parent = null;
/**
* @var int start byte in ppd
@@ -1120,16 +1117,16 @@ class PpdBlockInternal
public $start;
/**
- * @var int|bool end byte in ppd, false if block is not closed
+ * @var ?int end byte in ppd, null if block is not closed
*/
- public $end = false;
+ public $end = null;
/**
* @var string value of opening line for block, e.g. 'PickOne' for OpenUI
*/
- public $value = false;
+ public $value = '';
- public function __construct($id, $translation, $type, $parent, $start)
+ public function __construct(string $id, string $translation, string $type, ?PpdBlockInternal $parent, int $start)
{
$this->id = $id;
$this->translation = $translation;
@@ -1141,16 +1138,16 @@ class PpdBlockInternal
/**
* @return bool true if this is a UI block
*/
- public function isUi()
+ public function isUi(): bool
{
return $this->type == 'UI' || $this->type === 'JCLUI';
}
/**
- * @param \PpdBlockInternal $block some other PpdBlock instance
+ * @param PpdBlockInternal $block some other PpdBlock instance
* @return bool true if this is a child of $block
*/
- public function isChildOf($block)
+ public function isChildOf(PpdBlockInternal $block): bool
{
$parent = $this->parent;
while ($parent !== false) {
diff --git a/modules-available/sysconfig/inc/sysconfig.inc.php b/modules-available/sysconfig/inc/sysconfig.inc.php
index 9ad3a36f..09860c7d 100644
--- a/modules-available/sysconfig/inc/sysconfig.inc.php
+++ b/modules-available/sysconfig/inc/sysconfig.inc.php
@@ -3,12 +3,12 @@
class SysConfig
{
- public static function getAll()
+ public static function getAll(): array
{
$res = Database::simpleQuery("SELECT c.configid, c.title, c.filepath, c.status, Group_Concat(cl.locationid) AS locs FROM configtgz c"
. " LEFT JOIN configtgz_location cl USING (configid) GROUP BY c.configid");
$ret = array();
- while ($row = $res->fetch(PDO::FETCH_ASSOC)) {
+ foreach ($res as $row) {
$ret[] = $row;
}
return $ret;
diff --git a/modules-available/sysconfig/install.inc.php b/modules-available/sysconfig/install.inc.php
index 3f80ffe6..53882882 100644
--- a/modules-available/sysconfig/install.inc.php
+++ b/modules-available/sysconfig/install.inc.php
@@ -87,7 +87,7 @@ if (!tableHasColumn('configtgz_module', 'dateline')) {
$update[] = UPDATE_DONE;
// Infer from module's filemtime
$res = Database::simpleQuery('SELECT moduleid, filepath FROM configtgz_module');
- while ($row = $res->fetch(PDO::FETCH_ASSOC)) {
+ foreach ($res as $row) {
Database::exec('UPDATE configtgz_module SET dateline = :mtime WHERE moduleid = :moduleid',
['moduleid' => $row['moduleid'], 'mtime' => filemtime($row['filepath'])]);
}
@@ -102,7 +102,7 @@ if (!tableHasColumn('configtgz', 'dateline')) {
INNER JOIN configtgz_x_module cxm USING (configid)
INNER JOIN configtgz_module m USING (moduleid)
GROUP BY configid');
- while ($row = $res->fetch(PDO::FETCH_ASSOC)) {
+ foreach ($res as $row) {
Database::exec('UPDATE configtgz SET dateline = :mtime WHERE configid = :configid',
['configid' => $row['configid'], 'mtime' => $row['dateline']]);
}
@@ -125,28 +125,28 @@ Module::isAvailable('sysconfig');
$list = ConfigModule::getAll();
$parentTask = null;
$configList = [];
-if ($list === false) {
+if ($list === null) {
EventLog::warning('Could not regenerate configs - please do so manually');
} else {
- foreach ($list as $ad) {
- if ($ad->moduleType() === 'SshConfig') {
+ foreach ($list as $confMod) {
+ if ($confMod->moduleType() === 'SshConfig') {
// 2020-11-12: Split SshConfig into SshConfig and SshKey
- $pubkey = $ad->getData('publicKey');
- if ($pubkey !== false && !empty($pubkey)) {
- error_log('Legacy module with pubkey ' . $ad->id());
- $key = ConfigModule::getInstance('SshKey');
- if ($key !== false) {
+ $pubkey = $confMod->getData('publicKey');
+ if (!empty($pubkey)) {
+ error_log('Legacy module with pubkey ' . $confMod->id());
+ $key = ConfigModule::getInstanceOrNull('SshKey');
+ if ($key !== null) {
$key->setData('publicKey', $pubkey);
- if ($key->insert($ad->title())) {
+ if ($key->insert($confMod->title())) {
// Insert worked, remove key from old module, add this module to the same configs
$task = $key->generate(false, $parentTask);
if ($task !== false) {
$parentTask = $task;
}
error_log('Inserted new module with id ' . $key->id());
- $ad->setData('publicKey', false);
- $ad->update();
- $configs = ConfigTgz::getAllForModule($ad->id());
+ $confMod->setData('publicKey', false);
+ $confMod->update();
+ $configs = ConfigTgz::getAllForModule($confMod->id());
foreach ($configs as $config) {
// Add newly created key-only module to all configs
$new = array_merge($config->getModuleIds(), [$key->id()]);
@@ -158,9 +158,9 @@ if ($list === false) {
}
}
}
- if ($ad->needRebuild()) {
+ if ($confMod->needRebuild()) {
$update[] = UPDATE_DONE;
- $task = $ad->generate(false, $parentTask);
+ $task = $confMod->generate(false, $parentTask);
if ($task !== false) {
$parentTask = $task;
}
@@ -171,5 +171,8 @@ if ($list === false) {
}
}
+// Start any changed services
+ConfigModuleBaseLdap::ldadp();
+
// Create response for browser
responseFromArray($update);
diff --git a/modules-available/sysconfig/lang/de/module.json b/modules-available/sysconfig/lang/de/module.json
index 1dbb268b..4bc1642f 100644
--- a/modules-available/sysconfig/lang/de/module.json
+++ b/modules-available/sysconfig/lang/de/module.json
@@ -6,8 +6,12 @@
"lang_moduleAssign": "Modul zu Systemkonfigurationen zuweisen",
"lang_noModuleFromThisGroup": "(Kein Modul dieser Gruppe)",
"lang_unknwonTaskManager": "Unbekannter Taskmanager-Fehler",
+ "location-column-header": "Lokalisierung",
"module_name": "Lokalisierung + Integration",
"page_title": "Lokalisierung + Integration",
+ "saver_DescriptionIdleKill": "Ein Bildschirmschoner mit Timeout, nach dessen Ablauf alle Anwendungen ohne weitere Nachfragen geschlossen werden und der Nutzer ausgeloggt wird.",
+ "saver_DescriptionNoTimeout": "Ein Bildschirmschoner ohne Timeout.",
+ "saver_DescriptionShutdown": "Ein Bildschirmschoner mit Timeout, nach dessen Ablauf alle Anwendungen ohne weitere Nachfragen geschlossen werden und der PC heruntergefahren oder neugestartet wird.",
"saver_MessageDefaultIdleKill": "Diese Sitzung wird bei Inaktivit\u00e4t in %1 beendet.",
"saver_MessageDefaultIdleKillLocked": "Diese Sitzung wird in %1 beendet, wenn sie nicht entsperrt wird.",
"saver_MessageDefaultNoTimeout": "Dieser Bildschirm wird gerade geschont.",
@@ -15,13 +19,10 @@
"saver_MessageDefaultShutdown": "Achtung: Rechner wird in %1 heruntergefahren!",
"saver_MessageDefaultShutdownLocked": "Achtung: Rechner wird in %1 heruntergefahren!",
"saver_QssDefault": "#Saver {\r\n background: qlineargradient(spread:pad, x1:0, y1:0, x2:0, y2:1, stop:0 #443, stop:1 #000)\r\n}\r\n\r\nQLabel {\r\n color: #f64;\r\n}\r\n\r\n#lblClock {\r\n color: #999;\r\n font-size: 20pt;\r\n}\r\n\r\n#lblHeader {\r\n font-size: 20pt;\r\n}\r\n",
- "saver_DescriptionIdleKill": "Ein Bildschirmschoner mit Timeout, nach dessen Ablauf alle Anwendungen ohne weitere Nachfragen geschlossen werden und der Nutzer ausgeloggt wird.",
- "saver_DescriptionNoTimeout": "Ein Bildschirmschoner ohne Timeout.",
- "saver_DescriptionShutdown": "Ein Bildschirmschoner mit Timeout, nach dessen Ablauf alle Anwendungen ohne weitere Nachfragen geschlossen werden und der PC heruntergefahren oder neugestartet wird.",
- "saver_TitleIdleKill": "Idle Kill",
- "saver_TitleNoTimeout": "Ohne Timeout",
- "saver_TitleShutdown": "Herunterfahren",
"saver_TextDefaultIdleKill": "<html><body>Keine Nutzeraktivit\u00e4t festgestellt. <br>Zum oben angegebenen Zeitpunkt wird die aktuell laufende Sitzung beendet, wenn der Rechner nicht mehr verwendet wird. <br>Alle noch laufenden Programme <br>werden ohne Nachfrage geschlossen. Stellen Sie daher sicher, bis zum angegebenen Zeitpunkt <br>s\u00e4mtliche sich in Bearbeitung befindlichen Daten abzuspeichern. <br><br>Dies dient dazu zu vermeiden, dass ein Rechner stundenlang gesperrt wird und somit <br>anderen Nutzern nicht zur Verf\u00fcgung steht.<\/body><\/html>",
"saver_TextDefaultIdleKillLocked": "<html><body><br>Zum oben angegebenen Zeitpunkt wird die aktuell laufende Sitzung beendet, wenn sie zuvor nicht wieder entsperrt wird. <br>Alle noch laufenden Programme werden ohne Nachfrage geschlossen. <br>Stellen Sie daher sicher, bis zum angegebenen Zeitpunkt <br>s\u00e4mtliche sich in Bearbeitung befindlichen Daten abzuspeichern, bzw. die Sitzung wieder zu entsperren. <br><br>Dies dient dazu zu vermeiden, dass ein Rechner stundenlang gesperrt wird und somit<br>anderen Nutzern nicht zur Verf\u00fcgung steht.<\/body><\/html>",
- "saver_TextDefaultShutdown": "<html><body>Achtung: Zum oben angegebenen Zeitpunkt wird der Computer heruntergefahren bzw. neugestartet. <br>Alle noch laufenden Programme werden ohne Nachfrage beendet. Stellen Sie daher sicher, bis <br>zum angegebenen Zeitpunkt s\u00e4mtliche Daten abzuspeichern und die Sitzung zu verlassen.<\/body><\/html>"
-}
+ "saver_TextDefaultShutdown": "<html><body>Achtung: Zum oben angegebenen Zeitpunkt wird der Computer heruntergefahren bzw. neugestartet. <br>Alle noch laufenden Programme werden ohne Nachfrage beendet. Stellen Sie daher sicher, bis <br>zum angegebenen Zeitpunkt s\u00e4mtliche Daten abzuspeichern und die Sitzung zu verlassen.<\/body><\/html>",
+ "saver_TitleIdleKill": "Idle Kill",
+ "saver_TitleNoTimeout": "Ohne Timeout",
+ "saver_TitleShutdown": "Herunterfahren"
+} \ No newline at end of file
diff --git a/modules-available/sysconfig/lang/en/module.json b/modules-available/sysconfig/lang/en/module.json
index b49cc1cf..dbfacdb8 100644
--- a/modules-available/sysconfig/lang/en/module.json
+++ b/modules-available/sysconfig/lang/en/module.json
@@ -6,8 +6,12 @@
"lang_moduleAssign": "Assign Module to System Configurations",
"lang_noModuleFromThisGroup": "(No module from this group)",
"lang_unknwonTaskManager": "Unknown Task Manager error",
+ "location-column-header": "SysConfig",
"module_name": "Localization",
"page_title": "Localize and integrate",
+ "saver_DescriptionIdleKill": "A screensaver with a timeout which on it's expiration will close all running applications without further requests and logout the user.",
+ "saver_DescriptionNoTimeout": "A screensaver without a timeout.",
+ "saver_DescriptionShutdown": "A screensaver with a timeout which on it's expiration the PC will shutdown or restart. All applications will be closed without further requests.",
"saver_MessageDefaultIdleKill": "This session will end in %1 when inactive.",
"saver_MessageDefaultIdleKillLocked": "This session will end in %1 if the session is not unlocked.",
"saver_MessageDefaultNoTimeout": "This screen is in saving mode.",
@@ -15,13 +19,10 @@
"saver_MessageDefaultShutdown": "Caution: Computer will shutdown in %1!",
"saver_MessageDefaultShutdownLocked": "Caution: Computer will shutdown in %1!",
"saver_QssDefault": "#Saver {\r\n background: qlineargradient(spread:pad, x1:0, y1:0, x2:0, y2:1, stop:0 #443, stop:1 #000)\r\n}\r\n\r\nQLabel {\r\n color: #f64;\r\n}\r\n\r\n#lblClock {\r\n color: #999;\r\n font-size: 20pt;\r\n}\r\n\r\n#lblHeader {\r\n font-size: 20pt;\r\n}\r\n",
- "saver_DescriptionIdleKill": "A screensaver with a timeout which on it's expiration will close all running applications without further requests and logout the user.",
- "saver_DescriptionNoTimeout": "A screensaver without a timeout.",
- "saver_DescriptionShutdown": "A screensaver with a timeout which on it's expiration the PC will shutdown or restart. All applications will be closed without further requests.",
- "saver_TitleIdleKill": "Idle Kill",
- "saver_TitleNoTimeout": "No Timeout",
- "saver_TitleShutdown": "Shutdown",
"saver_TextDefaultIdleKill": "<html><body>No user activity detected. <br>If the computer is not used until the time specified above, the session will end. <br> All running applications <br>will be closed without further requests. Make sure that all files and changes are saved <br> before the time runs out. <br><br>It prevents computers from beeing locked for hours and <br>not beeing available for other users.<\/body><\/html>",
"saver_TextDefaultIdleKillLocked": "<html><body><br>The current session will end by the time specified above if the computer isn't unlocked before. <br>All running applications will be closed without further requests. <br>Make sure that all files and changes are saved <br>or the session is unlocked before the time runs out. <br><br>It prevents computers from beeing locked for hours and <br>not beeing available for other users.<\/body><\/html>",
- "saver_TextDefaultShutdown": "<html><body>Caution: The computer will shutdown or restart respectively at the specified time above. <br>All running applications will be closed without further requests. Make sure to save all files and changes and leave the session<br>before the time runs out.<\/body><\/html>"
-}
+ "saver_TextDefaultShutdown": "<html><body>Caution: The computer will shutdown or restart respectively at the specified time above. <br>All running applications will be closed without further requests. Make sure to save all files and changes and leave the session<br>before the time runs out.<\/body><\/html>",
+ "saver_TitleIdleKill": "Idle Kill",
+ "saver_TitleNoTimeout": "No Timeout",
+ "saver_TitleShutdown": "Shutdown"
+} \ No newline at end of file
diff --git a/modules-available/sysconfig/page.inc.php b/modules-available/sysconfig/page.inc.php
index ff3983c1..b11f399e 100644
--- a/modules-available/sysconfig/page.inc.php
+++ b/modules-available/sysconfig/page.inc.php
@@ -152,11 +152,12 @@ class Page_SysConfig extends Page
$listid = Request::post('list', Request::REQUIRED, 'int');
$this->listConfigContents($listid);
return;
+ default:
}
Message::addError('invalid-action', $action, 'main');
}
- private function getLocationNames($locations, $ids)
+ private function getLocationNames(array $locations, array $ids): string
{
$ret = array();
foreach ($ids as $id) {
@@ -188,7 +189,7 @@ class Page_SysConfig extends Page
$locationName = false;
}
$hasDefault = false;
- while ($row = $res->fetch(PDO::FETCH_ASSOC)) {
+ foreach ($res as $row) {
if (is_null($row['loclist'])) {
$locList = array();
} else {
@@ -236,7 +237,7 @@ class Page_SysConfig extends Page
private function listModules()
{
// Config modules
- $modules = ConfigModule::getAll();
+ $modules = ConfigModule::getAll() ?? [];
$types = array_map(function ($mod) { return $mod->moduleType(); }, $modules);
$titles = array_map(function ($mod) { return $mod->title(); }, $modules);
array_multisort($types, SORT_ASC, $titles, SORT_ASC, $modules);
@@ -291,7 +292,7 @@ class Page_SysConfig extends Page
. " ORDER BY module.title ASC", array('configid' => $configid));
$modules = array();
- while ($row = $res->fetch(PDO::FETCH_ASSOC)) {
+ foreach ($res as $row) {
$modules[] = array(
'module' => $row['moduletitle'],
'moduleid' => $row['moduleid']
@@ -336,7 +337,7 @@ class Page_SysConfig extends Page
{
$configid = Request::post('rebuild', Request::REQUIRED, 'int');
$config = ConfigTgz::get($configid);
- if ($config === false) {
+ if ($config === null) {
Message::addError('config-invalid', $configid);
Util::redirect('?do=sysconfig&locationid=' . $this->currentLoc);
}
@@ -375,9 +376,9 @@ class Page_SysConfig extends Page
Message::addSuccess('module-deleted', $module['title']);
}
// Rebuild depending config.tgz
- while ($crow = $existing->fetch(PDO::FETCH_ASSOC)) {
+ foreach ($existing as $crow) {
$config = ConfigTgz::get($crow['configid']);
- if ($config !== false) {
+ if ($config !== null) {
$config->generate();
}
}
@@ -401,11 +402,11 @@ class Page_SysConfig extends Page
{
$moduleid = Request::post('rebuild', Request::REQUIRED);
$module = ConfigModule::get($moduleid);
- if ($module === false) {
+ if ($module === null) {
Message::addError('config-invalid', $moduleid);
Util::redirect('?do=sysconfig');
}
- $ret = $module->generate(false, 250);
+ $ret = $module->generate(false, null, 500);
if ($ret === true)
Message::addSuccess('module-rebuilt', $module->title());
elseif ($ret === false)
@@ -419,7 +420,7 @@ class Page_SysConfig extends Page
{
$configid = Request::post('del', Request::REQUIRED);
$config = ConfigTgz::get($configid);
- if ($config === false) {
+ if ($config === null) {
Message::addError('config-invalid', $configid);
Util::redirect('?do=sysconfig&locationid=' . $this->currentLoc);
}
diff --git a/modules-available/sysconfig/templates/ad-start.html b/modules-available/sysconfig/templates/ad-start.html
index 3cca080f..6dd6208a 100644
--- a/modules-available/sysconfig/templates/ad-start.html
+++ b/modules-available/sysconfig/templates/ad-start.html
@@ -21,7 +21,7 @@
<input type="hidden" name="edit" value="{{edit}}">
<div class="input-group">
<span class="input-group-addon slx-ga2">{{lang_moduleTitle}}</span>
- <input tabindex="1" name="title" value="{{title}}" type="text" class="form-control" autofocus>
+ <input tabindex="1" name="title" value="{{title}}" type="text" class="form-control" autofocus required>
</div>
<div class="input-group">
<span class="input-group-addon slx-ga2">Server *</span>
diff --git a/modules-available/sysconfig/templates/branding-check.html b/modules-available/sysconfig/templates/branding-check.html
index d48f9631..80eb4d48 100644
--- a/modules-available/sysconfig/templates/branding-check.html
+++ b/modules-available/sysconfig/templates/branding-check.html
@@ -20,7 +20,7 @@
<input type="hidden" name="edit" value="{{edit}}">
<div class="form-group">
<label for="title-id">{{lang_title}}</label>
- <input type="text" name="title" value="{{title}}" id ="title-id" class="form-control" placeholder="Name des Moduls">
+ <input type="text" name="title" value="{{title}}" id ="title-id" class="form-control" placeholder="Name des Moduls" required>
</div>
<div class="btn-group">
<a class="btn btn-default" href="?do=SysConfig&action=addmodule&step=Branding_Start">{{lang_cancel}}</a>
diff --git a/modules-available/sysconfig/templates/branding-start.html b/modules-available/sysconfig/templates/branding-start.html
index 0db085d9..a6346552 100644
--- a/modules-available/sysconfig/templates/branding-start.html
+++ b/modules-available/sysconfig/templates/branding-start.html
@@ -14,7 +14,7 @@
<input type="text" class="form-control" readonly placeholder="{{lang_selectFile}}">
<span class="input-group-btn">
<span class="btn btn-default btn-file">
- {{lang_browseForFile}}&hellip; <input type="file" name="file" id="input-file">
+ {{lang_browseForFile}}&hellip; <input type="file" accept="image/svg+xml" name="file" id="input-file">
</span>
</span>
</div>
diff --git a/modules-available/sysconfig/templates/cfg-start.html b/modules-available/sysconfig/templates/cfg-start.html
index b4628cba..018cf89f 100644
--- a/modules-available/sysconfig/templates/cfg-start.html
+++ b/modules-available/sysconfig/templates/cfg-start.html
@@ -3,7 +3,7 @@
<input type="hidden" name="edit" value="{{edit}}">
<div class="input-group">
<span class="input-group-addon">{{lang_name}} *</span>
- <input type="text" name="title" value="{{title}}" class="form-control" placeholder="{{lang_configuration}}" autofocus="autofocus">
+ <input type="text" name="title" value="{{title}}" class="form-control" placeholder="{{lang_configuration}}" autofocus="autofocus" required>
</div>
<hr>
<p>{{lang_configurationChoose}}</p>
diff --git a/modules-available/sysconfig/templates/custom-fileselect.html b/modules-available/sysconfig/templates/custom-fileselect.html
index 3e7dd3d6..5f190f08 100644
--- a/modules-available/sysconfig/templates/custom-fileselect.html
+++ b/modules-available/sysconfig/templates/custom-fileselect.html
@@ -5,7 +5,7 @@
<div class="input-group">
<span class="input-group-addon">{{lang_moduleName}}</span>
<input type="text" name="title" value="{{title}}" class="form-control" placeholder="Mein Konfigurationsmodul"
- autofocus="autofocus">
+ autofocus="autofocus" required>
</div>
<div class="pull-right">
<button type="submit" class="btn btn-primary">{{lang_next}} &raquo;</button>
@@ -51,4 +51,5 @@
<div class="pull-right">
<button type="submit" class="btn btn-primary">{{lang_next}} &raquo;</button>
</div>
+ <div class="clearfix"></div>
</form>
diff --git a/modules-available/sysconfig/templates/ldap-start.html b/modules-available/sysconfig/templates/ldap-start.html
index 059d54f5..e6c98680 100644
--- a/modules-available/sysconfig/templates/ldap-start.html
+++ b/modules-available/sysconfig/templates/ldap-start.html
@@ -11,7 +11,7 @@
<input type="hidden" name="edit" value="{{edit}}">
<div class="input-group">
<span class="input-group-addon slx-ga2">{{lang_moduleTitle}}</span>
- <input tabindex="1" name="title" value="{{title}}" type="text" class="form-control">
+ <input tabindex="1" name="title" value="{{title}}" type="text" class="form-control" required>
</div>
<div class="input-group">
<span class="input-group-addon slx-ga2">Server *</span>
diff --git a/modules-available/sysconfig/templates/sshconfig-start.html b/modules-available/sysconfig/templates/sshconfig-start.html
index 9920683d..b56be415 100644
--- a/modules-available/sysconfig/templates/sshconfig-start.html
+++ b/modules-available/sysconfig/templates/sshconfig-start.html
@@ -3,7 +3,7 @@
<input type="hidden" name="edit" value="{{edit}}">
<div class="input-group">
<span class="input-group-addon">{{lang_moduleName}}</span>
- <input type="text" name="title" value="{{title}}" class="form-control" autofocus="autofocus">
+ <input type="text" name="title" value="{{title}}" class="form-control" autofocus="autofocus" required>
</div>
<br>
<div class="form-group">
diff --git a/modules-available/sysconfig/templates/sshkey-start.html b/modules-available/sysconfig/templates/sshkey-start.html
index 52709984..8033740c 100644
--- a/modules-available/sysconfig/templates/sshkey-start.html
+++ b/modules-available/sysconfig/templates/sshkey-start.html
@@ -3,13 +3,16 @@
<input type="hidden" name="edit" value="{{edit}}">
<div class="input-group">
<span class="input-group-addon">{{lang_moduleName}}</span>
- <input type="text" name="title" value="{{title}}" class="form-control" autofocus="autofocus">
+ <input type="text" name="title" value="{{title}}" class="form-control" autofocus="autofocus" required>
</div>
<div class="form-group">
<label for="root-key">{{lang_rootKey}}</label>
<input class="form-control" type="text" name="publicKey" value="{{publicKey}}" id="root-key" required pattern="[a-z0-9\-]+ +[a-zA-Z0-9=/\+]+ +.*">
<i>{{lang_rootKeyInfo}}</i>
</div>
+ <div class="btn-group">
+ <a class="btn btn-default" href="?do=SysConfig&action=addmodule">{{lang_back}}</a>
+ </div>
<div class="btn-group pull-right">
<button type="submit" class="btn btn-primary"><span class="glyphicon glyphicon-floppy-disk"></span> {{lang_save}}</button>
</div>