forked from Wavyzz/dolibarr
Merge branch 'develop' of git@github.com:Dolibarr/dolibarr.git into
develop
This commit is contained in:
50
ChangeLog
50
ChangeLog
@@ -25,7 +25,55 @@ The following changes may create regressions for some external modules, but were
|
||||
* Properties ->date_update and ->date_modification were merged into date_modification.
|
||||
|
||||
|
||||
***** ChangeLog for 19.0.0 compared to 18.0 *****
|
||||
|
||||
***** ChangeLog for 19.0.1 compared to 19.0.0 *****
|
||||
|
||||
FIX: 16.0 - parent company gets emptied when updating a third party from the card in edit mode (#28269)
|
||||
FIX: #22948
|
||||
FIX: #28205
|
||||
FIX: 28251 Fixing subpermission name on api_multicurrencies.class.php (#28252)
|
||||
FIX: #28369
|
||||
FIX: #28429
|
||||
FIX: #28491 (#28522)
|
||||
FIX: #28518 (#28520)
|
||||
FIX: #28533 Mo::deleteLine removes the "main" MoLine if consumed line is delete (#28535)
|
||||
FIX: #28564
|
||||
FIX: Adding the dependencies list feature for extrafields "select" (#28549)
|
||||
FIX: Add new hidden conf "DISABLE_QTY_OVERWRITTEN" (#28523)
|
||||
FIX: avoid error "Column 'entity' in where clause is ambiguous" (#28270)
|
||||
FIX: avoid Unknown column 'pfp.ref_fourn' (#28145)
|
||||
FIX: avoid warning "error parsing attribute name in Entity" (#28543)
|
||||
FIX: Bad column for total in bom list
|
||||
FIX: Bad condition on button back to draft on recruitment job.
|
||||
FIX: Bad CRLF when sending text only content. Fix dol_htmlwithnojs()
|
||||
FIX: Bad picto on list of permission of a user when user not admin
|
||||
FIX: bad timezone for the start/end date of an event
|
||||
FIX: Better test on validity of compute field syntax with parenthesis
|
||||
FIX: close #28279
|
||||
FIX: disabled pito of menu must be greyed.
|
||||
FIX: Don't display column when it's out of date (#28271)
|
||||
FIX: duplicate with lines: 414-416 (#28358)
|
||||
FIX: Error When cloning fourn price no default value for tva_tx (#28368)
|
||||
FIX: migration missing 2 columns in llx_resource and 1 in llx_user
|
||||
FIX: missing trans
|
||||
FIX: notification module: for supplier orders (any of the 3 triggers), user can choose an e-mail template in conf, but the conf is not used when sending the notification (#28216)
|
||||
FIX: Not truncate the multicurrency rate shown on cards (even if the global MAIN_MAX_DECIMALS_SHOWN is set to 0) (#28211)
|
||||
FIX: Payment on customer invoice - Remove accountid in url if empty for apply default value (#28156)
|
||||
FIX: Pb in redirect of a website page in USEDOLIBARRSERVER mode
|
||||
FIX: PHP Warning: Undefined variable $lib (#28342)
|
||||
FIX: Picto for mime
|
||||
FIX: position of field in list of field in shipment list
|
||||
FIX: postgresql error (#28542)
|
||||
FIX: quote in sql request
|
||||
FIX: Responsive on admin project
|
||||
FIX: Shipment closing action has wrong value (#28174)
|
||||
FIX: some tooltips has disappeared on invoice action button
|
||||
FIX: Special code is now transmitted by args only in order supplier (#28546)
|
||||
FIX: subscription must be editable when accounting isn't reconciled (#28469)
|
||||
FIX: Value of field int = 0 from modulebuilder must not be set to null
|
||||
|
||||
|
||||
***** ChangeLog for 19.0.0 compared to 18.0.0 *****
|
||||
|
||||
For users:
|
||||
----------
|
||||
|
||||
@@ -219,7 +219,7 @@ if (empty($reshook)) {
|
||||
if ($action == 'setassujtva' && $user->hasRight('societe', 'creer')) {
|
||||
$object->fetch($id);
|
||||
$object->tva_assuj = GETPOSTINT('assujtva_value');
|
||||
$result = $object->update($object->id);
|
||||
$result = $object->update($object->id, $user);
|
||||
if ($result < 0) {
|
||||
setEventMessages($object->error, $object->errors, 'errors');
|
||||
}
|
||||
|
||||
@@ -102,7 +102,7 @@ $arrayfields = array(
|
||||
'cs.fk_type' =>array('label'=>"Type", 'checked'=>1, 'position'=>30),
|
||||
'cs.date_ech' =>array('label'=>"Date", 'checked'=>1, 'position'=>40),
|
||||
'cs.periode' =>array('label'=>"PeriodEndDate", 'checked'=>1, 'position'=>50),
|
||||
'p.ref' =>array('label'=>"ProjectRef", 'checked'=>1, 'position'=>60, 'enable'=>(isModEnabled('project'))),
|
||||
'p.ref' =>array('label'=>"ProjectRef", 'checked'=>1, 'position'=>60, 'enabled'=>(isModEnabled('project'))),
|
||||
'cs.fk_user' =>array('label'=>"Employee", 'checked'=>1, 'position'=>70),
|
||||
'cs.fk_mode_reglement' =>array('checked'=>-1, 'position'=>80, 'label'=>"DefaultPaymentMode"),
|
||||
'cs.amount' =>array('label'=>"Amount", 'checked'=>1, 'position'=>100),
|
||||
|
||||
@@ -1149,7 +1149,7 @@ abstract class CommonInvoice extends CommonObject
|
||||
$sql .= " AND fk_facture = ".((int) $this->id); // Add a protection to not pay another invoice than current one
|
||||
}
|
||||
if ($type != 'direct-debit') {
|
||||
if ($$sourcetype == 'salary') {
|
||||
if ($sourcetype == 'salary') {
|
||||
$sql .= " AND fk_salary = ".((int) $this->id); // Add a protection to not pay another salary than current one
|
||||
} else {
|
||||
$sql .= " AND fk_facture_fourn = ".((int) $this->id); // Add a protection to not pay another invoice than current one
|
||||
|
||||
@@ -9853,18 +9853,23 @@ function dol_eval($s, $returnvalue = 0, $hideerrors = 1, $onlysimplestring = '1'
|
||||
return '';
|
||||
}
|
||||
}
|
||||
$scheck = preg_replace('/->[a-zA-Z0-9_]+\(/', '->__METHOD__', $s); // accept parenthesis in '...->method(...'
|
||||
$savescheck = '';
|
||||
$scheck = $s;
|
||||
while ($scheck && $savescheck != $scheck) {
|
||||
$savescheck = $scheck;
|
||||
$scheck = preg_replace('/->[a-zA-Z0-9_]+\(/', '->__METHOD__', $scheck); // accept parenthesis in '...->method(...'
|
||||
$scheck = preg_replace('/^\(/', '__PARENTHESIS__ ', $scheck); // accept parenthesis in '(...'. Must replace with __PARENTHESIS__ with a space after to allow following substitutions
|
||||
$scheck = preg_replace('/\s\(/', '__PARENTHESIS__ ', $scheck); // accept parenthesis in '... ('. Must replace with __PARENTHESIS__ with a space after to allow following substitutions
|
||||
$scheck = preg_replace('/^!?[a-zA-Z0-9_]+\(/', '__FUNCTION__', $scheck); // accept parenthesis in 'function(' and '!function('
|
||||
$scheck = preg_replace('/\s!?[a-zA-Z0-9_]+\(/', '__FUNCTION__', $scheck); // accept parenthesis in '... function(' and '... !function('
|
||||
$scheck = preg_replace('/(\^|\')\(/', '__REGEXSTART__', $scheck); // To allow preg_match('/^(aaa|bbb)/'... or isStringVarMatching('leftmenu', '(aaa|bbb)')
|
||||
}
|
||||
//print 'scheck='.$scheck." : ".strpos($scheck, '(')."<br>\n";
|
||||
if (strpos($scheck, '(') !== false) {
|
||||
if ($returnvalue) {
|
||||
return 'Bad string syntax to evaluate (found call of a function or method without using direct name): '.$s;
|
||||
return 'Bad string syntax to evaluate (mode 1, found call of a function or method without using the direct name of the function): '.$s;
|
||||
} else {
|
||||
dol_syslog('Bad string syntax to evaluate (found call of a function or method without using direct name): '.$s);
|
||||
dol_syslog('Bad string syntax to evaluate (mode 1, found call of a function or method without using the direct name of the function): '.$s);
|
||||
return '';
|
||||
}
|
||||
}
|
||||
@@ -9884,18 +9889,23 @@ function dol_eval($s, $returnvalue = 0, $hideerrors = 1, $onlysimplestring = '1'
|
||||
return '';
|
||||
}
|
||||
}
|
||||
$scheck = preg_replace('/->[a-zA-Z0-9_]+\(/', '->__METHOD__', $s); // accept parenthesis in '...->method(...'
|
||||
$savescheck = '';
|
||||
$scheck = $s;
|
||||
while ($scheck && $savescheck != $scheck) {
|
||||
$savescheck = $scheck;
|
||||
$scheck = preg_replace('/->[a-zA-Z0-9_]+\(/', '->__METHOD__', $scheck); // accept parenthesis in '...->method(...'
|
||||
$scheck = preg_replace('/^\(/', '__PARENTHESIS__ ', $scheck); // accept parenthesis in '(...'. Must replace with __PARENTHESIS__ with a space after to allow following substitutions
|
||||
$scheck = preg_replace('/\s\(/', '__PARENTHESIS__ ', $scheck); // accept parenthesis in '... ('. Must replace with __PARENTHESIS__ with a space after to allow following substitutions
|
||||
$scheck = preg_replace('/^!?[a-zA-Z0-9_]+\(/', '__FUNCTION__', $scheck); // accept parenthesis in 'function(' and '!function('
|
||||
$scheck = preg_replace('/\s!?[a-zA-Z0-9_]+\(/', '__FUNCTION__', $scheck); // accept parenthesis in '... function(' and '... !function('
|
||||
$scheck = preg_replace('/(\^|\')\(/', '__REGEXSTART__', $scheck); // To allow preg_match('/^(aaa|bbb)/'... or isStringVarMatching('leftmenu', '(aaa|bbb)')
|
||||
}
|
||||
//print 'scheck='.$scheck." : ".strpos($scheck, '(')."<br>\n";
|
||||
if (strpos($scheck, '(') !== false) {
|
||||
if ($returnvalue) {
|
||||
return 'Bad string syntax to evaluate (found call of a function or method without using direct name): '.$s;
|
||||
return 'Bad string syntax to evaluate (mode 2, found call of a function or method without using the direct name of the function): '.$s;
|
||||
} else {
|
||||
dol_syslog('Bad string syntax to evaluate (found call of a function or method without using direct name): '.$s);
|
||||
dol_syslog('Bad string syntax to evaluate (mode 2, found call of a function or method without using the direct name of the function): '.$s);
|
||||
return '';
|
||||
}
|
||||
}
|
||||
@@ -9932,22 +9942,27 @@ function dol_eval($s, $returnvalue = 0, $hideerrors = 1, $onlysimplestring = '1'
|
||||
|
||||
// We block use of php exec or php file functions
|
||||
$forbiddenphpstrings = array('$$');
|
||||
$forbiddenphpstrings = array_merge($forbiddenphpstrings, array('_ENV', '_SESSION', '_COOKIE', '_GET', '_POST', '_REQUEST'));
|
||||
$forbiddenphpstrings = array_merge($forbiddenphpstrings, array('_ENV', '_SESSION', '_COOKIE', '_GET', '_POST', '_REQUEST', 'ReflectionFunction'));
|
||||
|
||||
$forbiddenphpfunctions = array("exec", "passthru", "shell_exec", "system", "proc_open", "popen");
|
||||
$forbiddenphpfunctions = array_merge($forbiddenphpfunctions, array("dol_eval", "executeCLI", "verifCond")); // native dolibarr functions
|
||||
$forbiddenphpfunctions = array_merge($forbiddenphpfunctions, array("base64_decode", "rawurldecode", "urldecode")); // decode string functions
|
||||
$forbiddenphpfunctions = array_merge($forbiddenphpfunctions, array("base64_decode", "rawurldecode", "urldecode", "str_rot13", "hex2bin")); // decode string functions used to obfuscated function name
|
||||
$forbiddenphpfunctions = array_merge($forbiddenphpfunctions, array("fopen", "file_put_contents", "fputs", "fputscsv", "fwrite", "fpassthru", "require", "include", "mkdir", "rmdir", "symlink", "touch", "unlink", "umask"));
|
||||
$forbiddenphpfunctions = array_merge($forbiddenphpfunctions, array("get_defined_functions", "get_defined_vars", "get_defined_constants", "get_declared_classes"));
|
||||
$forbiddenphpfunctions = array_merge($forbiddenphpfunctions, array("function", "call_user_func"));
|
||||
$forbiddenphpfunctions = array_merge($forbiddenphpfunctions, array("eval", "create_function", "assert", "mb_ereg_replace")); // function with eval capabilities
|
||||
|
||||
$forbiddenphpmethods = array('invoke', 'invokeArgs'); // Method of ReflectionFunction to execute a function
|
||||
|
||||
$forbiddenphpregex = 'global\s+\$|\b('.implode('|', $forbiddenphpfunctions).')\b';
|
||||
|
||||
$forbiddenphpmethodsregex = '->('.implode('|', $forbiddenphpmethods).')';
|
||||
|
||||
do {
|
||||
$oldstringtoclean = $s;
|
||||
$s = str_ireplace($forbiddenphpstrings, '__forbiddenstring__', $s);
|
||||
$s = preg_replace('/'.$forbiddenphpregex.'/i', '__forbiddenstring__', $s);
|
||||
$s = preg_replace('/'.$forbiddenphpmethodsregex.'/i', '__forbiddenstring__', $s);
|
||||
//$s = preg_replace('/\$[a-zA-Z0-9_\->\$]+\(/i', '', $s); // Remove $function( call and $mycall->mymethod(
|
||||
} while ($oldstringtoclean != $s);
|
||||
|
||||
|
||||
@@ -896,6 +896,7 @@ class Mo extends CommonObject
|
||||
return -2;
|
||||
}
|
||||
$productstatic = new Product($this->db);
|
||||
|
||||
$arrayoflines = $this->fetchLinesLinked('consumed', $idline); // Get lines consumed under the one to delete
|
||||
|
||||
$result = 0;
|
||||
|
||||
@@ -253,6 +253,7 @@ if ($resql) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
|
||||
<script>
|
||||
@@ -520,20 +521,51 @@ if (getDolGlobalString('TAKEPOS_CUSTOMER_DISPLAY')) {
|
||||
?>
|
||||
</script>
|
||||
|
||||
<?php
|
||||
$showothercurrency = 0;
|
||||
if (isModEnabled('multicurrency') && $_SESSION["takeposcustomercurrency"] != "" && $conf->currency != $_SESSION["takeposcustomercurrency"]) {
|
||||
//Only show customer currency if multicurrency module is enabled, if currency selected and if this currency selected is not the same as main currency
|
||||
$showothercurrency = 1;
|
||||
include_once DOL_DOCUMENT_ROOT . '/multicurrency/class/multicurrency.class.php';
|
||||
$multicurrency = new MultiCurrency($db);
|
||||
$multicurrency->fetch(0, $_SESSION["takeposcustomercurrency"]);
|
||||
}
|
||||
?>
|
||||
|
||||
<div style="position:relative; padding-top: 20px; left:5%; height:140px; width:90%;">
|
||||
<div class="paymentbordline paymentbordlinetotal center">
|
||||
<span class="takepospay colorwhite"><?php echo $langs->trans('TotalTTC'); ?>: <span id="totaldisplay" class="colorwhite"><?php echo price($invoice->total_ttc, 1, '', 1, -1, -1, $invoice->multicurrency_code); ?></span></span>
|
||||
<span class="takepospay colorwhite"><?php echo $langs->trans('TotalTTC'); ?>: <span id="totaldisplay" class="colorwhite"><?php
|
||||
echo price($invoice->total_ttc, 1, '', 1, -1, -1, $conf->currency);
|
||||
if ($showothercurrency) {
|
||||
print ' <span id="linecolht-span-total opacitymedium" style="font-size:0.9em; font-style:italic;">(' . price($invoice->total_ht * $multicurrency->rate->rate) . ' ' . $_SESSION["takeposcustomercurrency"] . ')</span>';
|
||||
}
|
||||
?></span></span>
|
||||
</div>
|
||||
<?php if ($remaintopay != $invoice->total_ttc) { ?>
|
||||
<div class="paymentbordline paymentbordlineremain center">
|
||||
<span class="takepospay colorwhite"><?php echo $langs->trans('RemainToPay'); ?>: <span id="remaintopaydisplay" class="colorwhite"><?php echo price($remaintopay, 1, '', 1, -1, -1, $invoice->multicurrency_code); ?></span></span>
|
||||
<span class="takepospay colorwhite"><?php echo $langs->trans('RemainToPay'); ?>: <span id="remaintopaydisplay" class="colorwhite"><?php
|
||||
echo price($remaintopay, 1, '', 1, -1, -1, $invoice->multicurrency_code);
|
||||
if ($showothercurrency) {
|
||||
print ' <span id="linecolht-span-total opacitymedium" style="font-size:0.9em; font-style:italic;">(' . price($remaintopay * $multicurrency->rate->rate) . ' ' . $_SESSION["takeposcustomercurrency"] . ')</span>';
|
||||
}
|
||||
?></span></span>
|
||||
</div>
|
||||
<?php } ?>
|
||||
<div class="paymentbordline paymentbordlinereceived center">
|
||||
<span class="takepospay colorwhite"><?php echo $langs->trans("Received"); ?>: <span class="change1 colorred"><?php echo price(0, 1, '', 1, -1, -1, $invoice->multicurrency_code); ?></span><input type="hidden" id="change1" class="change1" value="0"></span>
|
||||
<span class="takepospay colorwhite"><?php echo $langs->trans("Received"); ?>: <span class="change1 colorred"><?php
|
||||
echo price(0, 1, '', 1, -1, -1, $invoice->multicurrency_code);
|
||||
if ($showothercurrency) {
|
||||
print ' <span id="linecolht-span-total opacitymedium" style="font-size:0.9em; font-style:italic;">(' . price(0 * $multicurrency->rate->rate) . ' ' . $_SESSION["takeposcustomercurrency"] . ')</span>';
|
||||
}
|
||||
?></span><input type="hidden" id="change1" class="change1" value="0"></span>
|
||||
</div>
|
||||
<div class="paymentbordline paymentbordlinechange center">
|
||||
<span class="takepospay colorwhite"><?php echo $langs->trans("Change"); ?>: <span class="change2 colorwhite"><?php echo price(0, 1, '', 1, -1, -1, $invoice->multicurrency_code); ?></span><input type="hidden" id="change2" class="change2" value="0"></span>
|
||||
<span class="takepospay colorwhite"><?php echo $langs->trans("Change"); ?>: <span class="change2 colorwhite"><?php
|
||||
echo price(0, 1, '', 1, -1, -1, $invoice->multicurrency_code);
|
||||
if ($showothercurrency) {
|
||||
print ' <span id="linecolht-span-total opacitymedium" style="font-size:0.9em; font-style:italic;">(' . price(0 * $multicurrency->rate->rate) . ' ' . $_SESSION["takeposcustomercurrency"] . ')</span>';
|
||||
}
|
||||
?></span><input type="hidden" id="change2" class="change2" value="0"></span>
|
||||
</div>
|
||||
<?php
|
||||
if (getDolGlobalString('TAKEPOS_CAN_FORCE_BANK_ACCOUNT_DURING_PAYMENT')) {
|
||||
|
||||
@@ -984,7 +984,11 @@ class SecurityTest extends CommonClassTest
|
||||
$langs = $this->savlangs;
|
||||
$db = $this->savdb;
|
||||
|
||||
$result = dol_eval('1==1', 1, 0);
|
||||
// Declare classes found into string to evaluate
|
||||
include_once DOL_DOCUMENT_ROOT.'/projet/class/project.class.php';
|
||||
include_once DOL_DOCUMENT_ROOT.'/projet/class/task.class.php';
|
||||
|
||||
$result=dol_eval('1==1', 1, 0);
|
||||
print "result1 = ".$result."\n";
|
||||
$this->assertTrue($result);
|
||||
|
||||
@@ -992,11 +996,18 @@ class SecurityTest extends CommonClassTest
|
||||
print "result2 = ".$result."\n";
|
||||
$this->assertFalse($result);
|
||||
|
||||
include_once DOL_DOCUMENT_ROOT.'/projet/class/project.class.php';
|
||||
include_once DOL_DOCUMENT_ROOT.'/projet/class/task.class.php';
|
||||
$s = '((($reloadedobj = new ClassThatDoesNotExists($db)) && ($reloadedobj->fetchNoCompute($objectoffield->fk_product) > 0)) ? \'1\' : \'0\')';
|
||||
$result3a = dol_eval($s, 1, 1, '2');
|
||||
print "result3a = ".$result3a."\n";
|
||||
$this->assertEquals('Exception during evaluation: '.$s, $result3a);
|
||||
|
||||
$s = '((($reloadedobj = new Project($db)) && ($reloadedobj->fetchNoCompute($objectoffield->fk_product) > 0)) ? \'1\' : \'0\')';
|
||||
$result3b = dol_eval($s, 1, 1, '2');
|
||||
print "result3b = ".$result."\n";
|
||||
$this->assertEquals('0', $result3b);
|
||||
|
||||
$s = '(($reloadedobj = new Task($db)) && ($reloadedobj->fetchNoCompute($object->id) > 0) && ($secondloadedobj = new Project($db)) && ($secondloadedobj->fetchNoCompute($reloadedobj->fk_project) > 0)) ? $secondloadedobj->ref : "Parent project not found"';
|
||||
$result = dol_eval($s, 1, 1, '2');
|
||||
$result = (string) dol_eval($s, 1, 1, '2');
|
||||
print "result3 = ".$result."\n";
|
||||
$this->assertEquals('Parent project not found', $result);
|
||||
|
||||
@@ -1005,6 +1016,17 @@ class SecurityTest extends CommonClassTest
|
||||
print "result4 = ".$result."\n";
|
||||
$this->assertEquals('Parent project not found', $result);
|
||||
|
||||
$s = 'new abc->invoke(\'whoami\')';
|
||||
$result = (string) dol_eval($s, 1, 1, '2');
|
||||
print "result = ".$result."\n";
|
||||
$this->assertEquals('Bad string syntax to evaluate: new abc__forbiddenstring__(\'whoami\')', $result);
|
||||
|
||||
$s = 'new ReflectionFunction(\'abc\')';
|
||||
$result = (string) dol_eval($s, 1, 1, '2');
|
||||
print "result = ".$result."\n";
|
||||
$this->assertEquals('Bad string syntax to evaluate: new __forbiddenstring__(\'abc\')', $result);
|
||||
|
||||
|
||||
$result = (string) dol_eval('$a=function() { }; $a;', 1, 1, '0');
|
||||
print "result5 = ".$result."\n";
|
||||
$this->assertStringContainsString('Bad string syntax to evaluate', $result);
|
||||
|
||||
Reference in New Issue
Block a user