functions.inc 51.80 KiB
<?php
/*
  This code is part of FusionDirectory (http://www.fusiondirectory.org/)
  Copyright (C) 2003-2010  Cajus Pollmeier
  Copyright (C) 2011-2016  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) */
/* 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",
    "Ó" => "O",
    "Ú" => "U",
    "ñ" => "ny",
    "Ñ" => "Ny" ];
7172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
/*! * \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 { logging::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. * * \param string $plugin the subject of the check * * \return boolean Return TRUE if successfull FALSE otherwise */ function plugin_available ($plugin)
141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210
{ global $class_mapping, $BASE_DIR; if (!isset($class_mapping[$plugin])) { return FALSE; } else { return is_readable($BASE_DIR.'/'.$class_mapping[$plugin]); } } /*! * \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 = '') { logging::debug($level, $line, $function, $file, $data, $info); } /*! * \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 */
211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280
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", $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'));
281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350
} /*! * \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 (array $ar1, array $ar2) { 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');
351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420
/* 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; } /*! * \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 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->get_errno() == 32) { /* No such object, means the locking branch is missing, create it */ $ldap->cd($config->current['BASE']); $ldap->create_missing_trees(get_ou('lockRDN').get_ou('fusiondirectoryRDN').$config->current['BASE']); $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);