forked from rebillar/site-accueil-insa
666 lines
27 KiB
PHP
666 lines
27 KiB
PHP
<?php
|
|
/**
|
|
* Matomo - free/libre analytics platform
|
|
*
|
|
* @link https://matomo.org
|
|
* @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
|
|
*
|
|
*/
|
|
namespace Piwik\Plugins\CoreAdminHome;
|
|
|
|
use Piwik\Common;
|
|
use Piwik\Nonce;
|
|
use Piwik\Piwik;
|
|
use Piwik\Plugins\LanguagesManager\API as APILanguagesManager;
|
|
use Piwik\Plugins\LanguagesManager\LanguagesManager;
|
|
use Piwik\Plugins\PrivacyManager\DoNotTrackHeaderChecker;
|
|
use Piwik\Tracker\IgnoreCookie;
|
|
use Piwik\Url;
|
|
use Piwik\View;
|
|
|
|
/*
|
|
* There are three different opt-out choices:
|
|
*
|
|
* iFrame : an <iframe> tag is added to the webpage with a Matomo URL as the source, this URL serves the opt-out
|
|
* content and sets the opt-out cookie for the Matomo URL domain. Translation and styling is done
|
|
* server side, a third party cookie is set. Not well supported with modern browser third party cookie
|
|
* restrictions, no longer offered as an option in the UI but the content URL is supported for existing
|
|
* webpages still using the iFrame code.
|
|
*
|
|
* JavaScript : an empty <div> tag is added to the webpage along with a <script> reference which loads dynamic
|
|
* JavaScript from a Matomo URL, the JavaScript then populates the empty div with the opt-out content.
|
|
* Translation and styling is read server side and built into the JavaScript, the Matomo tracker is
|
|
* used to set a first party cookie if it is loaded, otherwise the first party cookie is set directly.
|
|
* Can be broken by ad blockers that prevent third party scripts.
|
|
*
|
|
* Self-Contained: an empty <div> tag is added to the webpage along with an inline <script> tag containing the entire
|
|
* opt-out JavaScript. Translation and styling are built into the script when it is generated by the UI
|
|
* and any changes require modifying the code on each webpage. A first party cookie is set. It is
|
|
* unlikely that the script will be blocked as it is fully self-contained and part of the webpage.
|
|
*
|
|
*/
|
|
class OptOutManager
|
|
{
|
|
/** @var DoNotTrackHeaderChecker */
|
|
private $doNotTrackHeaderChecker;
|
|
|
|
/** @var array */
|
|
private $javascripts;
|
|
|
|
/** @var array */
|
|
private $stylesheets;
|
|
|
|
/** @var string */
|
|
private $title;
|
|
|
|
/** @var View|null */
|
|
private $view;
|
|
|
|
/** @var array */
|
|
private $queryParameters = array();
|
|
|
|
/**
|
|
* @param DoNotTrackHeaderChecker|null $doNotTrackHeaderChecker
|
|
*/
|
|
public function __construct(DoNotTrackHeaderChecker $doNotTrackHeaderChecker = null)
|
|
{
|
|
$this->doNotTrackHeaderChecker = $doNotTrackHeaderChecker ?: new DoNotTrackHeaderChecker();
|
|
|
|
$this->javascripts = array(
|
|
'inline' => array(),
|
|
'external' => array(),
|
|
);
|
|
|
|
$this->stylesheets = array(
|
|
'inline' => array(),
|
|
'external' => array(),
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Add a javascript file|code into the OptOut View
|
|
* Note: This method will not escape the inline javascript code!
|
|
*
|
|
* @param string $javascript
|
|
* @param bool $inline
|
|
*/
|
|
public function addJavaScript($javascript, $inline = true)
|
|
{
|
|
$type = $inline ? 'inline' : 'external';
|
|
$this->javascripts[$type][] = $javascript;
|
|
}
|
|
|
|
/**
|
|
* @return array
|
|
*/
|
|
public function getJavaScripts()
|
|
{
|
|
return $this->javascripts;
|
|
}
|
|
|
|
/**
|
|
* Add a stylesheet file|code into the OptOut View
|
|
* Note: This method will not escape the inline css code!
|
|
*
|
|
* @param string $stylesheet Escaped stylesheet
|
|
* @param bool $inline
|
|
*/
|
|
public function addStylesheet($stylesheet, $inline = true)
|
|
{
|
|
$type = $inline ? 'inline' : 'external';
|
|
$this->stylesheets[$type][] = $stylesheet;
|
|
}
|
|
|
|
/**
|
|
* @return array
|
|
*/
|
|
public function getStylesheets()
|
|
{
|
|
return $this->stylesheets;
|
|
}
|
|
|
|
/**
|
|
* @return string
|
|
*/
|
|
public function getTitle()
|
|
{
|
|
return $this->title;
|
|
}
|
|
|
|
/**
|
|
* @param string $title
|
|
*/
|
|
public function setTitle($title)
|
|
{
|
|
$this->title = $title;
|
|
}
|
|
|
|
/**
|
|
* @param string $key
|
|
* @param string $value
|
|
* @param bool $override
|
|
*
|
|
* @return bool
|
|
*/
|
|
public function addQueryParameter($key, $value, $override = true)
|
|
{
|
|
if (!isset($this->queryParameters[$key]) || true === $override) {
|
|
$this->queryParameters[$key] = $value;
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* @param array $items
|
|
* @param bool|true $override
|
|
*/
|
|
public function addQueryParameters(array $items, $override = true)
|
|
{
|
|
foreach ($items as $key => $value) {
|
|
$this->addQueryParameter($key, $value, $override);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @param $key
|
|
*/
|
|
public function removeQueryParameter($key)
|
|
{
|
|
unset($this->queryParameters[$key]);
|
|
}
|
|
|
|
/**
|
|
* @return array
|
|
*/
|
|
public function getQueryParameters()
|
|
{
|
|
return $this->queryParameters;
|
|
}
|
|
|
|
/**
|
|
* Return the HTML code to be added to pages for the JavaScript opt-out
|
|
*
|
|
* @param string $matomoUrl
|
|
* @param string $language
|
|
* @param string $backgroundColor
|
|
* @param string $fontColor
|
|
* @param string $fontSize
|
|
* @param string $fontFamily
|
|
* @param bool $applyStyling
|
|
* @param bool $showIntro
|
|
*
|
|
* @return string
|
|
*/
|
|
public function getOptOutJSEmbedCode(string $matomoUrl, string $language, string $backgroundColor, string $fontColor,
|
|
string $fontSize, string $fontFamily, bool $applyStyling, bool $showIntro): string
|
|
{
|
|
return '<div id="matomo-opt-out"></div>
|
|
<script src="'.rtrim($matomoUrl, '/').'/index.php?module=CoreAdminHome&action=optOutJS&divId=matomo-opt-out&language='.$language.($applyStyling ? '&backgroundColor='.$backgroundColor.'&fontColor='.$fontColor.'&fontSize='.$fontSize.'&fontFamily='.$fontFamily : '').'&showIntro='.($showIntro ? '1' : '0').'"></script>';
|
|
}
|
|
|
|
/**
|
|
* Return the HTML code to be added to pages for the self-contained opt-out
|
|
*
|
|
* @param string $backgroundColor
|
|
* @param string $fontColor
|
|
* @param string $fontSize
|
|
* @param string $fontFamily
|
|
* @param bool $applyStyling
|
|
* @param bool $showIntro
|
|
*
|
|
* @return string
|
|
*/
|
|
public function getOptOutSelfContainedEmbedCode(string $backgroundColor, string $fontColor, string $fontSize,
|
|
string $fontFamily, bool $applyStyling, bool $showIntro): string
|
|
{
|
|
|
|
$cookiePath = Common::getRequestVar('cookiePath', '', 'string');
|
|
$cookieDomain = Common::getRequestVar('cookieDomain', '', 'string');
|
|
|
|
$settings = [
|
|
'showIntro' => $showIntro,
|
|
'divId' => 'matomo-opt-out',
|
|
'useSecureCookies' => true,
|
|
'cookiePath' => ($cookiePath !== '' ? $cookiePath : null),
|
|
'cookieDomain' => ($cookieDomain !== '' ? $cookieDomain : null),
|
|
'cookieSameSite' => Common::getRequestVar('cookieSameSite', 'Lax', 'string'),
|
|
];
|
|
|
|
// Self contained code translations are static and always use the language of the user who generated the embed code
|
|
$settings = array_merge($settings, $this->getTranslations());
|
|
$settingsString = 'var settings = '.json_encode($settings).';';
|
|
|
|
$styleSheet = $this->optOutStyling($fontSize, $fontColor, $fontFamily, $backgroundColor, true);
|
|
|
|
$code = <<<HTML
|
|
<div id="matomo-opt-out" style=""></div>
|
|
<script>
|
|
var settings = {};
|
|
document.addEventListener('DOMContentLoaded', function() {
|
|
window.MatomoConsent.init(settings.useSecureCookies, settings.cookiePath, settings.cookieDomain, settings.cookieSameSite);
|
|
showContent(window.MatomoConsent.hasConsent());
|
|
});
|
|
|
|
window.MatomoConsent = { };
|
|
</script>
|
|
HTML;
|
|
return str_replace('window.MatomoConsent = { };', $this->getOptOutCommonJS(),
|
|
str_replace('style=""', ($applyStyling ? 'style="'.$styleSheet.'"' : ''),
|
|
str_replace("var settings = {};", $settingsString, $code)));
|
|
}
|
|
|
|
/**
|
|
* Generate and return JavaScript to show the opt-out option
|
|
*
|
|
* All optOutJS URL params:
|
|
* backgroundColor
|
|
* fontColor
|
|
* fontSize
|
|
* fontFamily
|
|
* language (default "auto") Language code for the translations or "auto" to use the browser language
|
|
* showIntro (default 1) Should the opt-out intro text be shown?
|
|
* divId (default "matomo-opt-out") The id of the div which will contain the opt-out form
|
|
* useCookiesIfNoTracker (default 1) Should consent cookies be read/written directly if the tracker can't be found?
|
|
* useCookiesTimeout (default 10) How long to wait for the tracker to be detected?
|
|
* useSecureCookies (default 1) Set secure cookies?
|
|
* cookiePath (default blank) Use this path for consent cookies
|
|
* cookieDomain (default blank) Use this domain for consent cookies
|
|
*
|
|
* @return string
|
|
*/
|
|
public function getOptOutJS() : string
|
|
{
|
|
|
|
$language = Common::getRequestVar('language', 'auto', 'string');
|
|
$showIntro = Common::getRequestVar('showIntro', 1, 'int');
|
|
$divId = Common::getRequestVar('divId', 'matomo-opt-out', 'string');
|
|
$useCookiesIfNoTracker = Common::getRequestVar('useCookiesIfNoTracker', 1, 'int');
|
|
$useCookiesTimeout = Common::getRequestVar('useCookiesTimeout', 10, 'int');
|
|
$useSecureCookies = Common::getRequestVar('useSecureCookies', 1, 'int');
|
|
$cookiePath = Common::getRequestVar('cookiePath', '', 'string');
|
|
$cookieDomain = Common::getRequestVar('cookieDomain', '', 'string');
|
|
|
|
// If the language parameter is 'auto' then use the browser language
|
|
if ($language === 'auto') {
|
|
$language = Common::extractLanguageCodeFromBrowserLanguage(Common::getBrowserLanguage(),
|
|
APILanguagesManager::getInstance()->getAvailableLanguages());
|
|
}
|
|
|
|
$settings = [
|
|
'showIntro' => $showIntro,
|
|
'divId' => $divId,
|
|
'useSecureCookies' => $useSecureCookies,
|
|
'cookiePath' => ($cookiePath !== '' ? $cookiePath : null),
|
|
'cookieDomain' => ($cookieDomain !== '' ? $cookieDomain : null),
|
|
'useCookiesIfNoTracker' => $useCookiesIfNoTracker,
|
|
'useCookiesTimeout' => $useCookiesTimeout,
|
|
];
|
|
|
|
// Self contained code translations are static and always use the language of the user who generated the embed code
|
|
$translations = $this->getTranslations($language);
|
|
$translations['OptOutErrorNoTracker'] = Piwik::translate('CoreAdminHome_OptOutErrorNoTracker', [], $language);
|
|
$settings = array_merge($settings, $translations);
|
|
$settingsString = 'var settings = '.json_encode($settings).';';
|
|
|
|
$styleSheet = $this->optOutStyling(null, null, null, null, true);
|
|
|
|
/** @lang JavaScript */
|
|
$code = <<<JS
|
|
|
|
var settings = {};
|
|
var checkForTrackerTried = 0;
|
|
var checkForTrackerTries = (settings.useCookiesTimeout * 4);
|
|
var checkForTrackerInterval = 250;
|
|
var optOutDiv = null;
|
|
|
|
function optOutInit() {
|
|
optOutDiv = document.getElementById(settings.divId);
|
|
if (optOutDiv) {
|
|
optOutDiv.style.cssText += 'stylecss'; // Appending css to avoid overwritting existing inline div styles
|
|
} else {
|
|
showContent(false, null, true); // will show unable to find opt-out div error
|
|
return;
|
|
}
|
|
checkForMatomoTracker();
|
|
}
|
|
|
|
function checkForMatomoTracker() {
|
|
if (typeof _paq !== 'undefined') {
|
|
showOptOutTracker();
|
|
return;
|
|
}
|
|
|
|
if (checkForTrackerTried < checkForTrackerTries) {
|
|
setTimeout(checkForMatomoTracker, checkForTrackerInterval);
|
|
checkForTrackerTried++;
|
|
return;
|
|
}
|
|
|
|
if (settings.useCookiesIfNoTracker) {
|
|
showOptOutDirect();
|
|
return;
|
|
}
|
|
|
|
console.log('Matomo OptOutJS: failed to find Matomo tracker after '+(checkForTrackerTries*checkForTrackerInterval / 1000)+' seconds');
|
|
}
|
|
|
|
function showOptOutTracker() {
|
|
_paq.push([function () {
|
|
if (settings.cookieDomain) {
|
|
_paq.push(['setCookieDomain', settings.cookieDomain]);
|
|
}
|
|
if (settings.cookiePath) {
|
|
_paq.push(['setCookiePath', settings.cookiePath]);
|
|
}
|
|
if (this.isUserOptedOut()) {
|
|
_paq.push(['forgetUserOptOut']);
|
|
showContent(false, null, true);
|
|
} else {
|
|
_paq.push(['optUserOut']);
|
|
showContent(true, null, true);
|
|
}
|
|
}]);
|
|
}
|
|
|
|
function showOptOutDirect() {
|
|
window.MatomoConsent.init(settings.useSecureCookies, settings.cookiePath, settings.cookieDomain, settings.cookieSameSite);
|
|
showContent(window.MatomoConsent.hasConsent());
|
|
}
|
|
|
|
document.addEventListener('DOMContentLoaded', optOutInit());
|
|
|
|
window.MatomoConsent = { };
|
|
JS;
|
|
|
|
return str_replace('window.MatomoConsent = { };', $this->getOptOutCommonJS(),
|
|
str_replace('stylecss', $styleSheet,
|
|
str_replace("var settings = {};", $settingsString, $code)));
|
|
|
|
}
|
|
|
|
/**
|
|
* Return the shared opt-out JavaScript (used by self-contained and tracker versions)
|
|
*
|
|
* @return string
|
|
*/
|
|
private function getOptOutCommonJS() : string
|
|
{
|
|
/** @lang JavaScript */
|
|
return <<<JS
|
|
|
|
function showContent(consent, errorMessage = null, useTracker = false) {
|
|
|
|
var errorBlock = '<p style="color: red; font-weight: bold;">';
|
|
|
|
var div = document.getElementById(settings.divId);
|
|
if (!div) {
|
|
const warningDiv = document.createElement("div");
|
|
var msg = 'Unable to find opt-out content div: "'+settings.divId+'"';
|
|
warningDiv.id = settings.divId+'-warning';
|
|
warningDiv.innerHTML = errorBlock+msg+'</p>';
|
|
document.body.insertBefore(warningDiv, document.body.firstChild);
|
|
console.log(msg);
|
|
return;
|
|
}
|
|
|
|
if (!navigator || !navigator.cookieEnabled) {
|
|
div.innerHTML = errorBlock+settings.OptOutErrorNoCookies+'</p>';
|
|
return;
|
|
}
|
|
if (location.protocol !== 'https:') {
|
|
div.innerHTML = errorBlock+settings.OptOutErrorNotHttps+'</p>';
|
|
return;
|
|
}
|
|
if (errorMessage !== null) {
|
|
div.innerHTML = errorBlock+errorMessage+'</p>';
|
|
return;
|
|
}
|
|
var content = '';
|
|
if (consent) {
|
|
if (settings.showIntro) {
|
|
content += '<p>'+settings.YouMayOptOut2+' '+settings.YouMayOptOut3+'</p>';
|
|
}
|
|
if (useTracker) {
|
|
content += '<input onclick="_paq.push([\'optUserOut\']);showContent(false, null, true);" id="trackVisits" type="checkbox" checked="checked" />';
|
|
} else {
|
|
content += '<input onclick="window.MatomoConsent.consentRevoked();showContent(false);" id="trackVisits" type="checkbox" checked="checked" />';
|
|
}
|
|
content += '<label for="trackVisits"><strong><span>'+settings.YouAreNotOptedOut+' '+settings.UncheckToOptOut+'</span></strong></label>';
|
|
} else {
|
|
if (settings.showIntro) {
|
|
content += '<p>'+settings.OptOutComplete+' '+settings.OptOutCompleteBis+'</p>';
|
|
}
|
|
if (useTracker) {
|
|
content += '<input onclick="_paq.push([\'forgetUserOptOut\']);showContent(true, null, true);" id="trackVisits" type="checkbox" />';
|
|
} else {
|
|
content += '<input onclick="window.MatomoConsent.consentGiven();showContent(true);" id="trackVisits" type="checkbox" />';
|
|
}
|
|
content += '<label for="trackVisits"><strong><span>'+settings.YouAreOptedOut+' '+settings.CheckToOptIn+'</span></strong></label>';
|
|
}
|
|
div.innerHTML = content;
|
|
};
|
|
|
|
window.MatomoConsent = {
|
|
cookiesDisabled: (!navigator || !navigator.cookieEnabled),
|
|
CONSENT_COOKIE_NAME: 'mtm_consent', CONSENT_REMOVED_COOKIE_NAME: 'mtm_consent_removed',
|
|
cookieIsSecure: false, useSecureCookies: true, cookiePath: '', cookieDomain: '', cookieSameSite: 'Lax',
|
|
init: function(useSecureCookies, cookiePath, cookieDomain, cookieSameSite) {
|
|
this.useSecureCookies = useSecureCookies; this.cookiePath = cookiePath;
|
|
this.cookieDomain = cookieDomain; this.cookieSameSite = cookieSameSite;
|
|
if(useSecureCookies && location.protocol !== 'https:') {
|
|
console.log('Error with setting useSecureCookies: You cannot use this option on http.');
|
|
} else {
|
|
this.cookieIsSecure = useSecureCookies;
|
|
}
|
|
},
|
|
hasConsent: function() {
|
|
var value = this.getCookie(this.CONSENT_COOKIE_NAME);
|
|
if (this.getCookie(this.CONSENT_REMOVED_COOKIE_NAME) && value) {
|
|
this.setCookie(this.CONSENT_COOKIE_NAME, '', -129600000);
|
|
return false;
|
|
}
|
|
return (value || value !== 0);
|
|
},
|
|
consentGiven: function() {
|
|
this.setCookie(this.CONSENT_REMOVED_COOKIE_NAME, '', -129600000);
|
|
this.setCookie(this.CONSENT_COOKIE_NAME, new Date().getTime(), 946080000000);
|
|
},
|
|
consentRevoked: function() {
|
|
this.setCookie(this.CONSENT_COOKIE_NAME, '', -129600000);
|
|
this.setCookie(this.CONSENT_REMOVED_COOKIE_NAME, new Date().getTime(), 946080000000);
|
|
},
|
|
getCookie: function(cookieName) {
|
|
var cookiePattern = new RegExp('(^|;)[ ]*' + cookieName + '=([^;]*)'), cookieMatch = cookiePattern.exec(document.cookie);
|
|
return cookieMatch ? window.decodeURIComponent(cookieMatch[2]) : 0;
|
|
},
|
|
setCookie: function(cookieName, value, msToExpire) {
|
|
var expiryDate = new Date();
|
|
expiryDate.setTime((new Date().getTime()) + msToExpire);
|
|
document.cookie = cookieName + '=' + window.encodeURIComponent(value) +
|
|
(msToExpire ? ';expires=' + expiryDate.toGMTString() : '') +
|
|
';path=' + (this.cookiePath || '/') +
|
|
(this.cookieDomain ? ';domain=' + this.cookieDomain : '') +
|
|
(this.cookieIsSecure ? ';secure' : '') +
|
|
';SameSite=' + this.cookieSameSite;
|
|
if ((!msToExpire || msToExpire >= 0) && this.getCookie(cookieName) !== String(value)) {
|
|
console.log('There was an error setting cookie `' + cookieName + '`. Please check domain and path.');
|
|
}
|
|
}
|
|
};
|
|
JS;
|
|
|
|
}
|
|
|
|
/**
|
|
* Get translations used by the opt-out popup
|
|
*
|
|
* @param string|null $language
|
|
*
|
|
* @return array
|
|
*/
|
|
private function getTranslations(string $language = null) : array
|
|
{
|
|
return [
|
|
'OptOutComplete' => Piwik::translate('CoreAdminHome_OptOutComplete', [], $language),
|
|
'OptOutCompleteBis' => Piwik::translate('CoreAdminHome_OptOutCompleteBis', [], $language),
|
|
'YouMayOptOut2' => Piwik::translate('CoreAdminHome_YouMayOptOut2', [], $language),
|
|
'YouMayOptOut3' => Piwik::translate('CoreAdminHome_YouMayOptOut3', [], $language),
|
|
'OptOutErrorNoCookies' => Piwik::translate('CoreAdminHome_OptOutErrorNoCookies', [], $language),
|
|
'OptOutErrorNotHttps' => Piwik::translate('CoreAdminHome_OptOutErrorNotHttps', [], $language),
|
|
'YouAreNotOptedOut' => Piwik::translate('CoreAdminHome_YouAreNotOptedOut', [], $language),
|
|
'UncheckToOptOut' => Piwik::translate('CoreAdminHome_UncheckToOptOut', [], $language),
|
|
'YouAreOptedOut' => Piwik::translate('CoreAdminHome_YouAreOptedOut', [], $language),
|
|
'CheckToOptIn' => Piwik::translate('CoreAdminHome_CheckToOptIn', [], $language),
|
|
];
|
|
}
|
|
|
|
/**
|
|
* Return the content of the iFrame opt out
|
|
*
|
|
* @return View
|
|
* @throws \Exception
|
|
*/
|
|
public function getOptOutViewIFrame()
|
|
{
|
|
if ($this->view) {
|
|
return $this->view;
|
|
}
|
|
|
|
$trackVisits = !IgnoreCookie::isIgnoreCookieFound();
|
|
$dntFound = $this->getDoNotTrackHeaderChecker()->isDoNotTrackFound();
|
|
|
|
$setCookieInNewWindow = Common::getRequestVar('setCookieInNewWindow', false, 'int');
|
|
if ($setCookieInNewWindow) {
|
|
$nonce = Common::getRequestVar('nonce', false);
|
|
|
|
if ($nonce !== false && !Nonce::verifyNonce('Piwik_OptOut', $nonce)) {
|
|
Nonce::discardNonce('Piwik_OptOut');
|
|
$nonce = '';
|
|
}
|
|
|
|
$reloadUrl = Url::getCurrentQueryStringWithParametersModified(array(
|
|
'showConfirmOnly' => 1,
|
|
'setCookieInNewWindow' => 0,
|
|
'nonce' => $nonce ? : ''
|
|
));
|
|
} else {
|
|
$reloadUrl = false;
|
|
|
|
$requestNonce = Common::getRequestVar('nonce', false);
|
|
if ($requestNonce !== false && Nonce::verifyNonce('Piwik_OptOut', $requestNonce)) {
|
|
Nonce::discardNonce('Piwik_OptOut');
|
|
IgnoreCookie::setIgnoreCookie();
|
|
$trackVisits = !$trackVisits;
|
|
}
|
|
}
|
|
|
|
$language = Common::getRequestVar('language', '');
|
|
$lang = APILanguagesManager::getInstance()->isLanguageAvailable($language)
|
|
? $language
|
|
: LanguagesManager::getLanguageCodeForCurrentUser();
|
|
|
|
$nonce = Nonce::getNonce('Piwik_OptOut', 3600);
|
|
|
|
$this->addQueryParameters(array(
|
|
'module' => 'CoreAdminHome',
|
|
'action' => 'optOut',
|
|
'language' => $lang,
|
|
'setCookieInNewWindow' => 1,
|
|
'nonce' => $nonce
|
|
), false);
|
|
|
|
if (Common::getRequestVar('applyStyling', 1, 'int')) {
|
|
$this->addStylesheet($this->optOutStyling());
|
|
}
|
|
|
|
$this->view = new View("@CoreAdminHome/optOut");
|
|
|
|
$this->addJavaScript('plugins/CoreAdminHome/javascripts/optOut.js', false);
|
|
|
|
$this->view->setXFrameOptions('allow');
|
|
$this->view->dntFound = $dntFound;
|
|
$this->view->trackVisits = $trackVisits;
|
|
$this->view->nonce = $nonce;
|
|
$this->view->language = $lang;
|
|
$this->view->showIntro = Common::getRequestVar('showIntro', 1, 'int');
|
|
$this->view->showConfirmOnly = Common::getRequestVar('showConfirmOnly', false, 'int');
|
|
$this->view->reloadUrl = $reloadUrl;
|
|
$this->view->javascripts = $this->getJavaScripts();
|
|
$this->view->stylesheets = $this->getStylesheets();
|
|
$this->view->title = $this->getTitle();
|
|
$this->view->queryParameters = $this->getQueryParameters();
|
|
return $this->view;
|
|
}
|
|
|
|
/**
|
|
* Provide a CSS style sheet based on the chosen opt out style options
|
|
*
|
|
* @param string|null $fontSize
|
|
* @param string|null $fontColor
|
|
* @param string|null $fontFamily
|
|
* @param string|null $backgroundColor
|
|
* @param bool $noBody
|
|
*
|
|
* @return string
|
|
* @throws \Exception
|
|
*/
|
|
private function optOutStyling(?string $fontSize = null, ?string $fontColor = null, ?string $fontFamily = null,
|
|
?string $backgroundColor = null, bool $noBody = false): string
|
|
{
|
|
$cssfontsize = ($fontSize ? : Common::unsanitizeInputValue(Common::getRequestVar('fontSize', false, 'string')));
|
|
$cssfontcolour = ($fontColor ? : Common::unsanitizeInputValue(Common::getRequestVar('fontColor', false, 'string')));
|
|
$cssfontfamily = ($fontFamily ? : Common::unsanitizeInputValue(Common::getRequestVar('fontFamily', false, 'string')));
|
|
$cssbackgroundcolor = ($backgroundColor ? : Common::unsanitizeInputValue(Common::getRequestVar('backgroundColor', false, 'string')));
|
|
|
|
if (!$noBody) {
|
|
$cssbody = 'body { ';
|
|
} else {
|
|
$cssbody = '';
|
|
}
|
|
|
|
$hexstrings = array(
|
|
'fontColor' => $cssfontcolour,
|
|
'backgroundColor' => $cssbackgroundcolor
|
|
);
|
|
foreach ($hexstrings as $key => $testcase) {
|
|
if ($testcase && !(ctype_xdigit($testcase) && in_array(strlen($testcase),array(3,6), true))) {
|
|
throw new \Exception("The URL parameter $key value of '$testcase' is not valid. Expected value is for example 'ffffff' or 'fff'.\n");
|
|
}
|
|
}
|
|
|
|
/** @noinspection RegExpRedundantEscape */
|
|
if ($cssfontsize && (preg_match("/^[0-9]+[\.]?[0-9]*(px|pt|em|rem|%)$/", $cssfontsize))) {
|
|
$cssbody .= 'font-size: ' . $cssfontsize . '; ';
|
|
} else if ($cssfontsize) {
|
|
throw new \Exception("The URL parameter fontSize value of '$cssfontsize' is not valid. Expected value is for example '15pt', '1.2em' or '13px'.\n");
|
|
}
|
|
|
|
/** @noinspection RegExpRedundantEscape */
|
|
if ($cssfontfamily && (preg_match('/^[a-zA-Z0-9-\ ,\'"]+$/', $cssfontfamily))) {
|
|
$cssbody .= 'font-family: ' . $cssfontfamily . '; ';
|
|
} else if ($cssfontfamily) {
|
|
throw new \Exception("The URL parameter fontFamily value of '$cssfontfamily' is not valid. Expected value is for example 'sans-serif' or 'Monaco, monospace'.\n");
|
|
}
|
|
|
|
if ($cssfontcolour) {
|
|
$cssbody .= 'color: #' . $cssfontcolour . '; ';
|
|
}
|
|
if ($cssbackgroundcolor) {
|
|
$cssbody .= 'background-color: #' . $cssbackgroundcolor . '; ';
|
|
}
|
|
|
|
if (!$noBody) {
|
|
$cssbody .= '}';
|
|
}
|
|
return $cssbody;
|
|
}
|
|
/**
|
|
* @return DoNotTrackHeaderChecker
|
|
*/
|
|
protected function getDoNotTrackHeaderChecker()
|
|
{
|
|
return $this->doNotTrackHeaderChecker;
|
|
}
|
|
}
|