Fred Tempez
751bc450b5
** Corrections :** - L'ajout d'un slash en fin d'adresse avec la réécriture active provoquait une mauvaise détermination des adresses des images dans TinyMCE. Résolution : une directive htaccess supprime tous les slash en fin d'adresse. - Lorsque la page est ouverte en édition, un clic sur le bouton édition dans la barre d'administration affiche une erreur, le lien étant incorrect. Afin d'éviter cette erreur et une redondance, le bouton d'édition est masqué lorsque la page est éditée.
966 lines
32 KiB
PHP
966 lines
32 KiB
PHP
<?php
|
|
|
|
/**
|
|
* This file is part of Zwii.
|
|
*
|
|
* For full copyright and license information, please see the LICENSE
|
|
* file that was distributed with this source code.
|
|
*
|
|
* @author Rémi Jean <remi.jean@outlook.com>
|
|
* @copyright Copyright (C) 2008-2018, Rémi Jean
|
|
* @author Frédéric Tempez <frederic.tempez@outlook.com>
|
|
* @copyright Copyright (C) 2018-2024, Frédéric Tempez
|
|
* @license CC Attribution-NonCommercial-NoDerivatives 4.0 International
|
|
* @link http://zwiicms.fr/
|
|
*/
|
|
|
|
class config extends common
|
|
{
|
|
|
|
public static $actions = [
|
|
'backup' => self::GROUP_ADMIN,
|
|
'copyBackups' => self::GROUP_ADMIN,
|
|
'delBackups' => self::GROUP_ADMIN,
|
|
'configMetaImage' => self::GROUP_ADMIN,
|
|
'siteMap' => self::GROUP_ADMIN,
|
|
'index' => self::GROUP_ADMIN,
|
|
'restore' => self::GROUP_ADMIN,
|
|
'updateBaseUrl' => self::GROUP_ADMIN,
|
|
'script' => self::GROUP_ADMIN,
|
|
'logReset' => self::GROUP_ADMIN,
|
|
'logDownload' => self::GROUP_ADMIN,
|
|
'blacklistReset' => self::GROUP_ADMIN,
|
|
'blacklistDownload' => self::GROUP_ADMIN
|
|
];
|
|
|
|
public static $timezones = [
|
|
'Pacific/Midway' => '(GMT-11:00) Midway Island',
|
|
'US/Samoa' => '(GMT-11:00) Samoa',
|
|
'US/Hawaii' => '(GMT-10:00) Hawaii',
|
|
'US/Alaska' => '(GMT-09:00) Alaska',
|
|
'US/Pacific' => '(GMT-08:00) Pacific Time (US & Canada)',
|
|
'America/Tijuana' => '(GMT-08:00) Tijuana',
|
|
'US/Arizona' => '(GMT-07:00) Arizona',
|
|
'US/Mountain' => '(GMT-07:00) Mountain Time (US & Canada)',
|
|
'America/Chihuahua' => '(GMT-07:00) Chihuahua',
|
|
'America/Mazatlan' => '(GMT-07:00) Mazatlan',
|
|
'America/Mexico_City' => '(GMT-06:00) Mexico City',
|
|
'America/Monterrey' => '(GMT-06:00) Monterrey',
|
|
'Canada/Saskatchewan' => '(GMT-06:00) Saskatchewan',
|
|
'US/Central' => '(GMT-06:00) Central Time (US & Canada)',
|
|
'US/Eastern' => '(GMT-05:00) Eastern Time (US & Canada)',
|
|
'US/East-Indiana' => '(GMT-05:00) Indiana (East)',
|
|
'America/Bogota' => '(GMT-05:00) Bogota',
|
|
'America/Lima' => '(GMT-05:00) Lima',
|
|
'America/Caracas' => '(GMT-04:30) Caracas',
|
|
'Canada/Atlantic' => '(GMT-04:00) Atlantic Time (Canada)',
|
|
'America/La_Paz' => '(GMT-04:00) La Paz',
|
|
'America/Santiago' => '(GMT-04:00) Santiago',
|
|
'Canada/Newfoundland' => '(GMT-03:30) Newfoundland',
|
|
'America/Buenos_Aires' => '(GMT-03:00) Buenos Aires',
|
|
'Greenland' => '(GMT-03:00) Greenland',
|
|
'Atlantic/Stanley' => '(GMT-02:00) Stanley',
|
|
'Atlantic/Azores' => '(GMT-01:00) Azores',
|
|
'Atlantic/Cape_Verde' => '(GMT-01:00) Cape Verde Is.',
|
|
'Africa/Casablanca' => '(GMT) Casablanca',
|
|
'Europe/Dublin' => '(GMT) Dublin',
|
|
'Europe/Lisbon' => '(GMT) Lisbon',
|
|
'Europe/London' => '(GMT) London',
|
|
'Africa/Monrovia' => '(GMT) Monrovia',
|
|
'Europe/Amsterdam' => '(GMT+01:00) Amsterdam',
|
|
'Europe/Belgrade' => '(GMT+01:00) Belgrade',
|
|
'Europe/Berlin' => '(GMT+01:00) Berlin',
|
|
'Europe/Bratislava' => '(GMT+01:00) Bratislava',
|
|
'Europe/Brussels' => '(GMT+01:00) Brussels',
|
|
'Europe/Budapest' => '(GMT+01:00) Budapest',
|
|
'Europe/Copenhagen' => '(GMT+01:00) Copenhagen',
|
|
'Europe/Ljubljana' => '(GMT+01:00) Ljubljana',
|
|
'Europe/Madrid' => '(GMT+01:00) Madrid',
|
|
'Europe/Paris' => '(GMT+01:00) Paris',
|
|
'Europe/Prague' => '(GMT+01:00) Prague',
|
|
'Europe/Rome' => '(GMT+01:00) Rome',
|
|
'Europe/Sarajevo' => '(GMT+01:00) Sarajevo',
|
|
'Europe/Skopje' => '(GMT+01:00) Skopje',
|
|
'Europe/Stockholm' => '(GMT+01:00) Stockholm',
|
|
'Europe/Vienna' => '(GMT+01:00) Vienna',
|
|
'Europe/Warsaw' => '(GMT+01:00) Warsaw',
|
|
'Europe/Zagreb' => '(GMT+01:00) Zagreb',
|
|
'Europe/Athens' => '(GMT+02:00) Athens',
|
|
'Europe/Bucharest' => '(GMT+02:00) Bucharest',
|
|
'Africa/Cairo' => '(GMT+02:00) Cairo',
|
|
'Africa/Harare' => '(GMT+02:00) Harare',
|
|
'Europe/Helsinki' => '(GMT+02:00) Helsinki',
|
|
'Europe/Istanbul' => '(GMT+02:00) Istanbul',
|
|
'Asia/Jerusalem' => '(GMT+02:00) Jerusalem',
|
|
'Europe/Kiev' => '(GMT+02:00) Kyiv',
|
|
'Europe/Minsk' => '(GMT+02:00) Minsk',
|
|
'Europe/Riga' => '(GMT+02:00) Riga',
|
|
'Europe/Sofia' => '(GMT+02:00) Sofia',
|
|
'Europe/Tallinn' => '(GMT+02:00) Tallinn',
|
|
'Europe/Vilnius' => '(GMT+02:00) Vilnius',
|
|
'Asia/Baghdad' => '(GMT+03:00) Baghdad',
|
|
'Asia/Kuwait' => '(GMT+03:00) Kuwait',
|
|
'Europe/Moscow' => '(GMT+03:00) Moscow',
|
|
'Africa/Nairobi' => '(GMT+03:00) Nairobi',
|
|
'Asia/Riyadh' => '(GMT+03:00) Riyadh',
|
|
'Europe/Volgograd' => '(GMT+03:00) Volgograd',
|
|
'Asia/Tehran' => '(GMT+03:30) Tehran',
|
|
'Asia/Baku' => '(GMT+04:00) Baku',
|
|
'Asia/Muscat' => '(GMT+04:00) Muscat',
|
|
'Asia/Tbilisi' => '(GMT+04:00) Tbilisi',
|
|
'Asia/Yerevan' => '(GMT+04:00) Yerevan',
|
|
'Asia/Kabul' => '(GMT+04:30) Kabul',
|
|
'Asia/Yekaterinburg' => '(GMT+05:00) Ekaterinburg',
|
|
'Asia/Karachi' => '(GMT+05:00) Karachi',
|
|
'Asia/Tashkent' => '(GMT+05:00) Tashkent',
|
|
'Asia/Kolkata' => '(GMT+05:30) Kolkata',
|
|
'Asia/Kathmandu' => '(GMT+05:45) Kathmandu',
|
|
'Asia/Almaty' => '(GMT+06:00) Almaty',
|
|
'Asia/Dhaka' => '(GMT+06:00) Dhaka',
|
|
'Asia/Novosibirsk' => '(GMT+06:00) Novosibirsk',
|
|
'Asia/Bangkok' => '(GMT+07:00) Bangkok',
|
|
'Asia/Jakarta' => '(GMT+07:00) Jakarta',
|
|
'Asia/Krasnoyarsk' => '(GMT+07:00) Krasnoyarsk',
|
|
'Asia/Chongqing' => '(GMT+08:00) Chongqing',
|
|
'Asia/Hong_Kong' => '(GMT+08:00) Hong Kong',
|
|
'Asia/Irkutsk' => '(GMT+08:00) Irkutsk',
|
|
'Asia/Kuala_Lumpur' => '(GMT+08:00) Kuala Lumpur',
|
|
'Australia/Perth' => '(GMT+08:00) Perth',
|
|
'Asia/Singapore' => '(GMT+08:00) Singapore',
|
|
'Asia/Taipei' => '(GMT+08:00) Taipei',
|
|
'Asia/Ulaanbaatar' => '(GMT+08:00) Ulaan Bataar',
|
|
'Asia/Urumqi' => '(GMT+08:00) Urumqi',
|
|
'Asia/Seoul' => '(GMT+09:00) Seoul',
|
|
'Asia/Tokyo' => '(GMT+09:00) Tokyo',
|
|
'Asia/Yakutsk' => '(GMT+09:00) Yakutsk',
|
|
'Australia/Adelaide' => '(GMT+09:30) Adelaide',
|
|
'Australia/Darwin' => '(GMT+09:30) Darwin',
|
|
'Australia/Brisbane' => '(GMT+10:00) Brisbane',
|
|
'Australia/Canberra' => '(GMT+10:00) Canberra',
|
|
'Pacific/Guam' => '(GMT+10:00) Guam',
|
|
'Australia/Hobart' => '(GMT+10:00) Hobart',
|
|
'Australia/Melbourne' => '(GMT+10:00) Melbourne',
|
|
'Pacific/Port_Moresby' => '(GMT+10:00) Port Moresby',
|
|
'Australia/Sydney' => '(GMT+10:00) Sydney',
|
|
'Asia/Vladivostok' => '(GMT+10:00) Vladivostok',
|
|
'Asia/Magadan' => '(GMT+11:00) Magadan',
|
|
'Pacific/Auckland' => '(GMT+12:00) Auckland',
|
|
'Pacific/Fiji' => '(GMT+12:00) Fiji',
|
|
'Asia/Kamchatka' => '(GMT+12:00) Kamchatka'
|
|
];
|
|
// Type de proxy
|
|
public static $proxyType = [
|
|
'tcp://' => 'TCP',
|
|
'http://' => 'HTTP'
|
|
];
|
|
// Authentification SMTP
|
|
public static $SMTPauth = [
|
|
true => 'Oui',
|
|
false => 'Non'
|
|
];
|
|
// Encryptation SMTP
|
|
public static $SMTPEnc = [
|
|
'' => 'Aucune',
|
|
'tls' => 'START TLS',
|
|
'ssl' => 'SSL/TLS'
|
|
];
|
|
// Sécurité de la connexion - tentative max avant blocage
|
|
public static $connectAttempt = [
|
|
999 => 'Sécurité désactivée',
|
|
3 => '3 tentatives',
|
|
5 => '5 tentatives',
|
|
10 => '10 tentatives'
|
|
];
|
|
// Sécurité de la connexion - durée du blocage
|
|
public static $connectTimeout = [
|
|
0 => 'Sécurité désactivée',
|
|
300 => '5 minutes',
|
|
600 => '10 minutes',
|
|
900 => '15 minutes'
|
|
];
|
|
// Anonymisation des IP du journal
|
|
public static $anonIP = [
|
|
4 => 'Non tronquée',
|
|
3 => 'Niveau 1 (192.168.12.x)',
|
|
2 => 'Niveau 2 (192.168.x.x)',
|
|
1 => 'Niveau 3 (192.x.x.x)',
|
|
];
|
|
public static $captchaTypes = [
|
|
'num' => 'Chiffres',
|
|
'alpha' => 'Lettres'
|
|
];
|
|
public static $updateDelay = [
|
|
86400 => '1',
|
|
172800 => '2',
|
|
345600 => '4',
|
|
604800 => '7',
|
|
1209600 => '14',
|
|
];
|
|
|
|
// Langue traduite courante
|
|
public static $i18nSite = 'fr_FR';
|
|
|
|
// Variable pour construire la liste des pages du site
|
|
public static $onlineVersion = '';
|
|
public static $updateButtonText = 'Réinstaller';
|
|
|
|
public static $imageOpenGraph = [];
|
|
public static $pagesList = [];
|
|
public static $orphansList = [];
|
|
|
|
/**
|
|
* Génére les fichiers pour les crawlers
|
|
* Sitemap compressé et non compressé
|
|
* Robots.txt
|
|
*/
|
|
public function siteMap()
|
|
{
|
|
// La page n'existe pas
|
|
if (
|
|
$this->getUser('permission', __CLASS__, __FUNCTION__) !== true
|
|
) {
|
|
// Valeurs en sortie
|
|
$this->addOutput([
|
|
'access' => false
|
|
]);
|
|
} else {
|
|
// Mettre à jour le site map
|
|
$successSitemap = $this->updateSitemap();
|
|
|
|
// Valeurs en sortie
|
|
$this->addOutput([
|
|
'redirect' => helper::baseUrl() . 'config',
|
|
'notification' => $successSitemap ? helper::translate('La carte du site a été mise à jour') : helper::translate('Echec de l\'écriture, vérifiez les permissions'),
|
|
'state' => $successSitemap
|
|
]);
|
|
}
|
|
|
|
}
|
|
|
|
|
|
/**
|
|
* Sauvegarde des données
|
|
*/
|
|
public function backup()
|
|
{
|
|
// Soumission du formulaire
|
|
if (
|
|
$this->getUser('permission', __CLASS__, __FUNCTION__) === true &&
|
|
$this->isPost()
|
|
) {
|
|
// Creation du ZIP
|
|
$filter = $this->getInput('configBackupOption', helper::FILTER_BOOLEAN) === true ? ['backup', 'tmp'] : ['backup', 'tmp', 'file'];
|
|
$fileName = helper::autoBackup(self::TEMP_DIR, $filter);
|
|
// Créer le répertoire manquant
|
|
if (!is_dir(self::FILE_DIR . 'source/backup')) {
|
|
mkdir(self::FILE_DIR . 'source/backup', 0755);
|
|
}
|
|
// Copie dans les fichiers
|
|
$success = copy(self::TEMP_DIR . $fileName, self::FILE_DIR . 'source/backup/' . $fileName);
|
|
// Détruire le temporaire
|
|
unlink(self::TEMP_DIR . $fileName);
|
|
// Valeurs en sortie
|
|
$this->addOutput([
|
|
'display' => self::DISPLAY_JSON,
|
|
'content' => json_encode($success)
|
|
]);
|
|
} else {
|
|
// Valeurs en sortie
|
|
$this->addOutput([
|
|
'title' => helper::translate('Sauvegarder'),
|
|
'view' => 'backup'
|
|
]);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Réalise une copie d'écran du site
|
|
*/
|
|
public function configMetaImage()
|
|
{
|
|
// fonction désactivée pour un site local
|
|
if (strpos(helper::baseUrl(false), 'localhost') > 0 or strpos(helper::baseUrl(false), '127.0.0.1') > 0) {
|
|
$site = 'https://zwiicms.fr/';
|
|
} else {
|
|
$site = helper::baseUrl(false);
|
|
}
|
|
|
|
// Clé de l'API
|
|
$token = $this->getData(['config', 'seo', 'keyApi']);
|
|
|
|
// Succès de l'opération par défaut
|
|
$success = false;
|
|
$data = false;
|
|
|
|
// lire l'API si le token est fourni
|
|
if (!empty($token)) {
|
|
// Tente de connecter 5 fois l'API
|
|
for ($i = 0; $i < 5; $i++) {
|
|
$data = helper::getUrlContents('https://shot.screenshotapi.net/screenshot?token=' . $token . '&url=' . $site . '&width=1200&height=627&output=json&file_type=jpeg&no_cookie_banners=true&wait_for_event=load');
|
|
if ($data !== false) {
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Traitement des données reçues valides.
|
|
if (!empty($token) && $data !== false) {
|
|
$data = json_decode($data, true);
|
|
$img = $data['screenshot'];
|
|
// Effacer l'image et la miniature png
|
|
if (file_exists(self::FILE_DIR . 'thumb/screenshot.jpg')) {
|
|
unlink(self::FILE_DIR . 'thumb/screenshot.jpg');
|
|
}
|
|
if (file_exists(self::FILE_DIR . 'source/screenshot.jpg')) {
|
|
unlink(self::FILE_DIR . 'source/screenshot.jpg');
|
|
}
|
|
$success = copy($img, self::FILE_DIR . 'source/screenshot.jpg');
|
|
}
|
|
|
|
$notification = empty($token)
|
|
? 'La clé de l\'API ne peut pas être vide'
|
|
: ($success === false ? 'Service en ligne inaccessible' : 'Capture d\'écran générée avec succès');
|
|
|
|
// Valeurs en sortie
|
|
$this->addOutput([
|
|
'redirect' => helper::baseUrl() . 'config',
|
|
'notification' => helper::translate($notification),
|
|
'state' => ($success === false or empty($token)) ? false : true
|
|
]);
|
|
}
|
|
|
|
/**
|
|
* Procédure d'importation
|
|
*/
|
|
public function restore()
|
|
{
|
|
// Soumission du formulaire
|
|
if (
|
|
$this->getUser('permission', __CLASS__, __FUNCTION__) === true &&
|
|
$this->isPost()
|
|
) {
|
|
|
|
$success = false;
|
|
|
|
if ($this->getInput('configRestoreImportFile', null, true)) {
|
|
|
|
$fileZip = $this->getInput('configRestoreImportFile');
|
|
$file_parts = pathinfo($fileZip);
|
|
// Validité du nom du fichier sélectionné
|
|
if ($file_parts['extension'] !== 'zip') {
|
|
// Valeurs en sortie erreur
|
|
$this->addOutput([
|
|
'title' => helper::translate('Restaurer'),
|
|
'view' => 'restore',
|
|
'notification' => helper::translate('Archive invalide'),
|
|
'state' => false
|
|
]);
|
|
}
|
|
// Ouverture de l'archive
|
|
$zip = new ZipArchive();
|
|
if ($zip->open(self::FILE_DIR . 'source/' . $fileZip) === FALSE) {
|
|
// Valeurs en sortie erreur
|
|
$this->addOutput([
|
|
'title' => helper::translate('Restaurer'),
|
|
'view' => 'restore',
|
|
'notification' => helper::translate('Archive invalide'),
|
|
'state' => false
|
|
]);
|
|
}
|
|
|
|
// Extraction de l'archive dans un dossier temporaire
|
|
$tmpDir = uniqid(8);
|
|
$success = $zip->extractTo(self::TEMP_DIR . $tmpDir);
|
|
// Version de l'archive
|
|
$data = json_decode(file_get_contents(self::TEMP_DIR . $tmpDir . '/data/core.json'), true);
|
|
$dataVersion = $data['core']['dataVersion'];
|
|
// Version non prises en charge <9 ou erreur d'extraction
|
|
if (intval(substr($dataVersion, 0, 1)) <= 9 or !$success) {
|
|
// Valeurs en sortie erreur
|
|
$this->addOutput([
|
|
'title' => helper::translate('Restaurer'),
|
|
'view' => 'restore',
|
|
'notification' => helper::translate('Archive invalide'),
|
|
'state' => false
|
|
]);
|
|
}
|
|
|
|
// Fermer le zip
|
|
$zip->close();
|
|
|
|
// Option active, préservation des utilisateurs
|
|
if ($this->getInput('configRestoreImportUser', helper::FILTER_BOOLEAN) === true) {
|
|
$users = $this->getData(['user']);
|
|
}
|
|
|
|
// Copie dans le dossier /site/data
|
|
$success = $this->copyDir(self::TEMP_DIR . $tmpDir, 'site/');
|
|
$this->deleteDir(self::TEMP_DIR . $tmpDir);
|
|
|
|
// Restaurer les users originaux d'une v10 si option cochée
|
|
if (
|
|
$this->getInput('configRestoreImportUser', helper::FILTER_BOOLEAN) === true
|
|
) {
|
|
$this->setData(['user', $users]);
|
|
}
|
|
}
|
|
|
|
// Message de notification
|
|
$notification = $success === true ? 'Restauration effectuée avec succès' : 'Erreur inconnue';
|
|
$redirect = $this->getInput('configRestoreImportUser', helper::FILTER_BOOLEAN) === true ? helper::baseUrl() . 'config/restore' : helper::baseUrl() . 'user/login/';
|
|
// Valeurs en sortie erreur
|
|
$this->addOutput([
|
|
'redirect' => $redirect,
|
|
'notification' => helper::translate($notification),
|
|
'state' => $success
|
|
]);
|
|
}
|
|
|
|
// Valeurs en sortie
|
|
$this->addOutput([
|
|
'title' => helper::translate('Restaurer'),
|
|
'view' => 'restore'
|
|
]);
|
|
}
|
|
|
|
|
|
/**
|
|
* Configuration
|
|
*/
|
|
public function index()
|
|
{
|
|
|
|
// Action interdite hors de l'espace accueil
|
|
if (
|
|
self::$siteContent !== 'home'
|
|
) {
|
|
// Valeurs en sortie
|
|
$this->addOutput([
|
|
'access' => false
|
|
]);
|
|
}
|
|
|
|
// Soumission du formulaire
|
|
if (
|
|
$this->getUser('permission', __CLASS__, __FUNCTION__) === true &&
|
|
$this->isPost()
|
|
) {
|
|
|
|
// Basculement en mise à jour auto, remise à 0 du compteur
|
|
if (
|
|
$this->getData(['config', 'autoUpdate']) === false &&
|
|
$this->getInput('configAutoUpdate', helper::FILTER_BOOLEAN) === true
|
|
) {
|
|
$this->setData(['core', 'lastAutoUpdate', 0]);
|
|
}
|
|
|
|
// Sauvegarder la configuration
|
|
$this->setData([
|
|
'config',
|
|
[
|
|
'favicon' => $this->getInput('configFavicon'),
|
|
'faviconDark' => $this->getInput('configFaviconDark'),
|
|
'timezone' => $this->getInput('configTimezone', helper::FILTER_STRING_SHORT, true),
|
|
'autoUpdate' => $this->getInput('configAutoUpdate', helper::FILTER_BOOLEAN),
|
|
'autoUpdateHtaccess' => $this->getInput('configAutoUpdateHtaccess', helper::FILTER_BOOLEAN),
|
|
'autoBackup' => $this->getInput('configAutoBackup', helper::FILTER_BOOLEAN),
|
|
'maintenance' => $this->getInput('configMaintenance', helper::FILTER_BOOLEAN),
|
|
'cookieConsent' => $this->getInput('configCookieConsent', helper::FILTER_BOOLEAN),
|
|
'proxyType' => $this->getInput('configProxyType'),
|
|
'proxyUrl' => $this->getInput('configProxyUrl'),
|
|
'proxyPort' => $this->getInput('configProxyPort', helper::FILTER_INT),
|
|
'autoUpdateDelay' => $this->getInput('configAutoUpdateDelay', helper::FILTER_INT),
|
|
'homePageId' => $this->getInput('configLocaleHomePageId', helper::FILTER_ID, true),
|
|
'page404' => $this->getInput('configLocalePage404'),
|
|
'page403' => $this->getInput('configLocalePage403'),
|
|
'page302' => $this->getInput('configLocalePage302'),
|
|
'legalPageId' => $this->getInput('configLocaleLegalPageId'),
|
|
'searchPageId' => $this->getInput('configLocaleSearchPageId'),
|
|
'poweredPageLabel' => empty($this->getInput('configLocalePoweredPageLabel', helper::FILTER_STRING_SHORT)) ? 'Motorisé par' : $this->getInput('configLocalePoweredPageLabel', helper::FILTER_STRING_SHORT),
|
|
'searchPageLabel' => empty($this->getInput('configLocaleSearchPageLabel', helper::FILTER_STRING_SHORT)) ? 'Rechercher' : $this->getInput('configLocaleSearchPageLabel', helper::FILTER_STRING_SHORT),
|
|
'legalPageLabel' => empty($this->getInput('configLocaleLegalPageLabel', helper::FILTER_STRING_SHORT)) ? 'Mentions légales' : $this->getInput('configLocaleLegalPageLabel', helper::FILTER_STRING_SHORT),
|
|
'sitemapPageLabel' => empty($this->getInput('configLocaleSitemapPageLabel', helper::FILTER_STRING_SHORT)) ? 'Sommaire' : $this->getInput('configLocaleSitemapPageLabel', helper::FILTER_STRING_SHORT),
|
|
'metaDescription' => $this->getInput('configLocaleMetaDescription', helper::FILTER_STRING_LONG, true),
|
|
'title' => $this->getInput('configLocaleTitle', helper::FILTER_STRING_SHORT, true),
|
|
'cookies' => [
|
|
// Les champs sont obligatoires si l'option consentement des cookies est active
|
|
'mainLabel' => $this->getInput('configLocaleCookiesZwiiText', helper::FILTER_STRING_LONG, $this->getInput('configCookieConsent', helper::FILTER_BOOLEAN)),
|
|
'titleLabel' => $this->getInput('configLocaleCookiesTitleText', helper::FILTER_STRING_SHORT, $this->getInput('configCookieConsent', helper::FILTER_BOOLEAN)),
|
|
'linkLegalLabel' => $this->getInput('configLocaleCookiesLinkMlText', helper::FILTER_STRING_SHORT, $this->getInput('configCookieConsent', helper::FILTER_BOOLEAN)),
|
|
'cookiesFooterText' => $this->getInput('configLocaleCookiesFooterText', helper::FILTER_STRING_SHORT, $this->getInput('configCookieConsent', helper::FILTER_BOOLEAN)),
|
|
'buttonValidLabel' => $this->getInput('configLocaleCookiesButtonText', helper::FILTER_STRING_SHORT, $this->getInput('configCookieConsent', helper::FILTER_BOOLEAN)),
|
|
],
|
|
'social' => [
|
|
'facebookId' => $this->getInput('socialFacebookId'),
|
|
'linkedinId' => $this->getInput('socialLinkedinId'),
|
|
'instagramId' => $this->getInput('socialInstagramId'),
|
|
'pinterestId' => $this->getInput('socialPinterestId'),
|
|
'twitterId' => $this->getInput('socialTwitterId'),
|
|
'youtubeId' => $this->getInput('socialYoutubeId'),
|
|
'youtubeUserId' => $this->getInput('socialYoutubeUserId'),
|
|
'githubId' => $this->getInput('socialGithubId'),
|
|
'redditId' => $this->getInput('socialRedditId'),
|
|
'twitchId' => $this->getInput('socialTwitchId'),
|
|
'vimeoId' => $this->getInput('socialVimeoId'),
|
|
'steamId' => $this->getInput('socialSteamId'),
|
|
],
|
|
'smtp' => [
|
|
'enable' => $this->getInput('smtpEnable', helper::FILTER_BOOLEAN),
|
|
'host' => $this->getInput('smtpHost', helper::FILTER_STRING_SHORT),
|
|
'port' => $this->getInput('smtpPort', helper::FILTER_INT),
|
|
'auth' => $this->getInput('smtpAuth', helper::FILTER_BOOLEAN),
|
|
'secure' => $this->getInput('smtpSecure', helper::FILTER_STRING_SHORT),
|
|
'username' => $this->getInput('smtpUsername', helper::FILTER_STRING_SHORT),
|
|
'password' => helper::encrypt($this->getInput('smtpPassword', helper::FILTER_STRING_SHORT), $this->getInput('smtpHost', helper::FILTER_STRING_SHORT)),
|
|
'from' => $this->getInput('smtpFrom', helper::FILTER_MAIL, true),
|
|
],
|
|
'seo' => [
|
|
'robots' => $this->getInput('seoRobots', helper::FILTER_BOOLEAN),
|
|
'openGraphImage' => $this->getInput('seoOpenGraphImage', helper::FILTER_STRING_SHORT),
|
|
],
|
|
'connect' => [
|
|
'attempt' => $this->getInput('connectAttempt', helper::FILTER_INT),
|
|
'timeout' => $this->getInput('connectTimeout', helper::FILTER_INT),
|
|
'log' => $this->getInput('connectLog', helper::FILTER_BOOLEAN),
|
|
'anonymousIp' => $this->getInput('connectAnonymousIp', helper::FILTER_INT),
|
|
'captcha' => $this->getInput('connectCaptcha', helper::FILTER_BOOLEAN),
|
|
'captchaStrong' => $this->getInput('connectCaptchaStrong', helper::FILTER_BOOLEAN),
|
|
'autoDisconnect' => $this->getInput('connectAutoDisconnect', helper::FILTER_BOOLEAN),
|
|
'captchaType' => $this->getInput('connectCaptchaType'),
|
|
'showPassword' => $this->getInput('connectShowPassword', helper::FILTER_BOOLEAN),
|
|
'redirectLogin' => $this->getInput('connectRedirectLogin', helper::FILTER_BOOLEAN)
|
|
]
|
|
]
|
|
]);
|
|
|
|
// Efface les fichiers de backup lorsque l'option est désactivée
|
|
if ($this->getInput('configFileBackup', helper::FILTER_BOOLEAN) === false) {
|
|
$path = realpath('site/data');
|
|
foreach (new RecursiveIteratorIterator(new RecursiveDirectoryIterator($path)) as $filename) {
|
|
if (strpos($filename, 'backup.json')) {
|
|
unlink($filename);
|
|
}
|
|
}
|
|
if (file_exists('site/data/.backup'))
|
|
unlink('site/data/.backup');
|
|
} else {
|
|
touch('site/data/.backup');
|
|
}
|
|
// Notice
|
|
if (self::$inputNotices === []) {
|
|
// Active la réécriture d'URL
|
|
$rewrite = $this->getInput('configRewrite', helper::FILTER_BOOLEAN);
|
|
if (
|
|
$rewrite
|
|
and helper::checkRewrite() === false
|
|
) {
|
|
// Ajout des lignes dans le .htaccess
|
|
$fileContent = file_get_contents('.htaccess');
|
|
$rewriteData = PHP_EOL .
|
|
' # Enlever le slash final des URL' . PHP_EOL .
|
|
'RewriteCond %{REQUEST_FILENAME} !-f' . PHP_EOL .
|
|
'RewriteCond %{REQUEST_FILENAME} !-d' . PHP_EOL .
|
|
'RewriteCond %{REQUEST_URI} ^(.+)/$' . PHP_EOL .
|
|
'RewriteRule ^ %1 [R=301,L]' . PHP_EOL .
|
|
PHP_EOL .
|
|
'# URL rewriting' . PHP_EOL .
|
|
'<IfModule mod_rewrite.c>' . PHP_EOL .
|
|
"\tRewriteEngine on" . PHP_EOL .
|
|
"\tRewriteBase " . helper::baseUrl(false, false) . PHP_EOL .
|
|
"\tRewriteCond %{REQUEST_FILENAME} !-f" . PHP_EOL .
|
|
"\tRewriteCond %{REQUEST_FILENAME} !-d" . PHP_EOL .
|
|
"\tRewriteRule ^(.*)$ index.php?$1 [L]" . PHP_EOL .
|
|
'</IfModule>' . PHP_EOL .
|
|
'# URL rewriting' . PHP_EOL;
|
|
$fileContent = str_replace('# URL rewriting', $rewriteData, $fileContent);
|
|
file_put_contents(
|
|
'.htaccess',
|
|
$fileContent
|
|
);
|
|
// Change le statut de la réécriture d'URL (pour le helper::baseUrl() de la redirection)
|
|
helper::$rewriteStatus = true;
|
|
}
|
|
// Désactive la réécriture d'URL
|
|
elseif (
|
|
$rewrite === false
|
|
and helper::checkRewrite()
|
|
) {
|
|
// Suppression des lignes dans le .htaccess
|
|
$fileContent = file_get_contents('.htaccess');
|
|
$fileContent = explode('# URL rewriting', $fileContent);
|
|
$fileContent = $fileContent[0] . '# URL rewriting' . $fileContent[2];
|
|
file_put_contents(
|
|
'.htaccess',
|
|
$fileContent
|
|
);
|
|
// Change le statut de la réécriture d'URL (pour le helper::baseUrl() de la redirection)
|
|
helper::$rewriteStatus = false;
|
|
}
|
|
}
|
|
// Générer robots.txt et sitemap
|
|
$this->siteMap();
|
|
// Valeurs en sortie
|
|
$this->addOutput([
|
|
'title' => helper::translate('Configuration'),
|
|
'view' => 'index',
|
|
'notification' => helper::translate('Modifications enregistrées'),
|
|
'state' => true
|
|
]);
|
|
}
|
|
|
|
// Activation du bouton de mise à jour
|
|
if (
|
|
helper::checkNewVersion(common::ZWII_UPDATE_CHANNEL)
|
|
&& $this->getData(['core', 'updateAvailable']) === false
|
|
&& $this->getData(['config', 'autoUpdate'])
|
|
) {
|
|
$this->setData(['core', 'updateAvailable', true]);
|
|
// Valeurs en sortie
|
|
$this->addOutput([
|
|
'redirect' => helper::baseUrl() . 'config',
|
|
]);
|
|
|
|
}
|
|
|
|
// Variable de version
|
|
if (helper::checkNewVersion(common::ZWII_UPDATE_CHANNEL)) {
|
|
self::$updateButtonText = helper::translate('Mise à jour');
|
|
}
|
|
|
|
|
|
// Sélecteur de délais, compléter avec la traduction en jours
|
|
foreach (self::$updateDelay as $key => $value) {
|
|
self::$updateDelay[$key] = $key === 86400 ? $value . ' ' . helper::translate('jour') : $value . ' ' . helper::translate('jours');
|
|
}
|
|
|
|
// Paramètres de l'image OpenGraph
|
|
$imagePath = self::FILE_DIR . 'source/' . $this->getData(['config', 'seo', 'openGraphImage']);
|
|
|
|
// Par défaut
|
|
self::$imageOpenGraph['type'] = '';
|
|
self::$imageOpenGraph['size'] = '';
|
|
self::$imageOpenGraph['wide'] = '';
|
|
self::$imageOpenGraph['height'] = '';
|
|
self::$imageOpenGraph['ratio'] = 0;
|
|
if (
|
|
$this->getData(['config', 'seo', 'openGraphImage'])
|
|
&& file_exists($imagePath)
|
|
) {
|
|
// Infos sur l'image Open Graph
|
|
$typeMime = exif_imagetype($imagePath);
|
|
switch ($typeMime) {
|
|
case IMAGETYPE_JPEG:
|
|
$typeMime = 'jpeg';
|
|
break;
|
|
case IMAGETYPE_PNG:
|
|
$typeMime = 'png';
|
|
break;
|
|
default:
|
|
$typeMime = image_type_to_mime_type($typeMime);
|
|
}
|
|
self::$imageOpenGraph['type'] = $typeMime;
|
|
$imageSize = getimagesize($imagePath);
|
|
self::$imageOpenGraph['wide'] = $imageSize[0];
|
|
self::$imageOpenGraph['height'] = $imageSize[1];
|
|
self::$imageOpenGraph['ratio'] = self::$imageOpenGraph['wide'] / self::$imageOpenGraph['height'];
|
|
|
|
self::$imageOpenGraph['size'] = filesize($imagePath);
|
|
$tailleEnOctets = filesize($imagePath);
|
|
|
|
if ($tailleEnOctets >= 1024 * 1024) {
|
|
// Si la taille est supérieure ou égale à 1 Mo, afficher en mégaoctets
|
|
self::$imageOpenGraph['size'] = round($tailleEnOctets / (1024 * 1024), 2) . ' Mo';
|
|
} else {
|
|
// Sinon, afficher en kilooctets
|
|
self::$imageOpenGraph['size'] = round($tailleEnOctets / 1024, 2) . ' Ko';
|
|
}
|
|
}
|
|
|
|
// Générer la liste des pages disponibles
|
|
self::$pagesList = $this->getData(['page']);
|
|
foreach (self::$pagesList as $page => $pageId) {
|
|
if (
|
|
$this->getData(['page', $page, 'block']) === 'bar' ||
|
|
$this->getData(['page', $page, 'disable']) === true
|
|
) {
|
|
unset(self::$pagesList[$page]);
|
|
}
|
|
}
|
|
|
|
self::$orphansList = $this->getData(['page']);
|
|
foreach (self::$orphansList as $page => $pageId) {
|
|
if (
|
|
$this->getData(['page', $page, 'block']) === 'bar' ||
|
|
$this->getData(['page', $page, 'disable']) === true ||
|
|
$this->getdata(['page', $page, 'position']) !== 0
|
|
) {
|
|
unset(self::$orphansList[$page]);
|
|
}
|
|
}
|
|
|
|
// Valeurs en sortie
|
|
$this->addOutput([
|
|
'title' => helper::translate('Configuration'),
|
|
'view' => 'index'
|
|
]);
|
|
}
|
|
|
|
|
|
public function script()
|
|
{
|
|
// Soumission du formulaire
|
|
if (
|
|
$this->getUser('permission', __CLASS__, __FUNCTION__) === true &&
|
|
$this->isPost()
|
|
) {
|
|
// Ecrire les fichiers de script
|
|
if ($this->geturl(2) === 'head') {
|
|
file_put_contents(self::DATA_DIR . 'head.inc.html', $this->getInput('configScriptHead', null));
|
|
}
|
|
if ($this->geturl(2) === 'body') {
|
|
file_put_contents(self::DATA_DIR . 'body.inc.html', $this->getInput('configScriptBody', null));
|
|
}
|
|
// Valeurs en sortie
|
|
$this->addOutput([
|
|
'title' => helper::translate('Éditeur de script dans ' . ucfirst($this->geturl(2))),
|
|
'vendor' => [
|
|
'codemirror'
|
|
],
|
|
'view' => 'script',
|
|
'state' => true
|
|
]);
|
|
}
|
|
// Valeurs en sortie
|
|
$this->addOutput([
|
|
'title' => sprintf(helper::translate('Éditeur de script %s'), ucfirst($this->geturl(2))),
|
|
'vendor' => [
|
|
'codemirror'
|
|
],
|
|
'view' => 'script'
|
|
]);
|
|
}
|
|
|
|
|
|
/**
|
|
* Vider le fichier de log
|
|
*/
|
|
|
|
public function logReset()
|
|
{
|
|
// Action interdite
|
|
if (
|
|
$this->getUser('permission', __CLASS__, __FUNCTION__) !== true
|
|
) {
|
|
// Valeurs en sortie
|
|
$this->addOutput([
|
|
'access' => false
|
|
]);
|
|
} else {
|
|
if (file_exists(self::DATA_DIR . 'journal.log')) {
|
|
unlink(self::DATA_DIR . 'journal.log');
|
|
// Créer les en-têtes des journaux
|
|
$d = 'Date;Heure;IP;Id;Action' . PHP_EOL;
|
|
file_put_contents(self::DATA_DIR . 'journal.log', $d);
|
|
// Valeurs en sortie
|
|
$this->addOutput([
|
|
'title' => helper::translate('Configuration'),
|
|
'view' => 'index',
|
|
'notification' => helper::translate('Journal réinitialisé avec succès'),
|
|
'state' => true
|
|
]);
|
|
} else {
|
|
// Valeurs en sortie
|
|
$this->addOutput([
|
|
'title' => helper::translate('Configuration'),
|
|
'view' => 'index',
|
|
'notification' => helper::translate('Aucun journal à effacer'),
|
|
'state' => false
|
|
]);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
* Télécharger le fichier de log
|
|
*/
|
|
public function logDownload()
|
|
{
|
|
// Action interdite
|
|
if (
|
|
$this->getUser('permission', __CLASS__, __FUNCTION__) !== true
|
|
) {
|
|
// Valeurs en sortie
|
|
$this->addOutput([
|
|
'access' => false
|
|
]);
|
|
} else {
|
|
$fileName = self::DATA_DIR . 'journal.log';
|
|
if (file_exists($fileName)) {
|
|
ob_start();
|
|
header('Content-Description: File Transfer');
|
|
header('Content-Type: application/octet-stream');
|
|
header('Content-Disposition: attachment; filename="' . $fileName . '"');
|
|
header('Content-Length: ' . filesize($fileName));
|
|
ob_clean();
|
|
ob_end_flush();
|
|
readfile($fileName);
|
|
exit();
|
|
} else {
|
|
// Valeurs en sortie
|
|
$this->addOutput([
|
|
'title' => helper::translate('Configuration'),
|
|
'view' => 'index',
|
|
'notification' => helper::translate('Aucun fichier journal à télécharger'),
|
|
'state' => false
|
|
]);
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Tableau des IP blacklistés
|
|
*/
|
|
public function blacklistDownload()
|
|
{
|
|
// Action interdite
|
|
if (
|
|
$this->getUser('permission', __CLASS__, __FUNCTION__) !== true
|
|
) {
|
|
// Valeurs en sortie
|
|
$this->addOutput([
|
|
'access' => false
|
|
]);
|
|
} else {
|
|
ob_start();
|
|
$fileName = self::TEMP_DIR . 'blacklist.log';
|
|
$d = 'Date dernière tentative;Heure dernière tentative;Id;Adresse IP;Nombre d\'échecs' . PHP_EOL;
|
|
file_put_contents($fileName, $d);
|
|
if (file_exists($fileName)) {
|
|
$d = $this->getData(['blacklist']);
|
|
$data = '';
|
|
foreach ($d as $key => $item) {
|
|
$data .= helper::dateUTF8('%Y %m %d', $item['lastFail'], self::$i18nUI) . ' - ' . helper::dateUTF8('%H:%M', time(), self::$i18nUI);
|
|
$data .= $key . ';' . $item['ip'] . ';' . $item['connectFail'] . PHP_EOL;
|
|
}
|
|
file_put_contents($fileName, $data, FILE_APPEND);
|
|
header('Content-Description: File Transfer');
|
|
header('Content-Type: application/octet-stream');
|
|
header('Content-Transfer-Encoding: binary');
|
|
header('Content-Disposition: attachment; filename="' . $fileName . '"');
|
|
header('Content-Length: ' . filesize($fileName));
|
|
ob_clean();
|
|
ob_end_flush();
|
|
readfile($fileName);
|
|
unlink(self::TEMP_DIR . 'blacklist.log');
|
|
exit();
|
|
} else {
|
|
// Valeurs en sortie
|
|
$this->addOutput([
|
|
'title' => helper::translate('Configuration'),
|
|
'view' => 'index',
|
|
'notification' => helper::translate('Aucune liste noire à télécharger'),
|
|
'state' => false
|
|
]);
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Réinitialiser les ip blacklistées
|
|
*/
|
|
|
|
public function blacklistReset()
|
|
{
|
|
// Action interdite
|
|
if (
|
|
$this->getUser('permission', __CLASS__, __FUNCTION__) !== true
|
|
) {
|
|
// Valeurs en sortie
|
|
$this->addOutput([
|
|
'access' => false
|
|
]);
|
|
} else {
|
|
if (file_exists(self::DATA_DIR . 'blacklist.json')) {
|
|
$this->setData(['blacklist', []]);
|
|
// Valeurs en sortie
|
|
$this->addOutput([
|
|
'title' => helper::translate('Configuration'),
|
|
'view' => 'index',
|
|
'notification' => helper::translate('Liste noire réinitialisée avec succès'),
|
|
'state' => true
|
|
]);
|
|
} else {
|
|
// Valeurs en sortie
|
|
$this->addOutput([
|
|
'title' => helper::translate('Configuration'),
|
|
'view' => 'index',
|
|
'notification' => helper::translate('Aucune liste noire à effacer'),
|
|
'state' => false
|
|
]);
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Récupération des backups auto dans le gestionnaire de fichiers
|
|
*/
|
|
public function copyBackups()
|
|
{
|
|
// Action interdite
|
|
if (
|
|
$this->getUser('permission', __CLASS__, __FUNCTION__) !== true
|
|
) {
|
|
// Valeurs en sortie
|
|
$this->addOutput([
|
|
'access' => false
|
|
]);
|
|
} else {
|
|
|
|
$success = $this->copyDir(self::BACKUP_DIR, self::FILE_DIR . 'source/backup');
|
|
|
|
// Valeurs en sortie
|
|
$this->addOutput([
|
|
'title' => helper::translate('Configuration'),
|
|
'view' => 'index',
|
|
'notification' => $success ? helper::translate('Copie terminée avec succès') : helper::translate('Copie terminée avec des erreurs'),
|
|
'state' => $success
|
|
]);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Vider le dosser des sauvegardes automatisées
|
|
*/
|
|
public function delBackups()
|
|
{
|
|
// Action interdite
|
|
if (
|
|
$this->getUser('permission', __CLASS__, __FUNCTION__) !== true
|
|
) {
|
|
// Valeurs en sortie
|
|
$this->addOutput([
|
|
'access' => false
|
|
]);
|
|
} else {
|
|
$path = realpath(self::BACKUP_DIR);
|
|
$success = $fail = 0;
|
|
foreach (new RecursiveIteratorIterator(new RecursiveDirectoryIterator($path)) as $filename) {
|
|
if (strpos($filename, '.zip')) {
|
|
|
|
$r = unlink($filename);
|
|
$success = $r === true ? $success + 1 : $success;
|
|
$fail = $r === false ? $fail + 1 : $fail;
|
|
}
|
|
}
|
|
// Valeurs en sortie
|
|
$this->addOutput([
|
|
'title' => helper::translate('Configuration'),
|
|
'view' => 'index',
|
|
'notification' => $success . helper::translate('Fichiers effacés') . ' - ' . helper::translate('Échecs') . ': ' . $fail,
|
|
'state' => true
|
|
]);
|
|
}
|
|
}
|
|
} |