Merge remote-tracking branch 'origin/support/3.0' into develop

This commit is contained in:
Eric Espie
2022-11-16 13:57:07 +01:00
9 changed files with 115 additions and 47 deletions

View File

@@ -141,7 +141,7 @@ class DBObjectSet implements iDBObjectSetIterator
{
$sRet = '';
$this->Rewind();
$sRet .= "Set (".$this->m_oFilter->ToOQL().")<br/>\n";
$sRet .= "Set (".$this->m_oFilter->ToOQL(true).")<br/>\n";
$sRet .= "Query: <pre style=\"font-size: smaller; display:inline;\">".$this->m_oFilter->MakeSelectQuery().")</pre>\n";
$sRet .= $this->Count()." records<br/>\n";
@@ -154,6 +154,7 @@ class DBObjectSet implements iDBObjectSetIterator
}
$sRet .= "</ul>\n";
}
$this->Rewind();
return $sRet;
}

View File

@@ -1717,6 +1717,6 @@ abstract class DBSearch
*/
public function __toString()
{
return $this->ToOQL();
return $this->ToOQL(true);
}
}

View File

@@ -575,7 +575,7 @@ class CoreServices implements iRestServiceProvider
$oObject = $oElement->GetProperty('object');
if ($oObject)
{
if ($bEnableRedundancy)
if ($bEnableRedundancy && $sDirection == 'down')
{
// Add only the "reached" objects
if ($oElement->GetProperty('is_reached'))

View File

@@ -1103,7 +1103,7 @@ EOF
$aParams = utils::ReadParam('params', '', false, 'raw_data');
$sDashletClass = $aParams['attr_dashlet_class'];
$sDashletType = $aParams['attr_dashlet_type'];
$sDashletId = $aParams['attr_dashlet_id'];
$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'
if (is_subclass_of($sDashletClass, 'Dashlet')) {

View File

@@ -1,33 +1,55 @@
<?php
namespace Combodo\iTop\Test\UnitTest;
use AppBundle\Twig\AppExtension;
use Combodo\iTop\Application\TwigBase\Twig\TwigHelper;
use Combodo\iTop\Test\UnitTest\ItopTestCase;
use Combodo\iTop\Portal\Twig\AppExtension;
use Twig_Environment;
use Twig_Loader_Array;
class TwigTest extends ItopTestCase
class TwigTest extends ItopDataTestCase
{
protected function setUp(): void
{
parent::setUp();
require_once __DIR__.'/../../core/config.class.inc.php';
}
/**
* Test the fix for ticket N°4384
*
* @dataProvider testTemplateProvider
* @dataProvider TemplateProvider
*
*/
public function testTemplate($sFileName, $expected)
public function testTemplate($sFileName, $sExpected)
{
$oTwig = TwigHelper::GetTwigEnvironment( dirname(__FILE__));
$sId = 'TestTwig';
$oAppExtension = new AppExtension();
$sHtml = $oTwig->render($sFileName.'.twig');
$this->assertSame($sHtml, $expected);
// Creating sandbox twig env. to load and test the custom form template
$oTwig = new Twig_Environment(new Twig_Loader_Array([$sId => $sFileName]));
// Manually registering filters and functions as we didn't find how to do it automatically
$aFilters = $oAppExtension->getFilters();
foreach ($aFilters as $oFilter)
{
$oTwig->addFilter($oFilter);
}
$aFunctions = $oAppExtension->getFunctions();
foreach ($aFunctions as $oFunction)
{
$oTwig->addFunction($oFunction);
}
public static function testTemplateProvider()
$sHtml = $oTwig->render($sId, ['AttackerURL' => 'file://'.__DIR__.'/attacker']);
$this->assertEquals($sExpected, $sHtml);
}
public static function TemplateProvider()
{
$aReturn = array();
$aReturn['filter_system'] = [
'sFileName' => 'test.html',
'expected' =>file_get_contents(dirname(__FILE__).'/test.html'),
'sFileName' => file_get_contents(__DIR__.'/test.html.twig'),
'expected' => file_get_contents(__DIR__.'/test.html'),
];
return $aReturn;

View File

@@ -0,0 +1 @@
!!! BACKDOOR !!!

View File

@@ -1,12 +1,33 @@
<div>
User Name
</div>
<div>
</div><div>
['id']|filter('system')
</div>
[&quot;id&quot;]
</div>
<div>
<div>
['touch+/tmp/test+']|filter('system')|join(',')
</div>
[&quot;touch+\/tmp\/test+&quot;]
</div>
<div>
<div>
set sizes = [34, 36, 38, 40, 42]
sizes|filter(v => v > 38)|join(', ')
</div>
40, 42
</div>
<div>
app.request.server.all|join(',')
</div><div>
self
</div><div>
[0]|reduce('system','echo')
</div>
[&quot;echo&quot;]
<div>
['echo']|map('system')|join
</div>
[&quot;echo&quot;]
<div>
['echo',1]|sort('system')|join
</div>
echo1
POST /subscribe?0=cat+/etc/passwd HTTP/1.1
email=""@attacker.tld

View File

@@ -1,13 +1,41 @@
<div>
{% spaceless %}
<div>
{{ 'UI:Login:UserNamePrompt'|dict_s }}
</div>
<div>
{{['id']|filter('system')}}
</div>
<div>
{{['touch+/tmp/test+']|filter('system')|join(',')}}
</div>
<div>
{% set sizes = [34, 36, 38, 40, 42] %}
</div>
<div>
['id']|filter('system')
</div>
{{ ['id']|filter('system') }}
<div>
['touch+/tmp/test+']|filter('system')|join(',')
</div>
{{ ['touch+/tmp/test+']|filter('system')|join(',') }}
<div>
set sizes = [34, 36, 38, 40, 42]
sizes|filter(v => v > 38)|join(', ')
</div>
{% set sizes = [34, 36, 38, 40, 42] %}
{{ sizes|filter(v => v > 38)|join(', ') }}
</div>
<div>
app.request.server.all|join(',')
</div>
{{ app.request.server.all|join(',') }} {# needs syfony #}
<div>
self
</div>
{{ self }} {# ??? not sure #}
<div>
[0]|reduce('system','echo')
</div>
{{ [0]|reduce('system','echo') }}
<div>
['echo']|map('system')|join
</div>
{{ ['echo']|map('system')|join }}
<div>
['echo',1]|sort('system')|join
</div>
{{ ['echo',1]|sort('system')|join }}
POST /subscribe?0=cat+/etc/passwd HTTP/1.1
email="{{ app.request.query.filter(0,0,1024,{'options':'system'}) }}"@attacker.tld
{% endspaceless %}

View File

@@ -14,7 +14,6 @@ use Combodo\iTop\Application\UI\Base\Component\Input\Select\SelectOptionUIBlockF
use Combodo\iTop\Application\UI\Base\Component\Input\SelectUIBlockFactory;
use Combodo\iTop\Application\UI\Base\Component\Input\TextArea;
use Combodo\iTop\Application\UI\Base\Component\Panel\PanelUIBlockFactory;
use Combodo\iTop\Application\UI\Base\Component\Title\TitleUIBlockFactory;
use Combodo\iTop\Application\UI\Base\Layout\UIContentBlockUIBlockFactory;
if (!defined('__DIR__')) {
@@ -27,19 +26,15 @@ require_once(APPROOT.'/core/bulkexport.class.inc.php');
require_once(APPROOT.'/application/startup.inc.php');
const EXIT_CODE_ERROR = -1;
const EXIT_CODE_FATAL = -2;
function ReportErrorAndExit($sErrorMessage)
{
if (utils::IsModeCLI())
{
$oP = new CLIPage("iTop - Export");
$oP->p('ERROR: '.$sErrorMessage);
$oP->p('ERROR: '.utils::HtmlEntities($sErrorMessage));
$oP->output();
exit(EXIT_CODE_ERROR);
}
@@ -47,7 +42,7 @@ function ReportErrorAndExit($sErrorMessage)
{
$oP = new WebPage("iTop - Export");
$oP->add_xframe_options();
$oP->p('ERROR: '.$sErrorMessage);
$oP->p('ERROR: '.utils::HtmlEntities($sErrorMessage));
$oP->output();
exit(EXIT_CODE_ERROR);
}