diff --git a/htdocs/bom/class/bom.class.php b/htdocs/bom/class/bom.class.php index ea4b306ac12..e6ae5c78ae5 100644 --- a/htdocs/bom/class/bom.class.php +++ b/htdocs/bom/class/bom.class.php @@ -1299,7 +1299,7 @@ class BOMLine extends CommonObjectLine } } if (count($sqlwhere) > 0) { - $sql .= ' AND ('.implode(' '.$filtermode.' ', $sqlwhere).')'; + $sql .= ' AND ('.implode(' '.$this->db->escape($filtermode).' ', $sqlwhere).')'; } if (!empty($sortfield)) { diff --git a/htdocs/core/class/conf.class.php b/htdocs/core/class/conf.class.php index 60ee78bbff5..ec145f89f43 100644 --- a/htdocs/core/class/conf.class.php +++ b/htdocs/core/class/conf.class.php @@ -215,26 +215,33 @@ class Conf // modules_parts['login'], modules_parts['menus'], modules_parts['substitutions'], modules_parts['triggers'], modules_parts['tpl'], // modules_parts['models'], modules_parts['theme'] // modules_parts['sms'], - // modules_parts['css'], ... + // modules_parts['css'], modules_parts['js'],... $modulename = strtolower($reg[1]); $partname = strtolower($reg[2]); if (!isset($this->modules_parts[$partname]) || !is_array($this->modules_parts[$partname])) { $this->modules_parts[$partname] = array(); } + $arrValue = json_decode($value, true); - if (is_array($arrValue) && !empty($arrValue)) { - $value = $arrValue; + + if (is_array($arrValue)) { + $newvalue = $arrValue; } elseif (in_array($partname, array('login', 'menus', 'substitutions', 'triggers', 'tpl'))) { - $value = '/'.$modulename.'/core/'.$partname.'/'; + $newvalue = '/'.$modulename.'/core/'.$partname.'/'; } elseif (in_array($partname, array('models', 'theme'))) { - $value = '/'.$modulename.'/'; + $newvalue = '/'.$modulename.'/'; } elseif (in_array($partname, array('sms'))) { - $value = '/'.$modulename.'/'; + $newvalue = '/'.$modulename.'/'; } elseif ($value == 1) { - $value = '/'.$modulename.'/core/modules/'.$partname.'/'; // ex: partname = societe + $newvalue = '/'.$modulename.'/core/modules/'.$partname.'/'; // ex: partname = societe + } else { + $newvalue = $value; + } + + if (!empty($newvalue)) { + $this->modules_parts[$partname] = array_merge($this->modules_parts[$partname], array($modulename => $newvalue)); // $value may be a string or an array } - $this->modules_parts[$partname] = array_merge($this->modules_parts[$partname], array($modulename => $value)); // $value may be a string or an array } elseif (preg_match('/^MAIN_MODULE_([0-9A-Z_]+)$/i', $key, $reg)) { // If this is a module constant (must be at end) $modulename = strtolower($reg[1]); diff --git a/htdocs/core/class/cproductnature.class.php b/htdocs/core/class/cproductnature.class.php index 2f523d4cda7..5b343b21dbc 100644 --- a/htdocs/core/class/cproductnature.class.php +++ b/htdocs/core/class/cproductnature.class.php @@ -219,7 +219,7 @@ class CProductNature // extends CommonObject } } if (count($sqlwhere) > 0) { - $sql .= ' WHERE ('.implode(' '.$filtermode.' ', $sqlwhere).')'; + $sql .= ' WHERE ('.implode(' '.$this->db->escape($filtermode).' ', $sqlwhere).')'; } if (!empty($sortfield)) { diff --git a/htdocs/core/class/ctyperesource.class.php b/htdocs/core/class/ctyperesource.class.php index 5b22e4e2033..891bf6bea10 100644 --- a/htdocs/core/class/ctyperesource.class.php +++ b/htdocs/core/class/ctyperesource.class.php @@ -239,12 +239,12 @@ class Ctyperesource $sqlwhere = array(); if (count($filter) > 0) { foreach ($filter as $key => $value) { - $sqlwhere [] = $key." LIKE '%".$this->db->escape($value)."%'"; + $sqlwhere[] = $key." LIKE '%".$this->db->escape($value)."%'"; } } if (count($sqlwhere) > 0) { - $sql .= ' WHERE '.implode(' '.$filtermode.' ', $sqlwhere); + $sql .= ' WHERE '.implode(' '.$this->db->escape($filtermode).' ', $sqlwhere); } if (!empty($sortfield)) { $sql .= $this->db->order($sortfield, $sortorder); diff --git a/htdocs/core/class/cunits.class.php b/htdocs/core/class/cunits.class.php index 6fd9b7a05cf..f2a672ec1a7 100644 --- a/htdocs/core/class/cunits.class.php +++ b/htdocs/core/class/cunits.class.php @@ -262,7 +262,7 @@ class CUnits // extends CommonObject } } if (count($sqlwhere) > 0) { - $sql .= ' WHERE ('.implode(' '.$filtermode.' ', $sqlwhere).')'; + $sql .= ' WHERE ('.implode(' '.$this->db->escape($filtermode).' ', $sqlwhere).')'; } if (!empty($sortfield)) { diff --git a/htdocs/core/class/defaultvalues.class.php b/htdocs/core/class/defaultvalues.class.php index bad30901594..ad69982357c 100644 --- a/htdocs/core/class/defaultvalues.class.php +++ b/htdocs/core/class/defaultvalues.class.php @@ -279,7 +279,7 @@ class DefaultValues extends CommonObject } } if (count($sqlwhere) > 0) { - $sql .= ' AND ('.implode(' '.$filtermode.' ', $sqlwhere).')'; + $sql .= ' AND ('.implode(' '.$this->db->escape($filtermode).' ', $sqlwhere).')'; } if (!empty($sortfield)) { diff --git a/htdocs/core/class/html.form.class.php b/htdocs/core/class/html.form.class.php index 3c8e5f8df17..4c32fa3fc71 100644 --- a/htdocs/core/class/html.form.class.php +++ b/htdocs/core/class/html.form.class.php @@ -6664,7 +6664,7 @@ class Form * @param string $htmlname Name of select html * @param string $filtertype Filter on ticket type * @param int $limit Limit on number of returned lines - * @param string $filterkey Filter on product + * @param string $filterkey Filter on ticket ref or subject * @param int $status Ticket status * @param int $outputmode 0=HTML select string, 1=Array * @param string $showempty '' to not show empty line. Translation key to show an empty line. '1' show empty line with no text. @@ -6696,7 +6696,7 @@ class Form if (count($scrit) > 1) $sql .= "("; foreach ($scrit as $crit) { if ($i > 0) $sql .= " AND "; - $sql .= "(p.ref LIKE '".$this->db->escape($prefix.$crit)."%' OR p.label LIKE '".$this->db->escape($prefix.$crit)."%'"; + $sql .= "(p.ref LIKE '".$this->db->escape($prefix.$crit)."%' OR p.subject LIKE '".$this->db->escape($prefix.$crit)."%'"; $sql .= ")"; $i++; } diff --git a/htdocs/core/db/Database.interface.php b/htdocs/core/db/Database.interface.php index 50e013ce8b7..9b812df8dc2 100644 --- a/htdocs/core/db/Database.interface.php +++ b/htdocs/core/db/Database.interface.php @@ -432,13 +432,13 @@ interface Database /** * Encrypt sensitive data in database - * Warning: This function includes the escape, so it must use direct value + * Warning: This function includes the escape and add the SQL simple quotes on strings. * - * @param string $fieldorvalue Field name or value to encrypt - * @param int $withQuotes Return string with quotes - * @return string XXX(field) or XXX('value') or field or 'value' + * @param string $fieldorvalue Field name or value to encrypt + * @param int $withQuotes Return string including the SQL simple quotes. This param must always be 1 (Value 0 is bugged and deprecated). + * @return string XXX(field) or XXX('value') or field or 'value' */ - public function encrypt($fieldorvalue, $withQuotes = 0); + public function encrypt($fieldorvalue, $withQuotes = 1); /** * Validate a database transaction diff --git a/htdocs/core/db/mysqli.class.php b/htdocs/core/db/mysqli.class.php index bef1209dd84..02a1e5d13d3 100644 --- a/htdocs/core/db/mysqli.class.php +++ b/htdocs/core/db/mysqli.class.php @@ -522,15 +522,14 @@ class DoliDBMysqli extends DoliDB } /** - * Encrypt sensitive data in database - * Warning: This function includes the escape, so it must use direct value - * - * @param string $fieldorvalue Field name or value to encrypt - * @param int $withQuotes Return string with quotes - * @return string XXX(field) or XXX('value') or field or 'value' + * Encrypt sensitive data in database + * Warning: This function includes the escape and add the SQL simple quotes on strings. * + * @param string $fieldorvalue Field name or value to encrypt + * @param int $withQuotes Return string including the SQL simple quotes. This param must always be 1 (Value 0 is bugged and deprecated). + * @return string XXX(field) or XXX('value') or field or 'value' */ - public function encrypt($fieldorvalue, $withQuotes = 0) + public function encrypt($fieldorvalue, $withQuotes = 1) { global $conf; @@ -540,17 +539,17 @@ class DoliDBMysqli extends DoliDB //Encryption key $cryptKey = (!empty($conf->db->dolibarr_main_db_cryptkey) ? $conf->db->dolibarr_main_db_cryptkey : ''); - $return = ($withQuotes ? "'" : "").$this->escape($fieldorvalue).($withQuotes ? "'" : ""); + $escapedstringwithquotes = ($withQuotes ? "'" : "").$this->escape($fieldorvalue).($withQuotes ? "'" : ""); if ($cryptType && !empty($cryptKey)) { if ($cryptType == 2) { - $return = 'AES_ENCRYPT('.$return.',\''.$cryptKey.'\')'; + $escapedstringwithquotes = "AES_ENCRYPT(".$escapedstringwithquotes.", '".$this->escape($cryptKey)."')"; } elseif ($cryptType == 1) { - $return = 'DES_ENCRYPT('.$return.',\''.$cryptKey.'\')'; + $escapedstringwithquotes = "DES_ENCRYPT(".$escapedstringwithquotes.", '".$this->escape($cryptKey)."')"; } } - return $return; + return $escapedstringwithquotes; } /** diff --git a/htdocs/core/db/pgsql.class.php b/htdocs/core/db/pgsql.class.php index 55d5f18dd00..9d17d4b9099 100644 --- a/htdocs/core/db/pgsql.class.php +++ b/htdocs/core/db/pgsql.class.php @@ -823,22 +823,22 @@ class DoliDBPgsql extends DoliDB } /** - * Encrypt sensitive data in database - * Warning: This function includes the escape, so it must use direct value + * Encrypt sensitive data in database + * Warning: This function includes the escape and add the SQL simple quotes on strings. * - * @param string $fieldorvalue Field name or value to encrypt - * @param int $withQuotes Return string with quotes - * @return string XXX(field) or XXX('value') or field or 'value' + * @param string $fieldorvalue Field name or value to encrypt + * @param int $withQuotes Return string including the SQL simple quotes. This param must always be 1 (Value 0 is bugged and deprecated). + * @return string XXX(field) or XXX('value') or field or 'value' */ - public function encrypt($fieldorvalue, $withQuotes = 0) + public function encrypt($fieldorvalue, $withQuotes = 1) { global $conf; // Type of encryption (2: AES (recommended), 1: DES , 0: no encryption) - $cryptType = ($conf->db->dolibarr_main_db_encryption ? $conf->db->dolibarr_main_db_encryption : 0); + //$cryptType = ($conf->db->dolibarr_main_db_encryption ? $conf->db->dolibarr_main_db_encryption : 0); //Encryption key - $cryptKey = (!empty($conf->db->dolibarr_main_db_cryptkey) ? $conf->db->dolibarr_main_db_cryptkey : ''); + //$cryptKey = (!empty($conf->db->dolibarr_main_db_cryptkey) ? $conf->db->dolibarr_main_db_cryptkey : ''); $return = $fieldorvalue; return ($withQuotes ? "'" : "").$this->escape($return).($withQuotes ? "'" : ""); diff --git a/htdocs/core/db/sqlite3.class.php b/htdocs/core/db/sqlite3.class.php index 072d5f0c4b3..e2a2c124737 100644 --- a/htdocs/core/db/sqlite3.class.php +++ b/htdocs/core/db/sqlite3.class.php @@ -744,34 +744,34 @@ class DoliDBSqlite3 extends DoliDB } /** - * Encrypt sensitive data in database - * Warning: This function includes the escape, so it must use direct value + * Encrypt sensitive data in database + * Warning: This function includes the escape and add the SQL simple quotes on strings. * - * @param string $fieldorvalue Field name or value to encrypt - * @param int $withQuotes Return string with quotes - * @return string XXX(field) or XXX('value') or field or 'value' + * @param string $fieldorvalue Field name or value to encrypt + * @param int $withQuotes Return string including the SQL simple quotes. This param must always be 1 (Value 0 is bugged and deprecated). + * @return string XXX(field) or XXX('value') or field or 'value' */ - public function encrypt($fieldorvalue, $withQuotes = 0) + public function encrypt($fieldorvalue, $withQuotes = 1) { global $conf; // Type of encryption (2: AES (recommended), 1: DES , 0: no encryption) - $cryptType = ($conf->db->dolibarr_main_db_encryption ? $conf->db->dolibarr_main_db_encryption : 0); + $cryptType = (!empty($conf->db->dolibarr_main_db_encryption) ? $conf->db->dolibarr_main_db_encryption : 0); //Encryption key $cryptKey = (!empty($conf->db->dolibarr_main_db_cryptkey) ? $conf->db->dolibarr_main_db_cryptkey : ''); - $return = ($withQuotes ? "'" : "").$this->escape($fieldorvalue).($withQuotes ? "'" : ""); + $escapedstringwithquotes = ($withQuotes ? "'" : "").$this->escape($fieldorvalue).($withQuotes ? "'" : ""); if ($cryptType && !empty($cryptKey)) { if ($cryptType == 2) { - $return = 'AES_ENCRYPT('.$return.',\''.$cryptKey.'\')'; + $escapedstringwithquotes = "AES_ENCRYPT(".$escapedstringwithquotes.", '".$this->escape($cryptKey)."')"; } elseif ($cryptType == 1) { - $return = 'DES_ENCRYPT('.$return.',\''.$cryptKey.'\')'; + $escapedstringwithquotes = "DES_ENCRYPT(".$escapedstringwithquotes.", '".$this->escape($cryptKey)."')"; } } - return $return; + return $escapedstringwithquotes; } /** diff --git a/htdocs/core/lib/admin.lib.php b/htdocs/core/lib/admin.lib.php index 531af9017b3..45b7e3b2096 100644 --- a/htdocs/core/lib/admin.lib.php +++ b/htdocs/core/lib/admin.lib.php @@ -345,7 +345,7 @@ function run_sql($sqlfile, $silent = 1, $entity = '', $usesavepoint = 1, $handle for ($j = 0; $j < $num; $j++) { $from = $reg[0][$j]; - $to = $db->encrypt($reg[1][$j], 1); + $to = $db->encrypt($reg[1][$j]); $newsql = str_replace($from, $to, $newsql); } $sqlmodified++; @@ -481,10 +481,10 @@ function run_sql($sqlfile, $silent = 1, $entity = '', $usesavepoint = 1, $handle /** - * Effacement d'une constante dans la base de donnees + * Delete a constant * * @param DoliDB $db Database handler - * @param string $name Name of constant or rowid of line + * @param string|int $name Name of constant or rowid of line * @param int $entity Multi company id, -1 for all entities * @return int <0 if KO, >0 if OK * @@ -502,7 +502,7 @@ function dolibarr_del_const($db, $name, $entity = 1) $sql = "DELETE FROM ".MAIN_DB_PREFIX."const"; $sql .= " WHERE (".$db->decrypt('name')." = '".$db->escape($name)."'"; if (is_numeric($name)) { - $sql .= " OR rowid = '".$db->escape($name)."'"; + $sql .= " OR rowid = ".((int) $name); } $sql .= ")"; if ($entity >= 0) { @@ -536,7 +536,7 @@ function dolibarr_get_const($db, $name, $entity = 1) $sql = "SELECT ".$db->decrypt('value')." as value"; $sql .= " FROM ".MAIN_DB_PREFIX."const"; - $sql .= " WHERE name = '".$db->escape($db->encrypt($name))."'"; + $sql .= " WHERE name = ".$db->encrypt($name); $sql .= " AND entity = ".((int) $entity); dol_syslog("admin.lib::dolibarr_get_const", LOG_DEBUG); @@ -583,7 +583,7 @@ function dolibarr_set_const($db, $name, $value, $type = 'chaine', $visible = 0, $db->begin(); $sql = "DELETE FROM ".MAIN_DB_PREFIX."const"; - $sql .= " WHERE name = '".$db->escape($db->encrypt($name))."'"; + $sql .= " WHERE name = ".$db->encrypt($name); if ($entity >= 0) { $sql .= " AND entity = ".((int) $entity); } @@ -594,8 +594,8 @@ function dolibarr_set_const($db, $name, $value, $type = 'chaine', $visible = 0, if (strcmp($value, '')) { // true if different. Must work for $value='0' or $value=0 $sql = "INSERT INTO ".MAIN_DB_PREFIX."const(name,value,type,visible,note,entity)"; $sql .= " VALUES ("; - $sql .= $db->encrypt($name, 1); - $sql .= ", ".$db->encrypt($value, 1); + $sql .= $db->encrypt($name); + $sql .= ", ".$db->encrypt($value); $sql .= ",'".$db->escape($type)."',".((int) $visible).",'".$db->escape($note)."',".((int) $entity).")"; //print "sql".$value."-".pg_escape_string($value)."-".$sql;exit; @@ -753,7 +753,7 @@ function security_prepare_head() $sql = "SELECT COUNT(r.id) as nb"; $sql .= " FROM ".MAIN_DB_PREFIX."rights_def as r"; $sql .= " WHERE r.libelle NOT LIKE 'tou%'"; // On ignore droits "tous" - $sql .= " AND entity = ".$conf->entity; + $sql .= " AND entity = ".((int) $conf->entity); $sql .= " AND bydefault = 1"; if (empty($conf->global->MAIN_USE_ADVANCED_PERMS)) { $sql .= " AND r.perms NOT LIKE '%_advance'"; // Hide advanced perms if option is not enabled @@ -1839,7 +1839,7 @@ function delDocumentModel($name, $type) $sql = "DELETE FROM ".MAIN_DB_PREFIX."document_model"; $sql .= " WHERE nom = '".$db->escape($name)."'"; $sql .= " AND type = '".$db->escape($type)."'"; - $sql .= " AND entity = ".$conf->entity; + $sql .= " AND entity = ".((int) $conf->entity); dol_syslog("admin.lib::delDocumentModel", LOG_DEBUG); $resql = $db->query($sql); diff --git a/htdocs/core/modules/DolibarrModules.class.php b/htdocs/core/modules/DolibarrModules.class.php index e9688daf28e..4191a3492ca 100644 --- a/htdocs/core/modules/DolibarrModules.class.php +++ b/htdocs/core/modules/DolibarrModules.class.php @@ -994,9 +994,9 @@ class DolibarrModules // Can not be abstract, because we need to instantiate it $note = json_encode(array('authorid'=>(is_object($user) ? $user->id : 0), 'ip'=>(empty($_SERVER['REMOTE_ADDR']) ? '' : $_SERVER['REMOTE_ADDR']))); $sql = "INSERT INTO ".MAIN_DB_PREFIX."const (name, value, visible, entity, note) VALUES"; - $sql .= " (".$this->db->encrypt($this->const_name, 1); - $sql .= ", ".$this->db->encrypt('1', 1); - $sql .= ", 0, ".$entity; + $sql .= " (".$this->db->encrypt($this->const_name); + $sql .= ", ".$this->db->encrypt('1'); + $sql .= ", 0, ".((int) $entity); $sql .= ", '".$this->db->escape($note)."')"; dol_syslog(get_class($this)."::_active insert activation constant", LOG_DEBUG); @@ -1555,9 +1555,9 @@ class DolibarrModules // Can not be abstract, because we need to instantiate it $sql .= ", entity"; $sql .= ")"; $sql .= " VALUES ("; - $sql .= $this->db->encrypt($this->const_name."_TABS_".$i, 1); + $sql .= $this->db->encrypt($this->const_name."_TABS_".$i); $sql .= ", 'chaine'"; - $sql .= ", ".$this->db->encrypt($newvalue, 1); + $sql .= ", ".$this->db->encrypt($newvalue); $sql .= ", null"; $sql .= ", '0'"; $sql .= ", ".$entity; @@ -1627,9 +1627,9 @@ class DolibarrModules // Can not be abstract, because we need to instantiate it if ($row[0] == 0) { // If not found $sql = "INSERT INTO ".MAIN_DB_PREFIX."const (name,type,value,note,visible,entity)"; $sql .= " VALUES ("; - $sql .= $this->db->encrypt($name, 1); + $sql .= $this->db->encrypt($name); $sql .= ",'".$this->db->escape($type)."'"; - $sql .= ",".(($val != '') ? $this->db->encrypt($val, 1) : "''"); + $sql .= ",".(($val != '') ? $this->db->encrypt($val) : "''"); $sql .= ",".($note ? "'".$this->db->escape($note)."'" : "null"); $sql .= ",'".$this->db->escape($visible)."'"; $sql .= ",".$entity; @@ -2064,8 +2064,8 @@ class DolibarrModules // Can not be abstract, because we need to instantiate it $row = $this->db->fetch_row($result); if ($row[0] == 0) { - $sql = "INSERT INTO ".MAIN_DB_PREFIX."const (name,type,value,note,visible,entity)"; - $sql .= " VALUES ('".$this->db->escape($this->db->encrypt($name))."', 'chaine', '".$this->db->escape($this->db->encrypt($dir))."', 'Directory for module ".$this->name."', '0', ".((int) $conf->entity).")"; + $sql = "INSERT INTO ".MAIN_DB_PREFIX."const (name, type, value, note, visible, entity)"; + $sql .= " VALUES (".$this->db->encrypt($name).", 'chaine', ".$this->db->encrypt($dir).", '".$this->db->escape("Directory for module ".$this->name)."', '0', ".((int) $conf->entity).")"; dol_syslog(get_class($this)."::insert_dirs", LOG_DEBUG); $this->db->query($sql); @@ -2126,7 +2126,7 @@ class DolibarrModules // Can not be abstract, because we need to instantiate it $entity = $conf->entity; // Reset the current entity $newvalue = $value; - + var_dump($newvalue); // Serialize array parameters if (is_array($value)) { // Can defined other parameters @@ -2141,11 +2141,12 @@ class DolibarrModules // Can not be abstract, because we need to instantiate it if (isset($value['entity'])) { $entity = $value['entity']; } - } else // when hook is declared with syntax 'hook'=>array('hookcontext1','hookcontext2',...) - { + } else { // when hook is declared with syntax 'hook'=>array('hookcontext1','hookcontext2',...) $newvalue = json_encode($value); } } + var_dump($newvalue); + var_dump($this->db->escape($newvalue)); $sql = "INSERT INTO ".MAIN_DB_PREFIX."const ("; $sql .= "name"; @@ -2156,14 +2157,14 @@ class DolibarrModules // Can not be abstract, because we need to instantiate it $sql .= ", entity"; $sql .= ")"; $sql .= " VALUES ("; - $sql .= "'".$this->db->escape($this->db->encrypt($this->const_name."_".strtoupper($key)))."'"; + $sql .= " ".$this->db->encrypt($this->const_name."_".strtoupper($key)); $sql .= ", 'chaine'"; - $sql .= ", '".$this->db->escape($this->db->encrypt($newvalue))."'"; + $sql .= ", ".$this->db->encrypt($newvalue); $sql .= ", null"; $sql .= ", '0'"; $sql .= ", ".((int) $entity); $sql .= ")"; - + print $sql; dol_syslog(get_class($this)."::insert_module_parts for key=".$this->const_name."_".strtoupper($key), LOG_DEBUG); $resql = $this->db->query($sql, 1); diff --git a/htdocs/core/modules/modApi.class.php b/htdocs/core/modules/modApi.class.php index bf7fc2777ae..ffd274c7096 100644 --- a/htdocs/core/modules/modApi.class.php +++ b/htdocs/core/modules/modApi.class.php @@ -245,8 +245,8 @@ class modApi extends DolibarrModules { // Remove old constants with entity fields different of 0 $sql = array( - "DELETE FROM ".MAIN_DB_PREFIX."const WHERE name = '".$this->db->escape($this->db->encrypt('MAIN_MODULE_API'))."'", - "DELETE FROM ".MAIN_DB_PREFIX."const WHERE name = '".$this->db->escape($this->db->encrypt('API_PRODUCTION_MODE'))."'" + "DELETE FROM ".MAIN_DB_PREFIX."const WHERE name = ".$this->db->encrypt('MAIN_MODULE_API'), // API can't be enabled per environment. Why ? + "DELETE FROM ".MAIN_DB_PREFIX."const WHERE name = ".$this->db->encrypt('API_PRODUCTION_MODE') // Not in production mode by default at activation ); return $this->_remove($sql, $options); diff --git a/htdocs/debugbar/class/TraceableDB.php b/htdocs/debugbar/class/TraceableDB.php index 85dd3080512..267c79ab08e 100644 --- a/htdocs/debugbar/class/TraceableDB.php +++ b/htdocs/debugbar/class/TraceableDB.php @@ -596,13 +596,13 @@ class TraceableDB extends DoliDB /** * Encrypt sensitive data in database - * Warning: This function includes the escape, so it must use direct value + * Warning: This function includes the escape and add the SQL simple quotes on strings. * - * @param string $fieldorvalue Field name or value to encrypt - * @param int $withQuotes Return string with quotes - * @return string XXX(field) or XXX('value') or field or 'value' + * @param string $fieldorvalue Field name or value to encrypt + * @param int $withQuotes Return string including the SQL simple quotes. This param must always be 1 (Value 0 is bugged and deprecated). + * @return string XXX(field) or XXX('value') or field or 'value' */ - public function encrypt($fieldorvalue, $withQuotes = 0) + public function encrypt($fieldorvalue, $withQuotes = 1) { return $this->db->encrypt($fieldorvalue, $withQuotes); } diff --git a/htdocs/ecm/class/ecmfiles.class.php b/htdocs/ecm/class/ecmfiles.class.php index 15cfba4c03e..6c2b8fc4023 100644 --- a/htdocs/ecm/class/ecmfiles.class.php +++ b/htdocs/ecm/class/ecmfiles.class.php @@ -542,7 +542,7 @@ class EcmFiles extends CommonObject $sql .= " AND entity IN (" . getEntity('ecmfiles') . ")"; }*/ if (count($sqlwhere) > 0) { - $sql .= ' AND '.implode(' '.$filtermode.' ', $sqlwhere); + $sql .= ' AND '.implode(' '.$this->db->escape($filtermode).' ', $sqlwhere); } if (!empty($sortfield)) { $sql .= $this->db->order($sortfield, $sortorder); diff --git a/htdocs/ecm/index.php b/htdocs/ecm/index.php index 3a8d33343c7..20d948b4b3b 100644 --- a/htdocs/ecm/index.php +++ b/htdocs/ecm/index.php @@ -120,7 +120,8 @@ if (GETPOST("sendit", 'alphanohtml') && !empty($conf->global->MAIN_UPLOAD_DOC)) if (!$error) { $generatethumbs = 0; - $res = dol_add_file_process($upload_dir, 0, 1, 'userfile', '', null, '', $generatethumbs); + $overwritefile = GETPOST('overwritefile', 'int')?GETPOST('overwritefile', 'int'):0; + $res = dol_add_file_process($upload_dir, $overwritefile, 1, 'userfile', '', null, '', $generatethumbs); if ($res > 0) { $result = $ecmdir->changeNbOfFiles('+'); } diff --git a/htdocs/eventorganization/class/conferenceorbooth.class.php b/htdocs/eventorganization/class/conferenceorbooth.class.php index f7369bd6166..d3e30f8e8b9 100644 --- a/htdocs/eventorganization/class/conferenceorbooth.class.php +++ b/htdocs/eventorganization/class/conferenceorbooth.class.php @@ -306,7 +306,7 @@ class ConferenceOrBooth extends ActionComm } } if (count($sqlwhere) > 0) { - $sql .= ' AND ('.implode(' '.$filtermode.' ', $sqlwhere).')'; + $sql .= ' AND ('.implode(' '.$this->db->escape($filtermode).' ', $sqlwhere).')'; } if (!empty($sortfield)) { diff --git a/htdocs/eventorganization/class/conferenceorboothattendee.class.php b/htdocs/eventorganization/class/conferenceorboothattendee.class.php index 5169058d41c..45e241bd1c1 100644 --- a/htdocs/eventorganization/class/conferenceorboothattendee.class.php +++ b/htdocs/eventorganization/class/conferenceorboothattendee.class.php @@ -427,7 +427,7 @@ class ConferenceOrBoothAttendee extends CommonObject } } if (count($sqlwhere) > 0) { - $sql .= ' AND ('.implode(' '.$filtermode.' ', $sqlwhere).')'; + $sql .= ' AND ('.implode(' '.$this->db->escape($filtermode).' ', $sqlwhere).')'; } if (!empty($sortfield)) { diff --git a/htdocs/expedition/shipment.php b/htdocs/expedition/shipment.php index 8510e6f3609..e9f79e2ef12 100644 --- a/htdocs/expedition/shipment.php +++ b/htdocs/expedition/shipment.php @@ -3,7 +3,7 @@ * Copyright (C) 2005-2012 Laurent Destailleur * Copyright (C) 2005-2012 Regis Houssin * Copyright (C) 2012-2015 Juanjo Menent - * Copyright (C) 2018 Frédéric France + * Copyright (C) 2018-2021 Frédéric France * Copyright (C) 2018 Philippe Grand * * This program is free software; you can redistribute it and/or modify @@ -624,6 +624,7 @@ if ($id > 0 || !empty($ref)) { $sql .= ' p.rowid as prodid, p.label as product_label, p.entity, p.ref, p.fk_product_type as product_type, p.description as product_desc,'; $sql .= ' p.weight, p.weight_units, p.length, p.length_units, p.width, p.width_units, p.height, p.height_units,'; $sql .= ' p.surface, p.surface_units, p.volume, p.volume_units'; + $sql .= ', p.tobatch, p.tosell, p.tobuy, p.barcode'; $sql .= " FROM ".MAIN_DB_PREFIX."commandedet as cd"; $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."product as p ON cd.fk_product = p.rowid"; $sql .= " WHERE cd.fk_commande = ".((int) $object->id); @@ -711,6 +712,10 @@ if ($id > 0 || !empty($ref)) { $product_static->id = $objp->fk_product; $product_static->ref = $objp->ref; $product_static->entity = $objp->entity; + $product_static->status = $objp->tosell; + $product_static->status_buy = $objp->tobuy; + $product_static->status_batch = $objp->tobatch; + $product_static->barcode = $objp->barcode; $product_static->weight = $objp->weight; $product_static->weight_units = $objp->weight_units; diff --git a/htdocs/fourn/class/fournisseur.commande.dispatch.class.php b/htdocs/fourn/class/fournisseur.commande.dispatch.class.php index 686583cab65..a83795996e4 100644 --- a/htdocs/fourn/class/fournisseur.commande.dispatch.class.php +++ b/htdocs/fourn/class/fournisseur.commande.dispatch.class.php @@ -677,7 +677,7 @@ class CommandeFournisseurDispatch extends CommonObjectLine } } if (count($sqlwhere) > 0) { - $sql .= ' WHERE '.implode(' '.$filtermode.' ', $sqlwhere); + $sql .= ' WHERE '.implode(' '.$this->db->escape($filtermode).' ', $sqlwhere); } if (!empty($sortfield)) { diff --git a/htdocs/install/mysql/migration/14.0.0-15.0.0.sql b/htdocs/install/mysql/migration/14.0.0-15.0.0.sql index 1d9dd28f9d7..5584ccc40f6 100644 --- a/htdocs/install/mysql/migration/14.0.0-15.0.0.sql +++ b/htdocs/install/mysql/migration/14.0.0-15.0.0.sql @@ -63,6 +63,7 @@ INSERT INTO llx_c_action_trigger (code,label,description,elementtype,rang) VALUE ALTER TABLE llx_product ADD COLUMN fk_default_bom integer DEFAULT NULL; +ALTER TABLE llx_mrp_mo ADD COLUMN mrptype integer DEFAULT 0; DELETE FROM llx_menu WHERE type = 'top' AND module = 'cashdesk' AND mainmenu = 'cashdesk'; diff --git a/htdocs/install/mysql/tables/llx_mrp_mo.sql b/htdocs/install/mysql/tables/llx_mrp_mo.sql index de1933ccfed..185ea1583c9 100644 --- a/htdocs/install/mysql/tables/llx_mrp_mo.sql +++ b/htdocs/install/mysql/tables/llx_mrp_mo.sql @@ -17,8 +17,9 @@ CREATE TABLE llx_mrp_mo( -- BEGIN MODULEBUILDER FIELDS rowid integer AUTO_INCREMENT PRIMARY KEY NOT NULL, - ref varchar(128) DEFAULT '(PROV)' NOT NULL, entity integer DEFAULT 1 NOT NULL, + ref varchar(128) DEFAULT '(PROV)' NOT NULL, + mrptype integer DEFAULT 0, -- 0 for a manufacture MO, 1 for a dismantle MO label varchar(255), qty real NOT NULL, fk_warehouse integer, diff --git a/htdocs/install/step5.php b/htdocs/install/step5.php index b434612afcd..f9424f51a32 100644 --- a/htdocs/install/step5.php +++ b/htdocs/install/step5.php @@ -234,7 +234,7 @@ if ($action == "set" || empty($action) || preg_match('/upgrade/i', $action)) { // Insert MAIN_VERSION_FIRST_INSTALL in a dedicated transaction. So if it fails (when first install was already done), we can do other following requests. $db->begin(); dolibarr_install_syslog('step5: set MAIN_VERSION_FIRST_INSTALL const to '.$targetversion, LOG_DEBUG); - $resql = $db->query("INSERT INTO ".MAIN_DB_PREFIX."const(name, value, type, visible, note, entity) values('".$db->escape($db->encrypt('MAIN_VERSION_FIRST_INSTALL'))."', '".$db->escape($db->encrypt($targetversion))."', 'chaine', 0, 'Dolibarr version when first install', 0)"); + $resql = $db->query("INSERT INTO ".MAIN_DB_PREFIX."const(name, value, type, visible, note, entity) values(".$db->encrypt('MAIN_VERSION_FIRST_INSTALL').", ".$db->encrypt($targetversion).", 'chaine', 0, 'Dolibarr version when first install', 0)"); if ($resql) { $conf->global->MAIN_VERSION_FIRST_INSTALL = $targetversion; $db->commit(); @@ -250,7 +250,7 @@ if ($action == "set" || empty($action) || preg_match('/upgrade/i', $action)) { if (!$resql) { dol_print_error($db, 'Error in setup program'); } - $resql = $db->query("INSERT INTO ".MAIN_DB_PREFIX."const(name,value,type,visible,note,entity) values('".$db->escape($db->encrypt('MAIN_VERSION_LAST_INSTALL'))."', '".$db->escape($db->encrypt($targetversion))."', 'chaine', 0, 'Dolibarr version when last install', 0)"); + $resql = $db->query("INSERT INTO ".MAIN_DB_PREFIX."const(name,value,type,visible,note,entity) values(".$db->encrypt('MAIN_VERSION_LAST_INSTALL').", ".$db->encrypt($targetversion).", 'chaine', 0, 'Dolibarr version when last install', 0)"); if (!$resql) { dol_print_error($db, 'Error in setup program'); } @@ -262,7 +262,7 @@ if ($action == "set" || empty($action) || preg_match('/upgrade/i', $action)) { if (!$resql) { dol_print_error($db, 'Error in setup program'); } - $resql = $db->query("INSERT INTO ".MAIN_DB_PREFIX."const(name,value,type,visible,note,entity) values('".$db->escape($db->encrypt('MAIN_REMOVE_INSTALL_WARNING'))."', '".$db->escape($db->encrypt(1))."', 'chaine', 1, 'Disable install warnings', 0)"); + $resql = $db->query("INSERT INTO ".MAIN_DB_PREFIX."const(name,value,type,visible,note,entity) values(".$db->encrypt('MAIN_REMOVE_INSTALL_WARNING').", ".$db->encrypt(1).", 'chaine', 1, 'Disable install warnings', 0)"); if (!$resql) { dol_print_error($db, 'Error in setup program'); } @@ -330,7 +330,7 @@ if ($action == "set" || empty($action) || preg_match('/upgrade/i', $action)) { if (!$resql) { dol_print_error($db, 'Error in setup program'); } - $resql = $db->query("INSERT INTO ".MAIN_DB_PREFIX."const(name, value, type, visible, note, entity) VALUES ('".$db->escape($db->encrypt('MAIN_VERSION_LAST_UPGRADE'))."', '".$db->escape($db->encrypt($targetversion))."', 'chaine', 0, 'Dolibarr version for last upgrade', 0)"); + $resql = $db->query("INSERT INTO ".MAIN_DB_PREFIX."const(name, value, type, visible, note, entity) VALUES (".$db->encrypt('MAIN_VERSION_LAST_UPGRADE').", ".$db->encrypt($targetversion).", 'chaine', 0, 'Dolibarr version for last upgrade', 0)"); if (!$resql) { dol_print_error($db, 'Error in setup program'); } @@ -346,7 +346,7 @@ if ($action == "set" || empty($action) || preg_match('/upgrade/i', $action)) { } // May fail if parameter already defined - $resql = $db->query("INSERT INTO ".MAIN_DB_PREFIX."const(name,value,type,visible,note,entity) VALUES ('".$db->escape($db->encrypt('MAIN_LANG_DEFAULT'))."', '".$db->escape($db->encrypt($setuplang))."', 'chaine', 0, 'Default language', 1)"); + $resql = $db->query("INSERT INTO ".MAIN_DB_PREFIX."const(name,value,type,visible,note,entity) VALUES (".$db->encrypt('MAIN_LANG_DEFAULT').", ".$db->encrypt($setuplang).", 'chaine', 0, 'Default language', 1)"); //if (! $resql) dol_print_error($db,'Error in setup program'); $db->close(); diff --git a/htdocs/knowledgemanagement/class/knowledgerecord.class.php b/htdocs/knowledgemanagement/class/knowledgerecord.class.php index 559e6f21cf0..8182a962b50 100644 --- a/htdocs/knowledgemanagement/class/knowledgerecord.class.php +++ b/htdocs/knowledgemanagement/class/knowledgerecord.class.php @@ -400,7 +400,7 @@ class KnowledgeRecord extends CommonObject } } if (count($sqlwhere) > 0) { - $sql .= ' AND ('.implode(' '.$filtermode.' ', $sqlwhere).')'; + $sql .= ' AND ('.implode(' '.$this->db->escape($filtermode).' ', $sqlwhere).')'; } if (!empty($sortfield)) { diff --git a/htdocs/langs/en_US/mrp.lang b/htdocs/langs/en_US/mrp.lang index 2414a92cefb..a1ccf238f0a 100644 --- a/htdocs/langs/en_US/mrp.lang +++ b/htdocs/langs/en_US/mrp.lang @@ -55,6 +55,7 @@ WarehouseForProduction=Warehouse for production CreateMO=Create MO ToConsume=To consume ToProduce=To produce +ToObtain=To obtain QtyAlreadyConsumed=Qty already consumed QtyAlreadyProduced=Qty already produced QtyRequiredIfNoLoss=Qty required if there is no loss (Manufacturing efficiency is 100%%) diff --git a/htdocs/mrp/class/mo.class.php b/htdocs/mrp/class/mo.class.php index c88f0f44b48..fcf54eb364e 100644 --- a/htdocs/mrp/class/mo.class.php +++ b/htdocs/mrp/class/mo.class.php @@ -101,6 +101,7 @@ class Mo extends CommonObject 'entity' => array('type'=>'integer', 'label'=>'Entity', 'enabled'=>1, 'visible'=>0, 'position'=>5, 'notnull'=>1, 'default'=>'1', 'index'=>1), 'ref' => array('type'=>'varchar(128)', 'label'=>'Ref', 'enabled'=>1, 'visible'=>4, 'position'=>10, 'notnull'=>1, 'default'=>'(PROV)', 'index'=>1, 'searchall'=>1, 'comment'=>"Reference of object", 'showoncombobox'=>'1', 'noteditable'=>1), 'fk_bom' => array('type'=>'integer:Bom:bom/class/bom.class.php:0:t.status=1', 'filter'=>'active=1', 'label'=>'BOM', 'enabled'=>1, 'visible'=>1, 'position'=>33, 'notnull'=>-1, 'index'=>1, 'comment'=>"Original BOM", 'css'=>'minwidth100 maxwidth300', 'csslist'=>'nowraponall'), + 'mrptype' => array('type'=>'integer', 'label'=>'Type', 'enabled'=>1, 'visible'=>1, 'position'=>34, 'notnull'=>1, 'default'=>'0', 'arrayofkeyval'=>array(0=>'Manufacturing', 1=>'Disassemble'), 'css'=>'minwidth150', 'csslist'=>'minwidth150 center'), 'fk_product' => array('type'=>'integer:Product:product/class/product.class.php:0', 'label'=>'Product', 'enabled'=>1, 'visible'=>1, 'position'=>35, 'notnull'=>1, 'index'=>1, 'comment'=>"Product to produce", 'css'=>'maxwidth300', 'csslist'=>'tdoverflowmax100', 'picto'=>'product'), 'qty' => array('type'=>'real', 'label'=>'QtyToProduce', 'enabled'=>1, 'visible'=>1, 'position'=>40, 'notnull'=>1, 'comment'=>"Qty to produce", 'css'=>'width75', 'default'=>1, 'isameasure'=>1), 'label' => array('type'=>'varchar(255)', 'label'=>'Label', 'enabled'=>1, 'visible'=>1, 'position'=>42, 'notnull'=>-1, 'searchall'=>1, 'showoncombobox'=>'2', 'css'=>'maxwidth300', 'csslist'=>'tdoverflowmax200'), @@ -121,8 +122,9 @@ class Mo extends CommonObject 'status' => array('type'=>'integer', 'label'=>'Status', 'enabled'=>1, 'visible'=>2, 'position'=>1000, 'default'=>0, 'notnull'=>1, 'index'=>1, 'arrayofkeyval'=>array('0'=>'Draft', '1'=>'Validated', '2'=>'InProgress', '3'=>'StatusMOProduced', '9'=>'Canceled')), ); public $rowid; - public $ref; public $entity; + public $ref; + public $mrptype; public $label; public $qty; public $fk_warehouse; @@ -253,7 +255,7 @@ class Mo extends CommonObject $this->db->begin(); // Check that product is not a kit/virtual product - if (empty($conf->global->ALLOW_USE_KITS_INTO_BOM_AND_MO) and $this->fk_product > 0) { + if (empty($conf->global->ALLOW_USE_KITS_INTO_BOM_AND_MO) && $this->fk_product > 0) { include_once DOL_DOCUMENT_ROOT.'/product/class/product.class.php'; $tmpproduct = new Product($this->db); $tmpproduct->fetch($this->fk_product); @@ -265,6 +267,14 @@ class Mo extends CommonObject } } + if ($this->fk_bom > 0) { + // If there is a nown BOM, we force the type of MO to the type of BOM + $tmpbom = new BOM($this->db); + $tmpbom->fetch($this->fk_bom); + + $this->mrptype = $tmpbom->bomtype; + } + if (!$error) { $idcreated = $this->createCommon($user, $notrigger); if ($idcreated <= 0) { @@ -273,7 +283,7 @@ class Mo extends CommonObject } if (!$error) { - $result = $this->updateProduction($user, $notrigger); + $result = $this->updateProduction($user, $notrigger); // Insert lines from BOM if ($result <= 0) { $error++; } @@ -448,7 +458,7 @@ class Mo extends CommonObject } } if (count($sqlwhere) > 0) { - $sql .= ' AND ('.implode(' '.$filtermode.' ', $sqlwhere).')'; + $sql .= ' AND ('.implode(' '.$this->db->escape($filtermode).' ', $sqlwhere).')'; } if (!empty($sortfield)) { @@ -638,7 +648,7 @@ class Mo extends CommonObject $moline->fk_product = $this->fk_product; $moline->position = 1; - if ($this->fk_bom > 0) { // If a BOM is defined, we know what to consume. + if ($this->fk_bom > 0) { // If a BOM is defined, we know what to produce. include_once DOL_DOCUMENT_ROOT.'/bom/class/bom.class.php'; $bom = new Bom($this->db); $bom->fetch($this->fk_bom); @@ -1557,7 +1567,7 @@ class MoLine extends CommonObjectLine } } if (count($sqlwhere) > 0) { - $sql .= ' AND ('.implode(' '.$filtermode.' ', $sqlwhere).')'; + $sql .= ' AND ('.implode(' '.$this->db->escape($filtermode).' ', $sqlwhere).')'; } if (!empty($sortfield)) { diff --git a/htdocs/mrp/mo_card.php b/htdocs/mrp/mo_card.php index 6eaf42ed833..fc8cab806c7 100644 --- a/htdocs/mrp/mo_card.php +++ b/htdocs/mrp/mo_card.php @@ -49,6 +49,7 @@ $backtopageforcancel = GETPOST('backtopageforcancel', 'alpha'); // Initialize technical objects $object = new Mo($db); $objectbom = new BOM($db); + $extrafields = new ExtraFields($db); $diroutputmassaction = $conf->mrp->dir_output.'/temp/massgeneration/'.$user->id; $hookmanager->initHooks(array('mocard', 'globalcard')); // Note that conf->hooks_modules contains array @@ -74,13 +75,14 @@ if (empty($action) && empty($id) && empty($ref)) { // Load object include DOL_DOCUMENT_ROOT.'/core/actions_fetchobject.inc.php'; // Must be include, not include_once. -if (GETPOST('fk_bom', 'int')) { +if (GETPOST('fk_bom', 'int') > 0) { $objectbom->fetch(GETPOST('fk_bom', 'int')); if ($action != 'add') { // We force calling parameters if we are not in the submit of creation of MO $_POST['fk_product'] = $objectbom->fk_product; $_POST['qty'] = $objectbom->qty; + $_POST['mrptype'] = $objectbom->bomtype; $_POST['fk_warehouse'] = $objectbom->fk_warehouse; $_POST['note_private'] = $objectbom->note_private; } @@ -205,6 +207,13 @@ llxHeader('', $title, ''); // Part to create if ($action == 'create') { + if (GETPOST('fk_bom', 'int') > 0) { + $titlelist = $langs->trans("ToConsume"); + if ($objectbom->bomtype == 1) { + $titlelist = $langs->trans("ToObtain"); + } + } + print load_fiche_titre($langs->trans("NewObject", $langs->transnoentitiesnoconv("Mo")), '', 'mrp'); print '
'; @@ -245,7 +254,10 @@ if ($action == 'create') { console.log(data); if (typeof data.rowid != "undefined") { console.log("New BOM loaded, we set values in form"); + console.log(data); $('#qty').val(data.qty); + $("#mrptype").val(data.bomtype); // We set bomtype into mrptype + $('#mrptype').trigger('change'); // Notify any JS components that the value changed $("#fk_product").val(data.fk_product); $('#fk_product').trigger('change'); // Notify any JS components that the value changed $('#note_private').val(data.description); @@ -268,7 +280,7 @@ if ($action == 'create') { else if (jQuery('#fk_bom').val() < 0) { // Redirect to page with all fields defined except fk_bom set console.log(jQuery('#fk_product').val()); - window.location.href = '?action=create&qty='+jQuery('#qty').val()+'&fk_product='+jQuery('#fk_product').val()+'&label='+jQuery('#label').val()+'&fk_project='+jQuery('#fk_project').val()+'&fk_warehouse='+jQuery('#fk_warehouse').val(); + window.location.href = '?action=create&qty='+jQuery('#qty').val()+'&mrptype='+jQuery('#mrptype').val()+'&fk_product='+jQuery('#fk_product').val()+'&label='+jQuery('#label').val()+'&fk_project='+jQuery('#fk_project').val()+'&fk_warehouse='+jQuery('#fk_warehouse').val(); /* $('#qty').val(''); $("#fk_product").val(''); @@ -288,13 +300,14 @@ if ($action == 'create') { print $form->buttonsSaveCancel("Create"); - if (GETPOST('fk_bom', 'int') > 0) { - print load_fiche_titre($langs->trans("ToConsume")); + if ($objectbom->id > 0) { + print load_fiche_titre($titlelist); print '
'; print ''; $object->lines = $objectbom->lines; + $object->mrptype = $objectbom->bomtype; $object->bom = $objectbom; $object->printOriginLinesList('', array()); diff --git a/htdocs/partnership/class/partnership.class.php b/htdocs/partnership/class/partnership.class.php index 121b53007df..82a5ee65171 100644 --- a/htdocs/partnership/class/partnership.class.php +++ b/htdocs/partnership/class/partnership.class.php @@ -496,7 +496,7 @@ class Partnership extends CommonObject } } if (count($sqlwhere) > 0) { - $sql .= ' AND ('.implode(' '.$filtermode.' ', $sqlwhere).')'; + $sql .= ' AND ('.implode(' '.$this->db->escape($filtermode).' ', $sqlwhere).')'; } if (!empty($sortfield)) { diff --git a/htdocs/product/class/productfournisseurprice.class.php b/htdocs/product/class/productfournisseurprice.class.php index 7597b32f21a..550b0e5db36 100644 --- a/htdocs/product/class/productfournisseurprice.class.php +++ b/htdocs/product/class/productfournisseurprice.class.php @@ -339,7 +339,7 @@ class ProductFournisseurPrice extends CommonObject } } if (count($sqlwhere) > 0) { - $sql .= ' AND ('.implode(' '.$filtermode.' ', $sqlwhere).')'; + $sql .= ' AND ('.implode(' '.$this->db->escape($filtermode).' ', $sqlwhere).')'; } if (!empty($sortfield)) { diff --git a/htdocs/product/stock/class/productstockentrepot.class.php b/htdocs/product/stock/class/productstockentrepot.class.php index 0a9636c0290..9b32fe1fe5e 100644 --- a/htdocs/product/stock/class/productstockentrepot.class.php +++ b/htdocs/product/stock/class/productstockentrepot.class.php @@ -277,7 +277,7 @@ class ProductStockEntrepot extends CommonObject } } if (count($sqlwhere) > 0) { - $sql .= ' AND '.implode(' '.$filtermode.' ', $sqlwhere); + $sql .= ' AND '.implode(' '.$this->db->escape($filtermode).' ', $sqlwhere); } if (!empty($fk_product) && $fk_product > 0) { diff --git a/htdocs/recruitment/class/recruitmentcandidature.class.php b/htdocs/recruitment/class/recruitmentcandidature.class.php index e0008d1a694..37635d27048 100644 --- a/htdocs/recruitment/class/recruitmentcandidature.class.php +++ b/htdocs/recruitment/class/recruitmentcandidature.class.php @@ -388,7 +388,7 @@ class RecruitmentCandidature extends CommonObject } } if (count($sqlwhere) > 0) { - $sql .= ' AND ('.implode(' '.$filtermode.' ', $sqlwhere).')'; + $sql .= ' AND ('.implode(' '.$this->db->escape($filtermode).' ', $sqlwhere).')'; } if (!empty($sortfield)) { diff --git a/htdocs/recruitment/class/recruitmentjobposition.class.php b/htdocs/recruitment/class/recruitmentjobposition.class.php index 94ce1f8683d..cbfd11fd431 100644 --- a/htdocs/recruitment/class/recruitmentjobposition.class.php +++ b/htdocs/recruitment/class/recruitmentjobposition.class.php @@ -397,7 +397,7 @@ class RecruitmentJobPosition extends CommonObject } } if (count($sqlwhere) > 0) { - $sql .= ' AND ('.implode(' '.$filtermode.' ', $sqlwhere).')'; + $sql .= ' AND ('.implode(' '.$this->db->escape($filtermode).' ', $sqlwhere).')'; } if (!empty($sortfield)) { diff --git a/htdocs/ticket/class/cticketcategory.class.php b/htdocs/ticket/class/cticketcategory.class.php index 34321b5b898..efd9b84330b 100644 --- a/htdocs/ticket/class/cticketcategory.class.php +++ b/htdocs/ticket/class/cticketcategory.class.php @@ -408,7 +408,7 @@ class CTicketCategory extends CommonObject } } if (count($sqlwhere) > 0) { - $sql .= ' AND ('.implode(' '.$filtermode.' ', $sqlwhere).')'; + $sql .= ' AND ('.implode(' '.$this->db->escape($filtermode).' ', $sqlwhere).')'; } if (!empty($sortfield)) { diff --git a/htdocs/user/class/user.class.php b/htdocs/user/class/user.class.php index db2d4583177..f229cd80637 100644 --- a/htdocs/user/class/user.class.php +++ b/htdocs/user/class/user.class.php @@ -3526,7 +3526,7 @@ class User extends CommonObject } } if (count($sqlwhere) > 0) { - $sql .= ' AND ('.implode(' '.$filtermode.' ', $sqlwhere).')'; + $sql .= ' AND ('.implode(' '.$this->db->escape($filtermode).' ', $sqlwhere).')'; } $sql .= $this->db->order($sortfield, $sortorder); if ($limit) { diff --git a/htdocs/website/class/website.class.php b/htdocs/website/class/website.class.php index ff06eff74b6..f80a705c3f2 100644 --- a/htdocs/website/class/website.class.php +++ b/htdocs/website/class/website.class.php @@ -419,7 +419,7 @@ class Website extends CommonObject } } if (count($sqlwhere) > 0) { - $sql .= ' AND '.implode(' '.$filtermode.' ', $sqlwhere); + $sql .= ' AND '.implode(' '.$this->db->escape($filtermode).' ', $sqlwhere); } if (!empty($sortfield)) { diff --git a/htdocs/website/class/websitepage.class.php b/htdocs/website/class/websitepage.class.php index 275c3c94afe..19fa8b8d12d 100644 --- a/htdocs/website/class/websitepage.class.php +++ b/htdocs/website/class/websitepage.class.php @@ -441,7 +441,7 @@ class WebsitePage extends CommonObject } } if (count($sqlwhere) > 0) { - $sql .= " AND (".implode(' '.$filtermode.' ', $sqlwhere).')'; + $sql .= " AND (".implode(' '.$this->db->escape($filtermode).' ', $sqlwhere).')'; } if (!empty($sortfield)) { @@ -543,7 +543,7 @@ class WebsitePage extends CommonObject } } if (count($sqlwhere) > 0) { - $sql .= ' AND ('.implode(' '.$filtermode.' ', $sqlwhere).')'; + $sql .= ' AND ('.implode(' '.$this->db->escape($filtermode).' ', $sqlwhere).')'; } $resql = $this->db->query($sql); diff --git a/htdocs/workstation/class/workstation.class.php b/htdocs/workstation/class/workstation.class.php index 8b550add124..aae74e3804c 100755 --- a/htdocs/workstation/class/workstation.class.php +++ b/htdocs/workstation/class/workstation.class.php @@ -440,7 +440,7 @@ class Workstation extends CommonObject } } if (count($sqlwhere) > 0) { - $sql .= ' AND ('.implode(' '.$filtermode.' ', $sqlwhere).')'; + $sql .= ' AND ('.implode(' '.$this->db->escape($filtermode).' ', $sqlwhere).')'; } if (!empty($sortfield)) { diff --git a/htdocs/zapier/class/hook.class.php b/htdocs/zapier/class/hook.class.php index fc03942d978..b27959a24c6 100644 --- a/htdocs/zapier/class/hook.class.php +++ b/htdocs/zapier/class/hook.class.php @@ -430,7 +430,7 @@ class Hook extends CommonObject } } if (count($sqlwhere) > 0) { - $sql .= ' AND ('.implode(' '.$filtermode.' ', $sqlwhere).')'; + $sql .= ' AND ('.implode(' '.$this->db->escape($filtermode).' ', $sqlwhere).')'; } if (!empty($sortfield)) { diff --git a/test/phpunit/CodingPhpTest.php b/test/phpunit/CodingPhpTest.php index a9f6221ea58..40ca07c441f 100644 --- a/test/phpunit/CodingPhpTest.php +++ b/test/phpunit/CodingPhpTest.php @@ -290,7 +290,13 @@ class CodingPhpTest extends PHPUnit\Framework\TestCase // with xxx that is not 'thi' (for $this->db->sanitize) and 'db-' (for $db->sanitize). It means we forget a ' if string, or an (int) if int, when forging sql request. preg_match_all('/(DELETE|OR|AND|WHERE|INSERT)\s.*([^\s][^\s][^\s])\s*=\s*"\s*\.\s*\$(...)/', $filecontent, $matches, PREG_SET_ORDER); foreach ($matches as $key => $val) { - if ($val[2] == 'ity' && $val[3] == 'con') { // exclude entity = $conf->entity + if ($val[2] == 'ity' && $val[3] == 'con') { // exclude entity = ".$conf->entity + continue; + } + if ($val[2] == 'ame' && $val[3] == 'db-' && preg_match('/WHERE name/', $val[0])) { // exclude name = ".$db->encrypt( + continue; + } + if ($val[2] == 'ame' && $val[3] == 'thi' && preg_match('/WHERE name/', $val[0])) { // exclude name = ".$this->db->encrypt( continue; } var_dump($matches); @@ -305,7 +311,10 @@ class CodingPhpTest extends PHPUnit\Framework\TestCase // with xxx that is not 'db-' (for $db->escape). It means we forget a ' if string, or an (int) if int, when forging sql request. preg_match_all('/(VALUES).*,\s*"\s*\.\s*\$(...)/', $filecontent, $matches, PREG_SET_ORDER); foreach ($matches as $key => $val) { - if ($val[2] == 'VALUES' && $val[3] == 'db-') { // exclude $db->escape( + if ($val[1] == 'VALUES' && $val[2] == 'db-') { // exclude $db->escape( + continue; + } + if ($val[1] == 'VALUES' && $val[2] == 'thi' && preg_match('/this->db->encrypt/', $val[0])) { // exclude ".$this->db->encrypt( continue; } var_dump($matches); @@ -345,7 +354,7 @@ class CodingPhpTest extends PHPUnit\Framework\TestCase // Check string sql|set...'.$yyy->xxx with xxx that is not 'escape', 'idate', .... It means we forget a db->escape when forging sql request. preg_match_all('/(\$sql|SET\s|WHERE\s|INSERT\s|VALUES\s|VALUES\().+\s*\'\s*\.\s*\$(.........)/', $filecontent, $matches, PREG_SET_ORDER); foreach ($matches as $key => $val) { - if (! in_array($val[2], array('this->db-', 'db->sanit', 'conf->ent', 'key : \'\')', 'key])."\')', 'excludefi', 'regexstri', 'filtermod'))) { + if (! in_array($val[2], array('this->db-', 'db->sanit', 'conf->ent', 'key : \'\')', 'key])."\')', 'excludefi', 'regexstri', ''))) { $ok=false; var_dump($matches); break;