Compare commits

...

36 Commits

Author SHA1 Message Date
Pierre Goiffon
2fd9523c16 🔖 Prepare 2.7.10 version 2024-01-05 15:50:41 +01:00
Pierre Goiffon
a4f6f6e877 N°4368 Fix CORB blocking regression (#598)
Don't send X-Content-Type-Options HTTP header for certain WebPage impl to workaround CORB blocking
To disable globally this new behavior introduced in 9865bf07, set the `security.enable_header_xcontent_type_options` config parameter to false

Thanks @Molkobain for the review !
2024-01-05 10:41:18 +01:00
Molkobain
94c604a6af N°3062 - Fix setup.css compilation test to ensure that it is versioned correctly. 2023-12-21 12:00:26 +01:00
Pierre Goiffon
6995a3c641 N°6889 backup mysqldump call : restore possibility to connect using socket protocol (#591)
With previous fix (N°6123) we forced to use the tcp protocol each time. This was blocking for users wanting to connect using the socket protocol on localhost.

Now for localhost we will : 
- send both port and protocol arguments if the `db_host` config parameter does contain a port
- don't send any of the port or protocol arguments if `db_host` doesn't contain a port
2023-12-20 15:19:50 +01:00
Pierre Goiffon
9865bf0779 N°4368 add sending X-Content-Type-Options HTTP header
Replace in consumers the \WebPage::add_xframe_options call by \WebPage::add_http_headers
2023-12-19 18:25:26 +01:00
Pierre Goiffon
d5449cca42 💡 iTopMutex: add link to mysql doc 2023-12-08 17:20:37 +01:00
Molkobain
5d38d22c50 N°7023 - Fix regression from the initial fix that throw exceptions even for ext. keys set programatically (eg. ComputeValues), which we still want to allow 2023-12-06 16:27:37 +01:00
Pierre Goiffon
99d69493d1 N°7023 - Update tests so that we are now checking negative ext. keys 2023-12-04 22:36:26 +01:00
Molkobain
c9bb628c30 N°7023 - Improve debug message on portal \DBObject::CheckChangedExtKeysValues() call 2023-12-04 22:36:09 +01:00
Molkobain
08e8d15d78 N°7023 - Fix check to write error when adding a contact on a new user request on the end-users portal 2023-12-04 22:35:07 +01:00
Molkobain
7b59df216b N°7005 - Fix portal stylesheets not being re-compiled when outdated
Stylesheets should remain as a relative path in the portal configuration, only when consumed by the TWIG should they become URLs

Note that if not absolute, URLs will be append to ITOP/pages/
2023-11-24 16:40:58 +01:00
Molkobain
cb5eab812e N°938 - Update compiled portal stylesheet 2023-11-24 16:22:36 +01:00
Anne-Catherine
c9b73a7fe2 N°938 - Improve print of portal object page and portal dashboard page (#537)
N°938 - Improve print of portal object page and portal dashboard page
2023-11-24 15:17:42 +01:00
Molkobain
3b2da39469 N°6989 - Security hardening 2023-11-22 18:02:50 +01:00
odain
fc22d91232 N°6949 - Run subset of itop core unit tests after the setup when validating a module github code 2023-11-22 10:14:58 +01:00
Stephen Abello
b10bcb976d N°6951 - Security hardening 2023-11-21 09:42:11 +01:00
Pierre Goiffon
5a43448644 N°6458 Security hardening 2023-11-15 11:14:07 +01:00
Pierre Goiffon
77409eed99 🎨 DBObject small phpdoc fixes 2023-11-13 16:25:37 +01:00
Anne-Catherine
83a70daf68 N°6887 - Fix excessive OQL requests to display user's grant matrix (#564)
* N°6887 - Fix excessive OQL requests to display user's grant matrix

* N°6887 - Rename variable and add PHPDoc

---------

Co-authored-by: Molkobain <lajarige.guillaume@free.fr>
2023-11-08 14:57:28 +01:00
Molkobain
a49a4e6c2b N°6886 - Add OAuth tests folder to removable directories list 2023-10-30 16:54:28 +01:00
Romain Quetiez
7419749ba6 Prerequisites for boosting tests 2023-10-26 20:51:28 +02:00
Romain Quetiez
037dfe1df6 Optimize tests execution time 2023-10-25 17:51:12 +02:00
Romain Quetiez
0b26d45014 Prerequisites for boosting tests 2023-10-25 17:50:41 +02:00
Molkobain
4fd8177165 N°3715 - Fix unit tests 2023-10-23 14:55:06 +02:00
Anne-Catherine
a2cdf214f0 N°3715 - Export above 1000 entries ignore obsolete data from user preference (#468)
* N°3715 - Export above 10000 entries ignore obsolete data from user preference
2023-10-20 17:02:16 +02:00
Anne-Catherine
013173019f N°2909 - Search on Enum, Date, TagSet,... with index fails (#496) 2023-10-20 16:45:35 +02:00
Stephen Abello
9469681a0c N°6777 - Security hardening 2023-10-17 09:12:40 +02:00
Pierre Goiffon
c72cb7e70e N°6606 security hardening 2023-10-13 17:15:37 +02:00
Pierre Goiffon
9df92665e0 N°6606 Backport of utils::ENUM_SANITIZATION_FILTER_* constants
Were introduced in 3.0.0, but not added to the support/2.7 branch
2023-10-13 17:10:35 +02:00
Molkobain
8ecebee511 PHP unit tests: Fix typo for "final private" methods as they can't be both 2023-09-20 16:11:39 +02:00
Pierre Goiffon
35cd965360 N°6629 Update ci_description php_version 2023-09-19 12:25:40 +02:00
Pierre Goiffon
e5dd51f637 N°6600 Portal download attachment : don't display anymore SQL query on attachment not found error (#525) 2023-09-19 09:54:43 +02:00
Molkobain
0a6c82dfe1 N°6752 - PHP unit tests: Fix typo in postbuild_integration.xml.dist 2023-09-19 08:37:46 +02:00
Molkobain
24c0f4950f Add missing .htaccess / web.config files in .gitignore for /extensions folder 2023-09-18 15:26:06 +02:00
Molkobain
d4dbbc59d4 N°6754 - PHP unit tests: Add local PHPUnit XML files to .gitignore 2023-09-18 15:23:52 +02:00
Molkobain
dc0cd44c79 N°6752 - PHP unit tests: Migrate usages of unitestautoload.php to composer autoloader 2023-09-18 15:14:44 +02:00
119 changed files with 1496 additions and 336 deletions

6
.gitignore vendored
View File

@@ -24,7 +24,9 @@ tests/*/vendor/*
# iTop extensions
/extensions/**
!/extensions/.htaccess
!/extensions/readme.txt
!/extensions/web.config
# all logs but listing prevention
/log/**
@@ -32,8 +34,10 @@ tests/*/vendor/*
!/log/index.php
!/log/web.config
# PHPUnit cache file
# PHPUnit: Cache file, local XML working copies
/tests/php-unit-tests/.phpunit.result.cache
/tests/php-unit-tests/phpunit.xml
/tests/php-unit-tests/postbuild_integration.xml
# Jetbrains

View File

@@ -425,6 +425,12 @@ class UserRightsProfile extends UserRightsAddOnAPI
UR_ACTION_BULK_DELETE => 'bd',
);
/**
* @var array $aUsersProfilesList Cache of users' profiles. Hash array of user ID => [profile ID => profile friendlyname, profile ID => profile friendlyname, ...]
* @since 2.7.10 3.0.4 3.1.1 3.2.0 N°6887
*/
private $aUsersProfilesList = [];
// Installation: create the very first user
public function CreateAdministrator($sAdminUser, $sAdminPwd, $sLanguage = 'EN US')
{
@@ -654,8 +660,12 @@ class UserRightsProfile extends UserRightsAddOnAPI
$sAction = self::$m_aActionCodes[$iActionCode];
$bStatus = null;
// Cache user's profiles
if(false === array_key_exists($iUser, $this->aUsersProfilesList)){
$this->aUsersProfilesList[$iUser] = UserRights::ListProfiles($oUser);
}
// Call the API of UserRights because it caches the list for us
foreach(UserRights::ListProfiles($oUser) as $iProfile => $oProfile)
foreach($this->aUsersProfilesList[$iUser] as $iProfile => $oProfile)
{
$bGrant = $this->GetProfileActionGrant($iProfile, $sClass, $sAction);
if (!is_null($bGrant))
@@ -781,11 +791,16 @@ class UserRightsProfile extends UserRightsAddOnAPI
// Note: this code is VERY close to the code of IsActionAllowed()
$iUser = $oUser->GetKey();
// Cache user's profiles
if(false === array_key_exists($iUser, $this->aUsersProfilesList)){
$this->aUsersProfilesList[$iUser] = UserRights::ListProfiles($oUser);
}
// Note: The object set is ignored because it was interesting to optimize for huge data sets
// and acceptable to consider only the root class of the object set
$bStatus = null;
// Call the API of UserRights because it caches the list for us
foreach(UserRights::ListProfiles($oUser) as $iProfile => $oProfile)
foreach($this->aUsersProfilesList[$iUser] as $iProfile => $oProfile)
{
$bGrant = $this->GetClassStimulusGrant($iProfile, $sClass, $sStimulusCode);
if (!is_null($bGrant))
@@ -814,8 +829,9 @@ class UserRightsProfile extends UserRightsAddOnAPI
}
/**
* Find out which attribute is corresponding the the dimension 'owner org'
* returns null if no such attribute has been found (no filtering should occur)
* @param string $sClass
* @return string|null Find out which attribute is corresponding the dimension 'owner org'
* returns null if no such attribute has been found (no filtering should occur)
*/
public static function GetOwnerOrganizationAttCode($sClass)
{

View File

@@ -604,10 +604,10 @@ class UserRightsProfile extends UserRightsAddOnAPI
/**
* Read and cache organizations allowed to the given user
*
* @param $oUser
* @param $sClass (not used here but can be used in overloads)
* @param User $oUser
* @param string $sClass (not used here but can be used in overloads)
*
* @return array
* @return array keys of the User allowed org
* @throws \CoreException
* @throws \Exception
*/

View File

@@ -42,7 +42,7 @@ class ajax_page extends WebPage implements iTabbedPage
$this->m_sReadyScript = "";
//$this->add_header("Content-type: text/html; charset=utf-8");
$this->no_cache();
$this->add_xframe_options();
$this->add_http_headers();
$this->m_oTabs = new TabManager();
$this->sContentType = 'text/html';
$this->sContentDisposition = 'inline';
@@ -51,6 +51,16 @@ class ajax_page extends WebPage implements iTabbedPage
utils::InitArchiveMode();
}
/**
* Disabling sending the header so that resource won't be blocked by CORB. See parent method documentation.
* @return void
* @since 2.7.10 3.0.4 3.1.2 3.2.0 N°4368 method creation
*/
public function add_xcontent_type_options()
{
// Nothing to do !
}
/**
* @inheritDoc
* @throws \Exception

View File

@@ -1621,6 +1621,8 @@ class RestUtils
*
* @return DBObject The object found
* @throws Exception If the input structure is not valid or it could not find exactly one object
*
* @see DBObject::CheckChangedExtKeysValues() generic method to check that we can access the linked object isn't used in that use case because values can be literal, OQL, friendlyname
*/
public static function FindObjectFromKey($sClass, $key, $bAllowNullValue = false)
{

View File

@@ -4764,6 +4764,11 @@ EOF
);
if ($bResult && (!$bPreview))
{
// doing the check will load multiple times same objects :/
// but it shouldn't cost too much on execution time
// user can mitigate by selecting less extkeys/lnk to set and/or less objects to update 🤷‍♂️
$oObj->CheckChangedExtKeysValues();
$oObj->DBUpdate();
}
}

View File

@@ -33,7 +33,7 @@ class CSVPage extends WebPage
parent::__construct($s_title);
$this->add_header("Content-type: text/plain; charset=".self::PAGES_CHARSET);
$this->no_cache();
$this->add_xframe_options();
$this->add_http_headers();
//$this->add_header("Content-Transfer-Encoding: binary");
}

View File

@@ -1193,12 +1193,12 @@ EOF
$sOkButtonLabel = Dict::S('UI:Button:Save');
$sCancelButtonLabel = Dict::S('UI:Button:Cancel');
$sId = addslashes($this->sId);
$sLayoutClass = addslashes($this->sLayoutClass);
$sId = utils::HtmlEntities($this->sId);
$sLayoutClass = utils::HtmlEntities($this->sLayoutClass);
$sAutoReload = $this->bAutoReload ? 'true' : 'false';
$sAutoReloadSec = (string) $this->iAutoReloadSec;
$sTitle = addslashes($this->sTitle);
$sFile = addslashes($this->GetDefinitionFile());
$sTitle = utils::HtmlEntities($this->sTitle);
$sFile = utils::HtmlEntities($this->GetDefinitionFile());
$sUrl = utils::GetAbsoluteUrlAppRoot().'pages/ajax.render.php';
$sReloadURL = $this->GetReloadURL();

View File

@@ -71,7 +71,7 @@ class iTopWebPage extends NiceWebPage implements iTabbedPage
$this->SetRootUrl(utils::GetAbsoluteUrlAppRoot());
$this->add_header("Content-type: text/html; charset=".self::PAGES_CHARSET);
$this->no_cache();
$this->add_xframe_options();
$this->add_http_headers();
$this->add_linked_stylesheet("../css/jquery.treeview.css");
$this->add_linked_stylesheet("../css/jquery.autocomplete.css");
$this->add_linked_stylesheet("../css/jquery-ui-timepicker-addon.css");

View File

@@ -85,7 +85,7 @@ class LoginWebPage extends NiceWebPage
parent::__construct($sTitle);
$this->SetStyleSheet();
$this->no_cache();
$this->add_xframe_options();
$this->add_http_headers();
}
public function SetStyleSheet()

View File

@@ -45,6 +45,74 @@ class FileUploadException extends Exception
*/
class utils
{
/**
* @var string
* @since 2.7.10 3.0.0
*/
public const ENUM_SANITIZATION_FILTER_INTEGER = 'integer';
/**
* Datamodel class
* @var string
* @since 2.7.10 3.0.0
* @since 2.7.10 3.0.4 3.1.1 3.2.0 N°6606 update PHPDoc
* @uses MetaModel::IsValidClass()
*/
public const ENUM_SANITIZATION_FILTER_CLASS = 'class';
/**
* @var string
* @since 2.7.10 3.0.4 3.1.1 3.2.0 N°6606
* @uses class_exists()
*/
public const ENUM_SANITIZATION_FILTER_PHP_CLASS = 'php_class';
/**
* @var string
* @since 2.7.10 3.0.0
*/
public const ENUM_SANITIZATION_FILTER_STRING = 'string';
/**
* @var string
* @since 2.7.10 3.0.0
*/
public const ENUM_SANITIZATION_FILTER_CONTEXT_PARAM = 'context_param';
/**
* @var string
* @since 2.7.10 3.0.0
*/
public const ENUM_SANITIZATION_FILTER_PARAMETER = 'parameter';
/**
* @var string
* @since 2.7.10 3.0.0
*/
public const ENUM_SANITIZATION_FILTER_FIELD_NAME = 'field_name';
/**
* @var string
* @since 2.7.10 3.0.0
*/
public const ENUM_SANITIZATION_FILTER_TRANSACTION_ID = 'transaction_id';
/**
* @var string For XML / HTML node identifiers
* @since 2.7.10 3.0.0
*/
public const ENUM_SANITIZATION_FILTER_ELEMENT_IDENTIFIER = 'element_identifier';
/**
* @var string
* @since 2.7.10 3.0.0
*/
public const ENUM_SANITIZATION_FILTER_RAW_DATA = 'raw_data';
/**
* @var string
* @since 3.0.2 3.1.0 N°4899
* @since 2.7.10 N°6606
*/
public const ENUM_SANITIZATION_FILTER_URL = 'url';
/**
* @var string
* @since 3.0.0
* @since 2.7.10 N°6606
*/
public const DEFAULT_SANITIZATION_FILTER = self::ENUM_SANITIZATION_FILTER_RAW_DATA;
/**
* Cache when getting config from disk or set externally (using {@link SetConfig})
* @internal
@@ -275,8 +343,7 @@ class utils
/**
* @param string|string[] $value
* @param string $sSanitizationFilter one of : integer, class, string, context_param, parameter, field_name,
* element_identifier, transaction_id, parameter, raw_data
* @param string $sSanitizationFilter one of utils::ENUM_SANITIZATION_* const
*
* @return string|string[]|bool boolean for :
* * the 'class' filter (true if valid, false otherwise)
@@ -285,16 +352,20 @@ class utils
* @since 2.5.2 2.6.0 new 'transaction_id' filter
* @since 2.7.0 new 'element_identifier' filter
* @since 2.7.7, 3.0.2, 3.1.0 N°4899 - new 'url' filter
* @since 2.7.10 N°6606 use the utils::ENUM_SANITIZATION_* const
* @since 2.7.10 N°6606 new case for ENUM_SANITIZATION_FILTER_PHP_CLASS
*
* @link https://www.php.net/manual/en/filter.filters.sanitize.php PHP sanitization filters
*/
protected static function Sanitize_Internal($value, $sSanitizationFilter)
{
switch ($sSanitizationFilter)
{
case 'integer':
case static::ENUM_SANITIZATION_FILTER_INTEGER:
$retValue = filter_var($value, FILTER_SANITIZE_NUMBER_INT);
break;
case 'class':
case static::ENUM_SANITIZATION_FILTER_CLASS:
$retValue = $value;
if (!MetaModel::IsValidClass($value))
{
@@ -302,14 +373,21 @@ class utils
}
break;
case 'string':
case static::ENUM_SANITIZATION_FILTER_STRING:
$retValue = filter_var($value, FILTER_SANITIZE_SPECIAL_CHARS);
break;
case 'context_param':
case 'parameter':
case 'field_name':
case 'transaction_id':
case static::ENUM_SANITIZATION_FILTER_PHP_CLASS:
$retValue = $value;
if (!class_exists($value)) {
$retValue = false;
}
break;
case static::ENUM_SANITIZATION_FILTER_CONTEXT_PARAM:
case static::ENUM_SANITIZATION_FILTER_PARAMETER:
case static::ENUM_SANITIZATION_FILTER_FIELD_NAME:
case static::ENUM_SANITIZATION_FILTER_TRANSACTION_ID:
if (is_array($value))
{
$retValue = array();
@@ -327,7 +405,7 @@ class utils
{
switch ($sSanitizationFilter)
{
case 'transaction_id':
case static::ENUM_SANITIZATION_FILTER_TRANSACTION_ID:
// same as parameter type but keep the dot character
// see N°1835 : when using file transaction_id on Windows you get *.tmp tokens
// it must be included at the regexp beginning otherwise you'll get an invalid character error
@@ -335,18 +413,18 @@ class utils
array("options" => array("regexp" => '/^[\. A-Za-z0-9_=-]*$/')));
break;
case 'parameter':
case static::ENUM_SANITIZATION_FILTER_PARAMETER:
$retValue = filter_var($value, FILTER_VALIDATE_REGEXP,
array("options" => array("regexp" => '/^[ A-Za-z0-9_=-]*$/'))); // the '=', '%3D, '%2B', '%2F'
// characters are used in serialized filters (starting 2.5, only the url encoded versions are presents, but the "=" is kept for BC)
break;
case 'field_name':
case static::ENUM_SANITIZATION_FILTER_FIELD_NAME:
$retValue = filter_var($value, FILTER_VALIDATE_REGEXP,
array("options" => array("regexp" => '/^[A-Za-z0-9_]+(->[A-Za-z0-9_]+)*$/'))); // att_code or att_code->name or AttCode->Name or AttCode->Key2->Name
break;
case 'context_param':
case static::ENUM_SANITIZATION_FILTER_CONTEXT_PARAM:
$retValue = filter_var($value, FILTER_VALIDATE_REGEXP,
array("options" => array("regexp" => '/^[ A-Za-z0-9_=%:+-]*$/')));
break;
@@ -356,18 +434,18 @@ class utils
break;
// For XML / HTML node identifiers
case 'element_identifier':
case static::ENUM_SANITIZATION_FILTER_ELEMENT_IDENTIFIER:
$retValue = preg_replace('/[^a-zA-Z0-9_]/', '', $value);
break;
// For URL
case 'url':
case static::ENUM_SANITIZATION_FILTER_URL:
// N°6350 - returns only valid URLs
$retValue = filter_var($value, FILTER_VALIDATE_URL);
break;
default:
case 'raw_data':
case static::ENUM_SANITIZATION_FILTER_RAW_DATA:
$retValue = $value;
// Do nothing
}
@@ -2262,6 +2340,38 @@ class utils
return in_array($sClass, $aHugeClasses);
}
/**
* Helper around the native strlen() PHP method to test a string for null or empty value
*
* @link https://www.php.net/releases/8.1/en.php#deprecations_and_bc_breaks "Passing null to non-nullable internal function parameters is deprecated"
*
* @param string|null $sString
*
* @return bool if string null or empty
* @since 3.0.2 N°5302
* @since 2.7.10 N°6458 add method in the 2.7 branch
*/
public static function IsNullOrEmptyString(?string $sString): bool
{
return $sString === null || strlen($sString) === 0;
}
/**
* Helper around the native strlen() PHP method to test a string not null or empty value
*
* @link https://www.php.net/releases/8.1/en.php#deprecations_and_bc_breaks "Passing null to non-nullable internal function parameters is deprecated"
*
* @param string|null $sString
*
* @return bool if string is not null and not empty
* @since 3.0.2 N°5302
* @since 2.7.10 N°6458 add method in the 2.7 branch
*/
public static function IsNotNullOrEmptyString(?string $sString): bool
{
return !static::IsNullOrEmptyString($sString);
}
/**
* Check if iTop is in a development environment (VCS vs build number)
*

View File

@@ -483,12 +483,24 @@ class WebPage implements Page
}
/**
* @param string|null $sHeaderValue for example `SAMESITE`. If null will set the header using the config parameter value.
* @param string|null $sXFrameOptionsHeaderValue passed to {@see add_xframe_options}
*
* @return void
* @since 2.7.10 3.0.4 3.1.2 3.2.0 N°4368 method creation, replace {@see add_xframe_options} consumers call
*/
public function add_http_headers($sXFrameOptionsHeaderValue = null)
{
$this->add_xframe_options($sXFrameOptionsHeaderValue);
$this->add_xcontent_type_options();
}
/**
* @param string|null $sHeaderValue for example `SAMESITE`. If null will set the header using the `security_header_xframe` config parameter value.
*
* @since 2.7.3 3.0.0 N°3416
* @uses security_header_xframe config parameter
* @uses \utils::GetConfig()
* @link https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Frame-Options
*
* @link https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Frame-Options HTTP header MDN documentation
*/
public function add_xframe_options($sHeaderValue = null)
{
@@ -499,6 +511,38 @@ class WebPage implements Page
$this->add_header('X-Frame-Options: '.$sHeaderValue);
}
/**
* Warning : this header will trigger the Cross-Origin Read Blocking (CORB) protection for some mime types (HTML, XML except SVG, JSON, text/plain)
* In consequence some children pages will override this method.
*
* Sending header can be disabled globally using the `security.enable_header_xcontent_type_options` optional config parameter.
*
* @return void
* @since 2.7.10 3.0.4 3.1.2 3.2.0 N°4368 method creation
*
* @link https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Content-Type-Options HTTP header MDN documentation
* @link https://chromium.googlesource.com/chromium/src/+/master/services/network/cross_origin_read_blocking_explainer.md#determining-whether-a-response-is-corb_protected "Determining whether a response is CORB-protected"
*/
public function add_xcontent_type_options()
{
try {
$oConfig = utils::GetConfig();
} catch (ConfigException|CoreException $e) {
$oConfig = null;
}
if (is_null($oConfig)) {
$bSendXContentTypeOptionsHttpHeader = true;
} else {
$bSendXContentTypeOptionsHttpHeader = $oConfig->Get('security.enable_header_xcontent_type_options');
}
if ($bSendXContentTypeOptionsHttpHeader === false) {
return;
}
$this->add_header('X-Content-Type-Options: nosniff');
}
/**
* Add needed headers to the page so that it will no be cached
*/

View File

@@ -44,10 +44,20 @@ class XMLPage extends WebPage
$this->m_bHeaderSent = false;
$this->add_header("Content-type: text/xml; charset=".self::PAGES_CHARSET);
$this->no_cache();
$this->add_xframe_options();
$this->add_http_headers();
$this->add_header("Content-location: export.xml");
}
/**
* Disabling sending the header so that resource won't be blocked by CORB. See parent method documentation.
* @return void
* @since 2.7.10 3.0.4 3.1.2 3.2.0 N°4368 method creation
*/
public function add_xcontent_type_options()
{
// Nothing to do !
}
public function output()
{
if (!$this->m_bPassThrough)

View File

@@ -14,7 +14,7 @@ define('APPCONF', APPROOT.'conf/');
* @used-by utils::GetItopVersionWikiSyntax()
* @used-by iTopModulesPhpVersionIntegrationTest
*/
define('ITOP_CORE_VERSION', '2.7.9');
define('ITOP_CORE_VERSION', '2.7.10');
require_once APPROOT.'bootstrap.inc.php';

View File

@@ -149,7 +149,9 @@ abstract class BulkExport
$this->oSearch = null;
$this->iChunkSize = 0;
$this->sFormatCode = null;
$this->aStatusInfo = array();
$this->aStatusInfo = [
'show_obsolete_data' => utils::ShowObsoleteData(),
];
$this->oBulkExportResult = null;
$this->sTmpFile = '';
$this->bLocalizeOutput = false;
@@ -203,15 +205,17 @@ abstract class BulkExport
if ($oInfo && ($oInfo->Get('user_id') == UserRights::GetUserId()))
{
$sFormatCode = $oInfo->Get('format');
$oSearch = DBObjectSearch::unserialize($oInfo->Get('search'));
$aStatusInfo = json_decode($oInfo->Get('status_info'),true);
$oSearch = DBObjectSearch::unserialize($oInfo->Get('search'));
$oSearch->SetShowObsoleteData($aStatusInfo['show_obsolete_data']);
$oBulkExporter = self::FindExporter($sFormatCode, $oSearch);
if ($oBulkExporter)
{
$oBulkExporter->SetFormat($sFormatCode);
$oBulkExporter->SetObjectList($oSearch);
$oBulkExporter->SetChunkSize($oInfo->Get('chunk_size'));
$oBulkExporter->SetStatusInfo(json_decode($oInfo->Get('status_info'), true));
$oBulkExporter->SetStatusInfo($aStatusInfo);
$oBulkExporter->SetLocalizeOutput($oInfo->Get('localize_output'));
@@ -289,6 +293,7 @@ abstract class BulkExport
*/
public function SetObjectList(DBSearch $oSearch)
{
$oSearch->SetShowObsoleteData($this->aStatusInfo['show_obsolete_data']);
$this->oSearch = $oSearch;
}

View File

@@ -134,6 +134,12 @@ class CMDBSource
const ENUM_DB_VENDOR_MARIADB = 'MariaDB';
const ENUM_DB_VENDOR_PERCONA = 'Percona';
/**
* @since 2.7.10 3.0.4 3.1.2 3.0.2 N°6889 constant creation
* @internal will be removed in a future version
*/
const MYSQL_DEFAULT_PORT = 3306;
/**
* Error: 1205 SQLSTATE: HY000 (ER_LOCK_WAIT_TIMEOUT)
* Message: Lock wait timeout exceeded; try restarting transaction
@@ -319,16 +325,19 @@ class CMDBSource
/**
* @param string $sDbHost initial value ("p:domain:port" syntax)
* @param string $sServer server variable to update
* @param int $iPort port variable to update
* @param int|null $iPort port variable to update, will return null if nothing is specified in $sDbHost
*
* @since 2.7.10 3.0.4 3.1.2 3.2.0 N°6889 will return null in $iPort if port isn't present in $sDbHost. Use {@see MYSQL_DEFAULT_PORT} if needed
*
* @link http://php.net/manual/en/mysqli.persistconns.php documentation for the "p:" prefix (persistent connexion)
*/
public static function InitServerAndPort($sDbHost, &$sServer, &$iPort)
{
$aConnectInfo = explode(':', $sDbHost);
$bUsePersistentConnection = false;
if (strcasecmp($aConnectInfo[0], 'p') == 0)
if (strcasecmp($aConnectInfo[0], 'p') === 0)
{
// we might have "p:" prefix to use persistent connections (see http://php.net/manual/en/mysqli.persistconns.php)
$bUsePersistentConnection = true;
$sServer = $aConnectInfo[0].':'.$aConnectInfo[1];
}
@@ -346,10 +355,6 @@ class CMDBSource
{
$iPort = (int)($aConnectInfo[1]);
}
else
{
$iPort = 3306;
}
}
/**

View File

@@ -1320,6 +1320,14 @@ class Config
'source_of_value' => '',
'show_in_conf_sample' => false,
],
'security.enable_header_xcontent_type_options' => [
'type' => 'bool',
'description' => 'If set to false, iTop will stop sending the X-Content-Type-Options HTTP header. This header could trigger CORB protection on certain resources (JSON, XML, HTML, text) therefore blocking them.',
'default' => true,
'value' => '',
'source_of_value' => '',
'show_in_conf_sample' => false,
],
'behind_reverse_proxy' => [
'type' => 'bool',
'description' => 'If true, then proxies custom header (X-Forwarded-*) are taken into account. Use only if the webserver is not publicly accessible (reachable only by the reverse proxy)',

View File

@@ -229,12 +229,47 @@ class CoreUnexpectedValue extends CoreException
{
}
/**
* @since 2.7.10 3.0.4 3.1.1 3.2.0 N°6458 object creation
*/
class InvalidExternalKeyValueException extends CoreUnexpectedValue
{
private const ENUM_PARAMS_OBJECT = 'current_object';
private const ENUM_PARAMS_ATTCODE = 'attcode';
private const ENUM_PARAMS_ATTVALUE = 'attvalue';
private const ENUM_PARAMS_USER = 'current_user';
public function __construct($oObject, $sAttCode, $aContextData = null, $oPrevious = null)
{
$aContextData[self::ENUM_PARAMS_OBJECT] = get_class($oObject) . '::' . $oObject->GetKey();
$aContextData[self::ENUM_PARAMS_ATTCODE] = $sAttCode;
$aContextData[self::ENUM_PARAMS_ATTVALUE] = $oObject->Get($sAttCode);
$oCurrentUser = UserRights::GetUserObject();
if (false === is_null($oCurrentUser)) {
$aContextData[self::ENUM_PARAMS_USER] = get_class($oCurrentUser) . '::' . $oCurrentUser->GetKey();
}
parent::__construct('Attribute pointing to an object that is either non existing or not readable by the current user', $aContextData, '', $oPrevious);
}
public function GetAttCode(): string
{
return $this->getContextData()[self::ENUM_PARAMS_ATTCODE];
}
public function GetAttValue(): string
{
return $this->getContextData()[self::ENUM_PARAMS_ATTVALUE];
}
}
class SecurityException extends CoreException
{
}
/**
* Throwned when querying on an object that exists in the database but is archived
* Thrown when querying on an object that exists in the database but is archived
*
* @see N.1108
* @since 2.5.1

View File

@@ -15,6 +15,7 @@
//
// You should have received a copy of the GNU Affero General Public License
// along with iTop. If not, see <http://www.gnu.org/licenses/>
use Combodo\iTop\Application\Helper\ExportHelper;
/**
* Bulk export: CSV export
@@ -113,6 +114,7 @@ class CSVBulkExport extends TabularBulkExport
case 'csv_options':
$oP->add('<fieldset><legend>'.Dict::S('Core:BulkExport:CSVOptions').'</legend>');
$oP->add(ExportHelper::GetAlertForExcelMaliciousInjection());
$oP->add('<table class="export_parameters"><tr><td style="vertical-align:top">');
$oP->add('<h3>'.Dict::S('UI:CSVImport:SeparatorCharacter').'</h3>');
$sRawSeparator = utils::ReadParam('separator', ',', true, 'raw_data');

View File

@@ -2140,7 +2140,6 @@ abstract class DBObject implements iDisplay
* @throws \ArchivedObjectException
* @throws \CoreException
* @throws \OQLException
*
*/
public function DoCheckToWrite()
{
@@ -2195,7 +2194,6 @@ abstract class DBObject implements iDisplay
}
/**
*
* @api
* @api-advanced
*
@@ -2211,7 +2209,6 @@ abstract class DBObject implements iDisplay
* @throws \ArchivedObjectException
* @throws \CoreException
* @throws \OQLException
*
*/
final public function CheckToWrite()
{
@@ -2238,6 +2235,87 @@ abstract class DBObject implements iDisplay
return array($this->m_bCheckStatus, $this->m_aCheckIssues, $this->m_bSecurityIssue);
}
/**
* Checks for extkey attributes values. This will throw exception on non-existing as well as non-accessible objects (silo, scopes).
* That's why the test is done for all users including Administrators
*
* Note that due to perf issues, this isn't called directly by the ORM, but has to be called by consumers when possible.
*
* @param callable(string, string):bool|null $oIsObjectLoadableCallback Override to check if object is accessible.
* Parameters are object class and key
* Return value should be false if cannot access object, true otherwise
* @return void
*
* @throws ArchivedObjectException
* @throws CoreException if cannot get object attdef list
* @throws CoreUnexpectedValue
* @throws InvalidExternalKeyValueException
* @throws MySQLException
* @throws SecurityException if one extkey is pointing to an invalid value
*
* @link https://github.com/Combodo/iTop/security/advisories/GHSA-245j-66p9-pwmh
* @since 2.7.10 3.0.4 3.1.1 3.2.0 N°6458
*
* @see \RestUtils::FindObjectFromKey for the same check in the REST endpoint
*/
final public function CheckChangedExtKeysValues(callable $oIsObjectLoadableCallback = null)
{
if (is_null($oIsObjectLoadableCallback)) {
$oIsObjectLoadableCallback = function ($sClass, $sId) {
$oRemoteObject = MetaModel::GetObject($sClass, $sId, false);
if (is_null($oRemoteObject)) {
return false;
}
return true;
};
}
$aChanges = $this->ListChanges();
$aAttCodesChanged = array_keys($aChanges);
foreach ($aAttCodesChanged as $sAttDefCode) {
$oAttDef = MetaModel::GetAttributeDef(get_class($this), $sAttDefCode);
if ($oAttDef instanceof AttributeLinkedSetIndirect) {
/** @var ormLinkSet $oOrmSet */
$oOrmSet = $this->Get($sAttDefCode);
while ($oLnk = $oOrmSet->Fetch()) {
$oLnk->CheckChangedExtKeysValues($oIsObjectLoadableCallback);
}
continue;
}
/** @noinspection PhpConditionCheckedByNextConditionInspection */
/** @noinspection NotOptimalIfConditionsInspection */
if (($oAttDef instanceof AttributeHierarchicalKey) || ($oAttDef instanceof AttributeExternalKey)) {
$sRemoteObjectClass = $oAttDef->GetTargetClass();
$sRemoteObjectKey = $this->Get($sAttDefCode);
} else if ($oAttDef instanceof AttributeObjectKey) {
$sRemoteObjectClassAttCode = $oAttDef->Get('class_attcode');
$sRemoteObjectClass = $this->Get($sRemoteObjectClassAttCode);
$sRemoteObjectKey = $this->Get($sAttDefCode);
} else {
continue;
}
if (utils::IsNullOrEmptyString($sRemoteObjectClass)
|| utils::IsNullOrEmptyString($sRemoteObjectKey)
) {
continue;
}
// 0 : Undefined ext. key (EG. non-mandatory and no value provided)
// < 0 : Non yet persisted object
/** @noinspection TypeUnsafeComparisonInspection Non-strict comparison as object ID can be string */
if ($sRemoteObjectKey <= 0) {
continue;
}
if (false === $oIsObjectLoadableCallback($sRemoteObjectClass, $sRemoteObjectKey)) {
throw new InvalidExternalKeyValueException($this, $sAttDefCode);
}
}
}
/**
* Check if it is allowed to delete the existing object from the database
*
@@ -2383,13 +2461,13 @@ abstract class DBObject implements iDisplay
* @api
* @api-advanced
*
* @see \DBObject::ListPreviousValuesForUpdatedAttributes() to get previous values anywhere in the CRUD stack
* @see https://www.itophub.io/wiki/page?id=latest%3Acustomization%3Asequence_crud iTop CRUD stack documentation
* @return array attname => currentvalue List the attributes that have been changed using {@see DBObject::Set()}.
* @return array attcode => currentvalue List the attributes that have been changed using {@see DBObject::Set()}.
* Reset during {@see DBObject::DBUpdate()}
* @throws Exception
* @see \DBObject::ListPreviousValuesForUpdatedAttributes() to get previous values anywhere in the CRUD stack
* @see https://www.itophub.io/wiki/page?id=latest%3Acustomization%3Asequence_crud iTop CRUD stack documentation
* @uses m_aCurrValues
*/
*/
public function ListChanges()
{
if ($this->m_bIsInDB)
@@ -2680,7 +2758,6 @@ abstract class DBObject implements iDisplay
* @throws \Exception
*
* @internal
*
*/
public function DBInsertNoReload()
{
@@ -2960,8 +3037,6 @@ abstract class DBObject implements iDisplay
* Persist an object to the DB, for the first time
*
* @api
* @see DBWrite
*
* @return int|null inserted object key
*
* @throws \ArchivedObjectException
@@ -2971,10 +3046,12 @@ abstract class DBObject implements iDisplay
* @throws \CoreWarning
* @throws \MySQLException
* @throws \OQLException
*
* @see DBWrite
*/
public function DBInsert()
{
$this->DBInsertNoReload();
$this->DBInsertNoReload();
if (MetaModel::DBIsReadOnly())
{
@@ -3073,13 +3150,13 @@ abstract class DBObject implements iDisplay
* Update an object in DB
*
* @api
* @see DBObject::DBWrite()
*
* @return int object key
*
* @throws \CoreException
* @throws \CoreCannotSaveObjectException if CheckToWrite() returns issues
* @throws \Exception
*
* @see DBObject::DBWrite()
*/
public function DBUpdate()
{
@@ -3087,6 +3164,7 @@ abstract class DBObject implements iDisplay
{
throw new CoreException("DBUpdate: could not update a newly created object, please call DBInsert instead");
}
// Protect against reentrance (e.g. cascading the update of ticket logs)
static $aUpdateReentrance = array();
$sKey = get_class($this).'::'.$this->GetKey();
@@ -3418,13 +3496,18 @@ abstract class DBObject implements iDisplay
/**
* Make the current changes persistent - clever wrapper for Insert or Update
*
* @api
*
* @api
*
* @return int
*
* @throws \CoreCannotSaveObjectException
* @throws \CoreException
*
* @throws ArchivedObjectException
* @throws CoreCannotSaveObjectException
* @throws CoreException
* @throws CoreUnexpectedValue
* @throws CoreWarning
* @throws MySQLException
* @throws OQLException
*/
public function DBWrite()
{

View File

@@ -23,6 +23,8 @@
* @license http://opensource.org/licenses/AGPL-3.0
*/
use Combodo\iTop\Application\Helper\ExportHelper;
require_once(APPROOT.'application/xlsxwriter.class.php');
class ExcelBulkExport extends TabularBulkExport
@@ -89,6 +91,7 @@ class ExcelBulkExport extends TabularBulkExport
case 'xlsx_options':
$oP->add('<fieldset><legend>'.Dict::S('Core:BulkExport:XLSXOptions').'</legend>');
$oP->add(ExportHelper::GetAlertForExcelMaliciousInjection());
$oP->add('<table class="export_parameters"><tr><td style="vertical-align:top">');
$sChecked = (utils::ReadParam('formatted_text', 0) == 1) ? ' checked ' : '';

View File

@@ -1213,8 +1213,10 @@ abstract class MetaModel
*
* @return AttributeDefinition[]
* @throws \CoreException
*
* @see GetAttributesList for attcode list
*/
final static public function ListAttributeDefs($sClass)
final public static function ListAttributeDefs($sClass)
{
self::_check_subclass($sClass);
return self::$m_aAttribDefs[$sClass];
@@ -1223,8 +1225,10 @@ abstract class MetaModel
/**
* @param string $sClass
*
* @return array
* @return string[] list of attcodes
* @throws \CoreException
*
* @see ListAttributeDefs to get AttributeDefinition array instead
*/
final public static function GetAttributesList($sClass)
{
@@ -6723,7 +6727,13 @@ abstract class MetaModel
if ($bMustBeFound && empty($aRow))
{
throw new CoreException("No result for the single row query: '$sSQL'");
$sNotFoundErrorMessage = "No result for the single row query";
IssueLog::Info($sNotFoundErrorMessage, LogChannels::CMDB_SOURCE, [
'class' => $sClass,
'key' => $iKey,
'sql_query' => $sSQL,
]);
throw new CoreException($sNotFoundErrorMessage);
}
return $aRow;

View File

@@ -22,7 +22,9 @@
* A class to serialize the execution of some code sections
* Emulates the API of PECL Mutex class
* Relies on MySQL locks because the API sem_get is not always present in the
* installed PHP.
* installed PHP.
*
* @link https://dev.mysql.com/doc/refman/5.7/en/locking-functions.html MySQL locking functions documentation
*
* @copyright Copyright (C) 2013-2018 Combodo SARL
* @license http://opensource.org/licenses/AGPL-3.0

View File

@@ -817,6 +817,9 @@ class UserRights
}
}
/**
* @return string connected {@see User} login field value, otherwise empty string
*/
public static function GetUser()
{
if (is_null(self::$m_oUser))
@@ -829,7 +832,9 @@ class UserRights
}
}
/** User */
/**
* @return User|null
*/
public static function GetUserObject()
{
if (is_null(self::$m_oUser))
@@ -1029,7 +1034,7 @@ class UserRights
/**
* @param string $sClass
* @param int $iActionCode
* @param int $iActionCode see UR_ACTION_* constants
* @param DBObjectSet $oInstanceSet
* @param User $oUser
* @return int (UR_ALLOWED_YES|UR_ALLOWED_NO|UR_ALLOWED_DEPENDS)

View File

@@ -17,7 +17,7 @@
*/
// Beware the version number MUST be enclosed with quotes otherwise v2.3.0 becomes v2 0.3 .0
$version: "v2.7.9";
$version: "v2.7.10";
$approot-relative: "../../../../../" !default; // relative to env-***/branding/themes/***/main.css
// Base colors

View File

@@ -5,7 +5,7 @@
SetupWebPage::AddModule(
__FILE__, // Path to the current file, all other file names are relative to the directory containing this file
'authent-cas/2.7.9',
'authent-cas/2.7.10',
array(
// Identification
//

View File

@@ -27,7 +27,7 @@
SetupWebPage::AddModule(
__FILE__, // Path to the current file, all other file names are relative to the directory containing this file
'authent-external/2.7.9',
'authent-external/2.7.10',
array(
// Identification
//

View File

@@ -9,7 +9,7 @@ if (function_exists('ldap_connect'))
SetupWebPage::AddModule(
__FILE__, // Path to the current file, all other file names are relative to the directory containing this file
'authent-ldap/2.7.9',
'authent-ldap/2.7.10',
array(
// Identification
//

View File

@@ -3,7 +3,7 @@
SetupWebPage::AddModule(
__FILE__, // Path to the current file, all other file names are relative to the directory containing this file
'authent-local/2.7.9',
'authent-local/2.7.10',
array(
// Identification
//

View File

@@ -24,7 +24,7 @@
/** @noinspection PhpUnhandledExceptionInspection */
SetupWebPage::AddModule(
__FILE__, // Path to the current file, all other file names are relative to the directory containing this file
'combodo-db-tools/2.7.9',
'combodo-db-tools/2.7.10',
array(
// Identification
//

View File

@@ -19,7 +19,7 @@
SetupWebPage::AddModule(
__FILE__, // Path to the current file, all other file names are relative to the directory containing this file
'itop-attachments/2.7.9',
'itop-attachments/2.7.10',
array(
// Identification
//

View File

@@ -3,7 +3,7 @@
SetupWebPage::AddModule(
__FILE__, // Path to the current file, all other file names are relative to the directory containing this file
'itop-backup/2.7.9',
'itop-backup/2.7.10',
array(
// Identification
//

View File

@@ -3,7 +3,7 @@
SetupWebPage::AddModule(
__FILE__, // Path to the current file, all other file names are relative to the directory containing this file
'itop-bridge-virtualization-storage/2.7.9',
'itop-bridge-virtualization-storage/2.7.10',
array(
// Identification
//

View File

@@ -3,7 +3,7 @@
SetupWebPage::AddModule(
__FILE__, // Path to the current file, all other file names are relative to the directory containing this file
'itop-change-mgmt-itil/2.7.9',
'itop-change-mgmt-itil/2.7.10',
array(
// Identification
//

View File

@@ -3,7 +3,7 @@
SetupWebPage::AddModule(
__FILE__, // Path to the current file, all other file names are relative to the directory containing this file
'itop-change-mgmt/2.7.9',
'itop-change-mgmt/2.7.10',
array(
// Identification
//

View File

@@ -3,7 +3,7 @@
SetupWebPage::AddModule(
__FILE__, // Path to the current file, all other file names are relative to the directory containing this file
'itop-config-mgmt/2.7.9',
'itop-config-mgmt/2.7.10',
array(
// Identification
//

View File

@@ -3,7 +3,7 @@
SetupWebPage::AddModule(
__FILE__, // Path to the current file, all other file names are relative to the directory containing this file
'itop-config/2.7.9',
'itop-config/2.7.10',
array(
// Identification
//

View File

@@ -24,7 +24,7 @@
/** @noinspection PhpUnhandledExceptionInspection */
SetupWebPage::AddModule(
__FILE__, // Path to the current file, all other file names are relative to the directory containing this file
'itop-core-update/2.7.9',
'itop-core-update/2.7.10',
array(
// Identification
//

View File

@@ -18,7 +18,7 @@
SetupWebPage::AddModule(
__FILE__, // Path to the current file, all other file names are relative to the directory containing this file
'itop-datacenter-mgmt/2.7.9',
'itop-datacenter-mgmt/2.7.10',
array(
// Identification
//

View File

@@ -25,7 +25,7 @@
SetupWebPage::AddModule(
__FILE__, // Path to the current file, all other file names are relative to the directory containing this file
'itop-endusers-devices/2.7.9',
'itop-endusers-devices/2.7.10',
array(
// Identification
//

View File

@@ -24,7 +24,7 @@
/** @noinspection PhpUnhandledExceptionInspection */
SetupWebPage::AddModule(
__FILE__, // Path to the current file, all other file names are relative to the directory containing this file
'itop-files-information/2.7.9',
'itop-files-information/2.7.10',
array(
// Identification
//

View File

@@ -6,7 +6,7 @@
SetupWebPage::AddModule(
__FILE__, // Path to the current file, all other file names are relative to the directory containing this file
'itop-full-itil/2.7.9',
'itop-full-itil/2.7.10',
array(
// Identification
//

View File

@@ -7,7 +7,7 @@ class HubConnectorPage extends NiceWebPage
parent::__construct($sTitle);
$this->no_cache();
$this->add_xframe_options();
$this->add_http_headers();
$sImagesDir = utils::GetAbsoluteUrlAppRoot().'images';
$sModuleImagesDir = utils::GetAbsoluteUrlModulesRoot().'itop-hub-connector/images';

View File

@@ -5,7 +5,7 @@
SetupWebPage::AddModule(
__FILE__, // Path to the current file, all other file names are relative to the directory containing this file
'itop-hub-connector/2.7.9',
'itop-hub-connector/2.7.10',
array(
// Identification
//

View File

@@ -3,7 +3,7 @@
SetupWebPage::AddModule(
__FILE__, // Path to the current file, all other file names are relative to the directory containing this file
'itop-incident-mgmt-itil/2.7.9',
'itop-incident-mgmt-itil/2.7.10',
array(
// Identification
//

View File

@@ -3,7 +3,7 @@
SetupWebPage::AddModule(
__FILE__, // Path to the current file, all other file names are relative to the directory containing this file
'itop-knownerror-mgmt/2.7.9',
'itop-knownerror-mgmt/2.7.10',
array(
// Identification
//

View File

@@ -5,7 +5,7 @@
SetupWebPage::AddModule(
__FILE__, // Path to the current file, all other file names are relative to the directory containing this file
'itop-oauth-client/2.7.9',
'itop-oauth-client/2.7.10',
array(
// Identification
//

View File

@@ -20,7 +20,7 @@
/** @noinspection PhpUnhandledExceptionInspection */
SetupWebPage::AddModule(
__FILE__, // Path to the current file, all other file names are relative to the directory containing this file
'itop-portal-base/2.7.9', array(
'itop-portal-base/2.7.10', array(
// Identification
'label' => 'Portal Development Library',
'category' => 'Portal',

View File

@@ -64,7 +64,7 @@ foreach ($aPortalConf['properties']['themes'] as $sKey => $value)
{
if (!is_array($value))
{
$aPortalConf['properties']['themes'][$sKey] = $_ENV['COMBODO_ABSOLUTE_URL'].utils::GetCSSFromSASS('env-'.utils::GetCurrentEnvironment().'/'.$value,
$aPortalConf['properties']['themes'][$sKey] = utils::GetCSSFromSASS('env-'.utils::GetCurrentEnvironment().'/'.$value,
$aImportPaths);
}
else
@@ -72,7 +72,7 @@ foreach ($aPortalConf['properties']['themes'] as $sKey => $value)
$aValues = array();
foreach ($value as $sSubValue)
{
$aValues[] = $_ENV['COMBODO_ABSOLUTE_URL'].utils::GetCSSFromSASS('env-'.utils::GetCurrentEnvironment().'/'.$sSubValue,
$aValues[] = utils::GetCSSFromSASS('env-'.utils::GetCurrentEnvironment().'/'.$sSubValue,
$aImportPaths);
}
$aPortalConf['properties']['themes'][$sKey] = $aValues;

View File

@@ -1379,3 +1379,19 @@ table .group-actions {
.wiki_broken_link {
text-decoration: line-through;
}
@media print {
/* Prevent URLs from being displayed */
a[href]::after, img[src]::after {
content: none !important;
/* Force modals to be displayed one after another instead of stacked */
}
.modal.in {
position: relative;
top: unset;
z-index: unset;
overflow-y: unset;
}
#drag_overlay {
display: none;
}
}

View File

@@ -1463,3 +1463,27 @@ table .group-actions .item-action-wrapper .panel-body > p:last-child{
.wiki_broken_link {
text-decoration: line-through;
}
@media print {
/* Prevent URLs from being displayed */
a[href], img[src] {
&::after {
content: none !important;
}
}
/* Force modals to be displayed one after another instead of stacked */
.modal {
&.in {
position: relative;
top: unset;
z-index: unset;
overflow-y: unset;
}
}
#drag_overlay {
display: none;
}
}

View File

@@ -49,6 +49,7 @@ use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request;
use UnaryExpression;
use URLButtonItem;
use utils;
/**
* Class ManageBrickController
@@ -259,6 +260,7 @@ class ManageBrickController extends BrickController
'oBrick' => $oBrick,
'sBrickId' => $sBrickId,
'sToken' => $oExporter->SaveState(),
'sWikiUrl' => 'https://www.itophub.io/wiki/page?id='.utils::GetItopVersionWikiSyntax().'%3Auser%3Alists#excel_export',
);
return $this->render(static::EXCEL_EXPORT_TEMPLATE_PATH, $aData);

View File

@@ -1035,7 +1035,11 @@ class ObjectController extends BrickController
// When reaching to an Attachment, we have to check security on its host object instead of the Attachment itself
if ($sObjectClass === 'Attachment')
{
$oAttachment = MetaModel::GetObject($sObjectClass, $sObjectId, true, true);
$oAttachment = MetaModel::GetObject($sObjectClass, $sObjectId, false, true);
if ($oAttachment === null) {
throw new HttpException(Response::HTTP_NOT_FOUND, Dict::S('UI:ObjectDoesNotExist'));
}
$sHostClass = $oAttachment->Get('item_class');
$sHostId = $oAttachment->Get('item_id');
}

View File

@@ -31,6 +31,7 @@ use Combodo\iTop\Form\Field\LabelField;
use Combodo\iTop\Form\Form;
use Combodo\iTop\Form\FormManager;
use Combodo\iTop\Portal\Helper\ApplicationHelper;
use Combodo\iTop\Portal\Helper\SecurityHelper;
use CoreCannotSaveObjectException;
use DBObject;
use DBObjectSearch;
@@ -41,6 +42,7 @@ use DOMDocument;
use DOMXPath;
use Exception;
use InlineImage;
use InvalidExternalKeyValueException;
use IssueLog;
use MetaModel;
use Symfony\Component\DependencyInjection\ContainerInterface;
@@ -48,6 +50,7 @@ use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Exception\HttpException;
use UserRights;
use utils;
use const UR_ACTION_READ;
/**
* Description of ObjectFormManager
@@ -1135,8 +1138,11 @@ class ObjectFormManager extends FormManager
$bWasModified = $this->oObject->IsModified();
$bActivateTriggers = (!$bIsNew && $bWasModified);
/** @var SecurityHelper $oSecurityHelper */
$oSecurityHelper = $this->oContainer->get('security_helper');
// Forcing allowed writing on the object if necessary. This is used in some particular cases.
$bAllowWrite = $this->oContainer->get('security_helper')->IsActionAllowed($bIsNew ? UR_ACTION_CREATE : UR_ACTION_MODIFY, $sObjectClass, $this->oObject->GetKey());
$bAllowWrite = $oSecurityHelper->IsActionAllowed($bIsNew ? UR_ACTION_CREATE : UR_ACTION_MODIFY, $sObjectClass, $this->oObject->GetKey());
if ($bAllowWrite) {
$this->oObject->AllowWrite(true);
}
@@ -1145,11 +1151,14 @@ class ObjectFormManager extends FormManager
try
{
$this->oObject->DBWrite();
}
catch (CoreCannotSaveObjectException $e) {
} catch (CoreCannotSaveObjectException $e) {
throw new Exception($e->getHtmlMessage());
}
catch (Exception $e) {
} catch (InvalidExternalKeyValueException $e) {
$sExceptionMessage = $e->getIssue();
$sExceptionMessage .= var_export($e->getContextData(), true);
throw new Exception($sExceptionMessage);
} catch (Exception $e) {
if ($bIsNew) {
throw new Exception(Dict::S('Portal:Error:ObjectCannotBeCreated'));
}
@@ -1359,6 +1368,12 @@ class ObjectFormManager extends FormManager
}
}
}
/** @var SecurityHelper $oSecurityHelper */
$oSecurityHelper = $this->oContainer->get('security_helper');
// N°7023 - Note that we check for ext. key now as we want the check to be done on user inputs and NOT on ext. keys set programatically, so it must be done before the DoComputeValues
$this->oObject->CheckChangedExtKeysValues(function ($sClass, $sId) use ($oSecurityHelper): bool {
return $oSecurityHelper->IsActionAllowed(UR_ACTION_READ, $sClass, $sId);
});
$this->oObject->DoComputeValues();
}

View File

@@ -11,6 +11,7 @@
</div>
<div id="export-feedback">
<p id="export-excel-warning" class="alert alert-warning" role="alert">{{ 'UI:Bulk:Export:MaliciousInjection:Alert:Message'|dict_format(sWikiUrl)|raw }}</p>
<p class="export-message" style="text-align:center;">{{ 'ExcelExport:PreparingExport'|dict_s }}</p>
<div class="progress">
<div class="progress-bar" role="progressbar" style="width: 0%"

View File

@@ -51,9 +51,9 @@
<link href="{{ app['combodo.absolute_url'] ~ 'css/c3.min.css'|add_itop_version }}" rel="stylesheet">
<link href="{{ app['combodo.absolute_url'] ~ 'js/ckeditor/plugins/codesnippet/lib/highlight/styles/obsidian.css'|add_itop_version }}" rel="stylesheet">
{# - Bootstrap theme #}
<link href="{{ app['combodo.portal.instance.conf'].properties.themes.bootstrap|add_itop_version }}" rel="stylesheet" id="css_bootstrap_theme">
<link href="{{ app['combodo.absolute_url'] ~ app['combodo.portal.instance.conf'].properties.themes.bootstrap|add_itop_version }}" rel="stylesheet" id="css_bootstrap_theme">
{# - Portal adjustments for BS theme #}
<link href="{{ app['combodo.portal.instance.conf'].properties.themes.portal|add_itop_version }}" rel="stylesheet" id="css_portal">
<link href="{{ app['combodo.absolute_url'] ~ app['combodo.portal.instance.conf'].properties.themes.portal|add_itop_version }}" rel="stylesheet" id="css_portal">
{# UI Extensions CSS, in an undefined order #}
{% if app['ui_extensions_helper'].css_files is defined %}
{% for css_file in app['ui_extensions_helper'].css_files %}

View File

@@ -20,7 +20,7 @@
/** @noinspection PhpUnhandledExceptionInspection */
SetupWebPage::AddModule(
__FILE__, // Path to the current file, all other file names are relative to the directory containing this file
'itop-portal/2.7.9', array(
'itop-portal/2.7.10', array(
// Identification
'label' => 'Enhanced Customer Portal',
'category' => 'Portal',

View File

@@ -3,7 +3,7 @@
SetupWebPage::AddModule(
__FILE__, // Path to the current file, all other file names are relative to the directory containing this file
'itop-problem-mgmt/2.7.9',
'itop-problem-mgmt/2.7.10',
array(
// Identification
//

View File

@@ -19,7 +19,7 @@
SetupWebPage::AddModule(
__FILE__, // Path to the current file, all other file names are relative to the directory containing this file
'itop-profiles-itil/2.7.9',
'itop-profiles-itil/2.7.10',
array(
// Identification
//

View File

@@ -3,7 +3,7 @@
SetupWebPage::AddModule(
__FILE__, // Path to the current file, all other file names are relative to the directory containing this file
'itop-request-mgmt-itil/2.7.9',
'itop-request-mgmt-itil/2.7.10',
array(
// Identification
//

View File

@@ -3,7 +3,7 @@
SetupWebPage::AddModule(
__FILE__, // Path to the current file, all other file names are relative to the directory containing this file
'itop-request-mgmt/2.7.9',
'itop-request-mgmt/2.7.10',
array(
// Identification
//

View File

@@ -3,7 +3,7 @@
SetupWebPage::AddModule(
__FILE__, // Path to the current file, all other file names are relative to the directory containing this file
'itop-service-mgmt-provider/2.7.9',
'itop-service-mgmt-provider/2.7.10',
array(
// Identification
//

View File

@@ -3,7 +3,7 @@
SetupWebPage::AddModule(
__FILE__, // Path to the current file, all other file names are relative to the directory containing this file
'itop-service-mgmt/2.7.9',
'itop-service-mgmt/2.7.10',
array(
// Identification
//

View File

@@ -18,7 +18,7 @@
SetupWebPage::AddModule(
__FILE__, // Path to the current file, all other file names are relative to the directory containing this file
'itop-sla-computation/2.7.9',
'itop-sla-computation/2.7.10',
array(
// Identification
//

View File

@@ -25,7 +25,7 @@
SetupWebPage::AddModule(
__FILE__, // Path to the current file, all other file names are relative to the directory containing this file
'itop-storage-mgmt/2.7.9',
'itop-storage-mgmt/2.7.10',
array(
// Identification
//

View File

@@ -3,7 +3,7 @@
SetupWebPage::AddModule(
__FILE__,
'itop-tickets/2.7.9',
'itop-tickets/2.7.10',
array(
// Identification
//

View File

@@ -16,7 +16,7 @@
SetupWebPage::AddModule(
__FILE__, // Path to the current file, all other file names are relative to the directory containing this file
'itop-virtualization-mgmt/2.7.9',
'itop-virtualization-mgmt/2.7.10',
array(
// Identification
//

View File

@@ -3,7 +3,7 @@
SetupWebPage::AddModule(
__FILE__, // Path to the current file, all other file names are relative to the directory containing this file
'itop-welcome-itil/2.7.9',
'itop-welcome-itil/2.7.10',
array(
// Identification
//

View File

@@ -1,4 +1,4 @@
<?xml version="1.0" encoding="UTF-8"?>
<information>
<version>2.7.9</version>
<version>2.7.10</version>
</information>

View File

@@ -934,6 +934,7 @@ Dict::Add('CS CZ', 'Czech', 'Čeština', array(
'Core:BulkExport:DateTimeFormatDefault_Example' => 'Default format (%1$s), e.g. %2$s~~',
'Core:BulkExport:DateTimeFormatCustom_Format' => 'Custom format: %1$s~~',
'Core:BulkExport:PDF:PageNumber' => 'Page %1$s~~',
'UI:Bulk:Export:MaliciousInjection:Alert:Message' => 'Opening a file with untrusted data in Microsoft Excel may lead to formula injection. Ensure that your Excel settings are configured to handle files safely. <a href="%1$s">Learn more in our documentation.</a>~~',
'Core:DateTime:Placeholder_d' => 'DD~~', // Day of the month: 2 digits (with leading zero)
'Core:DateTime:Placeholder_j' => 'D~~', // Day of the month: 1 or 2 digits (without leading zero)
'Core:DateTime:Placeholder_m' => 'MM~~', // Month on 2 digits i.e. 01-12

View File

@@ -932,7 +932,8 @@ Dict::Add('DA DA', 'Danish', 'Dansk', array(
'Core:BulkExport:DateTimeFormatDefault_Example' => 'Default format (%1$s), e.g. %2$s~~',
'Core:BulkExport:DateTimeFormatCustom_Format' => 'Custom format: %1$s~~',
'Core:BulkExport:PDF:PageNumber' => 'Page %1$s~~',
'Core:DateTime:Placeholder_d' => 'DD~~', // Day of the month: 2 digits (with leading zero)
'UI:Bulk:Export:MaliciousInjection:Alert:Message' => 'Opening a file with untrusted data in Microsoft Excel may lead to formula injection. Ensure that your Excel settings are configured to handle files safely. <a href="%1$s">Learn more in our documentation.</a>~~',
'Core:DateTime:Placeholder_d' => 'DD~~', // Day of the month: 2 digits (with leading zero)
'Core:DateTime:Placeholder_j' => 'D~~', // Day of the month: 1 or 2 digits (without leading zero)
'Core:DateTime:Placeholder_m' => 'MM~~', // Month on 2 digits i.e. 01-12
'Core:DateTime:Placeholder_n' => 'M~~', // Month on 1 or 2 digits 1-12

View File

@@ -931,7 +931,8 @@ Dict::Add('DE DE', 'German', 'Deutsch', array(
'Core:BulkExport:DateTimeFormatDefault_Example' => 'Standardformat (%1$s), z.B. %2$s',
'Core:BulkExport:DateTimeFormatCustom_Format' => 'Angepasstes format: %1$s',
'Core:BulkExport:PDF:PageNumber' => 'Seite %1$s',
'Core:DateTime:Placeholder_d' => 'TT', // Day of the month: 2 digits (with leading zero)
'UI:Bulk:Export:MaliciousInjection:Alert:Message' => 'Opening a file with untrusted data in Microsoft Excel may lead to formula injection. Ensure that your Excel settings are configured to handle files safely. <a href="%1$s">Learn more in our documentation.</a>~~',
'Core:DateTime:Placeholder_d' => 'TT', // Day of the month: 2 digits (with leading zero)
'Core:DateTime:Placeholder_j' => 'T', // Day of the month: 1 or 2 digits (without leading zero)
'Core:DateTime:Placeholder_m' => 'MM', // Month on 2 digits i.e. 01-12
'Core:DateTime:Placeholder_n' => 'M', // Month on 1 or 2 digits 1-12

View File

@@ -932,6 +932,7 @@ Dict::Add('EN US', 'English', 'English', array(
'Core:BulkExport:DateTimeFormatDefault_Example' => 'Default format (%1$s), e.g. %2$s',
'Core:BulkExport:DateTimeFormatCustom_Format' => 'Custom format: %1$s',
'Core:BulkExport:PDF:PageNumber' => 'Page %1$s',
'UI:Bulk:Export:MaliciousInjection:Alert:Message' => 'Opening a file with untrusted data in Microsoft Excel may lead to formula injection. Ensure that your Excel settings are configured to handle files safely. <a href="%1$s">Learn more in our documentation.</a>',
'Core:DateTime:Placeholder_d' => 'DD', // Day of the month: 2 digits (with leading zero)
'Core:DateTime:Placeholder_j' => 'D', // Day of the month: 1 or 2 digits (without leading zero)
'Core:DateTime:Placeholder_m' => 'MM', // Month on 2 digits i.e. 01-12

View File

@@ -933,7 +933,8 @@ Dict::Add('ES CR', 'Spanish', 'Español, Castellaño', array(
'Core:BulkExport:DateTimeFormatDefault_Example' => 'Formato por omisión (%1$s), ej. %2$s',
'Core:BulkExport:DateTimeFormatCustom_Format' => 'Formato personalizado: %1$s',
'Core:BulkExport:PDF:PageNumber' => 'Página %1$s',
'Core:DateTime:Placeholder_d' => 'DD', // Day of the month: 2 digits (with leading zero)
'UI:Bulk:Export:MaliciousInjection:Alert:Message' => 'Opening a file with untrusted data in Microsoft Excel may lead to formula injection. Ensure that your Excel settings are configured to handle files safely. <a href="%1$s">Learn more in our documentation.</a>~~',
'Core:DateTime:Placeholder_d' => 'DD', // Day of the month: 2 digits (with leading zero)
'Core:DateTime:Placeholder_j' => 'D', // Day of the month: 1 or 2 digits (without leading zero)
'Core:DateTime:Placeholder_m' => 'MM', // Month on 2 digits i.e. 01-12
'Core:DateTime:Placeholder_n' => 'M', // Month on 1 or 2 digits 1-12

View File

@@ -930,7 +930,8 @@ Dict::Add('FR FR', 'French', 'Français', array(
'Core:BulkExport:DateTimeFormatDefault_Example' => 'Format par défaut (%1$s), ex. %2$s',
'Core:BulkExport:DateTimeFormatCustom_Format' => 'Format spécial: %1$s',
'Core:BulkExport:PDF:PageNumber' => 'Page %1$s',
'Core:DateTime:Placeholder_d' => 'JJ', // Day of the month: 2 digits (with leading zero)
'UI:Bulk:Export:MaliciousInjection:Alert:Message' => 'L\'ouverture d\'un fichier contenant des données non fiables dans Microsoft Excel peut entraîner l\'injection de formules. Assurez-vous que vos paramètres Excel sont configurés pour traiter les fichiers en toute sécurité. <a href="%1$s">Pour en savoir plus, consultez notre documentation.</a>',
'Core:DateTime:Placeholder_d' => 'JJ', // Day of the month: 2 digits (with leading zero)
'Core:DateTime:Placeholder_j' => 'J', // Day of the month: 1 or 2 digits (without leading zero)
'Core:DateTime:Placeholder_m' => 'MM', // Month on 2 digits i.e. 01-12
'Core:DateTime:Placeholder_n' => 'M', // Month on 1 or 2 digits 1-12

View File

@@ -930,7 +930,8 @@ Dict::Add('HU HU', 'Hungarian', 'Magyar', array(
'Core:BulkExport:DateTimeFormatDefault_Example' => 'Default format (%1$s), e.g. %2$s~~',
'Core:BulkExport:DateTimeFormatCustom_Format' => 'Custom format: %1$s~~',
'Core:BulkExport:PDF:PageNumber' => 'Page %1$s~~',
'Core:DateTime:Placeholder_d' => 'DD~~', // Day of the month: 2 digits (with leading zero)
'UI:Bulk:Export:MaliciousInjection:Alert:Message' => 'Opening a file with untrusted data in Microsoft Excel may lead to formula injection. Ensure that your Excel settings are configured to handle files safely. <a href="%1$s">Learn more in our documentation.</a>~~',
'Core:DateTime:Placeholder_d' => 'DD~~', // Day of the month: 2 digits (with leading zero)
'Core:DateTime:Placeholder_j' => 'D~~', // Day of the month: 1 or 2 digits (without leading zero)
'Core:DateTime:Placeholder_m' => 'MM~~', // Month on 2 digits i.e. 01-12
'Core:DateTime:Placeholder_n' => 'M~~', // Month on 1 or 2 digits 1-12

View File

@@ -932,7 +932,8 @@ Dict::Add('IT IT', 'Italian', 'Italiano', array(
'Core:BulkExport:DateTimeFormatDefault_Example' => 'Default format (%1$s), e.g. %2$s~~',
'Core:BulkExport:DateTimeFormatCustom_Format' => 'Custom format: %1$s~~',
'Core:BulkExport:PDF:PageNumber' => 'Page %1$s~~',
'Core:DateTime:Placeholder_d' => 'GG', // Day of the month: 2 digits (with leading zero)
'UI:Bulk:Export:MaliciousInjection:Alert:Message' => 'Opening a file with untrusted data in Microsoft Excel may lead to formula injection. Ensure that your Excel settings are configured to handle files safely. <a href="%1$s">Learn more in our documentation.</a>~~',
'Core:DateTime:Placeholder_d' => 'GG', // Day of the month: 2 digits (with leading zero)
'Core:DateTime:Placeholder_j' => 'G', // Day of the month: 1 or 2 digits (without leading zero)
'Core:DateTime:Placeholder_m' => 'MM', // Month on 2 digits i.e. 01-12
'Core:DateTime:Placeholder_n' => 'M', // Month on 1 or 2 digits 1-12

View File

@@ -930,7 +930,8 @@ Dict::Add('JA JP', 'Japanese', '日本語', array(
'Core:BulkExport:DateTimeFormatDefault_Example' => 'Default format (%1$s), e.g. %2$s~~',
'Core:BulkExport:DateTimeFormatCustom_Format' => 'Custom format: %1$s~~',
'Core:BulkExport:PDF:PageNumber' => 'Page %1$s~~',
'Core:DateTime:Placeholder_d' => 'DD~~', // Day of the month: 2 digits (with leading zero)
'UI:Bulk:Export:MaliciousInjection:Alert:Message' => 'Opening a file with untrusted data in Microsoft Excel may lead to formula injection. Ensure that your Excel settings are configured to handle files safely. <a href="%1$s">Learn more in our documentation.</a>~~',
'Core:DateTime:Placeholder_d' => 'DD~~', // Day of the month: 2 digits (with leading zero)
'Core:DateTime:Placeholder_j' => 'D~~', // Day of the month: 1 or 2 digits (without leading zero)
'Core:DateTime:Placeholder_m' => 'MM~~', // Month on 2 digits i.e. 01-12
'Core:DateTime:Placeholder_n' => 'M~~', // Month on 1 or 2 digits 1-12

View File

@@ -938,7 +938,8 @@ Dict::Add('NL NL', 'Dutch', 'Nederlands', array(
'Core:BulkExport:DateTimeFormatDefault_Example' => 'Standaardformaat (%1$s), bv. %2$s',
'Core:BulkExport:DateTimeFormatCustom_Format' => 'Aangepast formaat: %1$s',
'Core:BulkExport:PDF:PageNumber' => 'Pagina %1$s',
'Core:DateTime:Placeholder_d' => 'DD', // Day of the month: 2 digits (with leading zero)
'UI:Bulk:Export:MaliciousInjection:Alert:Message' => 'Opening a file with untrusted data in Microsoft Excel may lead to formula injection. Ensure that your Excel settings are configured to handle files safely. <a href="%1$s">Learn more in our documentation.</a>~~',
'Core:DateTime:Placeholder_d' => 'DD', // Day of the month: 2 digits (with leading zero)
'Core:DateTime:Placeholder_j' => 'D', // Day of the month: 1 or 2 digits (without leading zero)
'Core:DateTime:Placeholder_m' => 'MM', // Month on 2 digits i.e. 01-12
'Core:DateTime:Placeholder_n' => 'M', // Month on 1 or 2 digits 1-12

View File

@@ -932,7 +932,8 @@ Dict::Add('PT BR', 'Brazilian', 'Brazilian', array(
'Core:BulkExport:DateTimeFormatDefault_Example' => 'Formato padrão (%1$s), por ex. %2$s',
'Core:BulkExport:DateTimeFormatCustom_Format' => 'Formato personalizado: %1$s',
'Core:BulkExport:PDF:PageNumber' => 'Página %1$s',
'Core:DateTime:Placeholder_d' => 'DD', // Day of the month: 2 digits (with leading zero)
'UI:Bulk:Export:MaliciousInjection:Alert:Message' => 'Opening a file with untrusted data in Microsoft Excel may lead to formula injection. Ensure that your Excel settings are configured to handle files safely. <a href="%1$s">Learn more in our documentation.</a>~~',
'Core:DateTime:Placeholder_d' => 'DD', // Day of the month: 2 digits (with leading zero)
'Core:DateTime:Placeholder_j' => 'D', // Day of the month: 1 or 2 digits (without leading zero)
'Core:DateTime:Placeholder_m' => 'MM', // Month on 2 digits i.e. 01-12
'Core:DateTime:Placeholder_n' => 'M', // Month on 1 or 2 digits 1-12

View File

@@ -919,7 +919,8 @@ Dict::Add('RU RU', 'Russian', 'Русский', array(
'Core:BulkExport:DateTimeFormatDefault_Example' => 'Формат по умолчанию (%1$s), например %2$s',
'Core:BulkExport:DateTimeFormatCustom_Format' => 'Пользовательский формат: %1$s',
'Core:BulkExport:PDF:PageNumber' => 'Страница %1$s',
'Core:DateTime:Placeholder_d' => 'DD', // Day of the month: 2 digits (with leading zero)
'UI:Bulk:Export:MaliciousInjection:Alert:Message' => 'Opening a file with untrusted data in Microsoft Excel may lead to formula injection. Ensure that your Excel settings are configured to handle files safely. <a href="%1$s">Learn more in our documentation.</a>~~',
'Core:DateTime:Placeholder_d' => 'DD', // Day of the month: 2 digits (with leading zero)
'Core:DateTime:Placeholder_j' => 'D', // Day of the month: 1 or 2 digits (without leading zero)
'Core:DateTime:Placeholder_m' => 'MM', // Month on 2 digits i.e. 01-12
'Core:DateTime:Placeholder_n' => 'M', // Month on 1 or 2 digits 1-12

View File

@@ -929,7 +929,8 @@ Dict::Add('SK SK', 'Slovak', 'Slovenčina', array(
'Core:BulkExport:DateTimeFormatDefault_Example' => 'Default format (%1$s), e.g. %2$s~~',
'Core:BulkExport:DateTimeFormatCustom_Format' => 'Custom format: %1$s~~',
'Core:BulkExport:PDF:PageNumber' => 'Page %1$s~~',
'Core:DateTime:Placeholder_d' => 'DD~~', // Day of the month: 2 digits (with leading zero)
'UI:Bulk:Export:MaliciousInjection:Alert:Message' => 'Opening a file with untrusted data in Microsoft Excel may lead to formula injection. Ensure that your Excel settings are configured to handle files safely. <a href="%1$s">Learn more in our documentation.</a>~~',
'Core:DateTime:Placeholder_d' => 'DD~~', // Day of the month: 2 digits (with leading zero)
'Core:DateTime:Placeholder_j' => 'D~~', // Day of the month: 1 or 2 digits (without leading zero)
'Core:DateTime:Placeholder_m' => 'MM~~', // Month on 2 digits i.e. 01-12
'Core:DateTime:Placeholder_n' => 'M~~', // Month on 1 or 2 digits 1-12

View File

@@ -940,7 +940,8 @@ Dict::Add('TR TR', 'Turkish', 'Türkçe', array(
'Core:BulkExport:DateTimeFormatDefault_Example' => 'Default format (%1$s), e.g. %2$s~~',
'Core:BulkExport:DateTimeFormatCustom_Format' => 'Custom format: %1$s~~',
'Core:BulkExport:PDF:PageNumber' => 'Page %1$s~~',
'Core:DateTime:Placeholder_d' => 'DD~~', // Day of the month: 2 digits (with leading zero)
'UI:Bulk:Export:MaliciousInjection:Alert:Message' => 'Opening a file with untrusted data in Microsoft Excel may lead to formula injection. Ensure that your Excel settings are configured to handle files safely. <a href="%1$s">Learn more in our documentation.</a>~~',
'Core:DateTime:Placeholder_d' => 'DD~~', // Day of the month: 2 digits (with leading zero)
'Core:DateTime:Placeholder_j' => 'D~~', // Day of the month: 1 or 2 digits (without leading zero)
'Core:DateTime:Placeholder_m' => 'MM~~', // Month on 2 digits i.e. 01-12
'Core:DateTime:Placeholder_n' => 'M~~', // Month on 1 or 2 digits 1-12

View File

@@ -931,7 +931,8 @@ Dict::Add('ZH CN', 'Chinese', '简体中文', array(
'Core:BulkExport:DateTimeFormatDefault_Example' => '默认格式 (%1$s), e.g. %2$s',
'Core:BulkExport:DateTimeFormatCustom_Format' => '自定义格式: %1$s',
'Core:BulkExport:PDF:PageNumber' => '第 %1$s 页',
'Core:DateTime:Placeholder_d' => 'DD', // Day of the month: 2 digits (with leading zero)
'UI:Bulk:Export:MaliciousInjection:Alert:Message' => 'Opening a file with untrusted data in Microsoft Excel may lead to formula injection. Ensure that your Excel settings are configured to handle files safely. <a href="%1$s">Learn more in our documentation.</a>~~',
'Core:DateTime:Placeholder_d' => 'DD', // Day of the month: 2 digits (with leading zero)
'Core:DateTime:Placeholder_j' => 'D', // Day of the month: 1 or 2 digits (without leading zero)
'Core:DateTime:Placeholder_m' => 'MM', // Month on 2 digits i.e. 01-12
'Core:DateTime:Placeholder_n' => 'M', // Month on 1 or 2 digits 1-12

View File

@@ -152,7 +152,7 @@ $(function()
_initChooseDefaultOperator: function()
{
//if the class has an index, in order to maximize the performance, we force the default operator to "equal"
if (this.options.field.has_index && typeof this.options.available_operators['='] == 'object' && this.options.values.length == 0)
if (this.options.field.has_index && this.options.available_operators['='] != null && typeof this.options.available_operators['='] == 'object' && this.options.values.length == 0)
{
this.options.operator = '=';
this.options.available_operators['='].rank = -1;//we want it to be the first displayed

View File

@@ -2,6 +2,24 @@
// autoload.php @generated by Composer
if (PHP_VERSION_ID < 50600) {
if (!headers_sent()) {
header('HTTP/1.1 500 Internal Server Error');
}
$err = 'Composer 2.3.0 dropped support for autoloading on PHP <5.6 and you are running '.PHP_VERSION.', please upgrade PHP or use Composer 2.2 LTS via "composer self-update --2.2". Aborting.'.PHP_EOL;
if (!ini_get('display_errors')) {
if (PHP_SAPI === 'cli' || PHP_SAPI === 'phpdbg') {
fwrite(STDERR, $err);
} elseif (!headers_sent()) {
echo $err;
}
}
trigger_error(
$err,
E_USER_ERROR
);
}
require_once __DIR__ . '/composer/autoload_real.php';
return ComposerAutoloaderInit0018331147de7601e7552f7da8e3bb8b::getLoader();

View File

@@ -42,35 +42,37 @@ namespace Composer\Autoload;
*/
class ClassLoader
{
/** @var ?string */
/** @var \Closure(string):void */
private static $includeFile;
/** @var string|null */
private $vendorDir;
// PSR-4
/**
* @var array[]
* @psalm-var array<string, array<string, int>>
* @var array<string, array<string, int>>
*/
private $prefixLengthsPsr4 = array();
/**
* @var array[]
* @psalm-var array<string, array<int, string>>
* @var array<string, list<string>>
*/
private $prefixDirsPsr4 = array();
/**
* @var array[]
* @psalm-var array<string, string>
* @var list<string>
*/
private $fallbackDirsPsr4 = array();
// PSR-0
/**
* @var array[]
* @psalm-var array<string, array<string, string[]>>
* List of PSR-0 prefixes
*
* Structured as array('F (first letter)' => array('Foo\Bar (full prefix)' => array('path', 'path2')))
*
* @var array<string, array<string, list<string>>>
*/
private $prefixesPsr0 = array();
/**
* @var array[]
* @psalm-var array<string, string>
* @var list<string>
*/
private $fallbackDirsPsr0 = array();
@@ -78,8 +80,7 @@ class ClassLoader
private $useIncludePath = false;
/**
* @var string[]
* @psalm-var array<string, string>
* @var array<string, string>
*/
private $classMap = array();
@@ -87,29 +88,29 @@ class ClassLoader
private $classMapAuthoritative = false;
/**
* @var bool[]
* @psalm-var array<string, bool>
* @var array<string, bool>
*/
private $missingClasses = array();
/** @var ?string */
/** @var string|null */
private $apcuPrefix;
/**
* @var self[]
* @var array<string, self>
*/
private static $registeredLoaders = array();
/**
* @param ?string $vendorDir
* @param string|null $vendorDir
*/
public function __construct($vendorDir = null)
{
$this->vendorDir = $vendorDir;
self::initializeIncludeClosure();
}
/**
* @return string[]
* @return array<string, list<string>>
*/
public function getPrefixes()
{
@@ -121,8 +122,7 @@ class ClassLoader
}
/**
* @return array[]
* @psalm-return array<string, array<int, string>>
* @return array<string, list<string>>
*/
public function getPrefixesPsr4()
{
@@ -130,8 +130,7 @@ class ClassLoader
}
/**
* @return array[]
* @psalm-return array<string, string>
* @return list<string>
*/
public function getFallbackDirs()
{
@@ -139,8 +138,7 @@ class ClassLoader
}
/**
* @return array[]
* @psalm-return array<string, string>
* @return list<string>
*/
public function getFallbackDirsPsr4()
{
@@ -148,8 +146,7 @@ class ClassLoader
}
/**
* @return string[] Array of classname => path
* @psalm-var array<string, string>
* @return array<string, string> Array of classname => path
*/
public function getClassMap()
{
@@ -157,8 +154,7 @@ class ClassLoader
}
/**
* @param string[] $classMap Class to filename map
* @psalm-param array<string, string> $classMap
* @param array<string, string> $classMap Class to filename map
*
* @return void
*/
@@ -175,24 +171,25 @@ class ClassLoader
* Registers a set of PSR-0 directories for a given prefix, either
* appending or prepending to the ones previously set for this prefix.
*
* @param string $prefix The prefix
* @param string[]|string $paths The PSR-0 root directories
* @param bool $prepend Whether to prepend the directories
* @param string $prefix The prefix
* @param list<string>|string $paths The PSR-0 root directories
* @param bool $prepend Whether to prepend the directories
*
* @return void
*/
public function add($prefix, $paths, $prepend = false)
{
$paths = (array) $paths;
if (!$prefix) {
if ($prepend) {
$this->fallbackDirsPsr0 = array_merge(
(array) $paths,
$paths,
$this->fallbackDirsPsr0
);
} else {
$this->fallbackDirsPsr0 = array_merge(
$this->fallbackDirsPsr0,
(array) $paths
$paths
);
}
@@ -201,19 +198,19 @@ class ClassLoader
$first = $prefix[0];
if (!isset($this->prefixesPsr0[$first][$prefix])) {
$this->prefixesPsr0[$first][$prefix] = (array) $paths;
$this->prefixesPsr0[$first][$prefix] = $paths;
return;
}
if ($prepend) {
$this->prefixesPsr0[$first][$prefix] = array_merge(
(array) $paths,
$paths,
$this->prefixesPsr0[$first][$prefix]
);
} else {
$this->prefixesPsr0[$first][$prefix] = array_merge(
$this->prefixesPsr0[$first][$prefix],
(array) $paths
$paths
);
}
}
@@ -222,9 +219,9 @@ class ClassLoader
* Registers a set of PSR-4 directories for a given namespace, either
* appending or prepending to the ones previously set for this namespace.
*
* @param string $prefix The prefix/namespace, with trailing '\\'
* @param string[]|string $paths The PSR-4 base directories
* @param bool $prepend Whether to prepend the directories
* @param string $prefix The prefix/namespace, with trailing '\\'
* @param list<string>|string $paths The PSR-4 base directories
* @param bool $prepend Whether to prepend the directories
*
* @throws \InvalidArgumentException
*
@@ -232,17 +229,18 @@ class ClassLoader
*/
public function addPsr4($prefix, $paths, $prepend = false)
{
$paths = (array) $paths;
if (!$prefix) {
// Register directories for the root namespace.
if ($prepend) {
$this->fallbackDirsPsr4 = array_merge(
(array) $paths,
$paths,
$this->fallbackDirsPsr4
);
} else {
$this->fallbackDirsPsr4 = array_merge(
$this->fallbackDirsPsr4,
(array) $paths
$paths
);
}
} elseif (!isset($this->prefixDirsPsr4[$prefix])) {
@@ -252,18 +250,18 @@ class ClassLoader
throw new \InvalidArgumentException("A non-empty PSR-4 prefix must end with a namespace separator.");
}
$this->prefixLengthsPsr4[$prefix[0]][$prefix] = $length;
$this->prefixDirsPsr4[$prefix] = (array) $paths;
$this->prefixDirsPsr4[$prefix] = $paths;
} elseif ($prepend) {
// Prepend directories for an already registered namespace.
$this->prefixDirsPsr4[$prefix] = array_merge(
(array) $paths,
$paths,
$this->prefixDirsPsr4[$prefix]
);
} else {
// Append directories for an already registered namespace.
$this->prefixDirsPsr4[$prefix] = array_merge(
$this->prefixDirsPsr4[$prefix],
(array) $paths
$paths
);
}
}
@@ -272,8 +270,8 @@ class ClassLoader
* Registers a set of PSR-0 directories for a given prefix,
* replacing any others previously set for this prefix.
*
* @param string $prefix The prefix
* @param string[]|string $paths The PSR-0 base directories
* @param string $prefix The prefix
* @param list<string>|string $paths The PSR-0 base directories
*
* @return void
*/
@@ -290,8 +288,8 @@ class ClassLoader
* Registers a set of PSR-4 directories for a given namespace,
* replacing any others previously set for this namespace.
*
* @param string $prefix The prefix/namespace, with trailing '\\'
* @param string[]|string $paths The PSR-4 base directories
* @param string $prefix The prefix/namespace, with trailing '\\'
* @param list<string>|string $paths The PSR-4 base directories
*
* @throws \InvalidArgumentException
*
@@ -425,7 +423,8 @@ class ClassLoader
public function loadClass($class)
{
if ($file = $this->findFile($class)) {
includeFile($file);
$includeFile = self::$includeFile;
$includeFile($file);
return true;
}
@@ -476,9 +475,9 @@ class ClassLoader
}
/**
* Returns the currently registered loaders indexed by their corresponding vendor directories.
* Returns the currently registered loaders keyed by their corresponding vendor directories.
*
* @return self[]
* @return array<string, self>
*/
public static function getRegisteredLoaders()
{
@@ -555,18 +554,26 @@ class ClassLoader
return false;
}
}
/**
* Scope isolated include.
*
* Prevents access to $this/self from included files.
*
* @param string $file
* @return void
* @private
*/
function includeFile($file)
{
include $file;
/**
* @return void
*/
private static function initializeIncludeClosure()
{
if (self::$includeFile !== null) {
return;
}
/**
* Scope isolated include.
*
* Prevents access to $this/self from included files.
*
* @param string $file
* @return void
*/
self::$includeFile = \Closure::bind(static function($file) {
include $file;
}, null, null);
}
}

View File

@@ -2,7 +2,7 @@
// autoload_classmap.php @generated by Composer
$vendorDir = dirname(dirname(__FILE__));
$vendorDir = dirname(__DIR__);
$baseDir = dirname($vendorDir);
return array(
@@ -138,6 +138,7 @@ return array(
'CharConcatWSExpression' => $baseDir . '/core/oql/expression.class.inc.php',
'CheckStopWatchThresholds' => $baseDir . '/core/ormstopwatch.class.inc.php',
'CheckableExpression' => $baseDir . '/core/oql/oqlquery.class.inc.php',
'Combodo\\iTop\\Application\\Helper\\ExportHelper' => $baseDir . '/sources/application/Helper/ExportHelper.php',
'Combodo\\iTop\\Application\\Search\\AjaxSearchException' => $baseDir . '/sources/application/search/ajaxsearchexception.class.inc.php',
'Combodo\\iTop\\Application\\Search\\CriterionConversionAbstract' => $baseDir . '/sources/application/search/criterionconversionabstract.class.inc.php',
'Combodo\\iTop\\Application\\Search\\CriterionConversion\\CriterionToOQL' => $baseDir . '/sources/application/search/criterionconversion/criteriontooql.class.inc.php',
@@ -450,6 +451,7 @@ return array(
'IntervalOqlExpression' => $baseDir . '/core/oql/oqlquery.class.inc.php',
'Introspection' => $baseDir . '/core/introspection.class.inc.php',
'InvalidConfigParamException' => $baseDir . '/core/coreexception.class.inc.php',
'InvalidExternalKeyValueException' => $baseDir . '/core/coreexception.class.inc.php',
'InvalidPasswordAttributeOneWayPassword' => $baseDir . '/core/coreexception.class.inc.php',
'IssueLog' => $baseDir . '/core/log.class.inc.php',
'ItopCounter' => $baseDir . '/core/counter.class.inc.php',

View File

@@ -2,25 +2,25 @@
// autoload_files.php @generated by Composer
$vendorDir = dirname(dirname(__FILE__));
$vendorDir = dirname(__DIR__);
$baseDir = dirname($vendorDir);
return array(
'320cde22f66dd4f5d3fd621d3e88b98f' => $vendorDir . '/symfony/polyfill-ctype/bootstrap.php',
'0e6d7bf4a5811bfa5cf40c5ccd6fae6a' => $vendorDir . '/symfony/polyfill-mbstring/bootstrap.php',
'5255c38a0faeba867671b61dfda6d864' => $vendorDir . '/paragonie/random_compat/lib/random.php',
'023d27dca8066ef29e6739335ea73bad' => $vendorDir . '/symfony/polyfill-php70/bootstrap.php',
'32dcc8afd4335739640db7d200c1971d' => $vendorDir . '/symfony/polyfill-apcu/bootstrap.php',
'667aeda72477189d0494fecd327c3641' => $vendorDir . '/symfony/var-dumper/Resources/functions/dump.php',
'bd9634f2d41831496de0d3dfe4c94881' => $vendorDir . '/symfony/polyfill-php56/bootstrap.php',
'0e6d7bf4a5811bfa5cf40c5ccd6fae6a' => $vendorDir . '/symfony/polyfill-mbstring/bootstrap.php',
'7e9bd612cc444b3eed788ebbe46263a0' => $vendorDir . '/laminas/laminas-zendframework-bridge/src/autoload.php',
'e69f7f6ee287b969198c3c9d6777bd38' => $vendorDir . '/symfony/polyfill-intl-normalizer/bootstrap.php',
'25072dd6e2470089de65ae7bf11d3109' => $vendorDir . '/symfony/polyfill-php72/bootstrap.php',
'f598d06aa772fa33d905e87be6398fb1' => $vendorDir . '/symfony/polyfill-intl-idn/bootstrap.php',
'7b11c4dc42b3b3023073cb14e519683c' => $vendorDir . '/ralouphie/getallheaders/src/getallheaders.php',
'bd9634f2d41831496de0d3dfe4c94881' => $vendorDir . '/symfony/polyfill-php56/bootstrap.php',
'c964ee0ededf28c96ebd9db5099ef910' => $vendorDir . '/guzzlehttp/promises/src/functions_include.php',
'a0edc8309cc5e1d60e3047b5df6b7052' => $vendorDir . '/guzzlehttp/psr7/src/functions_include.php',
'37a3dc5111fe8f707ab4c132ef1dbc62' => $vendorDir . '/guzzlehttp/guzzle/src/functions_include.php',
'32dcc8afd4335739640db7d200c1971d' => $vendorDir . '/symfony/polyfill-apcu/bootstrap.php',
'def43f6c87e4f8dfd0c9e1b1bab14fe8' => $vendorDir . '/symfony/polyfill-iconv/bootstrap.php',
'667aeda72477189d0494fecd327c3641' => $vendorDir . '/symfony/var-dumper/Resources/functions/dump.php',
'2c102faa651ef8ea5874edb585946bce' => $vendorDir . '/swiftmailer/swiftmailer/lib/swift_required.php',
);

View File

@@ -2,7 +2,7 @@
// autoload_namespaces.php @generated by Composer
$vendorDir = dirname(dirname(__FILE__));
$vendorDir = dirname(__DIR__);
$baseDir = dirname($vendorDir);
return array(

View File

@@ -2,7 +2,7 @@
// autoload_psr4.php @generated by Composer
$vendorDir = dirname(dirname(__FILE__));
$vendorDir = dirname(__DIR__);
$baseDir = dirname($vendorDir);
return array(

View File

@@ -25,46 +25,31 @@ class ComposerAutoloaderInit0018331147de7601e7552f7da8e3bb8b
require __DIR__ . '/platform_check.php';
spl_autoload_register(array('ComposerAutoloaderInit0018331147de7601e7552f7da8e3bb8b', 'loadClassLoader'), true, true);
self::$loader = $loader = new \Composer\Autoload\ClassLoader(\dirname(\dirname(__FILE__)));
self::$loader = $loader = new \Composer\Autoload\ClassLoader(\dirname(__DIR__));
spl_autoload_unregister(array('ComposerAutoloaderInit0018331147de7601e7552f7da8e3bb8b', 'loadClassLoader'));
$includePaths = require __DIR__ . '/include_paths.php';
$includePaths[] = get_include_path();
set_include_path(implode(PATH_SEPARATOR, $includePaths));
$useStaticLoader = PHP_VERSION_ID >= 50600 && !defined('HHVM_VERSION') && (!function_exists('zend_loader_file_encoded') || !zend_loader_file_encoded());
if ($useStaticLoader) {
require __DIR__ . '/autoload_static.php';
call_user_func(\Composer\Autoload\ComposerStaticInit0018331147de7601e7552f7da8e3bb8b::getInitializer($loader));
} else {
$classMap = require __DIR__ . '/autoload_classmap.php';
if ($classMap) {
$loader->addClassMap($classMap);
}
}
require __DIR__ . '/autoload_static.php';
call_user_func(\Composer\Autoload\ComposerStaticInit0018331147de7601e7552f7da8e3bb8b::getInitializer($loader));
$loader->setClassMapAuthoritative(true);
$loader->register(true);
if ($useStaticLoader) {
$includeFiles = Composer\Autoload\ComposerStaticInit0018331147de7601e7552f7da8e3bb8b::$files;
} else {
$includeFiles = require __DIR__ . '/autoload_files.php';
}
foreach ($includeFiles as $fileIdentifier => $file) {
composerRequire0018331147de7601e7552f7da8e3bb8b($fileIdentifier, $file);
$filesToLoad = \Composer\Autoload\ComposerStaticInit0018331147de7601e7552f7da8e3bb8b::$files;
$requireFile = \Closure::bind(static function ($fileIdentifier, $file) {
if (empty($GLOBALS['__composer_autoload_files'][$fileIdentifier])) {
$GLOBALS['__composer_autoload_files'][$fileIdentifier] = true;
require $file;
}
}, null, null);
foreach ($filesToLoad as $fileIdentifier => $file) {
$requireFile($fileIdentifier, $file);
}
return $loader;
}
}
function composerRequire0018331147de7601e7552f7da8e3bb8b($fileIdentifier, $file)
{
if (empty($GLOBALS['__composer_autoload_files'][$fileIdentifier])) {
require $file;
$GLOBALS['__composer_autoload_files'][$fileIdentifier] = true;
}
}

View File

@@ -8,21 +8,21 @@ class ComposerStaticInit0018331147de7601e7552f7da8e3bb8b
{
public static $files = array (
'320cde22f66dd4f5d3fd621d3e88b98f' => __DIR__ . '/..' . '/symfony/polyfill-ctype/bootstrap.php',
'0e6d7bf4a5811bfa5cf40c5ccd6fae6a' => __DIR__ . '/..' . '/symfony/polyfill-mbstring/bootstrap.php',
'5255c38a0faeba867671b61dfda6d864' => __DIR__ . '/..' . '/paragonie/random_compat/lib/random.php',
'023d27dca8066ef29e6739335ea73bad' => __DIR__ . '/..' . '/symfony/polyfill-php70/bootstrap.php',
'32dcc8afd4335739640db7d200c1971d' => __DIR__ . '/..' . '/symfony/polyfill-apcu/bootstrap.php',
'667aeda72477189d0494fecd327c3641' => __DIR__ . '/..' . '/symfony/var-dumper/Resources/functions/dump.php',
'bd9634f2d41831496de0d3dfe4c94881' => __DIR__ . '/..' . '/symfony/polyfill-php56/bootstrap.php',
'0e6d7bf4a5811bfa5cf40c5ccd6fae6a' => __DIR__ . '/..' . '/symfony/polyfill-mbstring/bootstrap.php',
'7e9bd612cc444b3eed788ebbe46263a0' => __DIR__ . '/..' . '/laminas/laminas-zendframework-bridge/src/autoload.php',
'e69f7f6ee287b969198c3c9d6777bd38' => __DIR__ . '/..' . '/symfony/polyfill-intl-normalizer/bootstrap.php',
'25072dd6e2470089de65ae7bf11d3109' => __DIR__ . '/..' . '/symfony/polyfill-php72/bootstrap.php',
'f598d06aa772fa33d905e87be6398fb1' => __DIR__ . '/..' . '/symfony/polyfill-intl-idn/bootstrap.php',
'7b11c4dc42b3b3023073cb14e519683c' => __DIR__ . '/..' . '/ralouphie/getallheaders/src/getallheaders.php',
'bd9634f2d41831496de0d3dfe4c94881' => __DIR__ . '/..' . '/symfony/polyfill-php56/bootstrap.php',
'c964ee0ededf28c96ebd9db5099ef910' => __DIR__ . '/..' . '/guzzlehttp/promises/src/functions_include.php',
'a0edc8309cc5e1d60e3047b5df6b7052' => __DIR__ . '/..' . '/guzzlehttp/psr7/src/functions_include.php',
'37a3dc5111fe8f707ab4c132ef1dbc62' => __DIR__ . '/..' . '/guzzlehttp/guzzle/src/functions_include.php',
'32dcc8afd4335739640db7d200c1971d' => __DIR__ . '/..' . '/symfony/polyfill-apcu/bootstrap.php',
'def43f6c87e4f8dfd0c9e1b1bab14fe8' => __DIR__ . '/..' . '/symfony/polyfill-iconv/bootstrap.php',
'667aeda72477189d0494fecd327c3641' => __DIR__ . '/..' . '/symfony/var-dumper/Resources/functions/dump.php',
'2c102faa651ef8ea5874edb585946bce' => __DIR__ . '/..' . '/swiftmailer/swiftmailer/lib/swift_required.php',
);
@@ -506,6 +506,7 @@ class ComposerStaticInit0018331147de7601e7552f7da8e3bb8b
'CharConcatWSExpression' => __DIR__ . '/../..' . '/core/oql/expression.class.inc.php',
'CheckStopWatchThresholds' => __DIR__ . '/../..' . '/core/ormstopwatch.class.inc.php',
'CheckableExpression' => __DIR__ . '/../..' . '/core/oql/oqlquery.class.inc.php',
'Combodo\\iTop\\Application\\Helper\\ExportHelper' => __DIR__ . '/../..' . '/sources/application/Helper/ExportHelper.php',
'Combodo\\iTop\\Application\\Search\\AjaxSearchException' => __DIR__ . '/../..' . '/sources/application/search/ajaxsearchexception.class.inc.php',
'Combodo\\iTop\\Application\\Search\\CriterionConversionAbstract' => __DIR__ . '/../..' . '/sources/application/search/criterionconversionabstract.class.inc.php',
'Combodo\\iTop\\Application\\Search\\CriterionConversion\\CriterionToOQL' => __DIR__ . '/../..' . '/sources/application/search/criterionconversion/criteriontooql.class.inc.php',
@@ -818,6 +819,7 @@ class ComposerStaticInit0018331147de7601e7552f7da8e3bb8b
'IntervalOqlExpression' => __DIR__ . '/../..' . '/core/oql/oqlquery.class.inc.php',
'Introspection' => __DIR__ . '/../..' . '/core/introspection.class.inc.php',
'InvalidConfigParamException' => __DIR__ . '/../..' . '/core/coreexception.class.inc.php',
'InvalidExternalKeyValueException' => __DIR__ . '/../..' . '/core/coreexception.class.inc.php',
'InvalidPasswordAttributeOneWayPassword' => __DIR__ . '/../..' . '/core/coreexception.class.inc.php',
'IssueLog' => __DIR__ . '/../..' . '/core/log.class.inc.php',
'ItopCounter' => __DIR__ . '/../..' . '/core/counter.class.inc.php',

View File

@@ -2,7 +2,7 @@
// include_paths.php @generated by Composer
$vendorDir = dirname(dirname(__FILE__));
$vendorDir = dirname(__DIR__);
$baseDir = dirname($vendorDir);
return array(

View File

@@ -1002,6 +1002,7 @@ HTML
{
throw new CoreCannotSaveObjectException(array('id' => $oObj->GetKey(), 'class' => $sClass, 'issues' => $aErrors));
}
$oObj->CheckChangedExtKeysValues();
// Transactions are now handled in DBUpdate
$oObj->DBUpdate();
$sMessage = Dict::Format('UI:Class_Object_Updated', MetaModel::GetName(get_class($oObj)), $oObj->GetName());
@@ -1233,6 +1234,7 @@ HTML
throw new CoreCannotSaveObjectException(array('id' => $oObj->GetKey(), 'class' => $sClass, 'issues' => $aErrors));
}
$oObj->CheckChangedExtKeysValues();
$oObj->DBInsertNoReload();// No need to reload
IssueLog::Trace('Object created', $sClass, array(

View File

@@ -67,7 +67,7 @@ try
// X-Frame http header : set in page constructor, but we need to allow frame integration for this specific page
// so we're resetting its value ! (see N°3416)
$oPage->add_xframe_options('');
$oPage->add_http_headers('');
$oPage->add_header("Last-Modified: Wed, 15 Jun 2015 13:21:15 GMT"); // An arbitrary date in the past is ok
}
@@ -88,7 +88,7 @@ try
// X-Frame http header : set in page constructor, but we need to allow frame integration for this specific page
// so we're resetting its value ! (see N°3416)
$oPage->add_xframe_options('');
$oPage->add_http_headers('');
$oPage->add_header("Last-Modified: Wed, 15 Jun 2016 13:21:15 GMT"); // An arbitrary date in the past is ok
}
@@ -103,7 +103,7 @@ try
// X-Frame http header : set in page constructor, but we need to allow frame integration for this specific page
// so we're resetting its value ! (see N°3416)
$oPage->add_xframe_options('');
$oPage->add_http_headers('');
$oPage->add(file_get_contents(Utils::GetCachePath().$sSignature.'.js'));
break;

View File

@@ -1036,7 +1036,7 @@ try
// X-Frame http header : set in page constructor, but we need to allow frame integration for this specific page
// so we're resetting its value ! (see N°3416)
$oPage->add_xframe_options('');
$oPage->add_http_headers('');
// N°4129 - Prevent XSS attacks & other script executions
if (utils::GetConfig()->Get('security.disable_inline_documents_sandbox') === false) {
@@ -1317,9 +1317,9 @@ EOF
case 'new_dashlet_id':
$sDashboardDivId = utils::ReadParam("dashboardid");
$bIsCustomized = true; // Only called at runtime when customizing a dashboard
$iRow = utils::ReadParam("iRow");
$iCol = utils::ReadParam("iCol");
$sDashletIdOrig = utils::ReadParam("dashletid");
$iRow = utils::ReadParam("iRow", 0, false, utils::ENUM_SANITIZATION_FILTER_INTEGER);
$iCol = utils::ReadParam("iCol", 0, false, utils::ENUM_SANITIZATION_FILTER_INTEGER);
$sDashletIdOrig = utils::ReadParam("dashletid", '', false, utils::ENUM_SANITIZATION_FILTER_ELEMENT_IDENTIFIER);
$sFinalDashletId = Dashboard::GetDashletUniqueId($bIsCustomized, $sDashboardDivId, $iRow, $iCol, $sDashletIdOrig);
$oPage = new ajax_page('');
$oPage->add($sFinalDashletId);
@@ -1328,8 +1328,8 @@ EOF
case 'new_dashlet':
require_once(APPROOT.'application/forms.class.inc.php');
require_once(APPROOT.'application/dashlet.class.inc.php');
$sDashletClass = utils::ReadParam('dashlet_class', '');
$sDashletId = utils::ReadParam('dashlet_id', '', false, 'raw_data');
$sDashletClass = utils::ReadParam('dashlet_class', '', false, utils::ENUM_SANITIZATION_FILTER_PHP_CLASS);
$sDashletId = utils::ReadParam('dashlet_id', '', false, utils::ENUM_SANITIZATION_FILTER_ELEMENT_IDENTIFIER);
if (is_subclass_of($sDashletClass, 'Dashlet'))
{
$oDashlet = new $sDashletClass(new ModelReflectionRuntime(), $sDashletId);
@@ -1352,13 +1352,14 @@ EOF
case 'update_dashlet_property':
require_once(APPROOT.'application/forms.class.inc.php');
require_once(APPROOT.'application/dashlet.class.inc.php');
$aExtraParams = utils::ReadParam('extra_params', array(), false, 'raw_data');
$aParams = utils::ReadParam('params', '', false, 'raw_data');
$sDashletClass = $aParams['attr_dashlet_class'];
$sDashletType = $aParams['attr_dashlet_type'];
$sDashletId = utils::HtmlEntities($aParams['attr_dashlet_id']);
$aUpdatedProperties = $aParams['updated']; // Code of the changed properties as an array: 'attr_xxx', 'attr_xxy', etc...
$aPreviousValues = $aParams['previous_values']; // hash array: 'attr_xxx' => 'old_value'
$aExtraParams = utils::ReadParam('extra_params', array(), false, utils::ENUM_SANITIZATION_FILTER_RAW_DATA);
$aParams = utils::ReadParam('params', [], false, utils::ENUM_SANITIZATION_FILTER_RAW_DATA); // raw_data because we need different filter depending on the options
$sDashletClass = utils::Sanitize($aParams['attr_dashlet_class'], DashletUnknown::class, utils::ENUM_SANITIZATION_FILTER_PHP_CLASS); // Dashlet PHP class or DashletUnknown if impl isn't present in the installed extensions
$sDashletType = utils::Sanitize($aParams['attr_dashlet_type'], '', utils::ENUM_SANITIZATION_FILTER_PHP_CLASS); // original Dashlet PHP class, could be non-existing on the iTop instance (XML definition loading)
$sDashletId = utils::Sanitize($aParams['attr_dashlet_id'], '', utils::ENUM_SANITIZATION_FILTER_ELEMENT_IDENTIFIER);
$aUpdatedProperties = utils::Sanitize($aParams['updated'], [], utils::ENUM_SANITIZATION_FILTER_ELEMENT_IDENTIFIER); // Code of the changed properties as an array: 'attr_xxx', 'attr_xxy' etc
$aPreviousValues = utils::Sanitize($aParams['previous_values'], [], utils::ENUM_SANITIZATION_FILTER_RAW_DATA); // hash array: 'attr_xxx' => 'old_value' - no sanitization as values will be handled in the Dashlet object
if (is_subclass_of($sDashletClass, 'Dashlet'))
{
/** @var \Dashlet $oDashlet */

View File

@@ -48,8 +48,9 @@ session_write_close();
$sTargetPage = APPROOT.'env-'.$sEnvironment.'/'.$sModule.'/'.$sPage;
if (!file_exists($sTargetPage))
{
if (!file_exists($sTargetPage)
|| (strtolower(pathinfo($sTargetPage, PATHINFO_EXTENSION)) !== "php")
) {
// Do not recall the parameters (security takes precedence)
echo "Wrong module, page name or environment...";
exit;

View File

@@ -305,9 +305,8 @@ class DBBackup
// Store the results in a temporary file
$sTmpFileName = self::EscapeShellArg($sBackupFileName);
$sPortOption = self::GetMysqliCliSingleOption('port', $this->iDBPort);
$sPortAndTransportOptions = self::GetMysqlCliPortAndTransportOptions($this->sDBHost, $this->iDBPort);
$sTlsOptions = self::GetMysqlCliTlsOptions($this->oConfig);
$sProtocolOption = self::GetMysqlCliTransportOption($this->sDBHost);
$sMysqlVersion = CMDBSource::GetDBVersion();
$bIsMysqlSupportUtf8mb4 = (version_compare($sMysqlVersion, self::MYSQL_VERSION_WITH_UTF8MB4_IN_PROGRAMS) === -1);
@@ -326,10 +325,10 @@ EOF;
chmod($sMySQLDumpCnfFile, 0600);
file_put_contents($sMySQLDumpCnfFile, $sMySQLDumpCnf, LOCK_EX);
// Note: opt implicitely sets lock-tables... which cancels the benefit of single-transaction!
// Note: opt implicitly sets lock-tables... which cancels the benefit of single-transaction!
// skip-lock-tables compensates and allows for writes during a backup
$sCommand = "$sMySQLDump --defaults-extra-file=\"$sMySQLDumpCnfFile\" --opt --skip-lock-tables --default-character-set=".$sMysqldumpCharset." --add-drop-database --single-transaction --host=$sHost $sPortOption $sProtocolOption --user=$sUser $sTlsOptions --result-file=$sTmpFileName $sDBName $sTables 2>&1";
$sCommandDisplay = "$sMySQLDump --defaults-extra-file=\"$sMySQLDumpCnfFile\" --opt --skip-lock-tables --default-character-set=".$sMysqldumpCharset." --add-drop-database --single-transaction --host=$sHost $sPortOption $sProtocolOption --user=xxxxx $sTlsOptions --result-file=$sTmpFileName $sDBName $sTables";
$sCommand = "$sMySQLDump --defaults-extra-file=\"$sMySQLDumpCnfFile\" --opt --skip-lock-tables --default-character-set=" . $sMysqldumpCharset . " --add-drop-database --single-transaction --host=$sHost $sPortAndTransportOptions --user=$sUser $sTlsOptions --result-file=$sTmpFileName $sDBName $sTables 2>&1";
$sCommandDisplay = "$sMySQLDump --defaults-extra-file=\"$sMySQLDumpCnfFile\" --opt --skip-lock-tables --default-character-set=" . $sMysqldumpCharset . " --add-drop-database --single-transaction --host=$sHost $sPortAndTransportOptions --user=xxxxx $sTlsOptions --result-file=$sTmpFileName $sDBName $sTables";
// Now run the command for real
$this->LogInfo("backup: generate data file with command: $sCommandDisplay");
@@ -523,25 +522,37 @@ EOF;
}
/**
* Define if we should force a transport option
*
* @param string $sHost
* @return string CLI options for port and protocol
*
* @return string .
* @since 2.7.9 3.0.4 3.1.1 N°6123
* @since 2.7.9 3.0.4 3.1.1 N°6123 method creation
* @since 2.7.10 3.0.4 3.1.2 3.2.0 N°6889 rename method to return both port and transport options. Keep default socket connexion if we are on localhost with no port
*
* @link https://bugs.mysql.com/bug.php?id=55796 MySQL CLI tools will ignore `--port` option on localhost
* @link https://jira.mariadb.org/browse/MDEV-14974 Since 10.6.1 the MariaDB CLI tools will use the `--port` option on host=localhost
*/
public static function GetMysqlCliTransportOption(string $sHost)
private static function GetMysqlCliPortAndTransportOptions(string $sHost, ?int $iPort): string
{
$sTransportOptions = '';
/** N°6123 As we're using a --port option, if we use localhost as host,
* MariaDB > 10.6 will implicitly change its protocol from socket to tcp and throw a warning **/
if($sHost === 'localhost'){
$sTransportOptions = '--protocol=tcp';
if (strtolower($sHost) === 'localhost') {
/**
* Since MariaDB 10.6.1 if we have host=localhost, and only the --port option we will get a warning
* To avoid this warning if we want to set --port option we must set --protocol=tcp
**/
if (is_null($iPort)) {
// no port specified => no option to return, this will mean using socket protocol (unix socket)
return '';
}
$sPortOption = self::GetMysqliCliSingleOption('port', $iPort);
$sTransportOptions = ' --protocol=tcp';
return $sPortOption . $sTransportOptions;
}
return $sTransportOptions;
if (is_null($iPort)) {
$iPort = CMDBSource::MYSQL_DEFAULT_PORT;
}
$sPortOption = self::GetMysqliCliSingleOption('port', $iPort);
return $sPortOption;
}
/**

View File

@@ -38,7 +38,7 @@ $oP = new SetupPage('iTop email test utility');
// Although this page doesn't expose sensitive info, with it we can send multiple emails
// So we're adding this http header to reduce CSRF exposure...
$oP->add_xframe_options('DENY');
$oP->add_http_headers('DENY');
/**

Some files were not shown because too many files have changed in this diff Show More