2017-07-20 16:49:20 +02:00
< ? php
2024-06-15 16:02:47 +02:00
/* Copyright ( C ) 2017 - 2024 Laurent Destailleur < eldy @ users . sourceforge . net >
2025-01-06 21:10:21 +01:00
* Copyright ( C ) 2024 - 2025 Frédéric France < frederic . france @ free . fr >
2017-07-20 16:49:20 +02:00
*
* This program is free software ; you can redistribute it and / or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation ; either version 3 of the License , or
* ( at your option ) any later version .
*
* This program is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
* GNU General Public License for more details .
*
* You should have received a copy of the GNU General Public License
2019-09-23 21:55:30 +02:00
* along with this program . If not , see < https :// www . gnu . org / licenses />.
* or see https :// www . gnu . org /
2017-07-20 16:49:20 +02:00
*/
/**
* \file htdocs / core / website . inc . php
2024-03-29 23:59:23 +01:00
* \brief Common file loaded by all website pages ( after master . inc . php ) . It sets the new object $weblangs .
* This file is included in top of all container pages ( in edit mode , in dolibarr web server mode and in external web server mode ) .
* It is run only when a web page is called .
2018-09-25 16:35:59 +02:00
* The global variable $websitekey must be defined .
2017-07-20 16:49:20 +02:00
*/
2018-10-03 20:58:45 +02:00
// Load website class
2017-10-20 23:48:42 +02:00
include_once DOL_DOCUMENT_ROOT . '/website/class/website.class.php' ;
2019-04-30 13:50:03 +02:00
include_once DOL_DOCUMENT_ROOT . '/website/class/websitepage.class.php' ;
2022-03-16 15:56:39 +01:00
$website = null ;
$websitepage = null ;
$weblangs = null ;
$pagelangs = null ;
2020-05-15 18:41:46 +02:00
// Detection browser (copy of code from main.inc.php)
2021-02-23 22:03:23 +01:00
if ( isset ( $_SERVER [ " HTTP_USER_AGENT " ]) && is_object ( $conf ) && empty ( $conf -> browser -> name )) {
2020-05-15 18:41:46 +02:00
$tmp = getBrowserInfo ( $_SERVER [ " HTTP_USER_AGENT " ]);
$conf -> browser -> name = $tmp [ 'browsername' ];
$conf -> browser -> os = $tmp [ 'browseros' ];
$conf -> browser -> version = $tmp [ 'browserversion' ];
$conf -> browser -> layout = $tmp [ 'layout' ]; // 'classic', 'phone', 'tablet'
//var_dump($conf->browser);
2021-02-23 22:03:23 +01:00
if ( $conf -> browser -> layout == 'phone' ) {
$conf -> dol_no_mouse_hover = 1 ;
}
2020-05-15 18:41:46 +02:00
}
2018-10-16 01:39:04 +02:00
// Define $website
2024-06-15 16:02:47 +02:00
if ( is_null ( $website )) {
2019-12-09 10:35:58 +01:00
$website = new Website ( $db );
2019-01-27 11:55:16 +01:00
$website -> fetch ( 0 , $websitekey );
2018-10-03 20:58:45 +02:00
}
2018-10-16 01:39:04 +02:00
// Define $websitepage if we have $websitepagefile defined
2023-03-09 18:12:17 +01:00
if ( empty ( $pageid ) && ! empty ( $websitepagefile )) {
2018-10-16 01:39:04 +02:00
$pageid = str_replace ( array ( '.tpl.php' , 'page' ), array ( '' , '' ), basename ( $websitepagefile ));
2021-02-23 22:03:23 +01:00
if ( $pageid == 'index.php' ) {
$pageid = $website -> fk_default_home ;
}
2019-04-30 13:50:03 +02:00
}
2024-06-15 16:02:47 +02:00
if ( is_null ( $websitepage )) {
2020-10-31 14:32:18 +01:00
$websitepage = new WebsitePage ( $db );
2018-10-16 01:39:04 +02:00
}
2020-05-08 14:25:49 +02:00
// Define $weblangs
2024-06-15 16:02:47 +02:00
if ( is_null ( $weblangs )) {
2020-05-08 14:35:03 +02:00
$weblangs = new Translate ( '' , $conf );
2020-05-08 14:25:49 +02:00
}
2024-06-15 16:02:47 +02:00
if ( is_null ( $pagelangs )) {
2020-05-15 19:01:12 +02:00
$pagelangs = new Translate ( '' , $conf );
}
2024-02-25 16:57:45 +01:00
if ( ! empty ( $pageid ) && $pageid > 0 ) {
2018-10-16 01:39:04 +02:00
$websitepage -> fetch ( $pageid );
2019-11-12 13:55:46 +01:00
2024-03-29 23:59:23 +01:00
// Rule to define weblang of visitor:
// 1 - Take parameter lang
// 2 - Cookie lang of website (set by a possible js lang selector)
// 3 - XX/... found in url page
// 4 - auto (so web browser lang)
$srclang = GETPOSTISSET ( 'lang' ) ? GETPOST ( 'lang' , 'aZ09' ) : '' ;
if ( empty ( $srclang )) {
$srclang = ( empty ( $_COOKIE [ 'weblangs-shortcode' ]) ? '' : preg_replace ( '/[^a-zA-Z0-9_\-]/' , '' , $_COOKIE [ 'weblangs-shortcode' ]));
}
if ( empty ( $srclang )) {
$reg = array ();
2024-03-30 00:18:42 +01:00
// With Dolibarr server, url is in parameter pageref
if ( defined ( 'USEDOLIBARRSERVER' ) && ! empty ( $_GET [ 'pageref' ]) && preg_match ( '/^\/?(\w\w)\//' , $_GET [ 'pageref' ], $reg ) && $reg [ 1 ] != 'js' ) { // We reuse $_GET['pageref'] because $pageref may have been cleaned already from the language code.
$srclang = $reg [ 1 ];
}
// With External server, url is in parameter pageref
if ( defined ( 'USEEXTERNALSERVER' ) && ! empty ( $_SERVER [ 'PHP_SELF' ]) && preg_match ( '/^\/?(\w\w)\//' , $_SERVER [ 'PHP_SELF' ], $reg ) && $reg [ 1 ] != 'js' ) {
2024-03-29 23:59:23 +01:00
$srclang = $reg [ 1 ];
}
}
if ( empty ( $srclang )) {
$srclang = 'auto' ;
}
$weblangs -> setDefaultLang ( $srclang );
2020-05-15 19:01:12 +02:00
$pagelangs -> setDefaultLang ( $websitepage -> lang ? $websitepage -> lang : $weblangs -> shortlang );
2020-05-08 14:25:49 +02:00
2022-03-16 15:56:39 +01:00
if ( ! defined ( 'USEDOLIBARREDITOR' ) && ( in_array ( $websitepage -> type_container , array ( 'menu' , 'other' )) || empty ( $websitepage -> status ) && ! defined ( 'USEDOLIBARRSERVER' ))) {
2019-11-12 13:55:46 +01:00
$weblangs -> load ( " website " );
2022-09-09 13:58:54 +02:00
// Security options
// X-Content-Type-Options
header ( " X-Content-Type-Options: nosniff " );
// X-Frame-Options
2023-11-27 11:39:32 +01:00
if ( empty ( $websitepage -> allowed_in_frames ) && ! getDolGlobalString ( 'WEBSITE_ALLOW_FRAMES_ON_ALL_PAGES' )) {
2022-09-09 13:58:54 +02:00
header ( " X-Frame-Options: SAMEORIGIN " );
}
//httponly_accessforbidden('<center><br><br>'.$weblangs->trans("YouTryToAccessToAFileThatIsNotAWebsitePage", $websitepage->pageurl, $websitepage->type_container, $websitepage->status).'</center>', 404, 1);
2019-11-12 13:55:46 +01:00
http_response_code ( 404 );
2020-06-09 22:43:37 +02:00
print '<center><br><br>' . $weblangs -> trans ( " YouTryToAccessToAFileThatIsNotAWebsitePage " , $websitepage -> pageurl , $websitepage -> type_container , $websitepage -> status ) . '</center>' ;
2019-11-12 13:55:46 +01:00
exit ;
}
2018-10-16 01:39:04 +02:00
}
2018-10-14 18:44:29 +02:00
2019-12-09 10:35:58 +01:00
if ( ! defined ( 'USEDOLIBARRSERVER' ) && ! defined ( 'USEDOLIBARREDITOR' )) {
2022-08-16 15:19:21 +02:00
// Security options
// X-Content-Type-Options
2019-12-07 11:51:21 +01:00
header ( " X-Content-Type-Options: nosniff " );
2022-08-16 15:19:21 +02:00
// X-Frame-Options
2023-11-27 11:39:32 +01:00
if ( empty ( $websitepage -> allowed_in_frames ) && ! getDolGlobalString ( 'WEBSITE_ALLOW_FRAMES_ON_ALL_PAGES' )) {
2019-12-07 15:46:14 +01:00
header ( " X-Frame-Options: SAMEORIGIN " );
}
2022-08-16 15:19:21 +02:00
// 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.
2023-02-28 10:39:39 +01:00
// Content-Security-Policy-Report-Only
2025-02-14 11:13:39 +01:00
if ( ! defined ( 'WEBSITE_' . $website -> id . '_SECURITY_FORCECSPRO' )) {
2023-02-28 10:39:39 +01:00
// 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'
//
2023-03-01 23:50:02 +01:00
// $contentsecuritypolicy = "frame-ancestors 'self'; img-src * data:; font-src *; default-src 'self' 'unsafe-inline' 'unsafe-eval' *.paypal.com *.stripe.com *.google.com *.googleapis.com *.google-analytics.com *.googletagmanager.com;";
// $contentsecuritypolicy = "frame-ancestors 'self'; img-src * data:; font-src *; default-src *; script-src 'self' 'unsafe-inline' *.paypal.com *.stripe.com *.google.com *.googleapis.com *.google-analytics.com *.googletagmanager.com; style-src 'self' 'unsafe-inline'; connect-src 'self';";
2025-02-14 11:13:39 +01:00
$contentsecuritypolicy = getDolGlobalString ( 'WEBSITE_' . $website -> id . '_SECURITY_FORCECSPRO' );
2023-02-28 10:39:39 +01:00
if ( ! is_object ( $hookmanager )) {
2023-03-26 17:59:28 +02:00
include_once DOL_DOCUMENT_ROOT . '/core/class/hookmanager.class.php' ;
2023-02-28 10:39:39 +01:00
$hookmanager = new HookManager ( $db );
}
$hookmanager -> initHooks ( array ( " main " ));
$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 );
}
}
2022-08-16 15:19:21 +02:00
// Content-Security-Policy
2025-02-10 10:27:06 +01:00
if ( ! defined ( 'WEBSITE_' . $website -> id . '_SECURITY_FORCECSP' )) {
2022-08-16 15:19:21 +02:00
// A default security policy that keep usage of js external component like ckeditor, stripe, google, working
2023-02-28 10:39:39 +01:00
// 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'
//
2023-03-01 23:50:02 +01:00
// $contentsecuritypolicy = "frame-ancestors 'self'; img-src * data:; font-src *; default-src 'self' 'unsafe-inline' 'unsafe-eval' *.paypal.com *.stripe.com *.google.com *.googleapis.com *.google-analytics.com *.googletagmanager.com;";
// $contentsecuritypolicy = "frame-ancestors 'self'; img-src * data:; font-src *; default-src *; script-src 'self' 'unsafe-inline' *.paypal.com *.stripe.com *.google.com *.googleapis.com *.google-analytics.com *.googletagmanager.com; style-src 'self' 'unsafe-inline'; connect-src 'self';";
2025-02-10 10:27:06 +01:00
$contentsecuritypolicy = getDolGlobalString ( 'WEBSITE_' . $website -> id . '_SECURITY_FORCECSP' );
2022-08-16 15:19:21 +02:00
if ( ! is_object ( $hookmanager )) {
2023-03-26 17:59:28 +02:00
include_once DOL_DOCUMENT_ROOT . '/core/class/hookmanager.class.php' ;
2022-08-16 15:19:21 +02:00
$hookmanager = new HookManager ( $db );
}
$hookmanager -> initHooks ( array ( " main " ));
2023-02-28 10:39:39 +01:00
$parameters = array ( 'contentsecuritypolicy' => $contentsecuritypolicy , 'mode' => 'active' );
2022-08-16 15:19:21 +02:00
$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: " . $contentsecuritypolicy );
}
}
2022-08-16 15:49:29 +02:00
// Referrer-Policy
2025-02-10 10:27:06 +01:00
if ( ! defined ( 'WEBSITE_' . $website -> id . '_SECURITY_FORCERP' )) {
2022-08-16 16:06:09 +02:00
// The constant WEBSITE_MAIN_SECURITY_FORCERP should never be defined by page, but the variable used just after may be
2022-08-16 15:49:29 +02:00
// For public web sites, we use the same default value than "strict-origin-when-cross-origin"
2025-02-10 10:27:06 +01:00
$referrerpolicy = getDolGlobalString ( 'WEBSITE_' . $website -> id . '_SECURITY_FORCERP' , " strict-origin-when-cross-origin " );
2022-08-16 15:49:29 +02:00
header ( " Referrer-Policy: " . $referrerpolicy );
}
2022-08-16 16:06:09 +02:00
// Strict-Transport-Security
2025-02-10 10:27:06 +01:00
if ( ! defined ( 'WEBSITE_' . $website -> id . '_SECURITY_FORCESTS' )) {
2022-08-16 16:06:09 +02:00
// The constant WEBSITE_MAIN_SECURITY_FORCESTS should never be defined by page, but the variable used just after may be
2022-08-16 16:58:28 +02:00
// Example: "max-age=31536000; includeSubDomains"
2025-02-10 10:27:06 +01:00
$sts = getDolGlobalString ( 'WEBSITE_' . $website -> id . '_SECURITY_FORCESTS' );
2022-08-16 16:06:09 +02:00
if ( ! empty ( $sts )) {
header ( " Strict-Transport-Security: " . $sts );
}
}
2022-08-16 16:58:28 +02:00
// Permissions-Policy (old name was Feature-Policy)
2025-02-10 10:27:06 +01:00
if ( ! defined ( 'WEBSITE_' . $website -> id . '_SECURITY_FORCEPP' )) {
2022-08-16 16:58:28 +02:00
// The constant WEBSITE_MAIN_SECURITY_FORCEPP should never be defined by page, but the variable used just after may be
// Example: "camera: 'none'; microphone: 'none';"
2025-02-10 10:27:06 +01:00
$pp = getDolGlobalString ( 'WEBSITE_' . $website -> id . '_SECURITY_FORCEPP' );
2022-08-16 16:58:28 +02:00
if ( ! empty ( $pp )) {
header ( " Permissions-Policy: " . $pp );
}
}
2019-12-07 11:51:21 +01:00
}
2018-10-14 18:44:29 +02:00
// A lang was forced, so we change weblangs init
2021-02-23 22:03:23 +01:00
if ( GETPOST ( 'l' , 'aZ09' )) {
$weblangs -> setDefaultLang ( GETPOST ( 'l' , 'aZ09' ));
}
2018-10-14 18:44:29 +02:00
// A lang was forced, so we check to find if we must make a redirect on translation page
2021-02-23 22:03:23 +01:00
if ( $_SERVER [ 'PHP_SELF' ] != DOL_URL_ROOT . '/website/index.php' ) { // If we browsing page using Dolibarr server or a Native web server
2018-10-14 20:04:25 +02:00
//print_r(get_defined_constants(true));exit;
2021-02-23 22:03:23 +01:00
if ( GETPOST ( 'l' , 'aZ09' )) {
2019-12-09 10:35:58 +01:00
$sql = " SELECT wp.rowid, wp.lang, wp.pageurl, wp.fk_page " ;
$sql .= " FROM " . MAIN_DB_PREFIX . " website_page as wp " ;
2021-03-30 17:53:25 +02:00
$sql .= " WHERE wp.fk_website = " . (( int ) $website -> id );
2021-04-24 20:18:11 +02:00
$sql .= " AND (wp.fk_page = " . (( int ) $pageid ) . " OR wp.rowid = " . (( int ) $pageid );
2021-02-23 22:03:23 +01:00
if ( is_object ( $websitepage ) && $websitepage -> fk_page > 0 ) {
2021-08-23 19:33:24 +02:00
$sql .= " OR wp.fk_page = " . (( int ) $websitepage -> fk_page ) . " OR wp.rowid = " . (( int ) $websitepage -> fk_page );
2021-02-23 22:03:23 +01:00
}
2019-12-09 10:35:58 +01:00
$sql .= " ) " ;
$sql .= " AND wp.lang = ' " . $db -> escape ( GETPOST ( 'l' , 'aZ09' )) . " ' " ;
2018-10-14 23:26:57 +02:00
2018-10-16 01:39:04 +02:00
$resql = $db -> query ( $sql );
2021-02-23 22:03:23 +01:00
if ( $resql ) {
2018-10-16 01:39:04 +02:00
$obj = $db -> fetch_object ( $resql );
2021-02-23 22:03:23 +01:00
if ( $obj ) {
2018-10-16 01:39:04 +02:00
$newpageid = $obj -> rowid ;
2021-02-23 22:03:23 +01:00
if ( $newpageid != $pageid ) { // To avoid to make a redirect on same page (infinite loop)
2018-10-16 01:39:04 +02:00
if ( defined ( 'USEDOLIBARRSERVER' )) {
2019-01-27 11:55:16 +01:00
header ( " Location: " . DOL_URL_ROOT . '/public/website/index.php?website=' . $websitekey . '&pageid=' . $newpageid . '&l=' . GETPOST ( 'l' , 'aZ09' ));
2018-10-16 01:39:04 +02:00
exit ;
2020-05-21 15:05:19 +02:00
} else {
2018-10-16 01:39:04 +02:00
$newpageref = $obj -> pageurl ;
2020-06-06 20:37:17 +02:00
header ( " Location: " . (( $obj -> lang && $obj -> lang != $website -> lang ) ? '/' . $obj -> lang . '/' : '/' ) . $newpageref . '.php?l=' . GETPOST ( 'l' , 'aZ09' ));
2018-10-16 01:39:04 +02:00
exit ;
2018-10-14 20:04:25 +02:00
}
2018-10-14 18:44:29 +02:00
}
}
}
}
}
2019-08-13 05:03:45 +02:00
2022-09-09 13:58:54 +02:00
// Show off line message when all website is off
2021-02-23 22:03:23 +01:00
if ( ! defined ( 'USEDOLIBARREDITOR' ) && empty ( $website -> status )) {
2022-09-09 13:58:54 +02:00
// Security options
// X-Content-Type-Options
header ( " X-Content-Type-Options: nosniff " );
// X-Frame-Options
2023-11-27 11:39:32 +01:00
if ( empty ( $websitepage -> allowed_in_frames ) && ! getDolGlobalString ( 'WEBSITE_ALLOW_FRAMES_ON_ALL_PAGES' )) {
2022-09-09 13:58:54 +02:00
header ( " X-Frame-Options: SAMEORIGIN " );
}
2019-08-13 05:03:45 +02:00
$weblangs -> load ( " website " );
2022-09-09 13:58:54 +02:00
//httponly_accessforbidden('<center><br><br>'.$weblangs->trans("SorryWebsiteIsCurrentlyOffLine").'</center>', 503, 1);
2019-08-13 06:37:06 +02:00
http_response_code ( 503 );
2019-08-13 05:03:45 +02:00
print '<center><br><br>' . $weblangs -> trans ( " SorryWebsiteIsCurrentlyOffLine " ) . '</center>' ;
exit ;
}
2024-03-14 22:06:43 +01:00
// Get session info and obfuscate session cookie and other variables
$prefix = dol_getprefix ( '' );
$sessionname = 'DOLSESSID_' . $prefix ;
//$savsessionid = $_COOKIE[$sessionname];
$_COOKIE [ $sessionname ] = 'obfuscatedcookie' ;
unset ( $conf -> file -> instance_unique_id );
2024-03-14 23:23:38 +01:00
unset ( $dolibarr_main_instance_unique_id );
unset ( $dolibarr_main_db_host );
unset ( $dolibarr_main_db_port );
unset ( $dolibarr_main_db_name );
unset ( $dolibarr_main_db_user );
unset ( $dolibarr_main_db_pass );
2025-01-06 21:10:21 +01:00
unset ( $dolibarr_main_db_type );
2024-03-14 23:23:38 +01:00
unset ( $dolibarr_main_document_root );
unset ( $dolibarr_main_document_root_alt );