An error occurred while loading the file. Please try again.
-
Côme Chilliet authored
Also global_is_set to is_set. issue #6024
Unverifiedb388c0db
<?php
/*
This code is part of FusionDirectory (http://www.fusiondirectory.org/)
Copyright (C) 2003-2010 Cajus Pollmeier
Copyright (C) 2011-2018 FusionDirectory
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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
*/
/*!
* \file functions.inc
* Common functions and named definitions.
*/
/* Define common locations and variables */
require_once ('variables.inc');
/* Include required files */
require_once (CACHE_DIR.'/'.CLASS_CACHE);
require_once ('functions_debug.inc');
require_once ('accept-to-gettext.inc');
/* Define constants for debugging */
define ('DEBUG_TRACE', 1); /*! Debug level for tracing of common actions (save, check, etc.) */
define ('DEBUG_LDAP', 2); /*! Debug level for LDAP queries */
define ('DEBUG_DB', 4); /*! Debug level for database operations */
define ('DEBUG_SHELL', 8); /*! Debug level for shell commands */
define ('DEBUG_POST', 16); /*! Debug level for POST content */
define ('DEBUG_SESSION', 32); /*! Debug level for SESSION content */
define ('DEBUG_CONFIG', 64); /*! Debug level for CONFIG information */
define ('DEBUG_ACL', 128); /*! Debug level for ACL infos */
define ('DEBUG_SI', 256); /*! Debug level for communication with Argonaut */
define ('DEBUG_MAIL', 512); /*! Debug level for all about mail (mailAccounts, imap, sieve etc.) */
define ('DEBUG_FAI', 1024); /* FAI (incomplete) */
/* Define shadow states */
define ('POSIX_ACCOUNT_EXPIRED', 1);
define ('POSIX_WARN_ABOUT_EXPIRATION', 2);
define ('POSIX_FORCE_PASSWORD_CHANGE', 4);
define ('POSIX_DISALLOW_PASSWORD_CHANGE', 8);
/* Rewrite german 'umlauts' and spanish 'accents'
to get better results */
$REWRITE = [ "ä" => "ae",
"ö" => "oe",
"ü" => "ue",
"Ä" => "Ae",
"Ö" => "Oe",
"Ü" => "Ue",
"ß" => "ss",
"á" => "a",
"é" => "e",
"í" => "i",
"ó" => "o",
"ú" => "u",
"Á" => "A",
"É" => "E",
"Í" => "I",
7172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
"Ó" => "O",
"Ú" => "U",
"ñ" => "ny",
"Ñ" => "Ny" ];
/*!
* \brief Does autoloading for classes used in FusionDirectory.
*
* Takes the list generated by 'fusiondirectory-setup' and loads the
* file containing the requested class.
*
* \param array $class_name list of class name
*/
function fusiondirectory_autoload ($class_name)
{
global $class_mapping, $BASE_DIR, $config;
if ($class_mapping === NULL) {
if (isset($config) && is_object($config) &&
$config->get_cfg_value('displayerrors') == 'TRUE') {
list($trace,) = html_trace();
echo $trace;
echo "<br/>\n";
}
echo sprintf(_("Fatal error: no class locations defined - please run '%s' to fix this"), "<b>fusiondirectory-setup --update-cache</b>");
exit;
}
/* Do not try to autoload smarty classes */
if (strpos($class_name, 'Smarty_') === 0) {
return;
}
if (isset($class_mapping["$class_name"])) {
require_once($BASE_DIR.'/'.$class_mapping["$class_name"]);
} else {
@DEBUG (DEBUG_TRACE, __LINE__, __FUNCTION__, __FILE__, $class_name, 'Could not load');
if (isset($config) && is_object($config) &&
$config->get_cfg_value('displayerrors') == 'TRUE') {
list($trace,) = html_trace();
echo $trace;
echo "<br/>\n";
}
echo sprintf(_("Fatal error: cannot instantiate class '%s' - try running '%s' to fix this"), $class_name, "<b>fusiondirectory-setup --update-cache</b>");
exit;
}
}
spl_autoload_register('fusiondirectory_autoload');
/*!
* \brief Checks if a class is available.
*
* \param string $name The subject of the test
*
* \return boolean Return TRUE if successfull FALSE otherwise
*/
function class_available ($name)
{
global $class_mapping;
return isset($class_mapping[$name]);
}
/*!
* \brief Check if plugin is available
*
* Checks if a given plugin is available and readable.
141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210
*
* \param string $plugin the subject of the check
*
* \return boolean Return TRUE if successfull FALSE otherwise
*/
function plugin_available ($plugin)
{
global $class_mapping, $BASE_DIR;
if (!isset($class_mapping[$plugin])) {
return FALSE;
} else {
return is_readable($BASE_DIR.'/'.$class_mapping[$plugin]);
}
}
/*!
* \brief Loads plist and load it in config object
*/
function load_plist ($ldap_available = TRUE)
{
global $config, $plist;
if (!session::is_set('plist')) {
/* Initially load all classes */
load_all_classes();
$plist = new pluglist();
session::set('plist', $plist);
$config->loadPlist($plist);
if ($ldap_available) {
$config->get_departments();
$config->make_idepartments();
}
}
return session::get('plist');
}
/*!
* \brief Debug level action
*
* Print a DEBUG level if specified debug level of the level matches the
* the configured debug level.
*
* \param int $level The log level of the message (should use the constants,
* defined in functions.in (DEBUG_TRACE, DEBUG_LDAP, etc.)
*
* \param int $line Define the line of the logged action (using __LINE__ is common)
*
* \param string $function Define the function where the logged action happened in
* (using __FUNCTION__ is common)
*
* \param string $file Define the file where the logged action happend in
* (using __FILE__ is common)
*
* \param mixed $data The data to log. Can be a message or an array, which is printed
* with print_a
*
* \param string $info Optional: Additional information
*/
function DEBUG ($level, $line, $function, $file, $data, $info = '')
{
static $first = TRUE;
if (($_SERVER['REQUEST_METHOD'] == 'POST') && preg_match('/index.php$/', $_SERVER['REQUEST_URI'])) {
return;
}
if (session::get('DEBUGLEVEL') & $level) {
if ($first) {
echo '<div id="debug-handling" class="notice">'.
'<img src="geticon.php?context=status&icon=dialog-information&size=22" alt="Information" style="vertical-align:middle;margin-right:.2em;"/>'.
'There is some debug output '.
211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280
'<button onClick="javascript:$$(\'div.debug_div\').each(function (a) { a.toggle (); });">Toggle</button>'.
'</div>';
$first = FALSE;
}
$output = "DEBUG[$level] ";
if ($function != '') {
$output .= "($file:$function():$line) - $info: ";
} else {
$output .= "($file:$line) - $info: ";
}
echo '<div class="debug_div">';
echo $output;
if (is_array($data)) {
print_a($data);
} else {
echo "'$data'";
}
echo "</div>\n";
}
}
/*!
* \brief Return themed path for specified base file
*
* Depending on its parameters, this function returns the full
* path of a template file. First match wins while searching
* in this order:
*
* - load theme depending file
* - load global theme depending file
* - load default theme file
* - load global default theme file
*
* \param string $filename The base file name
*
* \param boolean $plugin Flag to take the plugin directory as search base
*
* \param string $path User specified path to take as search base
*
* \return string Full path to the template file
*/
function get_template_path ($filename = '', $plugin = FALSE, $path = '')
{
global $config, $BASE_DIR;
$default_theme = 'breezy';
/* Set theme */
if (isset ($config)) {
$theme = $config->get_cfg_value('theme', $default_theme);
} else {
$theme = $default_theme;
}
/* Return path for empty filename */
if ($filename == '') {
return "themes/$theme/";
}
/* Return plugin dir or root directory? */
if ($plugin) {
if ($path == '') {
$path = session::get('plugin_dir');
$nf = preg_replace('!^'.$BASE_DIR.'/!', '', preg_replace('/^\.\.\//', '', $path));
} else {
$nf = preg_replace('!^'.$BASE_DIR.'/!', '', $path);
}
$paths = [
"$BASE_DIR/ihtml/themes/$theme/$nf/$filename",
"$BASE_DIR/ihtml/themes/$default_theme/$nf/$filename",
"$BASE_DIR/ihtml/themes/default/$nf/$filename",
281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350
$path."/$filename"
];
} else {
$paths = [
"themes/$theme/$filename",
"$BASE_DIR/ihtml/themes/$theme/$filename",
"themes/$default_theme/$filename",
"$BASE_DIR/ihtml/themes/$default_theme/$filename",
"themes/default/$filename",
"$BASE_DIR/ihtml/themes/default/$filename",
$filename
];
}
foreach ($paths as $path) {
if (file_exists($path)) {
return $path;
}
}
return end($paths);
}
/*!
* \brief Remove multiple entries from an array
*
* Removes every element that is in $needles from the
* array given as $haystack
*
* \param array $needles array of the entries to remove
*
* \param array $haystack original array to remove the entries from
*/
function array_remove_entries (array $needles, array $haystack)
{
return array_values(array_diff($haystack, $needles));
}
/*!
* \brief Remove multiple entries from an array (case-insensitive)
*
* Removes every element that is in $needles from the
* array given as $haystack but case insensitive
*
* \param array $needles array of the entries to remove
*
* \param array $haystack original array to remove the entries from
*/
function array_remove_entries_ics (array $needles, array $haystack)
{
// strcasecmp will work, because we only compare ASCII values here
return array_values(array_udiff($haystack, $needles, 'strcasecmp'));
}
/*!
* \brief Merge to array but remove duplicate entries (case-insensitive)
*
* Merges two arrays and removes duplicate entries. Triggers
* an error if first or second parametre is not an array.
*
* \param array $ar1 first array
*
* \param array $ar2 second array
*
* \return array
*/
function array_merge_unique ($ar1, $ar2)
{
351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420
if (!is_array($ar1) || !is_array($ar2)) {
trigger_error('Specified parameter(s) are not valid arrays.');
} else {
return array_values(array_unique(array_merge($ar1, $ar2)));
}
}
/*!
* \brief Generate a system log info
*
* Creates a syslog message, containing user information.
*
* \param string $message the message to log
*/
function fusiondirectory_log ($message)
{
global $ui;
/* Preset to something reasonable */
$username = '[unauthenticated]';
/* Replace username if object is present */
if (isset($ui)) {
if ($ui->uid != '') {
$username = '['.$ui->uid.']';
} else {
$username = '[unknown]';
}
}
syslog(LOG_INFO, "FusionDirectory $username: $message");
}
/*!
* \brief Initialize a LDAP connection
*
* Initializes a LDAP connection.
*
* \param string $server The server we are connecting to
*
* \param string $base The base of our ldap tree
*
* \param string $binddn Default: empty
*
* \param string $pass Default: empty
*
* \return LDAP object
*/
function ldap_init ($server, $base, $binddn = '', $pass = '')
{
global $config;
$ldap = new LDAP ($binddn, $pass, $server,
isset($config->current['LDAPFOLLOWREFERRALS']) && $config->current['LDAPFOLLOWREFERRALS'] == 'TRUE',
isset($config->current['LDAPTLS']) && $config->current['LDAPTLS'] == 'TRUE');
/* Sadly we've no proper return values here. Use the error message instead. */
if (!$ldap->success()) {
msg_dialog::display(_('Fatal error'),
sprintf(_("FATAL: Error when connecting the LDAP. Server said '%s'."), $ldap->get_error()),
FATAL_ERROR_DIALOG);
exit();
}
/* Preset connection base to $base and return to caller */
$ldap->cd ($base);
return $ldap;
}
421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490
/*!
* \brief Get user from LDAP directory
*
* Search the user by login or other fields authorized by the configuration
*
* \param string $username The username or email to check
*
* \return userinfo instance on SUCCESS, FALSE if not found, string error on error
*/
function ldap_get_user ($username)
{
global $config;
/* look through the entire ldap */
$ldap = $config->get_ldap_link();
if (!$ldap->success()) {
msg_dialog::display(_('LDAP error'),
msgPool::ldaperror($ldap->get_error(), '', LDAP_AUTH).'<br/><br/>'.session::get('errors'),
FATAL_ERROR_DIALOG);
exit();
}
$allowed_attributes = ['uid','mail'];
$verify_attr = [];
$tmp = explode(',', $config->get_cfg_value('loginAttribute'));
foreach ($tmp as $attr) {
if (in_array($attr, $allowed_attributes)) {
$verify_attr[] = $attr;
}
}
if (count($verify_attr) == 0) {
$verify_attr = ['uid'];
}
$tmp = $verify_attr;
$tmp[] = 'uid';
$filter = '';
foreach ($verify_attr as $attr) {
$filter .= '('.$attr.'='.$username.')';
}
$filter = '(&(|'.$filter.')(objectClass=inetOrgPerson))';
$ldap->cd($config->current['BASE']);
$ldap->search($filter, $tmp);
/* get results, only a count of 1 is valid */
if ($ldap->count() == 0) {
/* user not found */
return FALSE;
} elseif ($ldap->count() != 1) {
/* found more than one matching id */
return _('Login (uid) is not unique inside the LDAP tree. Please contact your administrator.');
}
/* LDAP schema is not case sensitive. Perform additional check. */
$attrs = $ldap->fetch();
$success = FALSE;
foreach ($verify_attr as $attr) {
if (isset($attrs[$attr][0]) && $attrs[$attr][0] == $username) {
$success = TRUE;
}
}
$ldap->disconnect();
if (!$success) {
return FALSE;
}
return new userinfo($attrs['dn']);
}
491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560
/*!
* \brief Verify user login against LDAP directory
*
* Checks if the specified username is in the LDAP and verifies if the
* password is correct by binding to the LDAP with the given credentials.
*
* \param string $username The username to check
*
* \param string $password The password to check
*
* \return TRUE on SUCCESS, NULL or FALSE on error
*/
function ldap_login_user ($username, $password)
{
global $config;
$ui = ldap_get_user($username);
if ($ui === FALSE) {
return NULL;
} elseif (is_string($ui)) {
msg_dialog::display(_('Internal error'), $ui, FATAL_ERROR_DIALOG);
return NULL;
}
/* password check, bind as user with supplied password */
$ldapObj = new LDAP($ui->dn, $password, $config->current['SERVER'],
isset($config->current['LDAPFOLLOWREFERRALS']) &&
$config->current['LDAPFOLLOWREFERRALS'] == 'TRUE',
isset($config->current['LDAPTLS'])
&& $config->current['LDAPTLS'] == 'TRUE'
);
$ldap = new ldapMultiplexer($ldapObj);
if (!$ldap->success()) {
return NULL;
}
if (class_available('ppolicyAccount')) {
$ldap->cd($config->current['BASE']);
$ldap->search('(objectClass=*)', [], 'one');
if (!$ldap->success()) {
msg_dialog::display(
_('Authentication error'),
_('It seems your user password has expired. Please use <a href="recovery.php">password recovery</a> to change it.'),
ERROR_DIALOG
);
return NULL;
}
}
/* Username is set, load subtreeACL's now */
$ui->loadACL();
return $ui;
}
/*!
* \brief Add a lock for object(s)
*
* Adds a lock by the specified user for one ore multiple objects.
* If the lock for that object already exists, an error is triggered.
*
* \param array $object The object or array of objects to lock
*
* \param string $user The user who shall own the lock
*/
function add_lock ($object, $user)
{
global $config;
/* Remember which entries were opened as read only, because we
561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630
don't need to remove any locks for them later.
*/
if (!session::is_set('LOCK_CACHE')) {
session::set('LOCK_CACHE', ['']);
}
if (is_array($object)) {
foreach ($object as $obj) {
add_lock($obj, $user);
}
return;
}
$cache = &session::get_ref('LOCK_CACHE');
if (isset($_POST['open_readonly'])) {
$cache['READ_ONLY'][$object] = TRUE;
return;
}
if (isset($cache['READ_ONLY'][$object])) {
unset($cache['READ_ONLY'][$object]);
}
/* Just a sanity check... */
if ($object == '' || $user == '') {
msg_dialog::display(_('Internal error'), _('Error while adding a lock. Contact the developers!'), ERROR_DIALOG);
return;
}
/* Check for existing entries in lock area */
$ldap = $config->get_ldap_link();
$ldap->cd(get_ou('lockRDN').get_ou('fusiondirectoryRDN').$config->current['BASE']);
$ldap->search('(&(objectClass=fdLockEntry)(fdUserDn='.ldap_escape_f($user).')(fdObjectDn='.base64_encode($object).'))',
['fdUserDn']);
if (!$ldap->success()) {
msg_dialog::display(_('Configuration error'), sprintf(_('Cannot create locking information in LDAP tree. Please contact your administrator!').'<br><br>'._('LDAP server returned: %s'), '<br><br><i>'.$ldap->get_error().'</i>'), ERROR_DIALOG);
return;
}
/* Add lock if none present */
if ($ldap->count() == 0) {
$attrs = [];
$name = md5($object);
$ldap->cd('cn='.$name.','.get_ou('lockRDN').get_ou('fusiondirectoryRDN').$config->current['BASE']);
$attrs = [
'objectClass' => 'fdLockEntry',
'fdUserDn' => $user,
'fdObjectDn' => base64_encode($object),
'cn' => $name,
'fdLockTimestamp' => LdapGeneralizedTime::toString(new DateTime('now')),
];
$ldap->add($attrs);
if (!$ldap->success()) {
msg_dialog::display(_('LDAP error'), msgPool::ldaperror($ldap->get_error(), "cn=$name,".get_ou('lockRDN').get_ou('fusiondirectoryRDN').$config->current['BASE'], 0), LDAP_ERROR);
return;
}
}
}
/*!
* \brief Remove a lock for object(s)
*
* Remove a lock for object(s)
*
* \param mixed $object object or array of objects for which a lock shall be removed
*/
function del_lock ($object)
{
global $config;
if (is_array($object)) {
631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700
foreach ($object as $obj) {
del_lock($obj);
}
return;
}
/* Sanity check */
if ($object == '') {
return;
}
/* If this object was opened in read only mode then
skip removing the lock entry, there wasn't any lock created.
*/
if (session::is_set('LOCK_CACHE')) {
$cache = &session::get_ref('LOCK_CACHE');
if (isset($cache['READ_ONLY'][$object])) {
unset($cache['READ_ONLY'][$object]);
return;
}
}
/* Check for existance and remove the entry */
$ldap = $config->get_ldap_link();
$ldap->cd(get_ou('lockRDN').get_ou('fusiondirectoryRDN').$config->current['BASE']);
$ldap->search('(&(objectClass=fdLockEntry)(fdObjectDn='.base64_encode($object).'))', ['fdObjectDn']);
$attrs = $ldap->fetch();
if (!$ldap->success()) {
msg_dialog::display(_('LDAP error'), msgPool::ldaperror($ldap->get_error(), $ldap->getDN(), LDAP_DEL, ERROR_DIALOG));
return;
} elseif (!empty($attrs['dn'])) {
$ldap->rmdir($attrs['dn']);
}
}
/*!
* \brief Remove all locks owned by a specific userdn
*
* For a given userdn remove all existing locks. This is usually
* called on logout.
*
* \param string $userdn the subject whose locks shall be deleted
*/
function del_user_locks ($userdn)
{
global $config;
/* Get LDAP ressources */
$ldap = $config->get_ldap_link();
$ldap->cd(get_ou('lockRDN').get_ou('fusiondirectoryRDN').$config->current['BASE']);
/* Remove all objects of this user, drop errors silently in this case. */
$ldap->search('(&(objectClass=fdLockEntry)(fdUserDn='.ldap_escape_f($userdn).'))', ['fdUserDn']);
while ($attrs = $ldap->fetch()) {
$ldap->rmdir($attrs['dn']);
}
}
/*!
* \brief Get a lock for a specific object
*
* Searches for a lock on a given object.
*
* \param string $object subject whose locks are to be searched
*
* \return string Returns the dn of the user who owns the lock or '' if no lock is found
* or FALSE if an error occured.
*/
701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770
function get_lock ($object)
{
/* Sanity check */
if ($object == '') {
msg_dialog::display(_('Internal error'), _('Error while adding a lock. Contact the developers!'), ERROR_DIALOG);
return FALSE;
}
/* Allow readonly access, the plugin constructor will restrict the acls */
if (isset($_POST['open_readonly'])) {
return '';
}
$locks = get_locks($object);
if ($locks === FALSE) {
return FALSE;
} elseif (empty($locks)) {
return '';
} else {
return $locks[0]['user'];
}
}
/*!
* \brief Get locks for objects
*
* Similar as get_lock(), but for multiple objects.
*
* \param mixed $objects Array of dns for which a lock will be searched or dn of a single object
*
* \param boolean $allow_readonly TRUE if readonly access should be permitted,
* FALSE if not (default).
*
* \return A numbered array containing all found locks as an array with key 'object'
* and key 'user', or FALSE if an error occured.
*/
function get_locks ($objects, $allow_readonly = FALSE)
{
global $config;
if (is_array($objects) && (count($objects) == 1)) {
$objects = reset($objects);
}
if (is_array($objects)) {
if ($allow_readonly) {
trigger_error('Read only is not possible for several objects');
}
$filter = '(&(objectClass=fdLockEntry)(|';
foreach ($objects as $obj) {
$filter .= '(fdObjectDn='.base64_encode($obj).')';
}
$filter .= '))';
} else {
if ($allow_readonly && isset($_POST['open_readonly'])) {
/* If readonly is allowed and asked and there is only one object, bypass lock detection */
return [];
}
$filter = '(&(objectClass=fdLockEntry)(fdObjectDn='.base64_encode($objects).'))';
}
/* Get LDAP link, check for presence of the lock entry */
$ldap = $config->get_ldap_link();
$ldap->cd(get_ou('lockRDN').get_ou('fusiondirectoryRDN').$config->current['BASE']);
$ldap->search($filter, ['fdUserDn','fdObjectDn', 'fdLockTimestamp']);
if (!$ldap->success()) {
msg_dialog::display(_('LDAP error'), msgPool::ldaperror($ldap->get_error(), '', LDAP_SEARCH), LDAP_ERROR);
return FALSE;
}
771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840
$locks = [];
while ($attrs = $ldap->fetch()) {
$locks[] = [
'dn' => $attrs['dn'],
'object' => base64_decode($attrs['fdObjectDn'][0]),
'user' => $attrs['fdUserDn'][0],
'timestamp' => LdapGeneralizedTime::fromString($attrs['fdLockTimestamp'][0]),
];
}
if (!is_array($objects) && (count($locks) > 1)) {
/* Hmm. We're removing broken LDAP information here and issue a warning. */
msg_dialog::display(_('Warning'), _('Found multiple locks for object to be locked. This should not happen - cleaning up multiple references.'), WARNING_DIALOG);
/* Clean up these references now... */
foreach ($locks as $lock) {
$ldap->rmdir($lock['dn']);
}
return FALSE;
}
return $locks;
}
/*!
* \brief Return the current userinfo object
*
* \return return the current userinfo object
*/
function &get_userinfo ()
{
global $ui;
return $ui;
}
/*!
* \brief Get global smarty object
*
* \return return the global smarty object
*/
function &get_smarty ()
{
global $smarty;
return $smarty;
}
/*!
* \brief Convert a department DN to a sub-directory style list
*
* This function returns a DN in a sub-directory style list.
* Examples:
* - ou=1.1.1,ou=limux becomes limux/1.1.1
* - cn=bla,ou=foo,dc=local becomes foo/bla or foo/bla/local, depending
* on the value for $base.
*
* If the specified DN contains a basedn which either matches
* the specified base or $config->current['BASE'] it is stripped.
*
* \param string $dn the subject for the conversion
*
* \param string $base the base dn, default: $config->current['BASE']
*
* \return a string in the form as described above
*/
function convert_department_dn ($dn, $base = NULL)
{
global $config;
841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910
if ($base == NULL) {
$base = $config->current['BASE'];
}
/* Build a sub-directory style list of the tree level
specified in $dn */
$dn = preg_replace('/'.preg_quote($base, '/')."$/i", '', $dn);
if (empty($dn)) {
return '/';
}
$dep = '';
foreach (explode(',', $dn) as $rdn) {
$dep = preg_replace("/^[^=]+=/", '', $rdn).'/'.$dep;
}
/* Return and remove accidently trailing slashes */
return trim($dep, '/');
}
/*! \brief Get the OU of a certain RDN
*
* Given a certain RDN name (ogroupRDN, applicationRDN etc.) this
* function returns either a configured OU or the default
* for the given RDN.
*
* Example:
* \code
* # Determine LDAP base where systems are stored
* $base = get_ou('systemRDN') . $config->current['BASE'];
* $ldap->cd($base);
* \endcode
*
* \param $name the rdn of the ou you are trying to find
*
* \return the ou associated the the RDN or nothing
*
*/
function get_ou ($name)
{
global $config;
$map = [
'fusiondirectoryRDN' => 'ou=fusiondirectory,',
'lockRDN' => 'ou=locks,',
'recoveryTokenRDN' => 'ou=recovery,',
'reminderTokenRDN' => 'ou=reminder,',
'roleRDN' => 'ou=roles,',
'ogroupRDN' => 'ou=groups,',
'applicationRDN' => 'ou=apps,',
'systemRDN' => 'ou=systems,',
'serverRDN' => 'ou=servers,ou=systems,',
'terminalRDN' => 'ou=terminals,ou=systems,',
'workstationRDN' => 'ou=workstations,ou=systems,',
'printerRDN' => 'ou=printers,ou=systems,',
'phoneRDN' => 'ou=phones,ou=systems,',
'componentRDN' => 'ou=netdevices,ou=systems,',
'mobilePhoneRDN' => 'ou=mobile,ou=systems,',
'inventoryRDN' => 'ou=inventory,',
'ipmiRDN' => 'ou=ipmi,',
'faxBlocklistRDN' => 'ou=gofax,ou=systems,',
'aclRoleRDN' => 'ou=aclroles,',
'phoneMacroRDN' => 'ou=macros,ou=asterisk,ou=configs,ou=systems,',
'phoneConferenceRDN' => 'ou=conferences,ou=asterisk,ou=configs,ou=systems,',
'faiBaseRDN' => 'ou=fai,ou=configs,ou=systems,',
911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980
'faiScriptRDN' => 'ou=scripts,',
'faiHookRDN' => 'ou=hooks,',
'faiTemplateRDN' => 'ou=templates,',
'faiVariableRDN' => 'ou=variables,',
'faiProfileRDN' => 'ou=profiles,',
'faiPackageRDN' => 'ou=packages,',
'faiPartitionRDN' => 'ou=disk,',
'debconfRDN' => 'ou=debconf,',
'supannStructuresRDN' => 'ou=structures,',
'sudoRDN' => 'ou=sudoers,',
'netgroupRDN' => 'ou=netgroup,',
'deviceRDN' => 'ou=devices,',
'aliasRDN' => 'ou=alias,',
'dsaRDN' => 'ou=dsa,',
'mimetypeRDN' => 'ou=mime,'
];
/* Preset ou... */
if ($config->get_cfg_value($name, '_not_set_') != '_not_set_') {
$ou = $config->get_cfg_value($name);
} elseif (isset($map[$name])) {
$ou = $map[$name];
return $ou;
} else {
return NULL;
}
if ($ou != '') {
if (!preg_match('/^[^=]+=[^=]+/', $ou)) {
$ou = "ou=$ou";
} else {
$ou = "$ou";
}
if (preg_match('/'.preg_quote($config->current['BASE'], '/').'$/', $ou)) {
return $ou;
} else {
if (preg_match('/,$/', $ou)) {
return $ou;
} else {
return "$ou,";
}
}
} else {
return '';
}
}
/*!
* \brief Get the OU for users
*
* Function for getting the userRDN
*
* \return the ou of the userRDN
*/
function get_people_ou ()
{
return get_ou('userRDN');
}
/*! \brief Return a base from a given user DN
*
981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050
* \code
* get_base_from_people('cn=Max Muster,dc=local')
* # Result is 'dc=local'
* \endcode
*
* \param string $dn
*
* \return the base from the dn
*/
function get_base_from_people ($dn)
{
global $config;
$pattern = "/^[^,]+,".preg_quote(get_people_ou(), '/')."/i";
$base = preg_replace($pattern, '', $dn);
/* Set to base, if we're not on a correct subtree */
if (!isset($config->idepartments[$base])) {
$base = $config->current['BASE'];
}
return $base;
}
/*!
* \brief Check if strict naming rules are configured
*
* Return TRUE or FALSE depending on weither strictNamingRules
* are configured or not.
*
* \return Returns TRUE if strictNamingRules is set to TRUE or if the
* config object is not available, otherwise FALSE.
*/
function strict_uid_mode ()
{
global $config;
if (isset($config)) {
return ($config->get_cfg_value('strictNamingRules') == 'TRUE');
}
return TRUE;
}
/*!
* \brief Generate a lock message
*
* This message shows a warning to the user, that a certain object is locked
* and presents some choices how the user can proceed. By default this
* is 'Cancel' or 'Edit anyway', but depending on the function call
* its possible to allow readonly access, too.
*
* Example usage:
* \code
* if ($locks = get_locks($this->dn)) {
* return gen_locked_message($locks, $this->dn, TRUE);
* }
* \endcode
*
* \param string $locks the locks as returned by get_locks
*
* \param string $dn the locked DN
*
* \param boolean $allow_readonly TRUE if readonly access should be permitted,
* FALSE if not (default).
*
*
*/
function gen_locked_message ($locks, $dn, $allow_readonly = FALSE)
{
1051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120
session::set('dn', $dn);
$remove = FALSE;
/* Save variables from LOCK_VARS_TO_USE in session - for further editing */
if ( session::is_set('LOCK_VARS_TO_USE') && count(session::get('LOCK_VARS_TO_USE'))) {
$LOCK_VARS_USED_GET = [];
$LOCK_VARS_USED_POST = [];
$LOCK_VARS_USED_REQUEST = [];
$LOCK_VARS_TO_USE = session::get('LOCK_VARS_TO_USE');
foreach ($LOCK_VARS_TO_USE as $name) {
if (empty($name)) {
continue;
}
foreach ($_POST as $Pname => $Pvalue) {
if (preg_match($name, $Pname)) {
$LOCK_VARS_USED_POST[$Pname] = $_POST[$Pname];
}
}
foreach ($_GET as $Pname => $Pvalue) {
if (preg_match($name, $Pname)) {
$LOCK_VARS_USED_GET[$Pname] = $_GET[$Pname];
}
}
foreach ($_REQUEST as $Pname => $Pvalue) {
if (preg_match($name, $Pname)) {
$LOCK_VARS_USED_REQUEST[$Pname] = $_REQUEST[$Pname];
}
}
}
session::set('LOCK_VARS_TO_USE', []);
session::set('LOCK_VARS_USED_GET', $LOCK_VARS_USED_GET);
session::set('LOCK_VARS_USED_POST', $LOCK_VARS_USED_POST);
session::set('LOCK_VARS_USED_REQUEST', $LOCK_VARS_USED_REQUEST);
}
/* Prepare and show template */
$smarty = get_smarty();
$smarty->assign('allow_readonly', $allow_readonly);
if (is_array($dn)) {
$msg = '<pre>';
foreach ($dn as $sub_dn) {
$msg .= "\n".$sub_dn.', ';
}
$msg = preg_replace("/, $/", "</pre>", $msg);
} else {
$msg = $dn;
}
$smarty->assign('dn', $msg);
if ($remove) {
$smarty->assign('action', _('Continue anyway'));
} else {
$smarty->assign('action', _('Edit anyway'));
}
$smarty->assign('message', sprintf(_("You're going to edit the LDAP entry/entries %s"), "<b>".$msg."</b>", ""));
$smarty->assign('locks', $locks);
return $smarty->fetch(get_template_path('islocked.tpl'));
}
/*!
* \brief Return a string/HTML representation of an array
*
1121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190
* This returns a string representation of a given value.
* It can be used to dump arrays, where every value is printed
* on its own line. The output is targetted at HTML output, it uses
* '<br>' for line breaks. If the value is already a string its
* returned unchanged.
*
* \param mixed $value Whatever needs to be printed.
*
* \return string $value in html form.
*/
function to_string ($value)
{
/* If this is an array, generate a text blob */
if (is_array($value)) {
$ret = '';
foreach ($value as $line) {
$ret .= $line."<br>\n";
}
return $ret;
} else {
return $value;
}
}
/*! \brief Function to rewrite some problematic characters
*
* This function takes a string and replaces all possibly characters in it
* with less problematic characters, as defined in $REWRITE.
*
* \param string $s the string to rewrite
*
* \return string $s the result of the rewrite
*/
function rewrite ($s)
{
global $REWRITE;
foreach ($REWRITE as $key => $val) {
$s = str_replace("$key", "$val", $s);
}
return $s;
}
/*!
* \brief Return the base of a given DN
*
* \param string $dn a DN
* \param string $ou an ou to remove from the base
*
* \return base of the given DN
*/
function dn2base ($dn, $ou = NULL)
{
if ($ou === NULL) {
if (get_people_ou() != '') {
$dn = preg_replace('/,'.get_people_ou().'/i', ',', $dn);
}
if (get_ou('groupRDN') != '') {
$dn = preg_replace('/,'.get_ou('groupRDN').'/i', ',', $dn);
}
} else {
$dn = preg_replace("/,$ou/i", ',', $dn);
}
return preg_replace ('/^[^,]+,/i', '', $dn);
}
/*!