forked from Wavyzz/dolibarr
Compare commits
8 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
55d177883f | ||
|
|
557e830aae | ||
|
|
a1b99da514 | ||
|
|
53aae1a4b8 | ||
|
|
dd09cb5f69 | ||
|
|
bb0974add9 | ||
|
|
6e3de32c36 | ||
|
|
6a4c7398a7 |
@@ -2,6 +2,12 @@
|
||||
English Dolibarr ChangeLog
|
||||
--------------------------------------------------------------
|
||||
|
||||
***** ChangeLog for 21.0.4 compared to 21.0.3 *****
|
||||
FIX: #35147 SQL Error on Beluga Export when ExpenseReport is enabled (#35149)
|
||||
FIX: error when using a code too large in dictionary
|
||||
FIX: Security when using feature Advanced Target of emailing (hidden in v21, default in v22+). Possible
|
||||
SQL injection by users with permission to make and send mass emailing.
|
||||
|
||||
|
||||
***** ChangeLog for 21.0.3 compared to 21.0.2 *****
|
||||
FIX: #34843 (#34875)
|
||||
|
||||
@@ -453,14 +453,14 @@ if ($nboftargetok) {
|
||||
{
|
||||
print 'Run git tag -a -f -m "'.$MAJOR.'.'.$MINOR.'.'.$BUILD.'" "'.$MAJOR.'.'.$MINOR.'.'.$BUILD.'"'."\n";
|
||||
$ret=`git tag -a -f -m "$MAJOR.$MINOR.$BUILD" "$MAJOR.$MINOR.$BUILD"`;
|
||||
print 'Run git push $GITREMOTENAME -f --tags'."\n";
|
||||
print "Run git push $GITREMOTENAME -f --tags\n";
|
||||
$ret=`git push $GITREMOTENAME -f --tags`;
|
||||
#$ret=`git push -f origin "$MAJOR.$MINOR.$BUILD"`;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
print 'Run git push $GITREMOTENAME --tags'."\n";
|
||||
print "Run git push $GITREMOTENAME --tags\n";
|
||||
$ret=`git push $GITREMOTENAME --tags`;
|
||||
#$ret=`git push origin "$MAJOR.$MINOR.$BUILD"`;
|
||||
}
|
||||
|
||||
@@ -927,23 +927,23 @@ class BookKeeping extends CommonObject
|
||||
} elseif ($key == 't.fk_doc' || $key == 't.fk_docdet' || $key == 't.piece_num') {
|
||||
$sqlwhere[] = $this->db->sanitize($key).' = '.((int) $value);
|
||||
} elseif ($key == 't.subledger_account' || $key == 't.numero_compte') {
|
||||
$sqlwhere[] = $this->db->sanitize($key).' LIKE \''.$this->db->escape($this->db->escapeforlike($value)).'%\'';
|
||||
$sqlwhere[] = $this->db->sanitize($key)." LIKE '".$this->db->escape($this->db->escapeforlike($value))."%'";
|
||||
} elseif ($key == 't.date_creation>=') {
|
||||
$sqlwhere[] = 't.date_creation >= \''.$this->db->idate($value).'\'';
|
||||
$sqlwhere[] = "t.date_creation >= '".$this->db->idate($value)."'";
|
||||
} elseif ($key == 't.date_creation<=') {
|
||||
$sqlwhere[] = 't.date_creation <= \''.$this->db->idate($value).'\'';
|
||||
$sqlwhere[] = "t.date_creation <= '".$this->db->idate($value)."'";
|
||||
} elseif ($key == 't.date_export>=') {
|
||||
$sqlwhere[] = 't.date_export >= \''.$this->db->idate($value).'\'';
|
||||
$sqlwhere[] = "t.date_export >= '".$this->db->idate($value)."'";
|
||||
} elseif ($key == 't.date_export<=') {
|
||||
$sqlwhere[] = 't.date_export <= \''.$this->db->idate($value).'\'';
|
||||
$sqlwhere[] = "t.date_export <= '".$this->db->idate($value)."'";
|
||||
} elseif ($key == 't.date_validated>=') {
|
||||
$sqlwhere[] = 't.date_validated >= \''.$this->db->idate($value).'\'';
|
||||
$sqlwhere[] = "t.date_validated >= '".$this->db->idate($value)."'";
|
||||
} elseif ($key == 't.date_validated<=') {
|
||||
$sqlwhere[] = 't.date_validated <= \''.$this->db->idate($value).'\'';
|
||||
$sqlwhere[] = "t.date_validated <= '".$this->db->idate($value)."'";
|
||||
} elseif ($key == 't.date_lim_reglement>=') {
|
||||
$sqlwhere[] = 't.date_lim_reglement>=\''.$this->db->idate($value).'\'';
|
||||
$sqlwhere[] = "t.date_lim_reglement>='".$this->db->idate($value)."'";
|
||||
} elseif ($key == 't.date_lim_reglement<=') {
|
||||
$sqlwhere[] = 't.date_lim_reglement<=\''.$this->db->idate($value).'\'';
|
||||
$sqlwhere[] = "t.date_lim_reglement<='".$this->db->idate($value)."'";
|
||||
} elseif ($key == 't.credit' || $key == 't.debit') {
|
||||
$sqlwhere[] = natural_search($key, $value, 1, 1);
|
||||
} elseif ($key == 't.reconciled_option') {
|
||||
@@ -955,7 +955,7 @@ class BookKeeping extends CommonObject
|
||||
$sqlwhere[] = natural_search("t.code_journal", $value, 3, 1);
|
||||
}
|
||||
} elseif ($key == 't.search_accounting_code_in' && !empty($value)) {
|
||||
$sqlwhere[] = 't.numero_compte IN ('.$this->db->sanitize($value, 1).')';
|
||||
$sqlwhere[] = "t.numero_compte IN (".$this->db->sanitize($value, 1).")";
|
||||
} else {
|
||||
$sqlwhere[] = natural_search($key, $value, 0, 1);
|
||||
}
|
||||
@@ -1108,7 +1108,7 @@ class BookKeeping extends CommonObject
|
||||
if (count($filter) > 0) {
|
||||
foreach ($filter as $key => $value) {
|
||||
if ($key == 't.doc_date') {
|
||||
$sqlwhere[] = $this->db->sanitize($key).' = \''.$this->db->idate($value).'\'';
|
||||
$sqlwhere[] = $this->db->sanitize($key)." = '".$this->db->idate($value)."'";
|
||||
} elseif ($key == 't.doc_date>=') {
|
||||
$sqlwhere[] = "t.doc_date >= '".$this->db->idate($value)."'";
|
||||
} elseif ($key == 't.doc_date<=') {
|
||||
@@ -1128,23 +1128,23 @@ class BookKeeping extends CommonObject
|
||||
} elseif ($key == 't.fk_doc' || $key == 't.fk_docdet' || $key == 't.piece_num') {
|
||||
$sqlwhere[] = $this->db->sanitize($key).' = '.((int) $value);
|
||||
} elseif ($key == 't.subledger_account' || $key == 't.numero_compte') {
|
||||
$sqlwhere[] = $this->db->sanitize($key).' LIKE \''.$this->db->escape($value).'%\'';
|
||||
$sqlwhere[] = $this->db->sanitize($key)." LIKE '".$this->db->escape($value)."%'";
|
||||
} elseif ($key == 't.date_creation>=') {
|
||||
$sqlwhere[] = 't.date_creation >= \''.$this->db->idate($value).'\'';
|
||||
$sqlwhere[] = "t.date_creation >= '".$this->db->idate($value)."'";
|
||||
} elseif ($key == 't.date_creation<=') {
|
||||
$sqlwhere[] = 't.date_creation <= \''.$this->db->idate($value).'\'';
|
||||
$sqlwhere[] = "t.date_creation <= '".$this->db->idate($value)."'";
|
||||
} elseif ($key == 't.tms>=') {
|
||||
$sqlwhere[] = 't.tms >= \''.$this->db->idate($value).'\'';
|
||||
$sqlwhere[] = "t.tms >= '".$this->db->idate($value)."'";
|
||||
} elseif ($key == 't.tms<=') {
|
||||
$sqlwhere[] = 't.tms <= \''.$this->db->idate($value).'\'';
|
||||
$sqlwhere[] = "t.tms <= '".$this->db->idate($value)."'";
|
||||
} elseif ($key == 't.date_export>=') {
|
||||
$sqlwhere[] = 't.date_export >= \''.$this->db->idate($value).'\'';
|
||||
$sqlwhere[] = "t.date_export >= '".$this->db->idate($value)."'";
|
||||
} elseif ($key == 't.date_export<=') {
|
||||
$sqlwhere[] = 't.date_export <= \''.$this->db->idate($value).'\'';
|
||||
$sqlwhere[] = "t.date_export <= '".$this->db->idate($value)."'";
|
||||
} elseif ($key == 't.date_validated>=') {
|
||||
$sqlwhere[] = 't.date_validated >= \''.$this->db->idate($value).'\'';
|
||||
$sqlwhere[] = "t.date_validated >= '".$this->db->idate($value)."'";
|
||||
} elseif ($key == 't.date_validated<=') {
|
||||
$sqlwhere[] = 't.date_validated <= \''.$this->db->idate($value).'\'';
|
||||
$sqlwhere[] = "t.date_validated <= '".$this->db->idate($value)."'";
|
||||
} elseif ($key == 't.credit' || $key == 't.debit') {
|
||||
$sqlwhere[] = natural_search($key, $value, 1, 1);
|
||||
} elseif ($key == 't.code_journal' && !empty($value)) {
|
||||
@@ -1159,7 +1159,7 @@ class BookKeeping extends CommonObject
|
||||
}
|
||||
}
|
||||
if (count($sqlwhere) > 0) {
|
||||
$sql .= ' AND '.implode(" ".$this->db->sanitize($filtermode)." ", $sqlwhere);
|
||||
$sql .= " AND ".implode(" ".$this->db->sanitize($filtermode)." ", $sqlwhere);
|
||||
}
|
||||
|
||||
$filter = '';
|
||||
|
||||
@@ -926,6 +926,10 @@ if (empty($reshook)) {
|
||||
$ok = 0;
|
||||
setEventMessages($langs->transnoentities("ErrorCountryCodeMustBe2Char", $langs->transnoentities("Code")), null, 'errors');
|
||||
}
|
||||
if ($id == DICT_PAIEMENT && strlen(GETPOST("code")) >= 6) { // 6 char max on code for payment mode codes
|
||||
$ok = 0;
|
||||
setEventMessages($langs->transnoentities("ErrorFieldMustHaveLessThanXChar", $langs->transnoentities("Code"), 6), null, 'errors');
|
||||
}
|
||||
|
||||
// Clean some parameters
|
||||
if ((GETPOST("localtax1_type") || (GETPOST('localtax1_type') == '0')) && !GETPOST("localtax1")) {
|
||||
|
||||
@@ -1013,9 +1013,9 @@ class AdvanceTargetingMailing extends CommonObject
|
||||
*/
|
||||
public function transformToSQL($column_to_test, $criteria)
|
||||
{
|
||||
$return_sql_criteria = '(';
|
||||
$return_sql_criteria = "(";
|
||||
|
||||
//This is a multiple value test
|
||||
// This is a multiple value test
|
||||
if (preg_match('/;/', $criteria)) {
|
||||
$return_sql_not_like = array();
|
||||
$return_sql_like = array();
|
||||
@@ -1023,23 +1023,23 @@ class AdvanceTargetingMailing extends CommonObject
|
||||
$criteria_array = explode(';', $criteria);
|
||||
foreach ($criteria_array as $inter_criteria) {
|
||||
if (preg_match('/!/', $inter_criteria)) {
|
||||
$return_sql_not_like[] = '('.$column_to_test.' NOT LIKE \''.str_replace('!', '', $inter_criteria).'\')';
|
||||
$return_sql_not_like[] = "(".$this->db->sanitize($column_to_test)." NOT LIKE '".$this->db->sanitize(str_replace('!', '', $inter_criteria))."')";
|
||||
} else {
|
||||
$return_sql_like[] = '('.$column_to_test.' LIKE \''.$inter_criteria.'\')';
|
||||
$return_sql_like[] = "(".$this->db->sanitize($column_to_test)." LIKE '".$this->db->sanitize($inter_criteria)."')";
|
||||
}
|
||||
}
|
||||
|
||||
if (count($return_sql_like) > 0) {
|
||||
$return_sql_criteria .= '('.implode(' OR ', $return_sql_like).')';
|
||||
$return_sql_criteria .= "(".implode(" OR ", $return_sql_like).")"; // element in arrays were sanitized previously
|
||||
}
|
||||
if (count($return_sql_not_like) > 0) {
|
||||
$return_sql_criteria .= ' AND ('.implode(' AND ', $return_sql_not_like).')';
|
||||
$return_sql_criteria .= " AND (".implode(" AND ", $return_sql_not_like).")"; // element in arrays were sanitized previously
|
||||
}
|
||||
} else {
|
||||
$return_sql_criteria .= $column_to_test.' LIKE \''.$this->db->escape($criteria).'\'';
|
||||
$return_sql_criteria .= $this->db->sanitize($column_to_test)." LIKE '".$this->db->escape($criteria)."'";
|
||||
}
|
||||
|
||||
$return_sql_criteria .= ')';
|
||||
$return_sql_criteria .= ")";
|
||||
|
||||
return $return_sql_criteria;
|
||||
}
|
||||
|
||||
@@ -246,6 +246,11 @@ abstract class CommonObjectLine extends CommonObject
|
||||
*/
|
||||
public $multicurrency_subprice;
|
||||
|
||||
/**
|
||||
* @var float Multicurrency subprice
|
||||
*/
|
||||
public $multicurrency_subprice_ttc;
|
||||
|
||||
/**
|
||||
* @var float Multicurrency total without tax
|
||||
*/
|
||||
|
||||
@@ -324,13 +324,13 @@ class DoliDBPgsql extends DoliDB
|
||||
|
||||
// To have PostgreSQL case sensitive
|
||||
$count_like = 0;
|
||||
$line = str_replace(' LIKE \'', ' ILIKE \'', $line, $count_like);
|
||||
$line = str_replace(" LIKE '", " ILIKE '", $line, $count_like);
|
||||
if (getDolGlobalString('PSQL_USE_UNACCENT') && $count_like > 0) {
|
||||
// @see https://docs.PostgreSQL.fr/11/unaccent.html : 'unaccent()' function must be installed before
|
||||
$line = preg_replace('/\s+(\(+\s*)([a-zA-Z0-9\-\_\.]+) ILIKE /', ' \1unaccent(\2) ILIKE ', $line);
|
||||
}
|
||||
|
||||
$line = str_replace(' LIKE BINARY \'', ' LIKE \'', $line);
|
||||
$line = str_replace(" LIKE BINARY '", " LIKE '", $line);
|
||||
|
||||
// Replace INSERT IGNORE into INSERT
|
||||
$line = preg_replace('/^INSERT IGNORE/', 'INSERT', $line);
|
||||
|
||||
@@ -1301,7 +1301,7 @@ class DoliDBSqlite3 extends DoliDB
|
||||
// FIXME: not for SQLite
|
||||
$fullpathofdump = '/pathtomysqldump/mysqldump';
|
||||
|
||||
$resql = $this->query('SHOW VARIABLES LIKE \'basedir\'');
|
||||
$resql = $this->query("SHOW VARIABLES LIKE 'basedir'");
|
||||
if ($resql) {
|
||||
$liste = $this->fetch_array($resql);
|
||||
$basedir = $liste['Value'];
|
||||
@@ -1320,7 +1320,7 @@ class DoliDBSqlite3 extends DoliDB
|
||||
// FIXME: not for SQLite
|
||||
$fullpathofimport = '/pathtomysql/mysql';
|
||||
|
||||
$resql = $this->query('SHOW VARIABLES LIKE \'basedir\'');
|
||||
$resql = $this->query("SHOW VARIABLES LIKE 'basedir'");
|
||||
if ($resql) {
|
||||
$liste = $this->fetch_array($resql);
|
||||
$basedir = $liste['Value'];
|
||||
@@ -1387,7 +1387,9 @@ class DoliDBSqlite3 extends DoliDB
|
||||
$result = array();
|
||||
/*
|
||||
$sql='SHOW STATUS';
|
||||
if ($filter) $sql.=" LIKE '".$this->escape($filter)."'";
|
||||
if ($filter) {
|
||||
$sql.=" LIKE '".$this->escape($filter)."'";
|
||||
}
|
||||
$resql=$this->query($sql);
|
||||
if ($resql)
|
||||
{
|
||||
|
||||
@@ -426,9 +426,9 @@ class pdf_beluga extends ModelePDFProjects
|
||||
'title' => "ListExpenseReportsAssociatedProject",
|
||||
'class' => 'ExpenseReport',
|
||||
'table' => 'expensereport',
|
||||
'datefieldname' => 'dated',
|
||||
'datefieldname' => 'date_debut',
|
||||
'margin' => 'minus',
|
||||
'disableamount' => 1,
|
||||
'disableamount' => 0,
|
||||
'test' => isModEnabled('expensereport') && $user->hasRight('expensereport', 'lire'),
|
||||
'lang' => 'trip'),
|
||||
'agenda' => array(
|
||||
@@ -644,6 +644,9 @@ class pdf_beluga extends ModelePDFProjects
|
||||
if (empty($date)) {
|
||||
$date = $element->datev; // Intervention card
|
||||
}
|
||||
if (empty($date)) {
|
||||
$date = $element->date_debut; // Expense report
|
||||
}
|
||||
}
|
||||
|
||||
$pdf->SetXY($this->posxdate, $curY);
|
||||
|
||||
@@ -36,7 +36,7 @@ if (!defined('DOL_APPLICATION_TITLE')) {
|
||||
define('DOL_APPLICATION_TITLE', 'Dolibarr');
|
||||
}
|
||||
if (!defined('DOL_VERSION')) {
|
||||
define('DOL_VERSION', '21.0.3'); // a.b.c-alpha, a.b.c-beta, a.b.c-rcX or a.b.c
|
||||
define('DOL_VERSION', '21.0.4'); // a.b.c-alpha, a.b.c-beta, a.b.c-rcX or a.b.c
|
||||
}
|
||||
|
||||
if (!defined('EURO')) {
|
||||
|
||||
@@ -87,6 +87,7 @@ ErrorBadFormatValueList=The list value cannot have more than one comma: <u>%s</u
|
||||
ErrorFieldCanNotContainSpecialCharacters=The field <b>%s</b> must not contains special characters.
|
||||
ErrorFieldCanNotContainSpecialNorUpperCharacters=The field <b>%s</b> must not contain special characters, nor upper case characters, and must start with an alphabetical character (a-z)
|
||||
ErrorFieldMustHaveXChar=The field <b>%s</b> must have at least %s characters.
|
||||
ErrorFieldMustHaveLessThanXChar=The field <b>%s</b> must have a maximum of %s characters.
|
||||
ErrorNoAccountancyModuleLoaded=No accountancy module activated
|
||||
ErrorExportDuplicateProfil=This profile name already exists for this export set.
|
||||
ErrorLDAPSetupNotComplete=Dolibarr-LDAP matching is not complete.
|
||||
|
||||
@@ -293,6 +293,22 @@ class CodingPhpTest extends CommonClassTest
|
||||
//exit;
|
||||
|
||||
|
||||
// Part to scan code vulnerability on SQL injection
|
||||
|
||||
|
||||
// Check sql using ' instead of "
|
||||
$ok = true;
|
||||
$matches = array();
|
||||
preg_match_all('/LIKE \\\/', $filecontent, $matches, PREG_SET_ORDER);
|
||||
foreach ($matches as $key => $val) {
|
||||
var_dump($matches);
|
||||
$ok = false;
|
||||
break;
|
||||
}
|
||||
//print __METHOD__." Result for checking we don't have non escaped string in sql requests for file ".$file."\n";
|
||||
$this->assertTrue($ok, "Found a LIKE \' when we should have LIKE ' - Bad.");
|
||||
//exit;
|
||||
|
||||
|
||||
// Check sql string DELETE|OR|AND|WHERE|INSERT ... yyy = ".$xxx
|
||||
// with xxx that is not 'thi' (for $this->db->sanitize) and 'db-' (for $db->sanitize). It means we forget a ' if string, or an (int) if int, when forging sql request.
|
||||
|
||||
Reference in New Issue
Block a user