mirror of
https://github.com/Combodo/iTop.git
synced 2026-10-09 09:59:13 +02:00
Compare commits
26 Commits
feature/10
...
support/3.
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
84a92b8529 | ||
|
|
4639d06a0d | ||
|
|
5c962b0fef | ||
|
|
09574d90d5 | ||
|
|
d375fc7d82 | ||
|
|
a32cff4286 | ||
|
|
87b6b34683 | ||
|
|
0a4bbfe5a9 | ||
|
|
31a4e1a0a0 | ||
|
|
de74103118 | ||
|
|
67c6a0732c | ||
|
|
a2a00cb582 | ||
|
|
4e8d34bb23 | ||
|
|
4d699f79e8 | ||
|
|
4e70886d2a | ||
|
|
c2929ecd33 | ||
|
|
873cea1a76 | ||
|
|
b7432b9e60 | ||
|
|
adc2596b4a | ||
|
|
16d68fe993 | ||
|
|
4e1bf80b9f | ||
|
|
2ac4229ee0 | ||
|
|
e6d485855e | ||
|
|
ab9d270b62 | ||
|
|
4a6af15237 | ||
|
|
05e585ced3 |
@@ -110,11 +110,11 @@ gitGraph
|
||||
commit id: "2025-09-25" tag: "2.7.13"
|
||||
checkout support/3.2
|
||||
commit id: "2026-04-27 " tag: "3.2.3"
|
||||
checkout support/3.2.3
|
||||
commit id: "2026-05-25 " tag: "3.2.3-1"
|
||||
commit id: "2026-07-17 " tag: "3.2.3-2"
|
||||
checkout develop
|
||||
commit id: "2026-07-23" tag: "3.3.0-beta1"
|
||||
commit id: "2026-09-15" tag: "3.3.0"
|
||||
```
|
||||
|
||||
To learn more, check the [iTop community versions history on the official wiki](https://www.itophub.io/wiki/page?id=latest:release:start).
|
||||
|
||||
1
.github/ISSUE_TEMPLATE/enhancement.yml
vendored
1
.github/ISSUE_TEMPLATE/enhancement.yml
vendored
@@ -9,6 +9,7 @@ body:
|
||||
- Please describe what's your improvement proposition.
|
||||
- Then tell us if you're willing to create a PR for this enhancement ? If so, we'll indicate in the issue if we're interested in it.
|
||||
- The more users are affected and the greater is the impact, the more likely this improvement will be accepted. If you identified a bug and have an improvement proposition, please use the 'Bug report' template instead."
|
||||
Please note we're not willing to accept code improvement (e.g. refactoring) that won't have a "functional" change for the user.
|
||||
|
||||
- type: textarea
|
||||
id: enhancement_details
|
||||
|
||||
5
.github/pull_request_template.md
vendored
5
.github/pull_request_template.md
vendored
@@ -2,8 +2,11 @@
|
||||
IMPORTANT: Before creating your PR, please create an issue first to know if Combodo is interested in your contribution (not needed for translations PR).
|
||||
Since we may refuse a PR, it's preferable to create an issue first, to avoid spending time coding something that won't be accepted.
|
||||
PR that will benefit the most users and has a greater impact on the product are more likely to be accepted, so please explain your use case and why you think it would be useful for the community.
|
||||
We're not willing to receive PR concerning codes improvements (e.g. code refactoring), except if it's part of a code that brings/corrects a feature for users.
|
||||
Please note that we're working with sprints, so we reserve the right to decline a PR if we do not plan to work on that subject in the 6 coming months.
|
||||
Thank you for your comprehension 😊
|
||||
|
||||
Once you've done it, and we confirmed we're interested in it, please follow the guidelines within this PR template before submitting it, it will greatly help us process your PR. 🙏
|
||||
Once you've created the issue, and we confirmed we're interested in it, please follow the guidelines within this PR template before submitting it, it will greatly help us process your PR. 🙏
|
||||
|
||||
Any PRs not following the guidelines or with missing information will not be considered.
|
||||
-->
|
||||
|
||||
1
.gitignore
vendored
1
.gitignore
vendored
@@ -33,7 +33,6 @@ tests/*/vendor/*
|
||||
!/data/index.php
|
||||
!/data/web.config
|
||||
!/data/exclude.txt
|
||||
!/data/.compilation-symlinks
|
||||
|
||||
# iTop extensions
|
||||
/extensions/**
|
||||
|
||||
@@ -61,7 +61,7 @@ foreach ($aTcpdfFontsDirContent as $sTcpdfFontResourceName) {
|
||||
* 2) Then adding the DroidSansFallback font (useful for CJK data for example)
|
||||
*/
|
||||
echo $sCurrentScriptFileName.": ---2) Copying font files to TCPDF ($sTcPdfFontsFolder)...\n";
|
||||
$aFontFilesToCopy = glob(__DIR__.'\droidsansfallback.*');
|
||||
$aFontFilesToCopy = glob(__DIR__.DIRECTORY_SEPARATOR.'droidsansfallback.*');
|
||||
foreach ($aFontFilesToCopy as $sFontFileToCopy) {
|
||||
$sFontFileName = basename($sFontFileToCopy);
|
||||
echo $sCurrentScriptFileName.': copying '.$sFontFileName."\n";
|
||||
|
||||
@@ -109,10 +109,18 @@ $('#shortcut_rename_dlg').dialog({
|
||||
modal: true,
|
||||
title: '$sDialogTitle',
|
||||
buttons: [
|
||||
{ text: "$sOkButtonLabel", click: ShortcutRenameOK},
|
||||
{ text: "$sCancelButtonLabel", click: function() {
|
||||
$(this).dialog( "close" ); $(this).remove();
|
||||
} },
|
||||
{
|
||||
text: "$sCancelButtonLabel",
|
||||
click: function() {
|
||||
$(this).dialog( "close" ); $(this).remove();
|
||||
},
|
||||
'class': 'ibo-button ibo-is-alternative ibo-is-neutral action cancel'
|
||||
},
|
||||
{
|
||||
text: "$sOkButtonLabel",
|
||||
click: ShortcutRenameOK,
|
||||
'class': 'ibo-is-regular ibo-is-primary'
|
||||
},
|
||||
],
|
||||
close: function() { $(this).remove(); }
|
||||
});
|
||||
|
||||
@@ -1886,6 +1886,9 @@ SQL;
|
||||
$aHTTPHeaders[] = trim($sHeaderString);
|
||||
}
|
||||
// Default options, can be overloaded/extended with the 4th parameter of this method, see above $aCurlOptions
|
||||
$iCurlAllowedProtocols = self::ConvertProtocolsToCurlOption(
|
||||
self::GetConfig()->Get('security.post_requests.allowed_protocols')
|
||||
);
|
||||
$aOptions = [
|
||||
CURLOPT_RETURNTRANSFER => true, // return the content of the request
|
||||
CURLOPT_HEADER => false, // don't return the headers in the output
|
||||
@@ -1908,6 +1911,9 @@ SQL;
|
||||
$aAllOptions = $aCurlOptions + $aOptions;
|
||||
$ch = curl_init($sUrl);
|
||||
curl_setopt_array($ch, $aAllOptions);
|
||||
if (!curl_setopt($ch, CURLOPT_PROTOCOLS, $iCurlAllowedProtocols)) {
|
||||
throw new Exception('Unable to enforce allowed protocols for cURL request');
|
||||
}
|
||||
$response = curl_exec($ch);
|
||||
$iErr = curl_errno($ch);
|
||||
$sErrMsg = curl_error($ch);
|
||||
@@ -1929,6 +1935,40 @@ SQL;
|
||||
return $response;
|
||||
}
|
||||
|
||||
private static function ConvertProtocolsToCurlOption(string $sProtocols): int
|
||||
{
|
||||
$aProtocols = explode(',', $sProtocols);
|
||||
|
||||
$iCurlProtocols = 0;
|
||||
foreach ($aProtocols as $sProtocol) {
|
||||
$iCurlProtocols |= match (strtolower(trim($sProtocol))) {
|
||||
'dict' => defined('CURLPROTO_DICT') ? CURLPROTO_DICT : 0,
|
||||
'file' => defined('CURLPROTO_FILE') ? CURLPROTO_FILE : 0,
|
||||
'ftp' => defined('CURLPROTO_FTP') ? CURLPROTO_FTP : 0,
|
||||
'ftps' => defined('CURLPROTO_FTPS') ? CURLPROTO_FTPS : 0,
|
||||
'gopher' => defined('CURLPROTO_GOPHER') ? CURLPROTO_GOPHER : 0,
|
||||
'http' => defined('CURLPROTO_HTTP') ? CURLPROTO_HTTP : 0,
|
||||
'https' => defined('CURLPROTO_HTTPS') ? CURLPROTO_HTTPS : 0,
|
||||
'imap' => defined('CURLPROTO_IMAP') ? CURLPROTO_IMAP : 0,
|
||||
'imaps' => defined('CURLPROTO_IMAPS') ? CURLPROTO_IMAPS : 0,
|
||||
'ldap' => defined('CURLPROTO_LDAP') ? CURLPROTO_LDAP : 0,
|
||||
'ldaps' => defined('CURLPROTO_LDAPS') ? CURLPROTO_LDAPS : 0,
|
||||
'mqtt' => defined('CURLPROTO_MQTT') ? CURLPROTO_MQTT : 0,
|
||||
'pop3' => defined('CURLPROTO_POP3') ? CURLPROTO_POP3 : 0,
|
||||
'pop3s' => defined('CURLPROTO_POP3S') ? CURLPROTO_POP3S : 0,
|
||||
'rtsp' => defined('CURLPROTO_RTSP') ? CURLPROTO_RTSP : 0,
|
||||
'scp' => defined('CURLPROTO_SCP') ? CURLPROTO_SCP : 0,
|
||||
'sftp' => defined('CURLPROTO_SFTP') ? CURLPROTO_SFTP : 0,
|
||||
'smtp' => defined('CURLPROTO_SMTP') ? CURLPROTO_SMTP : 0,
|
||||
'smtps' => defined('CURLPROTO_SMTPS') ? CURLPROTO_SMTPS : 0,
|
||||
'telnet' => defined('CURLPROTO_TELNET') ? CURLPROTO_TELNET : 0,
|
||||
'tftp' => defined('CURLPROTO_TFTP') ? CURLPROTO_TFTP : 0,
|
||||
default => throw new Exception("Unsupported protocol: $sProtocol"),
|
||||
};
|
||||
}
|
||||
return $iCurlProtocols;
|
||||
}
|
||||
|
||||
public static function QuoteForPHP(string $sValue): string
|
||||
{
|
||||
$sEscaped = str_replace(['\\', "'"], ['\\\\', "\\'"], $sValue);
|
||||
|
||||
@@ -23,7 +23,7 @@ define('ITOP_DESIGN_LATEST_VERSION', '3.3');
|
||||
* @used-by utils::GetItopVersionWikiSyntax()
|
||||
* @used-by iTopModulesPhpVersionIntegrationTest
|
||||
*/
|
||||
define('ITOP_CORE_VERSION', '3.3.0');
|
||||
define('ITOP_CORE_VERSION', '3.3.1');
|
||||
|
||||
/**
|
||||
* @var string
|
||||
|
||||
@@ -29,7 +29,7 @@ define('ITOP_APPLICATION_SHORT', 'iTop');
|
||||
*
|
||||
* @see ITOP_CORE_VERSION to get iTop core version
|
||||
*/
|
||||
define('ITOP_VERSION', '3.3.0-dev');
|
||||
define('ITOP_VERSION', '3.3.1-dev');
|
||||
|
||||
define('ITOP_VERSION_NAME', 'Fullmoon');
|
||||
define('ITOP_REVISION', 'svn');
|
||||
@@ -1765,8 +1765,8 @@ class Config
|
||||
'security.disable_joined_classes_filter' => [
|
||||
'type' => 'bool',
|
||||
'description' => 'If true, scope filters aren\'t applied to joined classes or union classes not directly listed in the SELECT clause.',
|
||||
'default' => true,
|
||||
'value' => true,
|
||||
'default' => false,
|
||||
'value' => false,
|
||||
'source_of_value' => '',
|
||||
'show_in_conf_sample' => false,
|
||||
],
|
||||
@@ -1781,8 +1781,16 @@ class Config
|
||||
'security.disable_exec_forced_login_for_all_enpoints' => [
|
||||
'type' => 'bool',
|
||||
'description' => 'If true, when no delegated authentication module is defined, no login will be forced on modules exec endpoints',
|
||||
'default' => true,
|
||||
'value' => true,
|
||||
'default' => false,
|
||||
'value' => false,
|
||||
'source_of_value' => '',
|
||||
'show_in_conf_sample' => false,
|
||||
],
|
||||
'security.post_requests.allowed_protocols' => [
|
||||
'type' => 'string',
|
||||
'description' => 'List of allowed protocols that will be used for post requests. Allowed values: dict, file, ftp, ftps, gopher, http, https, imap, imaps, ldap, ldaps, mqtt, pop3, pop3s, rtsp, scp, sftp, smtp, smtps, telnet, tftp',
|
||||
'default' => 'http,https,ftp,ftps,sftp',
|
||||
'value' => 'http,https,ftp,ftps,sftp',
|
||||
'source_of_value' => '',
|
||||
'show_in_conf_sample' => false,
|
||||
],
|
||||
|
||||
@@ -1711,7 +1711,7 @@ class DBObjectSearch extends DBSearch
|
||||
* @return array|mixed|\SQLObjectQuery|null
|
||||
* @throws \CoreException
|
||||
*/
|
||||
public function GetSQLQueryStructure($aAttToLoad, $bGetCount, $aGroupByExpr = null, $aSelectedClasses = null, $aSelectExpr = null)
|
||||
public function GetSQLQueryStructure($aAttToLoad, $bGetCount, $aGroupByExpr = null, $aSelectedClasses = null, $aSelectExpr = null, $bSelectOnlyIds = false)
|
||||
{
|
||||
// Hide objects that are not visible to the current user
|
||||
//
|
||||
@@ -1782,6 +1782,8 @@ class DBObjectSearch extends DBSearch
|
||||
$aContextData['aSelectExpr'] = $aSelectExpr;
|
||||
$sRawId .= $bGetCount;
|
||||
$aContextData['bGetCount'] = $bGetCount;
|
||||
$sRawId .= 'ids:'.($bSelectOnlyIds ? '1' : '0');
|
||||
$aContextData['bSelectOnlyIds'] = $bSelectOnlyIds;
|
||||
if (is_array($aSelectedClasses)) {
|
||||
$sRawId .= implode(',', $aSelectedClasses); // Unions may alter the list of selected columns
|
||||
}
|
||||
@@ -1835,7 +1837,7 @@ class DBObjectSearch extends DBSearch
|
||||
if (!isset($oSQLQuery)) {
|
||||
$oKPI = new ExecutionKPI();
|
||||
$oSQLObjectQueryBuilder = new SQLObjectQueryBuilder($oSearch);
|
||||
$oSQLQuery = $oSQLObjectQueryBuilder->BuildSQLQueryStruct($aAttToLoad, $bGetCount, $aModifierProperties, $aGroupByExpr, $aSelectedClasses, $aSelectExpr);
|
||||
$oSQLQuery = $oSQLObjectQueryBuilder->BuildSQLQueryStruct($aAttToLoad, $bGetCount, $aModifierProperties, $aGroupByExpr, $aSelectedClasses, $aSelectExpr, $bSelectOnlyIds);
|
||||
$oKPI->ComputeStats('BuildSQLQueryStruct', $sOqlQuery);
|
||||
|
||||
if (self::$m_bQueryCacheEnabled) {
|
||||
@@ -1945,7 +1947,7 @@ class DBObjectSearch extends DBSearch
|
||||
$oSearch = $this;
|
||||
$aClassesToFilter = $this->GetSelectedClasses();
|
||||
|
||||
// Opt-in for joined classes filtering, otherwise only filter the selected class(es)
|
||||
// Joined classes filtering can be disabled through the configuration.
|
||||
if (MetaModel::GetConfig()->Get('security.disable_joined_classes_filter') === false) {
|
||||
$aClassesToFilter = $this->GetJoinedClasses();
|
||||
}
|
||||
|
||||
@@ -921,7 +921,7 @@ abstract class DBSearch
|
||||
* @internal
|
||||
*
|
||||
*/
|
||||
public function MakeSelectQuery($aOrderBy = [], $aArgs = [], $aAttToLoad = null, $aExtendedDataSpec = null, $iLimitCount = 0, $iLimitStart = 0, $bGetCount = false, $bBeautifulSQL = true)
|
||||
public function MakeSelectQuery($aOrderBy = [], $aArgs = [], $aAttToLoad = null, $aExtendedDataSpec = null, $iLimitCount = 0, $iLimitStart = 0, $bGetCount = false, $bBeautifulSQL = true, $bSelectOnlyIds = false)
|
||||
{
|
||||
// Check the order by specification, and prefix with the class alias
|
||||
// and make sure that the ordering columns are going to be selected
|
||||
@@ -962,7 +962,7 @@ abstract class DBSearch
|
||||
}
|
||||
}
|
||||
|
||||
$oSQLQuery = $this->GetSQLQuery($aOrderBy, $aArgs, $aAttToLoad, $aExtendedDataSpec, $iLimitCount, $iLimitStart, $bGetCount);
|
||||
$oSQLQuery = $this->GetSQLQuery($aOrderBy, $aArgs, $aAttToLoad, $aExtendedDataSpec, $iLimitCount, $iLimitStart, $bGetCount, null, null, $bSelectOnlyIds);
|
||||
|
||||
if ($this->m_bNoContextParameters) {
|
||||
// Only internal parameters
|
||||
@@ -1046,7 +1046,7 @@ abstract class DBSearch
|
||||
* @internal
|
||||
*
|
||||
*/
|
||||
protected function GetSQLQuery($aOrderBy, $aArgs, $aAttToLoad, $aExtendedDataSpec, $iLimitCount, $iLimitStart, $bGetCount, $aGroupByExpr = null, $aSelectExpr = null)
|
||||
protected function GetSQLQuery($aOrderBy, $aArgs, $aAttToLoad, $aExtendedDataSpec, $iLimitCount, $iLimitStart, $bGetCount, $aGroupByExpr = null, $aSelectExpr = null, $bSelectOnlyIds = false)
|
||||
{
|
||||
$oSearch = $this->ApplyDataFilters();
|
||||
|
||||
@@ -1068,7 +1068,7 @@ abstract class DBSearch
|
||||
}
|
||||
}
|
||||
|
||||
$oSQLQuery = $oSearch->GetSQLQueryStructure($aAttToLoad, $bGetCount, $aGroupByExpr, null, $aSelectExpr);
|
||||
$oSQLQuery = $oSearch->GetSQLQueryStructure($aAttToLoad, $bGetCount, $aGroupByExpr, null, $aSelectExpr, $bSelectOnlyIds);
|
||||
$oSQLQuery->SetSourceOQL($oSearch->ToOQL());
|
||||
|
||||
// Join to an additional table, if required...
|
||||
@@ -1103,7 +1103,8 @@ abstract class DBSearch
|
||||
$bGetCount,
|
||||
$aGroupByExpr = null,
|
||||
$aSelectedClasses = null,
|
||||
$aSelectExpr = null
|
||||
$aSelectExpr = null,
|
||||
$bSelectOnlyIds = false
|
||||
);
|
||||
|
||||
/**
|
||||
|
||||
@@ -527,10 +527,10 @@ class DBUnionSearch extends DBSearch
|
||||
throw new Exception('MakeUpdateQuery is not implemented for the unions!');
|
||||
}
|
||||
|
||||
public function GetSQLQueryStructure($aAttToLoad, $bGetCount, $aGroupByExpr = null, $aSelectedClasses = null, $aSelectExpr = null)
|
||||
public function GetSQLQueryStructure($aAttToLoad, $bGetCount, $aGroupByExpr = null, $aSelectedClasses = null, $aSelectExpr = null, $bSelectOnlyIds = false)
|
||||
{
|
||||
if (count($this->aSearches) == 1) {
|
||||
return $this->aSearches[0]->GetSQLQueryStructure($aAttToLoad, $bGetCount, $aGroupByExpr, $aSelectedClasses, $aSelectExpr);
|
||||
return $this->aSearches[0]->GetSQLQueryStructure($aAttToLoad, $bGetCount, $aGroupByExpr, $aSelectedClasses, $aSelectExpr, $bSelectOnlyIds);
|
||||
}
|
||||
|
||||
$aSQLQueries = [];
|
||||
@@ -610,7 +610,7 @@ class DBUnionSearch extends DBSearch
|
||||
}
|
||||
}
|
||||
}
|
||||
$oSubQuery = $oSearch->GetSQLQueryStructure($aQueryAttToLoad, false, $aQueryGroupByExpr, $aSearchSelectedClasses, $aQuerySelectExpr);
|
||||
$oSubQuery = $oSearch->GetSQLQueryStructure($aQueryAttToLoad, false, $aQueryGroupByExpr, $aSearchSelectedClasses, $aQuerySelectExpr, $bSelectOnlyIds);
|
||||
if (count($aSearchAliases) > 1) {
|
||||
// Necessary to make sure that selected columns will match throughout all the queries
|
||||
// (default order of selected fields depending on the order of JOINS)
|
||||
@@ -683,7 +683,7 @@ class DBUnionSearch extends DBSearch
|
||||
return $this;
|
||||
}
|
||||
|
||||
// Opt-in for joined classes filtering, otherwise fallback on DBSearch filtering
|
||||
// Joined classes filtering can be disabled through the configuration.
|
||||
if (MetaModel::GetConfig()->Get('security.disable_joined_classes_filter') === true) {
|
||||
return parent::ApplyDataFilters();
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -29,13 +29,14 @@ class SQLObjectQueryBuilder
|
||||
* @param array $aGroupByExpr
|
||||
* @param array $aSelectedClasses
|
||||
* @param array $aSelectExpr
|
||||
* @param bool $bSelectOnlyIds
|
||||
*
|
||||
* @return null|SQLObjectQuery
|
||||
* @throws \CoreException
|
||||
*/
|
||||
public function BuildSQLQueryStruct($aAttToLoad, $bGetCount, $aModifierProperties, $aGroupByExpr = null, $aSelectedClasses = null, $aSelectExpr = null)
|
||||
public function BuildSQLQueryStruct($aAttToLoad, $bGetCount, $aModifierProperties, $aGroupByExpr = null, $aSelectedClasses = null, $aSelectExpr = null, $bSelectOnlyIds = false)
|
||||
{
|
||||
if ($bGetCount || !is_null($aGroupByExpr)) {
|
||||
if ($bGetCount || !is_null($aGroupByExpr) || $bSelectOnlyIds) {
|
||||
// Avoid adding all the fields for counts or "group by" requests
|
||||
$aAttToLoad = [];
|
||||
foreach ($this->oDBObjetSearch->GetSelectedClasses() as $sClassAlias => $sClass) {
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
|
||||
SetupWebPage::AddModule(
|
||||
__FILE__, // Path to the current file, all other file names are relative to the directory containing this file
|
||||
'authent-cas/3.3.0',
|
||||
'authent-cas/3.3.1',
|
||||
[
|
||||
// Identification
|
||||
//
|
||||
|
||||
@@ -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/3.3.0',
|
||||
'authent-external/3.3.1',
|
||||
[
|
||||
// Identification
|
||||
//
|
||||
|
||||
@@ -7,7 +7,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/3.3.0',
|
||||
'authent-ldap/3.3.1',
|
||||
[
|
||||
// Identification
|
||||
//
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
SetupWebPage::AddModule(
|
||||
__FILE__, // Path to the current file, all other file names are relative to the directory containing this file
|
||||
'authent-local/3.3.0',
|
||||
'authent-local/3.3.1',
|
||||
[
|
||||
// Identification
|
||||
//
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
|
||||
SetupWebPage::AddModule(
|
||||
__FILE__, // Path to the current file, all other file names are relative to the directory containing this file
|
||||
'combodo-backoffice-darkmoon-theme/3.3.0',
|
||||
'combodo-backoffice-darkmoon-theme/3.3.1',
|
||||
[
|
||||
// Identification
|
||||
//
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
|
||||
SetupWebPage::AddModule(
|
||||
__FILE__, // Path to the current file, all other file names are relative to the directory containing this file
|
||||
'combodo-backoffice-fullmoon-high-contrast-theme/3.3.0',
|
||||
'combodo-backoffice-fullmoon-high-contrast-theme/3.3.1',
|
||||
[
|
||||
// Identification
|
||||
//
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
|
||||
SetupWebPage::AddModule(
|
||||
__FILE__, // Path to the current file, all other file names are relative to the directory containing this file
|
||||
'combodo-backoffice-fullmoon-protanopia-deuteranopia-theme/3.3.0',
|
||||
'combodo-backoffice-fullmoon-protanopia-deuteranopia-theme/3.3.1',
|
||||
[
|
||||
// Identification
|
||||
//
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
|
||||
SetupWebPage::AddModule(
|
||||
__FILE__, // Path to the current file, all other file names are relative to the directory containing this file
|
||||
'combodo-backoffice-fullmoon-tritanopia-theme/3.3.0',
|
||||
'combodo-backoffice-fullmoon-tritanopia-theme/3.3.1',
|
||||
[
|
||||
// Identification
|
||||
//
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
|
||||
SetupWebPage::AddModule(
|
||||
__FILE__, // Path to the current file, all other file names are relative to the directory containing this file
|
||||
'combodo-data-feature-removal/3.3.0',
|
||||
'combodo-data-feature-removal/3.3.1',
|
||||
[
|
||||
// Identification
|
||||
//
|
||||
|
||||
@@ -25,7 +25,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/3.3.0',
|
||||
'combodo-db-tools/3.3.1',
|
||||
[
|
||||
// Identification
|
||||
//
|
||||
|
||||
@@ -56,7 +56,7 @@ function RenderAttachments(AjaxPage $oPage, $iTransactionId)
|
||||
try {
|
||||
require_once APPROOT.'/application/startup.inc.php';
|
||||
require_once APPROOT.'/application/loginwebpage.class.inc.php';
|
||||
LoginWebPage::DoLoginEx(null /* any portal */, false);
|
||||
LoginWebPage::DoLogin(); // No user portal should access this endpoint.
|
||||
|
||||
$oPage = new AjaxPage("");
|
||||
|
||||
@@ -105,15 +105,6 @@ try {
|
||||
$oPage->SetData($aResult);
|
||||
break;
|
||||
|
||||
case 'remove':
|
||||
$iAttachmentId = utils::ReadParam('att_id', '');
|
||||
$oSearch = DBObjectSearch::FromOQL("SELECT Attachment WHERE id = :id");
|
||||
$oSet = new DBObjectSet($oSearch, [], ['id' => $iAttachmentId]);
|
||||
while ($oAttachment = $oSet->Fetch()) {
|
||||
$oAttachment->DBDelete();
|
||||
}
|
||||
break;
|
||||
|
||||
case 'refresh_attachments_render':
|
||||
$sTempId = utils::ReadParam('temp_id', '', false, 'transaction_id');
|
||||
RenderAttachments($oPage, $sTempId);
|
||||
|
||||
@@ -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/3.3.0',
|
||||
'itop-attachments/3.3.1',
|
||||
[
|
||||
// Identification
|
||||
//
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
SetupWebPage::AddModule(
|
||||
__FILE__, // Path to the current file, all other file names are relative to the directory containing this file
|
||||
'itop-backup/3.3.0',
|
||||
'itop-backup/3.3.1',
|
||||
[
|
||||
// Identification
|
||||
//
|
||||
|
||||
@@ -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-bridge-cmdb-services/3.3.0',
|
||||
'itop-bridge-cmdb-services/3.3.1',
|
||||
[
|
||||
// Identification
|
||||
//
|
||||
|
||||
@@ -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-bridge-cmdb-ticket/3.3.0',
|
||||
'itop-bridge-cmdb-ticket/3.3.1',
|
||||
[
|
||||
// Identification
|
||||
//
|
||||
|
||||
@@ -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-bridge-datacenter-mgmt-services/3.3.0',
|
||||
'itop-bridge-datacenter-mgmt-services/3.3.1',
|
||||
[
|
||||
// Identification
|
||||
//
|
||||
|
||||
@@ -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-bridge-endusers-devices-services/3.3.0',
|
||||
'itop-bridge-endusers-devices-services/3.3.1',
|
||||
[
|
||||
// Identification
|
||||
//
|
||||
|
||||
@@ -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-bridge-storage-mgmt-services/3.3.0',
|
||||
'itop-bridge-storage-mgmt-services/3.3.1',
|
||||
[
|
||||
// Identification
|
||||
//
|
||||
|
||||
@@ -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-bridge-virtualization-mgmt-services/3.3.0',
|
||||
'itop-bridge-virtualization-mgmt-services/3.3.1',
|
||||
[
|
||||
// Identification
|
||||
//
|
||||
|
||||
@@ -2,7 +2,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/3.3.0',
|
||||
'itop-bridge-virtualization-storage/3.3.1',
|
||||
[
|
||||
// Identification
|
||||
//
|
||||
|
||||
@@ -2,7 +2,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/3.3.0',
|
||||
'itop-change-mgmt-itil/3.3.1',
|
||||
[
|
||||
// Identification
|
||||
//
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
SetupWebPage::AddModule(
|
||||
__FILE__, // Path to the current file, all other file names are relative to the directory containing this file
|
||||
'itop-change-mgmt/3.3.0',
|
||||
'itop-change-mgmt/3.3.1',
|
||||
[
|
||||
// Identification
|
||||
//
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
SetupWebPage::AddModule(
|
||||
__FILE__, // Path to the current file, all other file names are relative to the directory containing this file
|
||||
'itop-config-mgmt/3.3.0',
|
||||
'itop-config-mgmt/3.3.1',
|
||||
[
|
||||
// Identification
|
||||
//
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
SetupWebPage::AddModule(
|
||||
__FILE__, // Path to the current file, all other file names are relative to the directory containing this file
|
||||
'itop-config/3.3.0',
|
||||
'itop-config/3.3.1',
|
||||
[
|
||||
// Identification
|
||||
//
|
||||
|
||||
@@ -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-container-mgmt/3.3.0',
|
||||
'itop-container-mgmt/3.3.1',
|
||||
[
|
||||
// Identification
|
||||
//
|
||||
|
||||
@@ -25,7 +25,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/3.3.0',
|
||||
'itop-core-update/3.3.1',
|
||||
[
|
||||
// Identification
|
||||
//
|
||||
|
||||
@@ -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-datacenter-mgmt/3.3.0',
|
||||
'itop-datacenter-mgmt/3.3.1',
|
||||
[
|
||||
// Identification
|
||||
//
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
|
||||
SetupWebPage::AddModule(
|
||||
__FILE__, // Path to the current file, all other file names are relative to the directory containing this file
|
||||
'itop-endusers-devices/3.3.0',
|
||||
'itop-endusers-devices/3.3.1',
|
||||
[
|
||||
// Identification
|
||||
//
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
SetupWebPage::AddModule(
|
||||
__FILE__, // Path to the current file, all other file names are relative to the directory containing this file
|
||||
'itop-faq-light/3.3.0',
|
||||
'itop-faq-light/3.3.1',
|
||||
[
|
||||
// Identification
|
||||
//
|
||||
|
||||
@@ -25,7 +25,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/3.3.0',
|
||||
'itop-files-information/3.3.1',
|
||||
[
|
||||
// Identification
|
||||
//
|
||||
|
||||
@@ -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-flow-map/3.3.0',
|
||||
'itop-flow-map/3.3.1',
|
||||
[
|
||||
// Identification
|
||||
//
|
||||
|
||||
@@ -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/3.3.0',
|
||||
'itop-full-itil/3.3.1',
|
||||
[
|
||||
// Identification
|
||||
//
|
||||
|
||||
@@ -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-hub-connector/3.3.0',
|
||||
'itop-hub-connector/3.3.1',
|
||||
[
|
||||
// Identification
|
||||
//
|
||||
|
||||
@@ -2,7 +2,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/3.3.0',
|
||||
'itop-incident-mgmt-itil/3.3.1',
|
||||
[
|
||||
// Identification
|
||||
//
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
SetupWebPage::AddModule(
|
||||
__FILE__, // Path to the current file, all other file names are relative to the directory containing this file
|
||||
'itop-knownerror-mgmt/3.3.0',
|
||||
'itop-knownerror-mgmt/3.3.1',
|
||||
[
|
||||
// Identification
|
||||
//
|
||||
|
||||
@@ -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-oauth-client/3.3.0',
|
||||
'itop-oauth-client/3.3.1',
|
||||
[
|
||||
// Identification
|
||||
//
|
||||
|
||||
@@ -21,7 +21,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/3.3.0',
|
||||
'itop-portal-base/3.3.1',
|
||||
[
|
||||
// Identification
|
||||
'label' => 'Portal Development Library',
|
||||
|
||||
@@ -21,7 +21,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/3.3.0',
|
||||
'itop-portal/3.3.1',
|
||||
[
|
||||
// Identification
|
||||
'label' => 'Enhanced Customer Portal',
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
SetupWebPage::AddModule(
|
||||
__FILE__, // Path to the current file, all other file names are relative to the directory containing this file
|
||||
'itop-problem-mgmt/3.3.0',
|
||||
'itop-problem-mgmt/3.3.1',
|
||||
[
|
||||
// Identification
|
||||
//
|
||||
|
||||
@@ -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/3.3.0',
|
||||
'itop-profiles-itil/3.3.1',
|
||||
[
|
||||
// Identification
|
||||
//
|
||||
|
||||
@@ -2,7 +2,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/3.3.0',
|
||||
'itop-request-mgmt-itil/3.3.1',
|
||||
[
|
||||
// Identification
|
||||
//
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
SetupWebPage::AddModule(
|
||||
__FILE__, // Path to the current file, all other file names are relative to the directory containing this file
|
||||
'itop-request-mgmt/3.3.0',
|
||||
'itop-request-mgmt/3.3.1',
|
||||
[
|
||||
// Identification
|
||||
//
|
||||
|
||||
@@ -2,7 +2,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/3.3.0',
|
||||
'itop-service-mgmt-provider/3.3.1',
|
||||
[
|
||||
// Identification
|
||||
//
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
SetupWebPage::AddModule(
|
||||
__FILE__, // Path to the current file, all other file names are relative to the directory containing this file
|
||||
'itop-service-mgmt/3.3.0',
|
||||
'itop-service-mgmt/3.3.1',
|
||||
[
|
||||
// Identification
|
||||
//
|
||||
|
||||
@@ -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-sla-computation/3.3.0',
|
||||
'itop-sla-computation/3.3.1',
|
||||
[
|
||||
// Identification
|
||||
//
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
|
||||
SetupWebPage::AddModule(
|
||||
__FILE__, // Path to the current file, all other file names are relative to the directory containing this file
|
||||
'itop-storage-mgmt/3.3.0',
|
||||
'itop-storage-mgmt/3.3.1',
|
||||
[
|
||||
// Identification
|
||||
//
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
SetupWebPage::AddModule(
|
||||
__FILE__, // Path to the current file, all other file names are relative to the directory containing this file
|
||||
'itop-structure/3.3.0',
|
||||
'itop-structure/3.3.1',
|
||||
[
|
||||
// Identification
|
||||
//
|
||||
|
||||
@@ -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-themes-compat/3.3.0',
|
||||
'itop-themes-compat/3.3.1',
|
||||
[
|
||||
// Identification
|
||||
//
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
SetupWebPage::AddModule(
|
||||
__FILE__,
|
||||
'itop-tickets/3.3.0',
|
||||
'itop-tickets/3.3.1',
|
||||
[
|
||||
// Identification
|
||||
//
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
|
||||
SetupWebPage::AddModule(
|
||||
__FILE__, // Path to the current file, all other file names are relative to the directory containing this file
|
||||
'itop-virtualization-mgmt/3.3.0',
|
||||
'itop-virtualization-mgmt/3.3.1',
|
||||
[
|
||||
// Identification
|
||||
//
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
SetupWebPage::AddModule(
|
||||
__FILE__, // Path to the current file, all other file names are relative to the directory containing this file
|
||||
'itop-welcome-itil/3.3.0',
|
||||
'itop-welcome-itil/3.3.1',
|
||||
[
|
||||
// Identification
|
||||
//
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<information>
|
||||
<version>3.3.0</version>
|
||||
<version>3.3.1</version>
|
||||
</information>
|
||||
|
||||
19
js/pages/backoffice/dialog.js
Normal file
19
js/pages/backoffice/dialog.js
Normal file
@@ -0,0 +1,19 @@
|
||||
/*
|
||||
* @copyright Copyright (C) 2010-2024 Combodo SAS
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
// Overload of the default dialog widget
|
||||
$.widget('ui.dialog', $.ui.dialog, {
|
||||
_allowInteraction: function (oEvent) {
|
||||
const oTarget = $(oEvent.target);
|
||||
// If we interact with a CKEditor instance in fullscreen mode, we need to allow it
|
||||
// We could check if the current instance is in the dialog, but it's easier to always allow it in fullscreen
|
||||
if (oTarget.closest('.ck.ck-fullscreen__main-wrapper, .ck-body-wrapper').length > 0) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// If that's not a specific case, fall back to the default behavior
|
||||
return this._super(oEvent);
|
||||
}
|
||||
});
|
||||
BIN
lib/tecnickcom/tcpdf/fonts/droidsansfallback.ctg.z
Normal file
BIN
lib/tecnickcom/tcpdf/fonts/droidsansfallback.ctg.z
Normal file
Binary file not shown.
2975
lib/tecnickcom/tcpdf/fonts/droidsansfallback.php
Normal file
2975
lib/tecnickcom/tcpdf/fonts/droidsansfallback.php
Normal file
File diff suppressed because it is too large
Load Diff
BIN
lib/tecnickcom/tcpdf/fonts/droidsansfallback.z
Normal file
BIN
lib/tecnickcom/tcpdf/fonts/droidsansfallback.z
Normal file
Binary file not shown.
@@ -768,7 +768,7 @@ try {
|
||||
|
||||
// N°4129 - Prevent XSS attacks & other script executions
|
||||
if (utils::GetConfig()->Get('security.disable_inline_documents_sandbox') === false) {
|
||||
$oPage->add_header('Content-Security-Policy: sandbox;');
|
||||
$oPage->add_header('Content-Security-Policy: sandbox; default-src \'none\'');
|
||||
}
|
||||
|
||||
ormDocument::DownloadDocument($oPage, $sClass, $id, $sField, 'inline');
|
||||
@@ -1239,13 +1239,32 @@ JS
|
||||
$oSearch = new DBObjectSearch('Shortcut');
|
||||
$aShortcuts = utils::ReadMultipleSelection($oSearch);
|
||||
$iShortcut = $aShortcuts[0];
|
||||
$oShortcut = MetaModel::GetObject('Shortcut', $iShortcut);
|
||||
$oShortcutSearch = new DBObjectSearch('Shortcut');
|
||||
$oShortcutSearch->AddCondition('user_id', UserRights::GetUserId(), '=');
|
||||
$oShortcutSearch->AddCondition('id', $iShortcut, '=');
|
||||
$oShortcutSet = new CMDBObjectSet($oShortcutSearch);
|
||||
|
||||
$oShortcut = $oShortcutSet->Fetch();
|
||||
|
||||
if ($oShortcut === null) {
|
||||
throw new SecurityException(Dict::S('UI:ObjectDoesNotExist'));
|
||||
}
|
||||
|
||||
$oShortcut->StartRenameDialog($oPage);
|
||||
break;
|
||||
|
||||
case 'shortcut_rename_go':
|
||||
$iShortcut = utils::ReadParam('id', 0);
|
||||
$oShortcut = MetaModel::GetObject('Shortcut', $iShortcut);
|
||||
|
||||
$oShortcutSearch = new DBObjectSearch('Shortcut');
|
||||
$oShortcutSearch->AddCondition('user_id', UserRights::GetUserId(), '=');
|
||||
$oShortcutSearch->AddCondition('id', $iShortcut, '=');
|
||||
$oShortcutSet = new CMDBObjectSet($oShortcutSearch);
|
||||
$oShortcut = $oShortcutSet->Fetch();
|
||||
|
||||
if ($oShortcut === null) {
|
||||
throw new SecurityException(Dict::S('UI:ObjectDoesNotExist'));
|
||||
}
|
||||
|
||||
$sName = utils::ReadParam('attr_name', '', false, 'raw_data');
|
||||
if (strlen($sName) > 0) {
|
||||
|
||||
@@ -244,7 +244,7 @@ JS
|
||||
);
|
||||
$oShortcutsToolBar->AddSubBlock($oShortcutsRenameButton);
|
||||
// - Delete button
|
||||
$oShortcutsDeleteButton = ButtonUIBlockFactory::MakeForSecondaryAction(
|
||||
$oShortcutsDeleteButton = ButtonUIBlockFactory::MakeForDestructiveAction(
|
||||
Dict::S('UI:Button:Delete'),
|
||||
null,
|
||||
null,
|
||||
|
||||
@@ -1670,20 +1670,7 @@ JS
|
||||
$oExtensionsMap = iTopExtensionsMap::GetExtensionsMap($oWizard->GetParameter('target_env', ITOP_DEFAULT_ENV));
|
||||
$oExtensionsMap->DeclareExtensionAsRemoved($aRemovedExtensionCodes);
|
||||
|
||||
$aAvailableModules = $oProductionEnv->AnalyzeInstallation($oConfig, $aDirsToScan, $bAbortOnMissingDependency, $aModulesToLoad);
|
||||
|
||||
$bRemoteExtensionsShouldBeMandatory = !$oWizard->GetParameter('force-uninstall', false);
|
||||
if ($bRemoteExtensionsShouldBeMandatory) {
|
||||
foreach ($aAvailableModules as $key => $aModule) {
|
||||
$bIsExtra = (array_key_exists('root_dir', $aModule) && (strpos($aModule['root_dir'], $sExtraDir) !== false)); // Some modules (root, datamodel) have no 'root_dir'
|
||||
if ($bIsExtra) {
|
||||
// Modules in data/production-modules/ are considered as mandatory and always installed
|
||||
$aAvailableModules[$key]['visible'] = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $aAvailableModules;
|
||||
return $oProductionEnv->AnalyzeInstallation($oConfig, $aDirsToScan, $bAbortOnMissingDependency, $aModulesToLoad);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -331,12 +331,4 @@ class AjaxPage extends WebPage implements iTabbedPage
|
||||
{
|
||||
assert(false);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public static function FilterXSS($sHTML)
|
||||
{
|
||||
return str_ireplace(['<script', '</script>'], ['<!-- <removed-script', '</removed-script> -->'], $sHTML);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -47,15 +47,9 @@ class DownloadPage extends AjaxPage
|
||||
header($s_header);
|
||||
}
|
||||
|
||||
if (($this->sContentType == 'text/html') && ($this->sContentDisposition == 'inline')) {
|
||||
// inline content != attachment && html => filter all scripts for malicious XSS scripts
|
||||
$sContent = self::FilterXSS($this->sContent);
|
||||
} else {
|
||||
$sContent = $this->sContent;
|
||||
}
|
||||
$oKpi->ComputeAndReport(get_class($this).' output');
|
||||
echo $sContent;
|
||||
$oKpi->ComputeAndReport('Echoing ('.round(strlen($sContent) / 1024).' Kb)');
|
||||
echo $this->sContent;
|
||||
$oKpi->ComputeAndReport('Echoing ('.round(strlen($this->sContent) / 1024).' Kb)');
|
||||
ExecutionKPI::ReportStats();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -209,6 +209,7 @@ class iTopWebPage extends NiceWebPage implements iTabbedPage
|
||||
$this->LinkScriptFromAppRoot('js/pages/backoffice/keyboard-shortcuts.js');
|
||||
|
||||
// Used throughout the app.
|
||||
$this->LinkScriptFromAppRoot('js/pages/backoffice/dialog.js');
|
||||
$this->LinkScriptFromAppRoot('js/pages/backoffice/toolbox.js');
|
||||
$this->LinkScriptFromAppRoot('js/pages/backoffice/on-ready.js');
|
||||
|
||||
|
||||
@@ -111,7 +111,7 @@ class LoginWebPageTest extends ItopDataTestCase
|
||||
$this->assertStringContainsString('<title>iTop login</title>', $sPageContent, 'if itop is configured to force login when no there is no delegated authentication endpoints list, then login should be required.');
|
||||
}
|
||||
|
||||
public function testWithoutDelegatedAuthenticationEndpointsListWithDefaultConfiguration()
|
||||
public function testWithoutDelegatedAuthenticationEndpointsListRequiresLoginByDefault()
|
||||
{
|
||||
$sPageContent = $this->CallItopUri(
|
||||
"pages/exec.php?exec_module=extension-without-delegated-authentication-endpoints-list&exec_page=src/Controller/File.php",
|
||||
@@ -120,7 +120,24 @@ class LoginWebPageTest extends ItopDataTestCase
|
||||
true
|
||||
);
|
||||
|
||||
$this->assertStringContainsString('Yo', $sPageContent, 'by default (until N°9343) if no delegated authentication endpoints list is defined, not logged in persons should access pages');
|
||||
$this->assertStringContainsString('<title>iTop login</title>', $sPageContent, 'by default, login should be required when no delegated authentication endpoints list is defined');
|
||||
}
|
||||
|
||||
public function testWithoutDelegatedAuthenticationEndpointsListWithCompatibilityOptOut()
|
||||
{
|
||||
@chmod($this->oConfig->GetLoadedFile(), 0770);
|
||||
$this->oConfig->Set('security.disable_exec_forced_login_for_all_enpoints', true, 'AnythingButEmptyOrUnknownValue');
|
||||
$this->oConfig->WriteToFile();
|
||||
@chmod($this->oConfig->GetLoadedFile(), 0444);
|
||||
|
||||
$sPageContent = $this->CallItopUri(
|
||||
"pages/exec.php?exec_module=extension-without-delegated-authentication-endpoints-list&exec_page=src/Controller/File.php",
|
||||
[],
|
||||
[],
|
||||
true
|
||||
);
|
||||
|
||||
$this->assertStringContainsString('Yo !', $sPageContent, 'the compatibility opt-out should allow anonymous access when no delegated authentication endpoints list is defined');
|
||||
}
|
||||
|
||||
public function testNotInDelegatedAuthenticationEndpointsList()
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* @copyright Copyright (C) 2010-2026 Combodo SAS
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
namespace Combodo\iTop\Test\UnitTest\DotMake\Dependencies\Composer\Tcpdf;
|
||||
|
||||
use Combodo\iTop\Test\UnitTest\ItopTestCase;
|
||||
|
||||
/**
|
||||
* @coversNothing
|
||||
*/
|
||||
class TcpdfUpdateFontsTest extends ItopTestCase
|
||||
{
|
||||
public function testThatDroidSansFallbackFilesAreCopiedToTcpdfFontsFolderAfterLibraryUpdate(): void
|
||||
{
|
||||
$sSourcePattern = APPROOT
|
||||
.'.make'.DIRECTORY_SEPARATOR.'dependencies'.DIRECTORY_SEPARATOR.'composer'.DIRECTORY_SEPARATOR.'tcpdf'.DIRECTORY_SEPARATOR.'droidsansfallback.*';
|
||||
$aSourceFiles = glob($sSourcePattern);
|
||||
$this->assertIsArray($aSourceFiles, 'Unable to read source TCPDF custom font files.');
|
||||
$this->assertNotEmpty($aSourceFiles, 'No source files found for pattern droidsansfallback.*');
|
||||
|
||||
foreach ($aSourceFiles as $sSourceFilePath) {
|
||||
$sFontFileName = basename($sSourceFilePath);
|
||||
$sDestinationFilePath = APPROOT
|
||||
.'lib'.DIRECTORY_SEPARATOR.'tecnickcom'.DIRECTORY_SEPARATOR.'tcpdf'.DIRECTORY_SEPARATOR.'fonts'.DIRECTORY_SEPARATOR.$sFontFileName;
|
||||
|
||||
$this->assertFileExists($sDestinationFilePath, "Missing copied font file: {$sFontFileName}");
|
||||
$this->assertSame(
|
||||
hash_file('sha256', $sSourceFilePath),
|
||||
hash_file('sha256', $sDestinationFilePath),
|
||||
"Copied font file content mismatch: {$sFontFileName}"
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -72,6 +72,30 @@ class utilsTest extends ItopTestCase
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider DoPostRequestAllowedProtocolsProvider
|
||||
*/
|
||||
public function testDoPostRequestRespectsAllowedProtocolsConfig(string $sAllowedProtocols, bool $bFileProtocolAllowed): void
|
||||
{
|
||||
// Config::Set changes the in-memory setting only; the test framework reloads config after this test class.
|
||||
utils::GetConfig()->Set('security.post_requests.allowed_protocols', $sAllowedProtocols);
|
||||
if (!$bFileProtocolAllowed) {
|
||||
$this->expectException(\Exception::class);
|
||||
$this->expectExceptionMessage('Problem opening URL');
|
||||
} else {
|
||||
$this->expectNotToPerformAssertions();
|
||||
}
|
||||
utils::DoPostRequest('file:///tmp', ['payload' => 'test']);
|
||||
}
|
||||
|
||||
public function DoPostRequestAllowedProtocolsProvider(): array
|
||||
{
|
||||
return [
|
||||
'file protocol is allowed' => ['file,http,https', true],
|
||||
'file protocol is not allowed' => ['http,https', false],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider realPathDataProvider
|
||||
* @covers utils::RealPath()
|
||||
|
||||
@@ -419,6 +419,7 @@ class UserLocalTest extends ItopDataTestCase
|
||||
$this->assertInstanceOf(ormLinkSet::class, $oProfilesSet);
|
||||
$this->assertEquals(0, $oProfilesSet->Count());
|
||||
MetaModel::GetConfig()->Set('security.hide_administrators', false);
|
||||
MetaModel::GetConfig()->Set('security.disable_joined_classes_filter', true);
|
||||
$oProfilesSet = $this->GetAdminUserProfileList();
|
||||
$this->assertIsObject($oProfilesSet);
|
||||
$this->assertInstanceOf(ormLinkSet::class, $oProfilesSet);
|
||||
|
||||
@@ -0,0 +1,60 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Combodo\iTop\Test\UnitTest\Module\ItopAttachment;
|
||||
|
||||
use Combodo\iTop\Test\UnitTest\ItopDataTestCase;
|
||||
|
||||
class AttachmentAjaxEndpointTest extends ItopDataTestCase
|
||||
{
|
||||
public const USE_TRANSACTION = false;
|
||||
private const AUTHENTICATION_PASSWORD = 'tagada-Secret,007';
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
parent::setUp();
|
||||
|
||||
$this->BackupConfiguration();
|
||||
$this->AddLoginModeAndSaveConfiguration('url');
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider AjaxEndpointAccessProvider
|
||||
*/
|
||||
public function testAjaxEndpointAccess(string $sProfile, int $iExpectedHttpCode): void
|
||||
{
|
||||
$sLogin = 'user-'.uniqid();
|
||||
$this->CreateUser($sLogin, self::$aURP_Profiles[$sProfile], self::AUTHENTICATION_PASSWORD);
|
||||
|
||||
$iHttpCode = $this->CallAttachmentEndpointAs($sLogin);
|
||||
|
||||
$this->assertSame($iExpectedHttpCode, $iHttpCode);
|
||||
}
|
||||
|
||||
public function AjaxEndpointAccessProvider(): array
|
||||
{
|
||||
return [
|
||||
'console user' => ['Service Desk Agent', 200],
|
||||
'portal user' => ['Portal user', 302], // redirect to portal
|
||||
];
|
||||
}
|
||||
|
||||
private function CallAttachmentEndpointAs(string $sLogin): int
|
||||
{
|
||||
$this->CallItopUri(
|
||||
'env-production/itop-attachments/ajax.itop-attachment.php?operation=add&'.http_build_query([
|
||||
'auth_user' => $sLogin,
|
||||
'auth_pwd' => self::AUTHENTICATION_PASSWORD,
|
||||
]),
|
||||
[],
|
||||
[
|
||||
CURLOPT_HTTPHEADER => ['X-Combodo-Ajax:1'],
|
||||
CURLOPT_POST => 0,
|
||||
],
|
||||
true
|
||||
);
|
||||
|
||||
return $this->aLastCurlGetInfo['http_code'];
|
||||
}
|
||||
}
|
||||
@@ -4,6 +4,7 @@ namespace Combodo\iTop\Test\UnitTest\Pages;
|
||||
|
||||
use Combodo\iTop\Test\UnitTest\ItopDataTestCase;
|
||||
use Dict;
|
||||
use ormDocument;
|
||||
use UserLocal;
|
||||
use UserRequest;
|
||||
|
||||
@@ -132,6 +133,47 @@ class AjaxRenderTest extends ItopDataTestCase
|
||||
return $this->AcquireLockAsUser(self::$sLogin, self::$iTicketId);
|
||||
}
|
||||
|
||||
public function testDisplayDocumentHasSandboxWhenConfigurationDoesNotDisableIt(): void
|
||||
{
|
||||
$sLogin = uniqid('AjaxRenderTest');
|
||||
$this->CreateContactlessUser($sLogin, self::$aURP_Profiles['Administrator'], self::AUTHENTICATION_PASSWORD);
|
||||
$iDocumentId = $this->GivenObjectInDB('DocumentFile', [
|
||||
'name' => 'AjaxRenderTest_'.uniqid(),
|
||||
'org_id' => $this->getTestOrgId(),
|
||||
'file' => new ormDocument('<svg xmlns="http://www.w3.org/2000/svg"></svg>', 'image/svg+xml', 'test.svg'),
|
||||
]);
|
||||
|
||||
$this->oiTopConfig->Set('security.disable_inline_documents_sandbox', false);
|
||||
$this->SaveItopConfFile();
|
||||
$sResponseHeaders = $this->GetDocumentResponseHeaders($sLogin, $iDocumentId);
|
||||
$this->assertStringContainsString(
|
||||
'sandbox',
|
||||
$sResponseHeaders
|
||||
);
|
||||
}
|
||||
|
||||
private function GetDocumentResponseHeaders(string $sLogin, int $iDocumentId): string
|
||||
{
|
||||
$sResponse = $this->CallItopUri(
|
||||
'pages/ajax.render.php?'.http_build_query([
|
||||
'operation' => 'display_document',
|
||||
'class' => 'DocumentFile',
|
||||
'id' => $iDocumentId,
|
||||
'field' => 'file',
|
||||
'auth_user' => $sLogin,
|
||||
'auth_pwd' => self::AUTHENTICATION_PASSWORD,
|
||||
]),
|
||||
[],
|
||||
[
|
||||
CURLOPT_HTTPHEADER => ['X-Combodo-Ajax:1'],
|
||||
CURLOPT_HEADER => true,
|
||||
CURLOPT_POST => 0,
|
||||
]
|
||||
);
|
||||
|
||||
return substr($sResponse, 0, $this->aLastCurlGetInfo['header_size']);
|
||||
}
|
||||
|
||||
// Helper method to create a user with a specific profile
|
||||
private function CreateUserWithProfile(int $iProfileId): UserLocal
|
||||
{
|
||||
|
||||
@@ -2,9 +2,13 @@
|
||||
|
||||
namespace Combodo\iTop\Test\UnitTest\Setup;
|
||||
|
||||
use AnalyzeInstallation;
|
||||
use CheckResult;
|
||||
use Combodo\iTop\Setup\FeatureRemoval\ModelReflectionSerializer;
|
||||
use Combodo\iTop\Test\UnitTest\ItopTestCase;
|
||||
use Config;
|
||||
use ModuleDiscovery;
|
||||
use WizardController;
|
||||
use SetupUtils;
|
||||
|
||||
/**
|
||||
@@ -28,6 +32,13 @@ class SetupUtilsTest extends ItopTestCase
|
||||
|
||||
$this->RequireOnceItopFile('setup/setuputils.class.inc.php');
|
||||
$this->RequireOnceItopFile('setup/setuppage.class.inc.php');
|
||||
$this->RequireOnceItopFile('setup/wizardcontroller.class.inc.php');
|
||||
}
|
||||
|
||||
protected function tearDown(): void
|
||||
{
|
||||
parent::tearDown();
|
||||
ModuleDiscovery::ResetCache();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -219,6 +230,30 @@ OUTPUT;
|
||||
$this->ValidateCheckResults($expected, $aRes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Bug N°10045
|
||||
*/
|
||||
public function testAnalyzeInstallationDoesNotAutomaticallySetModulesInProductionModulesVisibilityToFalse()
|
||||
{
|
||||
$this->RequireOnceItopFile('setup/moduleinstallation/AnalyzeInstallation.php');
|
||||
$this->SetNonPublicProperty(AnalyzeInstallation::GetInstance(), 'aAvailableModules', null);
|
||||
|
||||
$sRemoteEnv = 'production-temp';
|
||||
$sExtraDir = \utils::GetDataPath().$sRemoteEnv.'-modules/';
|
||||
$sExtraModuleName = 'extra-module';
|
||||
|
||||
$this->createModule($sExtraDir, $sExtraModuleName, '1.0.0');
|
||||
|
||||
$oWizard = new WizardController('WizStepWelcome');
|
||||
$oWizard->SetParameter('source_dir', APPROOT.'datamodels/2.x');
|
||||
$oWizard->SetParameter('remote_env', $sRemoteEnv);
|
||||
|
||||
$aModules = SetupUtils::AnalyzeInstallation($oWizard);
|
||||
|
||||
$this->assertContains($sExtraModuleName, array_keys($aModules), 'Module discovery should have found the extra module');
|
||||
$this->assertTrue($aModules[$sExtraModuleName]['visible'], 'AnalyzeInstallation should not have automatically set the extra module visibility to false');
|
||||
}
|
||||
|
||||
private function ValidateCheckResults(array $expected, array $aActualCheckResults)
|
||||
{
|
||||
$aActual = [];
|
||||
@@ -232,4 +267,37 @@ OUTPUT;
|
||||
self::assertEquals($expected, $aActual);
|
||||
}
|
||||
|
||||
protected function createModule($sDirectory, $sModuleName, $sModuleVersion, $bMandatory = false, $bVisible = true)
|
||||
{
|
||||
$sModuleDir = $sDirectory.'/'.$sModuleName;
|
||||
SetupUtils::builddir($sModuleDir);
|
||||
$this->aFileToClean[] = $sDirectory;
|
||||
|
||||
$sModuleFileName = $sModuleDir.'/module.'.$sModuleName.'.php';
|
||||
|
||||
$sMandatory = var_export($bMandatory, true);
|
||||
$sVisible = var_export($bVisible, true);
|
||||
file_put_contents(
|
||||
$sModuleFileName,
|
||||
<<<PHP
|
||||
<?php
|
||||
SetupWebPage::AddModule(
|
||||
__FILE__,
|
||||
"$sModuleName/$sModuleVersion",
|
||||
[
|
||||
'label' => "$sModuleName",
|
||||
'dependencies' => [],
|
||||
'mandatory' => $sMandatory,
|
||||
'visible' => $sVisible,
|
||||
'datamodel' => [],
|
||||
'data.struct' => [],
|
||||
'data.sample' => [],
|
||||
'doc.manual_setup' => '',
|
||||
'doc.more_information' => '',
|
||||
]
|
||||
);
|
||||
PHP
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user