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 {