1<?php 2// Copyright (C) 2010-2018 Combodo SARL 3// 4// This file is part of iTop. 5// 6// iTop is free software; you can redistribute it and/or modify 7// it under the terms of the GNU Affero General Public License as published by 8// the Free Software Foundation, either version 3 of the License, or 9// (at your option) any later version. 10// 11// iTop is distributed in the hope that it will be useful, 12// but WITHOUT ANY WARRANTY; without even the implied warranty of 13// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14// GNU Affero General Public License for more details. 15// 16// You should have received a copy of the GNU Affero General Public License 17// along with iTop. If not, see <http://www.gnu.org/licenses/> 18 19 20define('ITOP_APPLICATION', 'iTop'); 21define('ITOP_APPLICATION_SHORT', 'iTop'); 22define('ITOP_VERSION', '2.6.1'); 23define('ITOP_REVISION', '4463'); 24define('ITOP_BUILD_DATE', '2019-03-25 16:49:30'); 25 26define('ACCESS_USER_WRITE', 1); 27define('ACCESS_ADMIN_WRITE', 2); 28define('ACCESS_FULL', ACCESS_USER_WRITE | ACCESS_ADMIN_WRITE); 29define('ACCESS_READONLY', 0); 30 31/** 32 * Configuration read/write 33 * 34 * @copyright Copyright (C) 2010-2018 Combodo SARL 35 * @license http://opensource.org/licenses/AGPL-3.0 36 */ 37 38require_once('coreexception.class.inc.php'); 39require_once('attributedef.class.inc.php'); // For the defines 40require_once('simplecrypt.class.inc.php'); 41 42class ConfigException extends CoreException 43{ 44} 45 46// was utf8 but it only supports BMP chars (https://dev.mysql.com/doc/refman/5.5/en/charset-unicode-utf8mb4.html) 47// so we switched to utf8mb4 in iTop 2.5, adding dependency to MySQL 5.5.3 48// The config params db_character_set and db_collation were introduced as a temporary workaround and removed in iTop 2.5 49// now everything uses those fixed value ! 50define('DEFAULT_CHARACTER_SET', 'utf8mb4'); 51define('DEFAULT_COLLATION', 'utf8mb4_unicode_ci'); 52 53define('DEFAULT_LOG_GLOBAL', true); 54define('DEFAULT_LOG_NOTIFICATION', true); 55define('DEFAULT_LOG_ISSUE', true); 56define('DEFAULT_LOG_WEB_SERVICE', true); 57 58define('DEFAULT_QUERY_CACHE_ENABLED', true); 59 60 61define('DEFAULT_MIN_DISPLAY_LIMIT', 10); 62define('DEFAULT_MAX_DISPLAY_LIMIT', 15); 63define('DEFAULT_STANDARD_RELOAD_INTERVAL', 5 * 60); 64define('DEFAULT_FAST_RELOAD_INTERVAL', 1 * 60); 65define('DEFAULT_SECURE_CONNECTION_REQUIRED', false); 66define('DEFAULT_ALLOWED_LOGIN_TYPES', 'form|basic|external'); 67define('DEFAULT_EXT_AUTH_VARIABLE', '$_SERVER[\'REMOTE_USER\']'); 68define('DEFAULT_ENCRYPTION_KEY', '@iT0pEncr1pti0n!'); // We'll use a random generated key later (if possible) 69define('DEFAULT_ENCRYPTION_LIB', 'Mcrypt'); // We'll define the best encryption available later 70/** 71 * Config 72 * configuration data (this class cannot not be localized, because it is responsible for loading the dictionaries) 73 * 74 * @package iTopORM 75 * 76 * @see \MetaModel::GetConfig() to get the config, if the metamodel was already loaded 77 * @see utils::GetConfig() to load config from the current env, if metamodel is not loaded 78 */ 79class Config 80{ 81 //protected $m_bIsLoaded = false; 82 protected $m_sFile = ''; 83 84 protected $m_aAppModules; 85 protected $m_aDataModels; 86 protected $m_aWebServiceCategories; 87 protected $m_aAddons; 88 89 protected $m_aModuleSettings; 90 91 /** 92 * New way to store the settings ! 93 * 94 * @var array 95 * @since 2.5 db* variables 96 */ 97 protected $m_aSettings = array( 98 'app_env_label' => array( 99 'type' => 'string', 100 'description' => 'Label displayed to describe the current application environment, defaults to the environment name (e.g. "production")', 101 'default' => '', 102 'value' => '', 103 'source_of_value' => '', 104 'show_in_conf_sample' => false, 105 ), 106 'app_root_url' => array( 107 'type' => 'string', 108 'description' => 'Root URL used for navigating within the application, or from an email to the application (you can put $SERVER_NAME$ as a placeholder for the server\'s name)', 109 'default' => '', 110 'value' => '', 111 'source_of_value' => '', 112 'show_in_conf_sample' => true, 113 ), 114 'app_icon_url' => array( 115 'type' => 'string', 116 'description' => 'Hyperlink to redirect the user when clicking on the application icon (in the main window, or login/logoff pages)', 117 'default' => 'http://www.combodo.com/itop', 118 'value' => '', 119 'source_of_value' => '', 120 'show_in_conf_sample' => false, 121 ), 122 'db_host' => array( 123 'type' => 'string', 124 'default' => null, 125 'value' => '', 126 'source_of_value' => '', 127 'show_in_conf_sample' => true, 128 ), 129 'db_user' => array( 130 'type' => 'string', 131 'default' => null, 132 'value' => '', 133 'source_of_value' => '', 134 'show_in_conf_sample' => true, 135 ), 136 'db_pwd' => array( 137 'type' => 'string', 138 'default' => null, 139 'value' => '', 140 'source_of_value' => '', 141 'show_in_conf_sample' => true, 142 ), 143 'db_name' => array( 144 'type' => 'string', 145 'default' => null, 146 'value' => '', 147 'source_of_value' => '', 148 'show_in_conf_sample' => true, 149 ), 150 'db_subname' => array( 151 'type' => 'string', 152 'default' => null, 153 'value' => '', 154 'source_of_value' => '', 155 'show_in_conf_sample' => true, 156 ), 157 'db_tls.enabled' => array( 158 'type' => 'bool', 159 'description' => 'If true then the connection to the DB will be encrypted', 160 'default' => false, 161 'value' => false, 162 'source_of_value' => '', 163 'show_in_conf_sample' => false, 164 ), 165 'db_tls.ca' => array( 166 'type' => 'string', 167 'description' => 'Path to certificate authority file for SSL', 168 'default' => null, 169 'value' => '', 170 'source_of_value' => '', 171 'show_in_conf_sample' => false, 172 ), 173 'db_character_set' => array( // @deprecated to remove in 2.7 ? N°1001 utf8mb4 switch 174 'type' => 'string', 175 'description' => 'Deprecated since iTop 2.5 : now using utf8mb4', 176 'default' => 'DEPRECATED_2.5', 177 'value' => '', 178 'source_of_value' => '', 179 'show_in_conf_sample' => false, 180 ), 181 'db_collation' => array( // @deprecated to remove in 2.7 ? N°1001 utf8mb4 switch 182 'type' => 'string', 183 'description' => 'Deprecated since iTop 2.5 : now using utf8mb4_unicode_ci', 184 'default' => 'DEPRECATED_2.5', 185 'value' => '', 186 'source_of_value' => '', 187 'show_in_conf_sample' => false, 188 ), 189 'skip_check_to_write' => array( 190 'type' => 'bool', 191 'description' => 'Disable data format and integrity checks to boost up data load (insert or update)', 192 'default' => false, 193 'value' => false, 194 'source_of_value' => '', 195 'show_in_conf_sample' => false, 196 ), 197 'skip_check_ext_keys' => array( 198 'type' => 'bool', 199 'description' => 'Disable external key check when checking the value of attributes', 200 'default' => false, 201 'value' => false, 202 'source_of_value' => '', 203 'show_in_conf_sample' => false, 204 ), 205 'skip_strong_security' => array( 206 'type' => 'bool', 207 'description' => 'Disable strong security - TEMPORARY: this flag should be removed when we are more confident in the recent change in security', 208 'default' => true, 209 'value' => true, 210 'source_of_value' => '', 211 'show_in_conf_sample' => false, 212 ), 213 'query_optimization_enabled' => array( 214 'type' => 'bool', 215 'description' => 'The queries are optimized based on the assumption that the DB integrity has been preserved. By disabling the optimization one can ensure that the fetched data is clean... but this can be really slower or not usable at all (some queries will exceed the allowed number of joins in MySQL: 61!)', 216 'default' => true, 217 'value' => true, 218 'source_of_value' => '', 219 'show_in_conf_sample' => false, 220 ), 221 'query_indentation_enabled' => array( 222 'type' => 'bool', 223 'description' => 'For developers: format the SQL queries for human analysis', 224 'default' => false, 225 'value' => false, 226 'source_of_value' => '', 227 'show_in_conf_sample' => false, 228 ), 229 'disable_mandatory_ext_keys' => array( 230 'type' => 'bool', 231 'description' => 'For developers: allow every external keys to be undefined', 232 'default' => false, 233 'value' => false, 234 'source_of_value' => '', 235 'show_in_conf_sample' => false, 236 ), 237 'graphviz_path' => array( 238 'type' => 'string', 239 'description' => 'Path to the Graphviz "dot" executable for graphing objects lifecycle', 240 'default' => '/usr/bin/dot', 241 'value' => '', 242 'source_of_value' => '', 243 'show_in_conf_sample' => true, 244 ), 245 'php_path' => array( 246 'type' => 'string', 247 'description' => 'Path to the php executable in CLI mode', 248 'default' => 'php', 249 'value' => 'php', 250 'source_of_value' => '', 251 'show_in_conf_sample' => true, 252 ), 253 'session_name' => array( 254 'type' => 'string', 255 'description' => 'The name of the cookie used to store the PHP session id', 256 'default' => 'iTop', 257 'value' => '', 258 'source_of_value' => '', 259 'show_in_conf_sample' => true, 260 ), 261 'max_combo_length' => array( 262 'type' => 'integer', 263 'description' => 'The maximum number of elements in a drop-down list. If more then an autocomplete will be used', 264 'default' => 50, 265 'value' => 50, 266 'source_of_value' => '', 267 'show_in_conf_sample' => false, 268 ), 269 'min_autocomplete_chars' => array( 270 'type' => 'integer', 271 'description' => 'The minimum number of characters to type in order to trigger the "autocomplete" behavior', 272 'default' => 2, 273 'value' => 2, 274 'source_of_value' => '', 275 'show_in_conf_sample' => false, 276 ), 277 'allow_menu_on_linkset' => array( 278 'type' => 'bool', 279 'description' => 'Display Action menus in view mode on any LinkedSet with edit_mode != none', 280 'default' => false, 281 'value' => false, 282 'source_of_value' => '', 283 'show_in_conf_sample' => false, 284 ), 285 'allow_target_creation' => array( 286 'type' => 'bool', 287 'description' => 'Displays the + button on external keys to create target objects', 288 'default' => true, 289 'value' => true, 290 'source_of_value' => '', 291 'show_in_conf_sample' => false, 292 ), 293 // Levels that trigger a confirmation in the CSV import/synchro wizard 294 'csv_import_min_object_confirmation' => array( 295 'type' => 'integer', 296 'description' => 'Minimum number of objects to check for the confirmation percentages', 297 'default' => 3, 298 'value' => 3, 299 'source_of_value' => '', 300 'show_in_conf_sample' => false, 301 ), 302 'csv_import_errors_percentage' => array( 303 'type' => 'integer', 304 'description' => 'Percentage of errors that trigger a confirmation in the CSV import', 305 'default' => 50, 306 'value' => 50, 307 'source_of_value' => '', 308 'show_in_conf_sample' => false, 309 ), 310 'csv_import_modifications_percentage' => array( 311 'type' => 'integer', 312 'description' => 'Percentage of modifications that trigger a confirmation in the CSV import', 313 'default' => 50, 314 'value' => 50, 315 'source_of_value' => '', 316 'show_in_conf_sample' => false, 317 ), 318 'csv_import_creations_percentage' => array( 319 'type' => 'integer', 320 'description' => 'Percentage of creations that trigger a confirmation in the CSV import', 321 'default' => 50, 322 'value' => 50, 323 'source_of_value' => '', 324 'show_in_conf_sample' => false, 325 ), 326 'csv_import_history_display' => array( 327 'type' => 'bool', 328 'description' => 'Display the history tab in the import wizard', 329 'default' => false, 330 'value' => false, 331 'source_of_value' => '', 332 'show_in_conf_sample' => true, 333 ), 334 'access_mode' => array( 335 'type' => 'integer', 336 'description' => 'Access mode: ACCESS_READONLY = 0, ACCESS_ADMIN_WRITE = 2, ACCESS_FULL = 3', 337 'default' => ACCESS_FULL, 338 'value' => ACCESS_FULL, 339 'source_of_value' => '', 340 'show_in_conf_sample' => true, 341 ), 342 'access_message' => array( 343 'type' => 'string', 344 'description' => 'Message displayed to the users when there is any access restriction', 345 'default' => 'iTop is temporarily frozen, please wait... (the admin team)', 346 'value' => '', 347 'source_of_value' => '', 348 'show_in_conf_sample' => true, 349 ), 350 'online_help' => array( 351 'type' => 'string', 352 'description' => 'Hyperlink to the online-help web page', 353 'default' => 'http://www.combodo.com/itop-help', 354 'value' => '', 355 'source_of_value' => '', 356 'show_in_conf_sample' => true, 357 ), 358 'log_usage' => array( 359 'type' => 'bool', 360 'description' => 'Log the usage of the application (i.e. the date/time and the user name of each login)', 361 'default' => false, 362 'value' => false, 363 'source_of_value' => '', 364 'show_in_conf_sample' => false, 365 ), 366 'log_rest_service' => array( 367 'type' => 'bool', 368 'description' => 'Log the usage of the REST/JSON service', 369 'default' => false, 370 'value' => false, 371 'source_of_value' => '', 372 'show_in_conf_sample' => false, 373 ), 374 'synchro_trace' => array( 375 'type' => 'string', 376 'description' => 'Synchronization details: none, display, save (includes \'display\')', 377 'default' => 'none', 378 'value' => 'none', 379 'source_of_value' => '', 380 'show_in_conf_sample' => true, 381 ), 382 'link_set_item_separator' => array( 383 'type' => 'string', 384 'description' => 'Link set from string: line separator', 385 'default' => '|', 386 'value' => '|', 387 'source_of_value' => '', 388 'show_in_conf_sample' => true, 389 ), 390 'link_set_attribute_separator' => array( 391 'type' => 'string', 392 'description' => 'Link set from string: attribute separator', 393 'default' => ';', 394 'value' => ';', 395 'source_of_value' => '', 396 'show_in_conf_sample' => true, 397 ), 398 'link_set_value_separator' => array( 399 'type' => 'string', 400 'description' => 'Link set from string: value separator (between the attcode and the value itself', 401 'default' => ':', 402 'value' => ':', 403 'source_of_value' => '', 404 'show_in_conf_sample' => true, 405 ), 406 'link_set_attribute_qualifier' => array( 407 'type' => 'string', 408 'description' => 'Link set from string: attribute qualifier (encloses both the attcode and the value)', 409 'default' => "'", 410 'value' => "'", 411 'source_of_value' => '', 412 'show_in_conf_sample' => true, 413 ), 414 'tag_set_item_separator' => array( 415 'type' => 'string', 416 'description' => 'Tag set from string: tag label separator', 417 'default' => '|', 418 'value' => '|', 419 'source_of_value' => '', 420 'show_in_conf_sample' => true, 421 ), 422 'cron_max_execution_time' => array( 423 'type' => 'integer', 424 'description' => 'Duration (seconds) of the page cron.php, must be shorter than php setting max_execution_time and shorter than the web server response timeout', 425 'default' => 600, 426 'value' => 600, 427 'source_of_value' => '', 428 'show_in_conf_sample' => true, 429 ), 430 'cron_sleep' => array( 431 'type' => 'integer', 432 'description' => 'Duration (seconds) before cron.php checks again if something must be done', 433 'default' => 2, 434 'value' => 2, 435 'source_of_value' => '', 436 'show_in_conf_sample' => false, 437 ), 438 'async_task_retries' => array( 439 'type' => 'array', 440 'description' => 'Automatic retries of asynchronous tasks in case of failure (per class)', 441 'default' => array('AsyncSendEmail' => array('max_retries' => 0, 'retry_delay' => 600)), 442 'value' => false, 443 'source_of_value' => '', 444 'show_in_conf_sample' => false, 445 ), 446 'email_asynchronous' => array( 447 'type' => 'bool', 448 'description' => 'If set, the emails are sent off line, which requires cron.php to be activated. Exception: some features like the email test utility will force the serialized mode', 449 'default' => false, 450 'value' => false, 451 'source_of_value' => '', 452 'show_in_conf_sample' => true, 453 ), 454 'email_transport' => array( 455 'type' => 'string', 456 'description' => 'Mean to send emails: PHPMail (uses the function mail()) or SMTP (implements the client protocol)', 457 'default' => "PHPMail", 458 'value' => "PHPMail", 459 'source_of_value' => '', 460 'show_in_conf_sample' => true, 461 ), 462 'email_transport_smtp.host' => array( 463 'type' => 'string', 464 'description' => 'host name or IP address (optional)', 465 'default' => "localhost", 466 'value' => "localhost", 467 'source_of_value' => '', 468 'show_in_conf_sample' => false, 469 ), 470 'email_transport_smtp.port' => array( 471 'type' => 'integer', 472 'description' => 'port number (optional)', 473 'default' => 25, 474 'value' => 25, 475 'source_of_value' => '', 476 'show_in_conf_sample' => false, 477 ), 478 'email_transport_smtp.encryption' => array( 479 'type' => 'string', 480 'description' => 'tls or ssl (optional)', 481 'default' => "", 482 'value' => "", 483 'source_of_value' => '', 484 'show_in_conf_sample' => false, 485 ), 486 'email_transport_smtp.username' => array( 487 'type' => 'string', 488 'description' => 'Authentication user (optional)', 489 'default' => "", 490 'value' => "", 491 'source_of_value' => '', 492 'show_in_conf_sample' => false, 493 ), 494 'email_transport_smtp.password' => array( 495 'type' => 'string', 496 'description' => 'Authentication password (optional)', 497 'default' => "", 498 'value' => "", 499 'source_of_value' => '', 500 'show_in_conf_sample' => false, 501 ), 502 'email_css' => array( 503 'type' => 'string', 504 'description' => 'CSS that will override the standard stylesheet used for the notifications', 505 'default' => "", 506 'value' => "", 507 'source_of_value' => '', 508 'show_in_conf_sample' => false, 509 ), 510 'email_default_sender_address' => array( 511 'type' => 'string', 512 'description' => 'Default address provided in the email from header field.', 513 'default' => "", 514 'value' => "", 515 'source_of_value' => '', 516 'show_in_conf_sample' => true, 517 ), 518 'email_default_sender_label' => array( 519 'type' => 'string', 520 'description' => 'Default label provided in the email from header field.', 521 'default' => "", 522 'value' => "", 523 'source_of_value' => '', 524 'show_in_conf_sample' => true, 525 ), 526 'apc_cache.enabled' => array( 527 'type' => 'bool', 528 'description' => 'If set, the APC cache is allowed (the PHP extension must also be active)', 529 'default' => true, 530 'value' => true, 531 'source_of_value' => '', 532 'show_in_conf_sample' => true, 533 ), 534 'apc_cache.query_ttl' => array( 535 'type' => 'integer', 536 'description' => 'Time to live set in APC for the prepared queries (seconds - 0 means no timeout)', 537 'default' => 3600, 538 'value' => 3600, 539 'source_of_value' => '', 540 'show_in_conf_sample' => true, 541 ), 542 'apc_cache_emulation.max_entries' => array( 543 'type' => 'integer', 544 'description' => 'Maximum number of cache entries (0 means no limit)', 545 'default' => 1000, 546 'value' => 1000, 547 'source_of_value' => '', 548 'show_in_conf_sample' => false, 549 ), 550 'timezone' => array( 551 'type' => 'string', 552 'description' => 'Timezone (reference: http://php.net/manual/en/timezones.php). If empty, it will be left unchanged and MUST be explicitly configured in PHP', 553 // examples... not used (nor 'description') 554 'examples' => array( 555 'America/Sao_Paulo', 556 'America/New_York (standing for EDT)', 557 'America/Los_Angeles (standing for PDT)', 558 'Asia/Istanbul', 559 'Asia/Singapore', 560 'Africa/Casablanca', 561 'Australia/Sydney' 562 ), 563 'default' => 'Europe/Paris', 564 'value' => 'Europe/Paris', 565 'source_of_value' => '', 566 'show_in_conf_sample' => true, 567 ), 568 'cas_include_path' => array( 569 'type' => 'string', 570 'description' => 'The path where to find the phpCAS library', 571 // examples... not used (nor 'description') 572 'default' => '/usr/share/php', 573 'value' => '/usr/share/php', 574 'source_of_value' => '', 575 'show_in_conf_sample' => true, 576 ), 577 'cas_version' => array( 578 'type' => 'string', 579 'description' => 'The CAS protocol version to use: "1.0" (CAS v1), "2.0" (CAS v2) or "S1" (SAML V1) )', 580 // examples... not used (nor 'description') 581 'default' => '2.0', 582 'value' => '', 583 'source_of_value' => '', 584 'show_in_conf_sample' => false, 585 ), 586 'cas_host' => array( 587 'type' => 'string', 588 'description' => 'The name of the CAS host', 589 // examples... not used (nor 'description') 590 'default' => '', 591 'value' => '', 592 'source_of_value' => '', 593 'show_in_conf_sample' => false, 594 ), 595 'cas_port' => array( 596 'type' => 'integer', 597 'description' => 'The port used by the CAS server', 598 // examples... not used (nor 'description') 599 'default' => 443, 600 'value' => 443, 601 'source_of_value' => '', 602 'show_in_conf_sample' => false, 603 ), 604 'cas_context' => array( 605 'type' => 'string', 606 'description' => 'The CAS context', 607 // examples... not used (nor 'description') 608 'default' => '', 609 'value' => '', 610 'source_of_value' => '', 611 'show_in_conf_sample' => false, 612 ), 613 'cas_server_ca_cert_path' => array( 614 'type' => 'string', 615 'description' => 'The path where to find the certificate of the CA for validating the certificate of the CAS server', 616 // examples... not used (nor 'description') 617 'default' => '', 618 'value' => '', 619 'source_of_value' => '', 620 'show_in_conf_sample' => false, 621 ), 622 'cas_logout_redirect_service' => array( 623 'type' => 'string', 624 'description' => 'The redirect service (URL) to use when logging-out with CAS', 625 // examples... not used (nor 'description') 626 'default' => '', 627 'value' => '', 628 'source_of_value' => '', 629 'show_in_conf_sample' => false, 630 ), 631 'cas_memberof' => array( 632 'type' => 'string', 633 'description' => 'A semicolon separated list of group names that the user must be member of (works only with SAML - e.g. cas_version=> "S1")', 634 // examples... not used (nor 'description') 635 'default' => '', 636 'value' => '', 637 'source_of_value' => '', 638 'show_in_conf_sample' => false, 639 ), 640 'cas_user_synchro' => array( 641 'type' => 'bool', 642 'description' => 'Whether or not to synchronize users with CAS/LDAP', 643 // examples... not used (nor 'description') 644 'default' => 0, 645 'value' => 0, 646 'source_of_value' => '', 647 'show_in_conf_sample' => false, 648 ), 649 'cas_update_profiles' => array( 650 'type' => 'bool', 651 'description' => 'Whether or not to update the profiles of an existing user from the CAS information', 652 // examples... not used (nor 'description') 653 'default' => 0, 654 'value' => 0, 655 'source_of_value' => '', 656 'show_in_conf_sample' => false, 657 ), 658 'cas_profile_pattern' => array( 659 'type' => 'string', 660 'description' => 'A regular expression pattern to extract the name of the iTop profile from the name of an LDAP/CAS group', 661 // examples... not used (nor 'description') 662 'default' => '/^cn=([^,]+),/', 663 'value' => '/^cn=([^,]+),/', 664 'source_of_value' => '', 665 'show_in_conf_sample' => false, 666 ), 667 'cas_default_profiles' => array( 668 'type' => 'string', 669 'description' => 'A semi-colon separated list of iTop Profiles to use when creating a new user if no profile is retrieved from CAS', 670 // examples... not used (nor 'description') 671 'default' => 'Portal user', 672 'value' => 'Portal user', 673 'source_of_value' => '', 674 'show_in_conf_sample' => false, 675 ), 676 'cas_debug' => array( 677 'type' => 'bool', 678 'description' => 'Activate the CAS debug', 679 // examples... not used (nor 'description') 680 'default' => false, 681 'value' => false, 682 'source_of_value' => '', 683 'show_in_conf_sample' => false, 684 ), 685 'forgot_password' => array( 686 'type' => 'bool', 687 'description' => 'Enable the "Forgot password" feature', 688 // examples... not used (nor 'description') 689 'default' => true, 690 'value' => true, 691 'source_of_value' => '', 692 'show_in_conf_sample' => false, 693 ), 694 'forgot_password_from' => array( 695 'type' => 'string', 696 'description' => 'Sender email address for the "forgot password" feature. If empty, defaults to the recipient\'s email address.', 697 // examples... not used (nor 'description') 698 'default' => '', 699 'value' => '', 700 'source_of_value' => '', 701 'show_in_conf_sample' => false, 702 ), 703 'deadline_format' => array( 704 'type' => 'string', 705 'description' => 'The format used for displaying "deadline" attributes: any string with the following placeholders: $date$, $difference$', 706 // examples... $date$ ($deadline$) 707 'default' => '$difference$', 708 'value' => '$difference$', 709 'source_of_value' => '', 710 'show_in_conf_sample' => true, 711 ), 712 'buttons_position' => array( 713 'type' => 'string', 714 'description' => 'Position of the forms buttons: bottom | top | both', 715 // examples... not used 716 'default' => 'both', 717 'value' => 'both', 718 'source_of_value' => '', 719 'show_in_conf_sample' => true, 720 ), 721 'shortcut_actions' => array( 722 'type' => 'string', 723 'description' => 'Actions that are available as direct buttons next to the "Actions" menu', 724 // examples... not used 725 'default' => 'UI:Menu:Modify,UI:Menu:New', 726 'value' => 'UI:Menu:Modify', 727 'source_of_value' => '', 728 'show_in_conf_sample' => true, 729 ), 730 'complex_actions_limit' => array( 731 'type' => 'integer', 732 'description' => 'Display the "actions" menu items that require long computation only if the list of objects is contains less objects than this number (0 means no limit)', 733 // examples... not used 734 'default' => 50, 735 'value' => 50, 736 'source_of_value' => '', 737 'show_in_conf_sample' => false, 738 ), 739 'synchro_prevent_delete_all' => array( 740 'type' => 'bool', 741 'description' => 'Stop the synchro if all the replicas of a data source become obsolete at the same time.', 742 // examples... not used 743 'default' => true, 744 'value' => true, 745 'source_of_value' => '', 746 'show_in_conf_sample' => false, 747 ), 748 'source_dir' => array( 749 'type' => 'string', 750 'description' => 'Source directory for the datamodel files. (which gets compiled to env-production).', 751 // examples... not used 752 'default' => '', 753 'value' => '', 754 'source_of_value' => '', 755 'show_in_conf_sample' => true, 756 ), 757 'csv_file_default_charset' => array( 758 'type' => 'string', 759 'description' => 'Character set used by default for downloading and uploading data as a CSV file. Warning: it is case sensitive (uppercase is preferable).', 760 // examples... not used 761 'default' => 'ISO-8859-1', 762 'value' => '', 763 'source_of_value' => '', 764 'show_in_conf_sample' => true, 765 ), 766 'debug_report_spurious_chars' => array( 767 'type' => 'bool', 768 'description' => 'Report, in the error log, the characters found in the output buffer, echoed by mistake in the loaded modules, and potentially corrupting the output', 769 // examples... not used 770 'default' => false, 771 'value' => '', 772 'source_of_value' => '', 773 'show_in_conf_sample' => false, 774 ), 775 'impact_analysis_first_tab' => array( 776 'type' => 'string', 777 'description' => 'Which tab to display first in the impact analysis view: list or graphics. Graphics are nicer but slower to display when there are many objects', 778 // examples... not used 779 'default' => 'graphics', 780 'value' => '', 781 'source_of_value' => '', 782 'show_in_conf_sample' => false, 783 ), 784 'url_validation_pattern' => array( 785 'type' => 'string', 786 'description' => 'Regular expression to validate/detect the format of an URL (URL attributes and Wiki formatting for Text attributes)', 787 'default' => '(https?|ftp)\://([a-zA-Z0-9+!*(),;?&=\$_.-]+(\:[a-zA-Z0-9+!*(),;?&=\$_.-]+)?@)?([a-zA-Z0-9-.]{3,})(\:[0-9]{2,5})?(/([a-zA-Z0-9%+\$_-]\.?)+)*/?(\?[a-zA-Z+&\$_.-][a-zA-Z0-9;:[\]@&%=+/\$_.-]*)?(#[a-zA-Z_.-][a-zA-Z0-9+\$_.-]*)?', 788 // SHEME.......... USER....................... PASSWORD.......................... HOST/IP........... PORT.......... PATH........................ GET............................................ ANCHOR............................ 789 // Example: http://User:passWord@127.0.0.1:8888/patH/Page.php?arrayArgument[2]=something:blah20#myAnchor 790 // Origin of this regexp: http://www.php.net/manual/fr/function.preg-match.php#93824 791 'value' => '', 792 'source_of_value' => '', 793 'show_in_conf_sample' => true, 794 ), 795 'email_validation_pattern' => array( 796 'type' => 'string', 797 'description' => 'Regular expression to validate/detect the format of an eMail address', 798 'default' => "[a-zA-Z0-9._&'-]+@[a-zA-Z0-9.-]+\.[a-zA-Z0-9-]{2,}", 799 'value' => '', 800 'source_of_value' => '', 801 'show_in_conf_sample' => true, 802 ), 803 'email_decoration_class' => array( 804 'type' => 'string', 805 'description' => 'CSS class(es) to use as decoration for the HTML rendering of the attribute. eg. "fa fa-envelope" will put a mail icon.', 806 'default' => 'fa fa-envelope', 807 'value' => '', 808 'source_of_value' => '', 809 'show_in_conf_sample' => false, 810 ), 811 'phone_number_validation_pattern' => array( 812 'type' => 'string', 813 'description' => 'Regular expression to validate/detect the format of a phone number', 814 'default' => "[0-9.\-\ \+\(\)]+", 815 'value' => '', 816 'source_of_value' => '', 817 'show_in_conf_sample' => false, 818 ), 819 'phone_number_url_pattern' => array( 820 'type' => 'string', 821 'description' => 'Format for phone number url, use %1$s as a placeholder for the value. eg. "tel:%1$s" for regular phone applications or "callto:%1$s" for Skype. Default is "tel:%1$s".', 822 'default' => 'tel:%1$s', 823 'value' => '', 824 'source_of_value' => '', 825 'show_in_conf_sample' => false, 826 ), 827 'phone_number_decoration_class' => array( 828 'type' => 'string', 829 'description' => 'CSS class(es) to use as decoration for the HTML rendering of the attribute. eg. "fa fa-phone" will put a phone icon.', 830 'default' => 'fa fa-phone', 831 'value' => '', 832 'source_of_value' => '', 833 'show_in_conf_sample' => false, 834 ), 835 'log_kpi_duration' => array( 836 'type' => 'integer', 837 'description' => 'Level of logging for troubleshooting performance issues (1 to enable, 2 +blame callers)', 838 // examples... not used 839 'default' => 0, 840 'value' => 0, 841 'source_of_value' => '', 842 'show_in_conf_sample' => false, 843 ), 844 'log_kpi_memory' => array( 845 'type' => 'integer', 846 'description' => 'Level of logging for troubleshooting memory limit issues', 847 // examples... not used 848 'default' => 0, 849 'value' => 0, 850 'source_of_value' => '', 851 'show_in_conf_sample' => false, 852 ), 853 'log_kpi_user_id' => array( 854 'type' => 'string', 855 'description' => 'Limit the scope of users to the given user id (* means no limit)', 856 // examples... not used 857 'default' => '*', 858 'value' => '*', 859 'source_of_value' => '', 860 'show_in_conf_sample' => false, 861 ), 862 'max_linkset_output' => array( 863 'type' => 'integer', 864 'description' => 'Maximum number of items shown when getting a list of related items in an email, using the form $this->some_list$. 0 means no limit.', 865 'default' => 100, 866 'value' => 100, 867 'source_of_value' => '', 868 'show_in_conf_sample' => true, 869 ), 870 'demo_mode' => array( 871 'type' => 'bool', 872 'description' => 'Set to true to prevent users from changing passwords/languages', 873 'default' => false, 874 'value' => '', 875 'source_of_value' => '', 876 'show_in_conf_sample' => false, 877 ), 878 'portal_tickets' => array( 879 'type' => 'string', 880 'description' => 'CSV list of classes supported in the portal', 881 // examples... not used 882 'default' => 'UserRequest', 883 'value' => 'UserRequest', 884 'source_of_value' => '', 885 'show_in_conf_sample' => true, 886 ), 887 'portal_dispatch_urls' => array( 888 'type' => 'array', 889 'description' => 'Associative array of sPortalId => Home page URL (relatively to the application root)', 890 // examples... not used 891 'default' => array(), 892 'value' => false, 893 'source_of_value' => '', 894 'show_in_conf_sample' => false, 895 ), 896 'max_execution_time_per_loop' => array( 897 'type' => 'integer', 898 'description' => 'Maximum execution time requested, per loop, during bulk operations. Zero means no limit.', 899 // examples... not used 900 'default' => 30, 901 'value' => 30, 902 'source_of_value' => '', 903 'show_in_conf_sample' => false, 904 ), 905 'max_history_length' => array( 906 'type' => 'integer', 907 'description' => 'Maximum length of the history table (in the "History" tab on each object) before it gets truncated. Latest modifications are displayed first.', 908 // examples... not used 909 'default' => 50, 910 'value' => 50, 911 'source_of_value' => '', 912 'show_in_conf_sample' => false, 913 ), 914 'max_history_case_log_entry_length' => array( 915 'type' => 'integer', 916 'description' => 'The length (in number of characters) at which to truncate the (expandable) display (in the history) of a case log entry. If zero, the display in the history is not truncated.', 917 // examples... not used 918 'default' => 60, 919 'value' => 60, 920 'source_of_value' => '', 921 'show_in_conf_sample' => false, 922 ), 923 'full_text_chunk_duration' => array( 924 'type' => 'integer', 925 'description' => 'Delay after which the results are displayed.', 926 // examples... not used 927 'default' => 2, 928 'value' => 2, 929 'source_of_value' => '', 930 'show_in_conf_sample' => false, 931 ), 932 'full_text_accelerators' => array( 933 'type' => 'array', 934 'description' => 'Specifies classes to be searched at first (and the subset of data) when running the full text search.', 935 'default' => array(), 936 'value' => false, 937 'source_of_value' => '', 938 'show_in_conf_sample' => false, 939 ), 940 'full_text_needle_min' => array( 941 'type' => 'integer', 942 'description' => 'Minimum size of the full text needle.', 943 'default' => 3, 944 'value' => 3, 945 'source_of_value' => '', 946 'show_in_conf_sample' => false, 947 ), 948 'tracking_level_linked_set_default' => array( 949 'type' => 'integer', 950 'description' => 'Default tracking level if not explicitly set at the attribute level, for AttributeLinkedSet (defaults to NONE in case of a fresh install, LIST otherwise - this to preserve backward compatibility while upgrading from a version older than 2.0.3 - see TRAC #936)', 951 'default' => LINKSET_TRACKING_LIST, 952 'value' => LINKSET_TRACKING_LIST, 953 'source_of_value' => '', 954 'show_in_conf_sample' => false, 955 ), 956 'tracking_level_linked_set_indirect_default' => array( 957 'type' => 'integer', 958 'description' => 'Default tracking level if not explicitly set at the attribute level, for AttributeLinkedSetIndirect', 959 'default' => LINKSET_TRACKING_ALL, 960 'value' => LINKSET_TRACKING_ALL, 961 'source_of_value' => '', 962 'show_in_conf_sample' => false, 963 ), 964 'user_rights_legacy' => array( 965 'type' => 'bool', 966 'description' => 'Set to true to restore the buggy algorithm for the computation of user rights (within the same profile, ALLOW on the class itself has precedence on DENY of a parent class)', 967 'default' => false, 968 'value' => '', 969 'source_of_value' => '', 970 'show_in_conf_sample' => false, 971 ), 972 'xlsx_exporter_memory_limit' => array( 973 'type' => 'string', 974 'description' => 'Memory limit to use when (interactively) exporting data to Excel', 975 'default' => '2048M', // Huuuuuuge 2GB! 976 'value' => '', 977 'source_of_value' => '', 978 'show_in_conf_sample' => false, 979 ), 980 'min_reload_interval' => array( 981 'type' => 'integer', 982 'description' => 'Minimum refresh interval (seconds) for dashboards, shortcuts, etc. Even if the interval is set programmatically, it is forced to that minimum', 983 'default' => 5, // In iTop 2.0.3, this was the hardcoded value 984 'value' => '', 985 'source_of_value' => '', 986 'show_in_conf_sample' => false, 987 ), 988 'relations_max_depth' => array( 989 'type' => 'integer', 990 'description' => 'Maximum number of successive levels (depth) to explore when displaying the impact/depends on relations.', 991 'default' => 20, // In iTop 2.0.3, this was the hardcoded value 992 'value' => '', 993 'source_of_value' => '', 994 'show_in_conf_sample' => false, 995 ), 996 'transaction_storage' => array( 997 'type' => 'string', 998 'description' => 'The type of mechanism to use for storing the unique identifiers for transactions (Session|File).', 999 'default' => 'File', 1000 'value' => '', 1001 'source_of_value' => '', 1002 'show_in_conf_sample' => false, 1003 ), 1004 'transactions_enabled' => array( 1005 'type' => 'bool', 1006 'description' => 'Whether or not the whole mechanism to prevent multiple submissions of a page is enabled.', 1007 'default' => true, 1008 'value' => '', 1009 'source_of_value' => '', 1010 'show_in_conf_sample' => false, 1011 ), 1012 'log_transactions' => array( 1013 'type' => 'bool', 1014 'description' => 'Whether or not to enable the debug log for the transactions.', 1015 'default' => false, 1016 'value' => '', 1017 'source_of_value' => '', 1018 'show_in_conf_sample' => false, 1019 ), 1020 'concurrent_lock_enabled' => array( 1021 'type' => 'bool', 1022 'description' => 'Whether or not to activate the locking mechanism in order to prevent concurrent edition of the same object.', 1023 'default' => false, 1024 'value' => '', 1025 'source_of_value' => '', 1026 'show_in_conf_sample' => false, 1027 ), 1028 'concurrent_lock_expiration_delay' => array( 1029 'type' => 'integer', 1030 'description' => 'Delay (in seconds) for a concurrent lock to expire', 1031 'default' => 120, 1032 'value' => '', 1033 'source_of_value' => '', 1034 'show_in_conf_sample' => false, 1035 ), 1036 'concurrent_lock_override_profiles' => array( 1037 'type' => 'array', 1038 'description' => 'The list of profiles allowed to "kill" a lock', 1039 'default' => array('Administrator'), 1040 'value' => '', 1041 'source_of_value' => '', 1042 'show_in_conf_sample' => false, 1043 ), 1044 'html_sanitizer' => array( 1045 'type' => 'string', 1046 'description' => 'The class to use for HTML sanitization: HTMLDOMSanitizer, HTMLPurifierSanitizer or HTMLNullSanitizer', 1047 'default' => 'HTMLDOMSanitizer', 1048 'value' => '', 1049 'source_of_value' => '', 1050 'show_in_conf_sample' => false, 1051 ), 1052 'inline_image_max_display_width' => array( 1053 'type' => 'integer', 1054 'description' => 'The maximum width (in pixels) when displaying images inside an HTML formatted attribute. Images will be displayed using this this maximum width.', 1055 'default' => '250', 1056 'value' => '', 1057 'source_of_value' => '', 1058 'show_in_conf_sample' => true, 1059 ), 1060 'inline_image_max_storage_width' => array( 1061 'type' => 'integer', 1062 'description' => 'The maximum width (in pixels) when uploading images to be used inside an HTML formatted attribute. Images larger than the given size will be downsampled before storing them in the database.', 1063 'default' => '1600', 1064 'value' => '', 1065 'source_of_value' => '', 1066 'show_in_conf_sample' => true, 1067 ), 1068 'draft_attachments_lifetime' => array( 1069 'type' => 'integer', 1070 'description' => 'Lifetime (in seconds) of drafts\' attachments and inline images: after this duration, the garbage collector will delete them.', 1071 'default' => 86400, 1072 'value' => '', 1073 'source_of_value' => '', 1074 'show_in_conf_sample' => false, 1075 ), 1076 'date_and_time_format' => array( 1077 'type' => 'array', 1078 'description' => 'Format for date and time display (per language)', 1079 'default' => array('default' => array('date' => 'Y-m-d', 'time' => 'H:i:s', 'date_time' => '$date $time')), 1080 'value' => false, 1081 'source_of_value' => '', 1082 'show_in_conf_sample' => true, 1083 ), 1084 'breadcrumb.max_count' => array( 1085 'type' => 'integer', 1086 'description' => 'Maximum number of items kept in the history breadcrumb. Set it to 0 to entirely disable the breadcrumb.', 1087 'default' => 8, 1088 'value' => 8, 1089 'source_of_value' => '', 1090 'show_in_conf_sample' => false, 1091 ), 1092 'obsolescence.show_obsolete_data' => array( 1093 'type' => 'bool', 1094 'description' => 'Default value for the user preference "show obsolete data"', 1095 'default' => false, 1096 'value' => '', 1097 'source_of_value' => '', 1098 'show_in_conf_sample' => false, 1099 ), 1100 'obsolescence.date_update_interval' => array( 1101 'type' => 'integer', 1102 'description' => 'Delay in seconds between two refreshes of the obsolescence dates.', 1103 'default' => 600, 1104 'value' => 600, 1105 'source_of_value' => '', 1106 'show_in_conf_sample' => false, 1107 ), 1108 'disable_attachments_download_legacy_portal' => array( 1109 'type' => 'bool', 1110 'description' => 'Disable attachments download from legacy portal', 1111 'default' => true, 1112 'value' => true, 1113 'source_of_value' => '', 1114 'show_in_conf_sample' => true, 1115 ), 1116 'secure_rest_services' => array( 1117 'type' => 'bool', 1118 'description' => 'When set to true, only the users with the profile "REST Services User" are allowed to use the REST web services.', 1119 'default' => true, 1120 'value' => true, 1121 'source_of_value' => '', 1122 'show_in_conf_sample' => false, 1123 ), 1124 'search_manual_submit' => array( 1125 'type' => 'array', 1126 'description' => 'Force manual submit of search all requests', 1127 'default' => false, 1128 'value' => true, 1129 'source_of_value' => '', 1130 'show_in_conf_sample' => true, 1131 ), 1132 'optimize_requests_for_join_count' => array( 1133 'type' => 'bool', 1134 'description' => 'Optimize request joins to minimize the count (default is true, try to set it to false in case of performance issues)', 1135 'default' => true, 1136 'value' => true, 1137 'source_of_value' => '', 1138 'show_in_conf_sample' => true, 1139 ), 1140 'high_cardinality_classes' => array( 1141 'type' => 'array', 1142 'description' => 'List of classes with high cardinality (Force manual submit of search)', 1143 'default' => array(), 1144 'value' => array(), 1145 'source_of_value' => '', 1146 'show_in_conf_sample' => true, 1147 ), 1148 'newsroom_enabled' => array( 1149 'type' => 'bool', 1150 'description' => 'Whether or not the whole newsroom is enabled', 1151 'default' => true, 1152 'value' => true, 1153 'source_of_value' => '', 1154 'show_in_conf_sample' => false, 1155 ), 1156 'regenerate_session_id_enabled' => array( 1157 'type' => 'bool', 1158 'description' => 'If true then session id will be regenerated on each login, to prevent session fixation.', 1159 'default' => true, 1160 'value' => true, 1161 'source_of_value' => '', 1162 'show_in_conf_sample' => false, 1163 ), 1164 ); 1165 1166 public function IsProperty($sPropCode) 1167 { 1168 return (array_key_exists($sPropCode, $this->m_aSettings)); 1169 } 1170 1171 /** 1172 * @return string identifier that can be used for example to name WebStorage/SessionStorage keys (they 1173 * are related to a whole domain, and a domain can host multiple itop) 1174 * Beware: do not expose server side information to the client ! 1175 */ 1176 public function GetItopInstanceid() 1177 { 1178 return md5(utils::GetAbsoluteUrlAppRoot() 1179 .'==='.$this->Get('db_host') 1180 .'/'.$this->Get('db_name') 1181 .'/'.$this->Get('db_subname')); 1182 } 1183 1184 public function GetDescription($sPropCode) 1185 { 1186 return $this->m_aSettings[$sPropCode]; 1187 } 1188 1189 /** 1190 * @param string $sPropCode 1191 * @param mixed $value 1192 * @param string $sSourceDesc mandatory for variables with show_in_conf_sample=false 1193 * 1194 * @throws \CoreException 1195 */ 1196 public function Set($sPropCode, $value, $sSourceDesc = 'unknown') 1197 { 1198 $sType = $this->m_aSettings[$sPropCode]['type']; 1199 switch ($sType) 1200 { 1201 case 'bool': 1202 $value = (bool)$value; 1203 break; 1204 case 'string': 1205 $value = (string)$value; 1206 break; 1207 case 'integer': 1208 $value = (integer)$value; 1209 break; 1210 case 'float': 1211 $value = (float)$value; 1212 break; 1213 case 'array': 1214 break; 1215 default: 1216 throw new CoreException('Unknown type for setting', array('property' => $sPropCode, 'type' => $sType)); 1217 } 1218 $this->m_aSettings[$sPropCode]['value'] = $value; 1219 $this->m_aSettings[$sPropCode]['source_of_value'] = $sSourceDesc; 1220 1221 } 1222 1223 /** 1224 * @param string $sPropCode 1225 * 1226 * @return mixed 1227 */ 1228 public function Get($sPropCode) 1229 { 1230 return $this->m_aSettings[$sPropCode]['value']; 1231 } 1232 1233 /** 1234 * Event log options (see LOG_... definition) 1235 */ 1236 // Those variables will be deprecated later, when the transition to ...Get('my_setting') will be done 1237 protected $m_bLogGlobal; 1238 protected $m_bLogNotification; 1239 protected $m_bLogIssue; 1240 protected $m_bLogWebService; 1241 protected $m_bQueryCacheEnabled; // private setting 1242 1243 /** 1244 * @var integer Number of elements to be displayed when there are more than m_iMaxDisplayLimit elements 1245 */ 1246 protected $m_iMinDisplayLimit; 1247 /** 1248 * @var integer Max number of elements before truncating the display 1249 */ 1250 protected $m_iMaxDisplayLimit; 1251 1252 /** 1253 * @var integer Number of seconds between two reloads of the display (standard) 1254 */ 1255 protected $m_iStandardReloadInterval; 1256 /** 1257 * @var integer Number of seconds between two reloads of the display (fast) 1258 */ 1259 protected $m_iFastReloadInterval; 1260 1261 /** 1262 * @var boolean Whether or not a secure connection is required for using the application. 1263 * If set, any attempt to connect to an iTop page with http:// will be redirected 1264 * to https:// 1265 */ 1266 protected $m_bSecureConnectionRequired; 1267 1268 /** 1269 * @var string Langage code, default if the user language is undefined 1270 */ 1271 protected $m_sDefaultLanguage; 1272 1273 /** 1274 * @var string Type of login process allowed: form|basic|url|external 1275 */ 1276 protected $m_sAllowedLoginTypes; 1277 1278 /** 1279 * @var string Name of the PHP variable in which external authentication information is passed by the web server 1280 */ 1281 protected $m_sExtAuthVariable; 1282 1283 /** 1284 * @var string Encryption key used for all attributes of type "encrypted string". Can be set to a random value 1285 * unless you want to import a database from another iTop instance, in which case you must use 1286 * the same encryption key in order to properly decode the encrypted fields 1287 */ 1288 protected $m_sEncryptionKey; 1289 1290 /** 1291 * @var string Encryption key used for all attributes of type "encrypted string". Can be set to a random value 1292 * unless you want to import a database from another iTop instance, in which case you must use 1293 * the same encryption key in order to properly decode the encrypted fields 1294 */ 1295 protected $m_sEncryptionLibrary; 1296 1297 /** 1298 * @var array Additional character sets to be supported by the interactive CSV import 1299 * 'iconv_code' => 'display name' 1300 */ 1301 protected $m_aCharsets; 1302 1303 /** 1304 * Config constructor. 1305 * 1306 * @param string|null $sConfigFile 1307 * @param bool $bLoadConfig 1308 * 1309 * @throws \ConfigException 1310 * @throws \CoreException 1311 */ 1312 public function __construct($sConfigFile = null, $bLoadConfig = true) 1313 { 1314 $this->m_sFile = $sConfigFile; 1315 if (is_null($sConfigFile)) 1316 { 1317 $bLoadConfig = false; 1318 } 1319 1320 $this->m_aAddons = array( 1321 // Default AddOn, always present can be moved to an official iTop Module later if needed 1322 'user rights' => 'addons/userrights/userrightsprofile.class.inc.php', 1323 ); 1324 1325 foreach ($this->m_aSettings as $sPropCode => $aSettingInfo) 1326 { 1327 $this->m_aSettings[$sPropCode]['value'] = $aSettingInfo['default']; 1328 } 1329 1330 $this->m_bLogGlobal = DEFAULT_LOG_GLOBAL; 1331 $this->m_bLogNotification = DEFAULT_LOG_NOTIFICATION; 1332 $this->m_bLogIssue = DEFAULT_LOG_ISSUE; 1333 $this->m_bLogWebService = DEFAULT_LOG_WEB_SERVICE; 1334 $this->m_iMinDisplayLimit = DEFAULT_MIN_DISPLAY_LIMIT; 1335 $this->m_iMaxDisplayLimit = DEFAULT_MAX_DISPLAY_LIMIT; 1336 $this->m_iStandardReloadInterval = DEFAULT_STANDARD_RELOAD_INTERVAL; 1337 $this->m_iFastReloadInterval = DEFAULT_FAST_RELOAD_INTERVAL; 1338 $this->m_bSecureConnectionRequired = DEFAULT_SECURE_CONNECTION_REQUIRED; 1339 $this->m_sDefaultLanguage = 'EN US'; 1340 $this->m_sAllowedLoginTypes = DEFAULT_ALLOWED_LOGIN_TYPES; 1341 $this->m_sExtAuthVariable = DEFAULT_EXT_AUTH_VARIABLE; 1342 $this->m_aCharsets = array(); 1343 $this->m_bQueryCacheEnabled = DEFAULT_QUERY_CACHE_ENABLED; 1344 1345 //define default encryption params according to php install 1346 $aEncryptParams = SimpleCrypt::GetNewDefaultParams(); 1347 $this->m_sEncryptionLibrary = isset($aEncryptParams['lib']) ? $aEncryptParams['lib'] : DEFAULT_ENCRYPTION_LIB; 1348 $this->m_sEncryptionKey= isset($aEncryptParams['key']) ? $aEncryptParams['key'] : DEFAULT_ENCRYPTION_KEY; 1349 1350 $this->m_aModuleSettings = array(); 1351 1352 if ($bLoadConfig) 1353 { 1354 $this->Load($sConfigFile); 1355 $this->Verify(); 1356 } 1357 1358 // Application root url: set a default value, then normalize it 1359 /* 1360 * Does not work in CLI/unattended mode 1361 $sAppRootUrl = trim($this->Get('app_root_url')); 1362 if (strlen($sAppRootUrl) == 0) 1363 { 1364 $sAppRootUrl = utils::GetDefaultUrlAppRoot(); 1365 } 1366 if (substr($sAppRootUrl, -1, 1) != '/') 1367 { 1368 $sAppRootUrl .= '/'; 1369 } 1370 $this->Set('app_root_url', $sAppRootUrl); 1371 */ 1372 } 1373 1374 /** 1375 * @param string $sPurpose 1376 * @param string $sFileName 1377 * 1378 * @throws \ConfigException 1379 */ 1380 protected function CheckFile($sPurpose, $sFileName) 1381 { 1382 if (!file_exists($sFileName)) 1383 { 1384 throw new ConfigException("Could not find $sPurpose file", array('file' => $sFileName)); 1385 } 1386 if (!is_readable($sFileName)) 1387 { 1388 throw new ConfigException("Could not read $sPurpose file (the file exists but cannot be read). Do you have the rights to access this file?", 1389 array('file' => $sFileName)); 1390 } 1391 } 1392 1393 /** 1394 * @param string $sConfigFile 1395 * 1396 * @throws \ConfigException 1397 * @throws \CoreException 1398 */ 1399 protected function Load($sConfigFile) 1400 { 1401 $this->CheckFile('configuration', $sConfigFile); 1402 1403 $sConfigCode = trim(file_get_contents($sConfigFile)); 1404 1405 // Variables created when doing an eval() on the config file 1406 /** @var array $MySettings */ 1407 $MySettings = null; 1408 /** @var array $MyModuleSettings */ 1409 $MyModuleSettings = null; 1410 /** @var array $MyModules */ 1411 $MyModules = null; 1412 1413 // This does not work on several lines 1414 // preg_match('/^<\\?php(.*)\\?'.'>$/', $sConfigCode, $aMatches)... 1415 // So, I've implemented a solution suggested in the PHP doc (search for phpWrapper) 1416 try 1417 { 1418 ob_start(); 1419 eval('?'.'>'.trim($sConfigCode)); 1420 $sNoise = trim(ob_get_contents()); 1421 ob_end_clean(); 1422 } 1423 catch (Exception $e) 1424 { 1425 // well, never reach in case of parsing error :-( 1426 // will be improved in PHP 6 ? 1427 throw new ConfigException('Error in configuration file', 1428 array('file' => $sConfigFile, 'error' => $e->getMessage())); 1429 } 1430 catch(Error $e) 1431 { 1432 // PHP 7 1433 throw new ConfigException('Error in configuration file', 1434 array('file' => $sConfigFile, 'error' => $e->getMessage().' at line '.$e->getLine())); 1435 } 1436 if (strlen($sNoise) > 0) 1437 { 1438 // Note: sNoise is an html output, but so far it was ok for me (e.g. showing the entire call stack) 1439 throw new ConfigException('Syntax error in configuration file', 1440 array('file' => $sConfigFile, 'error' => '<tt>'.htmlentities($sNoise, ENT_QUOTES, 'UTF-8').'</tt>')); 1441 } 1442 1443 if (!isset($MySettings) || !is_array($MySettings)) 1444 { 1445 throw new ConfigException('Missing array in configuration file', 1446 array('file' => $sConfigFile, 'expected' => '$MySettings')); 1447 } 1448 1449 if (!array_key_exists('addons', $MyModules)) 1450 { 1451 throw new ConfigException('Missing item in configuration file', 1452 array('file' => $sConfigFile, 'expected' => '$MyModules[\'addons\']')); 1453 } 1454 if (!array_key_exists('user rights', $MyModules['addons'])) 1455 { 1456 // Add one, by default 1457 $MyModules['addons']['user rights'] = '/addons/userrights/userrightsnull.class.inc.php'; 1458 } 1459 1460 $this->m_aAddons = $MyModules['addons']; 1461 1462 foreach ($MySettings as $sPropCode => $rawvalue) 1463 { 1464 if ($this->IsProperty($sPropCode)) 1465 { 1466 if (is_string($rawvalue)) 1467 { 1468 $value = trim($rawvalue); 1469 } 1470 else 1471 { 1472 $value = $rawvalue; 1473 } 1474 $this->Set($sPropCode, $value, $sConfigFile); 1475 } 1476 } 1477 1478 $this->m_bLogGlobal = isset($MySettings['log_global']) ? (bool)trim($MySettings['log_global']) : DEFAULT_LOG_GLOBAL; 1479 $this->m_bLogNotification = isset($MySettings['log_notification']) ? (bool)trim($MySettings['log_notification']) : DEFAULT_LOG_NOTIFICATION; 1480 $this->m_bLogIssue = isset($MySettings['log_issue']) ? (bool)trim($MySettings['log_issue']) : DEFAULT_LOG_ISSUE; 1481 $this->m_bLogWebService = isset($MySettings['log_web_service']) ? (bool)trim($MySettings['log_web_service']) : DEFAULT_LOG_WEB_SERVICE; 1482 $this->m_bQueryCacheEnabled = isset($MySettings['query_cache_enabled']) ? (bool)trim($MySettings['query_cache_enabled']) : DEFAULT_QUERY_CACHE_ENABLED; 1483 1484 $this->m_iMinDisplayLimit = isset($MySettings['min_display_limit']) ? trim($MySettings['min_display_limit']) : DEFAULT_MIN_DISPLAY_LIMIT; 1485 $this->m_iMaxDisplayLimit = isset($MySettings['max_display_limit']) ? trim($MySettings['max_display_limit']) : DEFAULT_MAX_DISPLAY_LIMIT; 1486 $this->m_iStandardReloadInterval = isset($MySettings['standard_reload_interval']) ? trim($MySettings['standard_reload_interval']) : DEFAULT_STANDARD_RELOAD_INTERVAL; 1487 $this->m_iFastReloadInterval = isset($MySettings['fast_reload_interval']) ? trim($MySettings['fast_reload_interval']) : DEFAULT_FAST_RELOAD_INTERVAL; 1488 $this->m_bSecureConnectionRequired = isset($MySettings['secure_connection_required']) ? (bool)trim($MySettings['secure_connection_required']) : DEFAULT_SECURE_CONNECTION_REQUIRED; 1489 1490 $this->m_aModuleSettings = isset($MyModuleSettings) ? $MyModuleSettings : array(); 1491 1492 $this->m_sDefaultLanguage = isset($MySettings['default_language']) ? trim($MySettings['default_language']) : 'EN US'; 1493 $this->m_sAllowedLoginTypes = isset($MySettings['allowed_login_types']) ? trim($MySettings['allowed_login_types']) : DEFAULT_ALLOWED_LOGIN_TYPES; 1494 $this->m_sExtAuthVariable = isset($MySettings['ext_auth_variable']) ? trim($MySettings['ext_auth_variable']) : DEFAULT_EXT_AUTH_VARIABLE; 1495 $this->m_sEncryptionKey = isset($MySettings['encryption_key']) ? trim($MySettings['encryption_key']) : $this->m_sEncryptionKey; 1496 $this->m_sEncryptionLibrary = isset($MySettings['encryption_library']) ? trim($MySettings['encryption_library']) : $this->m_sEncryptionLibrary; 1497 $this->m_aCharsets = isset($MySettings['csv_import_charsets']) ? $MySettings['csv_import_charsets'] : array(); 1498 } 1499 1500 protected function Verify() 1501 { 1502 // Files are verified later on, just before using them -see MetaModel::Plugin() 1503 // (we have their final path at that point) 1504 } 1505 1506 public function GetModuleSetting($sModule, $sProperty, $defaultvalue = null) 1507 { 1508 if (isset($this->m_aModuleSettings[$sModule][$sProperty])) 1509 { 1510 return $this->m_aModuleSettings[$sModule][$sProperty]; 1511 } 1512 1513 // Fall back to the predefined XML parameter, if any 1514 return $this->GetModuleParameter($sModule, $sProperty, $defaultvalue); 1515 } 1516 1517 /** 1518 * @param string $sModule 1519 * @param string $sProperty 1520 * @param mixed|null $defaultvalue 1521 * 1522 * @return mixed|null 1523 */ 1524 public function GetModuleParameter($sModule, $sProperty, $defaultvalue = null) 1525 { 1526 $ret = $defaultvalue; 1527 if (class_exists('ModulesXMLParameters')) 1528 { 1529 $aAllParams = ModulesXMLParameters::GetData($sModule); 1530 if (array_key_exists($sProperty, $aAllParams)) 1531 { 1532 $ret = $aAllParams[$sProperty]; 1533 } 1534 } 1535 1536 return $ret; 1537 } 1538 1539 public function SetModuleSetting($sModule, $sProperty, $value) 1540 { 1541 $this->m_aModuleSettings[$sModule][$sProperty] = $value; 1542 } 1543 1544 public function GetAddons() 1545 { 1546 return $this->m_aAddons; 1547 } 1548 1549 public function SetAddons($aAddons) 1550 { 1551 $this->m_aAddons = $aAddons; 1552 } 1553 1554 /** 1555 * @return string 1556 * 1557 * @deprecated 2.5 will be removed in 2.6 1558 * @see Config::Get() as a replacement 1559 */ 1560 public function GetDBHost() 1561 { 1562 return $this->Get('db_host'); 1563 } 1564 1565 /** 1566 * @return string 1567 * 1568 * @deprecated 2.5 will be removed in 2.6 1569 * @see Config::Get() as a replacement 1570 */ 1571 public function GetDBName() 1572 { 1573 return $this->Get('db_name'); 1574 } 1575 1576 /** 1577 * @return string 1578 * 1579 * @deprecated 2.5 will be removed in 2.6 1580 * @see Config::Get() as a replacement 1581 */ 1582 public function GetDBSubname() 1583 { 1584 return $this->Get('db_subname'); 1585 } 1586 1587 /** 1588 * @return string 1589 * 1590 * @deprecated 2.5 will be removed in 2.6 N°1001 utf8mb4 switch 1591 * @see Config::DEFAULT_CHARACTER_SET 1592 */ 1593 public function GetDBCharacterSet() 1594 { 1595 return DEFAULT_CHARACTER_SET; 1596 } 1597 1598 /** 1599 * @return string 1600 * 1601 * @deprecated 2.5 will be removed in 2.6 N°1001 utf8mb4 switch 1602 * @see Config::DEFAULT_COLLATION 1603 */ 1604 public function GetDBCollation() 1605 { 1606 return DEFAULT_COLLATION; 1607 } 1608 1609 /** 1610 * @return string 1611 * 1612 * @deprecated 2.5 will be removed in 2.6 1613 * @see Config::Get() as a replacement 1614 */ 1615 public function GetDBUser() 1616 { 1617 return $this->Get('db_user'); 1618 } 1619 1620 /** 1621 * @return string 1622 * 1623 * @deprecated 2.5 will be removed in 2.6 1624 * @see Config::Get() as a replacement 1625 */ 1626 public function GetDBPwd() 1627 { 1628 return $this->Get('db_pwd'); 1629 } 1630 1631 public function GetLogGlobal() 1632 { 1633 return $this->m_bLogGlobal; 1634 } 1635 1636 public function GetLogNotification() 1637 { 1638 return $this->m_bLogNotification; 1639 } 1640 1641 public function GetLogIssue() 1642 { 1643 return $this->m_bLogIssue; 1644 } 1645 1646 public function GetLogWebService() 1647 { 1648 return $this->m_bLogWebService; 1649 } 1650 1651 public function GetLogQueries() 1652 { 1653 return false; 1654 } 1655 1656 public function GetQueryCacheEnabled() 1657 { 1658 return $this->m_bQueryCacheEnabled; 1659 } 1660 1661 public function GetMinDisplayLimit() 1662 { 1663 return $this->m_iMinDisplayLimit; 1664 } 1665 1666 public function GetMaxDisplayLimit() 1667 { 1668 return $this->m_iMaxDisplayLimit; 1669 } 1670 1671 public function GetStandardReloadInterval() 1672 { 1673 return $this->m_iStandardReloadInterval; 1674 } 1675 1676 public function GetFastReloadInterval() 1677 { 1678 return $this->m_iFastReloadInterval; 1679 } 1680 1681 public function GetSecureConnectionRequired() 1682 { 1683 return $this->m_bSecureConnectionRequired; 1684 } 1685 1686 public function GetDefaultLanguage() 1687 { 1688 return $this->m_sDefaultLanguage; 1689 } 1690 1691 public function GetEncryptionKey() 1692 { 1693 return $this->m_sEncryptionKey; 1694 } 1695 1696 public function GetEncryptionLibrary() 1697 { 1698 return $this->m_sEncryptionLibrary; 1699 } 1700 1701 public function GetAllowedLoginTypes() 1702 { 1703 return explode('|', $this->m_sAllowedLoginTypes); 1704 } 1705 1706 public function GetExternalAuthenticationVariable() 1707 { 1708 return $this->m_sExtAuthVariable; 1709 } 1710 1711 public function GetCSVImportCharsets() 1712 { 1713 return $this->m_aCharsets; 1714 } 1715 1716 public function SetLogGlobal($iLogGlobal) 1717 { 1718 $this->m_iLogGlobal = $iLogGlobal; 1719 } 1720 1721 public function SetLogNotification($iLogNotification) 1722 { 1723 $this->m_iLogNotification = $iLogNotification; 1724 } 1725 1726 public function SetLogIssue($iLogIssue) 1727 { 1728 $this->m_iLogIssue = $iLogIssue; 1729 } 1730 1731 public function SetLogWebService($iLogWebService) 1732 { 1733 $this->m_iLogWebService = $iLogWebService; 1734 } 1735 1736 public function SetMinDisplayLimit($iMinDisplayLimit) 1737 { 1738 $this->m_iMinDisplayLimit = $iMinDisplayLimit; 1739 } 1740 1741 public function SetMaxDisplayLimit($iMaxDisplayLimit) 1742 { 1743 $this->m_iMaxDisplayLimit = $iMaxDisplayLimit; 1744 } 1745 1746 public function SetStandardReloadInterval($iStandardReloadInterval) 1747 { 1748 $this->m_iStandardReloadInterval = $iStandardReloadInterval; 1749 } 1750 1751 public function SetFastReloadInterval($iFastReloadInterval) 1752 { 1753 $this->m_iFastReloadInterval = $iFastReloadInterval; 1754 } 1755 1756 public function SetSecureConnectionRequired($bSecureConnectionRequired) 1757 { 1758 $this->m_bSecureConnectionRequired = $bSecureConnectionRequired; 1759 } 1760 1761 public function SetDefaultLanguage($sLanguageCode) 1762 { 1763 $this->m_sDefaultLanguage = $sLanguageCode; 1764 } 1765 1766 public function SetAllowedLoginTypes($aAllowedLoginTypes) 1767 { 1768 $this->m_sAllowedLoginTypes = implode('|', $aAllowedLoginTypes); 1769 } 1770 1771 public function SetExternalAuthenticationVariable($sExtAuthVariable) 1772 { 1773 $this->m_sExtAuthVariable = $sExtAuthVariable; 1774 } 1775 1776 public function SetEncryptionKey($sKey) 1777 { 1778 $this->m_sEncryptionKey = $sKey; 1779 } 1780 1781 public function SetCSVImportCharsets($aCharsets) 1782 { 1783 $this->m_aCharsets = $aCharsets; 1784 } 1785 1786 public function AddCSVImportCharset($sIconvCode, $sDisplayName) 1787 { 1788 $this->m_aCharsets[$sIconvCode] = $sDisplayName; 1789 } 1790 1791 public function GetLoadedFile() 1792 { 1793 if (is_null($this->m_sFile)) 1794 { 1795 return ''; 1796 } 1797 else 1798 { 1799 return $this->m_sFile; 1800 } 1801 } 1802 1803 /** 1804 * Render the configuration as an associative array 1805 * 1806 * @return array 1807 */ 1808 public function ToArray() 1809 { 1810 $aSettings = array(); 1811 foreach ($this->m_aSettings as $sPropCode => $aSettingInfo) 1812 { 1813 $aSettings[$sPropCode] = $aSettingInfo['value']; 1814 } 1815 $aSettings['log_global'] = $this->m_bLogGlobal; 1816 $aSettings['log_notification'] = $this->m_bLogNotification; 1817 $aSettings['log_issue'] = $this->m_bLogIssue; 1818 $aSettings['log_web_service'] = $this->m_bLogWebService; 1819 $aSettings['query_cache_enabled'] = $this->m_bQueryCacheEnabled; 1820 $aSettings['min_display_limit'] = $this->m_iMinDisplayLimit; 1821 $aSettings['max_display_limit'] = $this->m_iMaxDisplayLimit; 1822 $aSettings['standard_reload_interval'] = $this->m_iStandardReloadInterval; 1823 $aSettings['fast_reload_interval'] = $this->m_iFastReloadInterval; 1824 $aSettings['secure_connection_required'] = $this->m_bSecureConnectionRequired; 1825 $aSettings['default_language'] = $this->m_sDefaultLanguage; 1826 $aSettings['allowed_login_types'] = $this->m_sAllowedLoginTypes; 1827 $aSettings['ext_auth_variable'] = $this->m_sExtAuthVariable; 1828 $aSettings['encryption_key'] = $this->m_sEncryptionKey; 1829 $aSettings['encryption_library'] = $this->m_sEncryptionLibrary; 1830 $aSettings['csv_import_charsets'] = $this->m_aCharsets; 1831 1832 foreach ($this->m_aModuleSettings as $sModule => $aProperties) 1833 { 1834 foreach ($aProperties as $sProperty => $value) 1835 { 1836 $aSettings['module_settings'][$sModule][$sProperty] = $value; 1837 } 1838 } 1839 foreach ($this->m_aAddons as $sKey => $sFile) 1840 { 1841 $aSettings['addon_list'][] = $sFile; 1842 } 1843 1844 return $aSettings; 1845 } 1846 1847 /** 1848 * Write the configuration to a file (php format) that can be reloaded later 1849 * By default write to the same file that was specified when constructing the object 1850 * 1851 * @param string $sFileName string Name of the file to write to (emtpy to write to the same file) 1852 * 1853 * @return boolean True otherwise throws an Exception 1854 * 1855 * @throws \ConfigException 1856 */ 1857 public function WriteToFile($sFileName = '') 1858 { 1859 if (empty($sFileName)) 1860 { 1861 $sFileName = $this->m_sFile; 1862 } 1863 $hFile = @fopen($sFileName, 'w'); 1864 if ($hFile !== false) 1865 { 1866 fwrite($hFile, "<?php\n"); 1867 fwrite($hFile, "\n/**\n"); 1868 fwrite($hFile, " *\n"); 1869 fwrite($hFile, " * Configuration file, generated by the ".ITOP_APPLICATION." configuration wizard\n"); 1870 fwrite($hFile, " *\n"); 1871 fwrite($hFile, 1872 " * The file is used in MetaModel::LoadConfig() which does all the necessary initialization job\n"); 1873 fwrite($hFile, " *\n"); 1874 fwrite($hFile, " */\n"); 1875 1876 $aConfigSettings = $this->m_aSettings; 1877 1878 // Old fashioned boolean settings 1879 $aBoolValues = array( 1880 'log_global' => $this->m_bLogGlobal, 1881 'log_notification' => $this->m_bLogNotification, 1882 'log_issue' => $this->m_bLogIssue, 1883 'log_web_service' => $this->m_bLogWebService, 1884 'query_cache_enabled' => $this->m_bQueryCacheEnabled, 1885 'secure_connection_required' => $this->m_bSecureConnectionRequired, 1886 ); 1887 foreach ($aBoolValues as $sKey => $bValue) 1888 { 1889 $aConfigSettings[$sKey] = array( 1890 'show_in_conf_sample' => true, 1891 'type' => 'bool', 1892 'value' => $bValue, 1893 ); 1894 } 1895 1896 // Old fashioned integer settings 1897 $aIntValues = array( 1898 'fast_reload_interval' => $this->m_iFastReloadInterval, 1899 'max_display_limit' => $this->m_iMaxDisplayLimit, 1900 'min_display_limit' => $this->m_iMinDisplayLimit, 1901 'standard_reload_interval' => $this->m_iStandardReloadInterval, 1902 ); 1903 foreach ($aIntValues as $sKey => $iValue) 1904 { 1905 $aConfigSettings[$sKey] = array( 1906 'show_in_conf_sample' => true, 1907 'type' => 'integer', 1908 'value' => $iValue, 1909 ); 1910 } 1911 1912 // Old fashioned remaining values 1913 $aOtherValues = array( 1914 'default_language' => $this->m_sDefaultLanguage, 1915 'allowed_login_types' => $this->m_sAllowedLoginTypes, 1916 'ext_auth_variable' => $this->m_sExtAuthVariable, 1917 'encryption_key' => $this->m_sEncryptionKey, 1918 'encryption_library' => $this->m_sEncryptionLibrary, 1919 'csv_import_charsets' => $this->m_aCharsets, 1920 ); 1921 foreach ($aOtherValues as $sKey => $value) 1922 { 1923 $aConfigSettings[$sKey] = array( 1924 'show_in_conf_sample' => true, 1925 'type' => is_string($value) ? 'string' : 'mixed', 1926 'value' => $value, 1927 ); 1928 } 1929 1930 ksort($aConfigSettings); 1931 fwrite($hFile, "\$MySettings = array(\n"); 1932 foreach ($aConfigSettings as $sPropCode => $aSettingInfo) 1933 { 1934 // Write all values that are either always visible or present in the cloned config file 1935 if ($aSettingInfo['show_in_conf_sample'] || (!empty($aSettingInfo['source_of_value']) && ($aSettingInfo['source_of_value'] != 'unknown'))) 1936 { 1937 $sType = $aSettingInfo['type']; 1938 switch ($sType) 1939 { 1940 case 'bool': 1941 $sSeenAs = $aSettingInfo['value'] ? 'true' : 'false'; 1942 break; 1943 default: 1944 $sSeenAs = self::PrettyVarExport($aSettingInfo['value'], "\t"); 1945 } 1946 fwrite($hFile, "\n"); 1947 if (isset($aSettingInfo['description'])) 1948 { 1949 fwrite($hFile, "\t// $sPropCode: {$aSettingInfo['description']}\n"); 1950 } 1951 if (isset($aSettingInfo['default'])) 1952 { 1953 $default = $aSettingInfo['default']; 1954 if ($aSettingInfo['type'] == 'bool') 1955 { 1956 $default = $default ? 'true' : 'false'; 1957 } 1958 fwrite($hFile, 1959 "\t//\tdefault: ".self::PrettyVarExport($aSettingInfo['default'], "\t//\t\t", true)."\n"); 1960 } 1961 fwrite($hFile, "\t'$sPropCode' => $sSeenAs,\n"); 1962 } 1963 } 1964 fwrite($hFile, ");\n"); 1965 1966 fwrite($hFile, "\n"); 1967 fwrite($hFile, "/**\n *\n * Modules specific settings\n *\n */\n"); 1968 fwrite($hFile, "\$MyModuleSettings = array(\n"); 1969 foreach ($this->m_aModuleSettings as $sModule => $aProperties) 1970 { 1971 fwrite($hFile, "\t'$sModule' => array (\n"); 1972 foreach ($aProperties as $sProperty => $value) 1973 { 1974 $sNiceExport = self::PrettyVarExport($value, "\t\t"); 1975 fwrite($hFile, "\t\t'$sProperty' => $sNiceExport,\n"); 1976 } 1977 fwrite($hFile, "\t),\n"); 1978 } 1979 fwrite($hFile, ");\n"); 1980 1981 fwrite($hFile, "\n/**\n"); 1982 fwrite($hFile, " *\n"); 1983 fwrite($hFile, " * Data model modules to be loaded. Names are specified as relative paths\n"); 1984 fwrite($hFile, " *\n"); 1985 fwrite($hFile, " */\n"); 1986 fwrite($hFile, "\$MyModules = array(\n"); 1987 fwrite($hFile, "\t'addons' => array (\n"); 1988 foreach ($this->m_aAddons as $sKey => $sFile) 1989 { 1990 fwrite($hFile, "\t\t'$sKey' => '$sFile',\n"); 1991 } 1992 fwrite($hFile, "\t),\n"); 1993 fwrite($hFile, ");\n"); 1994 fwrite($hFile, '?'.'>'); // Avoid perturbing the syntax highlighting ! 1995 1996 return fclose($hFile); 1997 } 1998 else 1999 { 2000 throw new ConfigException("Could not write to configuration file", array('file' => $sFileName)); 2001 } 2002 } 2003 2004 /** 2005 * Helper function to initialize a configuration from the page arguments 2006 * 2007 * @param array $aParamValues 2008 * @param string|null $sModulesDir 2009 * @param bool $bPreserveModuleSettings 2010 * 2011 * @throws \Exception 2012 * @throws \CoreException 2013 */ 2014 public function UpdateFromParams($aParamValues, $sModulesDir = null, $bPreserveModuleSettings = false) 2015 { 2016 if (isset($aParamValues['application_path'])) 2017 { 2018 $this->Set('app_root_url', $aParamValues['application_path']); 2019 } 2020 if (isset($aParamValues['graphviz_path'])) 2021 { 2022 $this->Set('graphviz_path', $aParamValues['graphviz_path']); 2023 } 2024 if (isset($aParamValues['mode']) && isset($aParamValues['language'])) 2025 { 2026 if (($aParamValues['mode'] == 'install') || $this->GetDefaultLanguage() == '') 2027 { 2028 $this->SetDefaultLanguage($aParamValues['language']); 2029 } 2030 } 2031 if (isset($aParamValues['db_server'])) 2032 { 2033 $this->Set('db_host', $aParamValues['db_server']); 2034 $this->Set('db_user', $aParamValues['db_user']); 2035 $this->Set('db_pwd', $aParamValues['db_pwd']); 2036 $sDBName = $aParamValues['db_name']; 2037 if ($sDBName == '') 2038 { 2039 // Todo - obsolete after the transition to the new setup (2.0) is complete (WARNING: used by the designer) 2040 if (isset($aParamValues['new_db_name'])) 2041 { 2042 $sDBName = $aParamValues['new_db_name']; 2043 } 2044 } 2045 $this->Set('db_name', $sDBName); 2046 $this->Set('db_subname', $aParamValues['db_prefix']); 2047 2048 $bDbTlsEnabled = (bool) $aParamValues['db_tls_enabled']; 2049 if ($bDbTlsEnabled) 2050 { 2051 $this->Set('db_tls.enabled', $bDbTlsEnabled, 'UpdateFromParams'); 2052 } 2053 else 2054 { 2055 // disabled : we don't want parameter in the file 2056 $this->Set('db_tls.enabled', $bDbTlsEnabled, null); 2057 } 2058 $sDbTlsCa = $bDbTlsEnabled ? $aParamValues['db_tls_ca'] : null; 2059 if (isset($sDbTlsCa) && !empty($sDbTlsCa)) { 2060 $this->Set('db_tls.ca', $sDbTlsCa, 'UpdateFromParams'); 2061 } else { 2062 // empty parameter : we don't want it in the file 2063 $this->Set('db_tls.ca', null, null); 2064 } 2065 } 2066 2067 if (isset($aParamValues['selected_modules'])) 2068 { 2069 $aSelectedModules = explode(',', $aParamValues['selected_modules']); 2070 } 2071 else 2072 { 2073 $aSelectedModules = null; 2074 } 2075 $this->UpdateIncludes($sModulesDir, $aSelectedModules); 2076 2077 if (isset($aParamValues['source_dir'])) 2078 { 2079 $this->Set('source_dir', $aParamValues['source_dir']); 2080 } 2081 } 2082 2083 /** 2084 * Helper function to rebuild the default configuration and the list of includes from a directory and a list of 2085 * selected modules 2086 * 2087 * @param string $sModulesDir The relative path to the directory to scan for modules (typically the 'env-xxx' 2088 * directory resulting from the compilation) 2089 * @param array $aSelectedModules An array of selected modules' identifiers. If null all modules found will be 2090 * considered as installed 2091 * 2092 * @throws Exception 2093 */ 2094 public function UpdateIncludes($sModulesDir, $aSelectedModules = null) 2095 { 2096 if (!is_null($sModulesDir)) 2097 { 2098 // Initialize the arrays below with default values for the application... 2099 $oEmptyConfig = new Config('dummy_file', false); // Do NOT load any config file, just set the default values 2100 $aAddOns = $oEmptyConfig->GetAddOns(); 2101 2102 $aModules = ModuleDiscovery::GetAvailableModules(array(APPROOT.$sModulesDir)); 2103 foreach ($aModules as $sModuleId => $aModuleInfo) 2104 { 2105 list ($sModuleName, $sModuleVersion) = ModuleDiscovery::GetModuleName($sModuleId); 2106 if (is_null($aSelectedModules) || in_array($sModuleName, $aSelectedModules)) 2107 { 2108 if (isset($aModuleInfo['settings'])) 2109 { 2110 list ($sName, $sVersion) = ModuleDiscovery::GetModuleName($sModuleId); 2111 foreach ($aModuleInfo['settings'] as $sProperty => $value) 2112 { 2113 if (isset($this->m_aModuleSettings[$sName][$sProperty])) 2114 { 2115 // Do nothing keep the original value 2116 } 2117 else 2118 { 2119 $this->SetModuleSetting($sName, $sProperty, $value); 2120 } 2121 } 2122 } 2123 if (isset($aModuleInfo['installer'])) 2124 { 2125 $sModuleInstallerClass = $aModuleInfo['installer']; 2126 if (!class_exists($sModuleInstallerClass)) 2127 { 2128 throw new Exception("Wrong installer class: '$sModuleInstallerClass' is not a PHP class - Module: ".$aModuleInfo['label']); 2129 } 2130 if (!is_subclass_of($sModuleInstallerClass, 'ModuleInstallerAPI')) 2131 { 2132 throw new Exception("Wrong installer class: '$sModuleInstallerClass' is not derived from 'ModuleInstallerAPI' - Module: ".$aModuleInfo['label']); 2133 } 2134 $aCallSpec = array($sModuleInstallerClass, 'BeforeWritingConfig'); 2135 call_user_func_array($aCallSpec, array($this)); 2136 } 2137 } 2138 } 2139 $this->SetAddOns($aAddOns); 2140 } 2141 } 2142 2143 /** 2144 * Helper: for an array of string, change the prefix when found 2145 * 2146 * @param array $aStrings 2147 * @param string $sSearchPrefix 2148 * @param string $sNewPrefix 2149 */ 2150 protected static function ChangePrefix(&$aStrings, $sSearchPrefix, $sNewPrefix) 2151 { 2152 foreach ($aStrings as &$sFile) 2153 { 2154 if (substr($sFile, 0, strlen($sSearchPrefix)) == $sSearchPrefix) 2155 { 2156 $sFile = $sNewPrefix.substr($sFile, strlen($sSearchPrefix)); 2157 } 2158 } 2159 } 2160 2161 /** 2162 * Obsolete: kept only for backward compatibility of the Toolkit 2163 * Quick and dirty way to clone a config file into another environment 2164 * 2165 * @param string $sSourceEnv 2166 * @param string $sTargetEnv 2167 */ 2168 public function ChangeModulesPath($sSourceEnv, $sTargetEnv) 2169 { 2170 // Now does nothing since the includes are built into the environment itself 2171 } 2172 2173 /** 2174 * Pretty format a var_export'ed value so that (if possible) the identation is preserved on every line 2175 * 2176 * @param mixed $value The value to export 2177 * @param string $sIndentation The string to use to indent the text 2178 * @param bool $bForceIndentation Forces the identation (enven if it breaks/changes an eval, for example to ouput a 2179 * value inside a comment) 2180 * 2181 * @return string The indented export string 2182 */ 2183 protected static function PrettyVarExport($value, $sIndentation, $bForceIndentation = false) 2184 { 2185 $sExport = var_export($value, true); 2186 $sNiceExport = str_replace(array("\r\n", "\n", "\r"), "\n".$sIndentation, trim($sExport)); 2187 if (!$bForceIndentation) 2188 { 2189 /** @var array $aImported */ 2190 $aImported = null; 2191 eval('$aImported='.$sNiceExport.';'); 2192 // Check if adding the identations at the beginning of each line 2193 // did not modify the values (in case of a string containing a line break) 2194 if ($aImported != $value) 2195 { 2196 $sNiceExport = $sExport; 2197 } 2198 } 2199 2200 return $sNiceExport; 2201 } 2202 2203} 2204