diff --git a/htdocs/admin/company.php b/htdocs/admin/company.php index 95333ba7c57..4cdafdc39e0 100644 --- a/htdocs/admin/company.php +++ b/htdocs/admin/company.php @@ -74,6 +74,8 @@ $quality = $tmparraysize['quality']; // Initialize a technical object to manage hooks of page. Note that conf->hooks_modules contains an array of hook context $hookmanager->initHooks(array('admincompany', 'globaladmin')); +$object = new Societe($db); + /* * Actions @@ -451,11 +453,11 @@ print ''; print ''; print ''; -print ''."\n"; +print ''."\n"; // Company name print ''."\n"; +print ''."\n"; // Main currency print ''."\n"; // Address print ''."\n"; +print ''."\n"; // Zip print ''."\n"; +print ''."\n"; print ''."\n"; +print ''."\n"; // State print ''."\n"; // Phone print ''; +print ''; print ''."\n"; // Phone mobile print ''; +print ''; print ''."\n"; // Fax print ''; +print ''; print ''."\n"; // Email print ''; +print ''; print ''."\n"; // Web print ''; +print ''; print ''."\n"; // Barcode @@ -527,7 +529,7 @@ if (isModEnabled('barcode')) { print ''; + print ''; print ''; } @@ -563,7 +565,7 @@ print ''; // Note print ''; +print ''; print ''; print '
'.$langs->trans("CompanyInfo").'
'.$langs->trans("CompanyInfo").'
'; -print '
'; @@ -472,14 +474,14 @@ print '
'; -print '
'; -print '
'; -print '
'; @@ -495,31 +497,31 @@ print '
'; print img_picto('', 'object_phoning', '', 0, 0, 0, '', 'pictofixedwidth'); -print '
'; print img_picto('', 'object_phoning_mobile', '', 0, 0, 0, '', 'pictofixedwidth'); -print '
'; print img_picto('', 'object_phoning_fax', '', 0, 0, 0, '', 'pictofixedwidth'); -print '
'; print img_picto('', 'object_email', '', 0, 0, 0, '', 'pictofixedwidth'); -print '
'; print img_picto('', 'globe', '', 0, 0, 0, '', 'pictofixedwidth'); -print '
'; print ''; print ''; - print '
'; -print '
'; @@ -576,23 +578,23 @@ print '

