diff --git a/htdocs/admin/modulehelp.php b/htdocs/admin/modulehelp.php index 13332b5c277..e18e65e47a0 100644 --- a/htdocs/admin/modulehelp.php +++ b/htdocs/admin/modulehelp.php @@ -384,15 +384,16 @@ if ($mode == 'feature') { $text .= '

'; $text .= '
'.$langs->trans("AddDataTables").': '; - $sqlfiles = dol_dir_list(dol_buildpath($moduledir.'/sql/'), 'files', 0, 'llx.*\.sql', array('\.key\.sql', '\.sql\.back')); + $listofsqlfiles1 = dol_dir_list(DOL_DOCUMENT_ROOT.'/install/mysql/tables/', 'files', 0, 'llx.*-'.$moduledir.'\.sql', array('\.key\.sql', '\.sql\.back')); + $listofsqlfiles2 = dol_dir_list(dol_buildpath($moduledir.'/sql/'), 'files', 0, 'llx.*\.sql', array('\.key\.sql', '\.sql\.back')); + $sqlfiles = array_merge($listofsqlfiles1, $listofsqlfiles2); + if (count($sqlfiles) > 0) { - $text .= $langs->trans("Yes").' ('; $i = 0; foreach ($sqlfiles as $val) { - $text .= ($i ? ', ' : '').preg_replace('/\.sql$/', '', preg_replace('/llx_/', '', $val['name'])); + $text .= ($i ? ', ' : '').preg_replace('/\-'.$moduledir.'$/', '', preg_replace('/\.sql$/', '', preg_replace('/llx_/', '', $val['name']))); $i++; } - $text .= ')'; } else { $text .= $langs->trans("No"); } @@ -415,7 +416,7 @@ if ($mode == 'feature') { $text .= '
'.$langs->trans("AddData").': '; $filedata = dol_buildpath($moduledir.'/sql/data.sql'); if (dol_is_file($filedata)) { - $text .= $langs->trans("Yes").' ('.$moduledir.'/sql/data.sql)'; + $text .= $langs->trans("Yes").' ('.$moduledir.'/sql/data.sql)'; } else { $text .= $langs->trans("No"); } diff --git a/htdocs/core/db/Database.interface.php b/htdocs/core/db/Database.interface.php index 1d24b058614..faff7ff5172 100644 --- a/htdocs/core/db/Database.interface.php +++ b/htdocs/core/db/Database.interface.php @@ -182,9 +182,18 @@ interface Database * * @param string $stringtoencode String to escape * @return string String escaped + * @deprecated */ public function escapeunderscore($stringtoencode); + /** + * Escape a string to insert data into a like + * + * @param string $stringtoencode String to escape + * @return string String escaped + */ + public function escapeforlike($stringtoencode); + /** * Sanitize a string for SQL forging * diff --git a/htdocs/core/db/mysqli.class.php b/htdocs/core/db/mysqli.class.php index 1fe4ce77414..9393f10489f 100644 --- a/htdocs/core/db/mysqli.class.php +++ b/htdocs/core/db/mysqli.class.php @@ -479,12 +479,24 @@ class DoliDBMysqli extends DoliDB * * @param string $stringtoencode String to escape * @return string String escaped + * @deprecated */ public function escapeunderscore($stringtoencode) { return str_replace('_', '\_', (string) $stringtoencode); } + /** + * Escape a string to insert data into a like + * + * @param string $stringtoencode String to escape + * @return string String escaped + */ + public function escapeforlike($stringtoencode) + { + return str_replace(array('_', '\\', '%'), array('\_', '\\\\', '\%'), (string) $stringtoencode); + } + /** * Return generic error code of last operation. * diff --git a/htdocs/core/db/pgsql.class.php b/htdocs/core/db/pgsql.class.php index d33affec476..0515a043fd1 100644 --- a/htdocs/core/db/pgsql.class.php +++ b/htdocs/core/db/pgsql.class.php @@ -726,10 +726,22 @@ class DoliDBPgsql extends DoliDB * * @param string $stringtoencode String to escape * @return string String escaped + * @deprecated */ public function escapeunderscore($stringtoencode) { - return str_replace('_', '\_', $stringtoencode); + return str_replace('_', '\_', (string) $stringtoencode); + } + + /** + * Escape a string to insert data into a like + * + * @param string $stringtoencode String to escape + * @return string String escaped + */ + public function escapeforlike($stringtoencode) + { + return str_replace(array('_', '\\', '%'), array('\_', '\\\\', '\%'), (string) $stringtoencode); } /** diff --git a/htdocs/core/db/sqlite3.class.php b/htdocs/core/db/sqlite3.class.php index 8d0141e8ca6..e31eeffe457 100644 --- a/htdocs/core/db/sqlite3.class.php +++ b/htdocs/core/db/sqlite3.class.php @@ -654,10 +654,22 @@ class DoliDBSqlite3 extends DoliDB * * @param string $stringtoencode String to escape * @return string String escaped + * @deprecated */ public function escapeunderscore($stringtoencode) { - return str_replace('_', '\_', $stringtoencode); + return str_replace('_', '\_', (string) $stringtoencode); + } + + /** + * Escape a string to insert data into a like + * + * @param string $stringtoencode String to escape + * @return string String escaped + */ + public function escapeforlike($stringtoencode) + { + return str_replace(array('_', '\\', '%'), array('\_', '\\\\', '\%'), (string) $stringtoencode); } /** diff --git a/htdocs/core/lib/website.lib.php b/htdocs/core/lib/website.lib.php index 18bd7226400..4b43230adda 100644 --- a/htdocs/core/lib/website.lib.php +++ b/htdocs/core/lib/website.lib.php @@ -996,11 +996,11 @@ function getPagesFromSearchCriterias($type, $algo, $searchstring, $max = 25, $so $sql .= " AND ("; $searchalgo = ''; if (preg_match('/meta/', $algo)) { - $searchalgo .= ($searchalgo ? ' OR ' : '')."wp.title LIKE '%".$db->escapeunderscore($db->escape($searchstring))."%' OR wp.description LIKE '%".$db->escapeunderscore($db->escape($searchstring))."%'"; - $searchalgo .= ($searchalgo ? ' OR ' : '')."wp.keywords LIKE '".$db->escapeunderscore($db->escape($searchstring)).",%' OR wp.keywords LIKE '% ".$db->escapeunderscore($db->escape($searchstring))."%'"; // TODO Use a better way to scan keywords + $searchalgo .= ($searchalgo ? ' OR ' : '')."wp.title LIKE '%".$db->escapeforlike($db->escape($searchstring))."%' OR wp.description LIKE '%".$db->escapeforlike($db->escape($searchstring))."%'"; + $searchalgo .= ($searchalgo ? ' OR ' : '')."wp.keywords LIKE '".$db->escapeforlike($db->escape($searchstring)).",%' OR wp.keywords LIKE '% ".$db->escapeforlike($db->escape($searchstring))."%'"; // TODO Use a better way to scan keywords } if (preg_match('/content/', $algo)) { - $searchalgo .= ($searchalgo ? ' OR ' : '')."wp.content LIKE '%".$db->escapeunderscore($db->escape($searchstring))."%'"; + $searchalgo .= ($searchalgo ? ' OR ' : '')."wp.content LIKE '%".$db->escapeforlike($db->escape($searchstring))."%'"; } $sql .= $searchalgo; if (is_array($otherfilters) && !empty($otherfilters['category'])) { diff --git a/htdocs/core/modules/import/import_csv.modules.php b/htdocs/core/modules/import/import_csv.modules.php index 426a582c3f4..9f5a31109a8 100644 --- a/htdocs/core/modules/import/import_csv.modules.php +++ b/htdocs/core/modules/import/import_csv.modules.php @@ -835,8 +835,8 @@ class ImportCsv extends ModeleImports $sqlSelect = "SELECT ".$fname." FROM ".$tablename; $data = array_combine($listfields, $listvalues); - $where = array(); - $filters = array(); + $where = array(); // filters to forge SQL request + $filters = array(); // filters to forge output error message foreach ($updatekeys as $key) { $col = $objimport->array_import_updatekeys[0][$key]; $key = preg_replace('/^.*\./i', '', $key); @@ -846,8 +846,12 @@ class ImportCsv extends ModeleImports $socialnetwork = $tmp[1]; $jsondata = $data[$key]; $json = json_decode($jsondata); - $where[] = $key." LIKE '%\"".$socialnetwork."\":\"".$this->db->escape($json->$socialnetwork)."\"%'"; - $filters[] = $col." LIKE '%\"".$socialnetwork."\":\"".$this->db->escape($json->$socialnetwork)."\"%'"; + $stringtosearch = json_encode($socialnetwork).':'.json_encode($json->$socialnetwork); + //var_dump($stringtosearch); + //var_dump($this->db->escape($stringtosearch)); // This provide a value for sql string (but not for a like) + $where[] = $key." LIKE '%".$this->db->escapeforlike($this->db->escape($stringtosearch))."%'"; + $filters[] = $col." LIKE '%".$this->db->escapeforlike($this->db->escape($stringtosearch))."%'"; + //var_dump($where[1]); // This provide a value for sql string inside a like } else { $where[] = $key.' = '.$data[$key]; $filters[] = $col.' = '.$data[$key]; diff --git a/htdocs/core/modules/import/import_xlsx.modules.php b/htdocs/core/modules/import/import_xlsx.modules.php index 6b2c02de197..3637ce105c1 100644 --- a/htdocs/core/modules/import/import_xlsx.modules.php +++ b/htdocs/core/modules/import/import_xlsx.modules.php @@ -892,8 +892,12 @@ class ImportXlsx extends ModeleImports $socialnetwork = $tmp[1]; $jsondata = $data[$key]; $json = json_decode($jsondata); - $where[] = $key." LIKE '%\"".$socialnetwork."\":\"".$this->db->escape($json->$socialnetwork)."\"%'"; - $filters[] = $col." LIKE '%\"".$socialnetwork."\":\"".$this->db->escape($json->$socialnetwork)."\"%'"; + $stringtosearch = json_encode($socialnetwork).':'.json_encode($json->$socialnetwork); + //var_dump($stringtosearch); + //var_dump($this->db->escape($stringtosearch)); // This provide a value for sql string (but not for a like) + $where[] = $key." LIKE '%".$this->db->escapeforlike($this->db->escape($stringtosearch))."%'"; + $filters[] = $col." LIKE '%".$this->db->escapeforlike($this->db->escape($stringtosearch))."%'"; + //var_dump($where[1]); // This provide a value for sql string inside a like } else { $where[] = $key.' = '.$data[$key]; $filters[] = $col.' = '.$data[$key]; diff --git a/htdocs/core/modules/modAccounting.class.php b/htdocs/core/modules/modAccounting.class.php index 5e30978693e..737d2831db6 100644 --- a/htdocs/core/modules/modAccounting.class.php +++ b/htdocs/core/modules/modAccounting.class.php @@ -272,6 +272,24 @@ class modAccounting extends DolibarrModules //-------- $r = 0; + // Chart of accounts + $r++; + $this->import_code[$r] = $this->rights_class.'_'.$r; + $this->import_label[$r] = "Chartofaccounts"; // Translation key + $this->import_icon[$r] = $this->picto; + $this->import_entities_array[$r] = array(); // We define here only fields that use another icon that the one defined into import_icon + $this->import_tables_array[$r] = array('aa'=>MAIN_DB_PREFIX.'accounting_account'); + $this->import_tables_creator_array[$r] = array('aa'=>'fk_user_author'); // Fields to store import user id + $this->import_fields_array[$r] = array('aa.fk_pcg_version'=>"Chartofaccounts*", 'aa.account_number'=>"AccountAccounting*", 'aa.label'=>"Label*", 'aa.account_parent'=>"Accountparent", "aa.fk_accounting_category"=>"AccountingCategory", "aa.pcg_type"=>"Pcgtype*", 'aa.active'=>'Status*', 'aa.datec'=>"DateCreation"); + $this->import_regex_array[$r] = array('aa.fk_pcg_version'=>'pcg_version@'.MAIN_DB_PREFIX.'accounting_system', 'aa.account_number'=>'^.{1,32}$', 'aa.label'=>'^.{1,255}$', 'aa.account_parent'=>'^.{0,32}$', 'aa.fk_accounting_category'=>'rowid@'.MAIN_DB_PREFIX.'c_accounting_category', 'aa.pcg_type'=>'^.{1,20}$', 'aa.active'=>'^0|1$', 'aa.datec'=>'^\d{4}-\d{2}-\d{2}$'); + $this->import_convertvalue_array[$r] = array( + 'aa.account_number'=>array('rule'=>'accountingaccount'), + 'aa.account_parent'=>array('rule'=>'fetchidfromref', 'classfile'=>'/accountancy/class/accountingaccount.class.php', 'class'=>'AccountingAccount', 'method'=>'fetch', 'element'=>'AccountingAccount'), + 'aa.fk_accounting_category'=>array('rule'=>'fetchidfromcodeorlabel', 'classfile'=>'/accountancy/class/accountancycategory.class.php', 'class'=>'AccountancyCategory', 'method'=>'fetch', 'dict'=>'DictionaryAccountancyCategory'), + ); + $this->import_examplevalues_array[$r] = array('aa.fk_pcg_version'=>"PCG99-ABREGE", 'aa.account_number'=>"707", 'aa.label'=>"Product sales", 'aa.account_parent'=>"ref:7 or id:1407", "aa.fk_accounting_category"=>"", "aa.pcg_type"=>"PROD", 'aa.active'=>'1', 'aa.datec'=>"2017-04-28"); + $this->import_updatekeys_array[$r] = array('aa.fk_pcg_version'=>'Chartofaccounts', 'aa.account_number'=>'AccountAccounting'); + // General ledger $r++; $this->import_code[$r] = $this->rights_class.'_'.$r; @@ -393,23 +411,5 @@ class modAccounting extends DolibarrModules 'b.multicurrency_amount'=>"90 (Necessary if devise is different than EUR)", 'b.multicurrency_code'=>"US (Necessary if devise is different than EUR)", ); - - // Chart of accounts - $r++; - $this->import_code[$r] = $this->rights_class.'_'.$r; - $this->import_label[$r] = "Chartofaccounts"; // Translation key - $this->import_icon[$r] = $this->picto; - $this->import_entities_array[$r] = array(); // We define here only fields that use another icon that the one defined into import_icon - $this->import_tables_array[$r] = array('aa'=>MAIN_DB_PREFIX.'accounting_account'); - $this->import_tables_creator_array[$r] = array('aa'=>'fk_user_author'); // Fields to store import user id - $this->import_fields_array[$r] = array('aa.fk_pcg_version'=>"Chartofaccounts*", 'aa.account_number'=>"AccountAccounting*", 'aa.label'=>"Label*", 'aa.account_parent'=>"Accountparent", "aa.fk_accounting_category"=>"AccountingCategory", "aa.pcg_type"=>"Pcgtype*", 'aa.active'=>'Status*', 'aa.datec'=>"DateCreation"); - $this->import_regex_array[$r] = array('aa.fk_pcg_version'=>'pcg_version@'.MAIN_DB_PREFIX.'accounting_system', 'aa.account_number'=>'^.{1,32}$', 'aa.label'=>'^.{1,255}$', 'aa.account_parent'=>'^.{0,32}$', 'aa.fk_accounting_category'=>'rowid@'.MAIN_DB_PREFIX.'c_accounting_category', 'aa.pcg_type'=>'^.{1,20}$', 'aa.active'=>'^0|1$', 'aa.datec'=>'^\d{4}-\d{2}-\d{2}$'); - $this->import_convertvalue_array[$r] = array( - 'aa.account_number'=>array('rule'=>'accountingaccount'), - 'aa.account_parent'=>array('rule'=>'fetchidfromref', 'classfile'=>'/accountancy/class/accountingaccount.class.php', 'class'=>'AccountingAccount', 'method'=>'fetch', 'element'=>'AccountingAccount'), - 'aa.fk_accounting_category'=>array('rule'=>'fetchidfromcodeorlabel', 'classfile'=>'/accountancy/class/accountancycategory.class.php', 'class'=>'AccountancyCategory', 'method'=>'fetch', 'dict'=>'DictionaryAccountancyCategory'), - ); - $this->import_examplevalues_array[$r] = array('aa.fk_pcg_version'=>"PCG99-ABREGE", 'aa.account_number'=>"707", 'aa.label'=>"Product sales", 'aa.account_parent'=>"ref:7 or id:1407", "aa.fk_accounting_category"=>"", "aa.pcg_type"=>"PROD", 'aa.active'=>'1', 'aa.datec'=>"2017-04-28"); - $this->import_updatekeys_array[$r] = array('aa.fk_pcg_version'=>'Chartofaccounts', 'aa.account_number'=>'AccountAccounting'); } } diff --git a/htdocs/core/modules/modSociete.class.php b/htdocs/core/modules/modSociete.class.php index 5f898584ba4..5bc5c7da6cf 100644 --- a/htdocs/core/modules/modSociete.class.php +++ b/htdocs/core/modules/modSociete.class.php @@ -747,7 +747,7 @@ class modSociete extends DolibarrModules 's.fk_departement' => "StateCode", 's.fk_pays' => "CountryCode", 's.birthday' => "DateOfBirth", - 's.poste' => "Role", + 's.poste' => "PostOrFunction", 's.phone' => "Phone", 's.phone_perso' => "PhonePerso", 's.phone_mobile' => "PhoneMobile", diff --git a/htdocs/debugbar/class/TraceableDB.php b/htdocs/debugbar/class/TraceableDB.php index 082e45e4f43..785af37fc94 100644 --- a/htdocs/debugbar/class/TraceableDB.php +++ b/htdocs/debugbar/class/TraceableDB.php @@ -255,12 +255,24 @@ class TraceableDB extends DoliDB * * @param string $stringtoencode String to escape * @return string String escaped + * @deprecated */ public function escapeunderscore($stringtoencode) { return $this->db->escapeunderscore($stringtoencode); } + /** + * Escape a string to insert data into a like + * + * @param string $stringtoencode String to escape + * @return string String escaped + */ + public function escapeforlike($stringtoencode) + { + return str_replace(array('_', '\\', '%'), array('\_', '\\\\', '\%'), (string) $stringtoencode); + } + // phpcs:disable PEAR.NamingConventions.ValidFunctionName.ScopeNotCamelCaps /** * Get last ID after an insert INSERT diff --git a/htdocs/imports/import.php b/htdocs/imports/import.php index 2c85007c086..ab5223697e6 100644 --- a/htdocs/imports/import.php +++ b/htdocs/imports/import.php @@ -235,6 +235,7 @@ if ($action == 'add_import_model') { $result = $objimport->create($user); if ($result >= 0) { setEventMessages($langs->trans("ImportModelSaved", $objimport->model_name), null, 'mesgs'); + $import_name = ''; } else { $langs->load("errors"); if ($objimport->errno == 'DB_ERROR_RECORD_ALREADY_EXISTS') { @@ -1286,7 +1287,7 @@ if ($step == 4 && $datatoimport) { print ''; // Lines for remark - print ''.$langs->trans("Remark").''; + print ''.$langs->trans("Note").''; print '
'; print ''; @@ -1470,8 +1471,8 @@ if ($step == 4 && $datatoimport) { print ''; $nameofimportprofile = str_replace(' ', '-', $langs->trans("ImportProfile").' '.$titleofmodule.' '.dol_print_date(dol_now('gmt'), 'dayxcard')); - if (is_object($objimport) && !empty($objimport->model_name)) { - $nameofimportprofile = $objimport->model_name; + if (GETPOST('import_name')) { // If we have submited a form, we take value used fot the update try + $nameofimportprofile = $import_name; } print ''; @@ -1966,9 +1967,9 @@ if ($step == 5 && $datatoimport) { print '
'; print ''.$langs->trans("NowClickToRunTheImport", $langs->transnoentitiesnoconv("RunImportFile")).'
'; - if (empty($nboferrors)) { + /*if (empty($nboferrors)) { print $langs->trans("DataLoadedWithId", $importid).'
'; - } + }*/ print '
'; print '
'; diff --git a/htdocs/recruitment/recruitmentcandidature_card.php b/htdocs/recruitment/recruitmentcandidature_card.php index ca7e3c20e2c..33bf5b677af 100644 --- a/htdocs/recruitment/recruitmentcandidature_card.php +++ b/htdocs/recruitment/recruitmentcandidature_card.php @@ -559,7 +559,7 @@ if ($object->id > 0 && (empty($action) || ($action != 'edit' && $action != 'crea // Contract refused / accepted if ($object->status == $object::STATUS_CONTRACT_PROPOSED) { if ($permissiontoadd) { - print ''.$langs->trans("Accept").' / '.$langs->trans("Decline").''; + print ''.$langs->trans("Accept").' / '.$langs->trans("Decline").''; } } diff --git a/htdocs/recruitment/recruitmentjobposition_card.php b/htdocs/recruitment/recruitmentjobposition_card.php index bdae11bdc60..606786a4960 100644 --- a/htdocs/recruitment/recruitmentjobposition_card.php +++ b/htdocs/recruitment/recruitmentjobposition_card.php @@ -426,7 +426,7 @@ if ($object->id > 0 && (empty($action) || ($action != 'edit' && $action != 'crea // Close as recruited/canceled if ($object->status == $object::STATUS_VALIDATED) { if ($usercanclose) { - print 'global->MAIN_JUMP_TAG) ? '' : '#close').'"'; + print 'global->MAIN_JUMP_TAG) ? '' : '#close').'"'; print '>'.$langs->trans('Close').''; } else { print ''.$langs->trans('Close').''; diff --git a/htdocs/takepos/index.php b/htdocs/takepos/index.php index 5e1bd1350fb..2e4edc99da2 100644 --- a/htdocs/takepos/index.php +++ b/htdocs/takepos/index.php @@ -684,8 +684,8 @@ function Search2(keyCodeForEnter, moreorless) { console.log("There is only 1 answer with barcode matching the search, so we change the thirdparty "+data[0]['rowid']); ChangeThirdparty(data[0]['rowid']); } - else if ('product' == data[0]['object']) { - console.log("There is only 1 answer matching the search, so we add the product in basket, qty="+data[0]['qty']); + else if ($('#search').val() == data[0]['barcode'] && 'product' == data[0]['object']) { + console.log("There is only 1 answer and we found search on a barcode, so we add the product in basket, qty="+data[0]['qty']); ClickProduct(0, data[0]['qty']); } }