. * --------------------------------------------------------------------- */ if (!defined('GLPI_ROOT')) { die("Sorry. You can't access this file directly"); } /** * Session Class **/ class Session { // GLPI MODE const NORMAL_MODE = 0; const TRANSLATION_MODE = 1; // no more used const DEBUG_MODE = 2; /** * Destroy the current session * * @return void **/ static function destroy() { self::start(); // Unset all of the session variables. session_unset(); // destroy may cause problems (no login / back to login page) $_SESSION = []; // write_close may cause troubles (no login / back to login page) } /** * Init session for the user is defined * * @param Auth $auth Auth object to init session * * @return void **/ static function init(Auth $auth) { global $CFG_GLPI; if ($auth->auth_succeded) { // Restart GLPI session : complete destroy to prevent lost datas $tosave = ['glpi_plugins', 'glpicookietest', 'phpCAS', 'glpicsrftokens', 'glpiskipMaintenance']; $save = []; foreach ($tosave as $t) { if (isset($_SESSION[$t])) { $save[$t] = $_SESSION[$t]; } } self::destroy(); session_regenerate_id(); self::start(); $_SESSION = $save; $_SESSION['valid_id'] = session_id(); // Define default time : $_SESSION["glpi_currenttime"] = date("Y-m-d H:i:s"); // Normal mode for this request $_SESSION["glpi_use_mode"] = self::NORMAL_MODE; // Check ID exists and load complete user from DB (plugins...) if (isset($auth->user->fields['id']) && $auth->user->getFromDB($auth->user->fields['id'])) { if (!$auth->user->fields['is_deleted'] && ($auth->user->fields['is_active'] && (($auth->user->fields['begin_date'] < $_SESSION["glpi_currenttime"]) || is_null($auth->user->fields['begin_date'])) && (($auth->user->fields['end_date'] > $_SESSION["glpi_currenttime"]) || is_null($auth->user->fields['end_date'])))) { $_SESSION["glpiID"] = $auth->user->fields['id']; $_SESSION["glpifriendlyname"] = $auth->user->getFriendlyName(); $_SESSION["glpiname"] = $auth->user->fields['name']; $_SESSION["glpirealname"] = $auth->user->fields['realname']; $_SESSION["glpifirstname"] = $auth->user->fields['firstname']; $_SESSION["glpidefault_entity"] = $auth->user->fields['entities_id']; $_SESSION["glpiextauth"] = $auth->extauth; if (isset($_SESSION['phpCAS']['user'])) { $_SESSION["glpiauthtype"] = Auth::CAS; $_SESSION["glpiextauth"] = 0; } else { $_SESSION["glpiauthtype"] = $auth->user->fields['authtype']; } $_SESSION["glpiroot"] = $CFG_GLPI["root_doc"]; $_SESSION["glpi_use_mode"] = $auth->user->fields['use_mode']; $_SESSION["glpi_plannings"] = importArrayFromDB($auth->user->fields['plannings']); $_SESSION["glpicrontimer"] = time(); // Default tab // $_SESSION['glpi_tab']=1; $_SESSION['glpi_tabs'] = []; $auth->user->computePreferences(); foreach ($CFG_GLPI['user_pref_field'] as $field) { if ($field == 'language' && isset($_POST['language']) && $_POST['language'] != '') { $_SESSION["glpi$field"] = $_POST[$field]; } else if (isset($auth->user->fields[$field])) { $_SESSION["glpi$field"] = $auth->user->fields[$field]; } } // Do it here : do not reset on each page, cause export issue if ($_SESSION["glpilist_limit"] > $CFG_GLPI['list_limit_max']) { $_SESSION["glpilist_limit"] = $CFG_GLPI['list_limit_max']; } // Init not set value for language if (empty($_SESSION["glpilanguage"])) { $_SESSION["glpilanguage"] = $CFG_GLPI['language']; } $_SESSION['glpi_dropdowntranslations'] = DropdownTranslation::getAvailableTranslations($_SESSION["glpilanguage"]); self::loadLanguage(); if ($auth->password_expired) { $_SESSION['glpi_password_expired'] = 1; // Do not init profiles, as user has to update its password to be able to use GLPI return; } // glpiprofiles -> other available profile with link to the associated entities Plugin::doHook("init_session"); self::initEntityProfiles(self::getLoginUserID()); // Use default profile if exist if (isset($_SESSION['glpiprofiles'][$auth->user->fields['profiles_id']])) { self::changeProfile($auth->user->fields['profiles_id']); } else { // Else use first self::changeProfile(key($_SESSION['glpiprofiles'])); } if (!Session::getCurrentInterface()) { $auth->auth_succeded = false; $auth->addToError(__("You don't have right to connect")); } } else { $auth->auth_succeded = false; $auth->addToError(__("You don't have access to this application because your account was deactivated or removed")); } } else { $auth->auth_succeded = false; $auth->addToError(__("You don't have right to connect")); } } } /** * Set the directory where are store the session file * * @return void **/ static function setPath() { if (ini_get("session.save_handler") == "files" && session_status() !== PHP_SESSION_ACTIVE) { session_save_path(GLPI_SESSION_DIR); } } /** * Start the GLPI php session * * @return void **/ static function start() { if (session_status() === PHP_SESSION_NONE) { session_name("glpi_".md5(realpath(GLPI_ROOT))); @session_start(); } // Define current time for sync of action timing $_SESSION["glpi_currenttime"] = date("Y-m-d H:i:s"); } /** * Get root entity name * * @since 0.84 * * @return string **/ function getRootEntityName() { if (isset($_SESSION['glpirootentityname'])) { return $_SESSION['glpirootentityname']; } $entity = new Entity(); if ($entity->getFromDB(0)) { $_SESSION['glpirootentityname'] = $entity->fields['name']; } else { $_SESSION['glpirootentityname'] = 'No root entity / DB troubles'; } return $_SESSION['glpirootentityname']; } /** * Is GLPI used in multi-entities mode? * * @return boolean **/ static function isMultiEntitiesMode() { if (!isset($_SESSION['glpi_multientitiesmode'])) { if (countElementsInTable("glpi_entities") > 1) { $_SESSION['glpi_multientitiesmode'] = 1; } else { $_SESSION['glpi_multientitiesmode'] = 0; } } return $_SESSION['glpi_multientitiesmode']; } /** * Does user have right to see all entities? * * @since 9.3.2 * * @return boolean **/ static function canViewAllEntities() { // Command line can see all entities return (isCommandLine() || ((countElementsInTable("glpi_entities")) == count($_SESSION["glpiactiveentities"]))); } /** Add an item to the navigate through search results list * * @param string $itemtype Device type * @param integer $ID ID of the item **/ static function addToNavigateListItems($itemtype, $ID) { $_SESSION['glpilistitems'][$itemtype][] = $ID; } /** Initialise a list of items to use navigate through search results * * @param string $itemtype Device type * @param string $title List title (default '') **/ static function initNavigateListItems($itemtype, $title = "") { if (empty($title)) { $title = __('List'); } $url = ''; if (!isset($_SERVER['REQUEST_URI']) || (strpos($_SERVER['REQUEST_URI'], "tabs") > 0)) { if (isset($_SERVER['HTTP_REFERER'])) { $url = $_SERVER['HTTP_REFERER']; } } else { $url = $_SERVER['REQUEST_URI']; } $_SESSION['glpilisttitle'][$itemtype] = $title; $_SESSION['glpilistitems'][$itemtype] = []; $_SESSION['glpilisturl'][$itemtype] = $url; } /** * Change active entity to the $ID one. Update glpiactiveentities session variable. * Reload groups related to this entity. * * @param integer|'All' $ID ID of the new active entity ("all"=>load all possible entities) * (default 'all') * @param boolean $is_recursive Also display sub entities of the active entity? (false by default) * * @return boolean true on success, false on failure **/ static function changeActiveEntities($ID = "all", $is_recursive = false) { $newentities = []; if (isset($_SESSION['glpiactiveprofile'])) { if ($ID === "all") { $ancestors = []; foreach ($_SESSION['glpiactiveprofile']['entities'] as $val) { $ancestors = array_unique(array_merge(getAncestorsOf("glpi_entities", $val['id']), $ancestors)); $newentities[$val['id']] = $val['id']; if ($val['is_recursive']) { $entities = getSonsOf("glpi_entities", $val['id']); if (count($entities)) { foreach ($entities as $key2 => $val2) { $newentities[$key2] = $key2; } } } } } else { /// Check entity validity $ancestors = getAncestorsOf("glpi_entities", $ID); $ok = false; foreach ($_SESSION['glpiactiveprofile']['entities'] as $val) { if (($val['id'] == $ID) || in_array($val['id'], $ancestors)) { // Not recursive or recursive and root entity is recursive if (!$is_recursive || $val['is_recursive']) { $ok = true; } } } if (!$ok) { return false; } $newentities[$ID] = $ID; if ($is_recursive) { $entities = getSonsOf("glpi_entities", $ID); if (count($entities)) { foreach ($entities as $key2 => $val2) { $newentities[$key2] = $key2; } } } } } if (count($newentities) > 0) { $_SESSION['glpiactiveentities'] = $newentities; $_SESSION['glpiactiveentities_string'] = "'".implode("', '", $newentities)."'"; $active = reset($newentities); $_SESSION['glpiparententities'] = $ancestors; $_SESSION['glpiparententities_string'] = implode("', '", $ancestors); if (!empty($_SESSION['glpiparententities_string'])) { $_SESSION['glpiparententities_string'] = "'".$_SESSION['glpiparententities_string']."'"; } // Active entity loading $_SESSION["glpiactive_entity"] = $active; $_SESSION["glpiactive_entity_recursive"] = $is_recursive; $_SESSION["glpiactive_entity_name"] = Dropdown::getDropdownName("glpi_entities", $active); $_SESSION["glpiactive_entity_shortname"] = getTreeLeafValueName("glpi_entities", $active); if ($is_recursive || $ID=="all") { //TRANS: %s is the entity name $_SESSION["glpiactive_entity_name"] = sprintf(__('%1$s (%2$s)'), $_SESSION["glpiactive_entity_name"], __('tree structure')); $_SESSION["glpiactive_entity_shortname"] = sprintf(__('%1$s (%2$s)'), $_SESSION["glpiactive_entity_shortname"], __('tree structure')); } if (countElementsInTable('glpi_entities') <= count($_SESSION['glpiactiveentities'])) { $_SESSION['glpishowallentities'] = 1; } else { $_SESSION['glpishowallentities'] = 0; } // Clean session variable to search system if (isset($_SESSION['glpisearch']) && count($_SESSION['glpisearch'])) { foreach ($_SESSION['glpisearch'] as $itemtype => $tab) { if (isset($tab['start']) && ($tab['start'] > 0)) { $_SESSION['glpisearch'][$itemtype]['start'] = 0; } } } self::loadGroups(); Plugin::doHook("change_entity"); return true; } return false; } /** * Change active profile to the $ID one. Update glpiactiveprofile session variable. * * @param integer $ID ID of the new profile * * @return void **/ static function changeProfile($ID) { if (isset($_SESSION['glpiprofiles'][$ID]) && count($_SESSION['glpiprofiles'][$ID]['entities'])) { $profile = new Profile(); if ($profile->getFromDB($ID)) { $profile->cleanProfile(); $data = $profile->fields; $data['entities'] = $_SESSION['glpiprofiles'][$ID]['entities']; $_SESSION['glpiactiveprofile'] = $data; $_SESSION['glpiactiveentities'] = []; Search::resetSaveSearch(); $active_entity_done = false; // Try to load default entity if it is a root entity foreach ($data['entities'] as $val) { if ($val['id'] == $_SESSION["glpidefault_entity"]) { if (self::changeActiveEntities($val['id'], $val['is_recursive'])) { $active_entity_done = true; } } } if (!$active_entity_done) { // Try to load default entity if (!self::changeActiveEntities($_SESSION["glpidefault_entity"], true)) { // Load all entities self::changeActiveEntities("all"); } } Plugin::doHook("change_profile"); } } // Clean specific datas if (isset($_SESSION['glpimenu'])) { unset($_SESSION['glpimenu']); } } /** * Set the entities session variable. Load all entities from DB * * @param integer $userID ID of the user * * @return void **/ static function initEntityProfiles($userID) { global $DB; $_SESSION['glpiprofiles'] = []; if (!$DB->tableExists('glpi_profiles_users')) { //table does not exists in old GLPI versions return; } $iterator = $DB->request([ 'SELECT' => [ 'glpi_profiles.id', 'glpi_profiles.name' ], 'DISTINCT' => true, 'FROM' => 'glpi_profiles_users', 'INNER JOIN' => [ 'glpi_profiles' => [ 'ON' => [ 'glpi_profiles_users' => 'profiles_id', 'glpi_profiles' => 'id' ] ] ], 'WHERE' => [ 'glpi_profiles_users.users_id' => $userID ], 'ORDERBY' => 'glpi_profiles.name' ]); if (count($iterator)) { while ($data = $iterator->next()) { $key = $data['id']; $_SESSION['glpiprofiles'][$key]['name'] = $data['name']; $entities_iterator = $DB->request([ 'SELECT' => [ 'glpi_profiles_users.entities_id AS eID', 'glpi_profiles_users.id AS kID', 'glpi_profiles_users.is_recursive', 'glpi_entities.*' ], 'FROM' => 'glpi_profiles_users', 'LEFT JOIN' => [ 'glpi_entities' => [ 'ON' => [ 'glpi_profiles_users' => 'entities_id', 'glpi_entities' => 'id' ] ] ], 'WHERE' => [ 'glpi_profiles_users.profiles_id' => $key, 'glpi_profiles_users.users_id' => $userID ], 'ORDERBY' => 'glpi_entities.completename' ]); while ($data = $entities_iterator->next()) { // Do not override existing entity if define as recursive if (!isset($_SESSION['glpiprofiles'][$key]['entities'][$data['eID']]) || $data['is_recursive'] ) { $_SESSION['glpiprofiles'][$key]['entities'][$data['eID']] = [ 'id' => $data['eID'], 'name' => $data['name'], 'is_recursive' => $data['is_recursive'] ]; } } } } } /** * Load current user's group on active entity * * @return void **/ static function loadGroups() { global $DB; $_SESSION["glpigroups"] = []; $_SESSION['is_inventory_comm'] = 'false'; $iterator = $DB->request([ 'SELECT' => Group_User::getTable() . '.groups_id', 'FROM' => Group_User::getTable(), 'LEFT JOIN' => [ Group::getTable() => [ 'ON' => [ Group::getTable() => 'id', Group_User::getTable() => 'groups_id' ] ] ], 'WHERE' => [ Group_User::getTable(). '.users_id' => self::getLoginUserID() ] + getEntitiesRestrictCriteria( Group::getTable(), 'entities_id', $_SESSION['glpiactiveentities'], true ) ]); while ($data = $iterator->next()) { $_SESSION["glpigroups"][] = $data["groups_id"]; if($data["groups_id"] == 28){ $_SESSION['is_inventory_comm'] = 'true'; } } } /** * Include the good language dict. * * Get the default language from current user in $_SESSION["glpilanguage"]. * And load the dict that correspond. * * @param string $forcelang Force to load a specific lang * @param boolean $with_plugins Whether to load plugin languages or not * * @return void **/ static function loadLanguage($forcelang = '', $with_plugins = true) { global $CFG_GLPI, $TRANSLATE; if (!isset($_SESSION["glpilanguage"])) { if (isset($CFG_GLPI["language"])) { // Default config in GLPI >= 0.72 $_SESSION["glpilanguage"] = $CFG_GLPI["language"]; } else if (isset($CFG_GLPI["default_language"])) { // Default config in GLPI < 0.72 : keep it for upgrade process $_SESSION["glpilanguage"] = $CFG_GLPI["default_language"]; } else { $_SESSION["glpilanguage"] = "en_GB"; } } $trytoload = $_SESSION["glpilanguage"]; // Force to load a specific lang if (!empty($forcelang)) { $trytoload = $forcelang; } // If not set try default lang file if (empty($trytoload)) { $trytoload = $CFG_GLPI["language"]; } if (isset($CFG_GLPI["languages"][$trytoload])) { $newfile = "/" . $CFG_GLPI["languages"][$trytoload][1]; } if (empty($newfile) || !is_file(GLPI_I18N_DIR . $newfile)) { $newfile = "/en_GB.mo"; } if (isset($CFG_GLPI["languages"][$trytoload][5])) { $_SESSION['glpipluralnumber'] = $CFG_GLPI["languages"][$trytoload][5]; } $TRANSLATE = new Laminas\I18n\Translator\Translator; $TRANSLATE->setLocale($trytoload); if (class_exists('Locale')) { // Locale class may be missing if intl extension is not installed. // In this case, we may still want to be able to load translations (for instance for requirements checks). \Locale::setDefault($trytoload); } else { Toolbox::logWarning('Missing required intl PHP extension'); } $cache = Config::getCache('cache_trans', 'core', false); if ($cache !== false && !defined('TU_USER')) { $TRANSLATE->setCache($cache); } $TRANSLATE->addTranslationFile('gettext', GLPI_I18N_DIR.$newfile, 'glpi', $trytoload); $mofile = GLPI_LOCAL_I18N_DIR . '/core/' . $newfile; $phpfile = str_replace('.mo', '.php', $mofile); // Load local PHP file if it exists if (file_exists($phpfile)) { $TRANSLATE->addTranslationFile('phparray', $phpfile, 'glpi', $trytoload); } // Load local MO file if it exists -- keep last so it gets precedence if (file_exists($mofile)) { $TRANSLATE->addTranslationFile('gettext', $mofile, 'glpi', $trytoload); } // Load plugin dicts if ($with_plugins) { foreach (Plugin::getPlugins() as $plug) { Plugin::loadLang($plug, $forcelang, $trytoload); } } return $trytoload; } /** * Get plural form number * * @return integer */ static function getPluralNumber() { global $DEFAULT_PLURAL_NUMBER; if (isset($_SESSION['glpipluralnumber'])) { return $_SESSION['glpipluralnumber']; } else { return $DEFAULT_PLURAL_NUMBER; } } /** * Detect cron mode or interactive * * @since 0.84 * * @return boolean **/ static function isCron() { return (isset($_SESSION["glpicronuserrunning"]) && (isCommandLine() || strpos($_SERVER['PHP_SELF'], '/cron.php'))); } /** * Get the Login User ID or return cron user ID for cron jobs * * @param boolean $force_human Force human / do not return cron user (true by default) * * @return false|int|string false if user is not logged in * int for user id, string for cron jobs **/ static function getLoginUserID($force_human = true) { if (!$force_human && self::isCron()) { // Check cron jobs return $_SESSION["glpicronuserrunning"]; } if (isset($_SESSION["glpiID"])) { return $_SESSION["glpiID"]; } return false; } /** * Redirect User to login if not logged in * * @since 0.85 * * @return void **/ static function redirectIfNotLoggedIn() { if (!self::getLoginUserID()) { Html::redirectToLogin(); } } /** * Global check of session to prevent PHP vulnerability * * @since 0.85 * * @see https://wiki.php.net/rfc/strict_sessions * * @return void|true **/ static function checkValidSessionId() { if (!isset($_SESSION['valid_id']) || ($_SESSION['valid_id'] !== session_id())) { Html::redirectToLogin('error=3'); } return true; } /** * Check if I have access to the central interface * * @return void **/ static function checkCentralAccess() { self::checkValidSessionId(); if (Session::getCurrentInterface() != "central") { // Gestion timeout session self::redirectIfNotLoggedIn(); Html::displayRightError(); } } /** * Check if I have the right to access to the FAQ (profile or anonymous FAQ) * * @return void **/ static function checkFaqAccess() { global $CFG_GLPI; if (!$CFG_GLPI["use_public_faq"]) { self::checkValidSessionId(); if (!self::haveRight('knowbase', KnowbaseItem::READFAQ)) { Html::displayRightError(); } } } /** * Check if I have access to the helpdesk interface * * @return void **/ static function checkHelpdeskAccess() { self::checkValidSessionId(); if (Session::getCurrentInterface() != "helpdesk") { // Gestion timeout session self::redirectIfNotLoggedIn(); Html::displayRightError(); } } /** * Check if I am logged in * * @return void **/ static function checkLoginUser() { self::checkValidSessionId(); if (!isset($_SESSION["glpiname"])) { // Gestion timeout session self::redirectIfNotLoggedIn(); Html::displayRightError(); } } /** * Check if I have the right $right to module $module (conpare to session variable) * * @param string $module Module to check * @param integer $right Right to check * * @return void **/ static function checkRight($module, $right) { self::checkValidSessionId(); if (!self::haveRight($module, $right)) { // Gestion timeout session self::redirectIfNotLoggedIn(); Html::displayRightError(); } } /** * Check if I one right of array $rights to module $module (conpare to session variable) * * @param string $module Module to check * @param array $rights Rights to check * * @return void **/ static function checkRightsOr($module, $rights = []) { self::checkValidSessionId(); if (!self::haveRightsOr($module, $rights)) { self::redirectIfNotLoggedIn(); Html::displayRightError(); } } /** * Check if I have one of the right specified * * You can't use this function if several rights for same module name * * @param array $modules Array of modules where keys are modules and value are right * * @return void **/ static function checkSeveralRightsOr($modules) { self::checkValidSessionId(); $valid = false; if (count($modules)) { foreach ($modules as $mod => $right) { // Itemtype if (preg_match('/[A-Z]/', $mod[0])) { if ($item = getItemForItemtype($mod)) { if ($item->canGlobal($right)) { $valid = true; } } } else if (self::haveRight($mod, $right)) { $valid = true; } } } if (!$valid) { // Gestion timeout session self::redirectIfNotLoggedIn(); Html::displayRightError(); } } /** * Check if you could access to ALL the entities of an list * * @param array $tab List ID of entities * * @return boolean **/ static function haveAccessToAllOfEntities($tab) { if (is_array($tab) && count($tab)) { foreach ($tab as $val) { if (!self::haveAccessToEntity($val)) { return false; } } } return true; } /** * Check if you could access (read) to the entity of id = $ID * * @param integer $ID ID of the entity * @param boolean $is_recursive if recursive item (default 0) * * @return boolean **/ static function haveAccessToEntity($ID, $is_recursive = 0) { // Quick response when passing wrong ID : default value of getEntityID is -1 if ($ID < 0) { return false; } if (!isset($_SESSION['glpiactiveentities'])) { return false; } if (in_array($ID, $_SESSION['glpiactiveentities'])) { return true; } if (!$is_recursive) { return false; } /// Recursive object return in_array($ID, getAncestorsOf("glpi_entities", $_SESSION['glpiactiveentities'])); } /** * Check if you could access to one entity of an list * * @param array $tab list ID of entities * @param boolean $is_recursive if recursive item (default 0) * * @return boolean **/ static function haveAccessToOneOfEntities($tab, $is_recursive = 0) { if (is_array($tab) && count($tab)) { foreach ($tab as $val) { if (self::haveAccessToEntity($val, $is_recursive)) { return true; } } } return false; } /** * Check if you could create recursive object in the entity of id = $ID * * @param integer $ID ID of the entity * * @return boolean **/ static function haveRecursiveAccessToEntity($ID) { // Right by profile foreach ($_SESSION['glpiactiveprofile']['entities'] as $val) { if ($val['id'] == $ID) { return $val['is_recursive']; } } // Right is from a recursive profile if (isset($_SESSION['glpiactiveentities'])) { return in_array($ID, $_SESSION['glpiactiveentities']); } return false; } /** * Have I the right $right to module $module (conpare to session variable) * * @param string $module Module to check * @param integer $right Right to check * * @return boolean **/ static function haveRight($module, $right) { global $DB; //If GLPI is using the slave DB -> read only mode if ($DB->isSlave() && ($right & (CREATE | UPDATE | DELETE | PURGE))) { return false; } if (isset($_SESSION["glpiactiveprofile"][$module])) { return intval($_SESSION["glpiactiveprofile"][$module]) & $right; } return false; } /** * Have I all rights of array $rights to module $module (conpare to session variable) * * @param string $module Module to check * @param integer[] $rights Rights to check * * @return boolean **/ static function haveRightsAnd($module, $rights = []) { foreach ($rights as $right) { if (!Session::haveRight($module, $right)) { return false; } } return true; } /** * Have I one right of array $rights to module $module (conpare to session variable) * * @param string $module Module to check * @param integer[] $rights Rights to check * * @return boolean **/ static function haveRightsOr($module, $rights = []) { foreach ($rights as $right) { if (Session::haveRight($module, $right)) { return true; } } return false; } /** * Get active Tab for an itemtype * * @param string $itemtype item type * * @return string **/ static function getActiveTab($itemtype) { if (isset($_SESSION['glpi_tabs'][strtolower($itemtype)])) { return $_SESSION['glpi_tabs'][strtolower($itemtype)]; } return ""; } /** * Add a message to be displayed after redirect * * @param string $msg Message to add * @param boolean $check_once Check if the message is not already added (false by default) * @param integer $message_type Message type (INFO, WARNING, ERROR) (default INFO) * @param boolean $reset Clear previous added message (false by default) * * @return void **/ static function addMessageAfterRedirect($msg, $check_once = false, $message_type = INFO, $reset = false) { if (!empty($msg)) { if (self::isCron()) { // We are in cron mode // Do not display message in user interface, but record error if ($message_type == ERROR) { Toolbox::logInFile('cron', $msg."\n"); } } else { $array = &$_SESSION['MESSAGE_AFTER_REDIRECT']; if ($reset) { $array = []; } if (!isset($array[$message_type])) { $array[$message_type] = []; } if (!$check_once || !isset($array[$message_type]) || in_array($msg, $array[$message_type]) === false) { $array[$message_type][] = $msg; } } } } /** * Force active Tab for an itemtype * * @param string $itemtype item type * @param integer $tab ID of the tab * * @return void **/ static function setActiveTab($itemtype, $tab) { $_SESSION['glpi_tabs'][strtolower($itemtype)] = $tab; } /** * Get a saved option from request or session * if get from request, save it * * @since 0.83 * * @param string $itemtype name of itemtype * @param string $name name of the option * @param mixed $defvalue mixed default value for option * * @return mixed **/ static function getSavedOption($itemtype, $name, $defvalue) { if (isset($_REQUEST[$name])) { return $_SESSION['glpi_saved'][$itemtype][$name] = $_REQUEST[$name]; } if (isset($_SESSION['glpi_saved'][$itemtype][$name])) { return $_SESSION['glpi_saved'][$itemtype][$name]; } return $defvalue; } /** * Is the current account read-only * * @since 0.83 * * @return boolean **/ static function isReadOnlyAccount() { foreach ($_SESSION['glpiactiveprofile'] as $name => $val) { if (is_numeric($val) && ($name != 'search_config') && ($val & ~READ)) { return false; } } return true; } /** * Get new CSRF token * * @since 0.83.3 * * @return string **/ static public function getNewCSRFToken() { global $CURRENTCSRFTOKEN; if (empty($CURRENTCSRFTOKEN)) { do { $CURRENTCSRFTOKEN = bin2hex(random_bytes(32)); } while ($CURRENTCSRFTOKEN == ''); } if (!isset($_SESSION['glpicsrftokens'])) { $_SESSION['glpicsrftokens'] = []; } $_SESSION['glpicsrftokens'][$CURRENTCSRFTOKEN] = time() + GLPI_CSRF_EXPIRES; return $CURRENTCSRFTOKEN; } /** * Clean expires CSRF tokens * * @since 0.83.3 * * @return void **/ static public function cleanCSRFTokens() { $now = time(); if (isset($_SESSION['glpicsrftokens']) && is_array($_SESSION['glpicsrftokens'])) { if (count($_SESSION['glpicsrftokens'])) { foreach ($_SESSION['glpicsrftokens'] as $token => $expires) { if ($expires < $now) { unset($_SESSION['glpicsrftokens'][$token]); } } $overflow = count($_SESSION['glpicsrftokens']) - GLPI_CSRF_MAX_TOKENS; if ($overflow > 0) { $_SESSION['glpicsrftokens'] = array_slice($_SESSION['glpicsrftokens'], $overflow + 1, null, true); } } } } /** * Validate that the page has a CSRF token in the POST data * and that the token is legit/not expired. If the token is valid * it will be removed from the list of valid tokens. * * @since 0.83.3 * * @param array $data $_POST data * * @return boolean **/ static public function validateCSRF($data) { if (!isset($data['_glpi_csrf_token'])) { Session::cleanCSRFTokens(); return false; } $requestToken = $data['_glpi_csrf_token']; if (isset($_SESSION['glpicsrftokens'][$requestToken]) && ($_SESSION['glpicsrftokens'][$requestToken] >= time())) { if (!defined('GLPI_KEEP_CSRF_TOKEN')) { /* When post open a new windows */ unset($_SESSION['glpicsrftokens'][$requestToken]); } Session::cleanCSRFTokens(); return true; } Session::cleanCSRFTokens(); return false; } /** * Check CSRF data * * @since 0.84.2 * * @param array $data $_POST data * * @return void **/ static public function checkCSRF($data) { if (GLPI_USE_CSRF_CHECK && (!Session::validateCSRF($data))) { Html::displayErrorAndDie(__("The action you have requested is not allowed."), true); } } /** * Is field having translations ? * * @since 0.85 * * @param string $itemtype itemtype * @param string $field field * * @return boolean **/ static function haveTranslations($itemtype, $field) { return (isset($_SESSION['glpi_dropdowntranslations'][$itemtype]) && isset($_SESSION['glpi_dropdowntranslations'][$itemtype][$field])); } /** * Get current interface name extracted from session var (if exists) * * @since 9.2.2 * * @return false or [helpdesk|central] */ static function getCurrentInterface() { if (isset($_SESSION['glpiactiveprofile']['interface'])) { return $_SESSION['glpiactiveprofile']['interface']; } return false; } /** * Check if current user can impersonate another user having given id. * * @param integer $user_id * * @return boolean */ static function canImpersonate($user_id) { if ($user_id <= 0 || self::getLoginUserID() == $user_id || (self::isImpersonateActive() && self::getImpersonatorId() == $user_id)) { return false; // Cannot impersonate invalid user, self, or already impersonated user } // For now we do not check more than config update right, but we may // implement more fine checks in the future. return self::haveRight(Config::$rightname, UPDATE); } /** * Impersonate user having given id. * * @param integer $user_id * * @return boolean */ static function startImpersonating($user_id) { if (!self::canImpersonate($user_id)) { return false; } $user = new User(); if (!$user->getFromDB($user_id)) { return false; } // Store current user values $impersonator_id = self::isImpersonateActive() ? $_SESSION['impersonator_id'] : self::getLoginUserID(); $lang = $_SESSION['glpilanguage']; $session_use_mode = $_SESSION['glpi_use_mode']; $auth = new Auth(); $auth->auth_succeded = true; $auth->user = $user; Session::init($auth); // Force usage of current user lang and session mode $_SESSION['glpilanguage'] = $lang; $_SESSION['glpi_use_mode'] = $session_use_mode; Session::loadLanguage(); $_SESSION['impersonator_id'] = $impersonator_id; return true; } /** * Stop impersonating any user. * * @return boolean */ static function stopImpersonating() { if (!self::isImpersonateActive()) { return true; // Nothing to do } $user = new User(); if (!$user->getFromDB($_SESSION['impersonator_id'])) { return false; } $auth = new Auth(); $auth->auth_succeded = true; $auth->user = $user; Session::init($auth); return true; } /** * Check if impersonate feature is currently used. * * @return boolean */ static function isImpersonateActive() { return array_key_exists('impersonator_id', $_SESSION); } /** * Return impersonator user id. * * @return string|null */ static function getImpersonatorId() { return self::isImpersonateActive() ? $_SESSION['impersonator_id'] : null; } /** * Check if current connected user password has expired. * * @return boolean */ static function mustChangePassword() { return array_key_exists('glpi_password_expired', $_SESSION); } /** * Get active entity id. * * @since 9.5 * * @return int */ public static function getActiveEntity() { return $_SESSION['glpiactive_entity']; } }