diff --git a/htdocs/core/db/mysqli.class.php b/htdocs/core/db/mysqli.class.php index 9c2948cb262..5b43b4e2cbc 100644 --- a/htdocs/core/db/mysqli.class.php +++ b/htdocs/core/db/mysqli.class.php @@ -866,7 +866,7 @@ class DoliDBMysqli extends DoliDB $sqlfields[$i] .= " ".$this->sanitize($field_desc['null'], 0, 0, 1); } if (!is_null($field_desc['extra']) && $field_desc['extra'] !== '') { - $sqlfields[$i] .= " ".$this->sanitize($field_desc['extra']); + $sqlfields[$i] .= " ".$this->sanitize($field_desc['extra'], 0, 0, 1); } $i++; } @@ -940,7 +940,7 @@ class DoliDBMysqli extends DoliDB public function DDLDescTable($table, $field = "") { // phpcs:enable - $sql = "DESC ".$table." ".$field; + $sql = "DESC ".$this->sanitize($table)." ".$this->sanitize($field); dol_syslog(get_class($this)."::DDLDescTable ".$sql, LOG_DEBUG); $this->_results = $this->query($sql); @@ -962,30 +962,32 @@ class DoliDBMysqli extends DoliDB // phpcs:enable // cles recherchees dans le tableau des descriptions (field_desc) : type,value,attribute,null,default,extra // ex. : $field_desc = array('type'=>'int','value'=>'11','null'=>'not null','extra'=> 'auto_increment'); - $sql = "ALTER TABLE ".$table." ADD ".$field_name." "; - $sql .= $field_desc['type']; - if (preg_match("/^[^\s]/i", $field_desc['value'])) { - if (!in_array($field_desc['type'], array('date', 'datetime')) && $field_desc['value']) { - $sql .= "(".$field_desc['value'].")"; + $sql = "ALTER TABLE ".$this->sanitize($table)." ADD ".$this->sanitize($field_name)." "; + $sql .= $this->sanitize($field_desc['type']); + if (isset($field_desc['value']) && preg_match("/^[^\s]/i", $field_desc['value'])) { + if (!in_array($field_desc['type'], array('tinyint', 'smallint', 'int', 'date', 'datetime')) && $field_desc['value']) { + $sql .= "(".$this->sanitize($field_desc['value']).")"; } } if (isset($field_desc['attribute']) && preg_match("/^[^\s]/i", $field_desc['attribute'])) { - $sql .= " ".$field_desc['attribute']; + $sql .= " ".$this->sanitize($field_desc['attribute']); } if (isset($field_desc['null']) && preg_match("/^[^\s]/i", $field_desc['null'])) { $sql .= " ".$field_desc['null']; } if (isset($field_desc['default']) && preg_match("/^[^\s]/i", $field_desc['default'])) { - if (preg_match("/null/i", $field_desc['default'])) { - $sql .= " default ".$field_desc['default']; + if (in_array($field_desc['type'], array('tinyint', 'smallint', 'int', 'double'))) { + $sql .= " DEFAULT ".((float) $field_desc['default']); + } elseif ($field_desc['default'] == 'null' || $field_desc['default'] == 'CURRENT_TIMESTAMP') { + $sql .= " DEFAULT ".$this->sanitize($field_desc['default']); } else { - $sql .= " default '".$this->escape($field_desc['default'])."'"; + $sql .= " DEFAULT '".$this->escape($field_desc['default'])."'"; } } if (isset($field_desc['extra']) && preg_match("/^[^\s]/i", $field_desc['extra'])) { - $sql .= " ".$field_desc['extra']; + $sql .= " ".$this->escape($field_desc['extra'], 0, 0, 1); } - $sql .= " ".$field_position; + $sql .= " ".$this->escape($field_position, 0, 0, 1); dol_syslog(get_class($this)."::DDLAddField ".$sql, LOG_DEBUG); if ($this->query($sql)) { @@ -1006,18 +1008,18 @@ class DoliDBMysqli extends DoliDB public function DDLUpdateField($table, $field_name, $field_desc) { // phpcs:enable - $sql = "ALTER TABLE ".$table; - $sql .= " MODIFY COLUMN ".$field_name." ".$field_desc['type']; + $sql = "ALTER TABLE ".$this->sanitize($table); + $sql .= " MODIFY COLUMN ".$this->sanitize($field_name)." ".$this->sanitize($field_desc['type']); if (in_array($field_desc['type'], array('double', 'tinyint', 'int', 'varchar')) && $field_desc['value']) { - $sql .= "(".$field_desc['value'].")"; + $sql .= "(".$this->sanitize($field_desc['value']).")"; } if ($field_desc['null'] == 'not null' || $field_desc['null'] == 'NOT NULL') { // We will try to change format of column to NOT NULL. To be sure the ALTER works, we try to update fields that are NULL if ($field_desc['type'] == 'varchar' || $field_desc['type'] == 'text') { - $sqlbis = "UPDATE ".$table." SET ".$field_name." = '".$this->escape(isset($field_desc['default']) ? $field_desc['default'] : '')."' WHERE ".$field_name." IS NULL"; + $sqlbis = "UPDATE ".$this->sanitize($table)." SET ".$this->sanitize($field_name)." = '".$this->escape(isset($field_desc['default']) ? $field_desc['default'] : '')."' WHERE ".$this->sanitize($field_name)." IS NULL"; $this->query($sqlbis); - } elseif ($field_desc['type'] == 'tinyint' || $field_desc['type'] == 'int') { - $sqlbis = "UPDATE ".$table." SET ".$field_name." = ".((int) $this->escape(isset($field_desc['default']) ? $field_desc['default'] : 0))." WHERE ".$field_name." IS NULL"; + } elseif (in_array($field_desc['type'], array('tinyint', 'smallint', 'int', 'double'))) { + $sqlbis = "UPDATE ".$this->sanitize($table)." SET ".$this->sanitize($field_name)." = ".((float) $this->escape(isset($field_desc['default']) ? $field_desc['default'] : 0))." WHERE ".$this->sanitize($field_name)." IS NULL"; $this->query($sqlbis); } @@ -1053,7 +1055,7 @@ class DoliDBMysqli extends DoliDB // phpcs:enable $tmp_field_name = preg_replace('/[^a-z0-9\.\-\_]/i', '', $field_name); - $sql = "ALTER TABLE ".$table." DROP COLUMN `".$tmp_field_name."`"; + $sql = "ALTER TABLE ".$this->sanitize($table)." DROP COLUMN `".$this->sanitize($tmp_field_name)."`"; if ($this->query($sql)) { return 1; } diff --git a/htdocs/core/db/pgsql.class.php b/htdocs/core/db/pgsql.class.php index 3cfe5671085..51ea5e84447 100644 --- a/htdocs/core/db/pgsql.class.php +++ b/htdocs/core/db/pgsql.class.php @@ -1160,7 +1160,7 @@ class DoliDBPgsql extends DoliDB // phpcs:enable $tmptable = preg_replace('/[^a-z0-9\.\-\_]/i', '', $table); - $sql = "DROP TABLE ".$tmptable; + $sql = "DROP TABLE ".$this->sanitize($tmptable); if (!$this->query($sql)) { return -1; @@ -1169,31 +1169,6 @@ class DoliDBPgsql extends DoliDB } } - // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps - /** - * Create a user to connect to database - * - * @param string $dolibarr_main_db_host Ip server - * @param string $dolibarr_main_db_user Name of user to create - * @param string $dolibarr_main_db_pass Password of user to create - * @param string $dolibarr_main_db_name Database name where user must be granted - * @return int Return integer <0 if KO, >=0 if OK - */ - public function DDLCreateUser($dolibarr_main_db_host, $dolibarr_main_db_user, $dolibarr_main_db_pass, $dolibarr_main_db_name) - { - // phpcs:enable - // Note: using ' on user does not works with pgsql - $sql = "CREATE USER ".$this->escape($dolibarr_main_db_user)." with password '".$this->escape($dolibarr_main_db_pass)."'"; - - dol_syslog(get_class($this)."::DDLCreateUser", LOG_DEBUG); // No sql to avoid password in log - $resql = $this->query($sql); - if (!$resql) { - return -1; - } - - return 1; - } - // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps /** * Return a pointer of line with description of a table or field @@ -1231,30 +1206,32 @@ class DoliDBPgsql extends DoliDB // phpcs:enable // cles recherchees dans le tableau des descriptions (field_desc) : type,value,attribute,null,default,extra // ex. : $field_desc = array('type'=>'int','value'=>'11','null'=>'not null','extra'=> 'auto_increment'); - $sql = "ALTER TABLE ".$table." ADD ".$field_name." "; - $sql .= $field_desc['type']; - if (preg_match("/^[^\s]/i", $field_desc['value'])) { - if (!in_array($field_desc['type'], array('smallint', 'int', 'date', 'datetime')) && $field_desc['value']) { - $sql .= "(".$field_desc['value'].")"; + $sql = "ALTER TABLE ".$this->sanitize($table)." ADD ".$this->sanitize($field_name)." "; + $sql .= $this->sanitize($field_desc['type']); + if (isset($field_desc['value']) && preg_match("/^[^\s]/i", $field_desc['value'])) { + if (!in_array($field_desc['type'], array('tinyint', 'smallint', 'int', 'date', 'datetime')) && $field_desc['value']) { + $sql .= "(".$this->sanitize($field_desc['value']).")"; } } - if (preg_match("/^[^\s]/i", $field_desc['attribute'])) { - $sql .= " ".$field_desc['attribute']; + if (isset($field_desc['attribute']) && preg_match("/^[^\s]/i", $field_desc['attribute'])) { + $sql .= " ".$this->sanitize($field_desc['attribute']); } - if (preg_match("/^[^\s]/i", $field_desc['null'])) { + if (isset($field_desc['null']) && preg_match("/^[^\s]/i", $field_desc['null'])) { $sql .= " ".$field_desc['null']; } - if (preg_match("/^[^\s]/i", $field_desc['default'])) { - if (preg_match("/null/i", $field_desc['default'])) { - $sql .= " default ".$field_desc['default']; + if (isset($field_desc['default']) && preg_match("/^[^\s]/i", $field_desc['default'])) { + if (in_array($field_desc['type'], array('tinyint', 'smallint', 'int', 'double'))) { + $sql .= " DEFAULT ".((float) $field_desc['default']); + } elseif ($field_desc['default'] == 'null' || $field_desc['default'] == 'CURRENT_TIMESTAMP') { + $sql .= " DEFAULT ".$this->sanitize($field_desc['default']); } else { - $sql .= " default '".$this->escape($field_desc['default'])."'"; + $sql .= " DEFAULT '".$this->escape($field_desc['default'])."'"; } } - if (preg_match("/^[^\s]/i", $field_desc['extra'])) { - $sql .= " ".$field_desc['extra']; + if (isset($field_desc['extra']) && preg_match("/^[^\s]/i", $field_desc['extra'])) { + $sql .= " ".$this->escape($field_desc['extra'], 0, 0, 1); } - $sql .= " ".$field_position; + $sql .= " ".$this->escape($field_position, 0, 0, 1); dol_syslog($sql, LOG_DEBUG); if (!$this -> query($sql)) { @@ -1275,30 +1252,30 @@ class DoliDBPgsql extends DoliDB public function DDLUpdateField($table, $field_name, $field_desc) { // phpcs:enable - $sql = "ALTER TABLE ".$table; - $sql .= " ALTER COLUMN ".$this->escape($field_name)." TYPE ".$field_desc['type']; + $sql = "ALTER TABLE ".$this->sanitize($table); + $sql .= " ALTER COLUMN ".$this->sanitize($field_name)." TYPE ".$this->sanitize($field_desc['type']); if (preg_match("/^[^\s]/i", $field_desc['value'])) { if (!in_array($field_desc['type'], array('smallint', 'int', 'date', 'datetime')) && $field_desc['value']) { - $sql .= "(".$field_desc['value'].")"; + $sql .= "(".$this->sanitize($field_desc['value']).")"; } } if ($field_desc['null'] == 'not null' || $field_desc['null'] == 'NOT NULL') { // We will try to change format of column to NOT NULL. To be sure the ALTER works, we try to update fields that are NULL if ($field_desc['type'] == 'varchar' || $field_desc['type'] == 'text') { - $sqlbis = "UPDATE ".$table." SET ".$this->escape($field_name)." = '".$this->escape(isset($field_desc['default']) ? $field_desc['default'] : '')."' WHERE ".$this->escape($field_name)." IS NULL"; + $sqlbis = "UPDATE ".$this->sanitize($table)." SET ".$this->escape($field_name)." = '".$this->escape(isset($field_desc['default']) ? $field_desc['default'] : '')."' WHERE ".$this->escape($field_name)." IS NULL"; $this->query($sqlbis); - } elseif ($field_desc['type'] == 'tinyint' || $field_desc['type'] == 'int') { - $sqlbis = "UPDATE ".$table." SET ".$this->escape($field_name)." = ".((int) $this->escape(isset($field_desc['default']) ? $field_desc['default'] : 0))." WHERE ".$this->escape($field_name)." IS NULL"; + } elseif (in_array($field_desc['type'], array('tinyint', 'smallint', 'int', 'double'))) { + $sqlbis = "UPDATE ".$this->sanitize($table)." SET ".$this->escape($field_name)." = ".((float) $this->escape(isset($field_desc['default']) ? $field_desc['default'] : 0))." WHERE ".$this->escape($field_name)." IS NULL"; $this->query($sqlbis); } } if (isset($field_desc['default']) && $field_desc['default'] != '') { - if ($field_desc['type'] == 'double' || $field_desc['type'] == 'tinyint' || $field_desc['type'] == 'int') { - $sql .= ", ALTER COLUMN ".$this->escape($field_name)." SET DEFAULT ".((float) $field_desc['default']); + if (in_array($field_desc['type'], array('tinyint', 'smallint', 'int', 'double'))) { + $sql .= ", ALTER COLUMN ".$this->sanitize($field_name)." SET DEFAULT ".((float) $field_desc['default']); } elseif ($field_desc['type'] != 'text') { // Default not supported on text fields ? - $sql .= ", ALTER COLUMN ".$this->escape($field_name)." SET DEFAULT '".$this->escape($field_desc['default'])."'"; + $sql .= ", ALTER COLUMN ".$this->sanitize($field_name)." SET DEFAULT '".$this->escape($field_desc['default'])."'"; } } @@ -1322,7 +1299,7 @@ class DoliDBPgsql extends DoliDB // phpcs:enable $tmp_field_name = preg_replace('/[^a-z0-9\.\-\_]/i', '', $field_name); - $sql = "ALTER TABLE ".$table." DROP COLUMN ".$tmp_field_name; + $sql = "ALTER TABLE ".$this->sanitize($table)." DROP COLUMN ".$this->sanitize($tmp_field_name); if (!$this->query($sql)) { $this->error = $this->lasterror(); return -1; @@ -1330,6 +1307,31 @@ class DoliDBPgsql extends DoliDB return 1; } + // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps + /** + * Create a user to connect to database + * + * @param string $dolibarr_main_db_host Ip server + * @param string $dolibarr_main_db_user Name of user to create + * @param string $dolibarr_main_db_pass Password of user to create + * @param string $dolibarr_main_db_name Database name where user must be granted + * @return int Return integer <0 if KO, >=0 if OK + */ + public function DDLCreateUser($dolibarr_main_db_host, $dolibarr_main_db_user, $dolibarr_main_db_pass, $dolibarr_main_db_name) + { + // phpcs:enable + // Note: using ' on user does not works with pgsql + $sql = "CREATE USER ".$this->sanitize($dolibarr_main_db_user)." with password '".$this->escape($dolibarr_main_db_pass)."'"; + + dol_syslog(get_class($this)."::DDLCreateUser", LOG_DEBUG); // No sql to avoid password in log + $resql = $this->query($sql); + if (!$resql) { + return -1; + } + + return 1; + } + /** * Return charset used to store data in database * diff --git a/htdocs/core/db/sqlite3.class.php b/htdocs/core/db/sqlite3.class.php index 477d7d33c42..392b5addffa 100644 --- a/htdocs/core/db/sqlite3.class.php +++ b/htdocs/core/db/sqlite3.class.php @@ -1118,16 +1118,18 @@ class DoliDBSqlite3 extends DoliDB $sql .= " ".$field_desc['null']; } if (preg_match("/^[^\s]/i", $field_desc['default'])) { - if (preg_match("/null/i", $field_desc['default'])) { - $sql .= " default ".$field_desc['default']; + if (in_array($field_desc['type'], array('tinyint', 'smallint', 'int', 'double'))) { + $sql .= " DEFAULT ".((float) $field_desc['default']); + } elseif ($field_desc['default'] == 'null' || $field_desc['default'] == 'CURRENT_TIMESTAMP') { + $sql .= " DEFAULT ".$this->sanitize($field_desc['default']); } else { - $sql .= " default '".$this->escape($field_desc['default'])."'"; + $sql .= " DEFAULT '".$this->escape($field_desc['default'])."'"; } } - if (preg_match("/^[^\s]/i", $field_desc['extra'])) { - $sql .= " ".$field_desc['extra']; + if (isset($field_desc['extra']) && preg_match("/^[^\s]/i", $field_desc['extra'])) { + $sql .= " ".$this->escape($field_desc['extra'], 0, 0, 1); } - $sql .= " ".$field_position; + $sql .= " ".$this->escape($field_position, 0, 0, 1); dol_syslog(get_class($this)."::DDLAddField ".$sql, LOG_DEBUG); if (!$this->query($sql)) { @@ -1148,10 +1150,10 @@ class DoliDBSqlite3 extends DoliDB public function DDLUpdateField($table, $field_name, $field_desc) { // phpcs:enable - $sql = "ALTER TABLE ".$table; - $sql .= " MODIFY COLUMN ".$field_name." ".$field_desc['type']; + $sql = "ALTER TABLE ".$this->sanitize($table); + $sql .= " MODIFY COLUMN ".$this->sanitize(($field_name)." ".$this->sanitize($field_desc['type']); if ($field_desc['type'] == 'tinyint' || $field_desc['type'] == 'int' || $field_desc['type'] == 'varchar') { - $sql .= "(".$field_desc['value'].")"; + $sql .= "(".$this->sanitize($field_desc['value']).")"; } dol_syslog(get_class($this)."::DDLUpdateField ".$sql, LOG_DEBUG); @@ -1174,7 +1176,7 @@ class DoliDBSqlite3 extends DoliDB // phpcs:enable $tmp_field_name = preg_replace('/[^a-z0-9\.\-\_]/i', '', $field_name); - $sql = "ALTER TABLE ".$table." DROP COLUMN `".$tmp_field_name."`"; + $sql = "ALTER TABLE ".$this->sanitize($table)." DROP COLUMN `".$this->sanitize($tmp_field_name)."`"; if (!$this->query($sql)) { $this->error = $this->lasterror(); return -1; diff --git a/htdocs/core/lib/modulebuilder.lib.php b/htdocs/core/lib/modulebuilder.lib.php index 159c5712399..1ae0d52d93a 100644 --- a/htdocs/core/lib/modulebuilder.lib.php +++ b/htdocs/core/lib/modulebuilder.lib.php @@ -1288,7 +1288,7 @@ function createNewDictionnary($modulename, $file, $namedic, $dictionnaires = nul } $columns = array( - 'rowid' => array('type' => 'integer', 'value' => 11), + 'rowid' => array('type' => 'integer', 'value' => 11, 'extra' => 'AUTO_INCREMENT PRIMARY KEY'), 'code' => array('type' => 'varchar', 'value' => 255, 'null'=>'NOT NULL'), 'label' => array('type' => 'varchar', 'value' => 255, 'null'=>'NOT NULL'), 'position' => array('type' => 'integer', 'value' => 11, 'null'=>'NULL'), diff --git a/test/phpunit/DoliDBTest.php b/test/phpunit/DoliDBTest.php index 34f70e459c9..adafc6a676c 100644 --- a/test/phpunit/DoliDBTest.php +++ b/test/phpunit/DoliDBTest.php @@ -66,7 +66,7 @@ class DoliDBTest extends CommonClassTest $res = $db->DDLDropTable($namedic); $columns = array( - 'rowid' => array('type' => 'integer', 'value' => 11), + 'rowid' => array('type' => 'integer', 'value' => 11, 'AUTO_INCREMENT PRIMARY KEY'), 'code' => array('type' => 'varchar', 'value' => 255, 'null'=>'NOT NULL'), 'label' => array('type' => 'varchar', 'value' => 255, 'null'=>'NOT NULL'), 'position' => array('type' => 'integer', 'value' => 11, 'null'=>'NULL'),