Qual/Sec: Use db->sanitize instead of db->escape when not quoted, fix some quoting (#39286)

* FIX phpstan: Societe::$client (int<0,3>) does not accept -1 (#39244)

Societe::$client is annotated @var int<0,3> (domain 0=no customer,
1=customer, 2=prospect, 3=both) in societe.class.php, but the create
form in societe/card.php pre-set it to -1 as a transient "nothing
pre-selected" placeholder, tripping PHPStan level 10 on develop.

The value is never persisted (save paths compute 0..3) and the only
reader, the switch() building the form, treats -1 and 0 identically via
its default case. Use 0 (the property's own default) so the assignment
matches the declared type. No behavior change.

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>

* Qual: Fix entity handling in bonprelevement.class.php

The variable name 'entities' was changed to 'entity' to better reflect the singular nature of the value being retrieved.
It was also casted to an int instead of using an unquoted db->escape.

* Qual: Improve SQL query construction in company.lib.php

By escaping the concatenated string, injection verification does not identify a false positive.

* Qual: Avoid void positive, sanitize instead of escape

* Qual: Avoid false positive, sanitize instead of escape

* Sec: Fix potential injection with cast to int (timespent_duration)

* Qual: Avoid false positive, sanitize instead of escape

* Qual: Avoid false positive, sanitize instead of escape

* fix: Replace escape() with sanitize() in SQL queries

# FIX: Replace escape() with sanitize() in SQL queries

- Replace escape() with sanitize() in SQL queries to ensure proper SQL injection protection
- Update SQL queries in multiple files to use sanitize() instead of escape()
- Ensure consistent use of sanitize() across the codebase for better security

* fix(sql): Replace escape with sanitize in SQL queries

# FIX: Replace escape with sanitize in SQL queries

- Replace `escape` with `sanitize` in SQL queries to ensure proper SQL injection prevention

* Qual: Improve field escaping/quoting

# Qual: Qual: Improve field escaping/quoting

---------

Co-authored-by: Jam Balaya <jambalaya.pyoncafe@outlook.jp>
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
MDW 2026-07-27 13:00:33 +02:00 committed by GitHub
parent cec87d9425
commit f551727df9
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
34 changed files with 96 additions and 95 deletions

View file

@ -1,6 +1,7 @@
<?php
/* Copyright (C) 2024 AWeerWolf
* Copyright (C) 2026 Alexandre Spangaro <alexandre@inovea-conseil.com>
* Copyright (C) 2026 MDW <mdeweerd@users.noreply.github.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -256,10 +257,10 @@ foreach ($search as $key => $val) {
$columnName = preg_replace('/(_dtstart|_dtend)$/', '', $key);
if (preg_match('/^(date|timestamp|datetime)/', $object->fields[$columnName]['type'])) {
if (preg_match('/_dtstart$/', $key)) {
$sql .= " AND t.".$db->escape($columnName)." >= '".$db->idate($search[$key])."'";
$sql .= " AND t.".$db->sanitize($columnName)." >= '".$db->idate($search[$key])."'";
}
if (preg_match('/_dtend$/', $key)) {
$sql .= " AND t.".$db->escape($columnName)." <= '".$db->idate($search[$key])."'";
$sql .= " AND t.".$db->sanitize($columnName)." <= '".$db->idate($search[$key])."'";
}
}
}

View file

@ -1154,7 +1154,7 @@ if (empty($reshook)) {
$tablename = preg_replace('/^'.preg_quote(MAIN_DB_PREFIX, '/').'/', '', $tablename);
if ($rowid) {
$sql = "UPDATE ".MAIN_DB_PREFIX.$db->sanitize($tablename)." SET active = 1 WHERE ".$db->escape($rowidcol)." = '".$db->escape($rowid)."'".($entity != '' ? " AND entity = ".(int) $entity : '');
$sql = "UPDATE ".MAIN_DB_PREFIX.$db->sanitize($tablename)." SET active = 1 WHERE ".$db->sanitize($rowidcol)." = ".((int) $rowid)."'".($entity != '' ? " AND entity = ".(int) $entity : '');
} elseif ($code) {
$sql = "UPDATE ".MAIN_DB_PREFIX.$db->sanitize($tablename)." SET active = 1 WHERE code = '".$db->escape(dol_escape_htmltag($code))."'".($entity != '' ? " AND entity = ".(int) $entity : '');
} else {

View file

@ -2,7 +2,7 @@
/* Copyright (C) 2007-2017 Laurent Destailleur <eldy@users.sourceforge.net>
* Copyright (C) 2018 Ferran Marcet <fmarcet@2byte.es>
* Copyright (C) 2024-2026 Frédéric France <frederic.france@free.fr>
* Copyright (C) 2024-2025 MDW <mdeweerd@users.noreply.github.com>
* Copyright (C) 2024-2026 MDW <mdeweerd@users.noreply.github.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -292,10 +292,10 @@ foreach ($search as $key => $val) {
$columnName = preg_replace('/(_dtstart|_dtend)$/', '', $key);
if (preg_match('/^(date|timestamp|datetime)/', $object->fields[$columnName]['type'])) {
if (preg_match('/_dtstart$/', $key)) {
$sql .= " AND t.".$db->escape($columnName)." >= '".$db->idate($search[$key])."'";
$sql .= " AND t.".$db->sanitize($columnName)." >= '".$db->idate($search[$key])."'";
}
if (preg_match('/_dtend$/', $key)) {
$sql .= " AND t.".$db->escape($columnName)." <= '".$db->idate($search[$key])."'";
$sql .= " AND t.".$db->sanitize($columnName)." <= '".$db->idate($search[$key])."'";
}
}
}
@ -319,7 +319,7 @@ $sql .= $hookmanager->resPrint;
/* If a group by is required
$sql .= " GROUP BY ";
foreach($object->fields as $key => $val) {
$sql .= "t.".$db->escape($key).", ";
$sql .= "t.".$db->sanitize($key).", ";
}
// Add fields from extrafields
if (!empty($extrafields->attributes[$object->table_element]['label'])) {

View file

@ -12,7 +12,7 @@
* Copyright (C) 2015-2024 Ferran Marcet <fmarcet@2byte.es>
* Copyright (C) 2016 Raphaël Doursenaud <rdoursenaud@gpcsolutions.fr>
* Copyright (C) 2018-2026 Frédéric France <frederic.france@free.fr>
* Copyright (C) 2024-2025 MDW <mdeweerd@users.noreply.github.com>
* Copyright (C) 2024-2026 MDW <mdeweerd@users.noreply.github.com>
* Copyright (C) 2025 Vincent Maury <vmaury@timgroup.fr>
* Copyright (C) 2025 Jon Bendtsen <jon.bendtsen.github@jonb.dk>
*
@ -576,7 +576,7 @@ if (empty($reshook)) {
$i++;
}
$sql .= " WHERE ".$db->escape($rowidcol)." = ".((int) $rowid);
$sql .= " WHERE ".$db->sanitize($rowidcol)." = ".((int) $rowid);
if (!$user->admin) { // A non admin user can only edit its own template
$sql .= " AND fk_user = ".((int) $user->id);
}

View file

@ -960,7 +960,7 @@ If user says 'order' without any qualifier, they mean a SALES ORDER - use this t
$table = $tableMap[$type];
$sql = "UPDATE " . MAIN_DB_PREFIX . $this->db->escape($table);
$sql = "UPDATE " . MAIN_DB_PREFIX . $this->db->sanitize($table);
$sql .= " SET fk_unit = " . (int) $unitId;
$sql .= " WHERE rowid = " . (int) $lineId;

View file

@ -459,7 +459,7 @@ class BOM extends CommonObject
$sql = "SELECT ".$objectline->getFieldList('l');
$sql .= " FROM ".$this->db->prefix().$objectline->table_element." as l";
$sql .= " LEFT JOIN ".$this->db->prefix()."product as p ON p.rowid = l.fk_product";
$sql .= " WHERE l.fk_".$this->db->escape($this->element)." = ".((int) $this->id);
$sql .= " WHERE l.fk_".$this->db->sanitize($this->element)." = ".((int) $this->id);
$sql .= " AND p.fk_product_type = ". ((int) $typeproduct);
if (isset($objectline->fields['position'])) {
$sql .= $this->db->order('position', 'ASC');

View file

@ -2,7 +2,7 @@
/* Copyright (C) 2007-2017 Laurent Destailleur <eldy@users.sourceforge.net>
* Copyright (C) 2022 Alice Adminson <aadminson@example.com>
* Copyright (C) 2024-2026 Frédéric France <frederic.france@free.fr>
* Copyright (C) 2024-2025 MDW <mdeweerd@users.noreply.github.com>
* Copyright (C) 2024-2026 MDW <mdeweerd@users.noreply.github.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -292,17 +292,17 @@ foreach ($search as $key => $val) {
$mode_search = 2;
}
if ($search[$key] != '') {
$sql .= natural_search("t.".$db->escape($key), $search[$key], (($key == 'status') ? 2 : $mode_search));
$sql .= natural_search("t.".$db->sanitize($key), $search[$key], (($key == 'status') ? 2 : $mode_search));
}
} else {
if (preg_match('/(_dtstart|_dtend)$/', $key) && $search[$key] != '') {
$columnName = preg_replace('/(_dtstart|_dtend)$/', '', $key);
if (preg_match('/^(date|timestamp|datetime)/', $object->fields[$columnName]['type'])) {
if (preg_match('/_dtstart$/', $key)) {
$sql .= " AND t.".$db->escape($columnName)." >= '".$db->idate($search[$key])."'";
$sql .= " AND t.".$db->sanitize($columnName)." >= '".$db->idate($search[$key])."'";
}
if (preg_match('/_dtend$/', $key)) {
$sql .= " AND t.".$db->escape($columnName)." <= '".$db->idate($search[$key])."'";
$sql .= " AND t.".$db->sanitize($columnName)." <= '".$db->idate($search[$key])."'";
}
}
}

View file

@ -2,7 +2,7 @@
/* Copyright (C) 2007-2017 Laurent Destailleur <eldy@users.sourceforge.net>
* Copyright (C) 2023 Alice Adminson <aadminson@example.com>
* Copyright (C) 2024-2026 Frédéric France <frederic.france@free.fr>
* Copyright (C) 2024-2025 MDW <mdeweerd@users.noreply.github.com>
* Copyright (C) 2024-2026 MDW <mdeweerd@users.noreply.github.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -287,17 +287,17 @@ foreach ($search as $key => $val) {
$mode_search = 2;
}
if ($search[$key] != '') {
$sql .= natural_search("t.".$db->escape($key), $search[$key], (($key == 'status') ? 2 : $mode_search));
$sql .= natural_search("t.".$db->sanitize($key), $search[$key], (($key == 'status') ? 2 : $mode_search));
}
} else {
if (preg_match('/(_dtstart|_dtend)$/', $key) && $search[$key] != '') {
$columnName = preg_replace('/(_dtstart|_dtend)$/', '', $key);
if (preg_match('/^(date|timestamp|datetime)/', $object->fields[$columnName]['type'])) {
if (preg_match('/_dtstart$/', $key)) {
$sql .= " AND t.".$db->escape($columnName)." >= '".$db->idate($search[$key])."'";
$sql .= " AND t.".$db->sanitize($columnName)." >= '".$db->idate($search[$key])."'";
}
if (preg_match('/_dtend$/', $key)) {
$sql .= " AND t.".$db->escape($columnName)." <= '".$db->idate($search[$key])."'";
$sql .= " AND t.".$db->sanitize($columnName)." <= '".$db->idate($search[$key])."'";
}
}
}

View file

@ -1170,7 +1170,7 @@ if ($user->hasRight("holiday", "read")) {
$sql .= " AND (x.statut = '2' OR x.statut = '3')"; // Show only public leaves (2 = leave wait for approval, 3 = leave approved)
if ($mode == 'show_day') {
// Request only leaves for the current selected day
$sql .= " AND '".$db->escape($year)."-".$db->escape($month)."-".$db->escape($day)."' BETWEEN x.date_debut AND x.date_fin"; // date_debut and date_fin are date without time
$sql .= " AND '".$db->escape($year."-".$month."-".$day)."' BETWEEN x.date_debut AND x.date_fin"; // date_debut and date_fin are date without time
} elseif ($mode == 'show_week') {
// Restrict on current month (we get more, but we will filter later)
$sql .= " AND x.date_debut < '".$db->idate(dol_get_last_day($year, $month))."'";

View file

@ -1380,7 +1380,7 @@ class Account extends CommonObject
$sql .= " FROM ".MAIN_DB_PREFIX."bank";
$sql .= " WHERE fk_account = ".((int) $this->id);
if ($option == 1) {
$sql .= " AND ".$this->db->escape($field)." <= '".(!empty($date_end) ? $this->db->idate($date_end) : $this->db->idate(dol_now()))."'";
$sql .= " AND ".$this->db->sanitize($field)." <= '".(!empty($date_end) ? $this->db->idate($date_end) : $this->db->idate(dol_now()))."'";
}
$resql = $this->db->query($sql);

View file

@ -162,8 +162,8 @@ if ($result < 0) {
$sql .= ", ".MAIN_DB_PREFIX."bank_account as ba";
$sql .= " WHERE b.fk_account = ba.rowid";
$sql .= " AND ba.entity IN (".getEntity('bank_account').")";
$sql .= " AND b.datev >= '".$db->escape($year)."-".$db->escape($month)."-01 00:00:00'";
$sql .= " AND b.datev < '".$db->escape($yearnext)."-".$db->escape($monthnext)."-01 00:00:00'";
$sql .= " AND b.datev >= '".$db->escape($year."-".$month."-01 00:00:00")."'";
$sql .= " AND b.datev < '".$db->escape($yearnext."-".$monthnext."-01 00:00:00")."'";
if ($account && GETPOST("option") != 'all') {
$sql .= " AND b.fk_account IN (".$db->sanitize($account).")";
}
@ -617,8 +617,8 @@ if ($result < 0) {
$sql .= ", ".MAIN_DB_PREFIX."bank_account as ba";
$sql .= " WHERE b.fk_account = ba.rowid";
$sql .= " AND ba.entity IN (".getEntity('bank_account').")";
$sql .= " AND b.datev >= '".$db->escape($year)."-".$db->escape($month)."-01 00:00:00'";
$sql .= " AND b.datev < '".$db->escape($yearnext)."-".$db->escape($monthnext)."-01 00:00:00'";
$sql .= " AND b.datev >= '".$db->escape($year."-".$month."-01 00:00:00")."'";
$sql .= " AND b.datev < '".$db->escape($yearnext."-".$monthnext."-01 00:00:00")."'";
$sql .= " AND b.amount < 0";
if ($account && GETPOST("option") != 'all') {
$sql .= " AND b.fk_account IN (".$db->sanitize($account).")";

View file

@ -1128,12 +1128,12 @@ class BonPrelevement extends CommonObject
$error = 0;
// Pre-store some values into variables to simplify following sql requests
if ($sourcetype != 'salary') {
$entities = $type != 'bank-transfer' ? getEntity('invoice', 1) : getEntity('supplier_invoice', 1); // Return a list of entities
$entity = $type != 'bank-transfer' ? getEntity('invoice', 1) : getEntity('supplier_invoice', 1); // Return entity
$sqlTable = $type != 'bank-transfer' ? "facture" : "facture_fourn";
$socOrUser = 'fk_soc';
$societeOrUser = 'societe';
} else {
$entities = getEntity('salary', 1); // Return a list of entities
$entity = getEntity('salary', 1); // Return entity
$sqlTable = 'salary';
$socOrUser = 'fk_user';
$societeOrUser = 'user';
@ -1214,7 +1214,7 @@ class BonPrelevement extends CommonObject
// If we add a test on sr.default_rib = 1, we must also check we have a correct error management to stop if no default BAN is found.
// Also it may be found for on thirdparty and not for the other.
}
$sql .= " WHERE f.entity IN (".$this->db->escape($entities).')';
$sql .= " WHERE f.entity IN (".((int) $entity).')';
if ($sourcetype != 'salary') {
$sql .= " AND f.fk_statut = ".Facture::STATUS_VALIDATED; // Invoice validated
$sql .= " AND f.paye = 0";

View file

@ -8308,7 +8308,7 @@ abstract class CommonObject
// Note: $InfoFieldList can be 'sellist:TableName:LabelFieldName[:KeyFieldName[:KeyFieldParent[:Filter[:CategoryIdType[:CategoryIdList[:Sortfield]]]]]]'
if (isset($InfoFieldList[7]) && preg_match('/^[a-z0-9_\-,]+$/i', $InfoFieldList[7])) {
$sql .= " ORDER BY ".$this->db->escape($InfoFieldList[7]);
$sql .= " ORDER BY ".$this->db->sanitize($InfoFieldList[7]);
} else {
$sql .= " ORDER BY ".$this->db->sanitize(implode(', ', $fields_label));
}
@ -11109,7 +11109,7 @@ abstract class CommonObject
$sql = "SELECT ".$objectline->getFieldList('l');
$sql .= " FROM ".$this->db->prefix().$objectline->table_element." as l";
$sql .= " WHERE l.fk_".$this->db->escape($this->element)." = ".((int) $this->id);
$sql .= " WHERE l.fk_".$this->db->sanitize($this->element)." = ".((int) $this->id);
if ($morewhere) {
$sql .= $morewhere;
}
@ -11918,7 +11918,7 @@ abstract class CommonObject
// Delete ecm_files_extrafields with mode 0 (using name)
$sql = "DELETE FROM ".$this->db->prefix()."ecm_files_extrafields WHERE fk_object IN (";
$sql .= " SELECT rowid FROM ".$this->db->prefix()."ecm_files WHERE filename LIKE '".$this->db->escape($this->ref)."%'";
$sql .= " AND filepath = '".$this->db->escape($element)."/".$this->db->escape($this->ref)."' AND entity = ".((int) $conf->entity); // No need of getEntity here
$sql .= " AND filepath = '".$this->db->escape($element."/".$this->ref)."' AND entity = ".((int) $conf->entity); // No need of getEntity here
$sql .= ")";
if (!$this->db->query($sql)) {
@ -11930,7 +11930,7 @@ abstract class CommonObject
// Delete ecm_files with mode 0 (using name)
$sql = "DELETE FROM ".$this->db->prefix()."ecm_files";
$sql .= " WHERE filename LIKE '".$this->db->escape($this->ref)."%'";
$sql .= " AND filepath = '".$this->db->escape($element)."/".$this->db->escape($this->ref)."' AND entity = ".((int) $conf->entity); // No need of getEntity here
$sql .= " AND filepath = '".$this->db->escape($element."/".$this->ref)."' AND entity = ".((int) $conf->entity); // No need of getEntity here
if (!$this->db->query($sql)) {
$this->error = $this->db->lasterror();

View file

@ -2133,7 +2133,7 @@ function show_actions_done($conf, $langs, $db, $filterobj, $objcon = null, $nopr
&& $filterobj->table_element && $filterobj->element
) {
// Generic case (if there is a $filterobj and a field rowid and (ref or label) exists.
$sql .= " AND a.fk_element = o.rowid AND a.elementtype = '" . $db->escape($filterobj->element) . ($module ? "@" . $db->escape($module) : "") . "'";
$sql .= " AND a.fk_element = o.rowid AND a.elementtype = '" . $db->escape($filterobj->element. ($module ? "@" . $module : "")) . "'";
if ($filterobj->id) {
$sql .= " AND a.fk_element = " . ((int) $filterobj->id);
}

View file

@ -398,18 +398,18 @@ function dolSqlDateFilter($datefield, $day_date, $month_date, $year_date, $exclu
return " AND 1 = 2";
}
if ($year_date > 0 && empty($day_date)) {
$sqldate .= ($excludefirstand ? "" : " AND ").$sql_datefield." BETWEEN '".$db->idate(dol_get_first_day($year_date, $month_date, $gm));
$sqldate .= "' AND '".$db->idate(dol_get_last_day($year_date, $month_date, $gm))."'";
$sqldate .= ($excludefirstand ? "" : " AND ").$sql_datefield." BETWEEN '".$db->idate(dol_get_first_day($year_date, $month_date, $gm))."'";
$sqldate .= " AND '".$db->idate(dol_get_last_day($year_date, $month_date, $gm))."'";
} elseif ($year_date > 0 && !empty($day_date)) {
$sqldate .= ($excludefirstand ? "" : " AND ").$sql_datefield." BETWEEN '".$db->idate(dol_mktime(0, 0, 0, $month_date, $day_date, $year_date, $gm));
$sqldate .= "' AND '".$db->idate(dol_mktime(23, 59, 59, $month_date, $day_date, $year_date, $gm))."'";
$sqldate .= ($excludefirstand ? "" : " AND ").$sql_datefield." BETWEEN '".$db->idate(dol_mktime(0, 0, 0, $month_date, $day_date, $year_date, $gm))."'";
$sqldate .= " AND '".$db->idate(dol_mktime(23, 59, 59, $month_date, $day_date, $year_date, $gm))."'";
} else {
// This case is not reliable on TZ, but we should not need it.
$sqldate .= ($excludefirstand ? "" : " AND ")." date_format( ".$sql_datefield.", '%c') = '".$db->escape((string) $month_date)."'";
}
} elseif ($year_date > 0) {
$sqldate .= ($excludefirstand ? "" : " AND ").$sql_datefield." BETWEEN '".$db->idate(dol_get_first_day($year_date, 1, $gm));
$sqldate .= "' AND '".$db->idate(dol_get_last_day($year_date, 12, $gm))."'";
$sqldate .= ($excludefirstand ? "" : " AND ").$sql_datefield." BETWEEN '".$db->idate(dol_get_first_day($year_date, 1, $gm))."'";
$sqldate .= " AND '".$db->idate(dol_get_last_day($year_date, 12, $gm))."'";
}
return $sqldate;
}

View file

@ -2707,8 +2707,8 @@ function print_projecttasks_array($db, $form, $socid, $projectsListId, $mytasks
if (empty($project_year_filter) || !is_numeric($project_year_filter)) {
$project_year_filter = date("Y");
}
$sql .= " AND (p.dateo IS NULL OR p.dateo <= ".$db->idate(dol_get_last_day((int) $project_year_filter, 12, false)).")";
$sql .= " AND (p.datee IS NULL OR p.datee >= ".$db->idate(dol_get_first_day((int) $project_year_filter, 1, false)).")";
$sql .= " AND (p.dateo IS NULL OR p.dateo <= '".$db->idate(dol_get_last_day((int) $project_year_filter, 12, false))."')";
$sql .= " AND (p.datee IS NULL OR p.datee >= '".$db->idate(dol_get_first_day((int) $project_year_filter, 1, false))."')";
}
}

View file

@ -3,7 +3,7 @@
* Copyright (C) 2021 Florian Henry <florian.henry@scopen.fr>
* Copyright (C) 2023-2024 Frédéric France <frederic.france@free.fr>
* Copyright (C) 2024 Alexandre Spangaro <alexandre@inovea-conseil.com>
* Copyright (C) 2025 MDW <mdeweerd@users.noreply.github.com>
* Copyright (C) 2025-2026 MDW <mdeweerd@users.noreply.github.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -713,10 +713,10 @@ foreach ($search as $key => $val) {
$columnName = preg_replace('/(_dtstart|_dtend)$/', '', $key);
if (preg_match('/^(date|timestamp|datetime)/', $object->fields[$columnName]['type'])) {
if (preg_match('/_dtstart$/', $key)) {
$sql .= " AND t.".$db->escape($columnName)." >= '".$db->idate($search[$key])."'";
$sql .= " AND t.".$db->sanitize($columnName)." >= '".$db->idate($search[$key])."'";
}
if (preg_match('/_dtend$/', $key)) {
$sql .= " AND t.".$db->escape($columnName)." <= '".$db->idate($search[$key])."'";
$sql .= " AND t.".$db->sanitize($columnName)." <= '".$db->idate($search[$key])."'";
}
}
}

View file

@ -3,7 +3,7 @@
* Copyright (C) 2021 Florian Henry <florian.henry@scopen.fr>
* Copyright (C) 2024 Alexandre Spangaro <alexandre@inovea-conseil.com>
* Copyright (C) 2024 Frédéric France <frederic.france@free.fr>
* Copyright (C) 2025 MDW <mdeweerd@users.noreply.github.com>
* Copyright (C) 2025-2026 MDW <mdeweerd@users.noreply.github.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -342,10 +342,10 @@ foreach ($search as $key => $val) {
$columnName = preg_replace('/(_dtstart|_dtend)$/', '', $key);
if (preg_match('/^(date|timestamp|datetime)/', $object->fields[$columnName]['type'])) {
if (preg_match('/_dtstart$/', $key)) {
$sql .= " AND t.".$db->escape($columnName)." >= '".$db->idate($search[$key])."'";
$sql .= " AND t.".$db->sanitize($columnName)." >= '".$db->idate($search[$key])."'";
}
if (preg_match('/_dtend$/', $key)) {
$sql .= " AND t.".$db->escape($columnName)." <= '".$db->idate($search[$key])."'";
$sql .= " AND t.".$db->sanitize($columnName)." <= '".$db->idate($search[$key])."'";
}
}
}

View file

@ -15,7 +15,7 @@
* Copyright (C) 2019-2026 Alexandre Spangaro <alexandre@inovea-conseil.com>
* Copyright (C) 2023 Nick Fragoulis
* Copyright (C) 2023 Joachim Kueter <git-jk@bloxera.com>
* Copyright (C) 2024-2025 MDW <mdeweerd@users.noreply.github.com>
* Copyright (C) 2024-2026 MDW <mdeweerd@users.noreply.github.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -870,7 +870,7 @@ if ($filter && $filter != -1) {
$aFilter = explode(',', $filter);
foreach ($aFilter as $fil) {
$filt = explode(':', $fil);
$sql .= " AND ".$db->escape(trim($filt[0]))." = '".$db->escape(trim($filt[1]))."'";
$sql .= " AND ".$db->sanitize(trim($filt[0]))." = '".$db->escape(trim($filt[1]))."'";
}
}

View file

@ -5,7 +5,7 @@
* Copyright (C) 2021 Jean-Pascal BOUDET <jean-pascal.boudet@atm-consulting.fr>
* Copyright (C) 2021 Grégory BLEMAND <gregory.blemand@atm-consulting.fr>
* Copyright (C) 2024 Frédéric France <frederic.france@free.fr>
* Copyright (C) 2025 MDW <mdeweerd@users.noreply.github.com>
* Copyright (C) 2025-2026 MDW <mdeweerd@users.noreply.github.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -280,10 +280,10 @@ foreach ($search as $key => $val) {
$columnName = preg_replace('/(_dtstart|_dtend)$/', '', $key);
if (preg_match('/^(date|timestamp|datetime)/', $object->fields[$columnName]['type'])) {
if (preg_match('/_dtstart$/', $key)) {
$sql .= " AND t.".$db->escape($columnName)." >= '".$db->idate($search[$key])."'";
$sql .= " AND t.".$db->sanitize($columnName)." >= '".$db->idate($search[$key])."'";
}
if (preg_match('/_dtend$/', $key)) {
$sql .= " AND t.".$db->escape($columnName)." <= '".$db->idate($search[$key])."'";
$sql .= " AND t.".$db->sanitize($columnName)." <= '".$db->idate($search[$key])."'";
}
}
}

View file

@ -5,7 +5,7 @@
* Copyright (C) 2021 Jean-Pascal BOUDET <jean-pascal.boudet@atm-consulting.fr>
* Copyright (C) 2021 Grégory BLEMAND <gregory.blemand@atm-consulting.fr>
* Copyright (C) 2024 Frédéric France <frederic.france@free.fr>
* Copyright (C) 2025 MDW <mdeweerd@users.noreply.github.com>
* Copyright (C) 2025-2026 MDW <mdeweerd@users.noreply.github.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -287,10 +287,10 @@ foreach ($search as $key => $val) {
$columnName = preg_replace('/(_dtstart|_dtend)$/', '', $key);
if (preg_match('/^(date|timestamp|datetime)/', $object->fields[$columnName]['type'])) {
if (preg_match('/_dtstart$/', $key)) {
$sql .= " AND t.".$db->escape($columnName)." >= '".$db->idate($search[$key])."'";
$sql .= " AND t.".$db->sanitize($columnName)." >= '".$db->idate($search[$key])."'";
}
if (preg_match('/_dtend$/', $key)) {
$sql .= " AND t.".$db->escape($columnName)." <= '".$db->idate($search[$key])."'";
$sql .= " AND t.".$db->sanitize($columnName)." <= '".$db->idate($search[$key])."'";
}
}
}

View file

@ -473,7 +473,7 @@ class IntracommReport extends CommonObject
, c.code
, ext.mode_transport
FROM ".MAIN_DB_PREFIX.$tabledet." l
INNER JOIN ".MAIN_DB_PREFIX.$table." f ON (f.rowid = l.".$this->db->escape($field_link).")
INNER JOIN ".MAIN_DB_PREFIX.$table." f ON (f.rowid = l.".$this->db->sanitize($field_link).")
LEFT JOIN ".MAIN_DB_PREFIX.$table_extraf." ext ON (ext.fk_object = f.rowid)
INNER JOIN ".MAIN_DB_PREFIX."product p ON (p.rowid = l.fk_product)
INNER JOIN ".MAIN_DB_PREFIX."societe s ON (s.rowid = f.fk_soc)
@ -569,7 +569,7 @@ class IntracommReport extends CommonObject
foreach ($TLinesFraisDePort as $res) {
$sql = "SELECT p.customcode
FROM ".MAIN_DB_PREFIX.$tabledet." d
INNER JOIN ".MAIN_DB_PREFIX.$table." f ON (f.rowid = d.".$this->db->escape($field_link).")
INNER JOIN ".MAIN_DB_PREFIX.$table." f ON (f.rowid = d.".$this->db->sanitize($field_link).")
INNER JOIN ".MAIN_DB_PREFIX."product p ON (p.rowid = d.fk_product)
WHERE d.fk_product IS NOT NULL
AND f.entity = ".((int) $conf->entity)."
@ -578,7 +578,7 @@ class IntracommReport extends CommonObject
(
SELECT MAX(d.total_ht)
FROM ".MAIN_DB_PREFIX.$tabledet." d
INNER JOIN ".MAIN_DB_PREFIX.$table." f ON (f.rowid = d.".$this->db->escape($field_link).")
INNER JOIN ".MAIN_DB_PREFIX.$table." f ON (f.rowid = d.".$this->db->sanitize($field_link).")
WHERE d.fk_product IS NOT NULL
AND ".$more_sql." = '".$this->db->escape($res->refinvoice)."'
AND d.fk_product NOT IN

View file

@ -2,7 +2,7 @@
/* Copyright (C) 2007-2023 Laurent Destailleur <eldy@users.sourceforge.net>
* Copyright (C) 2021-2024 Frédéric France <frederic.france@free.fr>
* Copyright (C) 2023 Anthony Berton <anthony.berton@bb2a.fr>
* Copyright (C) 2025 MDW <mdeweerd@users.noreply.github.com>
* Copyright (C) 2025-2026 MDW <mdeweerd@users.noreply.github.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -284,10 +284,10 @@ foreach ($search as $key => $val) {
$columnName = preg_replace('/(_dtstart|_dtend)$/', '', $key);
if (preg_match('/^(date|timestamp|datetime)/', $object->fields[$columnName]['type'])) {
if (preg_match('/_dtstart$/', $key)) {
$sql .= " AND t.".$db->escape($columnName)." >= '".$db->idate($search[$key])."'";
$sql .= " AND t.".$db->sanitize($columnName)." >= '".$db->idate($search[$key])."'";
}
if (preg_match('/_dtend$/', $key)) {
$sql .= " AND t.".$db->escape($columnName)." <= '".$db->idate($search[$key])."'";
$sql .= " AND t.".$db->sanitize($columnName)." <= '".$db->idate($search[$key])."'";
}
}
}

View file

@ -415,10 +415,10 @@ foreach ($search as $key => $val) {
$columnName = preg_replace('/(_dtstart|_dtend)$/', '', $key);
if (preg_match('/^(date|timestamp|datetime)/', $object->fields[$columnName]['type'])) {
if (preg_match('/_dtstart$/', $key)) {
$sql .= " AND t.".$db->escape($columnName)." >= '".$db->idate($search[$key])."'";
$sql .= " AND t.".$db->sanitize($columnName)." >= '".$db->idate($search[$key])."'";
}
if (preg_match('/_dtend$/', $key)) {
$sql .= " AND t.".$db->escape($columnName)." <= '".$db->idate($search[$key])."'";
$sql .= " AND t.".$db->sanitize($columnName)." <= '".$db->idate($search[$key])."'";
}
}
}

View file

@ -1,7 +1,7 @@
<?php
/* Copyright (C) 2007-2017 Laurent Destailleur <eldy@users.sourceforge.net>
* Copyright (C) 2024 Frédéric France <frederic.france@free.fr>
* Copyright (C) 2025 MDW <mdeweerd@users.noreply.github.com>
* Copyright (C) 2025-2026 MDW <mdeweerd@users.noreply.github.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -269,10 +269,10 @@ foreach ($search as $key => $val) {
$columnName = preg_replace('/(_dtstart|_dtend)$/', '', $key);
if (preg_match('/^(date|timestamp|datetime)/', $object->fields[$columnName]['type'])) {
if (preg_match('/_dtstart$/', $key)) {
$sql .= " AND t.".$db->escape($columnName)." >= '".$db->idate($search[$key])."'";
$sql .= " AND t.".$db->sanitize($columnName)." >= '".$db->idate($search[$key])."'";
}
if (preg_match('/_dtend$/', $key)) {
$sql .= " AND t.".$db->escape($columnName)." <= '".$db->idate($search[$key])."'";
$sql .= " AND t.".$db->sanitize($columnName)." <= '".$db->idate($search[$key])."'";
}
}
}

View file

@ -365,10 +365,10 @@ foreach ($search as $key => $val) {
$columnName = preg_replace('/(_dtstart|_dtend)$/', '', $key);
if ($columnName == 'eatby' || $columnName == 'sellby') {
if (preg_match('/_dtstart$/', $key)) {
$sql .= " AND pl.".$db->escape($columnName)." >= '".$db->idate($search[$key])."'";
$sql .= " AND pl.".$db->sanitize($columnName)." >= '".$db->idate($search[$key])."'";
}
if (preg_match('/_dtend$/', $key)) {
$sql .= " AND pl.".$db->escape($columnName)." <= '".$db->idate($search[$key])."'";
$sql .= " AND pl.".$db->sanitize($columnName)." <= '".$db->idate($search[$key])."'";
}
}
}

View file

@ -4,7 +4,7 @@
* Copyright (C) 2005-2014 Regis Houssin <regis.houssin@inodbox.com>
* Copyright (C) 2015 Juanjo Menent <jmenent@2byte.es>
* Copyright (C) 2020 Tobias Sekan <tobias.sekan@startmail.com>
* Copyright (C) 2024-2025 MDW <mdeweerd@users.noreply.github.com>
* Copyright (C) 2024-2026 MDW <mdeweerd@users.noreply.github.com>
* Copyright (C) 2024 Frédéric France <frederic.france@free.fr>
*
* This program is free software; you can redistribute it and/or modify
@ -288,10 +288,10 @@ foreach ($search as $key => $val) {
$columnName = preg_replace('/(_dtstart|_dtend)$/', '', $key);
if (preg_match('/^(date|timestamp|datetime)/', $object->fields[$columnName]['type'])) {
if (preg_match('/_dtstart$/', $key)) {
$sql .= " AND t.".$db->escape($columnName)." >= '".$db->idate((int) $search[$key])."'";
$sql .= " AND t.".$db->sanitize($columnName)." >= '".$db->idate((int) $search[$key])."'";
}
if (preg_match('/_dtend$/', $key)) {
$sql .= " AND t.".$db->escape($columnName)." <= '".$db->idate((int) $search[$key])."'";
$sql .= " AND t.".$db->sanitize($columnName)." <= '".$db->idate((int) $search[$key])."'";
}
}
}
@ -340,7 +340,7 @@ $sql .= $hookmanager->resPrint;
$sql .= " GROUP BY ";
foreach ($object->fields as $key => $val) {
$sql .= "t.".$db->escape($key).", ";
$sql .= "t.".$db->sanitize($key).", ";
}
// Add fields from extrafields
if (!empty($extrafields->attributes[$object->table_element]['label'])) {

View file

@ -2,7 +2,7 @@
/* Copyright (C) 2007-2016 Laurent Destailleur <eldy@users.sourceforge.net>
* Copyright (C) 2018-2021 Ferran Marcet <fmarcet@2byte.es>
* Copyright (C) 2019-2026 Frédéric France <frederic.france@free.fr>
* Copyright (C) 2025 MDW <mdeweerd@users.noreply.github.com>
* Copyright (C) 2025-2026 MDW <mdeweerd@users.noreply.github.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -276,10 +276,10 @@ foreach ($search as $key => $val) {
$columnName = preg_replace('/(_dtstart|_dtend)$/', '', $key);
if (preg_match('/^(date|timestamp|datetime)/', $object->fields[$columnName]['type'])) {
if (preg_match('/_dtstart$/', $key)) {
$sql .= " AND t.".$db->escape($columnName)." >= '".$db->idate($search[$key])."'";
$sql .= " AND t.".$db->sanitize($columnName)." >= '".$db->idate($search[$key])."'";
}
if (preg_match('/_dtend$/', $key)) {
$sql .= " AND t.".$db->escape($columnName)." <= '".$db->idate($search[$key])."'";
$sql .= " AND t.".$db->sanitize($columnName)." <= '".$db->idate($search[$key])."'";
}
}
}

View file

@ -2,7 +2,7 @@
/* Copyright (C) 2007-2017 Laurent Destailleur <eldy@users.sourceforge.net>
* Copyright (C) 2021 Gauthier VERDOL <gauthier.verdol@atm-consulting.fr>
* Copyright (C) 2024 Frédéric France <frederic.france@free.fr>
* Copyright (C) 2025 MDW <mdeweerd@users.noreply.github.com>
* Copyright (C) 2025-2026 MDW <mdeweerd@users.noreply.github.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -267,10 +267,10 @@ foreach ($search as $key => $val) {
$columnName = preg_replace('/(_dtstart|_dtend)$/', '', $key);
if (preg_match('/^(date|timestamp|datetime)/', $object->fields[$columnName]['type'])) {
if (preg_match('/_dtstart$/', $key)) {
$sql .= " AND t.".$db->escape($columnName)." >= '".$db->idate($search[$key])."'";
$sql .= " AND t.".$db->sanitize($columnName)." >= '".$db->idate($search[$key])."'";
}
if (preg_match('/_dtend$/', $key)) {
$sql .= " AND t.".$db->escape($columnName)." <= '".$db->idate($search[$key])."'";
$sql .= " AND t.".$db->sanitize($columnName)." <= '".$db->idate($search[$key])."'";
}
}
}

View file

@ -2285,7 +2285,7 @@ class Task extends CommonObjectLine
if (!$error) {
$sql = "UPDATE ".MAIN_DB_PREFIX."projet_task";
$sql .= " SET duration_effective = duration_effective - ".$this->db->escape($this->timespent_duration ? (string) $this->timespent_duration : '0');
$sql .= " SET duration_effective = duration_effective - ".((int) $this->timespent_duration);
$sql .= " WHERE rowid = ".((int) $this->id);
dol_syslog(get_class($this)."::delTimeSpent", LOG_DEBUG);

View file

@ -1,7 +1,7 @@
<?php
/* Copyright (C) 2007-2017 Laurent Destailleur <eldy@users.sourceforge.net>
* Copyright (C) 2024-2025 Frédéric France <frederic.france@free.fr>
* Copyright (C) 2024-2025 MDW <mdeweerd@users.noreply.github.com>
* Copyright (C) 2024-2026 MDW <mdeweerd@users.noreply.github.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -279,10 +279,10 @@ foreach ($search as $key => $val) {
$columnName = preg_replace('/(_dtstart|_dtend)$/', '', $key);
if (preg_match('/^(date|timestamp|datetime)/', $object->fields[$columnName]['type'])) {
if (preg_match('/_dtstart$/', $key)) {
$sql .= " AND t.".$db->escape($columnName)." >= '".$db->idate($search[$key])."'";
$sql .= " AND t.".$db->sanitize($columnName)." >= '".$db->idate($search[$key])."'";
}
if (preg_match('/_dtend$/', $key)) {
$sql .= " AND t.".$db->escape($columnName)." <= '" . $db->idate($search[$key])."'";
$sql .= " AND t.".$db->sanitize($columnName)." <= '" . $db->idate($search[$key])."'";
}
}
}

View file

@ -1,7 +1,7 @@
<?php
/* Copyright (C) 2007-2017 Laurent Destailleur <eldy@users.sourceforge.net>
* Copyright (C) 2024 Frédéric France <frederic.france@free.fr>
* Copyright (C) 2025 MDW <mdeweerd@users.noreply.github.com>
* Copyright (C) 2025-2026 MDW <mdeweerd@users.noreply.github.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -253,17 +253,17 @@ foreach ($search as $key => $val) {
$mode_search = 2;
}
if ($search[$key] != '') {
$sql .= natural_search("t.".$db->escape($key), $search[$key], (($key == 'status') ? 2 : $mode_search));
$sql .= natural_search("t.".$db->sanitize($key), $search[$key], (($key == 'status') ? 2 : $mode_search));
}
} else {
if (preg_match('/(_dtstart|_dtend)$/', $key) && $search[$key] != '') {
$columnName = preg_replace('/(_dtstart|_dtend)$/', '', $key);
if (preg_match('/^(date|timestamp|datetime)/', $object->fields[$columnName]['type'])) {
if (preg_match('/_dtstart$/', $key)) {
$sql .= " AND t.".$db->escape($columnName)." >= '".$db->idate($search[$key])."'";
$sql .= " AND t.".$db->sanitize($columnName)." >= '".$db->idate($search[$key])."'";
}
if (preg_match('/_dtend$/', $key)) {
$sql .= " AND t.".$db->escape($columnName)." <= '" . $db->idate($search[$key])."'";
$sql .= " AND t.".$db->sanitize($columnName)." <= '" . $db->idate($search[$key])."'";
}
}
}
@ -283,7 +283,7 @@ $sql .= $hookmanager->resPrint;
/* If a group by is required */
$sql .= " GROUP BY ";
foreach ($object->fields as $key => $val) {
$sql .= "t.".$db->escape($key).", ";
$sql .= "t.".$db->sanitize($key).", ";
}
// Add fields from extrafields
if (!empty($extrafields->attributes[$object->table_element]['label'])) {

View file

@ -1,7 +1,7 @@
<?php
/* Copyright (C) 2007-2017 Laurent Destailleur <eldy@users.sourceforge.net>
* Copyright (C) 2024-2026 Frédéric France <frederic.france@free.fr>
* Copyright (C) 2025 MDW <mdeweerd@users.noreply.github.com>
* Copyright (C) 2025-2026 MDW <mdeweerd@users.noreply.github.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -275,10 +275,10 @@ foreach ($search as $key => $val) {
$columnName = preg_replace('/(_dtstart|_dtend)$/', '', $key);
if (preg_match('/^(date|timestamp|datetime)/', $object->fields[$columnName]['type'])) {
if (preg_match('/_dtstart$/', $key)) {
$sql .= " AND t.".$db->escape($columnName)." >= '".$db->idate($search[$key])."'";
$sql .= " AND t.".$db->sanitize($columnName)." >= '".$db->idate($search[$key])."'";
}
if (preg_match('/_dtend$/', $key)) {
$sql .= " AND t.".$db->escape($columnName)." <= '".$db->idate($search[$key])."'";
$sql .= " AND t.".$db->sanitize($columnName)." <= '".$db->idate($search[$key])."'";
}
}
}

View file

@ -2,7 +2,7 @@
/* Copyright (C) 2007-2017 Laurent Destailleur <eldy@users.sourceforge.net>
* Copyright (C) 2020 Gauthier VERDOL <gauthier.verdol@atm-consulting.fr>
* Copyright (C) 2024-2025 MDW <mdeweerd@users.noreply.github.com>
* Copyright (C) 2024-2026 MDW <mdeweerd@users.noreply.github.com>
* Copyright (C) 2024-2026 Frédéric France <frederic.france@free.fr>
*
* This program is free software; you can redistribute it and/or modify
@ -287,17 +287,17 @@ foreach ($search as $key => $val) {
$mode_search = 2;
}
if ($search[$key] != '') {
$sql .= natural_search("t.".$db->escape($key), $search[$key], (($key == 'status') ? 2 : $mode_search));
$sql .= natural_search("t.".$db->sanitize($key), $search[$key], (($key == 'status') ? 2 : $mode_search));
}
} else {
if (preg_match('/(_dtstart|_dtend)$/', $key) && $search[$key] != '') {
$columnName = preg_replace('/(_dtstart|_dtend)$/', '', $key);
if (preg_match('/^(date|timestamp|datetime)/', $object->fields[$columnName]['type'])) {
if (preg_match('/_dtstart$/', $key)) {
$sql .= " AND t.".$db->escape($columnName)." >= '".$db->idate($search[$key])."'";
$sql .= " AND t.".$db->sanitize($columnName)." >= '".$db->idate($search[$key])."'";
}
if (preg_match('/_dtend$/', $key)) {
$sql .= " AND t.".$db->escape($columnName)." <= '".$db->idate($search[$key])."'";
$sql .= " AND t.".$db->sanitize($columnName)." <= '".$db->idate($search[$key])."'";
}
}
}
@ -327,7 +327,7 @@ $sql .= $hookmanager->resPrint;
$sql .= " GROUP BY ";
foreach ($object->fields as $key => $val) {
$sql .= "t.".$db->escape($key).", ";
$sql .= "t.".$db->sanitize($key).", ";
}
// Add fields from extrafields
if (! empty($extrafields->attributes[$object->table_element]['label'])) {