From 9e7aeca44744a86e5208ae85a11b9bae6c92f118 Mon Sep 17 00:00:00 2001 From: Kamel Khelifa Date: Wed, 20 Mar 2024 15:26:19 +0100 Subject: [PATCH 01/11] FIX: Fix save directory for invoice ODT and multientities --- .../modules/facture/doc/doc_generic_invoice_odt.modules.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/core/modules/facture/doc/doc_generic_invoice_odt.modules.php b/htdocs/core/modules/facture/doc/doc_generic_invoice_odt.modules.php index 6b28da3e1e1..66182bcebba 100644 --- a/htdocs/core/modules/facture/doc/doc_generic_invoice_odt.modules.php +++ b/htdocs/core/modules/facture/doc/doc_generic_invoice_odt.modules.php @@ -253,7 +253,7 @@ class doc_generic_invoice_odt extends ModelePDFFactures $object->fetch_thirdparty(); - $dir = $conf->facture->dir_output; + $dir = empty($conf->facture->multidir_output[$object->entity]) ? $conf->facture->dir_output : $conf->facture->multidir_output[$object->entity]; $objectref = dol_sanitizeFileName($object->ref); if (!preg_match('/specimen/i', $objectref)) { $dir .= "/".$objectref; From 8ab3333eec2dc009ef294e783b5f83e15d87131a Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Wed, 20 Mar 2024 20:59:08 +0100 Subject: [PATCH 02/11] FIX logo of paypal payment on payment page --- htdocs/public/payment/newpayment.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/htdocs/public/payment/newpayment.php b/htdocs/public/payment/newpayment.php index 9e5d578e01a..9825b331f1b 100644 --- a/htdocs/public/payment/newpayment.php +++ b/htdocs/public/payment/newpayment.php @@ -2151,7 +2151,7 @@ if ($action != 'dopayment') { if (getDolGlobalString('PAYPAL_API_INTEGRAL_OR_PAYPALONLY') != 'integral') { print '
 
'; } - print ' '; + print ' '; if (getDolGlobalString('PAYPAL_API_INTEGRAL_OR_PAYPALONLY') == 'integral') { print '
'; print ''.$langs->trans("CreditOrDebitCard").' - '; From 34bd1f0fd300bfda0c263a5cce60a5122a94c213 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Wed, 20 Mar 2024 21:00:37 +0100 Subject: [PATCH 03/11] Doc --- ChangeLog | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index 32270994e3b..9f275d641ad 100644 --- a/ChangeLog +++ b/ChangeLog @@ -72,7 +72,7 @@ FIX: #yogosha21416 For users: ---------- -NEW: Compatibility with PHP 8.2 +NEW: Compatibility with PHP 8.2 (warning must be disabled) NEW: Module Workstation (used to enhance the module BOM and Manufacturing Order) is now stable NEW: Add a confirmation popup when deleting extrafields NEW: Add type 'icon' type for extrafields From 440c7b4493c67cf4e938341fd07096b96fb3e61c Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Wed, 20 Mar 2024 21:27:28 +0100 Subject: [PATCH 04/11] FIX #28978 FIX #28976 --- htdocs/takepos/index.php | 3 +-- htdocs/user/logout.php | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/htdocs/takepos/index.php b/htdocs/takepos/index.php index c58d0f5a81b..dc03d83ff90 100644 --- a/htdocs/takepos/index.php +++ b/htdocs/takepos/index.php @@ -73,7 +73,6 @@ if ($setcurrency != "") { // We will recalculate amount for foreign currency at next call of invoice.php when $_SESSION["takeposcustomercurrency"] differs from invoice->multicurrency_code. } -$_SESSION["urlfrom"] = '/takepos/index.php'; $langs->loadLangs(array("bills", "orders", "commercial", "cashdesk", "receiptprinter", "banks")); @@ -1146,7 +1145,7 @@ if (!getDolGlobalString('TAKEPOS_HIDE_HEAD_BAR')) { ?> diff --git a/htdocs/user/logout.php b/htdocs/user/logout.php index 4713d4e9e97..77fcb90a4b9 100644 --- a/htdocs/user/logout.php +++ b/htdocs/user/logout.php @@ -72,7 +72,7 @@ if ($reshook < 0) { } // Define url to go after disconnect -$urlfrom = empty($_SESSION["urlfrom"]) ? '' : $_SESSION["urlfrom"]; +$urlfrom = empty($_SESSION["urlfrom"]) ? GETPOST('urlfrom') : $_SESSION["urlfrom"]; // Define url to go $url = DOL_URL_ROOT."/index.php"; // By default go to login page From 5bae4ffe4d5cd6cbd323c92ecee6ef6e43f42460 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Wed, 20 Mar 2024 21:27:28 +0100 Subject: [PATCH 05/11] FIX #28978 FIX #28976 --- htdocs/takepos/index.php | 3 +-- htdocs/user/logout.php | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/htdocs/takepos/index.php b/htdocs/takepos/index.php index 97dae7e1a14..99374eebc9f 100644 --- a/htdocs/takepos/index.php +++ b/htdocs/takepos/index.php @@ -73,7 +73,6 @@ if ($setcurrency != "") { // We will recalculate amount for foreign currency at next call of invoice.php when $_SESSION["takeposcustomercurrency"] differs from invoice->multicurrency_code. } -$_SESSION["urlfrom"] = '/takepos/index.php'; $langs->loadLangs(array("bills", "orders", "commercial", "cashdesk", "receiptprinter", "banks")); @@ -1107,7 +1106,7 @@ if (empty($conf->global->TAKEPOS_HIDE_HEAD_BAR)) { }?> diff --git a/htdocs/user/logout.php b/htdocs/user/logout.php index d71ee34d93f..129ae24df06 100644 --- a/htdocs/user/logout.php +++ b/htdocs/user/logout.php @@ -72,7 +72,7 @@ if ($reshook < 0) { } // Define url to go after disconnect -$urlfrom = empty($_SESSION["urlfrom"]) ? '' : $_SESSION["urlfrom"]; +$urlfrom = empty($_SESSION["urlfrom"]) ? GETPOST('urlfrom') : $_SESSION["urlfrom"]; // Define url to go $url = DOL_URL_ROOT."/index.php"; // By default go to login page From 976686262d5ee858842ffaf93588e51f4b141b15 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9s=20Maldonado?= Date: Thu, 21 Mar 2024 02:36:40 +0100 Subject: [PATCH 06/11] FIX: SQL syntax error in DDLUpdateField --- htdocs/core/db/pgsql.class.php | 4 ++-- test/phpunit/DoliDBTest.php | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/htdocs/core/db/pgsql.class.php b/htdocs/core/db/pgsql.class.php index 2923992e345..29989873d3c 100644 --- a/htdocs/core/db/pgsql.class.php +++ b/htdocs/core/db/pgsql.class.php @@ -1273,9 +1273,9 @@ class DoliDBPgsql extends DoliDB if (isset($field_desc['default']) && $field_desc['default'] != '') { if ($field_desc['type'] == 'double' || $field_desc['type'] == 'tinyint' || $field_desc['type'] == 'int') { - $sql .= " DEFAULT ".$this->escape($field_desc['default']); + $sql .= ", ALTER COLUMN ".$this->escape($field_name)." SET DEFAULT ".$this->escape($field_desc['default']); } elseif ($field_desc['type'] != 'text') { - $sql .= " DEFAULT '".$this->escape($field_desc['default'])."'"; // Default not supported on text fields + $sql .= ", ALTER COLUMN ".$this->escape($field_name)." SET DEFAULT '"." DEFAULT '".$this->escape($field_desc['default'])."'"; // Default not supported on text fields } } diff --git a/test/phpunit/DoliDBTest.php b/test/phpunit/DoliDBTest.php index 999c3b3e54a..2a380fa637e 100644 --- a/test/phpunit/DoliDBTest.php +++ b/test/phpunit/DoliDBTest.php @@ -160,7 +160,7 @@ class DoliDBTest extends PHPUnit\Framework\TestCase print __METHOD__." result=".$result."\n"; // TODO Use $savtype and $savnull instead of hard coded - $field_desc = array('type'=>'varchar', 'value'=>'16', 'null'=>'NOT NULL'); + $field_desc = array('type'=>'varchar', 'value'=>'16', 'null'=>'NOT NULL', 'default'=>'aaaabbbbccccdddd'); $result = $db->DDLUpdateField($db->prefix().'c_paper_format', 'code', $field_desc); $this->assertEquals(1, $result); From 27c0192b7ca1657a48b559784f9e6df81437cc74 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Thu, 21 Mar 2024 11:14:39 +0100 Subject: [PATCH 07/11] cast smallint --- htdocs/core/db/mysqli.class.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/htdocs/core/db/mysqli.class.php b/htdocs/core/db/mysqli.class.php index ff63113e47b..6e11faa9fee 100644 --- a/htdocs/core/db/mysqli.class.php +++ b/htdocs/core/db/mysqli.class.php @@ -1013,8 +1013,8 @@ class DoliDBMysqli extends DoliDB } if (isset($field_desc['default']) && $field_desc['default'] != '') { - if ($field_desc['type'] == 'double' || $field_desc['type'] == 'tinyint' || $field_desc['type'] == 'int') { - $sql .= " DEFAULT ".$this->escape($field_desc['default']); + if (in_array($field_desc['type'], array('tinyint', 'smallint', 'int', 'double'))) { + $sql .= " DEFAULT ".((float) $field_desc['default']); } elseif ($field_desc['type'] != 'text') { $sql .= " DEFAULT '".$this->escape($field_desc['default'])."'"; // Default not supported on text fields } From 01a058b2081d2fe031bbdc75d6fa903cd23fca76 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Thu, 21 Mar 2024 11:22:12 +0100 Subject: [PATCH 08/11] Fix regression --- htdocs/core/db/pgsql.class.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/htdocs/core/db/pgsql.class.php b/htdocs/core/db/pgsql.class.php index 29989873d3c..a5d226804b3 100644 --- a/htdocs/core/db/pgsql.class.php +++ b/htdocs/core/db/pgsql.class.php @@ -1273,9 +1273,9 @@ class DoliDBPgsql extends DoliDB 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 ".$this->escape($field_desc['default']); + $sql .= ", ALTER COLUMN ".$this->escape($field_name)." SET DEFAULT ".((float) $field_desc['default']); } elseif ($field_desc['type'] != 'text') { - $sql .= ", ALTER COLUMN ".$this->escape($field_name)." SET DEFAULT '"." DEFAULT '".$this->escape($field_desc['default'])."'"; // Default not supported on text fields + $sql .= ", ALTER COLUMN ".$this->escape($field_name)." SET DEFAULT '".$this->escape($field_desc['default'])."'"; // Default not supported on text fields } } From ce2959b022a3cc0e74fe3353c70ee4680d9be1db Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Thu, 21 Mar 2024 12:10:09 +0100 Subject: [PATCH 09/11] Clean method DDLCreateTable (used by modulebuilder only) #28996 --- htdocs/core/db/mysqli.class.php | 56 ++++++++++++++--------- htdocs/core/db/pgsql.class.php | 60 +++++++++++++++---------- htdocs/core/db/sqlite3.class.php | 65 ++++++++++++++++----------- htdocs/core/lib/modulebuilder.lib.php | 16 +++---- 4 files changed, 117 insertions(+), 80 deletions(-) diff --git a/htdocs/core/db/mysqli.class.php b/htdocs/core/db/mysqli.class.php index 6e11faa9fee..6f3feb04dcc 100644 --- a/htdocs/core/db/mysqli.class.php +++ b/htdocs/core/db/mysqli.class.php @@ -825,55 +825,66 @@ class DoliDBMysqli extends DoliDB public function DDLCreateTable($table, $fields, $primary_key, $type, $unique_keys = null, $fulltext_keys = null, $keys = null) { // phpcs:enable - // FIXME: $fulltext_keys parameter is unused + // @TODO: $fulltext_keys parameter is unused + + if (empty($type)) { + $type = 'InnoDB'; + } $pk = ''; $sqluq = $sqlk = array(); - // cles recherchees dans le tableau des descriptions (fields) : type,value,attribute,null,default,extra - // ex. : $fields['rowid'] = array('type'=>'int','value'=>'11','null'=>'not null','extra'=> 'auto_increment'); - $sql = "CREATE TABLE ".$table."("; + // Keys found into the array $fields: type,value,attribute,null,default,extra + // ex. : $fields['rowid'] = array( + // 'type'=>'int' or 'integer', + // 'value'=>'11', + // 'null'=>'not null', + // 'extra'=> 'auto_increment' + // ); + $sql = "CREATE TABLE ".$this->sanitize($table)."("; $i = 0; $sqlfields = array(); foreach ($fields as $field_name => $field_desc) { - $sqlfields[$i] = $field_name." "; - $sqlfields[$i] .= $field_desc['type']; - if (preg_match("/^[^\s]/i", $field_desc['value'])) { - $sqlfields[$i] .= "(".$field_desc['value'].")"; + $sqlfields[$i] = $this->sanitize($field_name)." "; + $sqlfields[$i] .= $this->sanitize($field_desc['type']); + if (!is_null($field_desc['value']) && $field_desc['value'] !== '') { + $sqlfields[$i] .= "(".$this->sanitize($field_desc['value']).")"; } - if (preg_match("/^[^\s]/i", $field_desc['attribute'])) { - $sqlfields[$i] .= " ".$field_desc['attribute']; + if (!is_null($field_desc['attribute']) && $field_desc['attribute'] !== '') { + $sqlfields[$i] .= " ".$this->sanitize($field_desc['attribute']); } - if (preg_match("/^[^\s]/i", $field_desc['default'])) { - if ((preg_match("/null/i", $field_desc['default'])) || (preg_match("/CURRENT_TIMESTAMP/i", $field_desc['default']))) { - $sqlfields[$i] .= " default ".$field_desc['default']; + if (!is_null($field_desc['default']) && $field_desc['default'] !== '') { + if (in_array($field_desc['type'], array('tinyint', 'smallint', 'int', 'double'))) { + $sqlfields[$i] .= " DEFAULT ".((float) $field_desc['default']); + } elseif ($field_desc['default'] == 'null' || $field_desc['default'] == 'CURRENT_TIMESTAMP') { + $sqlfields[$i] .= " DEFAULT ".$this->sanitize($field_desc['default']); } else { - $sqlfields[$i] .= " default '".$this->escape($field_desc['default'])."'"; + $sqlfields[$i] .= " DEFAULT '".$this->escape($field_desc['default'])."'"; } } - if (preg_match("/^[^\s]/i", $field_desc['null'])) { - $sqlfields[$i] .= " ".$field_desc['null']; + if (!is_null($field_desc['null']) && $field_desc['null'] !== '') { + $sqlfields[$i] .= " ".$this->sanitize($field_desc['null'], 0, 0, 1); } - if (preg_match("/^[^\s]/i", $field_desc['extra'])) { - $sqlfields[$i] .= " ".$field_desc['extra']; + if (!is_null($field_desc['extra']) && $field_desc['extra'] !== '') { + $sqlfields[$i] .= " ".$this->sanitize($field_desc['extra']); } $i++; } if ($primary_key != "") { - $pk = "primary key(".$primary_key.")"; + $pk = "PRIMARY KEY(".$this->sanitize($primary_key).")"; } if (is_array($unique_keys)) { $i = 0; foreach ($unique_keys as $key => $value) { - $sqluq[$i] = "UNIQUE KEY '".$key."' ('".$this->escape($value)."')"; + $sqluq[$i] = "UNIQUE KEY '".$this->sanitize($key)."' ('".$this->escape($value)."')"; $i++; } } if (is_array($keys)) { $i = 0; foreach ($keys as $key => $value) { - $sqlk[$i] = "KEY ".$key." (".$value.")"; + $sqlk[$i] = "KEY ".$this->sanitize($key)." (".$value.")"; $i++; } } @@ -887,7 +898,8 @@ class DoliDBMysqli extends DoliDB if (is_array($keys)) { $sql .= ",".implode(',', $sqlk); } - $sql .= ") engine=".$type; + $sql .= ")"; + $sql .= " engine=".$this->sanitize($type); if (!$this->query($sql)) { return -1; diff --git a/htdocs/core/db/pgsql.class.php b/htdocs/core/db/pgsql.class.php index 250a7da0855..3cfe5671085 100644 --- a/htdocs/core/db/pgsql.class.php +++ b/htdocs/core/db/pgsql.class.php @@ -1068,51 +1068,63 @@ class DoliDBPgsql extends DoliDB public function DDLCreateTable($table, $fields, $primary_key, $type, $unique_keys = null, $fulltext_keys = null, $keys = null) { // phpcs:enable - // FIXME: $fulltext_keys parameter is unused + // @TODO: $fulltext_keys parameter is unused $sqlfields = array(); $sqlk = array(); $sqluq = array(); - // cles recherchees dans le tableau des descriptions (fields) : type,value,attribute,null,default,extra - // ex. : $fields['rowid'] = array('type'=>'int','value'=>'11','null'=>'not null','extra'=> 'auto_increment'); - $sql = "create table ".$table."("; + // Keys found into the array $fields: type,value,attribute,null,default,extra + // ex. : $fields['rowid'] = array( + // 'type'=>'int' or 'integer', + // 'value'=>'11', + // 'null'=>'not null', + // 'extra'=> 'auto_increment' + // ); + $sql = "CREATE TABLE ".$this->sanitize($table)."("; $i = 0; + $sqlfields = array(); foreach ($fields as $field_name => $field_desc) { - $sqlfields[$i] = $field_name." "; - $sqlfields[$i] .= $field_desc['type']; - if (preg_match("/^[^\s]/i", $field_desc['value'])) { - $sqlfields[$i] .= "(".$field_desc['value'].")"; - } elseif (preg_match("/^[^\s]/i", $field_desc['attribute'])) { - $sqlfields[$i] .= " ".$field_desc['attribute']; - } elseif (preg_match("/^[^\s]/i", $field_desc['default'])) { - if (preg_match("/null/i", $field_desc['default'])) { - $sqlfields[$i] .= " default ".$field_desc['default']; + $sqlfields[$i] = $this->sanitize($field_name)." "; + $sqlfields[$i] .= $this->sanitize($field_desc['type']); + if (!is_null($field_desc['value']) && $field_desc['value'] !== '') { + $sqlfields[$i] .= "(".$this->sanitize($field_desc['value']).")"; + } + if (!is_null($field_desc['attribute']) && $field_desc['attribute'] !== '') { + $sqlfields[$i] .= " ".$this->sanitize($field_desc['attribute']); + } + if (!is_null($field_desc['default']) && $field_desc['default'] !== '') { + if (in_array($field_desc['type'], array('tinyint', 'smallint', 'int', 'double'))) { + $sqlfields[$i] .= " DEFAULT ".((float) $field_desc['default']); + } elseif ($field_desc['default'] == 'null' || $field_desc['default'] == 'CURRENT_TIMESTAMP') { + $sqlfields[$i] .= " DEFAULT ".$this->sanitize($field_desc['default']); } else { - $sqlfields[$i] .= " default '".$this->escape($field_desc['default'])."'"; + $sqlfields[$i] .= " DEFAULT '".$this->escape($field_desc['default'])."'"; } - } elseif (preg_match("/^[^\s]/i", $field_desc['null'])) { - $sqlfields[$i] .= " ".$field_desc['null']; - } elseif (preg_match("/^[^\s]/i", $field_desc['extra'])) { - $sqlfields[$i] .= " ".$field_desc['extra']; + } + if (!is_null($field_desc['null']) && $field_desc['null'] !== '') { + $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']); } $i++; } if ($primary_key != "") { - $pk = "primary key(".$primary_key.")"; + $pk = "PRIMARY KEY(".$this->sanitize($primary_key).")"; } if (is_array($unique_keys)) { $i = 0; foreach ($unique_keys as $key => $value) { - $sqluq[$i] = "UNIQUE KEY '".$key."' ('".$this->escape($value)."')"; + $sqluq[$i] = "UNIQUE KEY '".$this->sanitize($key)."' ('".$this->escape($value)."')"; $i++; } } if (is_array($keys)) { $i = 0; foreach ($keys as $key => $value) { - $sqlk[$i] = "KEY ".$key." (".$value.")"; + $sqlk[$i] = "KEY ".$this->sanitize($key)." (".$value.")"; $i++; } } @@ -1120,15 +1132,15 @@ class DoliDBPgsql extends DoliDB if ($primary_key != "") { $sql .= ",".$pk; } - if (is_array($unique_keys)) { + if ($unique_keys != "") { $sql .= ",".implode(',', $sqluq); } if (is_array($keys)) { $sql .= ",".implode(',', $sqlk); } - $sql .= ") type=".$type; + $sql .= ")"; + //$sql .= " engine=".$this->sanitize($type); - dol_syslog($sql, LOG_DEBUG); if (!$this->query($sql)) { return -1; } else { diff --git a/htdocs/core/db/sqlite3.class.php b/htdocs/core/db/sqlite3.class.php index 060e7318b65..477d7d33c42 100644 --- a/htdocs/core/db/sqlite3.class.php +++ b/htdocs/core/db/sqlite3.class.php @@ -970,51 +970,63 @@ class DoliDBSqlite3 extends DoliDB public function DDLCreateTable($table, $fields, $primary_key, $type, $unique_keys = null, $fulltext_keys = null, $keys = null) { // phpcs:enable - // FIXME: $fulltext_keys parameter is unused + // @TODO: $fulltext_keys parameter is unused $sqlfields = array(); $sqlk = array(); $sqluq = array(); - // cles recherchees dans le tableau des descriptions (fields) : type,value,attribute,null,default,extra - // ex. : $fields['rowid'] = array('type'=>'int','value'=>'11','null'=>'not null','extra'=> 'auto_increment'); - $sql = "create table ".$table."("; + // Keys found into the array $fields: type,value,attribute,null,default,extra + // ex. : $fields['rowid'] = array( + // 'type'=>'int' or 'integer', + // 'value'=>'11', + // 'null'=>'not null', + // 'extra'=> 'auto_increment' + // ); + $sql = "CREATE TABLE ".$this->sanitize($table)."("; $i = 0; + $sqlfields = array(); foreach ($fields as $field_name => $field_desc) { - $sqlfields[$i] = $field_name." "; - $sqlfields[$i] .= $field_desc['type']; - if (preg_match("/^[^\s]/i", $field_desc['value'])) { - $sqlfields[$i] .= "(".$field_desc['value'].")"; - } elseif (preg_match("/^[^\s]/i", $field_desc['attribute'])) { - $sqlfields[$i] .= " ".$field_desc['attribute']; - } elseif (preg_match("/^[^\s]/i", $field_desc['default'])) { - if (preg_match("/null/i", $field_desc['default'])) { - $sqlfields[$i] .= " default ".$field_desc['default']; + $sqlfields[$i] = $this->sanitize($field_name)." "; + $sqlfields[$i] .= $this->sanitize($field_desc['type']); + if (!is_null($field_desc['value']) && $field_desc['value'] !== '') { + $sqlfields[$i] .= "(".$this->sanitize($field_desc['value']).")"; + } + if (!is_null($field_desc['attribute']) && $field_desc['attribute'] !== '') { + $sqlfields[$i] .= " ".$this->sanitize($field_desc['attribute']); + } + if (!is_null($field_desc['default']) && $field_desc['default'] !== '') { + if (in_array($field_desc['type'], array('tinyint', 'smallint', 'int', 'double'))) { + $sqlfields[$i] .= " DEFAULT ".((float) $field_desc['default']); + } elseif ($field_desc['default'] == 'null' || $field_desc['default'] == 'CURRENT_TIMESTAMP') { + $sqlfields[$i] .= " DEFAULT ".$this->sanitize($field_desc['default']); } else { - $sqlfields[$i] .= " default '".$this->escape($field_desc['default'])."'"; + $sqlfields[$i] .= " DEFAULT '".$this->escape($field_desc['default'])."'"; } - } elseif (preg_match("/^[^\s]/i", $field_desc['null'])) { - $sqlfields[$i] .= " ".$field_desc['null']; - } elseif (preg_match("/^[^\s]/i", $field_desc['extra'])) { - $sqlfields[$i] .= " ".$field_desc['extra']; + } + if (!is_null($field_desc['null']) && $field_desc['null'] !== '') { + $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']); } $i++; } if ($primary_key != "") { - $pk = "primary key(".$primary_key.")"; + $pk = "PRIMARY KEY(".$this->sanitize($primary_key).")"; } if (is_array($unique_keys)) { $i = 0; foreach ($unique_keys as $key => $value) { - $sqluq[$i] = "UNIQUE KEY '".$key."' ('".$this->escape($value)."')"; + $sqluq[$i] = "UNIQUE KEY '".$this->sanitize($key)."' ('".$this->escape($value)."')"; $i++; } } if (is_array($keys)) { $i = 0; foreach ($keys as $key => $value) { - $sqlk[$i] = "KEY ".$key." (".$value.")"; + $sqlk[$i] = "KEY ".$this->sanitize($key)." (".$value.")"; $i++; } } @@ -1022,19 +1034,20 @@ class DoliDBSqlite3 extends DoliDB if ($primary_key != "") { $sql .= ",".$pk; } - if (is_array($unique_keys)) { + if ($unique_keys != "") { $sql .= ",".implode(',', $sqluq); } if (is_array($keys)) { $sql .= ",".implode(',', $sqlk); } - $sql .= ") type=".$type; + $sql .= ")"; + //$sql .= " engine=".$this->sanitize($type); - dol_syslog($sql, LOG_DEBUG); - if (!$this -> query($sql)) { + if (!$this->query($sql)) { return -1; + } else { + return 1; } - return 1; } // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps diff --git a/htdocs/core/lib/modulebuilder.lib.php b/htdocs/core/lib/modulebuilder.lib.php index 95e4711b396..159c5712399 100644 --- a/htdocs/core/lib/modulebuilder.lib.php +++ b/htdocs/core/lib/modulebuilder.lib.php @@ -1288,12 +1288,12 @@ function createNewDictionnary($modulename, $file, $namedic, $dictionnaires = nul } $columns = array( - 'rowid' => array('type' => 'integer(11)'), - 'code' => array('type' => 'varchar(255) NOT NULL'), - 'label' => array('type' => 'varchar(255) NOT NULL'), - 'position' => array('type' => 'integer(11) NULL'), - 'use_default' => array('type' => 'varchar(255) DEFAULT 1'), - 'active' => array('type' => 'integer') + 'rowid' => array('type' => 'integer', 'value' => 11), + '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'), + 'use_default' => array('type' => 'varchar', 'value' => 11, 'default'=>'1'), + 'active' => array('type' => 'integer', 'value' => 3) ); @@ -1309,13 +1309,13 @@ function createNewDictionnary($modulename, $file, $namedic, $dictionnaires = nul } } // check if tablename exist in Database and create it if not - $query = "SHOW TABLES LIKE '" . MAIN_DB_PREFIX.strtolower($namedic) . "'"; + $query = "SHOW TABLES LIKE '" . $db->sanitize(MAIN_DB_PREFIX.strtolower($namedic)) . "'"; $checkTable = $db->query($query); if ($checkTable && $db->num_rows($checkTable) > 0) { setEventMessages($langs->trans("ErrorTableExist", $namedic), null, 'errors'); return; } else { - $_results = $db->DDLCreateTable(MAIN_DB_PREFIX.strtolower($namedic), $columns, $primaryKey, "InnoDB"); + $_results = $db->DDLCreateTable(MAIN_DB_PREFIX.strtolower($namedic), $columns, $primaryKey, ""); if ($_results < 0) { dol_print_error($db); $langs->load("errors"); From 171c32be342f08dd1c17a4997eb8b2f9123c424e Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Thu, 21 Mar 2024 12:21:38 +0100 Subject: [PATCH 10/11] Add DDLDropTable and DDLCreateTable into phpunit tests --- htdocs/core/db/mysqli.class.php | 2 +- test/phpunit/DoliDBTest.php | 36 +++++++++++++++++++++++++++++++++ 2 files changed, 37 insertions(+), 1 deletion(-) diff --git a/htdocs/core/db/mysqli.class.php b/htdocs/core/db/mysqli.class.php index 6f3feb04dcc..9c2948cb262 100644 --- a/htdocs/core/db/mysqli.class.php +++ b/htdocs/core/db/mysqli.class.php @@ -920,7 +920,7 @@ class DoliDBMysqli 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; diff --git a/test/phpunit/DoliDBTest.php b/test/phpunit/DoliDBTest.php index c2a0de05a20..34f70e459c9 100644 --- a/test/phpunit/DoliDBTest.php +++ b/test/phpunit/DoliDBTest.php @@ -48,6 +48,41 @@ $conf->global->MAIN_DISABLE_ALL_MAILS = 1; */ class DoliDBTest extends CommonClassTest { + /** + * testDDLUpdateField + * + * @return int + */ + public function testDDLCreateTable() + { + global $conf,$user,$langs,$db; + $conf = $this->savconf; + $user = $this->savuser; + $langs = $this->savlangs; + $db = $this->savdb; + + $namedic = MAIN_DB_PREFIX.'tmptesttabletoremove'; + + $res = $db->DDLDropTable($namedic); + + $columns = array( + 'rowid' => array('type' => 'integer', 'value' => 11), + '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'), + 'use_default' => array('type' => 'varchar', 'value' => 11, 'default'=>'1'), + 'active' => array('type' => 'integer', 'value' => 3) + ); + $primaryKey = 'rowid'; + + print __METHOD__.' db->type = '.$db->type."\n"; + + $res = $db->DDLCreateTable($namedic, $columns, $primaryKey, ""); + + $this->assertEquals(1, $res); + print __METHOD__." result=".$res."\n"; + } + /** * testDDLUpdateField * @@ -84,6 +119,7 @@ class DoliDBTest extends CommonClassTest $field_desc = array('type'=>'varchar', 'value'=>'16', 'null'=>'NOT NULL', 'default'=>'aaaabbbbccccdddd'); $result = $db->DDLUpdateField($db->prefix().'c_paper_format', 'code', $field_desc); + $this->assertEquals(1, $result); print __METHOD__." result=".$result."\n"; From aa77573cd9f6f4b16a39face533bdf78d03e0978 Mon Sep 17 00:00:00 2001 From: Laurent Destailleur Date: Thu, 21 Mar 2024 12:45:58 +0100 Subject: [PATCH 11/11] Sanitize DDL instructions --- htdocs/core/db/mysqli.class.php | 42 ++++++----- htdocs/core/db/pgsql.class.php | 104 +++++++++++++------------- htdocs/core/db/sqlite3.class.php | 22 +++--- htdocs/core/lib/modulebuilder.lib.php | 2 +- test/phpunit/DoliDBTest.php | 2 +- 5 files changed, 89 insertions(+), 83 deletions(-) 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'),