'; // IDs of the company (country-specific) print '
'; print ''; -print ''; +print ''; $langs->load("companies"); // Managing Director(s) print ''; +print ''; // GDPR contact print ''; +print ''; // Capital print ''; +print ''; // Juridical Status print ''; // Object of the company print ''; +print ''; print ''; // Tax ID Intra-community VAT number print ''; // ProfId1 if ($langs->transcountry("ProfId1", $mysoc->country_code) != '-') { print ''; +print $formother->select_month(getDolGlobalString('SOCIETE_FISCAL_MONTH_START'), 'SOCIETE_FISCAL_MONTH_START', 0, 1, 'maxwidth100').''; print "
'.$langs->trans("CompanyIds").'
'.$langs->trans("CompanyIds").'
'; -print '
'; print $form->textwithpicto($langs->trans("GDPRContact"), $langs->trans("GDPRContactDesc")); print ''; -print 'global->MAIN_INFO_GDPR : ''))).'">
'; -print '
'; @@ -605,19 +607,19 @@ print '
'; -print '
'; -print ''; +print ''; print '
'; if (!empty($mysoc->country_code)) { - print ''; + print ''; } else { print $countrynotdefined; } @@ -628,7 +630,7 @@ if ($langs->transcountry("ProfId1", $mysoc->country_code) != '-') { if ($langs->transcountry("ProfId2", $mysoc->country_code) != '-') { print '
'; if (!empty($mysoc->country_code)) { - print ''; + print ''; } else { print $countrynotdefined; } @@ -639,7 +641,7 @@ if ($langs->transcountry("ProfId2", $mysoc->country_code) != '-') { if ($langs->transcountry("ProfId3", $mysoc->country_code) != '-') { print '
'; if (!empty($mysoc->country_code)) { - print ''; + print ''; } else { print $countrynotdefined; } @@ -650,7 +652,7 @@ if ($langs->transcountry("ProfId3", $mysoc->country_code) != '-') { if ($langs->transcountry("ProfId4", $mysoc->country_code) != '-') { print '
'; if (!empty($mysoc->country_code)) { - print ''; + print ''; } else { print $countrynotdefined; } @@ -661,7 +663,7 @@ if ($langs->transcountry("ProfId4", $mysoc->country_code) != '-') { if ($langs->transcountry("ProfId5", $mysoc->country_code) != '-') { print '
'; if (!empty($mysoc->country_code)) { - print ''; + print ''; } else { print $countrynotdefined; } @@ -672,7 +674,7 @@ if ($langs->transcountry("ProfId5", $mysoc->country_code) != '-') { if ($langs->transcountry("ProfId6", $mysoc->country_code) != '-') { print '
'; if (!empty($mysoc->country_code)) { - print ''; + print ''; } else { print $countrynotdefined; } @@ -683,7 +685,7 @@ if ($langs->transcountry("ProfId6", $mysoc->country_code) != '-') { if ($langs->transcountry("ProfId7", $mysoc->country_code) != '-') { print '
'; if (!empty($mysoc->country_code)) { - print ''; + print ''; } else { print $countrynotdefined; } @@ -694,7 +696,7 @@ if ($langs->transcountry("ProfId7", $mysoc->country_code) != '-') { if ($langs->transcountry("ProfId8", $mysoc->country_code) != '-') { print '
'; if (!empty($mysoc->country_code)) { - print ''; + print ''; } else { print $countrynotdefined; } @@ -705,7 +707,7 @@ if ($langs->transcountry("ProfId8", $mysoc->country_code) != '-') { if ($langs->transcountry("ProfId9", $mysoc->country_code) != '-') { print '
'; if (!empty($mysoc->country_code)) { - print ''; + print ''; } else { print $countrynotdefined; } @@ -716,7 +718,7 @@ if ($langs->transcountry("ProfId9", $mysoc->country_code) != '-') { if ($langs->transcountry("ProfId10", $mysoc->country_code) != '-') { print '
'; if (!empty($mysoc->country_code)) { - print ''; + print ''; } else { print $countrynotdefined; } @@ -735,7 +737,7 @@ print ''.$langs->trans("FiscalYearInformation").'\n"; print '
'; -print $formother->select_month(getDolGlobalInt('SOCIETE_FISCAL_MONTH_START') ? $conf->global->SOCIETE_FISCAL_MONTH_START : '', 'SOCIETE_FISCAL_MONTH_START', 0, 1, 'maxwidth100').'
"; diff --git a/htdocs/compta/facture/class/api_invoices.class.php b/htdocs/compta/facture/class/api_invoices.class.php index cd48f2643eb..dc65c082759 100644 --- a/htdocs/compta/facture/class/api_invoices.class.php +++ b/htdocs/compta/facture/class/api_invoices.class.php @@ -1694,14 +1694,14 @@ class Invoices extends DolibarrApi $totalpaid = $this->invoice->getSommePaiement($is_multicurrency); $totalcreditnotes = $this->invoice->getSumCreditNotesUsed($is_multicurrency); $totaldeposits = $this->invoice->getSumDepositsUsed($is_multicurrency); - $remainstopay = $amount = price2num($total_ttc - $totalpaid - $totalcreditnotes - $totaldeposits, 'MT'); + $remainstopay = $amount = (float) price2num($total_ttc - $totalpaid - $totalcreditnotes - $totaldeposits, 'MT'); if (!$is_multicurrency && $amountarray["amount"] != 'remain') { - $amount = price2num($amountarray["amount"], 'MT'); + $amount = (float) price2num($amountarray["amount"], 'MT'); } if ($is_multicurrency && $amountarray["multicurrency_amount"] != 'remain') { - $amount = price2num($amountarray["multicurrency_amount"], 'MT'); + $amount = (float) price2num($amountarray["multicurrency_amount"], 'MT'); } if (abs($amount) > abs($remainstopay) && !$accepthigherpayment) { @@ -1710,7 +1710,7 @@ class Invoices extends DolibarrApi } if ($this->invoice->type == Facture::TYPE_CREDIT_NOTE) { - $amount = price2num(-1 * abs((float) $amount), 'MT'); + $amount = (float) price2num(-1 * abs((float) $amount), 'MT'); } if ($is_multicurrency) { diff --git a/htdocs/core/lib/functions.lib.php b/htdocs/core/lib/functions.lib.php index b3885f2e137..830c06f5f17 100644 --- a/htdocs/core/lib/functions.lib.php +++ b/htdocs/core/lib/functions.lib.php @@ -8530,14 +8530,21 @@ function dol_string_onlythesehtmlattributes($stringtoclean, $allowed_attributes { if (is_null($allowed_attributes)) { $allowed_attributes = array( - "allow", "allowfullscreen", "alt", "async", "class", "content", "contenteditable", "crossorigin", "data-html", "frameborder", "height", "href", "id", "name", "property", "rel", "src", "style", "target", "title", "type", "width", + "allow", "allowfullscreen", "alt", "async", "class", "contenteditable", "crossorigin", "data-html", "frameborder", "height", "href", "id", "name", "property", "rel", "src", "style", "target", "title", "type", "width", // HTML5 "header", "footer", "nav", "section", "menu", "menuitem" ); } + // Always add content and http-equiv for meta tags, required to force encoding and keep html content in utf8 by load/saveHTML functions. + if (!in_array("content", $allowed_attributes)) { + $allowed_attributes[] = "content"; + } + if (!in_array("http-equiv", $allowed_attributes)) { + $allowed_attributes[] = "http-equiv"; + } if (class_exists('DOMDocument') && !empty($stringtoclean)) { - $stringtoclean = ''.$stringtoclean.''; + $stringtoclean = ''.$stringtoclean.''; // Warning: loadHTML does not support HTML5 on old libxml versions. $dom = new DOMDocument('', 'UTF-8'); @@ -8588,12 +8595,15 @@ function dol_string_onlythesehtmlattributes($stringtoclean, $allowed_attributes } } + $dom->encoding = 'UTF-8'; + $return = $dom->saveHTML(); // This may add a LF at end of lines, so we will trim later //$return = 'aaaa

