From 3959293d09f1d350756b83a654dd2dfa234866df Mon Sep 17 00:00:00 2001 From: Roland Gruber Date: Sat, 24 Jul 2004 17:14:39 +0000 Subject: [PATCH] implemented configuration options for modules --- lam/docs/modules-specification.htm | 143 +++++++++++++++++++++++-- lam/lib/baseModule.inc | 102 +++++++++++++++++- lam/lib/config.inc | 10 +- lam/lib/modules.inc | 61 ++++++++++- lam/templates/config/confmain.php | 164 ++++++++++++++++++++++++++++- lam/templates/config/confsave.php | 48 +++++++++ 6 files changed, 515 insertions(+), 13 deletions(-) diff --git a/lam/docs/modules-specification.htm b/lam/docs/modules-specification.htm index 5141a39e..f46e351a 100644 --- a/lam/docs/modules-specification.htm +++ b/lam/docs/modules-specification.htm @@ -24,7 +24,7 @@ All module classes should extend the baseModule class.


-

2.1.1. can_manage

+

2.1.1. can_manage*


@@ -43,7 +43,7 @@ can manage accounts of the current type otherwise false.


-

2.1.2. get_alias

+

2.1.2. get_alias*


@@ -63,6 +63,8 @@ module selection of the configuration wizard.
Please take care that your alias name is not too long. It may contain any character but should not include parts that may be interpreted by the browser (e.g. '<' or '>').
+If you use different aliases dependent on the account type please make +sure that there is a general alias for unknown types.

2.1.3. is_base_module*


@@ -118,7 +120,7 @@ The resulting LDAP filter will look like this: is only used for base modules. Standard modules do not need to implement it.

-

2.1.5. get_dependencies

+

2.1.5. get_dependencies*


@@ -168,7 +170,92 @@ Returns an hash array including meta data for the baseModule.
Example: return array("is_base" => true);

-

2.1.7. get_scope()

+

2.1.7. get_configOptions()*

+
+
+ + + + + +
function get_configOptions($scopes)
+
+
+Returns a list of configuration options.
+$scopes is a list of account types (user, group, host) +which are used.
+
+The return value is an array +that contains meta HTML code.
+
+The type "fieldset" is not allowed here.
+The name attributes are used +as keywords to load and save settings. We recommend to use the module +name as prefix for them (e.g. posixAccount_homeDirectory) to avoid +naming confilcts.
+
+

2.1.8. get_configDescriptions()*

+
+ + + + + + +
function get_configDescriptions()
+
+
+Returns the description of every configuration option and the legend of +the module fieldset on the configuration page.
+
+The return value is a hash +array with this format:
+   
+    array( 'legend' +=> 'Some general description for fieldset',
+       +       'descriptions' => array('option1' +=> 'description1', ...))
+
+

2.1.9. check_configOptions*

+
+ + + + + + +
function check_configOptions($scopes, +$options)
+
+
+This function checks the input for module configuration settings.
+
+$scopes is a list of used +account types (user, group, host).
+$options +is an hash array +(option name => value) that contains the input. The option values +are all arrays containing one or more elements.
+If the input data is invalid the return value is an array that contains +arrays to build StatusMessages (0 => message type, 1 => message +head, 2 => message text, 3 => additional variables).
+If no errors occured the function returns an empty array.
+
+ +

2.1.10. get_scope()


@@ -187,6 +274,8 @@ Returns the account type (user/group/host) of this module object.
This function is provided by the baseModule and should not be overwritten.

+
+

2.2. Class functions

2.2.1. init


