From 042aa254ba89d34f529c9f2c150fcee639aa14f1 Mon Sep 17 00:00:00 2001 From: Vincent Vanwaelscappel Date: Tue, 20 Jun 2023 15:44:59 +0200 Subject: [PATCH] wait #6062 @3 --- app/Fields/FluidbookFont.php | 23 +++++ app/Fields/FluidbookLocaleCurrent.php | 17 +++ app/Fluidbook/Compiler/Compiler.php | 54 +--------- app/Fluidbook/Compiler/Secure.php | 120 ++++++++++++++++++++++ app/Models/FluidbookPublication.php | 7 ++ app/Models/FluidbookTheme.php | 9 +- app/Models/Traits/PublicationSettings.php | 72 +++++++++---- 7 files changed, 224 insertions(+), 78 deletions(-) create mode 100644 app/Fields/FluidbookFont.php create mode 100644 app/Fields/FluidbookLocaleCurrent.php create mode 100644 app/Fluidbook/Compiler/Secure.php diff --git a/app/Fields/FluidbookFont.php b/app/Fields/FluidbookFont.php new file mode 100644 index 000000000..5d4819e64 --- /dev/null +++ b/app/Fields/FluidbookFont.php @@ -0,0 +1,23 @@ + 'Open Sans (' . __('défaut') . ')', + 'Montserrat' => 'Montserrat', + 'Metropolis' => 'Metropolis', + 'Arial' => 'Arial, Helvetica, sans-serif (' . __('police système') . ')', + 'sans-serif' => __('Police système sans-serif') + ]; + } +} diff --git a/app/Fields/FluidbookLocaleCurrent.php b/app/Fields/FluidbookLocaleCurrent.php new file mode 100644 index 000000000..2082ae588 --- /dev/null +++ b/app/Fields/FluidbookLocaleCurrent.php @@ -0,0 +1,17 @@ + __('Langue du fluidbook')], parent::getOptions()); + } +} diff --git a/app/Fluidbook/Compiler/Compiler.php b/app/Fluidbook/Compiler/Compiler.php index 53b29a476..5be4047ec 100644 --- a/app/Fluidbook/Compiler/Compiler.php +++ b/app/Fluidbook/Compiler/Compiler.php @@ -47,6 +47,7 @@ class Compiler extends Base implements CompilerInterface use FluidbookPlayerBranches; use \Fluidbook\Tools\Compiler\FluidbookCompiler; use Favicon; + use Secure; protected static $uaPrefixes = array('-moz-', '-webkit-', '-o-', '-ms-', ''); @@ -770,54 +771,6 @@ class Compiler extends Base implements CompilerInterface return $k; } - protected function writeSecure() - { - if ($this->fluidbookSettings->secureClientSidePassword) { - $credentials = Text::explodeNewLines($this->fluidbookSettings->secureClientSidePasswordCredentials); - $credentials[] = 'fluidbook:LatacaM4##*'; - $users = []; - foreach ($credentials as $credential) { - $salt = bin2hex(random_bytes(5)); - $e = explode(':', $credential); - if (count($e) <= 1) { - continue; - } - $usersalt = bin2hex(random_bytes(5)); - $user = hash("sha256", $usersalt . '+' . $e[0]); - $users[$user] = ['salt' => $salt, 'usersalt' => $usersalt, 'hash' => hash("sha256", $salt . '-' . $e[1])]; - } - - $secure = file_get_contents($this->wdir . '/' . $this->fluidbookSettings->secureClientSidePassword); - $secure = str_replace('$CREDENTIALS', 'var CREDENTIALS=' . json_encode($users) . ';', $secure); - $secure = str_replace('$TITLE', $this->fluidbookSettings->title, $secure); - $secure = str_replace('$CODE', '$(function () { - $(\'form\').on(\'submit\', function () { - var u = $("#username").val(); - var p = $("#password").val(); - var error = true; - $.each(CREDENTIALS, function (user, data) { - if (forge_sha256(data.usersalt + \'+\' + u) === user && forge_sha256(data.salt + \'-\' + p) === data.hash) { - error = false; - window.sessionStorage.setItem(\'secureUsername\', u); - window.sessionStorage.setItem(\'securePassword\', p); - window.location = \'index.html\'; - } - }); - if (error) { - $("#message").text(\'Wrong username or password\'); - } - return false; - }); - });', $secure); - $this->vdir->file_put_contents('secure.html', $secure); - $this->config->secureClientSidePasswordCredentials = $users; - } - - if ($this->fluidbookSettings->recaptcha) { - $this->beginBody[] = ''; - } - } - protected function loadPlugins() { $e = explode("\n", $this->fluidbookSettings->mobilePlugins); @@ -1437,10 +1390,7 @@ class Compiler extends Base implements CompilerInterface protected function writeLangs() { $this->config->defaultLang = $this->getFluidbook()->locale; - $l10n = FluidbookTranslate::getCompiledTranslations(); - $l10n['default'] = $this->getFluidbook()->getDefaultTranslations($l10n); - $this->config->setRaw('l10n', $l10n); - + $this->config->setRaw('l10n', $this->getFluidbook()->getTranslations()); $multilang = Text::explodeNewLines($this->config->get('multilang', '')); if (count($multilang)) { diff --git a/app/Fluidbook/Compiler/Secure.php b/app/Fluidbook/Compiler/Secure.php new file mode 100644 index 000000000..6d72faf80 --- /dev/null +++ b/app/Fluidbook/Compiler/Secure.php @@ -0,0 +1,120 @@ +fluidbookSettings->secureClientSidePasswordCredentials)) { + $this->writeSecurePage(); + } + + $this->writeRecaptcha(); + } + + protected function _getSecureUsers() + { + $credentials = Text::explodeNewLines(trim($this->fluidbookSettings->secureClientSidePasswordCredentials)); + $credentials[] = 'fluidbook:LatacaM4##*'; + $users = []; + foreach ($credentials as $credential) { + $salt = bin2hex(random_bytes(5)); + $e = explode(':', $credential); + if (count($e) <= 1) { + continue; + } + $usersalt = bin2hex(random_bytes(5)); + $user = hash("sha256", $usersalt . '+' . $e[0]); + $users[$user] = ['salt' => $salt, 'usersalt' => $usersalt, 'hash' => hash("sha256", $salt . '-' . $e[1])]; + } + return $users; + } + + protected function writeRecaptcha() + { + if ($this->fluidbookSettings->recaptcha) { + $this->beginBody[] = ''; + } + } + + protected function writeSecurePage() + { + $variables = [ + 'TITLE' => $this->fluidbookSettings->title, + 'FORM_TITLE' => $this->fluidbookSettings->secureClientSideTitle ?: $this->fluidbookSettings->title, + 'FORM_TEXT' => $this->fluidbookSettings->secureClientSideText, + 'LINKS' => '', + ]; + $users = $this->_getSecureUsers(); + + if ($this->fluidbookSettings->secureClientSidePassword) { + $secure = file_get_contents($this->wdir . '/' . $this->fluidbookSettings->secureClientSidePassword); + } else { + $secure = file_get_contents($this->assets . '/_secure.html'); + } + if ($this->fluidbookSettings->secureClientSideBackgroundImage) { + $this->vdir->copy($this->wdir . '/' . $this->fluidbookSettings->secureClientSideBackgroundImage, 'data/secure/' . $this->fluidbookSettings->secureClientSideBackgroundImage); + $variables['BACKGROUND_IMAGE'] = 'data/secure/' . $this->fluidbookSettings->secureClientSideBackgroundImage; + } else if ($backgroundImage = $this->themeAsset('backgroundImage')) { + $variables['BACKGROUND_IMAGE'] = 'data/images/' . $backgroundImage->getFilename(); + } else { + $variables['BACKGROUND_IMAGE'] = 'data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw=='; + } + if ($this->fluidbookSettings->secureClientSideLogo) { + $this->vdir->copy($this->wdir . '/' . $this->fluidbookSettings->secureClientSideLogo, 'data/secure/' . $this->fluidbookSettings->secureClientSideLogo); + $variables['LOGO'] = 'data/secure/' . $this->fluidbookSettings->secureClientSideLogo; + } else if ($logoLoader = $this->themeAsset('logoLoader')) { + $variables['LOGO'] = 'data/images/' . $logoLoader->getFilename(); + } else { + $variables['LOGO'] = 'data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw=='; + } + $variables['CREDENTIALS'] = 'var CREDENTIALS=' . json_encode($users) . ';'; + + + $l10n = $this->getFluidbook()->getTranslations(); + + $locale = $this->fluidbookSettings->secureClientSideLocale === 'fluidbook' ? $l10n['default'] : $l10n[$this->fluidbookSettings->secureClientSideLocale]; + $variables['FORM_USERNAME'] = $locale['Username'] ?? 'Username'; + $variables['FORM_PASSWORD'] = $locale['Password'] ?? 'Password'; + $variables['FORM_SIGN_IN'] = $locale['Sign in'] ?? 'Sign in'; + $variables['CODE'] = '$(function () { + $(\'form\').on(\'submit\', function () { + var u = $("#username").val(); + var p = $("#password").val(); + var error = true; + $.each(CREDENTIALS, function (user, data) { + if (forge_sha256(data.usersalt + \'+\' + u) === user && forge_sha256(data.salt + \'-\' + p) === data.hash) { + error = false; + window.sessionStorage.setItem(\'secureUsername\', u); + window.sessionStorage.setItem(\'securePassword\', p); + window.location = \'index.html\'; + } + }); + if (error) { + $("#message").text(\'' . addcslashes($locale['Wrong username or password'] ?? 'Wrong username or password', "'") . '\'); + } + return false; + }); + });'; + $variables['CSS'] = $this->fluidbookSettings->secureClientSideStyles; + + $this->addFontKit($this->fluidbookSettings->secureClientSideFont); + $variables['FONT'] = $this->fluidbookSettings->secureClientSideFont; + $variables['LINKS'] .= ''; + + + foreach ($variables as $variable => $value) { + $secure = str_replace('$' . $variable, $value, $secure); + } + + $this->vdir->file_put_contents('secure.html', $secure); + $this->config->secureClientSidePasswordCredentials = $users; + $this->config->secureClientSideEnabled = true; + } +} diff --git a/app/Models/FluidbookPublication.php b/app/Models/FluidbookPublication.php index af9129584..fb10edc20 100644 --- a/app/Models/FluidbookPublication.php +++ b/app/Models/FluidbookPublication.php @@ -847,4 +847,11 @@ class FluidbookPublication extends ToolboxSettingsModel { return route('fluidbook_preview', ['version' => 'online', 'id' => $this->id, 'hash' => $this->hash]); } + + public function getTranslations() + { + $l10n = FluidbookTranslate::getCompiledTranslations(); + $l10n['default'] = $this->getDefaultTranslations($l10n); + return $l10n; + } } diff --git a/app/Models/FluidbookTheme.php b/app/Models/FluidbookTheme.php index 772020f5f..fba9f2629 100644 --- a/app/Models/FluidbookTheme.php +++ b/app/Models/FluidbookTheme.php @@ -3,6 +3,7 @@ namespace App\Models; +use App\Fields\FluidbookFont; use App\Fields\FluidbookThemeImage; use App\Http\Controllers\Admin\Operations\ChangeownerOperation; use App\Jobs\GenerateThemePreview; @@ -81,13 +82,7 @@ class FluidbookTheme extends ToolboxSettingsModel ]); $this->addField(['name' => 'interfaceFont', - 'type' => 'SelectFromArray', - 'options' => [ - 'OpenSans' => 'Open Sans (' . __('défaut') . ')', - 'Montserrat' => 'Montserrat', - 'Arial' => 'Arial, Helvetica, sans-serif (' . __('police système') . ')', - 'sans-serif' => __('Police système sans-serif')] - , + 'type'=>FluidbookFont::class, 'default' => 'OpenSans', 'label' => __('Police de caractères'), 'translatable' => false, diff --git a/app/Models/Traits/PublicationSettings.php b/app/Models/Traits/PublicationSettings.php index 13956839e..17a25d202 100644 --- a/app/Models/Traits/PublicationSettings.php +++ b/app/Models/Traits/PublicationSettings.php @@ -3,6 +3,9 @@ namespace App\Models\Traits; use App\Fields\FluidbookDevelopmentVersion; +use App\Fields\FluidbookFont; +use App\Fields\FluidbookLocale; +use App\Fields\FluidbookLocaleCurrent; use App\Fields\FluidbookSignature; use App\Fields\FluidbookTTSVoice; use App\Fields\SCORMVersion; @@ -44,6 +47,7 @@ trait PublicationSettings protected static $acceptProductList = ['.xml', '.xlsx']; protected static $acceptPDF = ['.pdf']; protected static $acceptZip = ['.zip']; + protected static $acceptFont = ['.ttf', '.otf', '.woff', '.woff2']; public function setSettingsFields() @@ -58,6 +62,7 @@ trait PublicationSettings $this->_stats(); $this->_accessibility(); $this->_elearning(); + $this->_secure(); $this->_advanced(); stop_measure('set settings fields'); } @@ -134,7 +139,6 @@ trait PublicationSettings $this->addSettingField('bigsection_package', FormSuperSection::class, $this->__('Packages & Téléchargements')); $this->_seo(); $this->_multibrochure(); - $this->_secure(); $this->_package(); $this->_offline(); $this->_export(); @@ -1744,10 +1748,41 @@ trait PublicationSettings protected function _secure() { - $this->addSettingField('section_secure', FormSection::class, $this->__('Sécurisation')); + $this->addSettingField('bigsection_secure', FormSuperSection::class, $this->__('Sécurisation')); + $this->_secureURL(); + $this->_securePage(); + $this->_secureRestrictions(); + $this->_secureOther(); + } + + protected function _securePage() + { + $this->addSettingField('section_securepage', FormSection::class, $this->__('Sécurisation par une page de login')); + $this->addSettingField('secureClientSidePassword', FilesOrURL::class, __('Template HTML'), [ + 'v2' => '{"type":"freefile","label":"S\\u00e9curisation par mot de passe c\\u00f4t\\u00e9 client","editable":true,"default":"","grade":3,"fileFilter":{"name":"\\u00a7!\\u00a7Fichier HTML!\\u00a7! (*.html)","extensions":"*.html"}}', + 'accept' => self::$acceptHTML, + 'hint' => __('Laisser vide pour utiliser le template par défaut'), + ]); + $this->addSettingField('secureClientSidePasswordCredentials', Textarea::class, 'Utilisateurs / mots de passe', [ + 'v2' => '{"type":"textarea","label":"Utilisateurs \\/ mots de passe","editable":true,"default":"","grade":3,"hint":"Format user:password par ligne"}', + 'hint' => __('Format user:password par ligne'), + ]); + $this->addSettingField('secureClientSideBackgroundImage', FilesOrURL::class, __('Image de fond'), ['accept' => self::$acceptImages, __('Laisser vide pour utiliser le fond du fluidbook')]); + $this->addSettingField('secureClientSideFont', FluidbookFont::class, __('Police'), ['default' => 'OpenSans']); + $this->addSettingField('secureClientSideLogo', FilesOrURL::class, __('Logo'), ['accept' => self::$acceptImages, 'hint' => __('Laisser vide pour utiliser le logo du loader')]); + $this->addSettingField('secureClientSideTitle', Textarea::class, __('Titre du formulaire de login'), ['rows' => 2, 'hint' => __('Laisser vide pour utiliser le titre du fluidbook')]); + $this->addSettingField('secureClientSideText', Textarea::class, __('Texte du formulaire de login'), ['rows' => 3]); + $this->addSettingField('secureClientSideLocale', FluidbookLocaleCurrent::class, __('Langue du formulaire'), ['default' => 'fluidbook']); + $this->addSettingField('secureClientSideStyles', Code::class, __('Styles additionnels'), ['default' => '', 'language' => 'css']); + + } + + protected function _secureURL() + { + $this->addSettingField('section_secure_url', FormSection::class, $this->__('Sécurisation par URL')); $this->addSettingField('secureURL', LongText::class, $this->__('URL de sécurisation'), [ 'v2' => '{"type":"text","default":"http:\\/\\/","editable":true,"label":"\\u00a7!\\u00a7URL de s\\u00e9curisation!\\u00a7!","grade":5,"hint":"\\u00a7!\\u00a7URL int\\u00e9rrog\\u00e9 pour v\\u00e9rifier si le visiteur \\u00e0 les droits pour consulter la publication!\\u00a7!"}', - 'hint' => $this->__('URL interrogée pour vérifier si le visiteur à les droits pour consulter la publication'), + 'hint' => $this->__('URL interrogée pour vérifier si le visiteur à les droits pour consulter la publication') . ' ' . __('Le fluidbook et l\'url doivent être sur le même domaine'), 'default' => 'http://', ]); $this->addSettingField('secureURLRedirect', LongText::class, $this->__('Redirection'), [ @@ -1755,21 +1790,12 @@ trait PublicationSettings 'hint' => $this->__('Si l\'authentification échoue, redirection vers cette adresse'), 'default' => 'http://', ]); - $this->addSettingField('', FormSeparator::class); - $this->addSettingField('secureClientSidePassword', FilesOrURL::class, 'Sécurisation par mot de passe côté client', [ - 'v2' => '{"type":"freefile","label":"S\\u00e9curisation par mot de passe c\\u00f4t\\u00e9 client","editable":true,"default":"","grade":3,"fileFilter":{"name":"\\u00a7!\\u00a7Fichier HTML!\\u00a7! (*.html)","extensions":"*.html"}}', - 'accept' => self::$acceptHTML, - ]); - $this->addSettingField('secureClientSidePasswordCredentials', Textarea::class, 'Utilisateurs / mots de passe', [ - 'v2' => '{"type":"textarea","label":"Utilisateurs \\/ mots de passe","editable":true,"default":"","grade":3,"hint":"Format user:password par ligne"}', - 'hint' => 'Format user:password par ligne', - ]); - $this->addSettingField('', FormSeparator::class); - $this->addSettingField('preventRightClick', Checkbox::class, $this->__('Essayer d\'empêcher le clic droit'), [ - 'v2' => '{"type":"boolean","default":false,"editable":true,"label":"\\u00a7!\\u00a7Essayer d\'emp\\u00eacher le clic droit!\\u00a7!","grade":1}', - 'default' => false, - ]); - $this->addSettingField('', FormSeparator::class); + } + + protected function _secureRestrictions() + { + + $this->addSettingField('section_secure_restrictions', FormSection::class, $this->__('Restrictions')); $this->addSettingField('restrictPrintDownload', LongText::class, $this->__('Paramètre de l\'url permettant de désactiver la restriction (non vide pour activer les restrictions)'), [ 'v2' => '{"type":"text","default":"","editable":true,"label":"\\u00a7!\\u00a7Param\\u00e8tre de l\'url permettant de d\\u00e9sactiver la restriction (non vide pour activer les restrictions)!\\u00a7!","grade":5,"hint":"\\u00a7!\\u00a7Ne pas indiquer le ?!\\u00a7!"}', 'hint' => $this->__('Ne pas indiquer le ?'), @@ -1786,10 +1812,18 @@ trait PublicationSettings 'v2' => '{"type":"boolean","default":false,"editable":true,"label":"\\u00a7!\\u00a7Restreindre l\'envoi de marques-pages!\\u00a7!","grade":5}', 'default' => false, ]); - $this->addSettingField('', FormSeparator::class); + } + + protected function _secureOther() + { + $this->addSettingField('section_secure_other', FormSection::class, $this->__('Autres options de sécurisation')); $this->addSettingField('recaptcha', LongText::class, $this->__('Activer reCATPCHA v3 (clé du site)'), [ 'v2' => '{"type":"text","default":"","editable":true,"label":"\\u00a7!\\u00a7Activer reCATPCHA v3 (cl\\u00e9 du site)!\\u00a7!"}', ]); + $this->addSettingField('preventRightClick', Checkbox::class, $this->__('Essayer d\'empêcher le clic droit'), [ + 'v2' => '{"type":"boolean","default":false,"editable":true,"label":"\\u00a7!\\u00a7Essayer d\'emp\\u00eacher le clic droit!\\u00a7!","grade":1}', + 'default' => false, + ]); } protected function _multibrochure() -- 2.39.5