Merge branch 'support/3.2' into develop

# Conflicts:
#	core/simplecrypt.class.inc.php
#	tests/php-unit-tests/unitary-tests/core/SympleCryptTest.php
This commit is contained in:
Stephen Abello
2025-11-06 10:27:03 +01:00
8 changed files with 122 additions and 38 deletions

View File

@@ -118,6 +118,7 @@ class SimpleCrypt
*/ */
function Encrypt($key, $sString) function Encrypt($key, $sString)
{ {
return $this->oEngine->Encrypt($key,$sString); return $this->oEngine->Encrypt($key,$sString);
} }
@@ -130,13 +131,11 @@ class SimpleCrypt
*/ */
function Decrypt($key, $string) function Decrypt($key, $string)
{ {
if (is_null($string) || strlen($string) == 0) { if (is_null($string) || strlen($string) == 0) {
IssueLog::Warning("Cannot decrypt empty/null value"); IssueLog::Warning("Cannot decrypt empty/null value");
return $string;
return $string; }
} return $this->oEngine->Decrypt($key,$string);
return $this->oEngine->Decrypt($key, $string);
} }
/** /**
@@ -240,6 +239,10 @@ class SimpleCryptSimpleEngine implements CryptEngine
public function Decrypt($key, $encrypted_data) public function Decrypt($key, $encrypted_data)
{ {
if (is_null($encrypted_data) || strlen($encrypted_data) == 0) {
IssueLog::Warning("Cannot decrypt empty/null value");
return $encrypted_data;
}
$result = ''; $result = '';
for($i=1; $i<=strlen($encrypted_data); $i++) for($i=1; $i<=strlen($encrypted_data); $i++)
{ {
@@ -336,6 +339,10 @@ class SimpleCryptSodiumEngine implements CryptEngine
public function Decrypt($key, $encrypted_data) public function Decrypt($key, $encrypted_data)
{ {
if (is_null($encrypted_data) || strlen($encrypted_data) == 0) {
IssueLog::Warning("Cannot decrypt empty/null value");
return $encrypted_data;
}
$key = hex2bin($key); $key = hex2bin($key);
$encrypted_data = base64_decode($encrypted_data); $encrypted_data = base64_decode($encrypted_data);
$nonce = mb_substr($encrypted_data, 0, SODIUM_CRYPTO_SECRETBOX_NONCEBYTES, '8bit'); $nonce = mb_substr($encrypted_data, 0, SODIUM_CRYPTO_SECRETBOX_NONCEBYTES, '8bit');
@@ -368,6 +375,10 @@ class SimpleCryptOpenSSLEngine implements CryptEngine
public function Decrypt($key, $encrypted_data) public function Decrypt($key, $encrypted_data)
{ {
if (is_null($encrypted_data) || strlen($encrypted_data) == 0) {
IssueLog::Warning("Cannot decrypt empty/null value");
return $encrypted_data;
}
$key = hex2bin($key); $key = hex2bin($key);
$iv = mb_substr($encrypted_data, 0, openssl_cipher_iv_length("AES-256-CBC"), '8bit'); $iv = mb_substr($encrypted_data, 0, openssl_cipher_iv_length("AES-256-CBC"), '8bit');
$encrypted_data = mb_substr($encrypted_data, openssl_cipher_iv_length("AES-256-CBC"), null, '8bit'); $encrypted_data = mb_substr($encrypted_data, openssl_cipher_iv_length("AES-256-CBC"), null, '8bit');
@@ -417,6 +428,10 @@ class SimpleCryptOpenSSLMcryptCompatibilityEngine implements CryptEngine
public function Decrypt($key, $encrypted_data) public function Decrypt($key, $encrypted_data)
{ {
if (is_null($encrypted_data) || strlen($encrypted_data) == 0) {
IssueLog::Warning("Cannot decrypt empty/null value");
return $encrypted_data;
}
$key = SimpleCryptOpenSSLMcryptCompatibilityEngine::MakeOpenSSLBlowfishKey($key); $key = SimpleCryptOpenSSLMcryptCompatibilityEngine::MakeOpenSSLBlowfishKey($key);
$iv = mb_substr($encrypted_data, 0, openssl_cipher_iv_length("BF-CBC"), '8bit'); $iv = mb_substr($encrypted_data, 0, openssl_cipher_iv_length("BF-CBC"), '8bit');
$encrypted_data = mb_substr($encrypted_data, openssl_cipher_iv_length("BF-CBC"), null, '8bit'); $encrypted_data = mb_substr($encrypted_data, openssl_cipher_iv_length("BF-CBC"), null, '8bit');

View File

@@ -81,9 +81,10 @@ $ibo-field--enable-bulk--checkbox--margin-left: $ibo-spacing-300 !default;
} }
} }
/*N°6543 - We need the rule to keep text inside the column when width is defined */ /* N°6543 - We need the rule to keep text inside the column when width is defined */
&[data-attribute-type="AttributeHTML"], &[data-attribute-type="AttributeHTML"],
&[data-attribute-type="AttributeText"] { &[data-attribute-type="AttributeText"],
&[data-attribute-type="AttributeLongText"] {
&[data-attribute-flag-read-only="true"] { &[data-attribute-flag-read-only="true"] {
display: grid; display: grid;

View File

@@ -127,7 +127,8 @@ $ibo-datatable--selected-result-count--padding-left: 0.1em !default;
} }
/* N°6543 - We need the rule to keep text inside the column when width is defined */ /* N°6543 - We need the rule to keep text inside the column when width is defined */
> [data-attribute-type="AttributeHTML"], > [data-attribute-type="AttributeHTML"],
> [data-attribute-type="AttributeText"] { > [data-attribute-type="AttributeText"],
> [data-attribute-type="AttributeLongText"] {
max-width: 100%; max-width: 100%;
overflow: auto; overflow: auto;
} }

View File

@@ -202,6 +202,11 @@ $ibo-input-select--autocomplete-item-image--border: 1px solid $ibo-color-grey-60
overflow-y: auto; overflow-y: auto;
} }
// N°7982 Default selectize stylesheet override
.selectize-dropdown-content{
max-height: $ibo-input-select-selectize--dropdown--max-height;
}
.selectize-dropdown.ui-menu .ui-state-active { .selectize-dropdown.ui-menu .ui-state-active {
margin: unset; margin: unset;
background-color: $ibo-input-select-selectize--item--active--background-color; background-color: $ibo-input-select-selectize--item--active--background-color;

View File

@@ -15,9 +15,10 @@ $ibo-activity-panel--padding-y: $ibo-spacing-0 !default;
/* - Header */ /* - Header */
$ibo-activity-panel--header--background-color: $ibo-color-grey-100 !default; $ibo-activity-panel--header--background-color: $ibo-color-grey-100 !default;
$ibo-activity-panel--togglers--color: $ibo-color-grey-600 !default; $ibo-activity-panel--actions--color: $ibo-color-grey-600 !default;
$ibo-activity-panel--togglers--on-hover--color: $ibo-color-grey-800 !default; $ibo-activity-panel--actions--on-hover--color: $ibo-color-grey-800 !default;
$ibo-activity-panel--togglers--elements-spacing: 0.75rem !default; $ibo-activity-panel--actions--elements-spacing: 0.75rem !default;
$ibo-activity-panel--actions-padding-right: $ibo-activity-panel--padding-x !default;
/* - Tabs togglers*/ /* - Tabs togglers*/
$ibo-activity-panel--tabs-togglers--padding-x: $ibo-activity-panel--padding-x * 3 !default; /* We need to increase this so the size toggler which will be set in abs. pos. can overlap it nicely */ $ibo-activity-panel--tabs-togglers--padding-x: $ibo-activity-panel--padding-x * 3 !default; /* We need to increase this so the size toggler which will be set in abs. pos. can overlap it nicely */
@@ -152,35 +153,45 @@ $ibo-activity-panel--open-icon--margin-left: 0.75rem !default;
background-color: $ibo-activity-panel--header--background-color; background-color: $ibo-activity-panel--header--background-color;
/* Remove hyperlinks default color */ /* Remove hyperlinks default color */
> .ibo-activity-panel--tabs-togglers a{ .ibo-activity-panel--togglers a{
color: $ibo-activity-panel--tab-toolbar--text-color; color: $ibo-activity-panel--tab-toolbar--text-color;
} }
} }
/* Size/display togglers */ /* All toggles container */
.ibo-activity-panel--togglers { .ibo-activity-panel--togglers {
position: absolute; display: flex;
right: $ibo-activity-panel--padding-x; align-items: center;
top: 0; }
bottom: 0;
@extend %ibo-fully-centered-content; /* Size/display togglers */
color: $ibo-activity-panel--togglers--color; .ibo-activity-panel--actions {
display: flex;
align-items: center;
flex-grow: 0;
position: sticky;
padding-right: $ibo-activity-panel--actions-padding-right;
background-color: $ibo-activity-panel--header--background-color;
color: $ibo-activity-panel--actions--color;
&:hover { &:hover {
color: $ibo-activity-panel--togglers--on-hover--color; color: $ibo-activity-panel--actions--on-hover--color;
} }
> *:not(:first-child) { > *:not(:first-child) {
margin-left: $ibo-activity-panel--togglers--elements-spacing; margin-left: $ibo-activity-panel--actions--elements-spacing;
} }
} }
/* Tabs togglers */ /* Tabs togglers */
.ibo-activity-panel--tabs-togglers{ .ibo-activity-panel--tabs-togglers{
position: relative; /* For size toggler */ display: flex;
align-items: center;
justify-content: safe center;
flex-grow: 1;
padding-left: $ibo-activity-panel--tabs-togglers--padding-x; padding-left: $ibo-activity-panel--tabs-togglers--padding-x;
padding-right: $ibo-activity-panel--tabs-togglers--padding-x; overflow-x: auto;
@extend %ibo-fully-centered-content;
} }
.ibo-activity-panel--tab-toggler{ .ibo-activity-panel--tab-toggler{
&.ibo-is-active{ &.ibo-is-active{

View File

@@ -619,11 +619,17 @@ $(function()
_InitializeCurrentTab : function(){ _InitializeCurrentTab : function(){
const sTabId = $.bbq.getState(this.element.attr('id'), true); const sTabId = $.bbq.getState(this.element.attr('id'), true);
if(sTabId !== undefined){ if(sTabId !== undefined){
let oTabTogglerElem = null;
if(sTabId.startsWith("caselog-")){ if(sTabId.startsWith("caselog-")){
this._GetTabTogglerFromCaseLogAttCode(sTabId.replace("caselog-", "")).find(this.js_selectors.tab_title).trigger('click') oTabTogglerElem = this._GetTabTogglerFromCaseLogAttCode(sTabId.replace("caselog-", "")).find(this.js_selectors.tab_title).trigger('click')
} }
else if(sTabId === "activity"){ else if(sTabId === "activity"){
this.element.find(this.js_selectors.tab_toggler + '[data-tab-type="activity"]').find(this.js_selectors.tab_title).trigger('click') oTabTogglerElem = this.element.find(this.js_selectors.tab_toggler + '[data-tab-type="activity"]').find(this.js_selectors.tab_title).trigger('click')
}
// Scroll to the tab toggler if found
if(oTabTogglerElem !== null){
oTabTogglerElem[0].scrollIntoView();
} }
} }
}, },

View File

@@ -5,7 +5,8 @@
data-object-id="{{ oUIBlock.GetObjectId() }}" data-object-id="{{ oUIBlock.GetObjectId() }}"
data-object-mode="{{ oUIBlock.GetObjectMode() }}"> data-object-mode="{{ oUIBlock.GetObjectMode() }}">
<div class="ibo-activity-panel--header" data-role="ibo-activity-panel--header"> <div class="ibo-activity-panel--header" data-role="ibo-activity-panel--header">
<div class="ibo-activity-panel--tabs-togglers" data-role="ibo-activity-panel--tabs-togglers"> <div class="ibo-activity-panel--togglers" data-role="ibo-activity-panel--togglers">
<div class="ibo-activity-panel--tabs-togglers" data-role="ibo-activity-panel--tabs-togglers">
{% for sCaseLogAttCode, aCaseLogData in oUIBlock.GetCaseLogTabs() %} {% for sCaseLogAttCode, aCaseLogData in oUIBlock.GetCaseLogTabs() %}
{% set sExtraCSSClass = (loop.index == 1) ? 'ibo-is-active' : '' %} {% set sExtraCSSClass = (loop.index == 1) ? 'ibo-is-active' : '' %}
<div class="ibo-activity-panel--tab-toggler ibo-activity-panel--tab-toggler-for-caselog ibo-activity-panel--tab-toggler-for-caselog-{{ loop.index }} {{ sExtraCSSClass }}" <div class="ibo-activity-panel--tab-toggler ibo-activity-panel--tab-toggler-for-caselog ibo-activity-panel--tab-toggler-for-caselog-{{ loop.index }} {{ sExtraCSSClass }}"
@@ -34,7 +35,8 @@
<span class="ibo-activity-panel--tab-title-text" title="{{ 'UI:Layout:ActivityPanel:Tab:Activity:Title'|dict_s }}">{{ 'UI:Layout:ActivityPanel:Tab:Activity:Title'|dict_s }}</span> <span class="ibo-activity-panel--tab-title-text" title="{{ 'UI:Layout:ActivityPanel:Tab:Activity:Title'|dict_s }}">{{ 'UI:Layout:ActivityPanel:Tab:Activity:Title'|dict_s }}</span>
</a> </a>
</div> </div>
<div class="ibo-activity-panel--togglers" data-role="ibo-activity-panel--togglers"> </div>
<div class="ibo-activity-panel--actions" data-role="ibo-activity-panel--actions">
<a href="#" class="ibo-activity-panel--expand-icon" <a href="#" class="ibo-activity-panel--expand-icon"
data-role="ibo-activity-panel--expand-icon" data-role="ibo-activity-panel--expand-icon"
data-tooltip-content="{{ 'UI:Layout:ActivityPanel:SizeToggler:Expand:Tooltip'|dict_s }}" data-tooltip-content="{{ 'UI:Layout:ActivityPanel:SizeToggler:Expand:Tooltip'|dict_s }}"

View File

@@ -14,23 +14,66 @@ use SodiumException;
*/ */
class SympleCryptTest extends ItopDataTestCase class SympleCryptTest extends ItopDataTestCase
{ {
public function testDecryptWithNullValue() public function DecryptClassProvider()
{
$aClassProvider = ['SimpleCrypt'=>['SimpleCrypt'],
'SimpleCryptSimpleEngine'=>['SimpleCryptSimpleEngine']];
if(function_exists('sodium_crypto_secretbox_open')){
$aClassProvider['SimpleCryptSodiumEngine'] = ['SimpleCryptSodiumEngine'] ;
}
if(function_exists('openssl_decrypt')){
$aClassProvider['SimpleCryptOpenSSLEngine'] = ['SimpleCryptOpenSSLEngine'];
$aClassProvider['SimpleCryptOpenSSLMcryptCompatibilityEngine'] = ['SimpleCryptOpenSSLMcryptCompatibilityEngine'];
}
return$aClassProvider;
}
/**
* @param $sClass
* @dataProvider DecryptClassProvider
**/
public function testDecryptWithNullValue($sClass)
{ {
$oSimpleCrypt = new \SimpleCrypt("Sodium"); $oSimpleCrypt = new $sClass();
$this->assertEquals(null, $oSimpleCrypt->Decrypt("dd", null)); $this->assertEquals(null, $oSimpleCrypt->Decrypt("dd", null));
} }
public function testDecryptWithEmptyValue() /**
* @param $sClass
* @dataProvider DecryptClassProvider
**/
public function testDecryptWithEmptyValue($sClass)
{ {
$oSimpleCrypt = new \SimpleCrypt("Sodium"); $oSimpleCrypt = new $sClass();
$this->assertEquals('', $oSimpleCrypt->Decrypt("dd", "")); $this->assertEquals('', $oSimpleCrypt->Decrypt("dd", ""));
} }
public function testDecrypNonDecryptableValue() public function DecryptClassWithNonDecryptableValueProvider()
{
$aClassProvider = ['SimpleCrypt'=>['SimpleCrypt', '** decryption error **'],
// 'SimpleCryptSimpleEngine'=>['SimpleCryptSimpleEngine', ' ']
];
if(function_exists('sodium_crypto_secretbox_open')){
$aClassProvider['SimpleCryptSodiumEngine'] = ['SimpleCryptSodiumEngine', '', 'SodiumException'] ;
}
if(function_exists('openssl_decrypt')){
$aClassProvider['SimpleCryptOpenSSLEngine'] = ['SimpleCryptOpenSSLEngine', '** decryption error **'];
$aClassProvider['SimpleCryptOpenSSLMcryptCompatibilityEngine'] = ['SimpleCryptOpenSSLMcryptCompatibilityEngine', '** decryption error **'];
}
return$aClassProvider;
}
/**
* @param $sClass
* @param $sExpectedValue
* @dataProvider DecryptClassWithNonDecryptableValueProvider
**/
public function testDecrypWithNonDecryptableValue($sClass, $sExpectedValue = '', $sExpectedException = null)
{ {
$this->expectException(SodiumException::class); if($sExpectedException !== null) {
$oSimpleCrypt = new \SimpleCrypt("Sodium"); $this->expectException($sExpectedException);
$this->assertEquals('', $oSimpleCrypt->Decrypt("dd", "gabuzomeu")); }
$oSimpleCrypt = new $sClass();
$result=$oSimpleCrypt->Decrypt("dd", "gabuzomeuuofteod");
$this->assertEquals($sExpectedValue, $result,'');
} }
} }