@@ -654,11 +743,51 @@ given (only if
  •  array to build StatusMessages (0 => message type, 1 => message -head, 2 => message text, 3 => additional variables)
    -
  • +head, 2 => message text, 3 => additional variables) +
    +

    6.7 get_configOptions()
    +

    +    "config_options" => array('user' => array, +'host' => array, 'all' => array)
    +
    +    The values from 'all' +are always returned, the other values only if they are inside the $scopes array.
    +
    +   Syntax for sub arrays is the same as for +the +return value of get_configOptions().
    +
    +
    +

    6.8 get_configDescriptions()
    +

    +    "config_descriptions" => array
    +
    +   Syntax for array is the same as for the +return value of get_configDescriptions().
    +
    +
    +

    6.9 check_configOptions()
    +

    +    "config_checks" => array('user' => array, +'host' => 'array', 'all' => array)
    +
    +    The values from 'all' are always used for checking, +the other values only if they are inside the $scopes array.
    +
    +
       Syntax for sub arrays is the same as for +check_profileOptions().
    +
    +
    +


    +

    meta['config_options'][$scopes[$i]])) $return = array_merge($return, $this->meta['config_options'][$scopes[$i]]); + } + if (isset($this->meta['config_options']['all'])) $return = array_merge($return, $this->meta['config_options']['all']); + return $return; + } + + /** + * Returns an array containing descriptions shown on configuration pages. + * + * The returned array has the format array('legend' => '...', descriptions => array('option1' => '...', ...)). + *
    The "legend" value is used as text for the fieldset, the descriptions are used when the configuration is printed. + * + * @return array configuration elements + */ + function get_configDescriptions() { + $return = array('legend' => 'no description', 'descriptions' => array()); + if (isset($this->meta['config_descriptions'])) $return = $this->meta['config_descriptions']; + return $return; + } + + /** + * Checks input values of module settings. + * + * @param array $scopes list of account types which are used + * @param array $options hash array containing the settings (array('option' => array('value'))) + * @return array profile elements + */ + function check_configOptions($scopes, $options) { + $messages = array(); + $scopes[] = 'all'; // add checks that are independent of scope + for ($s = 0; $s < sizeof($scopes); $s++) { + if (is_array($this->meta['config_checks'][$scopes[$s]])) { + $identifiers = array_keys($this->meta['config_checks'][$scopes[$s]]); + for ($i = 0; $i < sizeof($identifiers); $i++) { + // check if option is required + if ($this->meta['config_checks'][$scopes[$s]][$identifiers[$i]]['required'] && ($options[$identifiers[$i]][0] == '')) { + $messages[] = $this->meta['config_checks'][$scopes[$s]][$identifiers[$i]]['required_message']; + } + // check by regular expression (case insensitive) + if ($this->meta['config_checks'][$scopes[$s]][$identifiers[$i]]['type'] == 'regex_i') { + // ignore empty fileds + if ($options[$identifiers[$i]][0] == '') continue; + if (! eregi($this->meta['config_checks'][$scopes[$s]][$identifiers[$i]]['regex'], $options[$identifiers[$i]][0])) { + $messages[] = $this->meta['config_checks'][$scopes[$s]][$identifiers[$i]]['error_message']; + } + } + // check by regular expression (case sensitive) + elseif ($this->meta['config_checks'][$scopes[$s]][$identifiers[$i]]['type'] == 'regex') { + // ignore empty fileds + if ($options[$identifiers[$i]][0] == '') continue; + if (! ereg($this->meta['config_checks'][$scopes[$s]][$identifiers[$i]]['regex'], $options[$identifiers[$i]][0])) { + $messages[] = $this->meta['config_checks'][$scopes[$s]][$identifiers[$i]]['error_message']; + } + } + // check by integer comparison (greater) + elseif ($this->meta['config_checks'][$scopes[$s]][$identifiers[$i]]['type'] == 'int_greater') { + // ignore if both fields are empty + if (($options[$this->meta['config_checks'][$scopes[$s]][$identifiers[$i]]['cmp_name1']][0] == '') && ($options[$this->meta['config_checks'][$scopes[$s]][$identifiers[$i]]['cmp_name2']][0] == '')) continue; + // print error message if only one field is empty + if (($options[$this->meta['config_checks'][$scopes[$s]][$identifiers[$i]]['cmp_name1']][0] == '') || ($options[$this->meta['config_checks'][$scopes[$s]][$identifiers[$i]]['cmp_name2']][0] == '')) { + $messages[] = $this->meta['config_checks'][$scopes[$s]][$identifiers[$i]]['error_message']; + continue; + } + // compare + if (!(intval($options[$this->meta['config_checks'][$scopes[$s]][$identifiers[$i]]['cmp_name1']][0]) > intval($options[$this->meta['config_checks'][$scopes[$s]][$identifiers[$i]]['cmp_name2']][0]))) { + $messages[] = $this->meta['config_checks'][$scopes[$s]][$identifiers[$i]]['error_message']; + } + } + // check by integer comparison (greater or equal) + elseif ($this->meta['config_checks'][$scopes[$s]][$identifiers[$i]]['type'] == 'int_greaterOrEqual') { + // ignore if both fields are empty + if (($options[$this->meta['config_checks'][$scopes[$s]][$identifiers[$i]]['cmp_name1']][0] == '') && ($options[$this->meta['config_checks'][$scopes[$s]][$identifiers[$i]]['cmp_name2']][0] == '')) continue; + // print error message if only one field is empty + if (($options[$this->meta['config_checks'][$scopes[$s]][$identifiers[$i]]['cmp_name1']][0] == '') || ($options[$this->meta['config_checks'][$scopes[$s]][$identifiers[$i]]['cmp_name2']][0] == '')) { + $messages[] = $this->meta['config_checks'][$scopes[$s]][$identifiers[$i]]['error_message']; + continue; + } + // compare + if (!(intval($options[$this->meta['config_checks'][$scopes[$s]][$identifiers[$i]]['cmp_name1']][0]) >= intval($options[$this->meta['config_checks'][$scopes[$s]][$identifiers[$i]]['cmp_name2']][0]))) { + $messages[] = $this->meta['config_checks'][$scopes[$s]][$identifiers[$i]]['error_message']; + } + } + else { + StatusMessage("ERROR", "Unsupported type!", $this->meta['config_checks'][$scopes[$s]][$identifiers[$i]]['type']); + } + } + } + } + return $messages; + } + // TODO implement missing interface } diff --git a/lam/lib/config.inc b/lam/lib/config.inc index ce02ac42..c65bd87e 100644 --- a/lam/lib/config.inc +++ b/lam/lib/config.inc @@ -365,7 +365,15 @@ class Config { echo "" . _("Module settings") . ":
    \n"; echo "
      \n"; $names = array_keys($this->moduleSettings); - for ($i = 0; $i < sizeof($names); $i++) echo "
    • " . $names[$i] . ": " . implode(", ", $this->moduleSettings[$names[$i]]) . "
    • \n"; + $descriptions = getConfigDescriptions(); + $descriptions = $descriptions['descriptions']; + for ($i = 0; $i < sizeof($names); $i++) { + echo "
    • "; + // print description if available + if (isset($descriptions[$names[$i]])) echo $descriptions[$names[$i]]; + else echo $names[$i]; + echo ": " . implode(", ", $this->moduleSettings[$names[$i]]) . "
    • \n"; + } echo "
    \n"; } diff --git a/lam/lib/modules.inc b/lam/lib/modules.inc index da44adbd..40a7e6d5 100644 --- a/lam/lib/modules.inc +++ b/lam/lib/modules.inc @@ -50,12 +50,12 @@ while ($stay<7) { while ($entry = readdir($dir)) if ((substr($entry, strlen($entry) - 4, 4) == '.inc') && is_file($relative.'lib/modules/'.$entry)) include_once ($relative.'lib/modules/'.$entry); $stay=10; - } + } else { $stay++; $relative .= '../'; - } } +} /** * Returns the alias name of a module @@ -131,7 +131,7 @@ function getModulesDependencies($scope) { $return[$mods[$i]] = $module->get_dependencies(); } return $return; - } +} /** @@ -249,6 +249,61 @@ function checkProfileOptions($scope, $options) { return $_SESSION["profile_account_$scope"]->checkProfileOptions($options); } +/** +* Returns a hash array (module name => elements) of all module options for the configuration page. +* +* @param array $scopes hash array (module name => array(account types)) +* @return array configuration options +*/ +function getConfigOptions($scopes) { + $return = array(); + $modules = array_keys($scopes); + for ($i = 0; $i < sizeof($modules); $i++) { + $m = new $modules[$i]('none'); + $return[$modules[$i]] = $m->get_configOptions($scopes[$modules[$i]]); + } + return $return; +} + +/** +* Returns a hash array (module name => descriptions) containing descriptions shown on configuration pages. +* +* The returned array has the format array('legend' => array('posixAccount' => '...', ...), descriptions => array('option1' => '...', ...)). +*
    The "legend" value is used as text for the fieldset, the descriptions are used when the configuration is printed. +* +* @return array configuration descriptions +*/ +function getConfigDescriptions() { + $return = array('legend' => array(), 'descriptions' => array()); + $modules = array_merge(getAvailableModules('user'), getAvailableModules('group'), getAvailableModules('host')); + $modules = array_values(array_unique($modules)); + for ($i = 0; $i < sizeof($modules); $i++) { + $m = new $modules[$i]('none'); + $desc = $m->get_configDescriptions(); + $return['legend'][$modules[$i]] = $desc['legend']; + $return['descriptions'] = array_merge($return['descriptions'], $desc['descriptions']); + } + return $return; +} + +/** +* Checks if the configuration options are valid +* +* @param array $scopes hash array (module name => array(account types)) +* @param array $options hash array containing all options (name => array(...)) +* @return array list of error messages +*/ +function checkConfigOptions($scopes, $options) { + $return = array(); + $modules = array_keys($scopes); + for ($i = 0; $i < sizeof($modules); $i++) { + $m = new $modules[$i]('none'); + $errors = $m->check_configOptions($scopes[$modules[$i]], $options); + $return = array_merge($return, $errors); + } + return $return; +} + /** * Returns a help entry from an account module. * diff --git a/lam/templates/config/confmain.php b/lam/templates/config/confmain.php index 4eaf84bc..24416f57 100644 --- a/lam/templates/config/confmain.php +++ b/lam/templates/config/confmain.php @@ -33,6 +33,9 @@ $Id$ /** Access to config functions */ include_once ("../../lib/config.inc"); +/** access to module settings */ +include_once ("../../lib/modules.inc"); + // start session session_save_path("../../sess"); @session_start(); @@ -72,6 +75,8 @@ if ($_POST['back'] || $_POST['submitconf'] || $_POST['editmodules']){ $_SESSION['conf_groupmodules'] = explode(",", $_POST['groupmodules']); $_SESSION['conf_hostmodules'] = explode(",", $_POST['hostmodules']); $_SESSION['conf_filename'] = $_POST['filename']; + $modSettings = array_keys($_SESSION['config_types']); + for ($i = 0; $i < sizeof($modSettings); $i++) $_SESSION['config_moduleSettings'][$modSettings[$i]] = $_POST[$modSettings[$i]]; } // go to final page if ($_POST['submitconf']){ @@ -212,7 +217,7 @@ echo ("
    "); // LDAP cache timeout echo ("". + _("Cache timeout") . ": ". "
     
    ". - _("Cache timeout") . " : \n"; + for ($l = 0; $l < sizeof($options[$modules[$m]]); $l++) { // option lines + echo "\n"; + for ($o = 0; $o < sizeof($options[$modules[$m]][$l]); $o++) { // line parts + echo ""; + print_option($options[$modules[$m]][$l][$o], $modules[$m], $old_options, $tabindex); + echo "\n"; + } + echo "\n"; + } + echo "
    \n"; + echo "\n"; + echo "
    "; +} + + echo ("
    " . _("Ranges") . ""); echo (""); @@ -437,5 +494,110 @@ echo ("\n"); echo ("\n"); echo ("\n"); + + +/** +* prints out the row of a section table including the option name, values and help +* +* @param array $values an array formated as module option +* @param string $module_name the name of the module the options belong to +* @param array $old_options a hash array with the values from the loaded profile +* @param integer $tabindex current value for tabulator order +*/ +function print_option($values, $modulename, $old_options, &$tabindex) { + switch ($values['kind']) { + // text value + case 'text': + echo $values['text'] . "\n"; + break; + // help link + case 'help': + echo "" . _('Help') . "\n"; + break; + // input field + case 'input': + if (($values['type'] == 'text') || ($values['type'] == 'checkbox')) { + if ($values['type'] == 'text') { + $output = "\n"; + $_SESSION['config_types'][$values['name']] = "multiselect"; + } + else { + echo "\n"; + $tabindex++; + break; + // subtable + case 'table': + echo "
    \n"; + for ($l = 0; $l < sizeof($values['value']); $l++) { // option lines + echo "\n"; + for ($o = 0; $o < sizeof($values['value'][$l]); $o++) { // line parts + echo "\n"; + } + echo "\n"; + } + echo "
    "; + print_option($values['value'][$l][$o], $values['value'], $old_options, $tabindex); + echo "
    \n"; + break; + // print error message for invalid types + default: + echo _("Unrecognized type") . ": " . $values['kind'] . "\n"; + break; + } +} + + ?> diff --git a/lam/templates/config/confsave.php b/lam/templates/config/confsave.php index c2901ce6..b547debe 100644 --- a/lam/templates/config/confsave.php +++ b/lam/templates/config/confsave.php @@ -214,6 +214,54 @@ if (! $conf->set_HostModules($_SESSION['conf_hostmodules'])) { exit; } +// check module options +// create option array to check and save +$options = array(); +$opt_keys = array_keys($_SESSION['config_types']); +foreach ($opt_keys as $element) { + // text fields + if ($_SESSION['config_types'][$element] == "text") { + $options[$element] = array($_SESSION['config_moduleSettings'][$element]); + } + // checkboxes + elseif ($_SESSION['config_types'][$element] == "checkbox") { + if ($_SESSION['config_moduleSettings'][$element] == "on") $options[$element] = array('true'); + else $options[$element] = array('false'); + } + // dropdownbox + elseif ($_SESSION['config_types'][$element] == "select") { + $options[$element] = array($_SESSION['config_moduleSettings'][$element]); + } + // multiselect + elseif ($_SESSION['config_types'][$element] == "multiselect") { + $options[$element] = $_SESSION['config_moduleSettings'][$element]; // value is already an array + } +} + +// remove double slashes if magic quotes are on +if (get_magic_quotes_gpc() == 1) { + foreach ($opt_keys as $element) { + if (is_string($options[$element][0])) $options[$element][0] = stripslashes($options[$element][0]); + } +} + +// check options +$errors = checkConfigOptions($_SESSION['config_scopes'], $options); +// print error messages if any +if (sizeof($errors) > 0) { + for ($i = 0; $i < sizeof($errors); $i++) { + if (sizeof($errors[$i]) > 3) { // messages with additional variables + StatusMessage($errors[$i][0], $errors[$i][1], $errors[$i][2], $errors[$i][3]); + } + else { + StatusMessage($errors[$i][0], $errors[$i][1], $errors[$i][2]); + } + } + echo ("\n


    " . _("Back to preferences...") . ""); + exit; +} +// save module setting +$conf->set_moduleSettings($options); // check if password was changed if ($passwd1) {