diff --git a/ChangeLog b/ChangeLog index 0fe697ccb6c..43caeb47679 100644 --- a/ChangeLog +++ b/ChangeLog @@ -243,6 +243,8 @@ Following changes may create regressions for some external modules, but were nec * Rename the substitution for "project label" instead of "project title" in substitution variables * You must use "$objectoffield" to manipulate the current object inside the formulare of computed custom extrafields instead of $obj/$object. * Making a global search is sending the parameter using always the name search_all (instead of sometimes sall and search_all) +* The property $url_last_version must be public if defined into module descriptor files; + diff --git a/build/generate_filelist_xml.php b/build/generate_filelist_xml.php index b122f9b0305..45d649d90d9 100755 --- a/build/generate_filelist_xml.php +++ b/build/generate_filelist_xml.php @@ -46,6 +46,7 @@ require_once DOL_DOCUMENT_ROOT."/core/lib/files.lib.php"; $includecustom=0; $includeconstants=array(); +$buildzip=0; if (empty($argv[1])) { print "Usage: ".$script_file." release=autostable|auto[-mybuild]|x.y.z[-mybuild] [includecustom=1] [includeconstant=CC:MY_CONF_NAME:value] [buildzip=1]\n"; @@ -69,6 +70,9 @@ while ($i < $argc) { if (!empty($result["includeconstant"])) { $includeconstants[$i] = $result["includeconstant"]; } + if (!empty($result["buildzip"])) { + $buildzip=1; + } if (preg_match('/includeconstant=/', strval($argv[$i]))) { $tmp=explode(':', $result['includeconstant'], 3); // $includeconstant has been set with previous parse_str() if (count($tmp) != 3) { diff --git a/htdocs/admin/modules.php b/htdocs/admin/modules.php index 9dc1b6e0811..eae1174e965 100644 --- a/htdocs/admin/modules.php +++ b/htdocs/admin/modules.php @@ -205,6 +205,7 @@ if ($action == 'install') { dol_syslog("Uncompress of module file is a success."); + // We check if this is a metapackage $modulenamearrays = array(); if (dol_is_file($modulenamedir.'/metapackage.conf')) { // This is a meta package @@ -214,6 +215,7 @@ if ($action == 'install') { $modulenamearrays[$modulename] = $modulename; //var_dump($modulenamearrays);exit; + // Lop on each packacge of the metapackage foreach ($modulenamearrays as $modulenameval) { if (strpos($modulenameval, '#') === 0) { continue; // Discard comments @@ -227,13 +229,14 @@ if ($action == 'install') { // Now we install the module if (!$error) { - @dol_delete_dir_recursive($dirins.'/'.$modulenameval); // delete the zip file - dol_syslog("We copy now directory ".$conf->admin->dir_temp.'/'.$tmpdir.'/htdocs/'.$modulenameval." into target dir ".$dirins.'/'.$modulenameval); - $result = dolCopyDir($modulenamedir, $dirins.'/'.$modulenameval, '0444', 1); + @dol_delete_dir_recursive($dirins.'/'.$modulenameval); // delete the target directory + $submodulenamedir = $conf->admin->dir_temp.'/'.$tmpdir.'/htdocs/'.$modulenameval; + dol_syslog("We copy now directory ".$submodulenamedir." into target dir ".$dirins.'/'.$modulenameval); + $result = dolCopyDir($submodulenamedir, $dirins.'/'.$modulenameval, '0444', 1); if ($result <= 0) { - dol_syslog('Failed to call dolCopyDir result='.$result." with param ".$modulenamedir." and ".$dirins.'/'.$modulenameval, LOG_WARNING); + dol_syslog('Failed to call dolCopyDir result='.$result." with param ".$submodulenamedir." and ".$dirins.'/'.$modulenameval, LOG_WARNING); $langs->load("errors"); - setEventMessages($langs->trans("ErrorFailToCopyDir", $modulenamedir, $dirins.'/'.$modulenameval), null, 'errors'); + setEventMessages($langs->trans("ErrorFailToCopyDir", $submodulenamedir, $dirins.'/'.$modulenameval), null, 'errors'); $error++; } } diff --git a/htdocs/admin/system/security.php b/htdocs/admin/system/security.php index c47cb8b9379..10c3eecca1d 100644 --- a/htdocs/admin/system/security.php +++ b/htdocs/admin/system/security.php @@ -580,15 +580,23 @@ print '
'; print 'MAIN_DOCUMENT_IS_OUTSIDE_WEBROOT_SO_NOEXE_NOT_REQUIRED = '.getDolGlobalString('MAIN_DOCUMENT_IS_OUTSIDE_WEBROOT_SO_NOEXE_NOT_REQUIRED', ''.$langs->trans("Undefined").'   ('.$langs->trans("Recommended").': '.$langs->trans("Undefined").' '.$langs->trans("or").' 0)')."
"; print '
'; -print 'MAIN_SECURITY_FORCECSP = '.getDolGlobalString('MAIN_SECURITY_FORCECSP', ''.$langs->trans("Undefined").'').'   ('.$langs->trans("Example").": \"frame-ancestors 'self'; default-src *; img-src * data:; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline';\")
"; +$examplecsprule = "frame-ancestors 'self'; img-src * data:; default-src 'self' 'unsafe-inline' 'unsafe-eval' *.paypal.com *.stripe.com *.google.com *.googlapis.com *.google-analytics.com *.googletagmanager.com;"; +print 'MAIN_SECURITY_FORCECSPRO = '.getDolGlobalString('MAIN_SECURITY_FORCECSP', ''.$langs->trans("Undefined").'').'   ('.$langs->trans("Example").': "'.$examplecsprule.'")
'; +print '
'; + +$examplecsprule = "frame-ancestors 'self'; img-src * data:; default-src 'self' 'unsafe-inline' 'unsafe-eval' *.paypal.com *.stripe.com *.google.com *.googlapis.com *.google-analytics.com *.googletagmanager.com;"; +print 'MAIN_SECURITY_FORCECSP = '.getDolGlobalString('MAIN_SECURITY_FORCERP', ''.$langs->trans("Undefined").'').'   ('.$langs->trans("Example").': "'.$examplecsprule.'")
'; print '
'; print 'MAIN_SECURITY_FORCERP = '.getDolGlobalString('MAIN_SECURITY_FORCERP', ''.$langs->trans("Undefined").'').'   ('.$langs->trans("Recommended").': '.$langs->trans("Undefined").' '.$langs->trans("or")." \"same-origin\" so browser doesn't send any referrer when going into another web site domain)
"; print '
'; -print 'WEBSITE_MAIN_SECURITY_FORCECSP = '.getDolGlobalString('WEBSITE_MAIN_SECURITY_FORCECSP', ''.$langs->trans("Undefined").''); -print '   ('.$langs->trans("Example").": \"frame-ancestors 'self'; default-src 'self' 'unsafe-inline'; style-src https://cdnjs.cloudflare.com https://fonts.googleapis.com 'unsafe-inline'; script-src https://cdn.transifex.com https://www.googletagmanager.com 'unsafe-inline'; object-src https://youtube.com; frame-src https://youtube.com; img-src * data:;\")
"; +print 'WEBSITE_MAIN_SECURITY_FORCECSPRO = '.getDolGlobalString('WEBSITE_MAIN_SECURITY_FORCECSPRO', ''.$langs->trans("Undefined").''); +print '   ('.$langs->trans("Example").": \"frame-ancestors 'self'; default-src 'self' 'unsafe-inline'; style-src https://cdnjs.cloudflare.com *.googleapis.com; script-src *.transifex.com *.google-analytics.com *.googletagmanager.com; object-src https://youtube.com; frame-src https://youtube.com; img-src * data:;\")
"; +print '
'; +print 'WEBSITE_MAIN_SECURITY_FORCECSP = '.getDolGlobalString('WEBSITE_MAIN_SECURITY_FORCECSP', ''.$langs->trans("Undefined").''); +print '   ('.$langs->trans("Example").": \"frame-ancestors 'self'; default-src 'self' 'unsafe-inline'; style-src https://cdnjs.cloudflare.com *.googleapis.com; script-src *.transifex.com *.google-analytics.com *.googletagmanager.com; object-src https://youtube.com; frame-src https://youtube.com; img-src * data:;\")
"; print '
'; print 'WEBSITE_MAIN_SECURITY_FORCERP = '.getDolGlobalString('WEBSITE_MAIN_SECURITY_FORCERP', ''.$langs->trans("Undefined").'').'   ('.$langs->trans("Recommended").': '.$langs->trans("Undefined").' '.$langs->trans("or")." \"strict-origin-when-cross-origin\")
"; diff --git a/htdocs/core/lib/functions.lib.php b/htdocs/core/lib/functions.lib.php index 4fa2b7a9124..23d593cba8f 100644 --- a/htdocs/core/lib/functions.lib.php +++ b/htdocs/core/lib/functions.lib.php @@ -9091,11 +9091,9 @@ function dol_eval($s, $returnvalue = 0, $hideerrors = 1, $onlysimplestring = '1' } } } catch (Error $e) { - $error = 'Caught error : '; - $error .= $e->getMessage() . ', '; - $error .= 'Trace : '; - $error .= json_encode($e->getTrace()); - error_log($error, 1); + $error = 'dol_eval try/catch error : '; + $error .= $e->getMessage(); + dol_syslog($error); } } diff --git a/htdocs/core/website.inc.php b/htdocs/core/website.inc.php index 82fcabd557b..b934f333b1a 100644 --- a/htdocs/core/website.inc.php +++ b/htdocs/core/website.inc.php @@ -107,20 +107,58 @@ if (!defined('USEDOLIBARRSERVER') && !defined('USEDOLIBARREDITOR')) { // X-XSS-Protection //header("X-XSS-Protection: 1"); // XSS filtering protection of some browsers (note: use of Content-Security-Policy is more efficient). Disabled as deprecated. - // Content-Security-Policy - if (!defined('WEBSITE_MAIN_SECURITY_FORCECSP')) { - // The constant WEBSITE_MAIN_SECURITY_FORCECSP should never be defined by page, but the variable used just after may be - + // Content-Security-Policy-Report-Only + if (!defined('WEBSITE_MAIN_SECURITY_FORCECSPRO')) { // A default security policy that keep usage of js external component like ckeditor, stripe, google, working - // $contentsecuritypolicy = "font-src *; img-src *; style-src * 'unsafe-inline' 'unsafe-eval'; default-src 'self' *.stripe.com 'unsafe-inline' 'unsafe-eval'; script-src 'self' *.stripe.com 'unsafe-inline' 'unsafe-eval'; frame-ancestors 'self'; frame-src 'self' *.stripe.com; connect-src 'self';"; - $contentsecuritypolicy = getDolGlobalString('WEBSITE_MAIN_SECURITY_FORCECSP'); + // For example: to restrict to only local resources, except for css (cloudflare+google), and js (transifex + google tags) and object/iframe (youtube) + // default-src 'self'; style-src: https://cdnjs.cloudflare.com https://fonts.googleapis.com; script-src: https://cdn.transifex.com https://www.googletagmanager.com; object-src https://youtube.com; frame-src https://youtube.com; img-src: *; + // For example, to restrict everything to itself except img that can be on other servers: + // default-src 'self'; img-src *; + // Pre-existing site that uses too much js code to fix but wants to ensure resources are loaded only over https and disable plugins: + // default-src https: 'unsafe-inline' 'unsafe-eval'; object-src 'none' + // + // $contentsecuritypolicy = "frame-ancestors 'self'; img-src * data:; default-src 'self' 'unsafe-inline' 'unsafe-eval' *.paypal.com *.stripe.com *.google.com *.googlapis.com *.google-analytics.com *.googletagmanager.com;"; + // $contentsecuritypolicy = "frame-ancestors 'self'; img-src * data:; default-src *; script-src 'self' 'unsafe-inline' *.paypal.com *.stripe.com *.google.com *.googlapis.com *.google-analytics.com *.googletagmanager.com; style-src 'self' 'unsafe-inline'; connect-src 'self';"; + $contentsecuritypolicy = getDolGlobalString('WEBSITE_MAIN_SECURITY_FORCECSPRO'); if (!is_object($hookmanager)) { $hookmanager = new HookManager($db); } $hookmanager->initHooks(array("main")); - $parameters = array('contentsecuritypolicy'=>$contentsecuritypolicy); + $parameters = array('contentsecuritypolicy'=>$contentsecuritypolicy, 'mode'=>'reportonly'); + $result = $hookmanager->executeHooks('setContentSecurityPolicy', $parameters); // Note that $action and $object may have been modified by some hooks + if ($result > 0) { + $contentsecuritypolicy = $hookmanager->resPrint; // Replace CSP + } else { + $contentsecuritypolicy .= $hookmanager->resPrint; // Concat CSP + } + + if (!empty($contentsecuritypolicy)) { + header("Content-Security-Policy-Report-Only: ".$contentsecuritypolicy); + } + } + + // Content-Security-Policy + if (!defined('WEBSITE_MAIN_SECURITY_FORCECSP')) { + // A default security policy that keep usage of js external component like ckeditor, stripe, google, working + // For example: to restrict to only local resources, except for css (cloudflare+google), and js (transifex + google tags) and object/iframe (youtube) + // default-src 'self'; style-src: https://cdnjs.cloudflare.com https://fonts.googleapis.com; script-src: https://cdn.transifex.com https://www.googletagmanager.com; object-src https://youtube.com; frame-src https://youtube.com; img-src: *; + // For example, to restrict everything to itself except img that can be on other servers: + // default-src 'self'; img-src *; + // Pre-existing site that uses too much js code to fix but wants to ensure resources are loaded only over https and disable plugins: + // default-src https: 'unsafe-inline' 'unsafe-eval'; object-src 'none' + // + // $contentsecuritypolicy = "frame-ancestors 'self'; img-src * data:; default-src 'self' 'unsafe-inline' 'unsafe-eval' *.paypal.com *.stripe.com *.google.com *.googlapis.com *.google-analytics.com *.googletagmanager.com;"; + // $contentsecuritypolicy = "frame-ancestors 'self'; img-src * data:; default-src *; script-src 'self' 'unsafe-inline' *.paypal.com *.stripe.com *.google.com *.googlapis.com *.google-analytics.com *.googletagmanager.com; style-src 'self' 'unsafe-inline'; connect-src 'self';"; + $contentsecuritypolicy = getDolGlobalString('WEBSITE_MAIN_SECURITY_FORCECSP'); + + if (!is_object($hookmanager)) { + $hookmanager = new HookManager($db); + } + $hookmanager->initHooks(array("main")); + + $parameters = array('contentsecuritypolicy'=>$contentsecuritypolicy, 'mode'=>'active'); $result = $hookmanager->executeHooks('setContentSecurityPolicy', $parameters); // Note that $action and $object may have been modified by some hooks if ($result > 0) { $contentsecuritypolicy = $hookmanager->resPrint; // Replace CSP @@ -129,12 +167,6 @@ if (!defined('USEDOLIBARRSERVER') && !defined('USEDOLIBARREDITOR')) { } if (!empty($contentsecuritypolicy)) { - // For example: to restrict to only local resources, except for css (cloudflare+google), and js (transifex + google tags) and object/iframe (youtube) - // default-src 'self'; style-src: https://cdnjs.cloudflare.com https://fonts.googleapis.com; script-src: https://cdn.transifex.com https://www.googletagmanager.com; object-src https://youtube.com; frame-src https://youtube.com; img-src: *; - // For example, to restrict everything to itself except img that can be on other servers: - // default-src 'self'; img-src *; - // Pre-existing site that uses too much js code to fix but wants to ensure resources are loaded only over https and disable plugins: - // default-src https: 'unsafe-inline' 'unsafe-eval'; object-src 'none' header("Content-Security-Policy: ".$contentsecuritypolicy); } } diff --git a/htdocs/main.inc.php b/htdocs/main.inc.php index deba6883277..b287a595e71 100644 --- a/htdocs/main.inc.php +++ b/htdocs/main.inc.php @@ -1492,13 +1492,21 @@ function top_httphead($contenttype = 'text/html', $forcenocache = 0) // X-XSS-Protection //header("X-XSS-Protection: 1"); // XSS filtering protection of some browsers (note: use of Content-Security-Policy is more efficient). Disabled as deprecated. - // Content-Security-Policy - if (!defined('MAIN_SECURITY_FORCECSP')) { + // Content-Security-Policy-Report-Only + if (!defined('MAIN_SECURITY_FORCECSPRO')) { // If CSP not forced from the page // A default security policy that keep usage of js external component like ckeditor, stripe, google, working - // $contentsecuritypolicy = "frame-ancestors 'self'; font-src *; img-src *; style-src * 'unsafe-inline' 'unsafe-eval'; default-src 'self' *.stripe.com 'unsafe-inline' 'unsafe-eval'; script-src 'self' *.stripe.com 'unsafe-inline' 'unsafe-eval'; frame-src 'self' *.stripe.com; connect-src 'self';"; - $contentsecuritypolicy = getDolGlobalString('MAIN_SECURITY_FORCECSP'); + // For example: to restrict to only local resources, except for css (cloudflare+google), and js (transifex + google tags) and object/iframe (youtube) + // default-src 'self'; style-src: https://cdnjs.cloudflare.com https://fonts.googleapis.com; script-src: https://cdn.transifex.com https://www.googletagmanager.com; object-src https://youtube.com; frame-src https://youtube.com; img-src: *; + // For example, to restrict everything to itself except img that can be on other servers: + // default-src 'self'; img-src *; + // Pre-existing site that uses too much js code to fix but wants to ensure resources are loaded only over https and disable plugins: + // default-src https: 'unsafe-inline' 'unsafe-eval'; object-src 'none' + // + // $contentsecuritypolicy = "frame-ancestors 'self'; img-src * data:; default-src 'self' 'unsafe-inline' 'unsafe-eval' *.paypal.com *.stripe.com *.google.com *.googlapis.com *.google-analytics.com *.googletagmanager.com;"; + // $contentsecuritypolicy = "frame-ancestors 'self'; img-src * data:; default-src *; script-src 'self' 'unsafe-inline' *.paypal.com *.stripe.com *.google.com *.googlapis.com *.google-analytics.com *.googletagmanager.com; style-src 'self' 'unsafe-inline'; connect-src 'self';"; + $contentsecuritypolicy = getDolGlobalString('MAIN_SECURITY_FORCECSPRO'); if (!is_object($hookmanager)) { include_once DOL_DOCUMENT_ROOT.'/core/class/hookmanager.class.php'; @@ -1506,7 +1514,44 @@ function top_httphead($contenttype = 'text/html', $forcenocache = 0) } $hookmanager->initHooks(array("main")); - $parameters = array('contentsecuritypolicy'=>$contentsecuritypolicy); + $parameters = array('contentsecuritypolicy'=>$contentsecuritypolicy, 'mode'=>'reportonly'); + $result = $hookmanager->executeHooks('setContentSecurityPolicy', $parameters); // Note that $action and $object may have been modified by some hooks + if ($result > 0) { + $contentsecuritypolicy = $hookmanager->resPrint; // Replace CSP + } else { + $contentsecuritypolicy .= $hookmanager->resPrint; // Concat CSP + } + + if (!empty($contentsecuritypolicy)) { + header("Content-Security-Policy-Report-Only: ".$contentsecuritypolicy); + } + } else { + header("Content-Security-Policy: ".constant('MAIN_SECURITY_FORCECSPRO')); + } + + // Content-Security-Policy + if (!defined('MAIN_SECURITY_FORCECSP')) { + // If CSP not forced from the page + + // A default security policy that keep usage of js external component like ckeditor, stripe, google, working + // For example: to restrict to only local resources, except for css (cloudflare+google), and js (transifex + google tags) and object/iframe (youtube) + // default-src 'self'; style-src: https://cdnjs.cloudflare.com https://fonts.googleapis.com; script-src: https://cdn.transifex.com https://www.googletagmanager.com; object-src https://youtube.com; frame-src https://youtube.com; img-src: *; + // For example, to restrict everything to itself except img that can be on other servers: + // default-src 'self'; img-src *; + // Pre-existing site that uses too much js code to fix but wants to ensure resources are loaded only over https and disable plugins: + // default-src https: 'unsafe-inline' 'unsafe-eval'; object-src 'none' + // + // $contentsecuritypolicy = "frame-ancestors 'self'; img-src * data:; default-src 'self' 'unsafe-inline' 'unsafe-eval' *.paypal.com *.stripe.com *.google.com *.googlapis.com *.google-analytics.com *.googletagmanager.com;"; + // $contentsecuritypolicy = "frame-ancestors 'self'; img-src * data:; default-src *; script-src 'self' 'unsafe-inline' *.paypal.com *.stripe.com *.google.com *.googlapis.com *.google-analytics.com *.googletagmanager.com; style-src 'self' 'unsafe-inline'; connect-src 'self';"; + $contentsecuritypolicy = getDolGlobalString('MAIN_SECURITY_FORCECSP'); + + if (!is_object($hookmanager)) { + include_once DOL_DOCUMENT_ROOT.'/core/class/hookmanager.class.php'; + $hookmanager = new HookManager($db); + } + $hookmanager->initHooks(array("main")); + + $parameters = array('contentsecuritypolicy'=>$contentsecuritypolicy, 'mode'=>'active'); $result = $hookmanager->executeHooks('setContentSecurityPolicy', $parameters); // Note that $action and $object may have been modified by some hooks if ($result > 0) { $contentsecuritypolicy = $hookmanager->resPrint; // Replace CSP @@ -1515,14 +1560,6 @@ function top_httphead($contenttype = 'text/html', $forcenocache = 0) } if (!empty($contentsecuritypolicy)) { - // For example, to restrict 'script', 'object', 'frames' or 'img' to some domains: - // frame-ancestors 'self'; script-src https://api.google.com https://anotherhost.com; object-src https://youtube.com; frame-src https://youtube.com; img-src https://static.example.com - // For example, to restrict everything to one domain, except 'object', ...: - // default-src https://cdn.example.net; object-src 'none' - // For example, to restrict everything to itself except img that can be on other servers: - // default-src 'self'; img-src *; - // Pre-existing site that uses too much js code to fix but wants to ensure resources are loaded only over https and disable plugins: - // default-src https: 'unsafe-inline' 'unsafe-eval'; object-src 'none' header("Content-Security-Policy: ".$contentsecuritypolicy); } } else {