2126 lines
78 KiB
PHP
2126 lines
78 KiB
PHP
<?php
|
|
use \LAM\PDF\PDFLabelValue;
|
|
use \LAM\PDF\PDFTable;
|
|
use LAM\TYPES\ConfiguredType;
|
|
use function LAM\TYPES\getScopeFromTypeId;
|
|
use LAM\PDF\PDFImage;
|
|
/*
|
|
|
|
This code is part of LDAP Account Manager (http://www.ldap-account-manager.org/)
|
|
Copyright (C) 2003 - 2018 Roland Gruber
|
|
|
|
This program is free software; you can redistribute it and/or modify
|
|
it under the terms of the GNU General Public License as published by
|
|
the Free Software Foundation; either version 2 of the License, or
|
|
(at your option) any later version.
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with this program; if not, write to the Free Software
|
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
|
|
|
|
*/
|
|
|
|
/**
|
|
* This is the parent class for all account modules.
|
|
*
|
|
* It implements the complete module interface and uses meta-data
|
|
* provided by the account modules for its functions.
|
|
*
|
|
* @package modules
|
|
* @author Roland Gruber
|
|
* @see baseModule
|
|
*/
|
|
|
|
/** PDF functions */
|
|
include_once('pdf.inc');
|
|
|
|
/**
|
|
* Parent class of all account modules.
|
|
* It implements the complete module interface and uses meta-data
|
|
* provided by the account modules for its functions.<br>
|
|
* <br>
|
|
* <b>Location and naming of modules</b><br>
|
|
* All LAM modules are placed in lib/modules/ and are named "<class name>.inc".
|
|
* E.g. if you create a new module and its class name is "qmail" then the filename would be "qmail.inc".
|
|
* The class name of a module must contain only a-z, A-Z, 0-9, -, and _.<br>
|
|
* <br>
|
|
* You can avoid to override many functions by using {@link get_metaData()}.<br>
|
|
* <br>
|
|
* All module classes should extend the baseModule class.
|
|
*
|
|
* @package modules
|
|
* @author Roland Gruber
|
|
*/
|
|
abstract class baseModule {
|
|
|
|
/** includes all meta data provided by the sub class */
|
|
protected $meta;
|
|
|
|
/** the account type of this module (user, group, host) */
|
|
private $scope;
|
|
|
|
/** configuration settings of all modules */
|
|
protected $moduleSettings;
|
|
|
|
/**
|
|
* self service profile with settings of all modules
|
|
* @var selfServiceProfile profile
|
|
*/
|
|
protected $selfServiceSettings;
|
|
|
|
/** name of parent accountContainer ($_SESSION[$base]) */
|
|
private $base;
|
|
|
|
/** contains all ldap attributes which should be written */
|
|
protected $attributes;
|
|
|
|
/** contains all ldap attributes which are loaded from ldap */
|
|
protected $orig;
|
|
|
|
/** contains all error messages of a module */
|
|
protected $messages;
|
|
|
|
/** if true, managed object classes are added when an account is created or loaded (default: true) */
|
|
protected $autoAddObjectClasses = true;
|
|
|
|
/**
|
|
* Creates a new base module class
|
|
*
|
|
* @param string $scope the account type (user, group, host)
|
|
*/
|
|
public function __construct($scope) {
|
|
$this->scope = $scope;
|
|
// load configuration
|
|
if ($this->can_manage() || ($scope == 'none')) {
|
|
if (isset($_SESSION['config'])) {
|
|
$this->moduleSettings = $_SESSION['config']->get_moduleSettings();
|
|
}
|
|
if (isset($_SESSION['selfServiceProfile'])) {
|
|
$this->selfServiceSettings = $_SESSION['selfServiceProfile'];
|
|
}
|
|
// initialize module
|
|
$this->load_Messages();
|
|
$this->meta = $this->get_metaData();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* This function fills the $messages variable with output messages from this module.
|
|
*
|
|
* Calling this method requires the existence of an enclosing {@link accountContainer}.
|
|
*/
|
|
protected function load_Messages() {
|
|
}
|
|
|
|
/**
|
|
* Initializes the module after it became part of an {@link accountContainer}
|
|
*
|
|
* Calling this method requires the existence of an enclosing {@link accountContainer}.
|
|
*
|
|
* @param string $base the name of the {@link accountContainer} object ($_SESSION[$base])
|
|
*/
|
|
public function init($base) {
|
|
$this->base = $base;
|
|
$this->attributes = array();
|
|
$this->orig = array();
|
|
// add object classes if needed
|
|
$this->attributes['objectClass'] = array();
|
|
$this->orig['objectClass'] = array();
|
|
if ($this->autoAddObjectClasses === true) {
|
|
$objectClasses = $this->getManagedObjectClasses($this->getAccountContainer()->get_type()->getId());
|
|
for ($i = 0; $i < sizeof($objectClasses); $i++) {
|
|
if (!in_array($objectClasses[$i], $this->attributes['objectClass'])) {
|
|
$this->attributes['objectClass'][] = $objectClasses[$i];
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
* This function loads the LDAP attributes when an account should be loaded.
|
|
*
|
|
* Calling this method requires the existence of an enclosing {@link accountContainer}.<br>
|
|
* <br>
|
|
* By default this method loads the object classes and accounts which are specified in {@link getManagedObjectClasses()}
|
|
* and {@link getManagedAttributes()}.
|
|
*
|
|
* @param array $attributes array like the array returned by get_ldap_attributes(dn of account) but without count indices
|
|
*/
|
|
public function load_attributes($attributes) {
|
|
$this->attributes = array();
|
|
$this->attributes = array();
|
|
// load object classes
|
|
if (isset($attributes['objectClass'])) {
|
|
$this->attributes['objectClass'] = $attributes['objectClass'];
|
|
$this->orig['objectClass'] = $attributes['objectClass'];
|
|
}
|
|
else {
|
|
$this->attributes['objectClass'] = array();
|
|
$this->orig['objectClass'] = array();
|
|
}
|
|
$typeId = $this->getAccountContainer()->get_type()->getId();
|
|
// add object classes if needed
|
|
if ($this->autoAddObjectClasses === true) {
|
|
$objectClasses = $this->getManagedObjectClasses($typeId);
|
|
for ($i = 0; $i < sizeof($objectClasses); $i++) {
|
|
if (!in_array($objectClasses[$i], $this->attributes['objectClass'])) {
|
|
$this->attributes['objectClass'][] = $objectClasses[$i];
|
|
}
|
|
}
|
|
}
|
|
// load attributes
|
|
$attributeNames = array_merge($this->getManagedAttributes($typeId), $this->getManagedHiddenAttributes($typeId));
|
|
$attributeNames = array_unique($attributeNames);
|
|
$attributeNames = array_values($attributeNames);
|
|
for ($i = 0; $i < sizeof($attributeNames); $i++) {
|
|
if (isset($attributes[$attributeNames[$i]])) {
|
|
$this->attributes[$attributeNames[$i]] = $attributes[$attributeNames[$i]];
|
|
$this->orig[$attributeNames[$i]] = $attributes[$attributeNames[$i]];
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* This function provides meta data which is interpreted by baseModule.
|
|
* Only subclasses will return real data.<br>
|
|
* <br>
|
|
* The aim of the meta data is to reduce the number
|
|
* of functions in the subclasses. All major data is centralized in one place.<br>
|
|
* <br>
|
|
* The returned array contains a list of key-value pairs for the different functions.<br>
|
|
* <ul>
|
|
*
|
|
* <li><b>{@link is_base_module()}</b><br>
|
|
* <br>
|
|
* <b>Key:</b> is_base<br>
|
|
* <b>Value:</b> boolean<br>
|
|
* <br>
|
|
* <b>Example:</b> "is_base" => true
|
|
* <br><br>
|
|
* </li>
|
|
*
|
|
* <li><b>{@link get_ldap_filter()}</b><br>
|
|
* <br>
|
|
* <b>Key:</b> ldap_filter<br>
|
|
* <b>Value:</b> array of filters<br>
|
|
* <br>
|
|
* <b>Example:</b> "ldap_filter" => array('or' => 'objectClass=posixAccount', 'and' => '(!(uid=*$))')
|
|
* <br><br>
|
|
* </li>
|
|
*
|
|
* <li><b>{@link getManagedObjectClasses()}</b><br>
|
|
* <br>
|
|
* <b>Key:</b> objectClasses<br>
|
|
* <b>Value:</b> array of object classes<br>
|
|
* <br>
|
|
* <b>Example:</b> "objectClasses" => array('posixAccount')
|
|
* <br><br>
|
|
* </li>
|
|
*
|
|
* <li><b>{@link getLDAPAliases()}</b><br>
|
|
* <br>
|
|
* <b>Key:</b> LDAPaliases<br>
|
|
* <b>Value:</b> array of aliases<br>
|
|
* <br>
|
|
* <b>Example:</b> "LDAPaliases" => array('commonName' => 'cn')
|
|
* <br><br>
|
|
* </li>
|
|
*
|
|
* <li><b>{@link get_RDNAttributes()}</b><br>
|
|
* <br>
|
|
* <b>Key:</b> RDN<br>
|
|
* <b>Value:</b> array of RDNs<br>
|
|
* <br>
|
|
* <b>Example:</b> "RDN" => array('uid' => 'normal', 'cn' => 'low')
|
|
* <br><br>
|
|
* </li>
|
|
*
|
|
* <li><b>{@link get_dependencies()}</b><br>
|
|
* <br>
|
|
* <b>Key:</b> dependencies<br>
|
|
* <b>Value:</b> array of dependencies<br>
|
|
* <br>
|
|
* <b>Example:</b> "dependencies" => array("depends" => array("posixAccount", array("qmail", "sendmail")), "conflicts" => array("exim"))
|
|
* <br><br>
|
|
* </li>
|
|
*
|
|
* <li><b>{@link get_profileOptions()}</b><br>
|
|
* <br>
|
|
* <b>Key:</b> profile_options<br>
|
|
* <b>Value:</b> array of profile options<br>
|
|
* <br>
|
|
* The syntax for the value array is the same as for the return value of get_profileOptions().
|
|
* <br><br>
|
|
* </li>
|
|
*
|
|
* <li><b>{@link check_profileOptions()}</b><br>
|
|
* <br>
|
|
* <b>Key:</b> profile_checks<br>
|
|
* <b>Value:</b> array of checks (array("optionName" => array()))<br>
|
|
* <br>
|
|
* The "optionName" keys of the value array are the names of the option identifiers.<br>
|
|
* Each array element is an array itself containing these values:
|
|
* <ul>
|
|
* <li><b>type:</b> determines how to check input<br>
|
|
* Possible values:
|
|
* <ul>
|
|
* <li><b>regex:</b> check with regular expression from regex variable, case sensitive</li>
|
|
* <li><b>regex_i:</b> check with regular expression from regex variable, case insensitive</li>
|
|
* <li><b>int_greater:</b> integer value of cmp_name1 must be greater than the integer value from the option cmp_name2</li>
|
|
* <li><b>int_greaterOrEqual:</b> integer value of cmp_name1 must be greater or equal than the integer value from the option cmp_name2</li>
|
|
* </ul>
|
|
* </li>
|
|
* <li><b>error_message:</b> message that is displayed if input value was syntactically incorrect<br>
|
|
* error_message is an array to build StatusMessages (message type, message head, message text, additional variables)
|
|
* <li><b>regex:</b> regular expression string (only if type is regex/regex_i)</li>
|
|
* <li><b>cmp_name1:</b> name of first input variable that is used for comparison (only if type is int_greater/int_greaterOrEqual)</li>
|
|
* <li><b>cmp_name2:</b> name of second input variable that is used for comparison (only if type is int_greater/int_greaterOrEqual)</li>
|
|
* <li><b>required:</b> true or false, if this input field must be filled set to true (optional)
|
|
* <li><b>required_message:</b> message that is displayed if no input value was given (only if required == true)<br>
|
|
* required_message is an array to build StatusMessages (message type, message head, message text, additional variables)
|
|
* </li>
|
|
* </ul>
|
|
* <br><br>
|
|
* </li>
|
|
*
|
|
* <li><b>{@link load_profile()}</b><br>
|
|
* <br>
|
|
* <b>Key:</b> profile_mappings<br>
|
|
* <b>Value:</b> array('profile_identifier1' => 'LDAP_attribute1', 'profile_identifier2' => 'LDAP_attribute2')<br>
|
|
* <br>
|
|
* The mapped values are stored directly in $this->attributes.
|
|
* <br>
|
|
* <b>Example:</b> "profile_mappings" => array('inetOrgPerson_title' => 'title')
|
|
* <br><br>
|
|
* </li>
|
|
*
|
|
* <li><b>{@link get_configOptions()}</b><br>
|
|
* <br>
|
|
* <b>Key:</b> config_options<br>
|
|
* <b>Value:</b> array('user' => array, 'host' => array, 'all' => array)<br>
|
|
* <br>
|
|
* The values from 'all' are always returned, the other values only if they are inside the $scopes array.<br>
|
|
* The syntax for sub arrays is the same as for the return value of {@link get_configOptions()}.
|
|
* <br><br>
|
|
* </li>
|
|
*
|
|
* <li><b>{@link check_configOptions()}</b><br>
|
|
* <br>
|
|
* <b>Key:</b> config_checks<br>
|
|
* <b>Value:</b> array('user' => array, 'host' => 'array', 'all' => array)<br>
|
|
* <br>
|
|
* The values from 'all' are always used for checking, the other values only if they are inside the $scopes array.
|
|
* The syntax for sub arrays is the same as for {@link check_configOptions()}.
|
|
* <br><br>
|
|
* </li>
|
|
*
|
|
* <li><b>{@link get_uploadColumns()}</b><br>
|
|
* <br>
|
|
* <b>Key:</b> upload_columns<br>
|
|
* <b>Value:</b> array<br>
|
|
* <br>
|
|
* The syntax for array is the same as for the return value of {@link get_uploadColumns()}.
|
|
* <br><br>
|
|
* </li>
|
|
*
|
|
* <li><b>{@link get_uploadPreDepends()}</b><br>
|
|
* <br>
|
|
* <b>Key:</b> upload_preDepends<br>
|
|
* <b>Value:</b> array<br>
|
|
* <br>
|
|
* The syntax for array is the same as for the return value of {@link get_uploadPreDepends()}.
|
|
* <br><br>
|
|
* </li>
|
|
*
|
|
* <li><b>{@link getRequiredExtensions()}</b><br>
|
|
* <br>
|
|
* <b>Key:</b> extensions<br>
|
|
* <b>Value:</b> array of extension names<br>
|
|
* <br>
|
|
* <b>Example:</b> "extensions" => array('hash')
|
|
* <br><br>
|
|
* </li>
|
|
*
|
|
* <li><b>{@link get_help()}</b><br>
|
|
* <br>
|
|
* <b>Key:</b> help<br>
|
|
* <b>Value:</b> hashtable of help entries<br>
|
|
* <br>
|
|
* The hashtable is an array which maps help IDs to help entries.<br>
|
|
* <br>
|
|
* <b>Example:</b> 'help' => array('myEntry' => array('Headline' => 'This is the head line', 'Text' => 'Help content'))
|
|
* <br><br>
|
|
* </li>
|
|
*
|
|
* <li><b>{@link getSelfServiceSearchAttributes()}</b><br>
|
|
* <br>
|
|
* <b>Key:</b> selfServiceSearchAttributes<br>
|
|
* <b>Value:</b> array of attribute names<br>
|
|
* <br>
|
|
* <b>Example:</b> "selfServiceSearchAttributes" => array('uid')
|
|
* <br><br>
|
|
* </li>
|
|
*
|
|
* <li><b>{@link getSelfServiceFields()}</b><br>
|
|
* <br>
|
|
* <b>Key:</b> selfServiceFieldSettings<br>
|
|
* <b>Value:</b> array of self service fields<br>
|
|
* <br>
|
|
* <b>Example:</b> "selfServiceFieldSettings" => array('pwd' => 'Password')
|
|
* <br><br>
|
|
* </li>
|
|
*
|
|
* </ul>
|
|
* <b>Example:</b> return array("is_base" => true);
|
|
*
|
|
* @return array meta data
|
|
*/
|
|
public function get_metaData() {
|
|
return array();
|
|
}
|
|
|
|
/**
|
|
* Returns the account type of this module (user, group, host)
|
|
*
|
|
* @return string account type
|
|
*/
|
|
public function get_scope() {
|
|
return $this->scope;
|
|
}
|
|
|
|
/**
|
|
* Returns true if this module can manage accounts of the current type, otherwise false.
|
|
*
|
|
* Calling this method does not require the existence of an enclosing {@link accountContainer}.
|
|
*
|
|
* @return boolean true if module fits
|
|
*
|
|
* @see baseModule::get_metaData()
|
|
*/
|
|
public abstract function can_manage();
|
|
|
|
/**
|
|
* Returns true if your module is a base module and otherwise false.
|
|
*
|
|
* Calling this method does not require the existence of an enclosing {@link accountContainer}.<br>
|
|
* <br>
|
|
* Every account type needs exactly one base module. A base module manages a structural object class.
|
|
* E.g. the inetOrgPerson module is a base module since its object class is structural.
|
|
*
|
|
* @return boolean true if base module (defaults to false if no meta data is provided)
|
|
*
|
|
* @see baseModule::get_metaData()
|
|
*/
|
|
public function is_base_module() {
|
|
return (isset($this->meta['is_base']) && ($this->meta['is_base']));
|
|
}
|
|
|
|
/**
|
|
* Returns an LDAP filter for the account lists
|
|
*
|
|
* Calling this method does not require the existence of an enclosing {@link accountContainer}.<br>
|
|
* <br>
|
|
* Returns an array('or' => '...', 'and' => '...') that is used to build the LDAP filter. Usually, this is used to filter object classes.
|
|
* All "or" filter parts of the base modules are combined with OR and then combined with the "and" parts.<br>
|
|
* The resulting LDAP filter will look like this: (&(|(OR1)(OR2)(OR3))(AND1)(AND2)(AND3))<br>
|
|
* <br>
|
|
* <b>Example:</b> return array('or' => '(objectClass=posixAccount)', 'and' => '(!(uid=*$))')
|
|
*
|
|
* @param string $typeId account type id
|
|
* @return string LDAP filter
|
|
*
|
|
* @see baseModule::get_metaData()
|
|
*/
|
|
public function get_ldap_filter($typeId) {
|
|
if (isset($this->meta['ldap_filter'])) {
|
|
return $this->meta['ldap_filter'];
|
|
}
|
|
return "";
|
|
}
|
|
|
|
/**
|
|
* Returns an alias name for the module.
|
|
*
|
|
* Calling this method does not require the existence of an enclosing {@link accountContainer}.<br>
|
|
* <br>
|
|
* This function returns a more descriptive string than the class name. Alias names are used for the buttons on the account pages and the module selection in the configuration wizard.<br>
|
|
* 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.
|
|
*
|
|
* @return string alias name
|
|
*
|
|
* @see baseModule::get_metaData()
|
|
*/
|
|
public function get_alias() {
|
|
if (isset($this->meta['alias'])) {
|
|
return $this->meta['alias'];
|
|
}
|
|
return get_class($this);
|
|
}
|
|
|
|
/**
|
|
* Returns a hash array containing a list of possible LDAP attributes that can be used to form the RDN (Relative Distinguished Name).
|
|
*
|
|
* Calling this method does not require the existence of an enclosing {@link accountContainer}.<br>
|
|
* <br>
|
|
* The returned elements have this form: <attribute> => <priority>
|
|
* <br> <attribute> is the name of the LDAP attribute
|
|
* <br> <priority> defines the priority of the attribute (can be "low", "normal", "high")<br>
|
|
* <br>
|
|
* <b>Example:</b> return array('uid' => 'normal', 'cn' => 'low')
|
|
*
|
|
* @param string $typeId account type
|
|
* @return array list of attributes
|
|
*
|
|
* @see baseModule::get_metaData()
|
|
*/
|
|
public function get_RDNAttributes($typeId) {
|
|
if (isset($this->meta['RDN'])) {
|
|
return $this->meta['RDN'];
|
|
}
|
|
return array();
|
|
}
|
|
|
|
/**
|
|
* This function returns a list with all depending and conflicting modules.
|
|
*
|
|
* Calling this method does not require the existence of an enclosing {@link accountContainer}.<br>
|
|
* <br>
|
|
* The return value is an array with two sub arrays, "depends" and "conflicts".
|
|
* All values of the conflict array are string values with module names. All values of the depends
|
|
* array are either string values with module names or arrays which include only string values with
|
|
* module names.<br>
|
|
* If an element of the depends array is itself an array, this means that your module
|
|
* depends on one of these modules.<br>
|
|
* <br>
|
|
* <b>Example:</b> return array("depends" => array("posixAccount", array("qmail", "sendmail")), "conflicts" => array("exim"))
|
|
*
|
|
* @return array list of dependencies and conflicts
|
|
*
|
|
* @see baseModule::get_metaData()
|
|
*/
|
|
public function get_dependencies() {
|
|
if (isset($this->meta['dependencies'])) {
|
|
return $this->meta['dependencies'];
|
|
}
|
|
return array('depends' => array(), 'conflicts' => array());
|
|
}
|
|
|
|
/**
|
|
* This function defines what attributes will be used in the account profiles and their appearance in the profile editor.
|
|
*
|
|
* Calling this method does not require the existence of an enclosing {@link accountContainer}.<br>
|
|
* <br>
|
|
* The return value is an object implementing htmlElement.<br>
|
|
* The field name are used as keywords to load
|
|
* and save profiles. We recommend to use the module name as prefix for them
|
|
* (e.g. posixAccount_homeDirectory) to avoid naming conflicts.
|
|
*
|
|
* @param string $typeId type id (user, group, host, ...)
|
|
* @return htmlElement meta HTML object
|
|
*
|
|
* @see baseModule::get_metaData()
|
|
* @see htmlElement
|
|
*/
|
|
public function get_profileOptions($typeId) {
|
|
if (isset($this->meta['profile_options'])) {
|
|
return $this->meta['profile_options'];
|
|
}
|
|
return array();
|
|
}
|
|
|
|
/**
|
|
* Checks input values of account profiles.
|
|
*
|
|
* Calling this method does not require the existence of an enclosing {@link accountContainer}.<br>
|
|
* <br>
|
|
* $options is an hash array (option name => value) that contains the user input.
|
|
* The option values are all arrays containing one or more elements.<br>
|
|
* If the input data is invalid the return value is an array that contains arrays
|
|
* to build StatusMessages (message type, message head, message text). If no errors occured
|
|
* the function returns an empty array.
|
|
*
|
|
* @param array $options a hash array (name => value) containing the user input
|
|
* @param string $typeId type id (user, group, host)
|
|
* @return array list of error messages (array(type, title, text)) to generate StatusMessages, if any
|
|
*
|
|
* @see baseModule::get_metaData()
|
|
*/
|
|
public function check_profileOptions($options, $typeId) {
|
|
$messages = array();
|
|
if (isset($this->meta['profile_checks'])) {
|
|
$identifiers = array_keys($this->meta['profile_checks']);
|
|
for ($i = 0; $i < sizeof($identifiers); $i++) {
|
|
// empty input
|
|
if (!isset($options[$identifiers[$i]][0]) || ($options[$identifiers[$i]][0] == '')) {
|
|
// check if option is required
|
|
if (isset($this->meta['profile_checks'][$identifiers[$i]]['required']) && $this->meta['profile_checks'][$identifiers[$i]]['required']) {
|
|
$messages[] = $this->meta['profile_checks'][$identifiers[$i]]['required_message'];
|
|
}
|
|
continue;
|
|
}
|
|
switch ($this->meta['profile_checks'][$identifiers[$i]]['type']) {
|
|
// check by regular expression (from account.inc)
|
|
case "ext_preg":
|
|
// ignore empty fileds
|
|
if ($options[$identifiers[$i]][0] == '') {
|
|
continue;
|
|
}
|
|
if (! get_preg($options[$identifiers[$i]][0], $this->meta['profile_checks'][$identifiers[$i]]['regex'])) {
|
|
$messages[] = $this->meta['profile_checks'][$identifiers[$i]]['error_message'];
|
|
}
|
|
break;
|
|
// check by regular expression (case insensitive)
|
|
case 'regex_i':
|
|
// ignore empty fileds
|
|
if ($options[$identifiers[$i]][0] == '') {
|
|
continue;
|
|
}
|
|
if (! preg_match('/' . $this->meta['profile_checks'][$identifiers[$i]]['regex'] . '/i', $options[$identifiers[$i]][0])) {
|
|
$messages[] = $this->meta['profile_checks'][$identifiers[$i]]['error_message'];
|
|
}
|
|
break;
|
|
// check by regular expression (case sensitive)
|
|
case 'regex':
|
|
// ignore empty fileds
|
|
if ($options[$identifiers[$i]][0] == '') {
|
|
continue;
|
|
}
|
|
if (! preg_match('/' . $this->meta['profile_checks'][$identifiers[$i]]['regex'] . '/', $options[$identifiers[$i]][0])) {
|
|
$messages[] = $this->meta['profile_checks'][$identifiers[$i]]['error_message'];
|
|
}
|
|
break;
|
|
// check by integer comparison (greater)
|
|
case 'int_greater':
|
|
// ignore if both fields are empty
|
|
if (($options[$this->meta['profile_checks'][$identifiers[$i]]['cmp_name1']][0] == '') && ($options[$this->meta['profile_checks'][$identifiers[$i]]['cmp_name2']][0] == '')) {
|
|
continue;
|
|
}
|
|
// print error message if only one field is empty
|
|
if (($options[$this->meta['profile_checks'][$identifiers[$i]]['cmp_name1']][0] == '') || ($options[$this->meta['profile_checks'][$identifiers[$i]]['cmp_name2']][0] == '')) {
|
|
$messages[] = $this->meta['profile_checks'][$identifiers[$i]]['error_message'];
|
|
continue;
|
|
}
|
|
// compare
|
|
if (!(intval($options[$this->meta['profile_checks'][$identifiers[$i]]['cmp_name1']][0]) > intval($options[$this->meta['profile_checks'][$identifiers[$i]]['cmp_name2']][0]))) {
|
|
$messages[] = $this->meta['profile_checks'][$identifiers[$i]]['error_message'];
|
|
}
|
|
break;
|
|
// check by integer comparison (greater or equal)
|
|
case 'int_greaterOrEqual':
|
|
// ignore if both fields are empty
|
|
if (($options[$this->meta['profile_checks'][$identifiers[$i]]['cmp_name1']][0] == '') && ($options[$this->meta['profile_checks'][$identifiers[$i]]['cmp_name2']][0] == '')) {
|
|
continue;
|
|
}
|
|
// print error message if only one field is empty
|
|
if (($options[$this->meta['profile_checks'][$identifiers[$i]]['cmp_name1']][0] == '') || ($options[$this->meta['profile_checks'][$identifiers[$i]]['cmp_name2']][0] == '')) {
|
|
$messages[] = $this->meta['profile_checks'][$identifiers[$i]]['error_message'];
|
|
continue;
|
|
}
|
|
// compare
|
|
if (!(intval($options[$this->meta['profile_checks'][$identifiers[$i]]['cmp_name1']][0]) >= intval($options[$this->meta['profile_checks'][$identifiers[$i]]['cmp_name2']][0]))) {
|
|
$messages[] = $this->meta['profile_checks'][$identifiers[$i]]['error_message'];
|
|
}
|
|
break;
|
|
// print error message for invalid types
|
|
default:
|
|
StatusMessage("ERROR", "Unsupported type!", $this->meta['profile_checks'][$identifiers[$i]]['type']);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
return $messages;
|
|
}
|
|
|
|
/**
|
|
* This function loads the values from an account profile to the module's internal data structures.
|
|
*
|
|
* Calling this method does not require the existence of an enclosing {@link accountContainer}.
|
|
*
|
|
* @param array $profile hash array with profile values (identifier => value)
|
|
*
|
|
* @see baseModule::get_metaData()
|
|
*/
|
|
public function load_profile($profile) {
|
|
if (isset($this->meta['profile_mappings'])) {
|
|
$identifiers = array_keys($this->meta['profile_mappings']);
|
|
for ($i = 0; $i < sizeof($identifiers); $i++) {
|
|
if (isset($profile[$identifiers[$i]])) {
|
|
$this->attributes[$this->meta['profile_mappings'][$identifiers[$i]]] = $profile[$identifiers[$i]];
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Returns a list of configuration options.
|
|
*
|
|
* Calling this method does not require the existence of an enclosing {@link accountContainer}.<br>
|
|
* <br>
|
|
* The field names 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 conflicts.
|
|
*
|
|
* @param array $scopes account types (user, group, host)
|
|
* @param array $allScopes list of all active account modules and their account type id (module => array(type id))
|
|
* @return mixed htmlElement or array of htmlElement
|
|
*
|
|
* @see baseModule::get_metaData()
|
|
* @see htmlElement
|
|
*/
|
|
public function get_configOptions($scopes, $allScopes) {
|
|
$return = array();
|
|
for ($i = 0; $i < sizeof($scopes); $i++) {
|
|
if (isset($this->meta['config_options'][$scopes[$i]])) {
|
|
if (is_array($this->meta['config_options'][$scopes[$i]])) {
|
|
$return = array_merge($return, $this->meta['config_options'][$scopes[$i]]);
|
|
}
|
|
elseif (isset($return[0]) && ($return[0] instanceof htmlTable) && ($this->meta['config_options'][$scopes[$i]] instanceof htmlTable)) {
|
|
$return[0]->mergeTableElements($this->meta['config_options'][$scopes[$i]]);
|
|
}
|
|
else {
|
|
$return[] = $this->meta['config_options'][$scopes[$i]];
|
|
}
|
|
}
|
|
}
|
|
if (isset($this->meta['config_options']['all'])) {
|
|
if (is_array($this->meta['config_options']['all'])) {
|
|
$return = array_merge($return, $this->meta['config_options']['all']);
|
|
}
|
|
elseif (isset($return[0]) && ($return[0] instanceof htmlTable) && ($this->meta['config_options']['all'] instanceof htmlTable)) {
|
|
$return[0]->mergeTableElements($this->meta['config_options']['all']);
|
|
}
|
|
else {
|
|
$return[] = $this->meta['config_options']['all'];
|
|
}
|
|
}
|
|
return $return;
|
|
}
|
|
|
|
/**
|
|
* Checks input values of module settings.
|
|
*
|
|
* Calling this method does not require the existence of an enclosing {@link accountContainer}.<br>
|
|
* <br>
|
|
* If the input data is invalid the return value is an array that contains subarrays to build StatusMessages ('message type', 'message head', 'message text').
|
|
* <br>If no errors occured the function returns an empty array.
|
|
*
|
|
* @param array $typeIds list of account type ids which are used
|
|
* @param array $options hash array (option name => value) that contains the input. The option values are all arrays containing one or more elements.
|
|
* @return array list of error messages
|
|
*
|
|
* @see baseModule::get_metaData()
|
|
*/
|
|
public function check_configOptions($typeIds, &$options) {
|
|
$messages = array();
|
|
// add checks that are independent of scope
|
|
$scopes = array('all');
|
|
foreach ($typeIds as $typeId) {
|
|
$scopes[] = getScopeFromTypeId($typeId);
|
|
}
|
|
$scopes = array_unique($scopes);
|
|
for ($s = 0; $s < sizeof($scopes); $s++) {
|
|
if (isset($this->meta['config_checks'][$scopes[$s]]) && 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 (isset($this->meta['config_checks'][$scopes[$s]][$identifiers[$i]]['required']) && ($this->meta['config_checks'][$scopes[$s]][$identifiers[$i]]['required']) && ($options[$identifiers[$i]][0] == '')) {
|
|
$messages[] = $this->meta['config_checks'][$scopes[$s]][$identifiers[$i]]['required_message'];
|
|
}
|
|
switch ($this->meta['config_checks'][$scopes[$s]][$identifiers[$i]]['type']) {
|
|
// check by regular expression (from account.inc)
|
|
case "ext_preg":
|
|
// ignore empty fileds
|
|
if ($options[$identifiers[$i]][0] == '') {
|
|
break;
|
|
}
|
|
if (! get_preg($options[$identifiers[$i]][0], $this->meta['config_checks'][$scopes[$s]][$identifiers[$i]]['regex'])) {
|
|
$messages[] = $this->meta['config_checks'][$scopes[$s]][$identifiers[$i]]['error_message'];
|
|
}
|
|
break;
|
|
// check by regular expression (case insensitive)
|
|
case "regex_i":
|
|
// ignore empty fileds
|
|
if ($options[$identifiers[$i]][0] == '') {
|
|
break;
|
|
}
|
|
if (! preg_match('/' . $this->meta['config_checks'][$scopes[$s]][$identifiers[$i]]['regex'] . '/i', $options[$identifiers[$i]][0])) {
|
|
$messages[] = $this->meta['config_checks'][$scopes[$s]][$identifiers[$i]]['error_message'];
|
|
}
|
|
break;
|
|
// check by regular expression (case sensitive)
|
|
case "regex":
|
|
// ignore empty fileds
|
|
if ($options[$identifiers[$i]][0] == '') {
|
|
break;
|
|
}
|
|
if (! preg_match('/' . $this->meta['config_checks'][$scopes[$s]][$identifiers[$i]]['regex'] . '/', $options[$identifiers[$i]][0])) {
|
|
$messages[] = $this->meta['config_checks'][$scopes[$s]][$identifiers[$i]]['error_message'];
|
|
}
|
|
break;
|
|
// check by integer comparison (greater)
|
|
case "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] == '')) {
|
|
break;
|
|
}
|
|
// 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'];
|
|
break;
|
|
}
|
|
// 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'];
|
|
}
|
|
break;
|
|
// check by integer comparison (greater or equal)
|
|
case "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] == '')) {
|
|
break;
|
|
}
|
|
// 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'];
|
|
break;
|
|
}
|
|
// 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'];
|
|
}
|
|
break;
|
|
// print error message on undefined type
|
|
default:
|
|
StatusMessage("ERROR", "Unsupported type!", $this->meta['config_checks'][$scopes[$s]][$identifiers[$i]]['type']);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return $messages;
|
|
}
|
|
|
|
/**
|
|
* Returns a hashtable with all entries that may be printed out in the PDF.
|
|
*
|
|
* @param string $typeId type id (user, group, host)
|
|
* @return array PDF entries as key => label
|
|
*
|
|
* @see baseModule::get_metaData()
|
|
*/
|
|
public function get_pdfFields($typeId) {
|
|
return ((isset($this->meta['PDF_fields'])) ? $this->meta['PDF_fields'] : array());
|
|
}
|
|
|
|
/**
|
|
* Returns the PDF entries for this module.
|
|
*
|
|
* @param array $pdfKeys list of PDF keys that are included in document
|
|
* @param string $typeId type id (user, group, host)
|
|
* @return PDFEntry[] list of key => PDFEntry
|
|
*/
|
|
public function get_pdfEntries($pdfKeys, $typeId) {
|
|
return array();
|
|
}
|
|
|
|
/**
|
|
* Adds a simple PDF entry to the given array.
|
|
*
|
|
* @param array $result result array (entry will be added here)
|
|
* @param String $name ID
|
|
* @param String $label label name
|
|
* @param String $attrName attribute name (default: =$name)
|
|
* @param String $delimiter delimiter if multiple attribute values exist (default: ", ")
|
|
*/
|
|
protected function addSimplePDFField(&$result, $name, $label, $attrName = null, $delimiter = ', ') {
|
|
if ($attrName == null) {
|
|
$attrName = $name;
|
|
}
|
|
$value = '';
|
|
if (isset($this->attributes[$attrName]) && (sizeof($this->attributes[$attrName]) > 0)) {
|
|
natcasesort($this->attributes[$attrName]);
|
|
$value = implode($delimiter, $this->attributes[$attrName]);
|
|
$value = trim($value);
|
|
}
|
|
$result[get_class($this) . '_' . $name][] = new PDFLabelValue($label, $value);
|
|
}
|
|
|
|
/**
|
|
* Adds a simple PDF entry with the given key and value.
|
|
*
|
|
* @param array $result result array (entry will be added here)
|
|
* @param String $name ID
|
|
* @param String $label label name
|
|
* @param mixed $value value as String or array
|
|
* @param String $delimiter delimiter if value is array (default: ", ")
|
|
*/
|
|
public function addPDFKeyValue(&$result, $name, $label, $value, $delimiter = ', ') {
|
|
if (is_array($value)) {
|
|
natcasesort($value);
|
|
$value = implode($delimiter, $value);
|
|
}
|
|
$result[get_class($this) . '_' . $name][] = new PDFLabelValue($label, $value);
|
|
}
|
|
|
|
/**
|
|
* Adds a table entry to the PDF.
|
|
*
|
|
* @param array $result result array (entry will be added here)
|
|
* @param String $name ID
|
|
* @param PDFTable $table table
|
|
*/
|
|
public function addPDFTable(&$result, $name, $table) {
|
|
if (empty($table->rows)) {
|
|
return;
|
|
}
|
|
$result[get_class($this) . '_' . $name][] = $table;
|
|
}
|
|
|
|
/**
|
|
* Adds an image to the PDF.
|
|
*
|
|
* @param array $result result array (entry will be added here)
|
|
* @param String $attrName attribute name
|
|
* @param PDFTable $table table
|
|
*/
|
|
public function addPDFImage(&$result, $attrName) {
|
|
if (isset($this->attributes[$attrName]) && (sizeof($this->attributes[$attrName]) > 0)) {
|
|
$result[get_class($this) . '_' . $attrName][] = new PDFImage($this->attributes[$attrName][0]);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Returns an array containing all input columns for the file upload.
|
|
*
|
|
* Calling this method does not require the existence of an enclosing {@link accountContainer}.<br>
|
|
* <br>
|
|
* This funtion returns an array which contains subarrays which represent an upload column.
|
|
* <b>Syntax of column arrays:</b>
|
|
* <br>
|
|
* <br> array(
|
|
* <br> string: name, // fixed non-translated name which is used as column name (should be of format: <module name>_<column name>)
|
|
* <br> string: description, // short descriptive name
|
|
* <br> string: help, // help ID
|
|
* <br> string: example, // example value
|
|
* <br> string: values, // possible input values (optional)
|
|
* <br> string: default, // default value (optional)
|
|
* <br> boolean: required // true, if user must set a value for this column
|
|
* <br> boolean: unique // true if all values of this column must be different values (optional, default: "false")
|
|
* <br> )
|
|
*
|
|
* @param array $selectedModules list of selected account modules
|
|
* @param ConfiguredType $type account type
|
|
* @return array column list
|
|
*
|
|
* @see baseModule::get_metaData()
|
|
*/
|
|
public function get_uploadColumns($selectedModules, &$type) {
|
|
if (isset($this->meta['upload_columns'])) {
|
|
return $this->meta['upload_columns'];
|
|
}
|
|
return array();
|
|
}
|
|
|
|
/**
|
|
* Returns a list of module names which must be processed in building the account befor this module.
|
|
*
|
|
* Calling this method does not require the existence of an enclosing {@link accountContainer}.<br>
|
|
* <br>
|
|
* The named modules may not be active, LAM will check this automatically.
|
|
*
|
|
* @return array list of module names
|
|
*
|
|
* @see baseModule::get_metaData()
|
|
*/
|
|
public function get_uploadPreDepends() {
|
|
if (isset($this->meta['upload_preDepends'])) {
|
|
return $this->meta['upload_preDepends'];
|
|
}
|
|
return array();
|
|
}
|
|
|
|
/**
|
|
* In this function the LDAP accounts are built.
|
|
*
|
|
* Calling this method does not require the existence of an enclosing {@link accountContainer}.<br>
|
|
* <br>
|
|
* Returns an array which contains subarrays to generate StatusMessages if any errors occured.
|
|
*
|
|
* @param array $rawAccounts the user input data, contains one subarray for each account.
|
|
* @param array $ids list of IDs for column position (e.g. "posixAccount_uid" => 5)
|
|
* @param array $partialAccounts list of hash arrays (name => value) which are later added to LDAP
|
|
* @param array $selectedModules list of selected account modules
|
|
* @param ConfiguredType $type account type
|
|
* @return array list of error messages if any
|
|
*/
|
|
public function build_uploadAccounts($rawAccounts, $ids, &$partialAccounts, $selectedModules, &$type) {
|
|
// must be implemented in sub modules
|
|
return array();
|
|
}
|
|
|
|
/**
|
|
* Maps simple upload fields directly to LDAP attribute values.
|
|
*
|
|
* @param array $rawAccounts the user input data, contains one subarray for each account.
|
|
* @param array $ids list of IDs for column position (e.g. "posixAccount_uid" => 5)
|
|
* @param array $partialAccounts list of hash arrays (name => value) which are later added to LDAP
|
|
* @param String $position current position in CSV
|
|
* @param String $colName column name
|
|
* @param String $attrName LDAP attribute name
|
|
* @param String $regexID for get_preg() (e.g. 'ascii')
|
|
* @param array $message error message to add if regex does not match
|
|
* @param array $errors list of error messages if any
|
|
* @param String $regexSplit multiple values are separated and can be split with this preg_split expression (e.g. "/;[ ]?/")
|
|
*/
|
|
protected function mapSimpleUploadField(&$rawAccounts, &$ids, &$partialAccounts, $position, $colName, $attrName, $regex = null, $message = array(), &$errors = array(), $regexSplit = null) {
|
|
if (!isset($ids[$colName])) {
|
|
return;
|
|
}
|
|
if (!empty($rawAccounts[$position][$ids[$colName]])) {
|
|
// single value
|
|
if ($regexSplit == null) {
|
|
if (!empty($regex) && !get_preg($rawAccounts[$position][$ids[$colName]], $regex)) {
|
|
$errMsg = $message;
|
|
array_push($errMsg, array($position));
|
|
$errors[] = $errMsg;
|
|
}
|
|
$partialAccounts[$position][$attrName] = trim($rawAccounts[$position][$ids[$colName]]);
|
|
}
|
|
// multi-value
|
|
else {
|
|
$list = preg_split($regexSplit, trim($rawAccounts[$position][$ids[$colName]]));
|
|
$partialAccounts[$position][$attrName] = $list;
|
|
if (!empty($regex)) {
|
|
for ($x = 0; $x < sizeof($list); $x++) {
|
|
if (!get_preg($list[$x], $regex)) {
|
|
$errMsg = $message;
|
|
array_push($errMsg, array($position));
|
|
$errors[] = $errMsg;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* This function returns the help entry array for a specific help id.
|
|
*
|
|
* Calling this method does not require the existence of an enclosing {@link accountContainer}.<br>
|
|
* <br>
|
|
* The result is an hashtable with the following keys:<br>
|
|
* <ul>
|
|
* <li><b>Headline (required)</b><br>
|
|
* The headline of this help entry. Can consist of any alpha-numeric characters. No HTML/CSS elements are allowed.</li>
|
|
* <li><b>Text (required)</b><br>
|
|
* The text of the help entry which may contain any alpha-numeric characters.</li>
|
|
* <li><b>SeeAlso (optional)</b><br>
|
|
* A reference to anonther related web site. It must be an array containing a field called "text" with the link text
|
|
* that should be displayed and a field called "link" which is the link target.</li>
|
|
* </ul>
|
|
* <br>
|
|
* <b>Example:</b><br>
|
|
* <br>
|
|
* array('Headline' => 'This is the head line', 'Text' => 'Help content', 'SeeAlso' => array('text' => 'LAM homepage', 'link' => 'http://www.ldap-account-manager.org/'))
|
|
*
|
|
* @param string $id The id string for the help entry needed.
|
|
* @return array The desired help entry.
|
|
*
|
|
* @see baseModule::get_metaData()
|
|
*/
|
|
public function get_help($id) {
|
|
if(isset($this->meta['help'][$id])) {
|
|
return $this->meta['help'][$id];
|
|
}
|
|
elseif(isset($this->meta['help'][$this->scope][$id])) {
|
|
return $this->meta['help'][$this->scope][$id];
|
|
}
|
|
else {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* This function is used to check if this module page can be displayed.
|
|
*
|
|
* Calling this method requires the existence of an enclosing {@link accountContainer}.<br>
|
|
* <br>
|
|
* Your module might depend on input of other modules. This function determines if the user
|
|
* can change to your module page or not. The return value is true if your module accepts
|
|
* input, otherwise false.<br>
|
|
* This method's return value defaults to true.
|
|
*
|
|
* @return boolean true, if page can be displayed
|
|
*/
|
|
public function module_ready() {
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* This function is used to check if all settings for this module have been made.
|
|
*
|
|
* Calling this method requires the existence of an enclosing {@link accountContainer}.<br>
|
|
* <br>
|
|
* This function tells LAM if it can create/modify the LDAP account. If your module needs any
|
|
* additional input then set this to false. The user will be notified that your module needs
|
|
* more input.<br>
|
|
* This method's return value defaults to true.
|
|
*
|
|
* @return boolean true, if settings are complete
|
|
*/
|
|
public function module_complete() {
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* Controls if the module button the account page is visible and activated.
|
|
*
|
|
* Calling this method requires the existence of an enclosing {@link accountContainer}.<br>
|
|
* <br>
|
|
* <b>Possible return values:</b>
|
|
* <ul>
|
|
* <li><b>enabled:</b> button is visible and active</li>
|
|
* <li><b>disabled:</b> button is visible and deactivated (greyed)</li>
|
|
* <li><b>hidden:</b> no button will be shown</li>
|
|
* </ul>
|
|
*
|
|
* @return string status ("enabled", "disabled", "hidden")
|
|
*/
|
|
public function getButtonStatus() {
|
|
return "enabled";
|
|
}
|
|
|
|
/**
|
|
* Runs any actions that need to be done before an LDAP entry is created.
|
|
*
|
|
* @param array $attributes LDAP attributes of this entry (attributes are provided as reference, handle modifications of $attributes with care)
|
|
* @param ConfiguredType $type account type
|
|
* @return array array which contains status messages. Each entry is an array containing the status message parameters.
|
|
*/
|
|
public function doUploadPreActions($attributes, $type) {
|
|
return array();
|
|
}
|
|
|
|
/**
|
|
* This function is responsible to do additional tasks after the account has been created in LDAP (e.g. modifying group memberships, adding Quota etc..).
|
|
*
|
|
* Calling this method does not require the existence of an enclosing {@link accountContainer}.<br>
|
|
* <br>
|
|
* This function is called as long as the returned status is 'finished'. Please make sure
|
|
* that one function call lasts no longer than 3-4 seconds. Otherwise the upload may fail
|
|
* because the time limit is exceeded. You should not make more than one LDAP operation in
|
|
* each call.
|
|
*
|
|
* @param array $data array containing one account in each element
|
|
* @param array $ids maps the column names to keys for the sub arrays (array(<column_name> => <column number>))
|
|
* @param array $failed list of account numbers which could not be successfully uploaded to LDAP
|
|
* @param array $temp variable to store temporary data between two post actions
|
|
* @param array $accounts list of LDAP entries
|
|
* @param string[] $selectedModules selected account modules
|
|
* @return array current status
|
|
* <br> array (
|
|
* <br> 'status' => 'finished' | 'inProgress' // defines if all operations are complete
|
|
* <br> 'progress' => 0..100 // the progress of the operations in percent
|
|
* <br> 'errors' => array // list of arrays which are used to generate StatusMessages
|
|
* <br> )
|
|
* @param ConfiguredType $type account type
|
|
*/
|
|
public function doUploadPostActions(&$data, $ids, $failed, &$temp, &$accounts, $selectedModules, $type) {
|
|
return array(
|
|
'status' => 'finished',
|
|
'progress' => 100,
|
|
'errors' => array()
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Returns a list of modifications which have to be made to the LDAP account.
|
|
*
|
|
* Calling this method requires the existence of an enclosing {@link accountContainer}.<br>
|
|
* <br>
|
|
*
|
|
* <br>This function returns an array with 3 entries:
|
|
* <br>array( DN1 ('add' => array($attr), 'remove' => array($attr), 'modify' => array($attr)), DN2 .... )
|
|
* <br>DN is the DN to change. It is possible to change several DNs (e.g. create a new user and add him
|
|
* to some groups via attribute memberUid)<br>
|
|
* <br><b>"add"</b> are attributes which have to be added to the LDAP entry
|
|
* <br><b>"remove"</b> are attributes which have to be removed from the LDAP entry
|
|
* <br><b>"modify"</b> are attributes which have to be modified in the LDAP entry
|
|
* <br><b>"notchanged"</b> are attributes which stay unchanged
|
|
* <br><b>"info"</b> values with informational value (e.g. to be used later by pre/postModify actions)
|
|
* <br>
|
|
* <br>This builds the required comands from $this-attributes and $this->orig.
|
|
*
|
|
* @return array list of modifications
|
|
*/
|
|
public function save_attributes() {
|
|
return $this->getAccountContainer()->save_module_attributes($this->attributes, $this->orig);
|
|
}
|
|
|
|
/**
|
|
* Allows the module to run commands before the LDAP entry is changed or created.
|
|
*
|
|
* Calling this method requires the existence of an enclosing {@link accountContainer}.<br>
|
|
* <br>
|
|
* The modification is aborted if an error message is returned.
|
|
*
|
|
* @param boolean $newAccount new account
|
|
* @param array $attributes LDAP attributes of this entry (added/modified attributes are provided as reference, handle modifications of $attributes with care)
|
|
* @return array array which contains status messages. Each entry is an array containing the status message parameters.
|
|
*/
|
|
public function preModifyActions($newAccount, $attributes) {
|
|
return array();
|
|
}
|
|
|
|
/**
|
|
* Allows the module to run commands after the LDAP entry is changed or created.
|
|
*
|
|
* Calling this method requires the existence of an enclosing {@link accountContainer}.
|
|
*
|
|
* @param boolean $newAccount new account
|
|
* @param array $attributes LDAP attributes of this entry
|
|
* @return array array which contains status messages. Each entry is an array containing the status message parameters.
|
|
*/
|
|
public function postModifyActions($newAccount, $attributes) {
|
|
return array();
|
|
}
|
|
|
|
/**
|
|
* Allows the module to run commands before the LDAP entry is deleted.
|
|
*
|
|
* Calling this method requires the existence of an enclosing {@link accountContainer}.<br>
|
|
*
|
|
* @return array Array which contains status messages. Each entry is an array containing the status message parameters.
|
|
*/
|
|
public function preDeleteActions() {
|
|
return array();
|
|
}
|
|
|
|
/**
|
|
* Allows the module to run commands after the LDAP entry is deleted.
|
|
*
|
|
* Calling this method requires the existence of an enclosing {@link accountContainer}.
|
|
*
|
|
* @return array Array which contains status messages. Each entry is an array containing the status message parameters.
|
|
*/
|
|
public function postDeleteActions() {
|
|
return array();
|
|
}
|
|
|
|
/**
|
|
* This function returns an array with the same syntax as save_attributes().
|
|
*
|
|
* Calling this method requires the existence of an enclosing {@link accountContainer}.<br>
|
|
* <br>
|
|
* It allows additional LDAP changes when an account is deleted.
|
|
*
|
|
* @return List of LDAP operations, same as for save_attributes()
|
|
*/
|
|
public function delete_attributes() {
|
|
return 0;
|
|
}
|
|
|
|
/**
|
|
* This function creates meta HTML code which will be displayed when an account should be deleted.
|
|
*
|
|
* Calling this method requires the existence of an enclosing {@link accountContainer}.<br>
|
|
* <br>
|
|
* This can be used to interact with the user, e.g. should the home directory be deleted? The output
|
|
* of all modules is displayed on a single page.
|
|
*
|
|
* @return htmlElement meta HTML object
|
|
* @see htmlElement
|
|
*/
|
|
public function display_html_delete() {
|
|
return null;
|
|
}
|
|
|
|
/**
|
|
* Defines if the LDAP entry has only virtual child entries. This is the case for e.g. LDAP views.
|
|
*
|
|
* @return boolean has only virtual children
|
|
*/
|
|
public function hasOnlyVirtualChildren() {
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* This function processes user input.
|
|
*
|
|
* Calling this method requires the existence of an enclosing {@link accountContainer}.<br>
|
|
* <br>
|
|
* It checks the user input and saves changes in the module's data structures.<br>
|
|
* <br>
|
|
* <b>Example:</b> return array(array('ERROR', 'Invalid input!', 'This is not allowed here.'));
|
|
*
|
|
* @return array Array which contains status messages. Each entry is an array containing the status message parameters.
|
|
*/
|
|
public abstract function process_attributes();
|
|
|
|
/**
|
|
* This function creates meta HTML code to display the module page.
|
|
*
|
|
* Calling this method requires the existence of an enclosing {@link accountContainer}.
|
|
*
|
|
* @return htmlElement meta HTML object
|
|
*
|
|
* @see htmlElement
|
|
*/
|
|
public abstract function display_html_attributes();
|
|
|
|
/**
|
|
* Adds a simple text input field to the given htmlTable.
|
|
* The field name will be the same as the attribute name. There must also be a help entry with the attribute name as ID.
|
|
* A new line will also be added after this entry so multiple calls will show the fields one below the other.
|
|
*
|
|
* @param htmlTable $container parent container
|
|
* @param String $attrName attribute name
|
|
* @param String $label label name
|
|
* @param boolean $required this is a required field (default false)
|
|
* @param integer $length field length
|
|
* @param boolean $isTextArea show as text area (default false)
|
|
* @param array $autoCompleteValues values for auto-completion
|
|
* @return mixed reference to htmlTableExtendedInputField/htmlTableExtendedInputTextarea
|
|
*/
|
|
protected function &addSimpleInputTextField(&$container, $attrName, $label, $required = false, $length = null, $isTextArea = false, $autoCompleteValues = null) {
|
|
$value = '';
|
|
if (isset($this->attributes[$attrName][0])) {
|
|
$value = $this->attributes[$attrName][0];
|
|
}
|
|
if ($isTextArea) {
|
|
$cols = 30;
|
|
if ($length != null) {
|
|
$cols = $length;
|
|
}
|
|
$input = new htmlTableExtendedInputTextarea($attrName, $value, $cols, 3, $label, $attrName);
|
|
}
|
|
else {
|
|
$input = new htmlTableExtendedInputField($label, $attrName, $value, $attrName);
|
|
if ($length != null) {
|
|
$input->setFieldSize($length);
|
|
}
|
|
if (!empty($autoCompleteValues)) {
|
|
$input->enableAutocompletion($autoCompleteValues);
|
|
}
|
|
}
|
|
$input->setRequired($required);
|
|
$container->addElement($input, true);
|
|
return $input;
|
|
}
|
|
|
|
/**
|
|
* Adds a simple read-only field to the given container.
|
|
*
|
|
* @param htmlTable $container parent container
|
|
* @param String $attrName attribute name
|
|
* @param String $label field label
|
|
*/
|
|
protected function addSimpleReadOnlyField(&$container, $attrName, $label) {
|
|
$val = '';
|
|
if (!empty($this->attributes[$attrName][0])) {
|
|
$values = $this->attributes[$attrName];
|
|
array_map('htmlspecialchars', $values);
|
|
$val = implode('<br>', $values);
|
|
}
|
|
$labelBox = new htmlOutputText($label);
|
|
if (!empty($this->attributes[$attrName]) && (sizeof($this->attributes[$attrName]) > 1)) {
|
|
$labelBox->alignment = htmlElement::ALIGN_TOP;
|
|
}
|
|
$container->addElement($labelBox);
|
|
$container->addElement(new htmlOutputText($val, false), true);
|
|
}
|
|
|
|
/**
|
|
* Adds a text input field that may contain multiple values to the given htmlTable.
|
|
* The field name will be the same as the attribute name plus a counting number (e.g. street_0).
|
|
* The last field will be followed by a button to add a new value. This is named add_{attribute name} (e.g. add_street).
|
|
* There must be a help entry with the attribute name as ID.
|
|
* A new line will also be added after this entry so multiple calls will show the fields one below the other.
|
|
*
|
|
* @param htmlTable $container parent container
|
|
* @param String $attrName attribute name
|
|
* @param String $label label name
|
|
* @param boolean $required this is a required field (default false)
|
|
* @param integer $length field length
|
|
* @param boolean $isTextArea show as text area (default false)
|
|
* @param array $autoCompleteValues values for auto-completion
|
|
* @param integer $fieldSize field size
|
|
* @param array $htmlIDs reference to array where to add the generated HTML IDs of the input fields
|
|
* @param string $cssClasses additional CSS classes of input fields
|
|
*/
|
|
protected function addMultiValueInputTextField(&$container, $attrName, $label, $required = false, $length = null, $isTextArea = false,
|
|
$autoCompleteValues = null, $fieldSize = null, &$htmlIDs = null, $cssClasses = '') {
|
|
$values = array();
|
|
if (isset($this->attributes[$attrName][0])) {
|
|
$values = $this->attributes[$attrName];
|
|
}
|
|
if (sizeof($values) == 0) {
|
|
$values[] = '';
|
|
}
|
|
natcasesort($values);
|
|
$values = array_values($values);
|
|
if ($label !== null) {
|
|
$labelTextOut = new htmlOutputText($label, true, $required);
|
|
$labelTextOut->alignment = htmlElement::ALIGN_TOP;
|
|
$container->addElement($labelTextOut);
|
|
}
|
|
$subContainer = new htmlTable();
|
|
$subContainer->alignment = htmlElement::ALIGN_TOP;
|
|
for ($i = 0; $i < sizeof($values); $i++) {
|
|
if (!$isTextArea) {
|
|
$input = new htmlInputField($attrName . '_' . $i, $values[$i]);
|
|
if (!empty($cssClasses)) {
|
|
$input->setCSSClasses(array($cssClasses));
|
|
}
|
|
if (!empty($length)) {
|
|
$input->setFieldMaxLength($length);
|
|
}
|
|
if (!empty($fieldSize)) {
|
|
$input->setFieldSize($fieldSize);
|
|
}
|
|
if (!empty($autoCompleteValues)) {
|
|
$input->enableAutocompletion($autoCompleteValues);
|
|
}
|
|
$subContainer->addElement($input);
|
|
}
|
|
else {
|
|
$cols = 30;
|
|
if ($length != null) {
|
|
$cols = $length;
|
|
}
|
|
$textArea = new htmlInputTextarea($attrName . '_' . $i, $values[$i], $cols, 3);
|
|
if (!empty($cssClasses)) {
|
|
$textArea->setCSSClasses(array($cssClasses));
|
|
}
|
|
$subContainer->addElement($textArea);
|
|
}
|
|
if (!empty($htmlIDs)) {
|
|
$htmlIDs[] = $attrName . '_' . $i;
|
|
}
|
|
if (!empty($values[$i])) {
|
|
$subContainer->addElement(new htmlButton('del_' . $attrName . '_' . $i, 'del.png', true));
|
|
}
|
|
if ($i == 0) {
|
|
$subContainer->addElement(new htmlButton('add_' . $attrName, 'add.png', true));
|
|
}
|
|
$subContainer->addNewLine();
|
|
}
|
|
$container->addElement($subContainer);
|
|
$help = new htmlHelpLink($attrName);
|
|
$help->alignment = htmlElement::ALIGN_TOP;
|
|
$container->addElement($help, true);
|
|
}
|
|
|
|
/**
|
|
* Validates a multi-value text field.
|
|
* The input fields must be created with function addMultiValueInputTextField().
|
|
* If validation is used then there must exist a message named [{attribute name}][0] (e.g. $this->messages['street'][0]).
|
|
*
|
|
* @param String $attrName attribute name
|
|
* @param array $errors errors array where to put validation errors
|
|
* @param String $validationID validation ID for function get_preg() (default: null, null means no validation)
|
|
*/
|
|
protected function processMultiValueInputTextField($attrName, &$errors, $validationID = null) {
|
|
$counter = 0;
|
|
while (isset($_POST[$attrName . '_' . $counter])) {
|
|
$this->attributes[$attrName][$counter] = trim($_POST[$attrName . '_' . $counter]);
|
|
if (($this->attributes[$attrName][$counter] == '') || isset($_POST['del_' . $attrName . '_' . $counter])) {
|
|
unset($this->attributes[$attrName][$counter]);
|
|
}
|
|
elseif (($validationID != null) && ($this->attributes[$attrName][$counter] != '') && !get_preg($this->attributes[$attrName][$counter], $validationID)) {
|
|
$msg = $this->messages[$attrName][0];
|
|
if (sizeof($msg) < 3) {
|
|
$msg[] = htmlspecialchars($this->attributes[$attrName][$counter]);
|
|
}
|
|
$errors[] = $msg;
|
|
}
|
|
$counter++;
|
|
}
|
|
if (isset($_POST['add_' . $attrName])) {
|
|
$this->attributes[$attrName][] = '';
|
|
}
|
|
$this->attributes[$attrName] = array_values(array_unique($this->attributes[$attrName]));
|
|
}
|
|
|
|
/**
|
|
* Adds a select field type that may contain multiple values to the given htmlTable.
|
|
* The field name will be the same as the attribute name plus a counting number (e.g. street_0).
|
|
* The last field will be followed by a button to add a new value. This is named add_{attribute name} (e.g. add_street).
|
|
* There must be a help entry with the attribute name as ID.
|
|
* A new line will also be added after this entry so multiple calls will show the fields one below the other.
|
|
*
|
|
* @param htmlTable $container parent container
|
|
* @param String $attrName attribute name
|
|
* @param String $label label name
|
|
* @param array $options options for the selects
|
|
* @param boolean $hasDescriptiveOptions has descriptive options
|
|
* @param boolean $required this is a required field (default false)
|
|
* @param integer $fieldSize field size
|
|
* @param array $htmlIDs reference to array where to add the generated HTML IDs of the input fields
|
|
*/
|
|
protected function addMultiValueSelectField(&$container, $attrName, $label, $options, $hasDescriptiveOptions = false,
|
|
$required = false, $fieldSize = 1, &$htmlIDs = null) {
|
|
$values = array();
|
|
if (isset($this->attributes[$attrName][0])) {
|
|
$values = $this->attributes[$attrName];
|
|
}
|
|
if (sizeof($values) == 0) {
|
|
$values[] = '';
|
|
}
|
|
natcasesort($values);
|
|
$values = array_values($values);
|
|
if ($label !== null) {
|
|
$labelTextOut = new htmlOutputText($label);
|
|
$labelTextOut->alignment = htmlElement::ALIGN_TOP;
|
|
$labelTextOut->setMarkAsRequired($required);
|
|
$container->addElement($labelTextOut);
|
|
}
|
|
$subContainer = new htmlTable();
|
|
$subContainer->alignment = htmlElement::ALIGN_TOP;
|
|
for ($i = 0; $i < sizeof($values); $i++) {
|
|
$input = new htmlSelect($attrName . '_' . $i, $options, array($values[$i]), $fieldSize);
|
|
$input->setHasDescriptiveElements($hasDescriptiveOptions);
|
|
$subContainer->addElement($input);
|
|
if (!empty($htmlIDs)) {
|
|
$htmlIDs[] = $attrName . '_' . $i;
|
|
}
|
|
if (!empty($values[$i])) {
|
|
$subContainer->addElement(new htmlButton('del_' . $attrName . '_' . $i, 'del.png', true));
|
|
}
|
|
if ($i == 0) {
|
|
$subContainer->addElement(new htmlButton('add_' . $attrName, 'add.png', true));
|
|
}
|
|
$subContainer->addNewLine();
|
|
}
|
|
$container->addElement($subContainer);
|
|
$help = new htmlHelpLink($attrName);
|
|
$help->alignment = htmlElement::ALIGN_TOP;
|
|
$container->addElement($help, true);
|
|
}
|
|
|
|
/**
|
|
* Validates a multi-value select field.
|
|
* The select fields must be created with function addMultiValueSelectField().
|
|
*
|
|
* @param String $attrName attribute name
|
|
*/
|
|
protected function processMultiValueSelectField($attrName) {
|
|
$counter = 0;
|
|
while (isset($_POST[$attrName . '_' . $counter])) {
|
|
$this->attributes[$attrName][$counter] = trim($_POST[$attrName . '_' . $counter]);
|
|
if (($this->attributes[$attrName][$counter] == '') || isset($_POST['del_' . $attrName . '_' . $counter])) {
|
|
unset($this->attributes[$attrName][$counter]);
|
|
}
|
|
$counter++;
|
|
}
|
|
if (isset($_POST['add_' . $attrName])) {
|
|
$this->attributes[$attrName][] = '';
|
|
}
|
|
$this->attributes[$attrName] = array_values(array_unique($this->attributes[$attrName]));
|
|
}
|
|
|
|
/**
|
|
* Adds a simple text input field for the self service.
|
|
* The field name will be the same as the class name plus "_" plus attribute name (e.g. posixAccount_cn).
|
|
*
|
|
* @param array $container array that is used as return value for getSelfServiceOptions()
|
|
* @param String $name attribute name (== field name)
|
|
* @param String $label label to display in front of input field
|
|
* @param array $fields list of active fields
|
|
* @param array $attributes attributes of LDAP account
|
|
* @param array $readOnlyFields list of read-only fields
|
|
* @param boolean $required field is required
|
|
* @param boolean $isTextArea display as text area
|
|
*/
|
|
protected function addSimpleSelfServiceTextField(&$container, $name, $label, &$fields, &$attributes, &$readOnlyFields, $required = false, $isTextArea = false) {
|
|
$value = '';
|
|
if (isset($attributes[$name][0])) {
|
|
$value = $attributes[$name][0];
|
|
}
|
|
if (!$isTextArea && !in_array($name, $readOnlyFields)) {
|
|
$field = new htmlInputField(get_class($this) . '_' . $name, $value);
|
|
$field->setRequired($required);
|
|
$field->setFieldSize(null);
|
|
}
|
|
elseif ($isTextArea && !in_array($name, $readOnlyFields)) {
|
|
$field = new htmlInputTextarea(get_class($this) . '_' . $name, $value, null, null);
|
|
}
|
|
else {
|
|
if (!$isTextArea) {
|
|
$field = new htmlOutputText($value);
|
|
}
|
|
else {
|
|
$value = htmlspecialchars($value);
|
|
$value = str_replace("\n", '<br>', $value);
|
|
$field = new htmlOutputText($value, false);
|
|
}
|
|
}
|
|
$row = new htmlResponsiveRow();
|
|
$row->addLabel(new htmlOutputText($this->getSelfServiceLabel($name, $label)));
|
|
$row->addField($field);
|
|
$container[$name] = $row;
|
|
}
|
|
|
|
/**
|
|
* Checks the input value of a self service text field.
|
|
* The field name must be the same as the class name plus "_" plus attribute name (e.g. posixAccount_cn).
|
|
* If validation is used then there must exist a message named [{attribute name}][0] (e.g. $this->messages['street'][0]).
|
|
*
|
|
* @param array $container return value of checkSelfServiceOptions()
|
|
* @param String $name attribute name
|
|
* @param array $attributes LDAP attributes
|
|
* @param string $fields input fields
|
|
* @param array $readOnlyFields list of read-only fields
|
|
* @param String $validationID validation ID for get_preg()
|
|
*/
|
|
protected function checkSimpleSelfServiceTextField(&$container, $name, &$attributes, $fields, &$readOnlyFields, $validationID = null) {
|
|
if (in_array($name, $fields) && !in_array($name, $readOnlyFields)) {
|
|
$fieldName = get_class($this) . '_' . $name;
|
|
if (isset($_POST[$fieldName]) && ($_POST[$fieldName] != '')) {
|
|
if (($validationID != null) && !get_preg($_POST[$fieldName], $validationID)) {
|
|
$container['messages'][] = $this->messages[$name][0];
|
|
}
|
|
else {
|
|
if (isset($attributes[$name]) && ($attributes[$name][0] != $_POST[$fieldName])) {
|
|
$container['mod'][$name] = array($_POST[$fieldName]);
|
|
}
|
|
elseif (!isset($attributes[$name])) {
|
|
$container['add'][$name] = array($_POST[$fieldName]);
|
|
}
|
|
}
|
|
}
|
|
elseif (isset($attributes[$name])) {
|
|
$container['del'][$name] = $attributes[$name];
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Adds a simple text input field for the self service.
|
|
* The field name will be the same as the class name plus "_" plus attribute name (e.g. posixAccount_cn).
|
|
*
|
|
* @param array $container array that is used as return value for getSelfServiceOptions()
|
|
* @param String $name attribute name (== field name)
|
|
* @param String $label label to display in front of input field
|
|
* @param array $fields list of active fields
|
|
* @param array $attributes attributes of LDAP account
|
|
* @param array $readOnlyFields list of read-only fields
|
|
* @param boolean $required field is required
|
|
* @param boolean $isTextArea display as text area
|
|
*/
|
|
protected function addMultiValueSelfServiceTextField(&$container, $name, $label, &$fields, &$attributes, &$readOnlyFields, $required = false, $isTextArea = false) {
|
|
$values = array();
|
|
if (isset($attributes[$name][0])) {
|
|
$values = $attributes[$name];
|
|
}
|
|
$readOnly = in_array($name, $readOnlyFields);
|
|
$field = new htmlResponsiveRow();
|
|
if (!$readOnly) {
|
|
if (empty($values)) {
|
|
$values[] = '';
|
|
}
|
|
$fieldNamePrefix = get_class($this) . '_' . $name . '_';
|
|
for ($i = 0; $i < sizeof($values); $i++) {
|
|
$fieldRow = new htmlResponsiveRow();
|
|
$value = $values[$i];
|
|
if (!$isTextArea) {
|
|
$inputField = new htmlInputField($fieldNamePrefix . $i, $value);
|
|
$inputField->setRequired($required);
|
|
$inputField->setFieldSize(null);
|
|
}
|
|
else {
|
|
$inputField = new htmlInputTextarea($fieldNamePrefix . $i, $value, null, null);
|
|
}
|
|
$fieldRow->add($inputField, 9);
|
|
if (!empty($value)) {
|
|
$linkGroup = new htmlGroup();
|
|
$delLink = new htmlLink(null, '#', '../../graphics/del.png');
|
|
$delLink->setOnClick('window.lam.selfservice.delMultiValue(\'' . $fieldNamePrefix . '\', this); return false;');
|
|
$delLink->setCSSClasses(array('del-link'));
|
|
$linkGroup->addElement($delLink);
|
|
if ($i === (sizeof($values) - 1)) {
|
|
$addLink = new htmlLink(null, '#', '../../graphics/add.png');
|
|
$addLink->setOnClick('window.lam.selfservice.addMultiValue(\'' . $fieldNamePrefix . '\', this); return false;');
|
|
$addLink->setCSSClasses(array('add-link', 'margin-left5'));
|
|
$linkGroup->addElement($addLink);
|
|
}
|
|
$fieldRow->add($linkGroup, 3);
|
|
}
|
|
$field->add($fieldRow, 12);
|
|
}
|
|
}
|
|
else {
|
|
foreach ($values as $value) {
|
|
if (!$isTextArea) {
|
|
$inputField = new htmlOutputText($value);
|
|
}
|
|
else {
|
|
$inputField = new htmlOutputText($value);
|
|
$inputField->setPreformatted(true);
|
|
}
|
|
$field->add($inputField, 12);
|
|
}
|
|
}
|
|
$row = new htmlResponsiveRow();
|
|
$label = new htmlOutputText($this->getSelfServiceLabel($name, $label));
|
|
$label->setMarkAsRequired($required);
|
|
$row->addLabel($label);
|
|
$row->addField($field);
|
|
$container[$name] = $row;
|
|
}
|
|
|
|
/**
|
|
* Checks the input value of a self service multi-value text field.
|
|
* The field name must be the same as the class name plus "_" plus attribute name (e.g. posixAccount_cn).
|
|
* If validation is used then there must exist a message named [{attribute name}][0] (e.g. $this->messages['street'][0]).
|
|
*
|
|
* @param array $container return value of checkSelfServiceOptions()
|
|
* @param String $name attribute name
|
|
* @param array $attributes LDAP attributes
|
|
* @param string $fields input fields
|
|
* @param array $readOnlyFields list of read-only fields
|
|
* @param String $validationID validation ID for get_preg()
|
|
*/
|
|
protected function checkMultiValueSelfServiceTextField(&$container, $name, &$attributes, $fields, &$readOnlyFields, $validationID = null) {
|
|
if (in_array($name, $fields) && !in_array($name, $readOnlyFields)) {
|
|
$fieldName = get_class($this) . '_' . $name;
|
|
$valuesNew = array();
|
|
foreach ($_POST as $postKey => $postValue) {
|
|
if (strpos($postKey, $fieldName) === false) {
|
|
continue;
|
|
}
|
|
if (empty($postValue)) {
|
|
continue;
|
|
}
|
|
if (($validationID != null) && !get_preg($postValue, $validationID)) {
|
|
$container['messages'][] = $this->messages[$name][0];
|
|
return;
|
|
}
|
|
$valuesNew[] = $postValue;
|
|
}
|
|
$valuesOld = isset($attributes[$name]) ? $attributes[$name] : array();
|
|
$intersect = array_intersect($valuesOld, $valuesNew);
|
|
if ((sizeof($valuesOld) != sizeof($valuesNew)) || (sizeof($intersect) != sizeof($valuesOld))) {
|
|
$container['mod'][$name] = $valuesNew;
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Returns a list of managed object classes for this module.
|
|
*
|
|
* Calling this method does not require the existence of an enclosing {@link accountContainer}.<br>
|
|
* <br>
|
|
* This is used to fix spelling errors in LDAP-Entries (e.g. if "posixACCOUNT" is read instead of "posixAccount" from LDAP).<br>
|
|
* <br>
|
|
* <b>Example:</b> return array('posixAccount')
|
|
*
|
|
* @param string $typeId type id (user, group, host)
|
|
* @return array list of object classes
|
|
*
|
|
* @see baseModule::get_metaData()
|
|
*/
|
|
public function getManagedObjectClasses($typeId) {
|
|
if (isset($this->meta['objectClasses']) && is_array($this->meta['objectClasses'])) {
|
|
return $this->meta['objectClasses'];
|
|
}
|
|
return array();
|
|
}
|
|
|
|
/**
|
|
* Returns a list of aliases for LDAP attributes.
|
|
*
|
|
* Calling this method does not require the existence of an enclosing {@link accountContainer}.<br>
|
|
* <br>
|
|
* All alias attributes will be renamed to the given attribute names.
|
|
*
|
|
* @param string $typeId type id (user, group, host)
|
|
* @return array list of aliases like array("alias name" => "attribute name")
|
|
*
|
|
* @see baseModule::get_metaData()
|
|
*/
|
|
public function getLDAPAliases($typeId) {
|
|
if (isset($this->meta['LDAPaliases']) && is_array($this->meta['LDAPaliases'])) {
|
|
return $this->meta['LDAPaliases'];
|
|
}
|
|
return array();
|
|
}
|
|
|
|
/**
|
|
* Returns a list of LDAP attributes which are managed by this module.
|
|
* All attribute names will be renamed to match the given spelling.
|
|
*
|
|
* @param string $typeId type id (user, group, host)
|
|
* @return array list of attributes
|
|
*
|
|
* @see baseModule::get_metaData()
|
|
*/
|
|
public function getManagedAttributes($typeId) {
|
|
if (isset($this->meta['attributes']) && is_array($this->meta['attributes'])) {
|
|
return $this->meta['attributes'];
|
|
}
|
|
return array();
|
|
}
|
|
|
|
/**
|
|
* Returns a list of operational LDAP attributes which are managed by this module and need to be explicitly set for LDAP search.
|
|
*
|
|
* @param string $typeId account type id
|
|
* @return array list of hidden attributes
|
|
*
|
|
* @see baseModule::get_metaData()
|
|
*/
|
|
public function getManagedHiddenAttributes($typeId) {
|
|
if (isset($this->meta['hiddenAttributes']) && is_array($this->meta['hiddenAttributes'])) {
|
|
return $this->meta['hiddenAttributes'];
|
|
}
|
|
return array();
|
|
}
|
|
|
|
/**
|
|
* This function returns a list of PHP extensions (e.g. hash) which are needed by this module.
|
|
*
|
|
* Calling this method does not require the existence of an enclosing {@link accountContainer}.
|
|
*
|
|
* @return array extensions
|
|
*
|
|
* @see baseModule::get_metaData()
|
|
*/
|
|
public function getRequiredExtensions() {
|
|
if (isset($this->meta['extensions']) && is_array($this->meta['extensions'])) {
|
|
return $this->meta['extensions'];
|
|
}
|
|
return array();
|
|
}
|
|
|
|
/**
|
|
* This function returns a list of possible LDAP attributes (e.g. uid, cn, ...) which can be used to search for LDAP objects.
|
|
*
|
|
* Calling this method does not require the existence of an enclosing {@link accountContainer}.
|
|
*
|
|
* @return array attributes
|
|
*
|
|
* @see baseModule::get_metaData()
|
|
*/
|
|
public function getSelfServiceSearchAttributes() {
|
|
if (isset($this->meta['selfServiceSearchAttributes']) && is_array($this->meta['selfServiceSearchAttributes'])) {
|
|
return $this->meta['selfServiceSearchAttributes'];
|
|
}
|
|
return array();
|
|
}
|
|
|
|
/**
|
|
* Returns a list of possible input fields and their descriptions.
|
|
*
|
|
* Calling this method does not require the existence of an enclosing {@link accountContainer}.<br>
|
|
* <br>
|
|
* <b>Format:</b> array(<field identifier> => <field description>)
|
|
*
|
|
* @return array fields
|
|
*
|
|
* @see baseModule::get_metaData()
|
|
*/
|
|
public function getSelfServiceFields() {
|
|
if (isset($this->meta['selfServiceFieldSettings']) && is_array($this->meta['selfServiceFieldSettings'])) {
|
|
return $this->meta['selfServiceFieldSettings'];
|
|
}
|
|
return array();
|
|
}
|
|
|
|
/**
|
|
* Returns if a given self service field can be set in read-only mode.
|
|
*
|
|
* @param String $fieldID field identifier
|
|
* @param selfServiceProfile $profile currently edited profile
|
|
* @return boolean may be set read-only
|
|
*/
|
|
public function canSelfServiceFieldBeReadOnly($fieldID, $profile) {
|
|
if (isset($this->meta['selfServiceReadOnlyFields']) && is_array($this->meta['selfServiceReadOnlyFields'])) {
|
|
return in_array($fieldID, $this->meta['selfServiceReadOnlyFields']);
|
|
}
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* Returns if a self service field can be relabeled.
|
|
*
|
|
* @param String $fieldID field ID
|
|
* @param selfServiceProfile $profile currently edited profile
|
|
* @return boolean may be relabeled
|
|
*/
|
|
public function canSelfServiceFieldBeRelabeled($fieldID, $profile) {
|
|
if (isset($this->meta['selfServiceNoRelabelFields']) && is_array($this->meta['selfServiceNoRelabelFields'])) {
|
|
return !in_array($fieldID, $this->meta['selfServiceNoRelabelFields']);
|
|
}
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* Returns the field label. This can be either the given default label or an override value from profile.
|
|
*
|
|
* @param String $fieldID field ID
|
|
* @param String $defaultLabel default label text
|
|
* @return String label
|
|
*/
|
|
protected function getSelfServiceLabel($fieldID, $defaultLabel) {
|
|
if (!$this->canSelfServiceFieldBeRelabeled($fieldID, $this->selfServiceSettings)) {
|
|
return $defaultLabel;
|
|
}
|
|
$key = get_class($this) . '_' . $fieldID;
|
|
return empty($this->selfServiceSettings->relabelFields[$key]) ? $defaultLabel : $this->selfServiceSettings->relabelFields[$key];
|
|
}
|
|
|
|
/**
|
|
* Returns the meta HTML code for each input field.
|
|
*
|
|
* Calling this method does not require the existence of an enclosing {@link accountContainer}.<br>
|
|
* <br>
|
|
* It is not possible to display help links.
|
|
*
|
|
* @param array $fields list of active fields
|
|
* @param array $attributes attributes of LDAP account
|
|
* @param boolean $passwordChangeOnly indicates that the user is only allowed to change his password and no LDAP content is readable
|
|
* @param array $readOnlyFields list of read-only fields
|
|
* @return array list of meta HTML elements (field name => htmlResponsiveRow)
|
|
*
|
|
* @see htmlElement
|
|
*/
|
|
public function getSelfServiceOptions($fields, $attributes, $passwordChangeOnly, $readOnlyFields) {
|
|
// this function must be overwritten by subclasses.
|
|
return array();
|
|
}
|
|
|
|
/**
|
|
* Checks if all input values are correct and returns the LDAP attributes which should be changed.
|
|
* <br>Return values:
|
|
* <br>messages: array of parameters to create status messages
|
|
* <br>add: array of attributes to add
|
|
* <br>del: array of attributes to remove
|
|
* <br>mod: array of attributes to modify
|
|
* <br>info: array of values with informational value (e.g. to be used later by pre/postModify actions)
|
|
*
|
|
* Calling this method does not require the existence of an enclosing {@link accountContainer}.
|
|
*
|
|
* @param string $fields input fields
|
|
* @param array $attributes LDAP attributes
|
|
* @param boolean $passwordChangeOnly indicates that the user is only allowed to change his password and no LDAP content is readable
|
|
* @param array $readOnlyFields list of read-only fields
|
|
* @return array messages and attributes (array('messages' => array(), 'add' => array('mail' => array('test@test.com')), 'del' => array(), 'mod' => array(), 'info' => array()))
|
|
*/
|
|
public function checkSelfServiceOptions($fields, $attributes, $passwordChangeOnly, $readOnlyFields) {
|
|
$return = array('messages' => array(), 'add' => array(), 'del' => array(), 'mod' => array(), 'info' => array());
|
|
return $return;
|
|
}
|
|
|
|
/**
|
|
* Returns a list of self service configuration settings.
|
|
*
|
|
* Calling this method does not require the existence of an enclosing {@link accountContainer}.<br>
|
|
* <br>
|
|
* 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 conflicts.
|
|
*
|
|
* @param selfServiceProfile $profile currently edited profile
|
|
* @return htmlElement meta HTML object
|
|
*
|
|
* @see baseModule::get_metaData()
|
|
* @see htmlElement
|
|
*/
|
|
public function getSelfServiceSettings($profile) {
|
|
if (isset($this->meta['selfServiceSettings'])) {
|
|
return $this->meta['selfServiceSettings'];
|
|
}
|
|
else {
|
|
return array();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Checks if the self service settings are valid.
|
|
*
|
|
* Calling this method does not require the existence of an enclosing {@link accountContainer}.<br>
|
|
* <br>
|
|
* If the input data is invalid the return value is an array that contains arrays
|
|
* to build StatusMessages (message type, message head, message text). If no errors
|
|
* occured the function returns an empty array.
|
|
*
|
|
* @param array $options hash array (option name => value) that contains the input. The option values are all arrays containing one or more elements.
|
|
* @param selfServiceProfile $profile self service profile
|
|
* @return array error messages
|
|
*/
|
|
public function checkSelfServiceSettings(&$options, &$profile) {
|
|
// needs to be implemented by the subclasses, if needed
|
|
return array();
|
|
}
|
|
|
|
/**
|
|
* Allows the module to run commands before the LDAP entry is changed or created.
|
|
*
|
|
* An error message should be printed if the function returns false.
|
|
*
|
|
* @param boolean $newAccount is new account or existing one
|
|
* @param array $attributes LDAP attributes of this entry
|
|
* @return boolean true, if no problems occured
|
|
*/
|
|
public function preModifySelfService($newAccount, $attributes) {
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* Allows the module to run commands after the LDAP entry is changed or created.
|
|
*
|
|
* @param boolean $newAccount is new account or existing one
|
|
* @param array $attributes LDAP attributes of this entry
|
|
* @return boolean true, if no problems occured
|
|
*/
|
|
public function postModifySelfService($newAccount, $attributes) {
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* This allows modules to create a link to a module specific page
|
|
* for the self service.
|
|
* The link is shown on the login page of the self service. You
|
|
* can use this to provide e.g. a page to reset passwords.
|
|
*
|
|
* @param array $settings self service settings
|
|
* @return String link text (null if no special page used)
|
|
*/
|
|
public function getLinkToSpecialSelfServicePage($settings) {
|
|
return null;
|
|
}
|
|
|
|
/**
|
|
* This function creates meta HTML code to display the module specific page
|
|
* for the self service.
|
|
*
|
|
* @param selfServiceProfile $profile self service settings
|
|
* @return htmlElement meta HTML object
|
|
*
|
|
* @see htmlElement
|
|
*/
|
|
public function displaySpecialSelfServicePage($profile) {
|
|
return null;
|
|
}
|
|
|
|
/**
|
|
* Returns the {@link accountContainer} object.
|
|
*
|
|
* @return accountContainer accountContainer object
|
|
*
|
|
* @see accountContainer
|
|
*/
|
|
protected function getAccountContainer() {
|
|
if (isset($this->base) && isset($_SESSION[$this->base])) {
|
|
return $_SESSION[$this->base];
|
|
}
|
|
else {
|
|
return null;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Returns the LDAP attributes which are managed in this module.
|
|
*
|
|
* @return array attributes
|
|
*/
|
|
public function getAttributes() {
|
|
return $this->attributes;
|
|
}
|
|
|
|
/**
|
|
* Returns the LDAP attributes which are managed in this module (with unchanged values).
|
|
*
|
|
* @return array attributes
|
|
*/
|
|
public function getOriginalAttributes() {
|
|
return $this->orig;
|
|
}
|
|
|
|
/**
|
|
* Returns the path to the module icon.
|
|
* The path must be releative to graphics (e.g. key.png) or an URL (/icons/icon.png or http://server/icon.png).
|
|
* You can also set $this->meta['icon']. The preferred size is 32x32px.
|
|
*
|
|
* @return unknown
|
|
*
|
|
* @see baseModule::get_metaData()
|
|
*/
|
|
public function getIcon() {
|
|
if (isset($this->meta['icon'])) {
|
|
return $this->meta['icon'];
|
|
}
|
|
return null;
|
|
}
|
|
|
|
/**
|
|
* Manages AJAX requests.
|
|
* This function may be called with or without an account container.
|
|
*/
|
|
public function handleAjaxRequest() {
|
|
// modules that use AJAX need to implement this function
|
|
}
|
|
|
|
/**
|
|
* Specifies if this module supports the LAM admin interface.
|
|
* The LAM admin interface are the pages that allow to manage e.g. users and groups.
|
|
* In contrast there is also the LAM self service interface. Most modules support
|
|
* the admin interface.
|
|
*
|
|
* @return boolean support admin interface
|
|
*/
|
|
public function supportsAdminInterface() {
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* Returns a list of jobs that can be run.
|
|
*
|
|
* @param LAMConfig $config configuration
|
|
*/
|
|
public function getSupportedJobs(&$config) {
|
|
return array();
|
|
}
|
|
|
|
|
|
|
|
// helper functions
|
|
|
|
/**
|
|
* Returns if the given configuration option is set.
|
|
* This function returns false if the configuration options cannot be read.
|
|
*
|
|
* @param String $optionName name of the option
|
|
* @param boolean $default default value if config option is not set at all (default: false)
|
|
* @return boolean true if option is set
|
|
*/
|
|
protected function isBooleanConfigOptionSet($optionName, $default = false) {
|
|
// abort if configuration is not available
|
|
if (!isset($this->moduleSettings) || !is_array($this->moduleSettings) || !isset($this->moduleSettings[$optionName][0])) {
|
|
return $default;
|
|
}
|
|
return ($this->moduleSettings[$optionName][0] == 'true');
|
|
}
|
|
|
|
/**
|
|
* Returns a list of wildcards that can be replaced in input fileds.
|
|
* E.g. "$firstname" is replaced with "givenName" attribute value.
|
|
*
|
|
* @return array replacements as wildcard => value
|
|
*/
|
|
public function getWildCardReplacements() {
|
|
return array();
|
|
}
|
|
|
|
}
|
|
|
|
?>
|