bb

ssdd

'."\n

aaa

aa

bb

"; $return = preg_replace('/^'.preg_quote('', '/').'/', '', $return); - $return = preg_replace('/^'.preg_quote('', '/').'/', '', $return); - $return = preg_replace('/'.preg_quote('', '/').'$/', '', $return); + $return = preg_replace('/^'.preg_quote('<', '/').'[^<>]*'.preg_quote('>', '/').'/', '', $return); + $return = preg_replace('/'.preg_quote('', '/').'$/', '', trim($return)); + return trim($return); } else { return $stringtoclean; @@ -8765,17 +8775,24 @@ function dol_htmlwithnojs($stringtoencode, $nouseofiframesandbox = 0, $check = ' // like 'abc' that wrongly ends up, without the trick, with '

abc

' if (dol_textishtml($out)) { - $out = '
'.$out.'
'; + $out = '
'.$out.'
'; } else { - $out = '
'.dol_nl2br($out).'
'; + $out = '
'.dol_nl2br($out).'
'; } $dom->loadHTML($out, LIBXML_HTML_NODEFDTD | LIBXML_ERR_NONE | LIBXML_HTML_NOIMPLIED | LIBXML_NONET | LIBXML_NOWARNING | LIBXML_NOERROR | LIBXML_NOXMLDECL); + + $dom->encoding = 'UTF-8'; + $out = trim($dom->saveHTML()); - // Remove the trick added to solve pb with text without parent tag - $out = preg_replace('/^<\?xml encoding="UTF-8">
/', '', $out); - $out = preg_replace('/<\/div>$/', '', $out); + // Remove the trick added to solve pb with text in utf8 and text without parent tag + $out = preg_replace('/^'.preg_quote('', '/').'/', '', $out); + $out = preg_replace('/^'.preg_quote('<', '/').'[^<>]+'.preg_quote('>
', '/').'/', '', $out); + $out = preg_replace('/'.preg_quote('
', '/').'$/', '', trim($out)); + // $out = preg_replace('/^<\?xml encoding="UTF-8">
/', '', $out); + // $out = preg_replace('/<\/div>$/', '', $out); + // var_dump('rrrrrrrrrrrrrrrrrrrrrrrrrrrrr'.$out); } catch (Exception $e) { // If error, invalid HTML string with no way to clean it //print $e->getMessage(); @@ -8890,7 +8907,7 @@ function dol_htmlwithnojs($stringtoencode, $nouseofiframesandbox = 0, $check = ' $out = preg_replace('/on(repeat|begin|finish|beforeinput)[a-z]*\s*=/i', '', $out); } while ($oldstringtoclean != $out); - // Check the limit of external links that are automatically executed in a Rich text content. We count: + // Check the limit of external links that are automatically executed in a Rich text content. We count: // ', we can only accept " diff --git a/htdocs/langs/en_US/admin.lang b/htdocs/langs/en_US/admin.lang index 52bcfd9120b..3aa55259806 100644 --- a/htdocs/langs/en_US/admin.lang +++ b/htdocs/langs/en_US/admin.lang @@ -2008,7 +2008,7 @@ ConfirmDeleteFiscalYear=Are you sure to delete this accounting period? ShowFiscalYear=Show accounting period ##### Assets ##### AssetNumberingModules=Assets numbering module -AlwaysEditable=Can be edited for all object status +AlwaysEditable=Editable for any status PermissionOnField=Permission on field MAIN_APPLICATION_TITLE=Force visible name of application (warning: setting your own name here may break autofill login feature when using DoliDroid mobile application) NbMajMin=Minimum number of uppercase characters diff --git a/test/phpunit/.gitignore b/test/phpunit/.gitignore new file mode 100644 index 00000000000..647a82afb84 --- /dev/null +++ b/test/phpunit/.gitignore @@ -0,0 +1 @@ +/DemoTest.php diff --git a/test/phpunit/SecurityTest.php b/test/phpunit/SecurityTest.php index 3fdef280fed..1d34886db18 100644 --- a/test/phpunit/SecurityTest.php +++ b/test/phpunit/SecurityTest.php @@ -387,7 +387,8 @@ class SecurityTest extends CommonClassTest { $stringtotest = 'eée'; $decodedstring = dol_string_onlythesehtmlattributes($stringtotest); - $this->assertEquals('eée', $decodedstring, 'Function did not sanitize correctly with test 1'); + //$this->assertEquals('eée', $decodedstring, 'Function did not sanitize correctly with test 1'); + $this->assertEquals('eée', $decodedstring, 'Function did not sanitize correctly with test 1'); $stringtotest = '
abc
'; $decodedstring = dol_string_onlythesehtmlattributes($stringtotest); @@ -1296,6 +1297,30 @@ class SecurityTest extends CommonClassTest { global $conf; + // Test on a string in hindi with MAIN_RESTRICTHTML_REMOVE_ALSO_BAD_ATTRIBUTES because + // in past this case was losing the UTF8. + $conf->global->MAIN_RESTRICTHTML_REMOVE_ALSO_BAD_ATTRIBUTES = 0; + + $result = dol_htmlwithnojs('String in Hindi लेखाकर्म', 0, 'restricthtml'); + print __METHOD__." result=".$result."\n"; + $this->assertEquals('String in Hindi लेखाकर्म', $result, 'Test js sanitizing a Hindi string is ko'); + + $conf->global->MAIN_RESTRICTHTML_REMOVE_ALSO_BAD_ATTRIBUTES = 1; + + $result = dol_htmlwithnojs('String in Hindi लेखाकर्म', 0, 'restricthtml'); + print __METHOD__." result=".$result."\n"; + $this->assertEquals('String in Hindi लेखाकर्म', $result, 'Test js sanitizing a Hindi string is ko'); + + $conf->global->MAIN_RESTRICTHTML_REMOVE_ALSO_BAD_ATTRIBUTES = 1; + $conf->global->MAIN_RESTRICTHTML_ONLY_VALID_HTML = 1; + $conf->global->MAIN_RESTRICTHTML_ONLY_VALID_HTML_TIDY = 1; + + $result = dol_htmlwithnojs('String in Hindi लेखाकर्म', 0, 'restricthtml'); + print __METHOD__." result=".$result."\n"; + $this->assertEquals('String in Hindi लेखाकर्म', $result, 'Test js sanitizing a Hindi string is ko'); + + + $conf->global->MAIN_RESTRICTHTML_REMOVE_ALSO_BAD_ATTRIBUTES = 0; // If we set this to 1, it will also convert emoticon in htmlentities, so tests must be modified.