From ce010a54c7315b5a890fa39cb01bc88c734758c4 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Tue, 5 Mar 2024 00:15:33 +0100 Subject: [PATCH] Clean code and prepare a more powerfull phpunit check for sql forging. --- ChangeLog | 1 + htdocs/accountancy/admin/accountmodel.php | 18 +-- htdocs/accountancy/admin/categories_list.php | 30 ++--- htdocs/accountancy/admin/journals_list.php | 22 ++-- htdocs/accountancy/admin/productaccount.php | 14 +-- htdocs/accountancy/bookkeeping/export.php | 2 +- .../class/accountancycategory.class.php | 12 +- .../class/accountingaccount.class.php | 4 +- .../class/accountingjournal.class.php | 21 ++-- .../accountancy/class/bookkeeping.class.php | 16 +-- htdocs/accountancy/class/lettering.class.php | 28 ++--- htdocs/accountancy/customer/index.php | 30 ++--- htdocs/accountancy/customer/lines.php | 2 +- htdocs/accountancy/expensereport/index.php | 10 +- htdocs/accountancy/supplier/index.php | 10 +- htdocs/adherents/card.php | 3 +- htdocs/adherents/class/adherent.class.php | 12 +- .../adherents/class/adherent_type.class.php | 4 +- htdocs/adherents/class/subscription.class.php | 2 +- htdocs/admin/dict.php | 8 +- htdocs/admin/emailcollector_list.php | 2 +- htdocs/asset/class/asset.class.php | 42 +++---- htdocs/asset/class/assetmodel.class.php | 43 +++---- htdocs/bom/bom_list.php | 6 +- htdocs/bom/class/bom.class.php | 24 ++-- htdocs/bookcal/class/availabilities.class.php | 42 +++---- htdocs/bookcal/class/calendar.class.php | 42 +++---- htdocs/categories/class/categorie.class.php | 42 +++---- htdocs/compta/facture/class/facture.class.php | 24 ++-- htdocs/core/boxes/modules_boxes.php | 5 +- htdocs/core/class/commonobject.class.php | 37 +++--- htdocs/core/class/timespent.class.php | 42 +++---- htdocs/core/lib/functions.lib.php | 3 + htdocs/core/modules/DolibarrModules.class.php | 4 +- htdocs/core/modules/modBookCal.class.php | 8 +- htdocs/hrm/class/evaluation.class.php | 30 ++--- htdocs/hrm/class/evaluationdet.class.php | 30 ++--- htdocs/hrm/class/job.class.php | 30 ++--- htdocs/hrm/class/position.class.php | 30 ++--- htdocs/hrm/class/skill.class.php | 30 ++--- htdocs/hrm/class/skilldet.class.php | 30 ++--- htdocs/hrm/class/skillrank.class.php | 30 ++--- htdocs/install/upgrade2.php | 116 +++++------------- htdocs/langs/en_US/orders.lang | 2 +- .../mailmanspip/class/mailmanspip.class.php | 7 +- .../template/class/myobject.class.php | 52 +------- .../class/partnership_type.class.php | 40 +++--- htdocs/product/class/product.class.php | 4 +- htdocs/product/class/productbatch.class.php | 3 +- .../class/stocktransfer.class.php | 42 +++---- .../class/stocktransferline.class.php | 40 +++--- htdocs/webhook/class/target.class.php | 33 ++--- htdocs/website/class/websitepage.class.php | 56 +++------ test/phpunit/CodingPhpTest.php | 48 +++++++- 54 files changed, 504 insertions(+), 764 deletions(-) diff --git a/ChangeLog b/ChangeLog index 2a78269244d..278fc2984c0 100644 --- a/ChangeLog +++ b/ChangeLog @@ -25,6 +25,7 @@ The following changes may create regressions for some external modules, but were * Properties ->date_update and ->date_modification were merged into date_modification. * All CLI tools (into /scripts) return a positive value to the shell if error (0 remains success) for a better cross platform compatibility. On linux the exit(-1) was caught as 255, it may be now exit(1) so will be caught as 1. +* the parameter $filter of method fetchAll does not accept array of SQL but must be a string of an Universal Search Filter syntax. ***** ChangeLog for 19.0.1 compared to 19.0.0 ***** diff --git a/htdocs/accountancy/admin/accountmodel.php b/htdocs/accountancy/admin/accountmodel.php index 8ff908b61e8..8523baecacc 100644 --- a/htdocs/accountancy/admin/accountmodel.php +++ b/htdocs/accountancy/admin/accountmodel.php @@ -194,7 +194,7 @@ if (GETPOST('actionadd', 'alpha') || GETPOST('actionmodify', 'alpha')) { if ($tabrowid[$id]) { // Get free id for insert $newid = 0; - $sql = "SELECT MAX(".$tabrowid[$id].") newid from ".$tabname[$id]; + $sql = "SELECT MAX(".$db->sanitize($tabrowid[$id]).") newid FROM ".$db->sanitize($tabname[$id]); $result = $db->query($sql); if ($result) { $obj = $db->fetch_object($result); @@ -205,12 +205,12 @@ if (GETPOST('actionadd', 'alpha') || GETPOST('actionmodify', 'alpha')) { } // Add new entry - $sql = "INSERT INTO ".$tabname[$id]." ("; + $sql = "INSERT INTO ".$db->sanitize($tabname[$id])." ("; // List of fields if ($tabrowid[$id] && !in_array($tabrowid[$id], $listfieldinsert)) { - $sql .= $tabrowid[$id].","; + $sql .= $db->sanitize($tabrowid[$id]).","; } - $sql .= $tabfieldinsert[$id]; + $sql .= $db->sanitize($tabfieldinsert[$id]); $sql .= ",active)"; $sql .= " VALUES("; @@ -260,10 +260,10 @@ if (GETPOST('actionadd', 'alpha') || GETPOST('actionmodify', 'alpha')) { } // Modify entry - $sql = "UPDATE ".$tabname[$id]." SET "; + $sql = "UPDATE ".$db->sanitize($tabname[$id])." SET "; // Modifie valeur des champs if ($tabrowid[$id] && !in_array($tabrowid[$id], $listfieldmodify)) { - $sql .= $tabrowid[$id]."="; + $sql .= $db->sanitize($tabrowid[$id])." = "; $sql .= "'".$db->escape($rowid)."', "; } $i = 0; @@ -302,7 +302,7 @@ if ($action == 'confirm_delete' && $confirm == 'yes') { // delete $rowidcol = "rowid"; } - $sql = "DELETE from ".$tabname[$id]." WHERE ".$rowidcol." = ".((int) $rowid); + $sql = "DELETE from ".$db->sanitize($tabname[$id])." WHERE ".$db->sanitize($rowidcol)." = ".((int) $rowid); dol_syslog("delete", LOG_DEBUG); $result = $db->query($sql); @@ -317,7 +317,7 @@ if ($action == 'confirm_delete' && $confirm == 'yes') { // delete // activate if ($action == 'activate') { - $sql = "UPDATE ".$tabname[$id]." SET active = 1 WHERE rowid = ".((int) $rowid); + $sql = "UPDATE ".$db->sanitize($tabname[$id])." SET active = 1 WHERE rowid = ".((int) $rowid); $result = $db->query($sql); if (!$result) { dol_print_error($db); @@ -326,7 +326,7 @@ if ($action == 'activate') { // disable if ($action == $acts[1]) { - $sql = "UPDATE ".$tabname[$id]." SET active = 0 WHERE rowid = ".((int) $rowid); + $sql = "UPDATE ".$db->sanitize($tabname[$id])." SET active = 0 WHERE rowid = ".((int) $rowid); $result = $db->query($sql); if (!$result) { dol_print_error($db); diff --git a/htdocs/accountancy/admin/categories_list.php b/htdocs/accountancy/admin/categories_list.php index 848b6f14d52..5f6959cccd8 100644 --- a/htdocs/accountancy/admin/categories_list.php +++ b/htdocs/accountancy/admin/categories_list.php @@ -202,7 +202,7 @@ if (GETPOST('actionadd', 'alpha') || GETPOST('actionmodify', 'alpha')) { if ($tabrowid[$id]) { // Get free id for insert $newid = 0; - $sql = "SELECT MAX(".$tabrowid[$id].") newid from ".$tabname[$id]; + $sql = "SELECT MAX(".$db->sanitize($tabrowid[$id]).") newid FROM ".$db->sanitize($tabname[$id]); $result = $db->query($sql); if ($result) { $obj = $db->fetch_object($result); @@ -213,12 +213,12 @@ if (GETPOST('actionadd', 'alpha') || GETPOST('actionmodify', 'alpha')) { } // Add new entry - $sql = "INSERT INTO ".$tabname[$id]." ("; + $sql = "INSERT INTO ".$db->sanitize($tabname[$id])." ("; // List of fields if ($tabrowid[$id] && !in_array($tabrowid[$id], $listfieldinsert)) { - $sql .= $tabrowid[$id].","; + $sql .= $db->sanitize($tabrowid[$id]).","; } - $sql .= $tabfieldinsert[$id]; + $sql .= $db->sanitize($tabfieldinsert[$id]); $sql .= ",active)"; $sql .= " VALUES("; @@ -266,10 +266,10 @@ if (GETPOST('actionadd', 'alpha') || GETPOST('actionmodify', 'alpha')) { } // Modify entry - $sql = "UPDATE ".$tabname[$id]." SET "; + $sql = "UPDATE ".$db->sanitize($tabname[$id])." SET "; // Modifie valeur des champs if ($tabrowid[$id] && !in_array($tabrowid[$id], $listfieldmodify)) { - $sql .= $tabrowid[$id]."="; + $sql .= $db->sanitize($tabrowid[$id])." = "; $sql .= "'".$db->escape($rowid)."', "; } $i = 0; @@ -313,7 +313,7 @@ if ($action == 'confirm_delete' && $confirm == 'yes') { // delete $rowidcol = "rowid"; } - $sql = "DELETE from ".$tabname[$id]." WHERE ".$rowidcol." = ".((int) $rowid); + $sql = "DELETE from ".$db->sanitize($tabname[$id])." WHERE ".$db->sanitize($rowidcol)." = ".((int) $rowid); dol_syslog("delete", LOG_DEBUG); $result = $db->query($sql); @@ -335,9 +335,9 @@ if ($action == $acts[0]) { } if ($rowid) { - $sql = "UPDATE ".$tabname[$id]." SET active = 1 WHERE ".$rowidcol." = ".((int) $rowid); + $sql = "UPDATE ".$db->sanitize($tabname[$id])." SET active = 1 WHERE ".$db->sanitize($rowidcol)." = ".((int) $rowid); } elseif ($code) { - $sql = "UPDATE ".$tabname[$id]." SET active = 1 WHERE code = '".$db->escape($code)."'"; + $sql = "UPDATE ".$db->sanitize($tabname[$id])." SET active = 1 WHERE code = '".$db->escape($code)."'"; } $result = $db->query($sql); @@ -355,9 +355,9 @@ if ($action == $acts[1]) { } if ($rowid) { - $sql = "UPDATE ".$tabname[$id]." SET active = 0 WHERE ".$rowidcol." = ".((int) $rowid); + $sql = "UPDATE ".$db->sanitize($tabname[$id])." SET active = 0 WHERE ".$db->sanitize($rowidcol)." = ".((int) $rowid); } elseif ($code) { - $sql = "UPDATE ".$tabname[$id]." SET active = 0 WHERE code = '".$db->escape($code)."'"; + $sql = "UPDATE ".$db->sanitize($tabname[$id])." SET active = 0 WHERE code = '".$db->escape($code)."'"; } $result = $db->query($sql); @@ -375,9 +375,9 @@ if ($action == 'activate_favorite') { } if ($rowid) { - $sql = "UPDATE ".$tabname[$id]." SET favorite = 1 WHERE ".$rowidcol." = ".((int) $rowid); + $sql = "UPDATE ".$db->sanitize($tabname[$id])." SET favorite = 1 WHERE ".$db->sanitize($rowidcol)." = ".((int) $rowid); } elseif ($code) { - $sql = "UPDATE ".$tabname[$id]." SET favorite = 1 WHERE code = '".$db->escape($code)."'"; + $sql = "UPDATE ".$db->sanitize($tabname[$id])." SET favorite = 1 WHERE code = '".$db->escape($code)."'"; } $result = $db->query($sql); @@ -395,9 +395,9 @@ if ($action == 'disable_favorite') { } if ($rowid) { - $sql = "UPDATE ".$tabname[$id]." SET favorite = 0 WHERE ".$rowidcol." = ".((int) $rowid); + $sql = "UPDATE ".$db->sanitize($tabname[$id])." SET favorite = 0 WHERE ".$db->sanitize($rowidcol)." = ".((int) $rowid); } elseif ($code) { - $sql = "UPDATE ".$tabname[$id]." SET favorite = 0 WHERE code = '".$db->escape($code)."'"; + $sql = "UPDATE ".$db->sanitize($tabname[$id])." SET favorite = 0 WHERE code = '".$db->escape($code)."'"; } $result = $db->query($sql); diff --git a/htdocs/accountancy/admin/journals_list.php b/htdocs/accountancy/admin/journals_list.php index 5aca1af44a3..3c4365844e8 100644 --- a/htdocs/accountancy/admin/journals_list.php +++ b/htdocs/accountancy/admin/journals_list.php @@ -186,7 +186,7 @@ if (GETPOST('actionadd', 'alpha') || GETPOST('actionmodify', 'alpha')) { if ($tabrowid[$id]) { // Get free id for insert $newid = 0; - $sql = "SELECT MAX(".$tabrowid[$id].") newid from ".$tabname[$id]; + $sql = "SELECT MAX(".$db->sanitize($tabrowid[$id]).") newid FROM ".$db->sanitize($tabname[$id]); $result = $db->query($sql); if ($result) { $obj = $db->fetch_object($result); @@ -197,12 +197,12 @@ if (GETPOST('actionadd', 'alpha') || GETPOST('actionmodify', 'alpha')) { } // Add new entry - $sql = "INSERT INTO ".$tabname[$id]." ("; + $sql = "INSERT INTO ".$db->sanitize($tabname[$id])." ("; // List of fields if ($tabrowid[$id] && !in_array($tabrowid[$id], $listfieldinsert)) { $sql .= $tabrowid[$id].","; } - $sql .= $tabfieldinsert[$id]; + $sql .= $db->sanitize($tabfieldinsert[$id]); $sql .= ",active,entity)"; $sql .= " VALUES("; @@ -247,10 +247,10 @@ if (GETPOST('actionadd', 'alpha') || GETPOST('actionmodify', 'alpha')) { } // Modify entry - $sql = "UPDATE ".$tabname[$id]." SET "; + $sql = "UPDATE ".$db->sanitize($tabname[$id])." SET "; // Modifie valeur des champs if ($tabrowid[$id] && !in_array($tabrowid[$id], $listfieldmodify)) { - $sql .= $tabrowid[$id]."="; + $sql .= $db->sanitize($tabrowid[$id])." = "; $sql .= "'".$db->escape($rowid)."', "; } $i = 0; @@ -262,7 +262,7 @@ if (GETPOST('actionadd', 'alpha') || GETPOST('actionmodify', 'alpha')) { $sql .= "'".$db->escape(GETPOST($listfieldvalue[$i]))."'"; $i++; } - $sql .= " WHERE ".$rowidcol." = ".((int) $rowid); + $sql .= " WHERE ".$db->sanitize($rowidcol)." = ".((int) $rowid); $sql .= " AND entity = ".((int) $conf->entity); dol_syslog("actionmodify", LOG_DEBUG); @@ -287,7 +287,7 @@ if ($action == 'confirm_delete' && $confirm == 'yes') { // delete $rowidcol = "rowid"; } - $sql = "DELETE from ".$tabname[$id]." WHERE ".$rowidcol." = ".((int) $rowid); + $sql = "DELETE from ".$db->sanitize($tabname[$id])." WHERE ".$db->sanitize($rowidcol)." = ".((int) $rowid); $sql .= " AND entity = ".((int) $conf->entity); dol_syslog("delete", LOG_DEBUG); @@ -310,9 +310,9 @@ if ($action == $acts[0]) { } if ($rowid) { - $sql = "UPDATE ".$tabname[$id]." SET active = 1 WHERE ".$rowidcol." = ".((int) $rowid); + $sql = "UPDATE ".$db->sanitize($tabname[$id])." SET active = 1 WHERE ".$db->sanitize($rowidcol)." = ".((int) $rowid); } elseif ($code) { - $sql = "UPDATE ".$tabname[$id]." SET active = 1 WHERE code='".$db->escape($code)."'"; + $sql = "UPDATE ".$db->sanitize($tabname[$id])." SET active = 1 WHERE code = '".$db->escape($code)."'"; } $sql .= " AND entity = ".$conf->entity; @@ -331,9 +331,9 @@ if ($action == $acts[1]) { } if ($rowid) { - $sql = "UPDATE ".$tabname[$id]." SET active = 0 WHERE ".$rowidcol." = ".((int) $rowid); + $sql = "UPDATE ".$db->sanitize($tabname[$id])." SET active = 0 WHERE ".$db->sanitize($rowidcol)." = ".((int) $rowid); } elseif ($code) { - $sql = "UPDATE ".$tabname[$id]." SET active = 0 WHERE code='".$db->escape($code)."'"; + $sql = "UPDATE ".$db->sanitize($tabname[$id])." SET active = 0 WHERE code='".$db->escape($code)."'"; } $sql .= " AND entity = ".$conf->entity; diff --git a/htdocs/accountancy/admin/productaccount.php b/htdocs/accountancy/admin/productaccount.php index 164b5c72c04..a0556a5753a 100644 --- a/htdocs/accountancy/admin/productaccount.php +++ b/htdocs/accountancy/admin/productaccount.php @@ -212,19 +212,19 @@ if ($action == 'update') { $nb_exists = $db->num_rows($resql_exists); if ($nb_exists <= 0) { // insert - $sql = "INSERT INTO " . MAIN_DB_PREFIX . "product_perentity (fk_product, entity, " . $db->escape($accountancy_field_name) . ")"; + $sql = "INSERT INTO " . MAIN_DB_PREFIX . "product_perentity (fk_product, entity, " . $db->sanitize($accountancy_field_name) . ")"; $sql .= " VALUES (" . ((int) $productid) . ", " . ((int) $conf->entity) . ", '" . $db->escape($accounting->account_number) . "')"; } else { $obj_exists = $db->fetch_object($resql_exists); // update $sql = "UPDATE " . MAIN_DB_PREFIX . "product_perentity"; - $sql .= " SET " . $accountancy_field_name . " = '" . $db->escape($accounting->account_number) . "'"; + $sql .= " SET " . $db->sanitize($accountancy_field_name) . " = '" . $db->escape($accounting->account_number) . "'"; $sql .= " WHERE rowid = " . ((int) $obj_exists->rowid); } } } else { $sql = " UPDATE ".MAIN_DB_PREFIX."product"; - $sql .= " SET ".$accountancy_field_name." = '".$db->escape($accounting->account_number)."'"; + $sql .= " SET ".$db->sanitize($accountancy_field_name)." = '".$db->escape($accounting->account_number)."'"; $sql .= " WHERE rowid = ".((int) $productid); } @@ -323,16 +323,16 @@ $sql .= " aa.rowid as aaid"; $sql .= " FROM ".MAIN_DB_PREFIX."product as p"; if (getDolGlobalString('MAIN_PRODUCT_PERENTITY_SHARED')) { $sql .= " LEFT JOIN " . MAIN_DB_PREFIX . "product_perentity as ppe ON ppe.fk_product = p.rowid AND ppe.entity = " . ((int) $conf->entity); - $sql .= " LEFT JOIN " . MAIN_DB_PREFIX . "accounting_account as aa ON aa.account_number = ppe." . $accountancy_field_name . " AND aa.fk_pcg_version = '" . $db->escape($pcgvercode) . "'"; + $sql .= " LEFT JOIN " . MAIN_DB_PREFIX . "accounting_account as aa ON aa.account_number = ppe." . $db->sanitize($accountancy_field_name) . " AND aa.fk_pcg_version = '" . $db->escape($pcgvercode) . "'"; } else { - $sql .= " LEFT JOIN " . MAIN_DB_PREFIX . "accounting_account as aa ON aa.account_number = p." . $accountancy_field_name . " AND aa.fk_pcg_version = '" . $db->escape($pcgvercode) . "'"; + $sql .= " LEFT JOIN " . MAIN_DB_PREFIX . "accounting_account as aa ON aa.account_number = p." . $db->sanitize($accountancy_field_name) . " AND aa.fk_pcg_version = '" . $db->escape($pcgvercode) . "'"; } if (!empty($searchCategoryProductList)) { $sql .= ' LEFT JOIN '.MAIN_DB_PREFIX."categorie_product as cp ON p.rowid = cp.fk_product"; // We'll need this table joined to the select in order to filter by categ } $sql .= ' WHERE p.entity IN ('.getEntity('product').')'; if (strlen(trim($search_current_account))) { - $sql .= natural_search((!getDolGlobalString('MAIN_PRODUCT_PERENTITY_SHARED') ? "p." : "ppe.") . $accountancy_field_name, $search_current_account); + $sql .= natural_search((!getDolGlobalString('MAIN_PRODUCT_PERENTITY_SHARED') ? "p." : "ppe.") . $db->sanitize($accountancy_field_name), $search_current_account); } if ($search_current_account_valid == 'withoutvalidaccount') { $sql .= " AND aa.account_number IS NULL"; @@ -346,7 +346,7 @@ if ($searchCategoryProductOperator == 1) { if (intval($searchCategoryProduct) == -2) { $searchCategoryProductSqlList[] = "cp.fk_categorie IS NULL"; } elseif (intval($searchCategoryProduct) > 0) { - $searchCategoryProductSqlList[] = "cp.fk_categorie = ".$db->escape($searchCategoryProduct); + $searchCategoryProductSqlList[] = "cp.fk_categorie = ".((int) $searchCategoryProduct); } } if (!empty($searchCategoryProductSqlList)) { diff --git a/htdocs/accountancy/bookkeeping/export.php b/htdocs/accountancy/bookkeeping/export.php index 0b826be4a1e..5a782c8718f 100644 --- a/htdocs/accountancy/bookkeeping/export.php +++ b/htdocs/accountancy/bookkeeping/export.php @@ -657,7 +657,7 @@ if ($action == 'export_fileconfirm' && $user->hasRight('accounting', 'mouvements if ($setfields) { $sql = " UPDATE ".MAIN_DB_PREFIX."accounting_bookkeeping"; - $sql .= " SET ".$setfields; + $sql .= " SET ".$db->sanitize($setfields); $sql .= " WHERE rowid = ".((int) $movement->id); $result = $db->query($sql); diff --git a/htdocs/accountancy/class/accountancycategory.class.php b/htdocs/accountancy/class/accountancycategory.class.php index 4e9a8f93b09..5cd2e95de28 100644 --- a/htdocs/accountancy/class/accountancycategory.class.php +++ b/htdocs/accountancy/class/accountancycategory.class.php @@ -211,7 +211,7 @@ class AccountancyCategory // extends CommonObject if ($this->rowid > 0) { $sql .= " ".((int) $this->rowid).","; } - $sql .= " ".(!isset($this->code) ? 'NULL' : "'".$this->db->escape($this->code)."'").","; + $sql .= " ".(!isset($this->code) ? "NULL" : "'".$this->db->escape($this->code)."'").","; $sql .= " ".(!isset($this->label) ? 'NULL' : "'".$this->db->escape($this->label)."'").","; $sql .= " ".(!isset($this->range_account) ? 'NULL' : "'".$this->db->escape($this->range_account)."'").","; $sql .= " ".(!isset($this->sens) ? 'NULL' : "'".$this->db->escape($this->sens)."'").","; @@ -357,12 +357,12 @@ class AccountancyCategory // extends CommonObject $sql .= " code=".(isset($this->code) ? "'".$this->db->escape($this->code)."'" : "null").","; $sql .= " label=".(isset($this->label) ? "'".$this->db->escape($this->label)."'" : "null").","; $sql .= " range_account=".(isset($this->range_account) ? "'".$this->db->escape($this->range_account)."'" : "null").","; - $sql .= " sens=".(isset($this->sens) ? $this->sens : "null").","; - $sql .= " category_type=".(isset($this->category_type) ? $this->category_type : "null").","; + $sql .= " sens=".(isset($this->sens) ? ((int) $this->sens) : "null").","; + $sql .= " category_type=".(isset($this->category_type) ? ((int) $this->category_type) : "null").","; $sql .= " formula=".(isset($this->formula) ? "'".$this->db->escape($this->formula)."'" : "null").","; - $sql .= " position=".(isset($this->position) ? $this->position : "null").","; - $sql .= " fk_country=".(isset($this->fk_country) ? $this->fk_country : "null").","; - $sql .= " active=".(isset($this->active) ? $this->active : "null"); + $sql .= " position=".(isset($this->position) ? ((int) $this->position) : "null").","; + $sql .= " fk_country=".(isset($this->fk_country) ? ((int) $this->fk_country) : "null").","; + $sql .= " active=".(isset($this->active) ? ((int) $this->active) : "null"); $sql .= " WHERE rowid=".((int) $this->id); $this->db->begin(); diff --git a/htdocs/accountancy/class/accountingaccount.class.php b/htdocs/accountancy/class/accountingaccount.class.php index de202b575e5..b31f39c366d 100644 --- a/htdocs/accountancy/class/accountingaccount.class.php +++ b/htdocs/accountancy/class/accountingaccount.class.php @@ -632,7 +632,7 @@ class AccountingAccount extends CommonObject $this->db->begin(); $sql = "UPDATE ".MAIN_DB_PREFIX."accounting_account "; - $sql .= "SET ".$fieldtouse." = '0'"; + $sql .= "SET ".$this->db->sanitize($fieldtouse)." = 0"; $sql .= " WHERE rowid = ".((int) $id); dol_syslog(get_class($this)."::accountDeactivate ".$fieldtouse, LOG_DEBUG); @@ -670,7 +670,7 @@ class AccountingAccount extends CommonObject } $sql = "UPDATE ".MAIN_DB_PREFIX."accounting_account"; - $sql .= " SET ".$fieldtouse." = '1'"; + $sql .= " SET ".$this->db->sanitize($fieldtouse)." = 1"; $sql .= " WHERE rowid = ".((int) $id); dol_syslog(get_class($this)."::account_activate ".$fieldtouse, LOG_DEBUG); diff --git a/htdocs/accountancy/class/accountingjournal.class.php b/htdocs/accountancy/class/accountingjournal.class.php index 771e9554ebd..1c1ba9d8ba0 100644 --- a/htdocs/accountancy/class/accountingjournal.class.php +++ b/htdocs/accountancy/class/accountingjournal.class.php @@ -161,14 +161,13 @@ class AccountingJournal extends CommonObject /** * Load object in memory from the database * - * @param string $sortorder Sort Order - * @param string $sortfield Sort field - * @param int $limit offset limit - * @param int $offset offset limit - * @param array $filter filter array - * @param string $filtermode filter mode (AND or OR) - * - * @return int Return integer <0 if KO, >0 if OK + * @param string $sortorder Sort Order + * @param string $sortfield Sort field + * @param int $limit limit + * @param int $offset offset limit + * @param array $filter filter array + * @param string $filtermode filter mode (AND or OR) + * @return int Return integer <0 if KO, >0 if OK */ public function fetchAll($sortorder = '', $sortfield = '', $limit = 0, $offset = 0, array $filter = array(), $filtermode = 'AND') { @@ -179,16 +178,16 @@ class AccountingJournal extends CommonObject if (count($filter) > 0) { foreach ($filter as $key => $value) { if ($key == 't.code' || $key == 't.label' || $key == 't.nature') { - $sqlwhere[] = $key.'\''.$this->db->escape($value).'\''; + $sqlwhere[] = $key."='".$this->db->escape($value)."'"; } elseif ($key == 't.rowid' || $key == 't.active') { - $sqlwhere[] = $key.'='.$value; + $sqlwhere[] = $key.'='.((int) $value); } } } $sql .= ' WHERE 1 = 1'; $sql .= " AND entity IN (".getEntity('accountancy').")"; if (count($sqlwhere) > 0) { - $sql .= " AND ".implode(" ".$filtermode." ", $sqlwhere); + $sql .= " AND ".$this->db->sanitize(implode(" ".$this->db->sanitize($filtermode)." ", $sqlwhere), 1, 1, 1); } if (!empty($sortfield)) { diff --git a/htdocs/accountancy/class/bookkeeping.class.php b/htdocs/accountancy/class/bookkeeping.class.php index f8b3215e083..cef6d2e7891 100644 --- a/htdocs/accountancy/class/bookkeeping.class.php +++ b/htdocs/accountancy/class/bookkeeping.class.php @@ -853,7 +853,7 @@ class BookKeeping extends CommonObject * * @param string $sortorder Sort Order * @param string $sortfield Sort field - * @param int $limit offset limit + * @param int $limit limit * @param int $offset offset limit * @param array $filter filter array * @param string $filtermode filter mode (AND or OR) @@ -944,7 +944,7 @@ class BookKeeping extends CommonObject $sql .= ' FROM '.MAIN_DB_PREFIX.$this->table_element.' as t'; $sql .= ' WHERE entity = ' . ((int) $conf->entity); // Do not use getEntity for accounting features if (count($sqlwhere) > 0) { - $sql .= " AND ".implode(" ".$filtermode." ", $sqlwhere); + $sql .= " AND ".$this->db->sanitize(implode(" ".$this->db->sanitize($filtermode)." ", $sqlwhere), 1, 1, 1); } // Filter by ledger account or subledger account if (!empty($option)) { @@ -1114,7 +1114,7 @@ class BookKeeping extends CommonObject $sql .= " AND t.date_export IS NULL"; } if (count($sqlwhere) > 0) { - $sql .= ' AND '.implode(" ".$filtermode." ", $sqlwhere); + $sql .= ' AND '.$this->db->sanitize(implode(" ".$this->db->sanitize($filtermode)." ", $sqlwhere), 1, 1, 1); } if (!empty($sortfield)) { $sql .= $this->db->order($sortfield, $sortorder); @@ -1237,7 +1237,7 @@ class BookKeeping extends CommonObject } $sql .= ' WHERE entity = ' . ((int) $conf->entity); // Do not use getEntity for accounting features if (count($sqlwhere) > 0) { - $sql .= " AND ".implode(" ".$filtermode." ", $sqlwhere); + $sql .= " AND ".$this->db->sanitize(implode(" ".$this->db->sanitize($filtermode)." ", $sqlwhere), 1, 1, 1); } if (!empty($option)) { @@ -1448,7 +1448,7 @@ class BookKeeping extends CommonObject $this->db->begin(); $sql = "UPDATE ".MAIN_DB_PREFIX.$this->table_element.$mode; - $sql .= " SET ".$field." = ".(is_numeric($value) ? ((float) $value) : "'".$this->db->escape($value)."'"); + $sql .= " SET ".$this->db->sanitize($field)." = ".(is_numeric($value) ? ((float) $value) : "'".$this->db->escape($value)."'"); $sql .= " WHERE piece_num = ".((int) $piece_num); $sql .= $sql_filter; @@ -2277,7 +2277,7 @@ class BookKeeping extends CommonObject $sql_list[] = "('" . $this->db->idate($fiscal_period['date_start']) . "' <= {$alias}doc_date AND {$alias}doc_date <= '" . $this->db->idate($fiscal_period['date_end']) . "')"; } } - self::$can_modify_bookkeeping_sql_cached[$alias] = !empty($sql_list) ? ' AND (' . implode(' OR ', $sql_list) . ')' : ''; + self::$can_modify_bookkeeping_sql_cached[$alias] = !empty($sql_list) ? ' AND (' . $this->db->sanitize(implode(' OR ', $sql_list), 1, 1, 1) . ')' : ''; } return self::$can_modify_bookkeeping_sql_cached[$alias]; @@ -2459,7 +2459,7 @@ class BookKeeping extends CommonObject $sql .= " FROM " . $this->db->prefix() . "accounting_fiscalyear"; $sql .= " WHERE entity = " . ((int) $conf->entity); if (!empty($filter)) { - $sql .= " AND (" . $filter . ')'; + $sql .= " AND (" . $this->db->sanitize($filter, 1, 1, 1) . ')'; } $sql .= $this->db->order('date_start', 'ASC'); @@ -2496,7 +2496,7 @@ class BookKeeping extends CommonObject $sql = "SELECT YEAR(b.doc_date) as year"; for ($i = 1; $i <= 12; $i++) { - $sql .= ", SUM(" . $this->db->ifsql("MONTH(b.doc_date)=" . $i, "1", "0") . ") AS month" . $i; + $sql .= ", SUM(".$this->db->ifsql("MONTH(b.doc_date) = ".((int) $i), "1", "0") . ") AS month".((int) $i); } $sql .= ", COUNT(b.rowid) as total"; $sql .= " FROM " . MAIN_DB_PREFIX . "accounting_bookkeeping as b"; diff --git a/htdocs/accountancy/class/lettering.class.php b/htdocs/accountancy/class/lettering.class.php index 5686bab7de9..07329030e4b 100644 --- a/htdocs/accountancy/class/lettering.class.php +++ b/htdocs/accountancy/class/lettering.class.php @@ -671,11 +671,11 @@ class Lettering extends BookKeeping $bookkeeping_lines_by_type = array(); foreach (self::$doc_type_infos as $doc_type => $doc_type_info) { // Get all fk_doc by doc_type from bank ids - $sql = "SELECT DISTINCT dp." . $doc_type_info['doc_payment_table_fk_doc'] . " AS fk_doc"; - $sql .= " FROM " . MAIN_DB_PREFIX . $doc_type_info['payment_table'] . " AS p"; - $sql .= " LEFT JOIN " . MAIN_DB_PREFIX . $doc_type_info['doc_payment_table'] . " AS dp ON dp." . $doc_type_info['doc_payment_table_fk_payment'] . " = p.rowid"; - $sql .= " WHERE p." . $doc_type_info['payment_table_fk_bank'] . " IN (" . $this->db->sanitize(implode(',', $bank_ids)) . ")"; - $sql .= " AND dp." . $doc_type_info['doc_payment_table_fk_doc'] . " > 0"; + $sql = "SELECT DISTINCT dp." . $this->db->sanitize($doc_type_info['doc_payment_table_fk_doc']) . " AS fk_doc"; + $sql .= " FROM " . MAIN_DB_PREFIX . $this->db->sanitize($doc_type_info['payment_table']) . " AS p"; + $sql .= " LEFT JOIN " . MAIN_DB_PREFIX . $this->db->sanitize($doc_type_info['doc_payment_table']) . " AS dp ON dp." . $this->db->sanitize($doc_type_info['doc_payment_table_fk_payment']) . " = p.rowid"; + $sql .= " WHERE p." . $this->db->sanitize($doc_type_info['payment_table_fk_bank']) . " IN (" . $this->db->sanitize(implode(',', $bank_ids)) . ")"; + $sql .= " AND dp." . $this->db->sanitize($doc_type_info['doc_payment_table_fk_doc']) . " > 0"; dol_syslog(__METHOD__ . " - Get all fk_doc by doc_type from list of bank ids for '" . $doc_type . "'", LOG_DEBUG); $resql = $this->db->query($sql); @@ -726,11 +726,11 @@ class Lettering extends BookKeeping $bank_ids = array(); // Get all fk_doc by doc_type from bank ids - $sql = "SELECT DISTINCT p." . $doc_type_info['payment_table_fk_bank'] . " AS fk_doc"; - $sql .= " FROM " . MAIN_DB_PREFIX . $doc_type_info['payment_table'] . " AS p"; - $sql .= " LEFT JOIN " . MAIN_DB_PREFIX . $doc_type_info['doc_payment_table'] . " AS dp ON dp." . $doc_type_info['doc_payment_table_fk_payment'] . " = p.rowid"; - $sql .= " WHERE dp." . $doc_type_info['doc_payment_table_fk_doc'] . " IN (" . $this->db->sanitize(implode(',', $document_ids)) . ")"; - $sql .= " AND p." . $doc_type_info['payment_table_fk_bank'] . " > 0"; + $sql = "SELECT DISTINCT p." . $this->db->sanitize($doc_type_info['payment_table_fk_bank']) . " AS fk_doc"; + $sql .= " FROM " . MAIN_DB_PREFIX . $this->db->sanitize($doc_type_info['payment_table']) . " AS p"; + $sql .= " LEFT JOIN " . MAIN_DB_PREFIX . $this->db->sanitize($doc_type_info['doc_payment_table']) . " AS dp ON dp." . $this->db->sanitize($doc_type_info['doc_payment_table_fk_payment']) . " = p.rowid"; + $sql .= " WHERE dp." . $this->db->sanitize($doc_type_info['doc_payment_table_fk_doc']) . " IN (" . $this->db->sanitize(implode(',', $document_ids)) . ")"; + $sql .= " AND p." . $this->db->sanitize($doc_type_info['payment_table_fk_bank']) . " > 0"; dol_syslog(__METHOD__ . " - Get all bank ids from list of document ids of a type '" . $doc_type . "'", LOG_DEBUG); $resql = $this->db->query($sql); @@ -781,10 +781,10 @@ class Lettering extends BookKeeping $link_by_element = array(); $element_by_link = array(); foreach ($doc_type_info['linked_info'] as $linked_info) { - $sql = "SELECT DISTINCT tl2." . $linked_info['fk_link'] . " AS fk_link, tl2." . $linked_info['fk_doc'] . " AS fk_doc"; - $sql .= " FROM " . MAIN_DB_PREFIX . $linked_info['table'] . " AS tl"; - $sql .= " LEFT JOIN " . MAIN_DB_PREFIX . $linked_info['table'] . " AS tl2 ON tl2." . $linked_info['fk_link'] . " = tl." . $linked_info['fk_link']; - $sql .= " WHERE tl." . $linked_info['fk_doc'] . " IN (" . $this->db->sanitize(implode(',', $document_ids)) . ")"; + $sql = "SELECT DISTINCT tl2." . $this->db->sanitize($linked_info['fk_link']) . " AS fk_link, tl2." . $this->db->sanitize($linked_info['fk_doc']) . " AS fk_doc"; + $sql .= " FROM " . MAIN_DB_PREFIX . $this->db->sanitize($linked_info['table']) . " AS tl"; + $sql .= " LEFT JOIN " . MAIN_DB_PREFIX . $this->db->sanitize($linked_info['table']) . " AS tl2 ON tl2." . $this->db->sanitize($linked_info['fk_link']) . " = tl." . $this->db->sanitize($linked_info['fk_link']); + $sql .= " WHERE tl." . $this->db->sanitize($linked_info['fk_doc']) . " IN (" . $this->db->sanitize(implode(',', $document_ids)) . ")"; dol_syslog(__METHOD__ . " - Get document lines", LOG_DEBUG); $resql = $this->db->query($sql); diff --git a/htdocs/accountancy/customer/index.php b/htdocs/accountancy/customer/index.php index 391cac7daf4..c5bd8949880 100644 --- a/htdocs/accountancy/customer/index.php +++ b/htdocs/accountancy/customer/index.php @@ -157,10 +157,10 @@ if ($action == 'validatehistory') { } $alias_societe_perentity = !getDolGlobalString('MAIN_COMPANY_PERENTITY_SHARED') ? "s" : "spe"; $alias_product_perentity = !getDolGlobalString('MAIN_PRODUCT_PERENTITY_SHARED') ? "p" : "ppe"; - $sql .= " LEFT JOIN ".$db->prefix()."accounting_account as aa ON " . $alias_product_perentity . ".accountancy_code_sell = aa.account_number AND aa.active = 1 AND aa.fk_pcg_version = '".$db->escape($chartaccountcode)."' AND aa.entity = ".$conf->entity; - $sql .= " LEFT JOIN ".$db->prefix()."accounting_account as aa2 ON " . $alias_product_perentity . ".accountancy_code_sell_intra = aa2.account_number AND aa2.active = 1 AND aa2.fk_pcg_version = '".$db->escape($chartaccountcode)."' AND aa2.entity = ".$conf->entity; - $sql .= " LEFT JOIN ".$db->prefix()."accounting_account as aa3 ON " . $alias_product_perentity . ".accountancy_code_sell_export = aa3.account_number AND aa3.active = 1 AND aa3.fk_pcg_version = '".$db->escape($chartaccountcode)."' AND aa3.entity = ".$conf->entity; - $sql .= " LEFT JOIN ".$db->prefix()."accounting_account as aa4 ON " . $alias_societe_perentity . ".accountancy_code_sell = aa4.account_number AND aa4.active = 1 AND aa4.fk_pcg_version = '".$db->escape($chartaccountcode)."' AND aa4.entity = ".$conf->entity; + $sql .= " LEFT JOIN ".$db->prefix()."accounting_account as aa ON ".$db->sanitize($alias_product_perentity).".accountancy_code_sell = aa.account_number AND aa.active = 1 AND aa.fk_pcg_version = '".$db->escape($chartaccountcode)."' AND aa.entity = ".$conf->entity; + $sql .= " LEFT JOIN ".$db->prefix()."accounting_account as aa2 ON ".$db->sanitize($alias_product_perentity).".accountancy_code_sell_intra = aa2.account_number AND aa2.active = 1 AND aa2.fk_pcg_version = '".$db->escape($chartaccountcode)."' AND aa2.entity = ".$conf->entity; + $sql .= " LEFT JOIN ".$db->prefix()."accounting_account as aa3 ON ".$db->sanitize($alias_product_perentity).".accountancy_code_sell_export = aa3.account_number AND aa3.active = 1 AND aa3.fk_pcg_version = '".$db->escape($chartaccountcode)."' AND aa3.entity = ".$conf->entity; + $sql .= " LEFT JOIN ".$db->prefix()."accounting_account as aa4 ON ".$db->sanitize($alias_societe_perentity).".accountancy_code_sell = aa4.account_number AND aa4.active = 1 AND aa4.fk_pcg_version = '".$db->escape($chartaccountcode)."' AND aa4.entity = ".$conf->entity; $sql .= " WHERE f.fk_statut > 0 AND l.fk_code_ventilation <= 0"; $sql .= " AND l.product_type <= 2"; $sql .= " AND f.entity IN (".getEntity('invoice', 0).")"; // We don't share object for accountancy @@ -347,7 +347,7 @@ for ($i = 1; $i <= 12; $i++) { $param .= '&search_date_endday='.$tmp['mday'].'&search_date_endmonth='.$tmp['mon'].'&search_date_endyear='.$tmp['year']; print ''; } - print $langs->trans('MonthShort'.str_pad($j, 2, '0', STR_PAD_LEFT)); + print $langs->trans('MonthShort'.str_pad((int) $j, 2, '0', STR_PAD_LEFT)); if (!empty($tmp['mday'])) { print ''; } @@ -362,7 +362,7 @@ for ($i = 1; $i <= 12; $i++) { if ($j > 12) { $j -= 12; } - $sql .= " SUM(".$db->ifsql("MONTH(f.datef)=".$j, "fd.total_ht", "0").") AS month".str_pad($j, 2, "0", STR_PAD_LEFT).","; + $sql .= " SUM(".$db->ifsql("MONTH(f.datef) = ".((int) $j), "fd.total_ht", "0").") AS month".str_pad((int) $j, 2, "0", STR_PAD_LEFT).","; } $sql .= " SUM(fd.total_ht) as total"; $sql .= " FROM ".MAIN_DB_PREFIX."facturedet as fd"; @@ -484,7 +484,7 @@ for ($i = 1; $i <= 12; $i++) { $param .= '&search_date_endday='.$tmp['mday'].'&search_date_endmonth='.$tmp['mon'].'&search_date_endyear='.$tmp['year']; print ''; } - print $langs->trans('MonthShort'.str_pad($j, 2, '0', STR_PAD_LEFT)); + print $langs->trans('MonthShort'.str_pad((int) $j, 2, '0', STR_PAD_LEFT)); if (!empty($tmp['mday'])) { print ''; } @@ -499,7 +499,7 @@ for ($i = 1; $i <= 12; $i++) { if ($j > 12) { $j -= 12; } - $sql .= " SUM(".$db->ifsql("MONTH(f.datef)=".$j, "fd.total_ht", "0").") AS month".str_pad($j, 2, "0", STR_PAD_LEFT).","; + $sql .= " SUM(".$db->ifsql("MONTH(f.datef) = ".((int) $j), "fd.total_ht", "0").") AS month".str_pad((int) $j, 2, "0", STR_PAD_LEFT).","; } $sql .= " SUM(fd.total_ht) as total"; $sql .= " FROM ".MAIN_DB_PREFIX."facturedet as fd"; @@ -595,7 +595,7 @@ if (getDolGlobalString('SHOW_TOTAL_OF_PREVIOUS_LISTS_IN_LIN_PAGE')) { // This pa if ($j > 12) { $j -= 12; } - print ''.$langs->trans('MonthShort'.str_pad($j, 2, '0', STR_PAD_LEFT)).''; + print ''.$langs->trans('MonthShort'.str_pad((int) $j, 2, '0', STR_PAD_LEFT)).''; } print ''.$langs->trans("Total").''; @@ -605,7 +605,7 @@ if (getDolGlobalString('SHOW_TOTAL_OF_PREVIOUS_LISTS_IN_LIN_PAGE')) { // This pa if ($j > 12) { $j -= 12; } - $sql .= " SUM(".$db->ifsql("MONTH(f.datef)=".$j, "fd.total_ht", "0").") AS month".str_pad($j, 2, "0", STR_PAD_LEFT).","; + $sql .= " SUM(".$db->ifsql("MONTH(f.datef) = ".((int) $j), "fd.total_ht", "0").") AS month".str_pad((int) $j, 2, "0", STR_PAD_LEFT).","; } $sql .= " SUM(fd.total_ht) as total"; $sql .= " FROM ".MAIN_DB_PREFIX."facturedet as fd"; @@ -655,7 +655,7 @@ if (getDolGlobalString('SHOW_TOTAL_OF_PREVIOUS_LISTS_IN_LIN_PAGE')) { // This pa if ($j > 12) { $j -= 12; } - print ''.$langs->trans('MonthShort'.str_pad($j, 2, '0', STR_PAD_LEFT)).''; + print ''.$langs->trans('MonthShort'.str_pad((int) $j, 2, '0', STR_PAD_LEFT)).''; } print ''.$langs->trans("Total").''; @@ -668,14 +668,14 @@ if (getDolGlobalString('SHOW_TOTAL_OF_PREVIOUS_LISTS_IN_LIN_PAGE')) { // This pa $j -= 12; } $sql .= " SUM(".$db->ifsql( - "MONTH(f.datef)=".$j, + "MONTH(f.datef) = ".((int) $j), " (".$db->ifsql( "fd.total_ht < 0", " (-1 * (abs(fd.total_ht) - (fd.buy_price_ht * fd.qty * (fd.situation_percent / 100))))", // TODO This is bugged, we must use the percent for the invoice and fd.situation_percent is cumulated percent ! " (fd.total_ht - (fd.buy_price_ht * fd.qty * (fd.situation_percent / 100)))" ).")", 0 - ).") AS month".str_pad($j, 2, '0', STR_PAD_LEFT).","; + ).") AS month".str_pad((int) $j, 2, '0', STR_PAD_LEFT).","; } $sql .= " SUM(".$db->ifsql( "fd.total_ht < 0", @@ -690,14 +690,14 @@ if (getDolGlobalString('SHOW_TOTAL_OF_PREVIOUS_LISTS_IN_LIN_PAGE')) { // This pa $j -= 12; } $sql .= " SUM(".$db->ifsql( - "MONTH(f.datef)=".$j, + "MONTH(f.datef) = ".((int) $j), " (".$db->ifsql( "fd.total_ht < 0", " (-1 * (abs(fd.total_ht) - (fd.buy_price_ht * fd.qty)))", " (fd.total_ht - (fd.buy_price_ht * fd.qty))" ).")", 0 - ).") AS month".str_pad($j, 2, '0', STR_PAD_LEFT).","; + ).") AS month".str_pad((int) $j, 2, '0', STR_PAD_LEFT).","; } $sql .= " SUM(".$db->ifsql( "fd.total_ht < 0", diff --git a/htdocs/accountancy/customer/lines.php b/htdocs/accountancy/customer/lines.php index 5994dba600e..74753c65977 100644 --- a/htdocs/accountancy/customer/lines.php +++ b/htdocs/accountancy/customer/lines.php @@ -140,7 +140,7 @@ if (is_array($changeaccount) && count($changeaccount) > 0 && $user->hasRight('ac $db->begin(); $sql1 = "UPDATE ".MAIN_DB_PREFIX."facturedet"; - $sql1 .= " SET fk_code_ventilation=".(GETPOSTINT('account_parent') > 0 ? GETPOSTINT('account_parent') : '0'); + $sql1 .= " SET fk_code_ventilation = ".(GETPOSTINT('account_parent') > 0 ? GETPOSTINT('account_parent') : 0); $sql1 .= ' WHERE rowid IN ('.$db->sanitize(implode(',', $changeaccount)).')'; dol_syslog('accountancy/customer/lines.php::changeaccount sql= '.$sql1); diff --git a/htdocs/accountancy/expensereport/index.php b/htdocs/accountancy/expensereport/index.php index 00f52f0dd49..f72ad2b3037 100644 --- a/htdocs/accountancy/expensereport/index.php +++ b/htdocs/accountancy/expensereport/index.php @@ -223,7 +223,7 @@ for ($i = 1; $i <= 12; $i++) { $param .= '&search_month='.$tmp['mon'].'&search_year='.$tmp['year']; print ''; } - print $langs->trans('MonthShort'.str_pad($j, 2, '0', STR_PAD_LEFT)); + print $langs->trans('MonthShort'.str_pad((int) $j, 2, '0', STR_PAD_LEFT)); if (!empty($tmp['mday'])) { print ''; } @@ -238,7 +238,7 @@ for ($i = 1; $i <= 12; $i++) { if ($j > 12) { $j -= 12; } - $sql .= " SUM(".$db->ifsql("MONTH(er.date_debut)=".$j, "erd.total_ht", "0").") AS month".str_pad($j, 2, "0", STR_PAD_LEFT).","; + $sql .= " SUM(".$db->ifsql("MONTH(er.date_debut) = ".((int) $j), "erd.total_ht", "0").") AS month".str_pad((int) $j, 2, "0", STR_PAD_LEFT).","; } $sql .= " SUM(erd.total_ht) as total"; $sql .= " FROM ".MAIN_DB_PREFIX."expensereport_det as erd"; @@ -338,7 +338,7 @@ for ($i = 1; $i <= 12; $i++) { if ($j > 12) { $j -= 12; } - print ''.$langs->trans('MonthShort'.str_pad($j, 2, '0', STR_PAD_LEFT)).''; + print ''.$langs->trans('MonthShort'.str_pad((int) $j, 2, '0', STR_PAD_LEFT)).''; } print ''.$langs->trans("Total").''; @@ -349,7 +349,7 @@ for ($i = 1; $i <= 12; $i++) { if ($j > 12) { $j -= 12; } - $sql .= " SUM(".$db->ifsql("MONTH(er.date_debut)=".$j, "erd.total_ht", "0").") AS month".str_pad($j, 2, "0", STR_PAD_LEFT).","; + $sql .= " SUM(".$db->ifsql("MONTH(er.date_debut) = ".((int) $j), "erd.total_ht", "0").") AS month".str_pad((int) $j, 2, "0", STR_PAD_LEFT).","; } $sql .= " ROUND(SUM(erd.total_ht),2) as total"; $sql .= " FROM ".MAIN_DB_PREFIX."expensereport_det as erd"; @@ -436,7 +436,7 @@ if (getDolGlobalString('SHOW_TOTAL_OF_PREVIOUS_LISTS_IN_LIN_PAGE')) { // This pa if ($j > 12) { $j -= 12; } - $sql .= " SUM(".$db->ifsql("MONTH(er.date_create)=".$j, "erd.total_ht", "0").") AS month".str_pad($j, 2, "0", STR_PAD_LEFT).","; + $sql .= " SUM(".$db->ifsql("MONTH(er.date_create) = ".((int) $j), "erd.total_ht", "0").") AS month".str_pad((int) $j, 2, "0", STR_PAD_LEFT).","; } $sql .= " SUM(erd.total_ht) as total"; $sql .= " FROM ".MAIN_DB_PREFIX."expensereport_det as erd"; diff --git a/htdocs/accountancy/supplier/index.php b/htdocs/accountancy/supplier/index.php index ace576b4232..dea3d7b875a 100644 --- a/htdocs/accountancy/supplier/index.php +++ b/htdocs/accountancy/supplier/index.php @@ -340,7 +340,7 @@ for ($i = 1; $i <= 12; $i++) { $param .= '&search_date_endday='.$tmp['mday'].'&search_date_endmonth='.$tmp['mon'].'&search_date_endyear='.$tmp['year']; print ''; } - print $langs->trans('MonthShort'.str_pad($j, 2, '0', STR_PAD_LEFT)); + print $langs->trans('MonthShort'.str_pad((int) $j, 2, '0', STR_PAD_LEFT)); if (!empty($tmp['mday'])) { print ''; } @@ -355,7 +355,7 @@ for ($i = 1; $i <= 12; $i++) { if ($j > 12) { $j -= 12; } - $sql .= " SUM(".$db->ifsql("MONTH(ff.datef)=".$j, "ffd.total_ht", "0").") AS month".str_pad($j, 2, "0", STR_PAD_LEFT).","; + $sql .= " SUM(".$db->ifsql("MONTH(ff.datef) = ".((int) $j), "ffd.total_ht", "0").") AS month".str_pad((int) $j, 2, "0", STR_PAD_LEFT).","; } $sql .= " SUM(ffd.total_ht) as total"; $sql .= " FROM ".$db->prefix()."facture_fourn_det as ffd"; @@ -487,7 +487,7 @@ for ($i = 1; $i <= 12; $i++) { if ($j > 12) { $j -= 12; } - $sql .= " SUM(".$db->ifsql("MONTH(ff.datef)=".$j, "ffd.total_ht", "0").") AS month".str_pad($j, 2, "0", STR_PAD_LEFT).","; + $sql .= " SUM(".$db->ifsql("MONTH(ff.datef) = ".((int) $j), "ffd.total_ht", "0").") AS month".str_pad((int) $j, 2, "0", STR_PAD_LEFT).","; } $sql .= " SUM(ffd.total_ht) as total"; $sql .= " FROM ".$db->prefix()."facture_fourn_det as ffd"; @@ -571,7 +571,7 @@ if (getDolGlobalString('SHOW_TOTAL_OF_PREVIOUS_LISTS_IN_LIN_PAGE')) { // This pa if ($j > 12) { $j -= 12; } - print ''.$langs->trans('MonthShort'.str_pad($j, 2, '0', STR_PAD_LEFT)).''; + print ''.$langs->trans('MonthShort'.str_pad((int) $j, 2, '0', STR_PAD_LEFT)).''; } print ''.$langs->trans("Total").''; @@ -581,7 +581,7 @@ if (getDolGlobalString('SHOW_TOTAL_OF_PREVIOUS_LISTS_IN_LIN_PAGE')) { // This pa if ($j > 12) { $j -= 12; } - $sql .= " SUM(".$db->ifsql("MONTH(ff.datef)=".$j, "ffd.total_ht", "0").") AS month".str_pad($j, 2, "0", STR_PAD_LEFT).","; + $sql .= " SUM(".$db->ifsql("MONTH(ff.datef) = ".((int) $j), "ffd.total_ht", "0").") AS month".str_pad((int) $j, 2, "0", STR_PAD_LEFT).","; } $sql .= " SUM(ffd.total_ht) as total"; $sql .= " FROM ".$db->prefix()."facture_fourn_det as ffd"; diff --git a/htdocs/adherents/card.php b/htdocs/adherents/card.php index eeff802a2e4..151859f52d7 100644 --- a/htdocs/adherents/card.php +++ b/htdocs/adherents/card.php @@ -1169,7 +1169,8 @@ if (is_object($objcanvas) && $objcanvas->displayCanvasExists($action)) { // We set country_id, and country_code, country of the chosen country $country = GETPOSTINT('country'); if (!empty($country) || $object->country_id) { - $sql = "SELECT rowid, code, label from ".MAIN_DB_PREFIX."c_country where rowid = ".(!empty($country) ? $country : $object->country_id); + $sql = "SELECT rowid, code, label from ".MAIN_DB_PREFIX."c_country"; + $sql .= " WHERE rowid = ".(int) (!empty($country) ? $country : $object->country_id); $resql = $db->query($sql); if ($resql) { $obj = $db->fetch_object($resql); diff --git a/htdocs/adherents/class/adherent.class.php b/htdocs/adherents/class/adherent.class.php index 951b19a439d..7a88f72e0d0 100644 --- a/htdocs/adherents/class/adherent.class.php +++ b/htdocs/adherents/class/adherent.class.php @@ -754,13 +754,13 @@ class Adherent extends CommonObject $sql .= ", login = ".($this->login ? "'".$this->db->escape($this->login)."'" : "null"); $sql .= ", societe = ".($this->company ? "'".$this->db->escape($this->company)."'" : ($this->societe ? "'".$this->db->escape($this->societe)."'" : "null")); if ($this->socid) { - $sql .= ", fk_soc = ".($this->socid > 0 ? $this->db->escape($this->socid) : "null"); // Must be modified only when creating from a third-party + $sql .= ", fk_soc = ".($this->socid > 0 ? (int) $this->socid : "null"); // Must be modified only when creating from a third-party } $sql .= ", address = ".($this->address ? "'".$this->db->escape($this->address)."'" : "null"); $sql .= ", zip = ".($this->zip ? "'".$this->db->escape($this->zip)."'" : "null"); $sql .= ", town = ".($this->town ? "'".$this->db->escape($this->town)."'" : "null"); - $sql .= ", country = ".($this->country_id > 0 ? $this->db->escape($this->country_id) : "null"); - $sql .= ", state_id = ".($this->state_id > 0 ? $this->db->escape($this->state_id) : "null"); + $sql .= ", country = ".($this->country_id > 0 ? (int) $this->country_id : "null"); + $sql .= ", state_id = ".($this->state_id > 0 ? (int) $this->state_id : "null"); $sql .= ", email = '".$this->db->escape($this->email)."'"; $sql .= ", url = ".(!empty($this->url) ? "'".$this->db->escape($this->url)."'" : "null"); $sql .= ", socialnetworks = ".($this->socialnetworks ? "'".$this->db->escape(json_encode($this->socialnetworks))."'" : "null"); @@ -771,9 +771,9 @@ class Adherent extends CommonObject $sql .= ", note_public = ".($this->note_public ? "'".$this->db->escape($this->note_public)."'" : "null"); $sql .= ", photo = ".($this->photo ? "'".$this->db->escape($this->photo)."'" : "null"); $sql .= ", public = '".$this->db->escape($this->public)."'"; - $sql .= ", statut = ".$this->db->escape($this->statut); + $sql .= ", statut = ".(int) $this->statut; $sql .= ", default_lang = ".(!empty($this->default_lang) ? "'".$this->db->escape($this->default_lang)."'" : "null"); - $sql .= ", fk_adherent_type = ".$this->db->escape($this->typeid); + $sql .= ", fk_adherent_type = ".(int) $this->typeid; $sql .= ", morphy = '".$this->db->escape($this->morphy)."'"; $sql .= ", birth = ".($this->birth ? "'".$this->db->idate($this->birth)."'" : "null"); @@ -1284,7 +1284,7 @@ class Adherent extends CommonObject } // Add link to third party for current member - $sql = "UPDATE ".MAIN_DB_PREFIX."adherent SET fk_soc = ".($thirdpartyid > 0 ? $thirdpartyid : 'null'); + $sql = "UPDATE ".MAIN_DB_PREFIX."adherent SET fk_soc = ".($thirdpartyid > 0 ? (int) $thirdpartyid : 'null'); $sql .= " WHERE rowid = ".((int) $this->id); dol_syslog(get_class($this)."::setThirdPartyId", LOG_DEBUG); diff --git a/htdocs/adherents/class/adherent_type.class.php b/htdocs/adherents/class/adherent_type.class.php index 44f51ff9aca..aab2322d098 100644 --- a/htdocs/adherents/class/adherent_type.class.php +++ b/htdocs/adherents/class/adherent_type.class.php @@ -246,7 +246,7 @@ class AdherentType extends CommonObject } else { $sql2 = "INSERT INTO ".MAIN_DB_PREFIX."adherent_type_lang (fk_type, lang, label, description"; $sql2 .= ")"; - $sql2 .= " VALUES(".$this->id.",'".$this->db->escape($key)."','".$this->db->escape($this->multilangs["$key"]["label"])."',"; + $sql2 .= " VALUES(".((int) $this->id).",'".$this->db->escape($key)."','".$this->db->escape($this->multilangs["$key"]["label"])."',"; $sql2 .= " '".$this->db->escape($this->multilangs["$key"]["description"])."'"; $sql2 .= ")"; } @@ -395,7 +395,7 @@ class AdherentType extends CommonObject $sql .= "libelle = '".$this->db->escape($this->label)."',"; $sql .= "morphy = '".$this->db->escape($this->morphy)."',"; $sql .= "subscription = '".$this->db->escape($this->subscription)."',"; - $sql .= "amount = ".((empty($this->amount) && $this->amount == '') ? 'null' : ((float) $this->amount)).","; + $sql .= "amount = ".((empty($this->amount) && $this->amount == '') ? "null" : ((float) $this->amount)).","; $sql .= "caneditamount = ".((int) $this->caneditamount).","; $sql .= "duration = '".$this->db->escape($this->duration_value.$this->duration_unit)."',"; $sql .= "note = '".$this->db->escape($this->note_public)."',"; diff --git a/htdocs/adherents/class/subscription.class.php b/htdocs/adherents/class/subscription.class.php index d0ddd730d61..111cb2c04ea 100644 --- a/htdocs/adherents/class/subscription.class.php +++ b/htdocs/adherents/class/subscription.class.php @@ -279,7 +279,7 @@ class Subscription extends CommonObject $sql .= " fk_type = ".((int) $this->fk_type).","; $sql .= " fk_adherent = ".((int) $this->fk_adherent).","; $sql .= " note = ".($this->note_public ? "'".$this->db->escape($this->note_public)."'" : 'null').","; - $sql .= " subscription = ".price2num($this->amount).","; + $sql .= " subscription = ".(float) price2num($this->amount).","; $sql .= " dateadh = '".$this->db->idate($this->dateh)."',"; $sql .= " datef = '".$this->db->idate($this->datef)."',"; $sql .= " datec = '".$this->db->idate($this->datec)."',"; diff --git a/htdocs/admin/dict.php b/htdocs/admin/dict.php index a07b083ca12..0abc9213fb7 100644 --- a/htdocs/admin/dict.php +++ b/htdocs/admin/dict.php @@ -1014,9 +1014,9 @@ if (empty($reshook)) { $i++; } if (in_array($rowidcol, array('code', 'code_iso'))) { - $sql .= " WHERE ".$rowidcol." = '".$db->escape($rowid)."'"; + $sql .= " WHERE ".$db->sanitize($rowidcol)." = '".$db->escape($rowid)."'"; } else { - $sql .= " WHERE ".$rowidcol." = ".((int) $rowid); + $sql .= " WHERE ".$db->sanitize($rowidcol)." = ".((int) $rowid); } if (in_array('entity', $listfieldmodify)) { $sql .= " AND entity = ".((int) getEntity($tablename, 0)); @@ -1284,9 +1284,9 @@ if ($id > 0) { $sql .= natural_search($tablecode, $search_code); } if ($search_active == 'yes') { - $sql .= " AND ".$tableprefix."active = 1"; + $sql .= " AND ".$db->sanitize($tableprefix)."active = 1"; } elseif ($search_active == 'no') { - $sql .= " AND ".$tableprefix."active = 0"; + $sql .= " AND ".$db->sanitize($tableprefix)."active = 0"; } //var_dump($sql); diff --git a/htdocs/admin/emailcollector_list.php b/htdocs/admin/emailcollector_list.php index c8c4869e7d9..8d0c4ff1f27 100644 --- a/htdocs/admin/emailcollector_list.php +++ b/htdocs/admin/emailcollector_list.php @@ -245,7 +245,7 @@ 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] != '') { diff --git a/htdocs/asset/class/asset.class.php b/htdocs/asset/class/asset.class.php index 4b468a5633c..296659dda53 100644 --- a/htdocs/asset/class/asset.class.php +++ b/htdocs/asset/class/asset.class.php @@ -389,18 +389,17 @@ class Asset extends CommonObject /** * Load list of objects in memory from the database. * - * @param string $sortorder Sort Order - * @param string $sortfield Sort field - * @param int $limit limit - * @param int $offset Offset - * @param array $filter Filter array. Example array('field'=>'valueforlike', 'customurl'=>...) - * @param string $filtermode Filter mode (AND or OR) - * @return array|int int <0 if KO, array of pages if OK + * @param string $sortorder Sort Order + * @param string $sortfield Sort field + * @param int $limit limit + * @param int $offset Offset + * @param string $filter Filter as an Universal Search string. + * Example: '((client:=:1) OR ((client:>=:2) AND (client:<=:3))) AND (client:!=:8) AND (nom:like:'a%')' + * @param string $filtermode No more used + * @return array|int int <0 if KO, array of pages if OK */ public function fetchAll($sortorder = '', $sortfield = '', $limit = 0, $offset = 0, array $filter = array(), $filtermode = 'AND') { - global $conf; - dol_syslog(__METHOD__, LOG_DEBUG); $records = array(); @@ -414,24 +413,13 @@ class Asset extends CommonObject $sql .= " WHERE 1 = 1"; } // Manage filter - $sqlwhere = array(); - if (count($filter) > 0) { - foreach ($filter as $key => $value) { - if ($key == 't.rowid') { - $sqlwhere[] = $key." = ".((int) $value); - } elseif (array_key_exists($key, $this->fields) && in_array($this->fields[$key]['type'], array('date', 'datetime', 'timestamp'))) { - $sqlwhere[] = $key." = '".$this->db->idate($value)."'"; - } elseif ($key == 'customsql') { - $sqlwhere[] = $value; - } elseif (strpos($value, '%') === false) { - $sqlwhere[] = $key." IN (".$this->db->sanitize($this->db->escape($value)).")"; - } else { - $sqlwhere[] = $key." LIKE '%".$this->db->escape($value)."%'"; - } - } - } - if (count($sqlwhere) > 0) { - $sql .= " AND (".implode(" ".$filtermode." ", $sqlwhere).")"; + $errormessage = ''; + $sql .= forgeSQLFromUniversalSearchCriteria($filter, $errormessage); + if ($errormessage) { + $this->errors[] = $errormessage; + dol_syslog(__METHOD__.' '.join(',', $this->errors), LOG_ERR); + + return -1; } if (!empty($sortfield)) { diff --git a/htdocs/asset/class/assetmodel.class.php b/htdocs/asset/class/assetmodel.class.php index 12132d4b65a..768e2cd8e33 100644 --- a/htdocs/asset/class/assetmodel.class.php +++ b/htdocs/asset/class/assetmodel.class.php @@ -339,18 +339,17 @@ class AssetModel extends CommonObject /** * Load list of objects in memory from the database. * - * @param string $sortorder Sort Order - * @param string $sortfield Sort field - * @param int $limit limit - * @param int $offset Offset - * @param array $filter Filter array. Example array('field'=>'valueforlike', 'customurl'=>...) - * @param string $filtermode Filter mode (AND or OR) - * @return array|int int <0 if KO, array of pages if OK + * @param string $sortorder Sort Order + * @param string $sortfield Sort field + * @param int $limit limit + * @param int $offset Offset + * @param string $filter Filter as an Universal Search string. + * Example: '((client:=:1) OR ((client:>=:2) AND (client:<=:3))) AND (client:!=:8) AND (nom:like:'a%')' + * @param string $filtermode No more used + * @return array|int int <0 if KO, array of pages if OK */ public function fetchAll($sortorder = '', $sortfield = '', $limit = 0, $offset = 0, array $filter = array(), $filtermode = 'AND') { - global $conf; - dol_syslog(__METHOD__, LOG_DEBUG); $records = array(); @@ -363,25 +362,13 @@ class AssetModel extends CommonObject } else { $sql .= " WHERE 1 = 1"; } - // Manage filter - $sqlwhere = array(); - if (count($filter) > 0) { - foreach ($filter as $key => $value) { - if ($key == 't.rowid') { - $sqlwhere[] = $key." = ".((int) $value); - } elseif (array_key_exists($key, $this->fields) && in_array($this->fields[$key]['type'], array('date', 'datetime', 'timestamp'))) { - $sqlwhere[] = $key." = '".$this->db->idate($value)."'"; - } elseif ($key == 'customsql') { - $sqlwhere[] = $value; - } elseif (strpos($value, '%') === false) { - $sqlwhere[] = $key." IN (".$this->db->sanitize($this->db->escape($value)).")"; - } else { - $sqlwhere[] = $key." LIKE '%".$this->db->escape($value)."%'"; - } - } - } - if (count($sqlwhere) > 0) { - $sql .= " AND (".implode(" ".$filtermode." ", $sqlwhere).")"; + + $errormessage = ''; + $sql .= forgeSQLFromUniversalSearchCriteria($filter, $errormessage); + if ($errormessage) { + $this->errors[] = $errormessage; + dol_syslog(__METHOD__.' '.join(',', $this->errors), LOG_ERR); + return -1; } if (!empty($sortfield)) { diff --git a/htdocs/bom/bom_list.php b/htdocs/bom/bom_list.php index a1bb6de9595..cbf1f8cccf5 100644 --- a/htdocs/bom/bom_list.php +++ b/htdocs/bom/bom_list.php @@ -339,17 +339,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])."'"; } } } diff --git a/htdocs/bom/class/bom.class.php b/htdocs/bom/class/bom.class.php index ba88dfff476..e2ffdea9382 100644 --- a/htdocs/bom/class/bom.class.php +++ b/htdocs/bom/class/bom.class.php @@ -509,23 +509,13 @@ class BOM extends CommonObject } else { $sql .= ' WHERE 1 = 1'; } - // Manage filter - $sqlwhere = array(); - if (count($filter) > 0) { - foreach ($filter as $key => $value) { - if ($key == 't.rowid') { - $sqlwhere[] = $key." = ".((int) $value); - } elseif (strpos($key, 'date') !== false) { - $sqlwhere[] = $key." = '".$this->db->idate($value)."'"; - } elseif ($key == 'customsql') { - $sqlwhere[] = $value; - } else { - $sqlwhere[] = $key." LIKE '%".$this->db->escape($value)."%'"; - } - } - } - if (count($sqlwhere) > 0) { - $sql .= " AND (".implode(" ".$filtermode." ", $sqlwhere).")"; + + $errormessage = ''; + $sql .= forgeSQLFromUniversalSearchCriteria($filter, $errormessage); + if ($errormessage) { + $this->errors[] = $errormessage; + dol_syslog(__METHOD__.' '.join(',', $this->errors), LOG_ERR); + return -1; } if (!empty($sortfield)) { diff --git a/htdocs/bookcal/class/availabilities.class.php b/htdocs/bookcal/class/availabilities.class.php index e06d0244f01..5b81b8605d3 100644 --- a/htdocs/bookcal/class/availabilities.class.php +++ b/htdocs/bookcal/class/availabilities.class.php @@ -383,18 +383,17 @@ class Availabilities extends CommonObject /** * Load list of objects in memory from the database. * - * @param string $sortorder Sort Order - * @param string $sortfield Sort field - * @param int $limit limit - * @param int $offset Offset - * @param array $filter Filter array. Example array('field'=>'valueforlike', 'customurl'=>...) - * @param string $filtermode Filter mode (AND or OR) - * @return array|int int <0 if KO, array of pages if OK + * @param string $sortorder Sort Order + * @param string $sortfield Sort field + * @param int $limit limit + * @param int $offset Offset + * @param string $filter Filter as an Universal Search string. + * Example: '((client:=:1) OR ((client:>=:2) AND (client:<=:3))) AND (client:!=:8) AND (nom:like:'a%')' + * @param string $filtermode No more used + * @return array|int int <0 if KO, array of pages if OK */ public function fetchAll($sortorder = '', $sortfield = '', $limit = 0, $offset = 0, array $filter = array(), $filtermode = 'AND') { - global $conf; - dol_syslog(__METHOD__, LOG_DEBUG); $records = array(); @@ -407,25 +406,14 @@ class Availabilities extends CommonObject } else { $sql .= " WHERE 1 = 1"; } + // Manage filter - $sqlwhere = array(); - if (count($filter) > 0) { - foreach ($filter as $key => $value) { - if ($key == 't.rowid') { - $sqlwhere[] = $key." = ".((int) $value); - } elseif (array_key_exists($key, $this->fields) && in_array($this->fields[$key]['type'], array('date', 'datetime', 'timestamp'))) { - $sqlwhere[] = $key." = '".$this->db->idate($value)."'"; - } elseif ($key == 'customsql') { - $sqlwhere[] = $value; - } elseif (strpos($value, '%') === false) { - $sqlwhere[] = $key." IN (".$this->db->sanitize($this->db->escape($value)).")"; - } else { - $sqlwhere[] = $key." LIKE '%".$this->db->escape($value)."%'"; - } - } - } - if (count($sqlwhere) > 0) { - $sql .= " AND (".implode(" ".$filtermode." ", $sqlwhere).")"; + $errormessage = ''; + $sql .= forgeSQLFromUniversalSearchCriteria($filter, $errormessage); + if ($errormessage) { + $this->errors[] = $errormessage; + dol_syslog(__METHOD__.' '.join(',', $this->errors), LOG_ERR); + return -1; } if (!empty($sortfield)) { diff --git a/htdocs/bookcal/class/calendar.class.php b/htdocs/bookcal/class/calendar.class.php index a4a59c6d48c..ea0e5e13bba 100644 --- a/htdocs/bookcal/class/calendar.class.php +++ b/htdocs/bookcal/class/calendar.class.php @@ -341,15 +341,16 @@ class Calendar extends CommonObject /** * Load list of objects in memory from the database. * - * @param string $sortorder Sort Order - * @param string $sortfield Sort field - * @param int $limit limit - * @param int $offset Offset - * @param array $filter Filter array. Example array('field'=>'valueforlike', 'customurl'=>...) - * @param string $filtermode Filter mode (AND or OR) - * @return array|int int <0 if KO, array of pages if OK + * @param string $sortorder Sort Order + * @param string $sortfield Sort field + * @param int $limit limit + * @param int $offset Offset + * @param string $filter Filter as an Universal Search string. + * Example: '((client:=:1) OR ((client:>=:2) AND (client:<=:3))) AND (client:!=:8) AND (nom:like:'a%')' + * @param string $filtermode No more used + * @return array|int int <0 if KO, array of pages if OK */ - public function fetchAll($sortorder = '', $sortfield = '', $limit = 0, $offset = 0, array $filter = array(), $filtermode = 'AND') + public function fetchAll($sortorder = '', $sortfield = '', $limit = 0, $offset = 0, $filter = '', $filtermode = 'AND') { dol_syslog(__METHOD__, LOG_DEBUG); @@ -363,25 +364,14 @@ class Calendar extends CommonObject } else { $sql .= " WHERE 1 = 1"; } + // Manage filter - $sqlwhere = array(); - if (count($filter) > 0) { - foreach ($filter as $key => $value) { - if ($key == 't.rowid') { - $sqlwhere[] = $key." = ".((int) $value); - } elseif (array_key_exists($key, $this->fields) && in_array($this->fields[$key]['type'], array('date', 'datetime', 'timestamp'))) { - $sqlwhere[] = $key." = '".$this->db->idate($value)."'"; - } elseif ($key == 'customsql') { - $sqlwhere[] = $value; - } elseif (strpos($value, '%') === false) { - $sqlwhere[] = $key." IN (".$this->db->sanitize($this->db->escape($value)).")"; - } else { - $sqlwhere[] = $key." LIKE '%".$this->db->escape($value)."%'"; - } - } - } - if (count($sqlwhere) > 0) { - $sql .= " AND (".implode(" ".$filtermode." ", $sqlwhere).")"; + $errormessage = ''; + $sql .= forgeSQLFromUniversalSearchCriteria($filter, $errormessage); + if ($errormessage) { + $this->errors[] = $errormessage; + dol_syslog(__METHOD__.' '.join(',', $this->errors), LOG_ERR); + return -1; } if (!empty($sortfield)) { diff --git a/htdocs/categories/class/categorie.class.php b/htdocs/categories/class/categorie.class.php index 74310aea526..9cd365428f5 100644 --- a/htdocs/categories/class/categorie.class.php +++ b/htdocs/categories/class/categorie.class.php @@ -863,18 +863,19 @@ class Categorie extends CommonObject /** * Return list of fetched instance of elements having this category * - * @param string $type Type of category ('customer', 'supplier', 'contact', 'product', 'member', 'knowledge_management', ...) - * @param int $onlyids Return only ids of objects (consume less memory) - * @param int $limit Limit - * @param int $offset Offset - * @param string $sortfield Sort fields - * @param string $sortorder Sort order ('ASC' or 'DESC'); - * @param array $filter Filter array. Example array('field'=>'valueforlike', 'customsql'=>...) - * @param string $filtermode Filter mode (AND or OR) - * @return CommonObject[]|int[]|int Return -1 if KO, array of instance of object if OK + * @param string $type Type of category ('customer', 'supplier', 'contact', 'product', 'member', 'knowledge_management', ...) + * @param int $onlyids Return only ids of objects (consume less memory) + * @param int $limit Limit + * @param int $offset Offset + * @param string $sortfield Sort fields + * @param string $sortorder Sort order ('ASC' or 'DESC'); + * @param string $filter Filter as an Universal Search string. + * Example: '((client:=:1) OR ((client:>=:2) AND (client:<=:3))) AND (client:!=:8) AND (nom:like:'a%')' + * @param string $filtermode No more used + * @return CommonObject[]|int[]|int Return -1 if KO, array of instance of object if OK * @see containsObject() */ - public function getObjectsInCateg($type, $onlyids = 0, $limit = 0, $offset = 0, $sortfield = '', $sortorder = 'ASC', $filter = array(), $filtermode = 'AND') + public function getObjectsInCateg($type, $onlyids = 0, $limit = 0, $offset = 0, $sortfield = '', $sortorder = 'ASC', $filter = '', $filtermode = 'AND') { global $user; @@ -898,20 +899,15 @@ class Categorie extends CommonObject if (($type == 'customer' || $type == 'supplier') && $user->socid > 0) { $sql .= " AND o.rowid = ".((int) $user->socid); } - // Manage filter - $sqlwhere = array(); - if (count($filter) > 0) { - foreach ($filter as $key => $value) { - if ($key == 'o.rowid') { - $sqlwhere[] = $key." = ".((int) $value); - } elseif ($key == 'customsql') { - $sqlwhere[] = $value; - } - } - } - if (count($sqlwhere) > 0) { - $sql .= " AND (".implode(" ".$filtermode." ", $sqlwhere).")"; + + $errormessage = ''; + $sql .= forgeSQLFromUniversalSearchCriteria($filter, $errormessage); + if ($errormessage) { + $this->errors[] = $errormessage; + dol_syslog(__METHOD__.' '.join(',', $this->errors), LOG_ERR); + return -1; } + $sql .= $this->db->order($sortfield, $sortorder); if ($limit > 0 || $offset > 0) { $sql .= $this->db->plimit($limit + 1, $offset); diff --git a/htdocs/compta/facture/class/facture.class.php b/htdocs/compta/facture/class/facture.class.php index c37501e3377..b9d5e4b7dca 100644 --- a/htdocs/compta/facture/class/facture.class.php +++ b/htdocs/compta/facture/class/facture.class.php @@ -2508,18 +2508,18 @@ class Facture extends CommonInvoice $sql .= " paye=".(isset($this->paye) ? $this->db->escape($this->paye) : 0).","; $sql .= " close_code=".(isset($this->close_code) ? "'".$this->db->escape($this->close_code)."'" : "null").","; $sql .= " close_note=".(isset($this->close_note) ? "'".$this->db->escape($this->close_note)."'" : "null").","; - $sql .= " total_tva=".(isset($this->total_tva) ? $this->total_tva : "null").","; - $sql .= " localtax1=".(isset($this->total_localtax1) ? $this->total_localtax1 : "null").","; - $sql .= " localtax2=".(isset($this->total_localtax2) ? $this->total_localtax2 : "null").","; - $sql .= " total_ht=".(isset($this->total_ht) ? $this->total_ht : "null").","; - $sql .= " total_ttc=".(isset($this->total_ttc) ? $this->total_ttc : "null").","; - $sql .= " revenuestamp=".((isset($this->revenuestamp) && $this->revenuestamp != '') ? $this->db->escape($this->revenuestamp) : "null").","; - $sql .= " fk_statut=".(isset($this->status) ? $this->db->escape($this->status) : "null").","; - $sql .= " fk_user_valid=".(isset($this->fk_user_valid) ? $this->db->escape($this->fk_user_valid) : "null").","; - $sql .= " fk_facture_source=".(isset($this->fk_facture_source) ? $this->db->escape($this->fk_facture_source) : "null").","; - $sql .= " fk_projet=".(isset($this->fk_project) ? $this->db->escape($this->fk_project) : "null").","; - $sql .= " fk_cond_reglement=".(isset($this->cond_reglement_id) ? $this->db->escape($this->cond_reglement_id) : "null").","; - $sql .= " fk_mode_reglement=".(isset($this->mode_reglement_id) ? $this->db->escape($this->mode_reglement_id) : "null").","; + $sql .= " total_tva=".(isset($this->total_tva) ? (float) $this->total_tva : "null").","; + $sql .= " localtax1=".(isset($this->total_localtax1) ? (float) $this->total_localtax1 : "null").","; + $sql .= " localtax2=".(isset($this->total_localtax2) ? (float) $this->total_localtax2 : "null").","; + $sql .= " total_ht=".(isset($this->total_ht) ? (float) $this->total_ht : "null").","; + $sql .= " total_ttc=".(isset($this->total_ttc) ? (float) $this->total_ttc : "null").","; + $sql .= " revenuestamp=".((isset($this->revenuestamp) && $this->revenuestamp != '') ? (int) $this->revenuestamp : "null").","; + $sql .= " fk_statut=".(isset($this->status) ? (int) $this->status : "null").","; + $sql .= " fk_user_valid=".(isset($this->fk_user_valid) ? (int) $this->fk_user_valid : "null").","; + $sql .= " fk_facture_source=".(isset($this->fk_facture_source) ? (int) $this->fk_facture_source : "null").","; + $sql .= " fk_projet=".(isset($this->fk_project) ? (int) $this->fk_project : "null").","; + $sql .= " fk_cond_reglement=".(isset($this->cond_reglement_id) ? $this->escape($this->cond_reglement_id) : "null").","; + $sql .= " fk_mode_reglement=".(isset($this->mode_reglement_id) ? (int) $this->mode_reglement_id : "null").","; $sql .= " date_lim_reglement=".(strval($this->date_lim_reglement) != '' ? "'".$this->db->idate($this->date_lim_reglement)."'" : 'null').","; $sql .= " note_private=".(isset($this->note_private) ? "'".$this->db->escape($this->note_private)."'" : "null").","; $sql .= " note_public=".(isset($this->note_public) ? "'".$this->db->escape($this->note_public)."'" : "null").","; diff --git a/htdocs/core/boxes/modules_boxes.php b/htdocs/core/boxes/modules_boxes.php index 1bfd9688e2c..9be28e8bfc0 100644 --- a/htdocs/core/boxes/modules_boxes.php +++ b/htdocs/core/boxes/modules_boxes.php @@ -168,7 +168,8 @@ class ModeleBoxes // Can't be abstract as it is instantiated to build "empty" bo $sql .= " FROM ".MAIN_DB_PREFIX."boxes as b"; $sql .= " WHERE b.entity = ".$conf->entity; $sql .= " AND b.rowid = ".((int) $rowid); - dol_syslog(get_class($this)."::fetch rowid=".$rowid); + + dol_syslog(get_class($this)."::fetch rowid=".((int) $rowid)); $resql = $this->db->query($sql); if ($resql) { @@ -202,7 +203,7 @@ class ModeleBoxes // Can't be abstract as it is instantiated to build "empty" bo global $langs, $user, $conf; if (!empty($this->hidden)) { - return '\n\n'; // Nothing done if hidden (for example when user has no permission) + return "\n\n"; // Nothing done if hidden (for example when user has no permission) } require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php'; diff --git a/htdocs/core/class/commonobject.class.php b/htdocs/core/class/commonobject.class.php index f266588d090..f40841ba11b 100644 --- a/htdocs/core/class/commonobject.class.php +++ b/htdocs/core/class/commonobject.class.php @@ -10268,14 +10268,15 @@ abstract class CommonObject /** * Delete all child object from a parent ID * - * @param int $parentId Parent Id - * @param string $parentField Name of Foreign key parent column - * @param array $filter an array filter - * @param string $filtermode AND or OR - * @return int Return integer <0 if KO, >0 if OK - * @throws Exception + * @param int $parentId Parent Id + * @param string $parentField Name of Foreign key parent column + * @param string $filter Filter as an Universal Search string. + * Example: '((client:=:1) OR ((client:>=:2) AND (client:<=:3))) AND (client:!=:8) AND (nom:like:'a%')' + * @param string $filtermode No more used + * @return int Return integer <0 if KO, >0 if OK + * @throws Exception */ - public function deleteByParentField($parentId = 0, $parentField = '', $filter = array(), $filtermode = "AND") + public function deleteByParentField($parentId = 0, $parentField = '', $filter = '', $filtermode = "AND") { global $user; @@ -10288,21 +10289,13 @@ abstract class CommonObject $sql = "SELECT rowid FROM ".$this->db->prefix().$this->table_element; $sql .= " WHERE ".$parentField." = ".(int) $parentId; - // Manage filters - $sqlwhere = array(); - if (count($filter) > 0) { - foreach ($filter as $key => $value) { - if ($key == 'customsql') { - $sqlwhere[] = $value; - } elseif (strpos($value, '%') === false) { - $sqlwhere[] = $key." IN (".$this->db->sanitize($this->db->escape($value)).")"; - } else { - $sqlwhere[] = $key." LIKE '%".$this->db->escape($value)."%'"; - } - } - } - if (count($sqlwhere) > 0) { - $sql .= " AND (".implode(" ".$filtermode." ", $sqlwhere).")"; + // Manage filter + $errormessage = ''; + $sql .= forgeSQLFromUniversalSearchCriteria($filter, $errormessage); + if ($errormessage) { + $this->errors[] = $errormessage; + dol_syslog(__METHOD__.' '.join(',', $this->errors), LOG_ERR); + return -1; } $resql = $this->db->query($sql); diff --git a/htdocs/core/class/timespent.class.php b/htdocs/core/class/timespent.class.php index 36cedd67896..23544f73edd 100644 --- a/htdocs/core/class/timespent.class.php +++ b/htdocs/core/class/timespent.class.php @@ -321,15 +321,16 @@ class TimeSpent extends CommonObject /** * Load list of objects in memory from the database. * - * @param string $sortorder Sort Order - * @param string $sortfield Sort field - * @param int $limit limit - * @param int $offset Offset - * @param array $filter Filter array. Example array('field'=>'valueforlike', 'customurl'=>...) - * @param string $filtermode Filter mode (AND or OR) - * @return array|int int <0 if KO, array of pages if OK + * @param string $sortorder Sort Order + * @param string $sortfield Sort field + * @param int $limit limit + * @param int $offset Offset + * @param string $filter Filter as an Universal Search string. + * Example: '((client:=:1) OR ((client:>=:2) AND (client:<=:3))) AND (client:!=:8) AND (nom:like:'a%')' + * @param string $filtermode No more used + * @return array|int int <0 if KO, array of pages if OK */ - public function fetchAll($sortorder = '', $sortfield = '', $limit = 0, $offset = 0, array $filter = array(), $filtermode = 'AND') + public function fetchAll($sortorder = '', $sortfield = '', $limit = 0, $offset = 0, $filter = '', $filtermode = 'AND') { global $conf; @@ -345,25 +346,14 @@ class TimeSpent extends CommonObject } else { $sql .= " WHERE 1 = 1"; } + // Manage filter - $sqlwhere = array(); - if (count($filter) > 0) { - foreach ($filter as $key => $value) { - if ($key == 't.rowid') { - $sqlwhere[] = $key." = ".((int) $value); - } elseif (array_key_exists($key, $this->fields) && in_array($this->fields[$key]['type'], array('date', 'datetime', 'timestamp'))) { - $sqlwhere[] = $key." = '".$this->db->idate($value)."'"; - } elseif ($key == 'customsql') { - $sqlwhere[] = $value; - } elseif (strpos($value, '%') === false) { - $sqlwhere[] = $key." IN (".$this->db->sanitize($this->db->escape($value)).")"; - } else { - $sqlwhere[] = $key." LIKE '%".$this->db->escape($value)."%'"; - } - } - } - if (count($sqlwhere) > 0) { - $sql .= " AND (".implode(" ".$filtermode." ", $sqlwhere).")"; + $errormessage = ''; + $sql .= forgeSQLFromUniversalSearchCriteria($filter, $errormessage); + if ($errormessage) { + $this->errors[] = $errormessage; + dol_syslog(__METHOD__.' '.join(',', $this->errors), LOG_ERR); + return -1; } if (!empty($sortfield)) { diff --git a/htdocs/core/lib/functions.lib.php b/htdocs/core/lib/functions.lib.php index 6780c85e858..afdcc39cb52 100644 --- a/htdocs/core/lib/functions.lib.php +++ b/htdocs/core/lib/functions.lib.php @@ -12697,6 +12697,9 @@ function jsonOrUnserialize($stringtodecode) */ function forgeSQLFromUniversalSearchCriteria($filter, &$errorstr = '', $noand = 0, $nopar = 0, $noerror = 0) { + if ($filter === '') { + return ''; + } if (!preg_match('/^\(.*\)$/', $filter)) { // If $filter does not start and end with () $filter = '(' . $filter . ')'; } diff --git a/htdocs/core/modules/DolibarrModules.class.php b/htdocs/core/modules/DolibarrModules.class.php index 5a708ecac02..520a7ecc1f1 100644 --- a/htdocs/core/modules/DolibarrModules.class.php +++ b/htdocs/core/modules/DolibarrModules.class.php @@ -1746,7 +1746,7 @@ class DolibarrModules // Can not be abstract, because we need to instantiate it return 0; } - dol_syslog(get_class($this)."::insert_const", LOG_DEBUG); + dol_syslog(__METHOD__, LOG_DEBUG); foreach ($this->const as $key => $value) { $name = $this->const[$key][0]; @@ -1788,7 +1788,7 @@ class DolibarrModules // Can not be abstract, because we need to instantiate it $err++; } } else { - dol_syslog(get_class($this)."::insert_const constant '".$name."' already exists", LOG_DEBUG); + dol_syslog(__METHOD__." constant '".$name."' already exists", LOG_DEBUG); } } else { $err++; diff --git a/htdocs/core/modules/modBookCal.class.php b/htdocs/core/modules/modBookCal.class.php index aea486d455a..6ae92d3142a 100644 --- a/htdocs/core/modules/modBookCal.class.php +++ b/htdocs/core/modules/modBookCal.class.php @@ -584,10 +584,10 @@ class modBookCal extends DolibarrModules } $sql = array_merge($sql, array( - "DELETE FROM ".MAIN_DB_PREFIX."document_model WHERE nom = 'standard_".strtolower($myTmpObjectKey)."' AND type = '".$this->db->escape(strtolower($myTmpObjectKey))."' AND entity = ".((int) $conf->entity), - "INSERT INTO ".MAIN_DB_PREFIX."document_model (nom, type, entity) VALUES('standard_".strtolower($myTmpObjectKey)."', '".$this->db->escape(strtolower($myTmpObjectKey))."', ".((int) $conf->entity).")", - "DELETE FROM ".MAIN_DB_PREFIX."document_model WHERE nom = 'generic_".strtolower($myTmpObjectKey)."_odt' AND type = '".$this->db->escape(strtolower($myTmpObjectKey))."' AND entity = ".((int) $conf->entity), - "INSERT INTO ".MAIN_DB_PREFIX."document_model (nom, type, entity) VALUES('generic_".strtolower($myTmpObjectKey)."_odt', '".$this->db->escape(strtolower($myTmpObjectKey))."', ".((int) $conf->entity).")" + "DELETE FROM ".MAIN_DB_PREFIX."document_model WHERE nom = 'standard_".$this->db->escape(strtolower($myTmpObjectKey))."' AND type = '".$this->db->escape(strtolower($myTmpObjectKey))."' AND entity = ".((int) $conf->entity), + "INSERT INTO ".MAIN_DB_PREFIX."document_model (nom, type, entity) VALUES('standard_".$this->db->escape(strtolower($myTmpObjectKey))."', '".$this->db->escape(strtolower($myTmpObjectKey))."', ".((int) $conf->entity).")", + "DELETE FROM ".MAIN_DB_PREFIX."document_model WHERE nom = 'generic_".$this->db->escape(strtolower($myTmpObjectKey))."_odt' AND type = '".$this->db->escape(strtolower($myTmpObjectKey))."' AND entity = ".((int) $conf->entity), + "INSERT INTO ".MAIN_DB_PREFIX."document_model (nom, type, entity) VALUES('generic_".$this->db->escape(strtolower($myTmpObjectKey))."_odt', '".$this->db->escape(strtolower($myTmpObjectKey))."', ".((int) $conf->entity).")" )); } } diff --git a/htdocs/hrm/class/evaluation.class.php b/htdocs/hrm/class/evaluation.class.php index be133e09c62..50d2dce5c1c 100644 --- a/htdocs/hrm/class/evaluation.class.php +++ b/htdocs/hrm/class/evaluation.class.php @@ -390,8 +390,9 @@ class Evaluation extends CommonObject * @param string $sortfield Sort field * @param int $limit limit * @param int $offset Offset - * @param array $filter Filter array. Example array('field'=>'valueforlike', 'customurl'=>...) - * @param string $filtermode Filter mode (AND or OR) + * @param string $filter Filter as an Universal Search string. + * Example: '((client:=:1) OR ((client:>=:2) AND (client:<=:3))) AND (client:!=:8) AND (nom:like:'a%')' + * @param string $filtermode No more used * @return array|int int <0 if KO, array of pages if OK */ public function fetchAll($sortorder = '', $sortfield = '', $limit = 0, $offset = 0, array $filter = array(), $filtermode = 'AND') @@ -410,25 +411,14 @@ class Evaluation extends CommonObject } else { $sql .= ' WHERE 1 = 1'; } + // Manage filter - $sqlwhere = array(); - if (count($filter) > 0) { - foreach ($filter as $key => $value) { - if ($key == 't.rowid') { - $sqlwhere[] = $key.'='.$value; - } elseif (array_key_exists($key, $this->fields) && in_array($this->fields[$key]['type'], array('date', 'datetime', 'timestamp'))) { - $sqlwhere[] = $key.' = \''.$this->db->idate($value).'\''; - } elseif ($key == 'customsql') { - $sqlwhere[] = $value; - } elseif (strpos($value, '%') === false) { - $sqlwhere[] = $key.' IN ('.$this->db->sanitize($this->db->escape($value)).')'; - } else { - $sqlwhere[] = $key.' LIKE \'%'.$this->db->escape($value).'%\''; - } - } - } - if (count($sqlwhere) > 0) { - $sql .= " AND (".implode(" ".$filtermode." ", $sqlwhere).")"; + $errormessage = ''; + $sql .= forgeSQLFromUniversalSearchCriteria($filter, $errormessage); + if ($errormessage) { + $this->errors[] = $errormessage; + dol_syslog(__METHOD__.' '.join(',', $this->errors), LOG_ERR); + return -1; } if (!empty($sortfield)) { diff --git a/htdocs/hrm/class/evaluationdet.class.php b/htdocs/hrm/class/evaluationdet.class.php index 216b5ff1704..247e9feaeb4 100644 --- a/htdocs/hrm/class/evaluationdet.class.php +++ b/htdocs/hrm/class/evaluationdet.class.php @@ -356,8 +356,9 @@ class EvaluationLine extends CommonObjectLine * @param string $sortfield Sort field * @param int $limit limit * @param int $offset Offset - * @param array $filter Filter array. Example array('field'=>'valueforlike', 'customurl'=>...) - * @param string $filtermode Filter mode (AND or OR) + * @param string $filter Filter as an Universal Search string. + * Example: '((client:=:1) OR ((client:>=:2) AND (client:<=:3))) AND (client:!=:8) AND (nom:like:'a%')' + * @param string $filtermode No more used * @return array|int int <0 if KO, array of pages if OK */ public function fetchAll($sortorder = '', $sortfield = '', $limit = 0, $offset = 0, array $filter = array(), $filtermode = 'AND') @@ -376,25 +377,14 @@ class EvaluationLine extends CommonObjectLine } else { $sql .= ' WHERE 1 = 1'; } + // Manage filter - $sqlwhere = array(); - if (count($filter) > 0) { - foreach ($filter as $key => $value) { - if ($key == 't.rowid') { - $sqlwhere[] = $key.'='.$value; - } elseif ($key == 'customsql') { - $sqlwhere[] = $value; - } elseif (array_key_exists($key, $this->fields) && in_array($this->fields[$key]['type'], array('date', 'datetime', 'timestamp'))) { - $sqlwhere[] = $key.' = \''.$this->db->idate($value).'\''; - } elseif (strpos($value, '%') === false) { - $sqlwhere[] = $key.' IN ('.$this->db->sanitize($this->db->escape($value)).')'; - } else { - $sqlwhere[] = $key.' LIKE \'%'.$this->db->escape($value).'%\''; - } - } - } - if (count($sqlwhere) > 0) { - $sql .= " AND (".implode(" ".$filtermode." ", $sqlwhere).")"; + $errormessage = ''; + $sql .= forgeSQLFromUniversalSearchCriteria($filter, $errormessage); + if ($errormessage) { + $this->errors[] = $errormessage; + dol_syslog(__METHOD__.' '.join(',', $this->errors), LOG_ERR); + return -1; } if (!empty($sortfield)) { diff --git a/htdocs/hrm/class/job.class.php b/htdocs/hrm/class/job.class.php index 743a5f75e02..4799957bae6 100644 --- a/htdocs/hrm/class/job.class.php +++ b/htdocs/hrm/class/job.class.php @@ -360,8 +360,9 @@ class Job extends CommonObject * @param string $sortfield Sort field * @param int $limit limit * @param int $offset Offset - * @param array $filter Filter array. Example array('field'=>'valueforlike', 'customurl'=>...) - * @param string $filtermode Filter mode (AND or OR) + * @param string $filter Filter as an Universal Search string. + * Example: '((client:=:1) OR ((client:>=:2) AND (client:<=:3))) AND (client:!=:8) AND (nom:like:'a%')' + * @param string $filtermode No more used * @return array|int int <0 if KO, array of pages if OK */ public function fetchAll($sortorder = '', $sortfield = '', $limit = 0, $offset = 0, array $filter = array(), $filtermode = 'AND') @@ -380,25 +381,14 @@ class Job extends CommonObject } else { $sql .= ' WHERE 1 = 1'; } + // Manage filter - $sqlwhere = array(); - if (count($filter) > 0) { - foreach ($filter as $key => $value) { - if ($key == 't.rowid') { - $sqlwhere[] = $key.'='.$value; - } elseif (array_key_exists($key, $this->fields) && in_array($this->fields[$key]['type'], array('date', 'datetime', 'timestamp'))) { - $sqlwhere[] = $key.' = \''.$this->db->idate($value).'\''; - } elseif ($key == 'customsql') { - $sqlwhere[] = $value; - } elseif (strpos($value, '%') === false) { - $sqlwhere[] = $key.' IN ('.$this->db->sanitize($this->db->escape($value)).')'; - } else { - $sqlwhere[] = $key.' LIKE \'%'.$this->db->escape($value).'%\''; - } - } - } - if (count($sqlwhere) > 0) { - $sql .= " AND (".implode(" ".$filtermode." ", $sqlwhere).")"; + $errormessage = ''; + $sql .= forgeSQLFromUniversalSearchCriteria($filter, $errormessage); + if ($errormessage) { + $this->errors[] = $errormessage; + dol_syslog(__METHOD__.' '.join(',', $this->errors), LOG_ERR); + return -1; } if (!empty($sortfield)) { diff --git a/htdocs/hrm/class/position.class.php b/htdocs/hrm/class/position.class.php index 14fe2f18be4..18f28abb5ac 100644 --- a/htdocs/hrm/class/position.class.php +++ b/htdocs/hrm/class/position.class.php @@ -369,8 +369,9 @@ class Position extends CommonObject * @param string $sortfield Sort field * @param int $limit limit * @param int $offset Offset - * @param array $filter Filter array. Example array('field'=>'valueforlike', 'customurl'=>...) - * @param string $filtermode Filter mode (AND or OR) + * @param string $filter Filter as an Universal Search string. + * Example: '((client:=:1) OR ((client:>=:2) AND (client:<=:3))) AND (client:!=:8) AND (nom:like:'a%')' + * @param string $filtermode No more used * @return array|int int <0 if KO, array of pages if OK */ public function fetchAll($sortorder = '', $sortfield = '', $limit = 0, $offset = 0, array $filter = array(), $filtermode = 'AND') @@ -389,25 +390,14 @@ class Position extends CommonObject } else { $sql .= ' WHERE 1 = 1'; } + // Manage filter - $sqlwhere = array(); - if (count($filter) > 0) { - foreach ($filter as $key => $value) { - if ($key == 't.rowid') { - $sqlwhere[] = $key . '=' . $value; - } elseif ($key == 'customsql') { - $sqlwhere[] = $value; - } elseif (array_key_exists($key, $this->fields) && in_array($this->fields[$key]['type'], array('date', 'datetime', 'timestamp'))) { - $sqlwhere[] = $key . ' = \'' . $this->db->idate($value) . '\''; - } elseif (strpos($value, '%') === false) { - $sqlwhere[] = $key . ' IN (' . $this->db->sanitize($this->db->escape($value)) . ')'; - } else { - $sqlwhere[] = $key . ' LIKE \'%' . $this->db->escape($value) . '%\''; - } - } - } - if (count($sqlwhere) > 0) { - $sql .= " AND (".implode(" ".$filtermode." ", $sqlwhere).")"; + $errormessage = ''; + $sql .= forgeSQLFromUniversalSearchCriteria($filter, $errormessage); + if ($errormessage) { + $this->errors[] = $errormessage; + dol_syslog(__METHOD__.' '.join(',', $this->errors), LOG_ERR); + return -1; } if (!empty($sortfield)) { diff --git a/htdocs/hrm/class/skill.class.php b/htdocs/hrm/class/skill.class.php index 6d3be881130..60292ff94d8 100644 --- a/htdocs/hrm/class/skill.class.php +++ b/htdocs/hrm/class/skill.class.php @@ -428,8 +428,9 @@ class Skill extends CommonObject * @param string $sortfield Sort field * @param int $limit limit * @param int $offset Offset - * @param array $filter Filter array. Example array('field'=>'valueforlike', 'customurl'=>...) - * @param string $filtermode Filter mode (AND or OR) + * @param string $filter Filter as an Universal Search string. + * Example: '((client:=:1) OR ((client:>=:2) AND (client:<=:3))) AND (client:!=:8) AND (nom:like:'a%')' + * @param string $filtermode No more used * @return array|int int <0 if KO, array of pages if OK */ public function fetchAll($sortorder = '', $sortfield = '', $limit = 0, $offset = 0, array $filter = array(), $filtermode = 'AND') @@ -448,25 +449,14 @@ class Skill extends CommonObject } else { $sql .= ' WHERE 1 = 1'; } + // Manage filter - $sqlwhere = array(); - if (count($filter) > 0) { - foreach ($filter as $key => $value) { - if ($key == 't.rowid') { - $sqlwhere[] = $key.'='.$value; - } elseif (array_key_exists($key, $this->fields) && in_array($this->fields[$key]['type'], array('date', 'datetime', 'timestamp'))) { - $sqlwhere[] = $key.' = \''.$this->db->idate($value).'\''; - } elseif ($key == 'customsql') { - $sqlwhere[] = $value; - } elseif (strpos($value, '%') === false) { - $sqlwhere[] = $key.' IN ('.$this->db->sanitize($this->db->escape($value)).')'; - } else { - $sqlwhere[] = $key.' LIKE \'%'.$this->db->escape($value).'%\''; - } - } - } - if (count($sqlwhere) > 0) { - $sql .= " AND (".implode(" ".$filtermode." ", $sqlwhere).")"; + $errormessage = ''; + $sql .= forgeSQLFromUniversalSearchCriteria($filter, $errormessage); + if ($errormessage) { + $this->errors[] = $errormessage; + dol_syslog(__METHOD__.' '.join(',', $this->errors), LOG_ERR); + return -1; } if (!empty($sortfield)) { diff --git a/htdocs/hrm/class/skilldet.class.php b/htdocs/hrm/class/skilldet.class.php index 8865aa94db8..fb69b0454cd 100644 --- a/htdocs/hrm/class/skilldet.class.php +++ b/htdocs/hrm/class/skilldet.class.php @@ -351,8 +351,9 @@ class Skilldet extends CommonObjectLine * @param string $sortfield Sort field * @param int $limit limit * @param int $offset Offset - * @param array $filter Filter array. Example array('field'=>'valueforlike', 'customurl'=>...) - * @param string $filtermode Filter mode (AND or OR) + * @param string $filter Filter as an Universal Search string. + * Example: '((client:=:1) OR ((client:>=:2) AND (client:<=:3))) AND (client:!=:8) AND (nom:like:'a%')' + * @param string $filtermode No more used * @return array|int int <0 if KO, array of pages if OK */ public function fetchAll($sortorder = '', $sortfield = '', $limit = 0, $offset = 0, array $filter = array(), $filtermode = 'AND') @@ -371,25 +372,14 @@ class Skilldet extends CommonObjectLine } else { $sql .= ' WHERE 1 = 1'; } + // Manage filter - $sqlwhere = array(); - if (count($filter) > 0) { - foreach ($filter as $key => $value) { - if ($key == 't.rowid') { - $sqlwhere[] = $key.'='.$value; - } elseif ($key == 'customsql') { - $sqlwhere[] = $value; - } elseif (array_key_exists($key, $this->fields) && in_array($this->fields[$key]['type'], array('date', 'datetime', 'timestamp'))) { - $sqlwhere[] = $key." = '".$this->db->idate($value)."'"; - } elseif (strpos($value, '%') === false) { - $sqlwhere[] = $key." IN (".$this->db->sanitize($this->db->escape($value)).")"; - } else { - $sqlwhere[] = $key." LIKE '%".$this->db->escape($value)."%'"; - } - } - } - if (count($sqlwhere) > 0) { - $sql .= " AND (".implode(" ".$filtermode." ", $sqlwhere).")"; + $errormessage = ''; + $sql .= forgeSQLFromUniversalSearchCriteria($filter, $errormessage); + if ($errormessage) { + $this->errors[] = $errormessage; + dol_syslog(__METHOD__.' '.join(',', $this->errors), LOG_ERR); + return -1; } if (!empty($sortfield)) { diff --git a/htdocs/hrm/class/skillrank.class.php b/htdocs/hrm/class/skillrank.class.php index 788cf2a1ded..9babe71a842 100644 --- a/htdocs/hrm/class/skillrank.class.php +++ b/htdocs/hrm/class/skillrank.class.php @@ -399,8 +399,9 @@ class SkillRank extends CommonObject * @param string $sortfield Sort field * @param int $limit limit * @param int $offset Offset - * @param array $filter Filter array. Example array('field'=>'valueforlike', 'customurl'=>...) - * @param string $filtermode Filter mode (AND or OR) + * @param string $filter Filter as an Universal Search string. + * Example: '((client:=:1) OR ((client:>=:2) AND (client:<=:3))) AND (client:!=:8) AND (nom:like:'a%')' + * @param string $filtermode No more used * @return array|int int <0 if KO, array of pages if OK */ public function fetchAll($sortorder = '', $sortfield = '', $limit = 0, $offset = 0, array $filter = array(), $filtermode = 'AND') @@ -419,25 +420,14 @@ class SkillRank extends CommonObject } else { $sql .= ' WHERE 1 = 1'; } + // Manage filter - $sqlwhere = array(); - if (count($filter) > 0) { - foreach ($filter as $key => $value) { - if ($key == 't.rowid') { - $sqlwhere[] = $key." = ".((int) $value); - } elseif (array_key_exists($key, $this->fields) && $key != 'customsql' && in_array($this->fields[$key]['type'], array('date', 'datetime', 'timestamp'))) { - $sqlwhere[] = $key." = '".$this->db->idate($value)."'"; - } elseif ($key == 'customsql') { - $sqlwhere[] = $value; - } elseif (strpos($value, '%') === false) { - $sqlwhere[] = $key." IN (".$this->db->sanitize($this->db->escape($value)).")"; - } else { - $sqlwhere[] = $key." LIKE '%".$this->db->escape($value)."%'"; - } - } - } - if (count($sqlwhere) > 0) { - $sql .= " AND (".implode(" ".$filtermode." ", $sqlwhere).")"; + $errormessage = ''; + $sql .= forgeSQLFromUniversalSearchCriteria($filter, $errormessage); + if ($errormessage) { + $this->errors[] = $errormessage; + dol_syslog(__METHOD__.' '.join(',', $this->errors), LOG_ERR); + return -1; } if (!empty($sortfield)) { diff --git a/htdocs/install/upgrade2.php b/htdocs/install/upgrade2.php index f7d513d4e3f..536d9d7bee5 100644 --- a/htdocs/install/upgrade2.php +++ b/htdocs/install/upgrade2.php @@ -1575,7 +1575,7 @@ function migrate_price_facture($db, $langs, $conf) $facligne->total_ttc = $total_ttc; dolibarr_install_syslog("upgrade2: line ".$rowid.": facid=".$obj->facid." pu=".$pu." qty=".$qty." vatrate=".$vatrate." remise_percent=".$remise_percent." remise_global=".$remise_percent_global." -> ".$total_ht.", ".$total_tva.", ".$total_ttc); - print ". "; + print '. '; $facligne->update_total(); @@ -1676,29 +1676,9 @@ function migrate_price_propal($db, $langs, $conf) $propalligne->total_ttc = $total_ttc; dolibarr_install_syslog("upgrade2: Line ".$rowid.": propalid=".$obj->rowid." pu=".$pu." qty=".$qty." vatrate=".$vatrate." remise_percent=".$remise_percent." remise_global=".$remise_percent_global." -> ".$total_ht.", ".$total_tva.", ".$total_ttc); - print ". "; + print '. '; $propalligne->update_total(); - - /* On touche pas a propal mere - $propal = new Propal($db); - $propal->id=$obj->rowid; - if ( $propal->fetch($propal->id) >= 0 ) - { - if ( $propal->update_price() > 0 ) - { - print ". "; - } - else - { - print "Error id=".$propal->id; - } - } - else - { - print "Error #3"; - } - */ $i++; } } else { @@ -1780,7 +1760,7 @@ function migrate_price_contrat($db, $langs, $conf) $contratligne->total_ttc = $total_ttc; dolibarr_install_syslog("upgrade2: Line ".$rowid.": contratdetid=".$obj->rowid." pu=".$pu." qty=".$qty." vatrate=".$vatrate." remise_percent=".$remise_percent." -> ".$total_ht.", ".$total_tva." , ".$total_ttc); - print ". "; + print '. '; $contratligne->update_total(); $i++; @@ -1861,28 +1841,9 @@ function migrate_price_commande($db, $langs, $conf) $commandeligne->total_ttc = $total_ttc; dolibarr_install_syslog("upgrade2: Line ".$rowid." : commandeid=".$obj->rowid." pu=".$pu." qty=".$qty." vatrate=".$vatrate." remise_percent=".$remise_percent." remise_global=".$remise_percent_global." -> ".$total_ht.", ".$total_tva.", ".$total_ttc); - print ". "; + print '. '; $commandeligne->update_total(); - /* On touche pas a facture mere - $commande = new Commande($db); - $commande->id = $obj->rowid; - if ( $commande->fetch($commande->id) >= 0 ) - { - if ( $commande->update_price() > 0 ) - { - print ". "; - } - else - { - print "Error id=".$commande->id; - } - } - else - { - print "Error #3"; - } - */ $i++; } } else { @@ -1973,28 +1934,9 @@ function migrate_price_commande_fournisseur($db, $langs, $conf) $commandeligne->total_ttc = $total_ttc; dolibarr_install_syslog("upgrade2: Line ".$rowid.": commandeid=".$obj->rowid." pu=".$pu." qty=".$qty." vatrate=".$vatrate." remise_percent=".$remise_percent." remise_global=".$remise_percent_global." -> ".$total_ht.", ".$total_tva.", ".$total_ttc); - print ". "; + print '. '; $commandeligne->update_total(); - /* On touche pas a facture mere - $commande = new Commande($db); - $commande->id = $obj->rowid; - if ( $commande->fetch($commande->id) >= 0 ) - { - if ( $commande->update_price() > 0 ) - { - print ". "; - } - else - { - print "Error id=".$commande->id; - } - } - else - { - print "Error #3"; - } - */ $i++; } } else { @@ -2125,7 +2067,7 @@ function migrate_commande_expedition($db, $langs, $conf) $error++; dol_print_error($db); } - print ". "; + print '. '; $i++; } } @@ -2205,7 +2147,7 @@ function migrate_commande_livraison($db, $langs, $conf) $error++; dol_print_error($db); } - print ". "; + print '. '; $i++; } } @@ -2301,7 +2243,7 @@ function migrate_detail_livraison($db, $langs, $conf) $error++; dol_print_error($db); } - print ". "; + print '. '; $i++; } } @@ -2373,7 +2315,7 @@ function migrate_stocks($db, $langs, $conf) $error++; dol_print_error($db); } - print ". "; + print '. '; $i++; } } @@ -2437,7 +2379,7 @@ function migrate_menus($db, $langs, $conf) $error++; dol_print_error($db); } - print ". "; + print '. '; $i++; } } @@ -2505,7 +2447,7 @@ function migrate_commande_deliveryaddress($db, $langs, $conf) $error++; dol_print_error($db); } - print ". "; + print '. '; $i++; } } else { @@ -2589,7 +2531,7 @@ function migrate_restore_missing_links($db, $langs, $conf) $error++; dol_print_error($db); } - //print ". "; + //print '. '; $i++; } } else { @@ -2648,7 +2590,7 @@ function migrate_restore_missing_links($db, $langs, $conf) $error++; dol_print_error($db); } - //print ". "; + //print '. '; $i++; } } else { @@ -2725,7 +2667,7 @@ function migrate_project_user_resp($db, $langs, $conf) dol_print_error($db); } } - print ". "; + print '. '; $i++; } @@ -2803,7 +2745,7 @@ function migrate_project_task_actors($db, $langs, $conf) $error++; dol_print_error($db); } - print ". "; + print '. '; $i++; } } @@ -2884,7 +2826,7 @@ function migrate_relationship_tables($db, $langs, $conf, $table, $fk_source, $so $error++; dol_print_error($db); } - print ". "; + print '. '; $i++; } } else { @@ -2964,7 +2906,7 @@ function migrate_element_time($db, $langs, $conf) $error++; dol_print_error($db); } - print ". "; + print '. '; $oldtime++; if (!empty($totaltime[$obj->fk_element])) { $totaltime[$obj->fk_element] += $newtime; @@ -3073,7 +3015,7 @@ function migrate_customerorder_shipping($db, $langs, $conf) $error++; dol_print_error($db); } - print ". "; + print '. '; $i++; } } else { @@ -3160,7 +3102,7 @@ function migrate_shipping_delivery($db, $langs, $conf) $error++; dol_print_error($db); } - print ". "; + print '. '; } else { $error++; dol_print_error($db); @@ -3248,7 +3190,7 @@ function migrate_shipping_delivery2($db, $langs, $conf) $error++; dol_print_error($db); } - print ". "; + print '. '; $i++; } } else { @@ -3315,7 +3257,7 @@ function migrate_actioncomm_element($db, $langs, $conf) // We will drop at next version because a migrate should be runnable several times if it fails. //$sqlDrop = "ALTER TABLE ".MAIN_DB_PREFIX."actioncomm DROP COLUMN ".$field; //$db->query($sqlDrop); - //print ". "; + //print '. '; } else { dol_print_error($db); $db->rollback(); @@ -3392,7 +3334,7 @@ function migrate_mode_reglement($db, $langs, $conf) dol_print_error($db); $error++; } - print ". "; + print '. '; } if (!$error) { @@ -3536,7 +3478,7 @@ function migrate_categorie_association($db, $langs, $conf) $error++; dol_print_error($db); } - print ". "; + print '. '; $i++; } } else { @@ -3604,7 +3546,7 @@ function migrate_event_assignement($db, $langs, $conf) $error++; dol_print_error($db); } - print ". "; + print '. '; $i++; } } else { @@ -3670,7 +3612,7 @@ function migrate_event_assignement_contact($db, $langs, $conf) $error++; dol_print_error($db); } - print ". "; + print '. '; $i++; } } else { @@ -3837,7 +3779,7 @@ function migrate_remise_entity($db, $langs, $conf) dol_print_error($db); } - print ". "; + print '. '; $i++; } } else { @@ -3928,7 +3870,7 @@ function migrate_remise_except_entity($db, $langs, $conf) dol_print_error($db); } - print ". "; + print '. '; $i++; } } else { @@ -3993,7 +3935,7 @@ function migrate_user_rights_entity($db, $langs, $conf) dol_print_error($db); } - print ". "; + print '. '; $i++; } } else { @@ -4058,7 +4000,7 @@ function migrate_usergroup_rights_entity($db, $langs, $conf) dol_print_error($db); } - print ". "; + print '. '; $i++; } } else { diff --git a/htdocs/langs/en_US/orders.lang b/htdocs/langs/en_US/orders.lang index acee379edad..b7b702892fb 100644 --- a/htdocs/langs/en_US/orders.lang +++ b/htdocs/langs/en_US/orders.lang @@ -99,7 +99,7 @@ ListOfOrders=List of orders ListOrderLigne=Lines of orders productobuy=Products to buy only productonly=Products only -disablelinefree=No free lines +disablelinefree=Predefined products only CloseOrder=Close order ConfirmCloseOrder=Are you sure you want to set this order to delivered? Once an order is delivered, it can be set to billed. ConfirmDeleteOrder=Are you sure you want to delete this order? diff --git a/htdocs/mailmanspip/class/mailmanspip.class.php b/htdocs/mailmanspip/class/mailmanspip.class.php index 462e553847e..9d9d065ed19 100644 --- a/htdocs/mailmanspip/class/mailmanspip.class.php +++ b/htdocs/mailmanspip/class/mailmanspip.class.php @@ -156,7 +156,7 @@ class MailmanSpip * Fonction qui donne les droits redacteurs dans spip * * @param Adherent $object Object with data (->firstname, ->lastname, ->email and ->login) - * @return int =0 if KO, >0 if OK + * @return int =0 if KO, >0 if OK */ public function add_to_spip($object) { @@ -171,7 +171,10 @@ class MailmanSpip require_once DOL_DOCUMENT_ROOT.'/core/lib/security2.lib.php'; $mdpass = dol_hash($object->pass); $htpass = crypt($object->pass, makesalt()); - $query = "INSERT INTO spip_auteurs (nom, email, login, pass, htpass, alea_futur, statut) VALUES(\"".dolGetFirstLastname($object->firstname, $object->lastname)."\",\"".$object->email."\",\"".$object->login."\",\"$mdpass\",\"$htpass\",FLOOR(32000*RAND()),\"1comite\")"; + + $query = "INSERT INTO spip_auteurs (nom, email, login, pass, htpass, alea_futur, statut)"; + $query .= " VALUES('".$mydb->escape(dolGetFirstLastname($object->firstname, $object->lastname))."', '".$mydb->escape($object->email)."',"; + $query .= " '".$mydb->escape($object->login)."', '".$mydb->escape($mdpass)."', '".$mydb->escape($htpass)."', FLOOR(32000*RAND()), '1comite')"; $result = $mydb->query($query); diff --git a/htdocs/modulebuilder/template/class/myobject.class.php b/htdocs/modulebuilder/template/class/myobject.class.php index c0363bbc5b6..7d8a3e0556a 100644 --- a/htdocs/modulebuilder/template/class/myobject.class.php +++ b/htdocs/modulebuilder/template/class/myobject.class.php @@ -442,7 +442,7 @@ class MyObject extends CommonObject * @param int $offset Offset * @param string $filter Filter as an Universal Search string. * Example: '((client:=:1) OR ((client:>=:2) AND (client:<=:3))) AND (client:!=:8) AND (nom:like:'a%')' - * @param string $filtermode Filter mode (AND or OR) + * @param string $filtermode No more used * @return array|int int <0 if KO, array of pages if OK */ public function fetchAll($sortorder = '', $sortfield = '', $limit = 1000, $offset = 0, string $filter = '', $filtermode = 'AND') @@ -462,63 +462,15 @@ class MyObject extends CommonObject } else { $sql .= " WHERE 1 = 1"; } - // Manage filter - /* We keep this part of code that is still used by a lot of old class. The 'else" shows how to switch to Universal Search filters - $sqlwhere = array(); - if (is_array($filter) && count($filter) > 0) { - dol_syslog("Warning: Use of an array as filter is now forbidden and deprecated. Use an universal SQL filter string instead", LOG_WARNING); - foreach ($filter as $key => $value) { - $columnName = preg_replace('/^t\./', '', $key); - if ($key === 'customsql') { - // Never use 'customsql' with a value from a user input since it is injected as is. The value must be hard coded. - $sqlwhere[] = $value; - continue; - } elseif (isset($this->fields[$columnName])) { - $type = $this->fields[$columnName]['type']; - if (preg_match('/^integer/', $type)) { - if (is_int($value)) { - // single value - $sqlwhere[] = $key . " = " . intval($value); - } elseif (is_array($value)) { - if (empty($value)) { - continue; - } - $sqlwhere[] = $key . ' IN (' . $this->db->sanitize(implode(',', array_map('intval', $value))) . ')'; - } - continue; - } elseif (in_array($type, array('date', 'datetime', 'timestamp'))) { - $sqlwhere[] = $key . " = '" . $this->db->idate($value) . "'"; - continue; - } - } - // when the $key doesn't fall into the previously handled categories, we do as if the column were a varchar/text - if (is_array($value) && count($value)) { - $value = implode(',', array_map(function ($v) { - return "'" . $this->db->sanitize($this->db->escape($v)) . "'"; - }, $value)); - $sqlwhere[] = $key . ' IN (' . $this->db->sanitize($value, true) . ')'; - } elseif (is_scalar($value)) { - if (strpos($value, '%') === false) { - $sqlwhere[] = $key . " = '" . $this->db->sanitize($this->db->escape($value)) . "'"; - } else { - $sqlwhere[] = $key . " LIKE '%" . $this->db->escape($this->db->escapeforlike($value)) . "%'"; - } - } - } - } else { */ + // Manage filter $errormessage = ''; $sql .= forgeSQLFromUniversalSearchCriteria($filter, $errormessage); if ($errormessage) { $this->errors[] = $errormessage; dol_syslog(__METHOD__.' '.join(',', $this->errors), LOG_ERR); - return -1; } - /*} - if (count($sqlwhere) > 0) { - $sql .= " AND (".implode(" ".$filtermode." ", $sqlwhere).")"; - }*/ if (!empty($sortfield)) { $sql .= $this->db->order($sortfield, $sortorder); diff --git a/htdocs/partnership/class/partnership_type.class.php b/htdocs/partnership/class/partnership_type.class.php index 06f7ab7b35c..97e87ce88e0 100644 --- a/htdocs/partnership/class/partnership_type.class.php +++ b/htdocs/partnership/class/partnership_type.class.php @@ -151,13 +151,14 @@ class PartnershipType extends CommonObject /** * Load list of objects in memory from the database. * - * @param string $sortorder Sort Order - * @param string $sortfield Sort field - * @param int $limit limit - * @param int $offset Offset - * @param array $filter Filter array. Example array('field'=>'valueforlike', 'customurl'=>...) - * @param string $filtermode Filter mode (AND or OR) - * @return array|int int <0 if KO, array of pages if OK + * @param string $sortorder Sort Order + * @param string $sortfield Sort field + * @param int $limit limit + * @param int $offset Offset + * @param string $filter Filter as an Universal Search string. + * Example: '((client:=:1) OR ((client:>=:2) AND (client:<=:3))) AND (client:!=:8) AND (nom:like:'a%')' + * @param string $filtermode No more used + * @return array|int int <0 if KO, array of pages if OK */ public function fetchAll($sortorder = '', $sortfield = '', $limit = 0, $offset = 0, array $filter = array(), $filtermode = 'AND') { @@ -175,25 +176,14 @@ class PartnershipType extends CommonObject } else { $sql .= " WHERE 1 = 1"; } + // Manage filter - $sqlwhere = array(); - if (count($filter) > 0) { - foreach ($filter as $key => $value) { - if ($key == 't.rowid') { - $sqlwhere[] = $key." = ".((int) $value); - } elseif (array_key_exists($key, $this->fields) && in_array($this->fields[$key]['type'], array('date', 'datetime', 'timestamp'))) { - $sqlwhere[] = $key." = '".$this->db->idate($value)."'"; - } elseif ($key == 'customsql') { - $sqlwhere[] = $value; - } elseif (strpos($value, '%') === false) { - $sqlwhere[] = $key." IN (".$this->db->sanitize($this->db->escape($value)).")"; - } else { - $sqlwhere[] = $key." LIKE '%".$this->db->escape($value)."%'"; - } - } - } - if (count($sqlwhere) > 0) { - $sql .= " AND (".implode(" ".$filtermode." ", $sqlwhere).")"; + $errormessage = ''; + $sql .= forgeSQLFromUniversalSearchCriteria($filter, $errormessage); + if ($errormessage) { + $this->errors[] = $errormessage; + dol_syslog(__METHOD__.' '.join(',', $this->errors), LOG_ERR); + return -1; } if (!empty($sortfield)) { diff --git a/htdocs/product/class/product.class.php b/htdocs/product/class/product.class.php index 262fbeaeb6c..feb1dde19ce 100644 --- a/htdocs/product/class/product.class.php +++ b/htdocs/product/class/product.class.php @@ -1697,7 +1697,7 @@ class Product extends CommonObject $sql2 .= ", note"; } $sql2 .= ")"; - $sql2 .= " VALUES(".$this->id.",'".$this->db->escape($key)."','".$this->db->escape($this->label)."',"; + $sql2 .= " VALUES(".((int) $this->id).",'".$this->db->escape($key)."','".$this->db->escape($this->label)."',"; $sql2 .= " '".$this->db->escape($this->description)."'"; if (getDolGlobalString('PRODUCT_USE_OTHER_FIELD_IN_TRANSLATION')) { $sql2 .= ", '".$this->db->escape($this->other)."'"; @@ -1737,7 +1737,7 @@ class Product extends CommonObject $sql2 .= ", note"; } $sql2 .= ")"; - $sql2 .= " VALUES(".$this->id.",'".$this->db->escape($key)."','".$this->db->escape($this->multilangs["$key"]["label"])."',"; + $sql2 .= " VALUES(".((int) $this->id).",'".$this->db->escape($key)."','".$this->db->escape($this->multilangs["$key"]["label"])."',"; $sql2 .= " '".$this->db->escape($this->multilangs["$key"]["description"])."'"; if (getDolGlobalString('PRODUCT_USE_OTHER_FIELD_IN_TRANSLATION')) { $sql2 .= ", '".$this->db->escape($this->multilangs["$key"]["other"])."'"; diff --git a/htdocs/product/class/productbatch.class.php b/htdocs/product/class/productbatch.class.php index a447910fe5d..2da779311c4 100644 --- a/htdocs/product/class/productbatch.class.php +++ b/htdocs/product/class/productbatch.class.php @@ -386,6 +386,7 @@ class Productbatch extends CommonObject public function find($fk_product_stock = 0, $eatby = null, $sellby = null, $batch_number = '', $fk_warehouse = 0) { $where = array(); + $sql = "SELECT"; $sql .= " t.rowid,"; $sql .= " t.tms,"; @@ -414,7 +415,7 @@ class Productbatch extends CommonObject } if (!empty($where)) { - $sql .= " AND (".implode(" OR ", $where).")"; + $sql .= " AND (".$this->db->sanitize(implode(" OR ", $where), 1, 1, 1).")"; } dol_syslog(get_class($this)."::fetch", LOG_DEBUG); diff --git a/htdocs/product/stock/stocktransfer/class/stocktransfer.class.php b/htdocs/product/stock/stocktransfer/class/stocktransfer.class.php index ed7c6394d61..75a74314c1f 100644 --- a/htdocs/product/stock/stocktransfer/class/stocktransfer.class.php +++ b/htdocs/product/stock/stocktransfer/class/stocktransfer.class.php @@ -407,18 +407,17 @@ class StockTransfer extends CommonObject /** * Load list of objects in memory from the database. * - * @param string $sortorder Sort Order - * @param string $sortfield Sort field - * @param int $limit limit - * @param int $offset Offset - * @param array $filter Filter array. Example array('field'=>'valueforlike', 'customurl'=>...) - * @param string $filtermode Filter mode (AND or OR) - * @return array|int int <0 if KO, array of pages if OK + * @param string $sortorder Sort Order + * @param string $sortfield Sort field + * @param int $limit limit + * @param int $offset Offset + * @param string $filter Filter as an Universal Search string. + * Example: '((client:=:1) OR ((client:>=:2) AND (client:<=:3))) AND (client:!=:8) AND (nom:like:'a%')' + * @param string $filtermode No more used + * @return array|int int <0 if KO, array of pages if OK */ - public function fetchAll($sortorder = '', $sortfield = '', $limit = 0, $offset = 0, array $filter = array(), $filtermode = 'AND') + public function fetchAll($sortorder = '', $sortfield = '', $limit = 0, $offset = 0, $filter = '', $filtermode = 'AND') { - global $conf; - dol_syslog(__METHOD__, LOG_DEBUG); $records = array(); @@ -431,23 +430,14 @@ class StockTransfer extends CommonObject } else { $sql .= ' WHERE 1 = 1'; } + // Manage filter - $sqlwhere = array(); - if (count($filter) > 0) { - foreach ($filter as $key => $value) { - if ($key == 't.rowid') { - $sqlwhere[] = $key.'='.$value; - } elseif (strpos($key, 'date') !== false) { - $sqlwhere[] = $key.' = \''.$this->db->idate($value).'\''; - } elseif ($key == 'customsql') { - $sqlwhere[] = $value; - } else { - $sqlwhere[] = $key.' LIKE \'%'.$this->db->escape($value).'%\''; - } - } - } - if (count($sqlwhere) > 0) { - $sql .= " AND (".implode(" ".$filtermode." ", $sqlwhere).")"; + $errormessage = ''; + $sql .= forgeSQLFromUniversalSearchCriteria($filter, $errormessage); + if ($errormessage) { + $this->errors[] = $errormessage; + dol_syslog(__METHOD__.' '.join(',', $this->errors), LOG_ERR); + return -1; } if (!empty($sortfield)) { diff --git a/htdocs/product/stock/stocktransfer/class/stocktransferline.class.php b/htdocs/product/stock/stocktransfer/class/stocktransferline.class.php index bc0c56baa3f..dbd2db3bce4 100644 --- a/htdocs/product/stock/stocktransfer/class/stocktransferline.class.php +++ b/htdocs/product/stock/stocktransfer/class/stocktransferline.class.php @@ -299,15 +299,16 @@ class StockTransferLine extends CommonObjectLine /** * Load list of objects in memory from the database. * - * @param string $sortorder Sort Order - * @param string $sortfield Sort field - * @param int $limit limit - * @param int $offset Offset - * @param array $filter Filter array. Example array('field'=>'valueforlike', 'customurl'=>...) - * @param string $filtermode Filter mode (AND or OR) - * @return array|int int <0 if KO, array of pages if OK + * @param string $sortorder Sort Order + * @param string $sortfield Sort field + * @param int $limit limit + * @param int $offset Offset + * @param string $filter Filter as an Universal Search string. + * Example: '((client:=:1) OR ((client:>=:2) AND (client:<=:3))) AND (client:!=:8) AND (nom:like:'a%')' + * @param string $filtermode No more used + * @return array|int int <0 if KO, array of pages if OK */ - public function fetchAll($sortorder = '', $sortfield = '', $limit = 0, $offset = 0, array $filter = array(), $filtermode = 'AND') + public function fetchAll($sortorder = '', $sortfield = '', $limit = 0, $offset = 0, $filter = '', $filtermode = 'AND') { dol_syslog(__METHOD__, LOG_DEBUG); @@ -321,23 +322,14 @@ class StockTransferLine extends CommonObjectLine } else { $sql .= ' WHERE 1 = 1'; } + // Manage filter - $sqlwhere = array(); - if (count($filter) > 0) { - foreach ($filter as $key => $value) { - if ($key == 't.rowid') { - $sqlwhere[] = $key.'='.$value; - } elseif (strpos($key, 'date') !== false) { - $sqlwhere[] = $key.' = \''.$this->db->idate($value).'\''; - } elseif ($key == 'customsql') { - $sqlwhere[] = $value; - } else { - $sqlwhere[] = $key.' LIKE \'%'.$this->db->escape($value).'%\''; - } - } - } - if (count($sqlwhere) > 0) { - $sql .= " AND (".implode(" ".$filtermode." ", $sqlwhere).")"; + $errormessage = ''; + $sql .= forgeSQLFromUniversalSearchCriteria($filter, $errormessage); + if ($errormessage) { + $this->errors[] = $errormessage; + dol_syslog(__METHOD__.' '.join(',', $this->errors), LOG_ERR); + return -1; } if (!empty($sortfield)) { diff --git a/htdocs/webhook/class/target.class.php b/htdocs/webhook/class/target.class.php index 6d538208dfa..1b7ae1004f3 100644 --- a/htdocs/webhook/class/target.class.php +++ b/htdocs/webhook/class/target.class.php @@ -362,11 +362,12 @@ class Target extends CommonObject * @param string $sortfield Sort field * @param int $limit limit * @param int $offset Offset - * @param array $filter Filter array. Example array('field'=>'valueforlike', 'customurl'=>...) - * @param string $filtermode Filter mode (AND or OR) + * @param string $filter Filter as an Universal Search string. + * Example: '((client:=:1) OR ((client:>=:2) AND (client:<=:3))) AND (client:!=:8) AND (nom:like:'a%')' + * @param string $filtermode No more used * @return array|int int <0 if KO, array of pages if OK */ - public function fetchAll($sortorder = '', $sortfield = '', $limit = 0, $offset = 0, array $filter = array(), $filtermode = 'AND') + public function fetchAll($sortorder = '', $sortfield = '', $limit = 0, $offset = 0, $filter = '', $filtermode = 'AND') { global $conf; @@ -382,25 +383,13 @@ class Target extends CommonObject } else { $sql .= " WHERE 1 = 1"; } - // Manage filter - $sqlwhere = array(); - if (count($filter) > 0) { - foreach ($filter as $key => $value) { - if ($key == 't.rowid') { - $sqlwhere[] = $key." = ".((int) $value); - } elseif (array_key_exists($key, $this->fields) && in_array($this->fields[$key]['type'], array('date', 'datetime', 'timestamp'))) { - $sqlwhere[] = $key." = '".$this->db->idate($value)."'"; - } elseif ($key == 'customsql') { - $sqlwhere[] = $value; - } elseif (strpos($value, '%') === false) { - $sqlwhere[] = $key." IN (".$this->db->sanitize($this->db->escape($value)).")"; - } else { - $sqlwhere[] = $key." LIKE '%".$this->db->escape($value)."%'"; - } - } - } - if (count($sqlwhere) > 0) { - $sql .= " AND (".implode(" ".$filtermode." ", $sqlwhere).")"; + + $errormessage = ''; + $sql .= forgeSQLFromUniversalSearchCriteria($filter, $errormessage); + if ($errormessage) { + $this->errors[] = $errormessage; + dol_syslog(__METHOD__.' '.join(',', $this->errors), LOG_ERR); + return -1; } if (!empty($sortfield)) { diff --git a/htdocs/website/class/websitepage.class.php b/htdocs/website/class/websitepage.class.php index 737e57ac3ec..bcaeca4bd7e 100644 --- a/htdocs/website/class/websitepage.class.php +++ b/htdocs/website/class/websitepage.class.php @@ -356,16 +356,17 @@ class WebsitePage extends CommonObject /** * Return array of all web site pages. * - * @param string $websiteid Web site - * @param string $sortorder Sort Order - * @param string $sortfield Sort field - * @param int $limit limit - * @param int $offset Offset - * @param array $filter Filter array - * @param string $filtermode Filter mode (AND or OR) - * @return array|int int <0 if KO, array of pages if OK + * @param string $websiteid Web site + * @param string $sortorder Sort Order + * @param string $sortfield Sort field + * @param int $limit limit + * @param int $offset Offset + * @param string $filter Filter as an Universal Search string. + * Example: '((client:=:1) OR ((client:>=:2) AND (client:<=:3))) AND (client:!=:8) AND (nom:like:'a%')' + * @param string $filtermode No more used + * @return array|int int <0 if KO, array of pages if OK */ - public function fetchAll($websiteid, $sortorder = '', $sortfield = '', $limit = 0, $offset = 0, array $filter = array(), $filtermode = 'AND') + public function fetchAll($websiteid, $sortorder = '', $sortfield = '', $limit = 0, $offset = 0, $filter = '', $filtermode = 'AND') { dol_syslog(__METHOD__, LOG_DEBUG); @@ -398,36 +399,13 @@ class WebsitePage extends CommonObject $sql .= " t.fk_object"; $sql .= ' FROM '.MAIN_DB_PREFIX.$this->table_element.' as t'; $sql .= ' WHERE t.fk_website = '.((int) $websiteid); - // Manage filter (same than into countAll) - $sqlwhere = array(); - if (count($filter) > 0) { - foreach ($filter as $key => $value) { - if ($key == 't.rowid' || $key == 'rowid' || $key == 't.fk_website' || $key == 'fk_website' || $key == 'status' || $key == 't.status') { - $sqlwhere[] = $key." = ".((int) $value); - } elseif ($key == 'type_container' || $key == 't.type_container') { - $sqlwhere[] = $key." = '".$this->db->escape($value)."'"; - } elseif ($key == 'lang' || $key == 't.lang') { - $listoflang = array(); - $foundnull = 0; - foreach (explode(',', $value) as $tmpvalue) { - if ($tmpvalue == 'null') { - $foundnull++; - continue; - } - $listoflang[] = "'".$this->db->escape(substr(str_replace("'", '', $tmpvalue), 0, 2))."'"; - } - $stringtouse = $key." IN (".$this->db->sanitize(implode(',', $listoflang), 1).")"; - if ($foundnull) { - $stringtouse = "(".$stringtouse." OR ".$key." IS NULL)"; - } - $sqlwhere[] = $stringtouse; - } else { - $sqlwhere[] = $key." LIKE '%".$this->db->escape($value)."%'"; - } - } - } - if (count($sqlwhere) > 0) { - $sql .= " AND (".implode(' '.$this->db->escape($filtermode).' ', $sqlwhere).')'; + + $errormessage = ''; + $sql .= forgeSQLFromUniversalSearchCriteria($filter, $errormessage); + if ($errormessage) { + $this->errors[] = $errormessage; + dol_syslog(__METHOD__.' '.join(',', $this->errors), LOG_ERR); + return -1; } if (!empty($sortfield)) { diff --git a/test/phpunit/CodingPhpTest.php b/test/phpunit/CodingPhpTest.php index 0d192ad6b33..202c3b6564e 100644 --- a/test/phpunit/CodingPhpTest.php +++ b/test/phpunit/CodingPhpTest.php @@ -370,7 +370,7 @@ class CodingPhpTest extends CommonClassTest $ok = true; $matches = array(); $found = ""; - preg_match_all('/(sql|SET|WHERE|INSERT|VALUES|LIKE).+\s*\'"\s*\.\s*\$(.......)/', $filecontent, $matches, PREG_SET_ORDER); + preg_match_all('/(sql|SET|WHERE|where|INSERT|insert|VALUES|LIKE).+\s*\'"\s*\.\s*\$(.......)/', $filecontent, $matches, PREG_SET_ORDER); foreach ($matches as $key => $val) { if (! in_array($val[2], array('this->d', 'this->e', 'db->esc', 'dbs->es', 'dbs->id', 'mydb->e', 'dbsessi', 'db->ida', 'escaped', 'exclude', 'include'))) { $found = $val[0]; @@ -401,6 +401,52 @@ class CodingPhpTest extends CommonClassTest $this->assertTrue($ok, 'Found non escaped string in building of a sql request (case 3) in '.$file['relativename'].': '.$found.' - Bad.'); //exit; + // Check string sql|set...=".... without (int). It means we forget a cast (int) when forging sql request. + $ok = true; + $matches = array(); + $found = ""; + // $sql .= " field = ".(isset($this->field) ? $this->escape($this->field) : "null")... is KO + // $sql .= " field = ".(isset($this->field) ? "'".$this->escape($this->field)."'" : "null")... is OK + /* + preg_match_all('/(\$sql|VALUES\()[^\'\n]*[^\'\n]"\s*\.\s*([^\n]+)\n/m', $filecontent, $matches, PREG_SET_ORDER); + foreach ($matches as $key => $val) { + if (! preg_match('/^(implode\(\' OR \', \$search|implode\(\' AND \', \$search|MAIN_DB_PREFIX|accountancy_code|\w+::|\$key|\$db->prefix|\$this->db->prefix|\$predefinedgroupwhere|\$db->sanitize|\$this->db->sanitize|\$db->ifsql|\$db->decrypt|\(int\)|\(float\)|\(\(int\)|\(\(float\)|\$conf->entity|getEntity|\$this->from)/', $val[2])) { + //print "Found a suspicious string: ".$val[2]."\n"; + if (preg_match('/.+\?.+:.+/', $val[2])) { + // We found a string that follow the " in $sql .= " "..... and does not contains simple quote for escapement nor casting + // May be it is later, into the b or c in case of a ? b : c + // Example: + // $val[2] is (isset($this->field) ? $this->escape($this->field) : "null")... is KO + // $val[2] is (isset($this->field) ? "'".$this->escape($this->field)."'" : "null")... is OK + $tmps = $val[2]; + $tmps = preg_replace('/^[^\?]+\?/', '', $tmps); + $tmps2 = explode(':', $tmps, 2); + $tmps2a = trim($tmps2[0]); + if (!empty($tmps2[1])) { + $tmps2b = trim($tmps2[1]); + } else { + $tmps2b = ''; + } + } else { + $tmps2a = $val[2]; + $tmps2b = ''; + } + if (preg_match('/^(\(*["\']|\(+int\)|\(+float\)|\(*\d|GETPOSTINT|getDolGlobalInt|dolSqlDateFilter|\$user->id|\$conf->entity|\$this->entity|\$this->where|\(?\$this->societe|str_pad\(\(int)/', $tmps2a) + && (empty($tmps2b) || preg_match('/^(\(*["\']|\(+int\)|\(+float\)|\(*\d|GETPOSTINT|getDolGlobalInt|dolSqlDateFilter|\$user->id|\$conf->entity|\$this->entity|\$this->where|\(?\$this->societe|str_pad\(\(int)/', $tmps2b))) { + continue; // No problem + } + + var_dump($val); + + $found = $val[0]; + $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 non escaped or non casted string in building of a sql request (case 4) in '.$file['relativename'].': '.$found.' - Bad.'); + */ + // Checks with IN // Check string ' IN (".xxx' or ' IN (\'.xxx' with xxx that is not '$this->db->sanitize' and not '$db->sanitize'. It means we forget a db->sanitize when forging sql request.