functions.inc 64.99 KiB
<?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&amp;icon=dialog-information&amp;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); } /*!