. * --------------------------------------------------------------------- */ use Glpi\Dashboard\Grid; use Glpi\Cache\SimpleCache; use Glpi\Exception\PasswordTooWeakException; use Glpi\System\RequirementsManager; use Laminas\Cache\Storage\AvailableSpaceCapableInterface; use Laminas\Cache\Storage\FlushableInterface; use Laminas\Cache\Storage\TotalSpaceCapableInterface; use PHPMailer\PHPMailer\PHPMailer; if (!defined('GLPI_ROOT')) { die("Sorry. You can't access this file directly"); } /** * Config class **/ class Config extends CommonDBTM { const DELETE_ALL = -1; const KEEP_ALL = 0; // From CommonGLPI protected $displaylist = false; // From CommonDBTM public $auto_message_on_action = false; public $showdebug = true; static $rightname = 'config'; static $undisclosedFields = ['proxy_passwd', 'smtp_passwd', 'glpinetwork_registration_key']; static $saferUndisclosedFields = ['admin_email', 'admin_reply']; static function getTypeName($nb = 0) { return __('Setup'); } static function getMenuContent() { $menu = []; if (static::canView()) { $menu['title'] = _x('setup', 'General'); $menu['page'] = Config::getFormURL(false); $menu['icon'] = Config::getIcon(); $menu['options']['apiclient']['title'] = APIClient::getTypeName(Session::getPluralNumber()); $menu['options']['apiclient']['page'] = Config::getFormURL(false) . '?forcetab=Config$8'; $menu['options']['apiclient']['links']['search'] = Config::getFormURL(false) . '?forcetab=Config$8'; $menu['options']['apiclient']['links']['add'] = '/front/apiclient.form.php'; } if (count($menu)) { return $menu; } return false; } static function canCreate() { return false; } function canViewItem() { if (isset($this->fields['context']) && ($this->fields['context'] == 'core' || Plugin::isPluginActive($this->fields['context']))) { return true; } return false; } function defineTabs($options = []) { $ong = []; $this->addStandardTab(__CLASS__, $ong, $options); $this->addStandardTab('GLPINetwork', $ong, $options); $this->addStandardTab('Log', $ong, $options); return $ong; } function prepareInputForUpdate($input) { global $CFG_GLPI; // Unset _no_history to not save it as a configuration value unset($input['_no_history']); // Update only an item if (isset($input['context'])) { return $input; } // Process configuration for plugins if (!empty($input['config_context'])) { $config_context = $input['config_context']; unset($input['id']); unset($input['_glpi_csrf_token']); unset($input['update']); unset($input['config_context']); if ((!empty($input['config_class'])) && (class_exists($input['config_class'])) && (method_exists ($input['config_class'], 'configUpdate'))) { $config_method = $input['config_class'].'::configUpdate'; unset($input['config_class']); $input = call_user_func($config_method, $input); } $this->setConfigurationValues($config_context, $input); return false; } // Trim automatically endig slash for url_base config as, for all existing occurences, // this URL will be prepended to something that starts with a slash. if (isset($input["url_base"]) && !empty($input["url_base"])) { if (Toolbox::isValidWebUrl($input["url_base"])) { $input["url_base"] = rtrim($input["url_base"], '/'); } else { Session::addMessageAfterRedirect(__('Invalid base URL!'), false, ERROR); return false; } } if (isset($input["url_base_api"]) && !empty($input["url_base_api"])) { if (!Toolbox::isValidWebUrl($input["url_base_api"])) { Session::addMessageAfterRedirect(__('Invalid API base URL!'), false, ERROR); return false; } } if (isset($input['allow_search_view']) && !$input['allow_search_view']) { // Global search need "view" $input['allow_search_global'] = 0; } if (isset($input["smtp_passwd"])) { if (empty($input["smtp_passwd"])) { unset($input["smtp_passwd"]); } else { $input["smtp_passwd"] = Toolbox::sodiumEncrypt(stripslashes($input["smtp_passwd"])); } } if (isset($input["_blank_smtp_passwd"]) && $input["_blank_smtp_passwd"]) { $input['smtp_passwd'] = ''; } if (isset($input["proxy_passwd"])) { if (empty($input["proxy_passwd"])) { unset($input["proxy_passwd"]); } else { $input["proxy_passwd"] = Toolbox::sodiumEncrypt(stripslashes($input["proxy_passwd"])); } } if (isset($input["_blank_proxy_passwd"]) && $input["_blank_proxy_passwd"]) { $input['proxy_passwd'] = ''; } // Manage DB Slave process if (isset($input['_dbslave_status'])) { $already_active = DBConnection::isDBSlaveActive(); if ($input['_dbslave_status']) { DBConnection::changeCronTaskStatus(true); if (!$already_active) { // Activate Slave from the "system" tab DBConnection::createDBSlaveConfig(); } else if (isset($input["_dbreplicate_dbhost"])) { // Change parameter from the "replicate" tab DBConnection::saveDBSlaveConf($input["_dbreplicate_dbhost"], $input["_dbreplicate_dbuser"], $input["_dbreplicate_dbpassword"], $input["_dbreplicate_dbdefault"]); } } if (!$input['_dbslave_status'] && $already_active) { DBConnection::deleteDBSlaveConfig(); DBConnection::changeCronTaskStatus(false); } } // Matrix for Impact / Urgence / Priority if (isset($input['_matrix'])) { $tab = []; for ($urgency=1; $urgency<=5; $urgency++) { for ($impact=1; $impact<=5; $impact++) { $priority = $input["_matrix_${urgency}_${impact}"]; $tab[$urgency][$impact] = $priority; } } $input['priority_matrix'] = exportArrayToDB($tab); $input['urgency_mask'] = 0; $input['impact_mask'] = 0; for ($i=1; $i<=5; $i++) { if ($input["_urgency_${i}"]) { $input['urgency_mask'] += (1<<$i); } if ($input["_impact_${i}"]) { $input['impact_mask'] += (1<<$i); } } } if (isset($input['_update_devices_in_menu'])) { $input['devices_in_menu'] = exportArrayToDB( (isset($input['devices_in_menu']) ? $input['devices_in_menu'] : []) ); } // lock mechanism update if (isset( $input['lock_use_lock_item'])) { $input['lock_item_list'] = exportArrayToDB((isset($input['lock_item_list']) ? $input['lock_item_list'] : [])); } if (isset($input[Impact::CONF_ENABLED])) { $input[Impact::CONF_ENABLED] = exportArrayToDB($input[Impact::CONF_ENABLED]); } // encrypt registration key if (isset($input["glpinetwork_registration_key"]) && !empty($input["glpinetwork_registration_key"])) { $input["glpinetwork_registration_key"] = Toolbox::sodiumEncrypt(stripslashes($input["glpinetwork_registration_key"])); } // Beware : with new management system, we must update each value unset($input['id']); unset($input['_glpi_csrf_token']); unset($input['update']); // Add skipMaintenance if maintenance mode update if (isset($input['maintenance_mode']) && $input['maintenance_mode']) { $_SESSION['glpiskipMaintenance'] = 1; $url = $CFG_GLPI['root_doc']."/index.php?skipMaintenance=1"; Session::addMessageAfterRedirect(sprintf(__('Maintenance mode activated. Backdoor using: %s'), "$url"), false, WARNING); } $this->setConfigurationValues('core', $input); return false; } static public function unsetUndisclosedFields(&$fields) { if (isset($fields['context']) && isset($fields['name'])) { if ($fields['context'] == 'core' && in_array($fields['name'], self::$undisclosedFields)) { unset($fields['value']); } else { $fields = Plugin::doHookFunction('undiscloseConfigValue', $fields); } } } /** * Print the config form for display * * @return void **/ function showFormDisplay() { global $CFG_GLPI; if (!self::canView()) { return; } $rand = mt_rand(); $canedit = Session::haveRight(self::$rightname, UPDATE); if ($canedit) { echo "
"; } echo "
"; echo ""; echo ""; echo ""; echo ""; echo ""; echo ""; echo ""; echo ""; echo ""; echo ""; echo ""; echo ""; echo ""; echo ""; echo ""; echo ""; echo ""; echo ""; echo ""; echo ""; echo ""; echo ""; echo ""; echo ""; echo ""; echo ""; echo ""; echo ""; echo ""; echo ""; echo ""; echo ""; echo ""; echo ""; echo ""; echo ""; echo ""; echo ""; echo ""; echo ""; echo ""; echo ""; echo ""; echo ""; echo ""; echo ""; echo ""; echo ""; echo ""; echo ""; echo ""; echo ""; if ($canedit) { echo ""; echo ""; } echo "
" . __('General setup') . "
"; echo "
"; echo ""; echo "
"; Dropdown::showYesNo("use_public_faq", $CFG_GLPI["use_public_faq"], -1, ['rand' => $rand]); echo "
"; Dropdown::showNumber("list_limit_max", ['value' => $CFG_GLPI["list_limit_max"], 'min' => 5, 'max' => 200, 'step' => 5, 'rand' => $rand]); echo "
"; echo Html::input('cut', [ 'value' => $CFG_GLPI["cut"], 'id' => "cut$rand" ]); echo ""; Dropdown::showNumber('url_maxlength', ['value' => $CFG_GLPI["url_maxlength"], 'min' => 20, 'max' => 80, 'step' => 5, 'rand' => $rand]); echo "
"; Dropdown::showNumber("decimal_number", ['value' => $CFG_GLPI["decimal_number"], 'min' => 1, 'max' => 4, 'rand' => $rand]); echo "
"; Dropdown::showYesNo("translate_dropdowns", $CFG_GLPI["translate_dropdowns"], -1, ['rand' => $rand]); echo ""; Dropdown::showYesNo("translate_kb", $CFG_GLPI["translate_kb"], -1, ['rand' => $rand]); echo "
"; Dropdown::showYesNo("translate_reminders", $CFG_GLPI["translate_reminders"], -1, ['rand' => $rand]); echo ""; echo "
".__('Dynamic display'). "
"; Dropdown::showNumber('dropdown_max', ['value' => $CFG_GLPI["dropdown_max"], 'min' => 1, 'max' => 200, 'rand' => $rand]); echo ""; Dropdown::showYesNo("use_ajax_autocompletion", $CFG_GLPI["use_ajax_autocompletion"], -1, ['rand' => $rand]); echo "
"; Dropdown::showNumber('ajax_limit_count', ['value' => $CFG_GLPI["ajax_limit_count"], 'min' => 1, 'max' => 200, 'step' => 1, 'toadd' => [0 => __('Never')], 'rand' => $rand]); echo "
".__('Search engine')."
"; $values = [0 => __('No'), 1 => sprintf(__('%1$s (%2$s)'), __('Yes'), __('last criterion')), 2 => sprintf(__('%1$s (%2$s)'), __('Yes'), __('default criterion'))]; Dropdown::showFromArray('allow_search_view', $values, ['value' => $CFG_GLPI['allow_search_view'], 'rand' => $rand]); echo ""; if ($CFG_GLPI['allow_search_view']) { Dropdown::showYesNo('allow_search_global', $CFG_GLPI['allow_search_global'], -1, ['rand' => $rand]); } else { echo Dropdown::getYesNo(0); } echo "
"; $values = [0 => __('No'), 1 => sprintf(__('%1$s (%2$s)'), __('Yes'), __('last criterion'))]; Dropdown::showFromArray('allow_search_all', $values, ['value' => $CFG_GLPI['allow_search_all'], 'rand' => $rand]); echo "
".__('Item locks')."
"; Dropdown::showYesNo("lock_use_lock_item", $CFG_GLPI["lock_use_lock_item"], -1, ['rand' => $rand]); echo ""; if ($CFG_GLPI["lock_use_lock_item"]) { Profile::dropdown(['name' => 'lock_lockprofile_id', 'display_emptychoice' => true, 'value' => $CFG_GLPI['lock_lockprofile_id'], 'rand' => $rand]); } else { echo Dropdown::getDropdownName(Profile::getTable(), $CFG_GLPI['lock_lockprofile_id']); } echo "
"; Dropdown::showFromArray('lock_item_list', ObjectLock::getLockableObjects(), ['values' => $CFG_GLPI['lock_item_list'], 'width' => '100%', 'multiple' => true, 'readonly' => !$CFG_GLPI["lock_use_lock_item"], 'rand' => $rand]); echo "
".__('Auto Login'). "
"; Dropdown::showTimeStamp('login_remember_time', ['value' => $CFG_GLPI["login_remember_time"], 'emptylabel' => __('Disabled'), 'min' => 0, 'max' => MONTH_TIMESTAMP * 2, 'step' => DAY_TIMESTAMP, 'toadd' => [HOUR_TIMESTAMP, HOUR_TIMESTAMP * 2, HOUR_TIMESTAMP * 6, HOUR_TIMESTAMP * 12], 'rand' => $rand]); echo ""; Dropdown::showYesNo("login_remember_default", $CFG_GLPI["login_remember_default"], -1, ['rand' => $rand]); echo "
"; Dropdown::showYesNo("display_login_source", $CFG_GLPI["display_login_source"], -1, ['rand' => $rand]); echo "
"; echo ""; echo "
"; Html::closeForm(); } /** * Print the config form for restrictions * * @return void **/ function showFormInventory() { global $CFG_GLPI; if (!self::canView()) { return; } $rand = mt_rand(); $canedit = Config::canUpdate(); if ($canedit) { echo ""; } echo "
"; echo ""; echo ""; echo ""; echo ""; echo ""; echo ""; echo ""; echo ""; echo ""; echo ""; echo ""; echo ""; echo ""; echo ""; echo "\n"; echo "
" . __('Assets') . "
"; Dropdown::ShowYesNo('auto_create_infocoms', $CFG_GLPI["auto_create_infocoms"], -1, ['rand' => $rand]); echo ""; $this->dropdownGlobalManagement ("monitors_management_restrict", $CFG_GLPI["monitors_management_restrict"], $rand); echo "
"; SoftwareCategory::dropdown(['value' => $CFG_GLPI["softwarecategories_id_ondelete"], 'name' => "softwarecategories_id_ondelete", 'rand' => $rand]); echo ""; $this->dropdownGlobalManagement ("peripherals_management_restrict", $CFG_GLPI["peripherals_management_restrict"], $rand); echo "
"; Html::showDateField("date_tax", ['value' => $CFG_GLPI["date_tax"], 'maybeempty' => false, 'canedit' => true, 'min' => '', 'max' => '', 'showyear' => false, 'rand' => $rand]); echo ""; $this->dropdownGlobalManagement ("phones_management_restrict", $CFG_GLPI["phones_management_restrict"], $rand); echo "
"; $tab = [0 => __('Global'), 1 => __('By entity')]; Dropdown::showFromArray('use_autoname_by_entity', $tab, ['value' => $CFG_GLPI["use_autoname_by_entity"], 'rand' => $rand]); echo ""; $this->dropdownGlobalManagement("printers_management_restrict", $CFG_GLPI["printers_management_restrict"], $rand); echo "
"; $dd_params = [ 'name' => 'devices_in_menu', 'values' => $CFG_GLPI['devices_in_menu'], 'display' => true, 'rand' => $rand, 'multiple' => true, 'size' => 3 ]; $item_devices_types = []; foreach ($CFG_GLPI['itemdevices'] as $key => $itemtype) { if ($item = getItemForItemtype($itemtype)) { $item_devices_types[$itemtype] = $item->getTypeName(); } else { unset($CFG_GLPI['itemdevices'][$key]); } } Dropdown::showFromArray($dd_params['name'], $item_devices_types, $dd_params); echo ""; echo "
"; if (Session::haveRightsOr("transfer", [CREATE, UPDATE]) && Session::isMultiEntitiesMode()) { echo "
"; echo ""; echo ""; echo ""; echo "
" . __('Automatic transfer of computers') . "
"; Transfer::dropdown(['value' => $CFG_GLPI["transfers_id_auto"], 'name' => "transfers_id_auto", 'emptylabel' => __('No automatic transfer'), 'rand' => $rand]); echo "
"; } echo "
"; echo ""; echo ""; echo ""; echo ""; echo ""; echo ""; echo ""; echo ""; echo ""; $fields = ["contact", "user", "group", "location"]; echo ""; echo ""; $values = [ __('Do not copy'), __('Copy'), ]; foreach ($fields as $field) { echo ""; } echo ""; echo ""; echo ""; $values = [ __('Do not delete'), __('Clear'), ]; foreach ($fields as $field) { echo ""; } echo ""; if ($canedit) { echo ""; echo ""; } echo "
".__('Automatically update of the elements related to the computers'); echo "".__('Unit management')."
 " . __('Alternate username') . "" . User::getTypeName(1) . "" . Group::getTypeName(1) . "" . Location::getTypeName(1) . "" . __('Status') . "
" . __('When connecting or updating') . ""; $fieldname = "is_".$field."_autoupdate"; Dropdown::showFromArray($fieldname, $values, ['value' => $CFG_GLPI[$fieldname]]); echo ""; State::dropdownBehaviour("state_autoupdate_mode", __('Copy computer status'), $CFG_GLPI["state_autoupdate_mode"]); echo "
" . __('When disconnecting') . ""; $fieldname = "is_".$field."_autoclean"; Dropdown::showFromArray($fieldname, $values, ['value' => $CFG_GLPI[$fieldname]]); echo ""; State::dropdownBehaviour("state_autoclean_mode", __('Clear status'), $CFG_GLPI["state_autoclean_mode"]); echo "
"; echo ""; echo "
"; Html::closeForm(); } /** * Print the config form for restrictions * * @return void **/ function showFormAuthentication() { global $CFG_GLPI; if (!Config::canUpdate()) { return; } echo ""; echo "
"; echo ""; echo ""; echo ""; echo ""; echo ""; echo ""; echo ""; echo ""; echo "
" . __('Authentication') . "
". __('Automatically add users from an external authentication source'). ""; Dropdown::showYesNo("is_users_auto_add", $CFG_GLPI["is_users_auto_add"]); echo "". __('Add a user without accreditation from a LDAP directory'). ""; Dropdown::showYesNo("use_noright_users_add", $CFG_GLPI["use_noright_users_add"]); echo "
" . __('Action when a user is deleted from the LDAP directory') . ""; AuthLDAP::dropdownUserDeletedActions($CFG_GLPI["user_deleted_ldap"]); echo " " . __('GLPI server time zone') . ""; Dropdown::showGMT("time_offset", $CFG_GLPI["time_offset"]); echo "
"; echo ""; echo "
"; Html::closeForm(); } /** * Print the config form for slave DB * * @return void **/ function showFormDBSlave() { global $DB, $CFG_GLPI, $DBslave; if (!Config::canUpdate()) { return; } echo ""; echo "
"; echo ""; echo ""; echo ""; $DBslave = DBConnection::getDBSlaveConf(); if (is_array($DBslave->dbhost)) { $host = implode(' ', $DBslave->dbhost); } else { $host = $DBslave->dbhost; } echo ""; echo ""; echo ""; echo ""; echo ""; echo ""; echo ""; echo ""; echo ""; echo ""; echo ""; echo ""; echo ""; if ($DBslave->connected && !$DB->isSlave()) { echo ""; } echo ""; echo "
" . _n('SQL replica', 'SQL replicas', Session::getPluralNumber()) . "
" . __('SQL server (MariaDB or MySQL)') . "" . __('Database') . ""; echo "
" . __('SQL user') . "" . __('SQL password') . ""; echo "
" . __('Use the slave for the search engine') . ""; $values = [0 => __('Never'), 1 => __('If synced (all changes)'), 2 => __('If synced (current user changes)'), 3 => __('If synced or read-only account'), 4 => __('Always')]; Dropdown::showFromArray('use_slave_for_search', $values, ['value' => $CFG_GLPI["use_slave_for_search"]]); echo " 
"; DBConnection::showAllReplicateDelay(); echo "
"; echo ""; echo "
"; Html::closeForm(); } /** * Print the config form for External API * * @since 9.1 * @return void **/ function showFormAPI() { global $CFG_GLPI; if (!self::canView()) { return; } echo "
"; $rand = mt_rand(); $canedit = Config::canUpdate(); if ($canedit) { echo ""; } echo ""; echo ""; echo ""; echo ""; echo ""; echo ""; echo ""; echo ""; echo ""; if ($CFG_GLPI["enable_api"]) { echo ""; } echo ""; echo ""; echo ""; echo ""; echo ""; echo ""; echo ""; echo ""; echo ""; echo "
" . __('API') . "
"; Dropdown::showYesNo("enable_api", $CFG_GLPI["enable_api"], -1, ['rand' => $rand]); echo ""; $inline_doc_api = trim($CFG_GLPI['url_base_api'], '/')."/"; echo "".__("API inline Documentation").""; echo "
" . __('Authentication') . "
 "; Html::showToolTip(__("Allow to login to API and get a session token with user credentials")); echo ""; Dropdown::showYesNo("enable_api_login_credentials", $CFG_GLPI["enable_api_login_credentials"], -1, ['rand' => $rand]); echo " "; Html::showToolTip(__("Allow to login to API and get a session token with user external token. See Remote access key in user Settings tab ")); echo ""; Dropdown::showYesNo("enable_api_login_external_token", $CFG_GLPI["enable_api_login_external_token"], -1, ['rand' => $rand]); echo "
"; echo ""; echo "


"; echo "
"; Html::closeForm(); echo ""; echo ""; echo "
"; echo "
"; $buttons = [ 'apiclient.form.php' => __('Add API client'), ]; Html::displayTitle("", self::getTypeName(Session::getPluralNumber()), "", $buttons); Search::show("APIClient"); echo "
"; } /** * Print the config form for connections * * @return void **/ function showFormHelpdesk() { global $CFG_GLPI; if (!self::canView()) { return; } $rand = mt_rand(); $canedit = Config::canUpdate(); if ($canedit) { echo ""; } echo "
"; echo ""; echo ""; echo ""; echo ""; echo ""; echo ""; echo ""; echo ""; echo ""; echo ""; echo ""; echo ""; echo ""; echo ""; echo "
" . __('Assistance') . "
"; Dropdown::showNumber('time_step', ['value' => $CFG_GLPI["time_step"], 'min' => 30, 'max' => 60, 'step' => 30, 'toadd' => [1 => 1, 5 => 5, 10 => 10, 15 => 15, 20 => 20], 'rand' => $rand]); echo ""; Dropdown::showHours('planning_begin', ['value' => $CFG_GLPI["planning_begin"], 'rand' => $rand]); echo "  "; Dropdown::showHours('planning_end', ['value' => $CFG_GLPI["planning_end"], 'rand' => $rand]); echo "
"; MailCollector::showMaxFilesize('default_mailcollector_filesize_max', $CFG_GLPI["default_mailcollector_filesize_max"], $rand); echo ""; DocumentCategory::dropdown(['value' => $CFG_GLPI["documentcategories_id_forticket"], 'name' => "documentcategories_id_forticket", 'rand' => $rand]); echo "
"; Dropdown::showYesNo("default_software_helpdesk_visible", $CFG_GLPI["default_software_helpdesk_visible"], -1, ['rand' => $rand]); echo ""; Dropdown::showYesNo("keep_tickets_on_delete", $CFG_GLPI["keep_tickets_on_delete"], -1, ['rand' => $rand]); echo "
"; Dropdown::showYesNo('use_check_pref', $CFG_GLPI['use_check_pref'], -1, ['rand' => $rand]); echo ""; Dropdown::showYesNo("use_anonymous_helpdesk", $CFG_GLPI["use_anonymous_helpdesk"], -1, ['rand' => $rand]); echo "
"; Dropdown::showYesNo("use_anonymous_followups", $CFG_GLPI["use_anonymous_followups"], -1, ['rand' => $rand]); echo "
"; echo ""; echo ""; echo ""; echo ""; $isimpact = []; for ($impact=5; $impact>=1; $impact--) { echo ""; } echo ""; echo ""; echo ""; for ($impact=5; $impact>=1; $impact--) { echo ""; } echo ""; $isurgency = []; for ($urgency=5; $urgency>=1; $urgency--) { echo ""; echo ""; echo ""; for ($impact=5; $impact>=1; $impact--) { $pri = round(($urgency+$impact)/2); if (isset($CFG_GLPI['priority_matrix'][$urgency][$impact])) { $pri = $CFG_GLPI['priority_matrix'][$urgency][$impact]; } if ($isurgency[$urgency] && $isimpact[$impact]) { $bgcolor=$_SESSION["glpipriority_$pri"]; echo ""; } else { echo ""; } } echo "\n"; } if ($canedit) { echo ""; echo ""; } echo "
" . __('Matrix of calculus for priority'); echo "
".__('Impact')."".Ticket::getImpactName($impact).'
'; if ($impact==3) { $isimpact[3] = 1; echo ""; } else { $isimpact[$impact] = (($CFG_GLPI['impact_mask']&(1<<$impact)) >0); Dropdown::showYesNo("_impact_${impact}", $isimpact[$impact]); } echo "
".__('Urgency')." 
".Ticket::getUrgencyName($urgency)." "; if ($urgency==3) { $isurgency[3] = 1; echo ""; } else { $isurgency[$urgency] = (($CFG_GLPI['urgency_mask']&(1<<$urgency)) >0); Dropdown::showYesNo("_urgency_${urgency}", $isurgency[$urgency]); } echo ""; Ticket::dropdownPriority(['value' => $pri, 'name' => "_matrix_${urgency}_${impact}"]); echo "
"; echo ""; echo "
"; Html::closeForm(); } /** * Print the config form for default user prefs * * @param $data array containing datas * (CFG_GLPI for global config / glpi_users fields for user prefs) * * @return void **/ function showFormUserPrefs($data = []) { global $CFG_GLPI, $DB; $oncentral = (Session::getCurrentInterface() == "central"); $userpref = false; $url = Toolbox::getItemTypeFormURL(__CLASS__); $rand = mt_rand(); $canedit = Config::canUpdate(); $canedituser = Session::haveRight('personalization', UPDATE); if (array_key_exists('last_login', $data)) { $userpref = true; if ($data["id"] === Session::getLoginUserID()) { $url = $CFG_GLPI['root_doc']."/front/preference.php"; } else { $url = User::getFormURL(); } } if ((!$userpref && $canedit) || ($userpref && $canedituser)) { echo ""; } // Only set id for user prefs if ($userpref) { echo ""; } echo "
"; echo ""; echo ""; echo ""; echo ""; echo ""; echo ""; echo ""; echo ""; echo ""; $values = [0 => '1 234.56', 1 => '1,234.56', 2 => '1 234,56', 3 => '1234.56', 4 => '1234,56']; echo ""; echo ""; echo ""; echo ""; echo ""; echo ""; echo ""; if ($oncentral) { echo ""; } else { echo ""; } if (!$userpref || ($CFG_GLPI['show_count_on_tabs'] != -1)) { echo ""; } else { echo ""; } echo ""; echo ""; if ($oncentral) { echo ""; } else { echo ""; } echo ""; echo ""; echo ""; echo ""; if ($oncentral) { echo ""; } else { echo ""; } echo ""; echo ""; echo ""; echo ""; echo ""; echo ""; echo ""; echo ""; echo ""; echo ""; echo ""; echo ""; echo ""; echo ""; if ($oncentral) { echo ""; echo ""; echo ""; echo ""; echo ""; echo ""; echo ""; echo ""; echo ""; } echo ""; echo "". ""; echo ""; echo ""; echo ""; echo ""; echo ""; echo ""; echo "". ""; echo ""; echo ""; echo ""; if ($oncentral && $CFG_GLPI["lock_use_lock_item"]) { echo ""; echo ""; echo ""; } if (Grid::canViewOneDashboard()) { echo ""; echo ""; echo ""; echo ""; echo ""; } if ((!$userpref && $canedit) || ($userpref && $canedituser)) { echo ""; echo ""; } echo "
" . __('Personalization') . "
"; if (Config::canUpdate() || !GLPI_DEMO_MODE) { Dropdown::showLanguages("language", ['value' => $data["language"], 'rand' => $rand]); } else { echo " "; } echo ""; Dropdown::showFromArray('date_format', Toolbox::phpDateFormats(), ['value' => $data["date_format"], 'rand' => $rand]); echo "
"; $values = [User::REALNAME_BEFORE => __('Surname, First name'), User::FIRSTNAME_BEFORE => __('First name, Surname')]; Dropdown::showFromArray('names_format', $values, ['value' => $data["names_format"], 'rand' => $rand]); echo ""; Dropdown::showFromArray('number_format', $values, ['value' => $data["number_format"], 'rand' => $rand]); echo "
"; // Limit using global config $value = (($data['list_limit'] < $CFG_GLPI['list_limit_max']) ? $data['list_limit'] : $CFG_GLPI['list_limit_max']); Dropdown::showNumber('list_limit', ['value' => $value, 'min' => 5, 'max' => $CFG_GLPI['list_limit_max'], 'step' => 5, 'rand' => $rand]); echo ""; Dropdown::showYesNo("backcreated", $data["backcreated"], -1, ['rand' => $rand]); echo "
"; Dropdown::showYesNo('use_flat_dropdowntree', $data["use_flat_dropdowntree"], -1, ['rand' => $rand]); echo " "; $values = [0 => __('No'), 1 => __('Yes')]; if (!$userpref) { $values[-1] = __('Never'); } Dropdown::showFromArray('show_count_on_tabs', $values, ['value' => $data["show_count_on_tabs"], 'rand' => $rand]); echo " 
"; Dropdown::showYesNo("is_ids_visible", $data["is_ids_visible"], -1, ['rand' => $rand]); echo ""; Dropdown::showYesNo('keep_devices_when_purging_item', $data['keep_devices_when_purging_item'], -1, ['rand' => $rand]); echo "
"; Dropdown::showYesNo("notification_to_myself", $data["notification_to_myself"], -1, ['rand' => $rand]); echo ""; Dropdown::showNumber('display_count_on_home', ['value' => $data['display_count_on_home'], 'min' => 0, 'max' => 30, 'rand' => $rand]); echo " 
"; Dropdown::showFromArray("pdffont", GLPIPDF::getFontList(), ['value' => $data["pdffont"], 'width' => 200, 'rand' => $rand]); echo ""; $values = [';' => ';', ',' => ',']; Dropdown::showFromArray('csv_delimiter', $values, ['value' => $data["csv_delimiter"], 'rand' => $rand]); echo "
"; echo Html::select( 'palette', $this->getPalettes(), [ 'id' => 'theme-selector', 'selected' => $data['palette'] ] ); echo Html::scriptBlock(" function formatThemes(theme) { if (!theme.id) { return theme.text; } return $('').html('' + ' ' + theme.text); } $(\"#theme-selector\").select2({ templateResult: formatThemes, templateSelection: formatThemes, width: '100%', escapeMarkup: function(m) { return m; } }); $('label[for=theme-selector]').on('click', function(){ $('#theme-selector').select2('open'); }); "); echo ""; $layout_options = [ 'lefttab' => __("Tabs on left"), 'classic' => __("Classic view"), 'vsplit' => __("Vertical split") ]; echo Html::select( 'layout', $layout_options, [ 'id' => 'layout-selector', 'selected' => $data['layout'] ] ); echo Html::scriptBlock(" function formatLayout(layout) { if (!layout.id) { return layout.text; } return $('').html('' + ' ' + layout.text); } $(\"#layout-selector\").select2({ dropdownAutoWidth: true, templateResult: formatLayout, templateSelection: formatLayout }); $('label[for=layout-selector]').on('click', function(){ $('#layout-selector').select2('open'); }); "); echo ""; echo "
"; Dropdown::showYesNo('highcontrast_css', $data['highcontrast_css'], -1, ['rand' => $rand]); echo ""; $tz_warning = ''; $tz_available = $DB->areTimezonesAvailable($tz_warning); if ($tz_available) { $timezones = $DB->getTimezones(); Dropdown::showFromArray( 'timezone', $timezones, [ 'value' => $data["timezone"], 'display_emptychoice' => true, 'emptylabel' => __('Use server configuration') ] ); } else { echo ""; echo $tz_warning; } echo "
".__('Assistance')."
"; Dropdown::showYesNo("followup_private", $data["followup_private"], -1, ['rand' => $rand]); echo ""; if (Session::haveRightsOr("ticket", [Ticket::READMY, Ticket::READALL, Ticket::READASSIGN])) { Dropdown::showYesNo("show_jobs_at_login", $data["show_jobs_at_login"], -1, ['rand' => $rand]); } else { echo Dropdown::getYesNo(0); } echo "
"; Dropdown::showYesNo("task_private", $data["task_private"], -1, ['rand' => $rand]); echo ""; RequestType::dropdown([ 'value' => $data["default_requesttypes_id"], 'name' => "default_requesttypes_id", 'condition' => ['is_active' => 1, 'is_ticketheader' => 1], 'rand' => $rand ]); echo "
"; Planning::dropdownState("task_state", $data["task_state"], true, ['rand' => $rand]); echo ""; Dropdown::showNumber('refresh_views', ['value' => $data["refresh_views"], 'min' => 1, 'max' => 30, 'step' => 1, 'toadd' => [0 => __('Never')], 'rand' => $rand]); echo "
"; if (!$userpref || Session::haveRight('ticket', Ticket::OWN)) { Dropdown::showYesNo("set_default_tech", $data["set_default_tech"], -1, ['rand' => $rand]); } else { echo Dropdown::getYesNo(0); } echo ""; if (!$userpref || Session::haveRight('ticket', CREATE)) { Dropdown::showYesNo("set_default_requester", $data["set_default_requester"], -1, ['rand' => $rand]); } else { echo Dropdown::getYesNo(0); } echo "
" . __('Priority colors') . ""; echo ""; echo ""; echo ""; echo ""; echo ""; echo ""; echo ""; echo "
 "; Html::showColorField('priority_1', ['value' => $data["priority_1"], 'rand' => $rand]); echo " "; Html::showColorField('priority_2', ['value' => $data["priority_2"], 'rand' => $rand]); echo " "; Html::showColorField('priority_3', ['value' => $data["priority_3"], 'rand' => $rand]); echo " "; Html::showColorField('priority_4', ['value' => $data["priority_4"], 'rand' => $rand]); echo " "; Html::showColorField('priority_5', ['value' => $data["priority_5"], 'rand' => $rand]); echo " "; Html::showColorField('priority_6', ['value' => $data["priority_6"], 'rand' => $rand]); echo "
"; echo "
".__('Due date progression')."
".__('OK state color').""; Html::showColorField('duedateok_color', ['value' => $data["duedateok_color"]]); echo " 
".__('Warning state color').""; Html::showColorField('duedatewarning_color', ['value' => $data["duedatewarning_color"]]); echo "".__('Warning state threshold').""; Dropdown::showNumber("duedatewarning_less", ['value' => $data['duedatewarning_less']]); $elements = ['%' => '%', 'hours' => _n('Hour', 'Hours', Session::getPluralNumber()), 'days' => _n('Day', 'Days', Session::getPluralNumber())]; echo " "; Dropdown::showFromArray("duedatewarning_unit", $elements, ['value' => $data['duedatewarning_unit']]); echo "
".__('Critical state color').""; Html::showColorField('duedatecritical_color', ['value' => $data["duedatecritical_color"]]); echo "".__('Critical state threshold').""; Dropdown::showNumber("duedatecritical_less", ['value' => $data['duedatecritical_less']]); echo " "; $elements = ['%' => '%', 'hours' => _n('Hour', 'Hours', Session::getPluralNumber()), 'days' => _n('Day', 'Days', Session::getPluralNumber())]; Dropdown::showFromArray("duedatecritical_unit", $elements, ['value' => $data['duedatecritical_unit']]); echo "
".__('Item locks')."
" . __('Auto-lock Mode') . ""; Dropdown::showYesNo("lock_autolock_mode", $data["lock_autolock_mode"]); echo "". __('Direct Notification (requester for unlock will be the notification sender)'). ""; Dropdown::showYesNo("lock_directunlock_notification", $data["lock_directunlock_notification"]); echo "
".__('Dashboards')."
" . __('Default for central') . ""; Grid::dropdownDashboard("default_dashboard_central", [ 'value' => $data['default_dashboard_central'], 'display_emptychoice' => true ]); echo "". __('Default for Assets'). ""; Grid::dropdownDashboard("default_dashboard_assets", [ 'value' => $data['default_dashboard_assets'], 'display_emptychoice' => true ]); echo "
". __('Default for Assistance') . ""; Grid::dropdownDashboard("default_dashboard_helpdesk", [ 'value' => $data['default_dashboard_helpdesk'], 'display_emptychoice' => true ]); echo "". __('Default for tickets (mini dashboard)'). ""; Grid::dropdownDashboard("default_dashboard_mini_ticket", [ 'value' => $data['default_dashboard_mini_ticket'], 'display_emptychoice' => true ]); echo "
"; echo ""; echo "
"; Html::closeForm(); } /** * Display security checks on password * * @param $field string id of the field containing password to check (default 'password') * * @since 0.84 **/ static function displayPasswordSecurityChecks($field = 'password') { global $CFG_GLPI; $needs = []; if ($CFG_GLPI["use_password_security"]) { printf(__('%1$s: %2$s'), __('Password minimum length'), "".$CFG_GLPI['password_min_length']. ""); } echo "'; if (count($needs)) { echo "
"; printf(__('%1$s: %2$s'), __('Password must contains'), implode(', ', $needs)); } } /** * Validate password based on security rules * * @since 0.84 * * @param $password string password to validate * @param $display boolean display errors messages? (true by default) * * @throws PasswordTooWeakException when $display is false and the password does not matches the requirements * * @return boolean is password valid? **/ static function validatePassword($password, $display = true) { global $CFG_GLPI; $ok = true; $exception = new PasswordTooWeakException(); if ($CFG_GLPI["use_password_security"]) { if (Toolbox::strlen($password) < $CFG_GLPI['password_min_length']) { $ok = false; if ($display) { Session::addMessageAfterRedirect(__('Password too short!'), false, ERROR); } else { $exception->addMessage(__('Password too short!')); } } if ($CFG_GLPI["password_need_number"] && !preg_match("/[0-9]+/", $password)) { $ok = false; if ($display) { Session::addMessageAfterRedirect(__('Password must include at least a digit!'), false, ERROR); } else { $exception->addMessage(__('Password must include at least a digit!')); } } if ($CFG_GLPI["password_need_letter"] && !preg_match("/[a-z]+/", $password)) { $ok = false; if ($display) { Session::addMessageAfterRedirect(__('Password must include at least a lowercase letter!'), false, ERROR); } else { $exception->addMessage(__('Password must include at least a lowercase letter!')); } } if ($CFG_GLPI["password_need_caps"] && !preg_match("/[A-Z]+/", $password)) { $ok = false; if ($display) { Session::addMessageAfterRedirect(__('Password must include at least a uppercase letter!'), false, ERROR); } else { $exception->addMessage(__('Password must include at least a uppercase letter!')); } } if ($CFG_GLPI["password_need_symbol"] && !preg_match("/\W+/", $password)) { $ok = false; if ($display) { Session::addMessageAfterRedirect(__('Password must include at least a symbol!'), false, ERROR); } else { $exception->addMessage(__('Password must include at least a symbol!')); } } } if (!$ok && !$display) { throw $exception; } return $ok; } /** * Display a report about system performance * - opcode cache (opcache) * - user data cache (apcu / apcu-bc) * * @since 9.1 **/ function showPerformanceInformations() { $GLPI_CACHE = self::getCache('cache_db', 'core', false); if (!Config::canUpdate()) { return false; } echo "
"; echo ""; echo ""; $ext = 'Zend OPcache'; if (extension_loaded($ext) && ($info = opcache_get_status(false))) { $msg = sprintf(__s('%s extension is installed'), $ext); echo ""; // Memory $used = $info['memory_usage']['used_memory']; $free = $info['memory_usage']['free_memory']; $rate = round(100.0 * $used / ($used + $free)); $max = Toolbox::getSize($used + $free); $used = Toolbox::getSize($used); echo ""; // Hits $hits = $info['opcache_statistics']['hits']; $miss = $info['opcache_statistics']['misses']; $max = $hits+$miss; $rate = round($info['opcache_statistics']['opcache_hit_rate']); echo ""; // Restart (1 seems ok, can happen) $max = $info['opcache_statistics']['oom_restarts']; echo ""; if ($_SESSION['glpi_use_mode'] == Session::DEBUG_MODE) { echo "\n"; } } else { $msg = sprintf(__s('%s extension is not present'), $ext); echo ""; } echo ""; $ext = strtolower(get_class($GLPI_CACHE)); $ext = substr($ext, strrpos($ext, '\\')+1); if (in_array($ext, ['apcu', 'memcache', 'memcached', 'wincache', 'redis'])) { $msg = sprintf(__s('The "%s" cache extension is installed'), $ext); } else { $msg = sprintf(__s('"%s" cache system is used'), $ext); } echo ""; if ($ext != 'filesystem' && $GLPI_CACHE instanceof AvailableSpaceCapableInterface && $GLPI_CACHE instanceof TotalSpaceCapableInterface) { $free = $GLPI_CACHE->getAvailableSpace(); $max = $GLPI_CACHE->getTotalSpace(); $used = $max - $free; $rate = round(100.0 * $used / $max); $max = Toolbox::getSize($max); $used = Toolbox::getSize($used); echo ""; } if ($GLPI_CACHE instanceof FlushableInterface) { echo "\n"; } echo ""; $translation_cache = self::getCache('cache_trans', 'core', false); $adapter_class = strtolower(get_class($translation_cache)); $adapter = substr($adapter_class, strrpos($adapter_class, '\\')+1); $msg = sprintf(__s('"%s" cache system is used'), $adapter); echo ""; if ($translation_cache instanceof FlushableInterface) { echo "\n"; } echo "
" . __('PHP opcode cache') . "
" . sprintf(__('The "%s" extension is installed'), $ext) . " " . phpversion($ext) . " $msg
" . _n('Memory', 'Memories', 1) . " " . sprintf(__('%1$s / %2$s'), $used, $max) . ""; Html::displayProgressBar('100', $rate, ['simple' => true, 'forcepadding' => false]); $class = 'info-circle missing'; $msg = sprintf(__s('%1$s memory usage is too low or too high'), $ext); if ($rate > 5 && $rate < 75) { $class = 'check-circle ok'; $msg = sprintf(__s('%1$s memory usage is correct'), $ext); } echo "
" . __('Hits rate') . " " . sprintf(__('%1$s / %2$s'), $hits, $max) . ""; Html::displayProgressBar('100', $rate, ['simple' => true, 'forcepadding' => false]); $class = 'info-circle missing'; $msg = sprintf(__s('%1$s hits rate is low'), $ext); if ($rate > 90) { $class = 'check-circle ok'; $msg = sprintf(__s('%1$s hits rate is correct'), $ext); } echo "
" . __('Out of memory restart') . " $max"; $class = 'info-circle missing'; $msg = sprintf(__s('%1$s restart rate is too high'), $ext); if ($max < 2) { $class = 'check-circle ok'; $msg = sprintf(__s('%1$s restart rate is correct'), $ext); } echo "
"; echo ""; echo __('Reset'); echo "
" . sprintf(__('Installing and enabling the "%s" extension may improve GLPI performance'), $ext) . " $msg
" . __('User data cache') . "
" . $msg . " " . phpversion($ext) . " $msg
" . _n('Memory', 'Memories', 1) . " " . sprintf(__('%1$s / %2$s'), $used, $max) . ""; Html::displayProgressBar('100', $rate, ['simple' => true, 'forcepadding' => false]); $class = 'info-circle missing'; $msg = sprintf(__s('%1$s memory usage is too high'), $ext); if ($rate < 80) { $class = 'check-circle ok'; $msg = sprintf(__s('%1$s memory usage is correct'), $ext); } echo "
"; echo ""; echo __('Reset'); echo "
" . __('Translation cache') . "
" . $msg . " $msg
"; echo ""; echo __('Reset'); echo "
\n"; } /** * Display a HTML report about systeme information / configuration **/ function showSystemInformations() { global $DB, $CFG_GLPI; if (!Config::canUpdate()) { return false; } $rand = mt_rand(); echo "
"; echo ""; echo ""; echo ""; echo ""; echo ""; echo ""; echo ""; echo ""; echo ""; echo ""; echo ""; echo ""; //TRANS: Proxy port echo ""; echo ""; echo ""; echo ""; echo ""; echo ""; echo ""; //TRANS: Proxy port echo ""; echo ""; echo ""; echo ""; echo ""; echo ""; echo ""; echo ""; echo ""; echo ""; echo "
" . __('General setup') . "
"; $values = [ 1 => __('1- Critical (login error only)'), 2 => __('2- Severe (not used)'), 3 => __('3- Important (successful logins)'), 4 => __('4- Notices (add, delete, tracking)'), 5 => __('5- Complete (all)'), ]; Dropdown::showFromArray('event_loglevel', $values, ['value' => $CFG_GLPI["event_loglevel"], 'rand' => $rand]); echo ""; Dropdown::showNumber('cron_limit', ['value' => $CFG_GLPI["cron_limit"], 'min' => 1, 'max' => 30, 'rand' => $rand]); echo "
"; Dropdown::showYesNo("use_log_in_files", $CFG_GLPI["use_log_in_files"], -1, ['rand' => $rand]); echo ""; $active = DBConnection::isDBSlaveActive(); Dropdown::showYesNo("_dbslave_status", $active, -1, ['rand' => $rand]); echo "
".__('Maintenance mode'); echo "
"; Dropdown::showYesNo("maintenance_mode", $CFG_GLPI["maintenance_mode"], -1, ['rand' => $rand]); echo ""; echo ""; echo "
".__('Proxy configuration for upgrade check'); echo "
"; echo "
"; echo "
"; echo ""; echo "
"; Html::closeForm(); $width = 128; echo "

" . Telemetry::getViewLink() . "

"; echo ""; echo ""; echo ""; $oldlang = $_SESSION['glpilanguage']; // Keep this, for some function call which still use translation (ex showAllReplicateDelay) Session::loadLanguage('en_GB'); // No need to translate, this part always display in english (for copy/paste to forum) // Try to compute a better version for .git $ver = GLPI_VERSION; if (is_dir(GLPI_ROOT."/.git")) { $dir = getcwd(); chdir(GLPI_ROOT); $returnCode = 1; /** @var array $output */ $gitrev = @exec('git show --format="%h" --no-patch 2>&1', $output, $returnCode); $gitbranch = ''; if (!$returnCode) { $gitbranch = @exec('git symbolic-ref --quiet --short HEAD || git rev-parse --short HEAD 2>&1', $output, $returnCode); } chdir($dir); if (!$returnCode) { $ver .= '-git-' .$gitbranch . '-' . $gitrev; } } echo ""; echo "\n"; echo ""; echo "\n"; echo ""; self::showLibrariesInformation(); foreach ($CFG_GLPI["systeminformations_types"] as $type) { $tmp = new $type(); $tmp->showSystemInformations($width); } Session::loadLanguage($oldlang); $files = array_merge( glob(GLPI_LOCAL_I18N_DIR."/**/*.php"), glob(GLPI_LOCAL_I18N_DIR."/**/*.mo") ); sort($files); if (count($files)) { echo "\n"; echo ""; } echo ""; echo "\n"; echo "
". __('Information about system installation and configuration')."
"; echo "".__('Check if a new version is available').""; echo "
[code]\n \n";
      echo "GLPI $ver (" . $CFG_GLPI['root_doc']." => " . GLPI_ROOT . ")\n";
      echo "Installation mode: " . GLPI_INSTALL_MODE . "\n";
      echo "\n
Server
\n \n";
      echo wordwrap("Operating system: ".php_uname()."\n", $width, "\n\t");
      $exts = get_loaded_extensions();
      sort($exts);
      echo wordwrap("PHP ".phpversion().' '.php_sapi_name()." (".implode(', ', $exts).")\n",
                    $width, "\n\t");
      $msg = "Setup: ";

      foreach (['max_execution_time', 'memory_limit', 'post_max_size', 'safe_mode',
                     'session.save_handler', 'upload_max_filesize'] as $key) {
         $msg .= $key.'="'.ini_get($key).'" ';
      }
      echo wordwrap($msg."\n", $width, "\n\t");

      $msg = 'Software: ';
      if (isset($_SERVER["SERVER_SOFTWARE"])) {
         $msg .= $_SERVER["SERVER_SOFTWARE"];
      }
      if (isset($_SERVER["SERVER_SIGNATURE"])) {
         $msg .= ' ('.Html::clean($_SERVER["SERVER_SIGNATURE"]).')';
      }
      echo wordwrap($msg."\n", $width, "\n\t");

      if (isset($_SERVER["HTTP_USER_AGENT"])) {
         echo "\t" . Toolbox::clean_cross_side_scripting_deep($_SERVER["HTTP_USER_AGENT"]) . "\n";
      }

      foreach ($DB->getInfo() as $key => $val) {
         echo "$key: $val\n\t";
      }
      echo "\n";

      $core_requirements = (new RequirementsManager())->getCoreRequirementList($DB);
      /* @var \Glpi\System\Requirement\RequirementInterface $requirement */
      foreach ($core_requirements as $requirement) {
         if ($requirement->isOutOfContext()) {
            continue; // skip requirement if not relevant
         }

         $img = $requirement->isValidated()
            ? 'ok'
            : ($requirement->isOptional() ? 'warning' : 'ko');
         $messages = Html::entities_deep($requirement->getValidationMessages());

         echo '' . implode(' ', $messages) . '';
         echo implode("\n", $messages);

         echo "\n";
      }

      echo "\n
GLPI constants
\n \n";
      foreach (get_defined_constants() as $constant_name => $constant_value) {
         if (preg_match('/^GLPI_/', $constant_name)) {
            echo $constant_name . ': ' . $constant_value . "\n";
         }
      }
      echo "\n
Locales overrides
\n"; foreach ($files as $file) { echo "$file
\n"; } echo "
[/code]\n
". __('To copy/paste in your support request')."
\n"; } /** * Retrieve full directory of a lib * @param $libstring object, class or function * @return string the path or false * * @since 9.1 */ static function getLibraryDir($libstring) { if (is_object($libstring)) { return realpath(dirname((new ReflectionObject($libstring))->getFileName())); } else if (class_exists($libstring) || interface_exists($libstring)) { return realpath(dirname((new ReflectionClass($libstring))->getFileName())); } else if (function_exists($libstring)) { // Internal function have no file name $path = (new ReflectionFunction($libstring))->getFileName(); return ($path ? realpath(dirname($path)) : false); } return false; } /** * get libraries list * * @param $all (default false) * @return array dependencies list * * @since 9.4 */ static function getLibraries($all = false) { $pm = new PHPMailer(); $sp = new SimplePie(); // use same name that in composer.json $deps = [[ 'name' => 'htmlawed/htmlawed', 'version' => hl_version() , 'check' => 'hl_version' ], [ 'name' => 'phpmailer/phpmailer', 'version' => $pm::VERSION, 'check' => 'PHPMailer\\PHPMailer\\PHPMailer' ], [ 'name' => 'simplepie/simplepie', 'version' => SIMPLEPIE_VERSION, 'check' => $sp ], [ 'name' => 'tecnickcom/tcpdf', 'version' => TCPDF_STATIC::getTCPDFVersion(), 'check' => 'TCPDF' ], [ 'name' => 'michelf/php-markdown', 'check' => 'Michelf\\Markdown' ], [ 'name' => 'true/punycode', 'check' => 'TrueBV\\Punycode' ], [ 'name' => 'iamcal/lib_autolink', 'check' => 'autolink' ], [ 'name' => 'sabre/dav', 'check' => 'Sabre\\DAV\\Version' ], [ 'name' => 'sabre/http', 'check' => 'Sabre\\HTTP\\Version' ], [ 'name' => 'sabre/uri', 'check' => 'Sabre\\Uri\\Version' ], [ 'name' => 'sabre/vobject', 'check' => 'Sabre\\VObject\\Component' ], [ 'name' => 'laminas/laminas-cache', 'check' => 'Laminas\\Cache\\Module' ], [ 'name' => 'laminas/laminas-i18n', 'check' => 'Laminas\\I18n\\Module' ], [ 'name' => 'laminas/laminas-serializer', 'check' => 'Laminas\\Serializer\\Module' ], [ 'name' => 'monolog/monolog', 'check' => 'Monolog\\Logger' ], [ 'name' => 'sebastian/diff', 'check' => 'SebastianBergmann\\Diff\\Diff' ], [ 'name' => 'elvanto/litemoji', 'check' => 'LitEmoji\\LitEmoji' ], [ 'name' => 'symfony/console', 'check' => 'Symfony\\Component\\Console\\Application' ], [ 'name' => 'scssphp/scssphp', 'check' => 'ScssPhp\ScssPhp\Compiler' ], [ 'name' => 'laminas/laminas-mail', 'check' => 'Laminas\\Mail\\Protocol\\Imap' ], [ 'name' => 'laminas/laminas-mime', 'check' => 'Laminas\\Mime\\Mime' ], [ 'name' => 'rlanvin/php-rrule', 'check' => 'RRule\\RRule' ], [ 'name' => 'blueimp/jquery-file-upload', 'check' => 'UploadHandler' ], [ 'name' => 'ramsey/uuid', 'check' => 'Ramsey\\Uuid\\Uuid' ], [ 'name' => 'psr/log', 'check' => 'Psr\\Log\\LoggerInterface' ], [ 'name' => 'psr/simple-cache', 'check' => 'Psr\\SimpleCache\\CacheInterface' ], [ 'name' => 'mexitek/phpcolors', 'check' => 'Mexitek\\PHPColors\\Color' ], [ 'name' => 'guzzlehttp/guzzle', 'check' => 'GuzzleHttp\\Client' ], [ 'name' => 'guzzlehttp/psr7', 'check' => 'GuzzleHttp\\Psr7\\Response' ], [ 'name' => 'wapmorgan/unified-archive', 'check' => 'wapmorgan\\UnifiedArchive\\UnifiedArchive' ], [ 'name' => 'paragonie/sodium_compat', 'check' => 'ParagonIE_Sodium_Compat' ], ]; if (Toolbox::canUseCAS()) { $deps[] = [ 'name' => 'phpCas', 'version' => phpCAS::getVersion(), 'check' => 'phpCAS' ]; } return $deps; } /** * show Libraries information in system information * * @since 0.84 **/ static function showLibrariesInformation() { // No gettext echo "Libraries\n"; echo "
\n \n";

      foreach (self::getLibraries() as $dep) {
         $path = self::getLibraryDir($dep['check']);
         if ($path) {
            echo "{$dep['name']} ";
            if (isset($dep['version'])) {
               echo "version {$dep['version']} ";
            }
            echo "in ($path)\n";
         } else {
            echo "{$dep['name']} not found\n";
         }
      }

      echo "\n
"; } /** * Dropdown for global management config * * @param string $name select name * @param string $value default value * @param integer|null $rand rand **/ static function dropdownGlobalManagement($name, $value, $rand = null) { $choices = [ __('Yes - Restrict to unit management for manual add'), __('Yes - Restrict to global management for manual add'), __('No'), ]; Dropdown::showFromArray($name, $choices, ['value'=>$value, 'rand' => $rand]); } /** * Get language in GLPI associated with the value coming from LDAP/SSO * Value can be, for example : English, en_EN, en-EN or en * * @param string $lang the value coming from LDAP/SSO * * @return string locale's php page in GLPI or '' is no language associated with the value **/ static function getLanguage($lang) { global $CFG_GLPI; // Alternative language code: en-EN --> en_EN $altLang = str_replace("-", "_", $lang); // Search in order : ID or extjs dico or tinymce dico / native lang / english name // / extjs dico / tinymce dico // ID or extjs dico or tinymce dico foreach ($CFG_GLPI["languages"] as $ID => $language) { if ((strcasecmp($lang, $ID) == 0) || (strcasecmp($altLang, $ID) == 0) || (strcasecmp($lang, $language[2]) == 0) || (strcasecmp($lang, $language[3]) == 0)) { return $ID; } } // native lang foreach ($CFG_GLPI["languages"] as $ID => $language) { if (strcasecmp($lang, $language[0]) == 0) { return $ID; } } // english lang name foreach ($CFG_GLPI["languages"] as $ID => $language) { if (strcasecmp($lang, $language[4]) == 0) { return $ID; } } return ""; } static function detectRootDoc() { global $CFG_GLPI; if (!isset($CFG_GLPI["root_doc"])) { if (!isset($_SERVER['REQUEST_URI'])) { $_SERVER['REQUEST_URI'] = $_SERVER['PHP_SELF']; } $currentdir = getcwd(); chdir(GLPI_ROOT); $glpidir = str_replace(str_replace('\\', '/', getcwd()), "", str_replace('\\', '/', $currentdir)); chdir($currentdir); $globaldir = Html::cleanParametersURL($_SERVER['REQUEST_URI']); $globaldir = preg_replace("/\/[0-9a-zA-Z\.\-\_]+\.php/", "", $globaldir); // api exception if (strpos($globaldir, 'api/') !== false) { $globaldir = preg_replace("/(.*\/)api\/.*/", "$1", $globaldir); } $CFG_GLPI["root_doc"] = str_replace($glpidir, "", $globaldir); $CFG_GLPI["root_doc"] = preg_replace("/\/$/", "", $CFG_GLPI["root_doc"]); // urldecode for space redirect to encoded URL : change entity $CFG_GLPI["root_doc"] = urldecode($CFG_GLPI["root_doc"]); } } /** * Display debug information for dbslave **/ function showDebug() { $options = [ 'diff' => 0, 'name' => '', ]; NotificationEvent::debugEvent(new DBConnection(), $options); } /** * Display field unicity criterias form **/ function showFormFieldUnicity() { $unicity = new FieldUnicity(); $unicity->showForm(1, -1); } function getTabNameForItem(CommonGLPI $item, $withtemplate = 0) { switch ($item->getType()) { case 'Preference' : return __('Personalization'); case 'User' : if (User::canUpdate() && $item->currentUserHaveMoreRightThan($item->getID())) { return __('Settings'); } break; case __CLASS__ : $tabs = [ 1 => __('General setup'), // Display 2 => __('Default values'), // Prefs 3 => __('Assets'), 4 => __('Assistance'), ]; if (Config::canUpdate()) { $tabs[9] = __('Logs purge'); $tabs[5] = __('System'); $tabs[10] = __('Security'); $tabs[7] = __('Performance'); $tabs[8] = __('API'); $tabs[11] = Impact::getTypeName(); } if (DBConnection::isDBSlaveActive() && Config::canUpdate()) { $tabs[6] = _n('SQL replica', 'SQL replicas', Session::getPluralNumber()); // Slave } return $tabs; case 'GLPINetwork': return 'GLPI Network'; case Impact::getType(): return Impact::getTypeName(); } return ''; } static function displayTabContentForItem(CommonGLPI $item, $tabnum = 1, $withtemplate = 0) { global $CFG_GLPI; if ($item->getType() == 'Preference') { $config = new self(); $user = new User(); if ($user->getFromDB(Session::getLoginUserID())) { $user->computePreferences(); $config->showFormUserPrefs($user->fields); } } else if ($item->getType() == 'User') { $config = new self(); $item->computePreferences(); $config->showFormUserPrefs($item->fields); } else if ($item->getType() == __CLASS__) { switch ($tabnum) { case 1 : $item->showFormDisplay(); break; case 2 : $item->showFormUserPrefs($CFG_GLPI); break; case 3 : $item->showFormInventory(); break; case 4 : $item->showFormHelpdesk(); break; case 5 : $item->showSystemInformations(); break; case 6 : $item->showFormDBSlave(); break; case 7 : $item->showPerformanceInformations(); break; case 8 : $item->showFormAPI(); break; case 9: $item->showFormLogs(); break; case 10: $item->showFormSecurity(); break; case 11: Impact::showConfigForm(); break; } } return true; } /** * Display database engine checks report * * @since 9.3 * * @param boolean $fordebug display for debug (no html required) (false by default) * @param string $version Version to check (mainly from install), defaults to null * * @return integer 2: missing extension, 1: missing optionnal extension, 0: OK, **/ static function displayCheckDbEngine($fordebug = false, $version = null) { global $CFG_GLPI; $error = 0; $result = self::checkDbEngine($version); $version = key($result); $db_ver = $result[$version]; $ok_message = sprintf(__s('Database version seems correct (%s) - Perfect!'), $version); $ko_message = sprintf(__s('Your database engine version seems too old: %s.'), $version); if (!$db_ver) { $error = 2; } $message = $error > 0 ? $ko_message : $ok_message; $img = " 0 ? "ko_min" : "ok_min") . ".png' alt='$message' title='$message'/>"; if (isCommandLine()) { echo $message . "\n"; } else if ($fordebug) { echo $img . $message . "\n"; } else { $html = " 0) { $html .= " class='red'"; } $html .= ">"; $html .= $img; $html .= ''; echo $html; } return $error; } /** * Display extensions checks report * * @since 9.2 * * @param boolean $fordebug display for debug (no html required) (false by default) * * @return integer 2: missing extension, 1: missing optionnal extension, 0: OK, * * @deprecated 9.5.0 **/ static function displayCheckExtensions($fordebug = false) { Toolbox::deprecated(); global $CFG_GLPI; $report = self::checkExtensions(); foreach ($report['good'] as $ext => $msg) { if (!$fordebug) { echo "" . sprintf(__('%s extension test'), $ext) . ""; echo "\"$msg\""; echo ""; } else { echo "\"\"$msg\n"; } } foreach ($report['may'] as $ext => $msg) { if (!$fordebug) { echo "" . sprintf(__('%s extension test'), $ext) . ""; echo " " . $msg . ""; echo ""; } else { echo "" . $msg . "\n"; } } foreach ($report['missing'] as $ext => $msg) { if (!$fordebug) { echo "" . sprintf(__('%s extension test'), $ext) . ""; echo " " . $msg . ""; echo ""; } else { echo "" . $msg . "\n"; } } return $report['error']; } /** * Check for needed extensions * * @since 9.3 * * @param string $raw Raw version to check (mainly from install), defaults to null * * @return boolean **/ static function checkDbEngine($raw = null) { // MySQL >= 5.6 || MariaDB >= 10 if ($raw === null) { global $DB; $raw = $DB->getVersion(); } /** @var array $found */ preg_match('/(\d+(\.)?)+/', $raw, $found); $version = $found[0]; $db_ver = version_compare($version, '5.6', '>='); return [$version => $db_ver]; } /** * Check for needed extensions * * @since 9.2 Method signature and return has changed * * @param null|array $list Extensions list (from plugins) * * @return array [ * 'error' => integer 2: missing extension, 1: missing optionnal extension, 0: OK, * 'good' => [ext => message], * 'missing' => [ext => message], * 'may' => [ext => message] * ] **/ static function checkExtensions($list = null) { if ($list === null) { $extensions_to_check = [ 'mysqli' => [ 'required' => true ], 'ctype' => [ 'required' => true, 'function' => 'ctype_digit', ], 'fileinfo' => [ 'required' => true, 'class' => 'finfo' ], 'json' => [ 'required' => true, 'function' => 'json_encode' ], 'mbstring' => [ 'required' => true, ], 'iconv' => [ 'required' => true, ], 'zlib' => [ 'required' => true, ], 'curl' => [ 'required' => true, ], 'gd' => [ 'required' => true, ], 'simplexml' => [ 'required' => true, ], 'xml' => [ 'required' => true, 'function' => 'utf8_decode' ], //to sync/connect from LDAP 'ldap' => [ 'required' => false, ], //to enhance perfs 'Zend OPcache' => [ 'required' => false ], //to enhance perfs 'APCu' => [ 'required' => false, 'function' => 'apcu_fetch' ], //for XMLRPC API 'xmlrpc' => [ 'required' => false ], //for CAS lib 'CAS' => [ 'required' => false, 'class' => 'phpCAS' ], 'exif' => [ 'required' => false ], 'intl' => [ 'required' => true ], 'sodium' => [ 'required' => false ] ]; } else { $extensions_to_check = $list; } $report = [ 'error' => 0, 'good' => [], 'missing' => [], 'may' => [] ]; //check for PHP extensions foreach ($extensions_to_check as $ext => $params) { $success = true; if (isset($params['call'])) { $success = call_user_func($params['call']); } else if (isset($params['function'])) { if (!function_exists($params['function'])) { $success = false; } } else if (isset($params['class'])) { if (!class_exists($params['class'])) { $success = false; } } else { if (!extension_loaded($ext)) { $success = false; } } if ($success) { $msg = sprintf(__('%s extension is installed'), $ext); $report['good'][$ext] = $msg; } else { if (isset($params['required']) && $params['required'] === true) { if ($report['error'] < 2) { $report['error'] = 2; } $msg = sprintf(__('%s extension is missing'), $ext); $report['missing'][$ext] = $msg; } else { if ($report['error'] < 1) { $report['error'] = 1; } $msg = sprintf(__('%s extension is not present'), $ext); $report['may'][$ext] = $msg; } } } return $report; } /** * Get data directories for checks * * @return array * * @deprecated 9.5.0 */ private static function getDataDirectories() { Toolbox::deprecated(); $dir_to_check = [ GLPI_CONFIG_DIR => __('Checking write permissions for setting files'), GLPI_DOC_DIR => __('Checking write permissions for document files'), GLPI_DUMP_DIR => __('Checking write permissions for dump files'), GLPI_SESSION_DIR => __('Checking write permissions for session files'), GLPI_CRON_DIR => __('Checking write permissions for automatic actions files'), GLPI_GRAPH_DIR => __('Checking write permissions for graphic files'), GLPI_LOCK_DIR => __('Checking write permissions for lock files'), GLPI_PLUGIN_DOC_DIR => __('Checking write permissions for plugins document files'), GLPI_TMP_DIR => __('Checking write permissions for temporary files'), GLPI_CACHE_DIR => __('Checking write permissions for cache files'), GLPI_RSS_DIR => __('Checking write permissions for rss files'), GLPI_UPLOAD_DIR => __('Checking write permissions for upload files'), GLPI_PICTURE_DIR => __('Checking write permissions for pictures files') ]; return $dir_to_check; } /** * Check Write Access to needed directories * * @param boolean $fordebug display for debug (no html, no gettext required) (false by default) * * @return integer 2 : creation error 1 : delete error 0: OK * * @deprecated 9.5.0 **/ static function checkWriteAccessToDirs($fordebug = false) { Toolbox::deprecated(); global $CFG_GLPI; // Only write test for GLPI_LOG as SElinux prevent removing log file. if (!$fordebug) { echo "". __('Checking write permissions for log files').""; } $can_write_logs = false; try { global $PHPLOGGER; $PHPLOGGER->addRecord(Monolog\Logger::WARNING, "Test logger"); $can_write_logs = true; } catch (\UnexpectedValueException $e) { $catched = true; //empty catch } if ($can_write_logs) { if ($fordebug) { echo "\"".__s('OK')."\"". GLPI_LOG_DIR." : OK\n"; } else { echo "\""."; } } else { if ($fordebug) { echo "". sprintf(__('Check permissions to the directory: %s'), GLPI_LOG_DIR)."\n"; } else { echo "". "

".__('The file could not be created.')."

". sprintf(__('Check permissions to the directory: %s'), GLPI_LOG_DIR).""; } } if ($can_write_logs) { $dir_to_check = self::getDataDirectories(); //log dir is tested differently below unset($dir_to_check[GLPI_LOG_DIR]); $error = 0; foreach ($dir_to_check as $dir => $message) { if (!$fordebug) { echo "".$message.""; } $tmperror = Toolbox::testWriteAccessToDirectory($dir); $errors = [ 4 => __('The directory could not be created.'), 3 => __('The directory was created but could not be removed.'), 2 => __('The file could not be created.'), 1 => __("The file was created but can't be deleted.") ]; if ($tmperror > 0) { if ($fordebug) { echo " ". sprintf(__('Check permissions to the directory: %s'), $dir). " ".$errors[$tmperror]."\n"; } else { echo "

". $errors[$tmperror]."

". sprintf(__('Check permissions to the directory: %s'), $dir). "'"; } $error = 2; } else { if ($fordebug) { echo "\"".__s('OK').$dir : OK\n"; } else { echo "\"".". ""; } } } } else { $error = 2; } $check_access = false; $directories = array_keys(self::getDataDirectories()); foreach ($directories as $dir) { if (Toolbox::startsWith($dir, GLPI_ROOT)) { //only check access if one of the data directories is under GLPI document root. $check_access = true; break; } } if ($check_access) { $oldhand = set_error_handler(function($errno, $errmsg, $filename, $linenum, $vars){return true;}); $oldlevel = error_reporting(0); //create a context to set timeout $context = stream_context_create([ 'http' => [ 'timeout' => 2.0 ] ]); /* TODO: could be improved, only default vhost checked */ $protocol = 'http'; if (isset($_SERVER['HTTPS'])) { $protocol = 'https'; } $uri = $protocol . '://' . $_SERVER['SERVER_NAME'] . $CFG_GLPI['root_doc']; if ($fic = fopen($uri.'/index.php?skipCheckWriteAccessToDirs=1', 'r', false, $context)) { fclose($fic); if (!$fordebug) { echo "". __('Web access to files directory is protected').""; } if ($fic = fopen($uri.'/files/_log/php-errors.log', 'r', false, $context)) { fclose($fic); if ($fordebug) { echo "". __('Web access to the files directory should not be allowed')."\n". __('Check the .htaccess file and the web server configuration.')."\n"; } else { echo "". "

".__('Web access to the files directory should not be allowed')."
". __('Check the .htaccess file and the web server configuration.')."

"; } $error = 1; } else { if ($fordebug) { echo "\"".". __s('Web access to files directory is protected')." : OK\n"; } else { echo "\""."; } } } else { $msg = __('Web access to the files directory should not be allowed but this cannot be checked automatically on this instance.')."\n". "Make sure acces to ".__('error log file')." is forbidden; otherwise review .htaccess file and web server configuration."; if ($fordebug) { echo "".$msg; } else { echo "". "

".nl2br($msg)."

"; } } error_reporting($oldlevel); set_error_handler($oldhand); } return $error; } /** * Get current DB version (compatible with all version of GLPI) * * @since 0.85 * * @return DB version **/ static function getCurrentDBVersion() { global $DB; //Default current case $select = 'value AS version'; $table = 'glpi_configs'; $where = [ 'context' => 'core', 'name' => 'version' ]; if (!$DB->tableExists('glpi_configs')) { $select = 'version'; $table = 'glpi_config'; $where = ['id' => 1]; } else if ($DB->fieldExists('glpi_configs', 'version')) { $select = 'version'; $where = ['id' => 1]; } $row = $DB->request([ 'SELECT' => [$select], 'FROM' => $table, 'WHERE' => $where ])->next(); return trim($row['version']); } /** * Get config values * * @since 0.85 * * @param $context string context to get values (default for glpi is core) * @param $names array of config names to get * * @return array of config values **/ static function getConfigurationValues($context, array $names = []) { global $DB; $query = [ 'FROM' => self::getTable(), 'WHERE' => [ 'context' => $context ] ]; if (count($names) > 0) { $query['WHERE']['name'] = $names; } $iterator = $DB->request($query); $result = []; while ($line = $iterator->next()) { $result[$line['name']] = $line['value']; } return $result; } /** * Load legacy configuration into $CFG_GLPI global variable. * * @param boolean $older_to_latest Search on old configuration objects first * * @return boolean True for success, false if an error occured */ public static function loadLegacyConfiguration($older_to_latest = true) { global $CFG_GLPI, $DB; $config_tables_iterator = $DB->listTables('glpi_config%'); $config_tables = []; foreach ($config_tables_iterator as $config_table) { $config_tables[] = $config_table['TABLE_NAME']; } $get_prior_to_078_config = function() use ($DB, $config_tables) { if (!in_array('glpi_config', $config_tables)) { return false; } $config = new Config(); $config->forceTable('glpi_config'); if ($config->getFromDB(1)) { return $config->fields; } return false; }; $get_078_to_latest_config = function() use ($DB, $config_tables) { if (!in_array('glpi_configs', $config_tables)) { return false; } Config::forceTable('glpi_configs'); $iterator = $DB->request(['FROM' => 'glpi_configs']); if ($iterator->count() === 0) { return false; } if ($iterator->count() === 1) { // 1 row = 0.78 to 0.84 config table schema return $iterator->next(); } // multiple rows = 0.85+ config $config = []; while ($row = $iterator->next()) { if ('core' !== $row['context']) { continue; } $config[$row['name']] = $row['value']; } return $config; }; $functions = []; if ($older_to_latest) { // Try with old config table first : for update process management from < 0.80 to >= 0.80. $functions = [ $get_prior_to_078_config, $get_078_to_latest_config, ]; } else { // Normal load process : use normal config table. If problem try old one. $functions = [ $get_078_to_latest_config, $get_prior_to_078_config, ]; } $values = []; foreach ($functions as $function) { if ($config = $function()) { $values = $config; break; } } if (count($values) === 0) { return false; } $CFG_GLPI = array_merge($CFG_GLPI, $values); if (isset($CFG_GLPI['priority_matrix'])) { $CFG_GLPI['priority_matrix'] = importArrayFromDB($CFG_GLPI['priority_matrix']); } if (isset($CFG_GLPI['devices_in_menu'])) { $CFG_GLPI['devices_in_menu'] = importArrayFromDB($CFG_GLPI['devices_in_menu']); } if (isset($CFG_GLPI['lock_item_list'])) { $CFG_GLPI['lock_item_list'] = importArrayFromDB($CFG_GLPI['lock_item_list']); } if (isset($CFG_GLPI['lock_lockprofile_id']) && $CFG_GLPI['lock_use_lock_item'] && $CFG_GLPI['lock_lockprofile_id'] > 0 && !isset($CFG_GLPI['lock_lockprofile'])) { $prof = new Profile(); $prof->getFromDB($CFG_GLPI['lock_lockprofile_id']); $prof->cleanProfile(); $CFG_GLPI['lock_lockprofile'] = $prof->fields; } // Path for icon of document type (web mode only) if (isset($CFG_GLPI['root_doc'])) { $CFG_GLPI['typedoc_icon_dir'] = $CFG_GLPI['root_doc'] . '/pics/icones'; } return true; } /** * Set config values : create or update entry * * @since 0.85 * * @param $context string context to get values (default for glpi is core) * @param $values array of config names to set * * @return void **/ static function setConfigurationValues($context, array $values = []) { $config = new self(); foreach ($values as $name => $value) { if ($config->getFromDBByCrit([ 'context' => $context, 'name' => $name ])) { $input = ['id' => $config->getID(), 'context' => $context, 'value' => $value]; $config->update($input); } else { $input = ['context' => $context, 'name' => $name, 'value' => $value]; $config->add($input); } } } /** * Delete config entries * * @since 0.85 * * @param $context string context to get values (default for glpi is core) * @param $values array of config names to delete * * @return void **/ static function deleteConfigurationValues($context, array $values = []) { $config = new self(); foreach ($values as $value) { if ($config->getFromDBByCrit([ 'context' => $context, 'name' => $value ])) { $config->delete(['id' => $config->getID()]); } } } function getRights($interface = 'central') { $values = parent::getRights(); unset($values[CREATE], $values[DELETE], $values[PURGE]); return $values; } /** * Get message that informs the user he's using a development version * * @param boolean $bg Display a background * * @return void */ public static function agreeDevMessage($bg = false) { $msg = '

' . __('You are using a development version, be careful!') . '
'; $msg .= "

"; $msg .= ""; return $msg; } /** * Get a cache adapter from configuration * * @param string $optname name of the configuration field * @param string $context name of the configuration context (default 'core') * @param boolean $psr16 Whether to return a PSR16 compliant obkect or not (since Laminas Translator is NOT PSR16 compliant). * * @return Psr\SimpleCache\CacheInterface|Laminas\Cache\Storage\StorageInterface object */ public static function getCache($optname, $context = 'core', $psr16 = true) { global $DB; /* Tested configuration values * * - {"adapter":"apcu"} * - {"adapter":"redis","options":{"server":{"host":"127.0.0.1"}},"plugins":["serializer"]} * - {"adapter":"filesystem"} * - {"adapter":"filesystem","options":{"cache_dir":"_cache_trans"},"plugins":["serializer"]} * - {"adapter":"dba"} * - {"adapter":"dba","options":{"pathname":"trans.db","handler":"flatfile"},"plugins":["serializer"]} * - {"adapter":"memcache","options":{"servers":["127.0.0.1"]}} * - {"adapter":"memcached","options":{"servers":["127.0.0.1"]}} * - {"adapter":"wincache"} * */ // Read configuration $conf = []; if ($DB && $DB->connected && $DB->fieldExists(self::getTable(), 'context') ) { $conf = self::getConfigurationValues($context, [$optname]); } // Adapter default options $opt = []; if (isset($conf[$optname])) { $opt = json_decode($conf[$optname], true); Toolbox::logDebug("CACHE CONFIG $optname", $opt); } //use memory adapter when called from tests if (defined('TU_USER') && !defined('CACHED_TESTS')) { $opt['adapter'] = 'memory'; } //force FS adapter for translations for tests if (defined('TU_USER') && $optname == 'cache_trans') { $opt['adapter'] = 'filesystem'; } if (!isset($opt['options']['namespace'])) { $namespace = "glpi_${optname}_" . GLPI_VERSION; if ($DB) { $namespace .= md5( (is_array($DB->dbhost) ? implode(' ', $DB->dbhost) : $DB->dbhost) . $DB->dbdefault ); } $opt['options']['namespace'] = $namespace; } if (!isset($opt['adapter'])) { if (function_exists('apcu_fetch')) { $opt['adapter'] = (version_compare(PHP_VERSION, '7.0.0') >= 0) ? 'apcu' : 'apc'; } else if (function_exists('wincache_ucache_add')) { $opt['adapter'] = 'wincache'; } else { $opt['adapter'] = 'filesystem'; } // Cannot skip integrity checks if 'adapter' was computed, // as computation result may differ for a different context (CLI VS web server). $skip_integrity_checks = false; $is_computed_config = true; } else { // Adapter names can be written using case variations. // see Laminas\Cache\Storage\AdapterPluginManager::$aliases $opt['adapter'] = strtolower($opt['adapter']); switch ($opt['adapter']) { // Cache adapters that can share their data accross processes case 'dba': case 'ext_mongo_db': case 'extmongodb': case 'filesystem': case 'memcache': case 'memcached': case 'mongo_db': case 'mongodb': case 'redis': $skip_integrity_checks = true; break; // Cache adapters that cannot share their data accross processes case 'apc': case 'apcu': case 'memory': case 'session': // wincache activation uses different configuration variable for CLI and web server // so it may not be available for all contexts case 'win_cache': case 'wincache': // zend server adapters are not available for CLI context case 'zend_server_disk': case 'zendserverdisk': case 'zend_server_shm': case 'zendservershm': default: $skip_integrity_checks = false; break; } $is_computed_config = false; } // Adapter specific options $ser = false; switch ($opt['adapter']) { case 'filesystem': if (!isset($opt['options']['cache_dir'])) { $opt['options']['cache_dir'] = $optname; } // Make configured directory relative to GLPI cache directory $opt['options']['cache_dir'] = GLPI_CACHE_DIR . '/' . $opt['options']['cache_dir']; if (!is_dir($opt['options']['cache_dir'])) { mkdir($opt['options']['cache_dir']); } $ser = true; break; case 'dba': if (!isset($opt['options']['pathname'])) { $opt['options']['pathname'] = "$optname.data"; } // Make configured path relative to GLPI cache directory $opt['options']['pathname'] = GLPI_CACHE_DIR . '/' . $opt['options']['pathname']; $ser = true; break; case 'redis': $ser = true; break; } // Some know plugins require data serialization if ($ser && !isset($opt['plugins'])) { $opt['plugins'] = ['serializer']; } // Create adapter try { $storage = Laminas\Cache\StorageFactory::factory($opt); } catch (Exception $e) { if (!$is_computed_config) { Toolbox::logError($e->getMessage()); } // fallback to filesystem cache system if adapter was not explicitely defined in config $fallback = false; if ($is_computed_config && $opt['adapter'] != 'filesystem') { $opt = [ 'adapter' => 'filesystem', 'options' => [ 'cache_dir' => GLPI_CACHE_DIR . '/' . $optname, 'namespace' => $namespace, ], 'plugins' => ['serializer'] ]; if (!is_dir($opt['options']['cache_dir'])) { mkdir($opt['options']['cache_dir']); } try { $storage = Laminas\Cache\StorageFactory::factory($opt); $fallback = true; } catch (Exception $e1) { Toolbox::logError($e1->getMessage()); if (isset($_SESSION['glpi_use_mode']) && Session::DEBUG_MODE == $_SESSION['glpi_use_mode']) { //preivous attempt has faled as well. Toolbox::logDebug($e->getMessage()); } } } if ($fallback === false) { $opt = ['adapter' => 'memory']; $storage = Laminas\Cache\StorageFactory::factory($opt); } if (isset($_SESSION['glpi_use_mode']) && Session::DEBUG_MODE == $_SESSION['glpi_use_mode']) { Toolbox::logDebug($e->getMessage()); } } if (defined('TU_USER')) { $skip_integrity_checks = true; } if ($psr16) { return new SimpleCache($storage, GLPI_CACHE_DIR, !$skip_integrity_checks); } else { return $storage; } } /** * Get available palettes * * @return array */ public function getPalettes() { $themes_files = scandir(GLPI_ROOT."/css/palettes/"); $themes = []; foreach ($themes_files as $file) { if (strpos($file, ".scss") !== false) { $name = substr($file, 1, -5); $themes[$name] = ucfirst($name); } } return $themes; } /** * Logs purge form * * @since 9.3 * * @return void */ function showFormLogs() { global $CFG_GLPI; if (!Config::canUpdate()) { return false; } echo ""; echo "
"; echo ""; echo ""; echo ""; echo ""; echo ""; echo ""; echo ""; echo ""; echo ""; echo ""; echo ""; echo ""; echo ""; echo ""; echo ""; echo ""; echo ""; echo ""; echo ""; echo ""; echo ""; echo ""; echo ""; echo ""; echo ""; echo ""; echo ""; echo ""; echo ""; echo ""; echo ""; echo ""; echo ""; echo ""; echo ""; echo ""; echo ""; echo ""; echo ""; echo ""; echo ""; echo ""; echo ""; echo ""; echo ""; echo ""; echo ""; echo ""; echo ""; echo ""; echo "
".__("Logs purge configuration"). "
".__("Change all").""; echo Html::scriptBlock("function form_init_all(value) { $('#purgelogs_form .purgelog_interval select').val(value).trigger('change');; }"); self::showLogsInterval( 'init_all', 0, [ 'on_change' => "form_init_all(this.value);", 'class' => '' ] ); echo "
".__("General")."
".__("Add/update relation between items"). ""; self::showLogsInterval('purge_addrelation', $CFG_GLPI["purge_addrelation"]); echo "".__("Delete relation between items").""; self::showLogsInterval('purge_deleterelation', $CFG_GLPI["purge_deleterelation"]); echo "
".__("Add the item").""; self::showLogsInterval('purge_createitem', $CFG_GLPI["purge_createitem"]); echo "".__("Delete the item").""; self::showLogsInterval('purge_deleteitem', $CFG_GLPI["purge_deleteitem"]); echo "
".__("Restore the item").""; self::showLogsInterval('purge_restoreitem', $CFG_GLPI["purge_restoreitem"]); echo "".__('Update the item').""; self::showLogsInterval('purge_updateitem', $CFG_GLPI["purge_updateitem"]); echo "
".__("Comments").""; self::showLogsInterval('purge_comments', $CFG_GLPI["purge_comments"]); echo "".__("Last update").""; self::showLogsInterval('purge_datemod', $CFG_GLPI["purge_datemod"]); echo "
". __("Plugins").""; self::showLogsInterval('purge_plugins', $CFG_GLPI["purge_plugins"]); echo ""; echo "
"._n('Software', 'Software', Session::getPluralNumber())."
". __("Installation/uninstallation of software on items").""; self::showLogsInterval('purge_item_software_install', $CFG_GLPI["purge_item_software_install"]); echo "".__("Installation/uninstallation versions on softwares").""; self::showLogsInterval('purge_software_version_install', $CFG_GLPI["purge_software_version_install"]); echo "
". __("Add/Remove items from software versions").""; self::showLogsInterval('purge_software_item_install', $CFG_GLPI["purge_software_item_install"]); echo "
".__('Financial and administrative information'). "
". __("Add financial information to an item").""; self::showLogsInterval('purge_infocom_creation', $CFG_GLPI["purge_infocom_creation"]); echo "
".User::getTypeName(Session::getPluralNumber())."
". __("Add/remove profiles to users").""; self::showLogsInterval('purge_profile_user', $CFG_GLPI["purge_profile_user"]); echo "".__("Add/remove groups to users").""; self::showLogsInterval('purge_group_user', $CFG_GLPI["purge_group_user"]); echo "
". __("User authentication method changes").""; self::showLogsInterval('purge_user_auth_changes', $CFG_GLPI["purge_user_auth_changes"]); echo "".__("Deleted user in LDAP directory"). ""; self::showLogsInterval('purge_userdeletedfromldap', $CFG_GLPI["purge_userdeletedfromldap"]); echo "
"._n('Component', 'Components', Session::getPluralNumber())."
".__("Add component").""; self::showLogsInterval('purge_adddevice', $CFG_GLPI["purge_adddevice"]); echo "".__("Update component").""; self::showLogsInterval('purge_updatedevice', $CFG_GLPI["purge_updatedevice"]); echo "
".__("Disconnect a component"). ""; self::showLogsInterval('purge_disconnectdevice', $CFG_GLPI["purge_disconnectdevice"]); echo "".__("Connect a component").""; self::showLogsInterval('purge_connectdevice', $CFG_GLPI["purge_connectdevice"]); echo "
".__("Delete component"). ""; self::showLogsInterval('purge_deletedevice', $CFG_GLPI["purge_deletedevice"]); echo "
".__("All sections")."
".__("Purge all log entries").""; self::showLogsInterval('purge_all', $CFG_GLPI["purge_all"]); echo "
"; echo ""; echo"
"; Html::closeForm(); } /** * Show intervals for logs purge * * @since 9.3 * * @param string $name Parameter name * @param mixed $value Parameter value * @param array $options Options * * @return void */ static function showLogsInterval($name, $value, $options = []) { $values = [ self::DELETE_ALL => __("Delete all"), self::KEEP_ALL => __("Keep all"), ]; for ($i = 1; $i < 121; $i++) { $values[$i] = sprintf( _n( "Delete if older than %s month", "Delete if older than %s months", $i ), $i ); } $options = array_merge([ 'value' => $value, 'display' => false, 'class' => 'purgelog_interval' ], $options); $out = "
"; $out.= Dropdown::showFromArray($name, $values, $options); $out.= "
"; echo $out; } /** * Security policy form * * @since 9.5.0 * * @return void */ function showFormSecurity() { global $CFG_GLPI; if (!Config::canUpdate()) { return false; } $rand = mt_rand(); echo '
'; echo ''; echo ''; echo ''; echo ''; echo ''; echo ''; echo ''; echo ''; echo ''; echo ''; echo ''; echo ''; echo ''; echo ''; echo ''; echo ''; echo ''; echo ''; echo ''; echo ''; echo ''; echo ''; echo ''; echo ''; echo ''; echo ''; echo ''; echo ''; echo ''; echo ''; echo ''; echo ''; echo ''; echo ''; echo ''; echo ''; echo ''; echo ''; echo ''; echo ''; echo ''; echo '
' . __('Security setup') . '
' . __('Password security policy') . '
'; echo ''; echo ''; Dropdown::showYesNo( 'use_password_security', $CFG_GLPI['use_password_security'], -1, [ 'rand' => $rand, ] ); echo ''; echo ''; echo ''; Dropdown::showNumber( 'password_min_length', [ 'value' => $CFG_GLPI['password_min_length'], 'min' => 4, 'max' => 30, 'rand' => $rand ] ); echo '
'; echo ''; echo ''; Dropdown::showYesNo( 'password_need_number', $CFG_GLPI['password_need_number'], -1, [ 'rand' => $rand, ] ); echo ''; echo ''; echo ''; Dropdown::showYesNo( 'password_need_letter', $CFG_GLPI['password_need_letter'], -1, [ 'rand' => $rand, ] ); echo '
'; echo ''; echo ''; Dropdown::showYesNo( 'password_need_caps', $CFG_GLPI['password_need_caps'], -1, [ 'rand' => $rand, ] ); echo ''; echo ''; echo ''; Dropdown::showYesNo( 'password_need_symbol', $CFG_GLPI['password_need_symbol'], -1, [ 'rand' => $rand, ] ); echo '
' . __('Password expiration policy') . '
'; echo ''; echo ''; Dropdown::showNumber( 'password_expiration_delay', [ 'value' => $CFG_GLPI['password_expiration_delay'], 'min' => 30, 'max' => 365, 'step' => 15, 'toadd' => [-1 => __('Never')], 'rand' => $rand ] ); echo ''; echo ''; echo ''; Dropdown::showNumber( 'password_expiration_notice', [ 'value' => $CFG_GLPI['password_expiration_notice'], 'min' => 0, 'max' => 30, 'step' => 1, 'toadd' => [-1 => __('Notification disabled')], 'rand' => $rand ] ); echo '
'; echo ''; echo ''; Dropdown::showNumber( 'password_expiration_lock_delay', [ 'value' => $CFG_GLPI['password_expiration_lock_delay'], 'min' => 0, 'max' => 30, 'step' => 1, 'toadd' => [-1 => __('Do not deactivate')], 'rand' => $rand ] ); echo '
'; echo ''; echo '
'; Html::closeForm(); } public function rawSearchOptions() { $tab = []; $tab[] = [ 'id' => 'common', 'name' => __('Characteristics') ]; $tab[] = [ 'id' => 1, 'table' => $this->getTable(), 'field' => 'value', 'name' => __('Value'), 'massiveaction' => false ]; return $tab; } function getLogTypeID() { return [$this->getType(), 1]; } public function post_updateItem($history = 1) { global $DB; // Check if password expiration mechanism has been activated if ($this->fields['name'] == 'password_expiration_delay' && array_key_exists('value', $this->oldvalues) && (int)$this->oldvalues['value'] === -1) { // As passwords will now expire, consider that "now" is the reference date of expiration delay $DB->update( User::getTable(), ['password_last_update' => $_SESSION['glpi_currenttime']], ['authtype' => Auth::DB_GLPI] ); // Activate passwordexpiration automated task $DB->update( CronTask::getTable(), ['state' => 1,], ['name' => 'passwordexpiration'] ); } // Keep it at the end as it alter $this->oldvalues if (count($this->oldvalues)) { foreach ($this->oldvalues as &$value) { $value = $this->fields['name'] . ' ' . $value; } Log::constructHistory($this, $this->oldvalues, $this->fields); } } /** * Get the GLPI Config without unsafe keys like passwords and emails (true on $safer) * * @param boolean $safer do we need to clean more (avoid emails disclosure) * @return array of $CFG_GLPI without unsafe keys * * @since 9.5 */ public static function getSafeConfig($safer = false) { global $CFG_GLPI; $excludedKeys = array_flip(self::$undisclosedFields); $safe_config = array_diff_key($CFG_GLPI, $excludedKeys); if ($safer) { $excludedKeys = array_flip(self::$saferUndisclosedFields); $safe_config = array_diff_key($safe_config, $excludedKeys); } return $safe_config; } static function getIcon() { return "fas fa-cog"; } /** * Get UUID * * @param string $type UUID type (e.g. 'instance' or 'registration') * * @return string */ public static final function getUuid($type) { $conf = self::getConfigurationValues('core', [$type . '_uuid']); $uuid = null; if (!isset($conf[$type . '_uuid']) || empty($conf[$type . '_uuid'])) { $uuid = self::generateUuid($type); } else { $uuid = $conf[$type . '_uuid']; } return $uuid; } /** * Generates an unique identifier and store it * * @param string $type UUID type (e.g. 'instance' or 'registration') * * @return string */ public static final function generateUuid($type) { $uuid = Toolbox::getRandomString(40); self::setConfigurationValues('core', [$type . '_uuid' => $uuid]); return $uuid; } }