From 18f00cbe3cfdcdf5097ac5f152eca9706d27615c Mon Sep 17 00:00:00 2001 From: Fred Tempez Date: Tue, 4 Jul 2023 19:03:27 +0200 Subject: [PATCH 1/9] =?UTF-8?q?Durcissselment=20des=20contr=C3=B4les?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- core/module/config/config.php | 256 +++++++++++++++++----------- core/module/install/install.php | 288 +++++++++++++++++--------------- core/module/theme/theme.php | 150 +++++++++-------- core/module/user/user.php | 3 +- 4 files changed, 389 insertions(+), 308 deletions(-) diff --git a/core/module/config/config.php b/core/module/config/config.php index 73233d67..18734c5d 100644 --- a/core/module/config/config.php +++ b/core/module/config/config.php @@ -367,10 +367,10 @@ class config extends common } // Lire le contenu de l'archive dans le tableau files /* - for ($i = 0; $i < $zip->numFiles; $i++) { - $stat = $zip->statIndex($i); - $files[] = (basename($stat['name'])); - }*/ + for ($i = 0; $i < $zip->numFiles; $i++) { + $stat = $zip->statIndex($i); + $files[] = (basename($stat['name'])); + }*/ // Extraction de l'archive dans un dossier temporaire $tmpDir = uniqid(8); $success = $zip->extractTo(self::TEMP_DIR . $tmpDir); @@ -647,26 +647,36 @@ class config extends common public function logReset() { - 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); + // Action interdite + if ( + $this->getUser('permission', __CLASS__, __FUNCTION__) !== true + ) { // Valeurs en sortie $this->addOutput([ - 'title' => helper::translate('Configuration'), - 'view' => 'index', - 'notification' => helper::translate('Journal réinitialisé avec succès'), - 'state' => true + 'access' => false ]); } else { - // Valeurs en sortie - $this->addOutput([ - 'title' => helper::translate('Configuration'), - 'view' => 'index', - 'notification' => helper::translate('Aucun journal à effacer'), - 'state' => false - ]); + 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 + ]); + } } } @@ -677,25 +687,35 @@ class config extends common */ public function logDownload() { - $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 { + // Action interdite + if ( + $this->getUser('permission', __CLASS__, __FUNCTION__) !== true + ) { // Valeurs en sortie $this->addOutput([ - 'title' => helper::translate('Configuration'), - 'view' => 'index', - 'notification' => helper::translate('Aucun fichier journal à télécharger'), - 'state' => false + '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 + ]); + } } } @@ -704,36 +724,46 @@ class config extends common */ public function blacklistDownload() { - 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']) . ' - ' . helper::dateUTF8('%H:%M', time()); - $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 { + // Action interdite + if ( + $this->getUser('permission', __CLASS__, __FUNCTION__) !== true + ) { // Valeurs en sortie $this->addOutput([ - 'title' => helper::translate('Confighelper::translate(uration'), - 'view' => 'index', - 'notification' => helper::translate('Aucune liste noire à télécharger'), - 'state' => false + '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']) . ' - ' . helper::dateUTF8('%H:%M', time()); + $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('Confighelper::translate(uration'), + 'view' => 'index', + 'notification' => helper::translate('Aucune liste noire à télécharger'), + 'state' => false + ]); + } } } @@ -743,23 +773,33 @@ class config extends common public function blacklistReset() { - if (file_exists(self::DATA_DIR . 'blacklist.json')) { - $this->setData(['blacklist', []]); + // Action interdite + if ( + $this->getUser('permission', __CLASS__, __FUNCTION__) !== true + ) { // Valeurs en sortie $this->addOutput([ - 'title' => helper::translate('Configuration'), - 'view' => 'index', - 'notification' => helper::translate('Liste noire réinitialisée avec succès'), - 'state' => true + 'access' => false ]); } else { - // Valeurs en sortie - $this->addOutput([ - 'title' => helper::translate('Configuration'), - 'view' => 'index', - 'notification' => helper::translate('Aucune liste noire à effacer'), - 'state' => false - ]); + 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 + ]); + } } } @@ -768,16 +808,26 @@ class config extends common */ 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'); + $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 - ]); + // 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 + ]); + } } /** @@ -785,22 +835,32 @@ class config extends common */ public function delBackups() { - $path = realpath(self::BACKUP_DIR); - $success = $fail = 0; - foreach (new RecursiveIteratorIterator(new RecursiveDirectoryIterator($path)) as $filename) { - if (strpos($filename, '.zip')) { + // 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; + $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 + ]); } - // Valeurs en sortie - $this->addOutput([ - 'title' => helper::translate('Configuration'), - 'view' => 'index', - 'notification' => $success . helper::translate('Fichiers effacés') . ' - ' . helper::translate('Échecs') . ': ' . $fail, - 'state' => true - ]); } } \ No newline at end of file diff --git a/core/module/install/install.php b/core/module/install/install.php index 26ae0119..6baa922c 100644 --- a/core/module/install/install.php +++ b/core/module/install/install.php @@ -273,147 +273,157 @@ class install extends common */ public function steps() { - switch ($this->getInput('step', helper::FILTER_INT)) { - // Préparation - case 1: - $success = true; - $message = ''; - // RAZ la mise à jour auto - $this->setData(['core', 'updateAvailable', false]); - // Backup du dossier Data - helper::autoBackup(self::BACKUP_DIR, ['backup', 'tmp', 'file']); - // Sauvegarde htaccess - if ($this->getData(['config', 'autoUpdateHtaccess'])) { - $success = copy('.htaccess', '.htaccess' . '.bak'); - $message = 'Erreur de copie du fichier htaccess'; - } - // Nettoyage des fichiers d'installation précédents - if (file_exists(self::TEMP_DIR . 'update.tar.gz') && $success) { - $success = $success || unlink(self::TEMP_DIR . 'update.tar.gz'); - $message = 'Impossible d\'effacer la mise à jour précédente'; - } - if (file_exists(self::TEMP_DIR . 'update.tar') && $success) { - $success = $success || unlink(self::TEMP_DIR . 'update.tar'); - $message = 'Impossible d\'effacer la mise à jour précédente'; - } - // Valeurs en sortie - $this->addOutput([ - 'display' => self::DISPLAY_JSON, - 'content' => [ - 'success' => $success, - 'data' => $success ? null : json_encode($message, JSON_UNESCAPED_UNICODE) - ] - ]); - break; - // Téléchargement - case 2: - file_put_contents(self::TEMP_DIR . 'update.tar.gz', helper::getUrlContents(common::ZWII_UPDATE_URL . common::ZWII_UPDATE_CHANNEL . '/update.tar.gz')); - $md5origin = helper::getUrlContents(common::ZWII_UPDATE_URL . common::ZWII_UPDATE_CHANNEL . '/update.md5'); - $md5origin = explode(' ', $md5origin); - $md5target = md5_file(self::TEMP_DIR . 'update.tar.gz'); - // Valeurs en sortie - $this->addOutput([ - 'display' => self::DISPLAY_JSON, - 'content' => [ - 'success' => $md5origin[0] === $md5target, - 'data' => $md5origin[0] === $md5target ? null : json_encode('Erreur de téléchargement ou de somme de contrôle', JSON_UNESCAPED_UNICODE) - ] - ]); - break; - // Installation - case 3: - $success = true; - // Check la réécriture d'URL avant d'écraser les fichiers - $rewrite = helper::checkRewrite(); - // Décompression et installation - try { - // Décompression dans le dossier de fichier temporaires - $pharData = new PharData(self::TEMP_DIR . 'update.tar.gz'); - $pharData->decompress(); - // Installation - $pharData->extractTo(__DIR__ . '/../../../', null, true); - } catch (Exception $e) { - $success = $e->getMessage(); - } - // Nettoyage du dossier - if (file_exists(self::TEMP_DIR . 'update.tar.gz')) { - unlink(self::TEMP_DIR . 'update.tar.gz'); - } - if (file_exists(self::TEMP_DIR . 'update.tar')) { - unlink(self::TEMP_DIR . 'update.tar'); - } - // Valeurs en sortie - $this->addOutput([ - 'display' => self::DISPLAY_JSON, - 'content' => [ - 'success' => $success, - 'data' => $rewrite - ] - ]); - break; - // Configuration - case 4: - $success = true; - $message = ''; - $rewrite = $this->getInput('data'); - // Réécriture d'URL - if ($rewrite === 'true') { // Ajout des lignes dans le .htaccess - $fileContent = file_get_contents('.htaccess'); - $rewriteData = PHP_EOL . - '# URL rewriting' . PHP_EOL . - '' . 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 . - '' . PHP_EOL . - '# URL rewriting' . PHP_EOL; - $fileContent = str_replace('# URL rewriting', $rewriteData, $fileContent); - $r = file_put_contents( - '.htaccess', - $fileContent - ); - $success = $r === false ? false : true; - $message = $r === false ? 'Le fichier htaccess n\'a pas été restauré' : null; - } - // Recopie htaccess - if ( - $this->getData(['config', 'autoUpdateHtaccess']) && - $success && file_exists('.htaccess.bak') - ) { - // L'écraser avec le backup - $success = $success || copy('.htaccess.bak', '.htaccess'); - // Effacer le backup - unlink('.htaccess.bak'); - } - - /** - * Met à jour les dictionnaires des langues depuis les modèles installés - */ - - // Langues installées - $installedUI = $this->getData(['language']); - - // Langues disponibles avec la mise à jour - require_once('core/module/install/ressource/defaultdata.php'); - $default = init::$defaultData['language']; - - foreach ($installedUI as $key => $value) { - if ($default[$key]['version'] > $value['version']) { - copy('core/module/install/ressource/i18n/' . $key . '.json', self::I18N_DIR . $key . '.json'); - $this->setData(['language', $key, $default[$key]]); + // Action interdite + if ( + $this->getUser('permission', __CLASS__, __FUNCTION__) !== true + ) { + // Valeurs en sortie + $this->addOutput([ + 'access' => false + ]); + } else { + switch ($this->getInput('step', helper::FILTER_INT)) { + // Préparation + case 1: + $success = true; + $message = ''; + // RAZ la mise à jour auto + $this->setData(['core', 'updateAvailable', false]); + // Backup du dossier Data + helper::autoBackup(self::BACKUP_DIR, ['backup', 'tmp', 'file']); + // Sauvegarde htaccess + if ($this->getData(['config', 'autoUpdateHtaccess'])) { + $success = copy('.htaccess', '.htaccess' . '.bak'); + $message = 'Erreur de copie du fichier htaccess'; + } + // Nettoyage des fichiers d'installation précédents + if (file_exists(self::TEMP_DIR . 'update.tar.gz') && $success) { + $success = $success || unlink(self::TEMP_DIR . 'update.tar.gz'); + $message = 'Impossible d\'effacer la mise à jour précédente'; + } + if (file_exists(self::TEMP_DIR . 'update.tar') && $success) { + $success = $success || unlink(self::TEMP_DIR . 'update.tar'); + $message = 'Impossible d\'effacer la mise à jour précédente'; + } + // Valeurs en sortie + $this->addOutput([ + 'display' => self::DISPLAY_JSON, + 'content' => [ + 'success' => $success, + 'data' => $success ? null : json_encode($message, JSON_UNESCAPED_UNICODE) + ] + ]); + break; + // Téléchargement + case 2: + file_put_contents(self::TEMP_DIR . 'update.tar.gz', helper::getUrlContents(common::ZWII_UPDATE_URL . common::ZWII_UPDATE_CHANNEL . '/update.tar.gz')); + $md5origin = helper::getUrlContents(common::ZWII_UPDATE_URL . common::ZWII_UPDATE_CHANNEL . '/update.md5'); + $md5origin = explode(' ', $md5origin); + $md5target = md5_file(self::TEMP_DIR . 'update.tar.gz'); + // Valeurs en sortie + $this->addOutput([ + 'display' => self::DISPLAY_JSON, + 'content' => [ + 'success' => $md5origin[0] === $md5target, + 'data' => $md5origin[0] === $md5target ? null : json_encode('Erreur de téléchargement ou de somme de contrôle', JSON_UNESCAPED_UNICODE) + ] + ]); + break; + // Installation + case 3: + $success = true; + // Check la réécriture d'URL avant d'écraser les fichiers + $rewrite = helper::checkRewrite(); + // Décompression et installation + try { + // Décompression dans le dossier de fichier temporaires + $pharData = new PharData(self::TEMP_DIR . 'update.tar.gz'); + $pharData->decompress(); + // Installation + $pharData->extractTo(__DIR__ . '/../../../', null, true); + } catch (Exception $e) { + $success = $e->getMessage(); + } + // Nettoyage du dossier + if (file_exists(self::TEMP_DIR . 'update.tar.gz')) { + unlink(self::TEMP_DIR . 'update.tar.gz'); + } + if (file_exists(self::TEMP_DIR . 'update.tar')) { + unlink(self::TEMP_DIR . 'update.tar'); + } + // Valeurs en sortie + $this->addOutput([ + 'display' => self::DISPLAY_JSON, + 'content' => [ + 'success' => $success, + 'data' => $rewrite + ] + ]); + break; + // Configuration + case 4: + $success = true; + $message = ''; + $rewrite = $this->getInput('data'); + // Réécriture d'URL + if ($rewrite === 'true') { // Ajout des lignes dans le .htaccess + $fileContent = file_get_contents('.htaccess'); + $rewriteData = PHP_EOL . + '# URL rewriting' . PHP_EOL . + '' . 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 . + '' . PHP_EOL . + '# URL rewriting' . PHP_EOL; + $fileContent = str_replace('# URL rewriting', $rewriteData, $fileContent); + $r = file_put_contents( + '.htaccess', + $fileContent + ); + $success = $r === false ? false : true; + $message = $r === false ? 'Le fichier htaccess n\'a pas été restauré' : null; + } + // Recopie htaccess + if ( + $this->getData(['config', 'autoUpdateHtaccess']) && + $success && file_exists('.htaccess.bak') + ) { + // L'écraser avec le backup + $success = $success || copy('.htaccess.bak', '.htaccess'); + // Effacer le backup + unlink('.htaccess.bak'); } - } - // Valeurs en sortie - $this->addOutput([ - 'display' => self::DISPLAY_JSON, - 'content' => [ - 'success' => $success, - 'data' => json_encode($message, JSON_UNESCAPED_UNICODE) - ] - ]); + /** + * Met à jour les dictionnaires des langues depuis les modèles installés + */ + + // Langues installées + $installedUI = $this->getData(['language']); + + // Langues disponibles avec la mise à jour + require_once('core/module/install/ressource/defaultdata.php'); + $default = init::$defaultData['language']; + + foreach ($installedUI as $key => $value) { + if ($default[$key]['version'] > $value['version']) { + copy('core/module/install/ressource/i18n/' . $key . '.json', self::I18N_DIR . $key . '.json'); + $this->setData(['language', $key, $default[$key]]); + } + } + + // Valeurs en sortie + $this->addOutput([ + 'display' => self::DISPLAY_JSON, + 'content' => [ + 'success' => $success, + 'data' => json_encode($message, JSON_UNESCAPED_UNICODE) + ] + ]); + } } } diff --git a/core/module/theme/theme.php b/core/module/theme/theme.php index c5f122cd..8d4a9b5d 100644 --- a/core/module/theme/theme.php +++ b/core/module/theme/theme.php @@ -1016,81 +1016,91 @@ class theme extends common public function import($zipName = '') { - + // Action interdite if ( - $zipName !== '' && - file_exists($zipName) + $this->getUser('permission', __CLASS__, __FUNCTION__) !== true ) { - // Init variables de retour - $success = false; - $notification = ''; - // Dossier temporaire - $tempFolder = uniqid(); - // Ouvrir le zip - $zip = new ZipArchive(); - if ($zip->open($zipName) === TRUE) { - mkdir(self::TEMP_DIR . $tempFolder, 0755); - $zip->extractTo(self::TEMP_DIR . $tempFolder); - $modele = ''; - // Archive de thème ? - if ( - file_exists(self::TEMP_DIR . $tempFolder . '/site/data/custom.css') - and file_exists(self::TEMP_DIR . $tempFolder . '/site/data/theme.css') - and file_exists(self::TEMP_DIR . $tempFolder . '/site/data/theme.json') - ) { - $modele = 'theme'; - } - if ( - file_exists(self::TEMP_DIR . $tempFolder . '/site/data/admin.json') - and file_exists(self::TEMP_DIR . $tempFolder . '/site/data/admin.css') - ) { - $modele = 'admin'; - } - if (!empty($modele)) { - // traiter l'archive - $success = $zip->extractTo('.'); + // Valeurs en sortie + $this->addOutput([ + 'access' => false + ]); + } else { - // Substitution des fontes Google - if ($modele = 'theme') { - $c = $this->subFont(self::DATA_DIR . 'theme.json'); - // Un remplacement nécessite la régénération de la feuille de style - if ( - $c > 0 - and file_exists(self::DATA_DIR . 'theme.css') - ) { - unlink(self::DATA_DIR . 'theme.css'); - } - } - if ($modele = 'admin') { - $c = $this->subFont(self::DATA_DIR . 'admin.json'); - // Un remplacement nécessite la régénération de la feuille de style - if ( - $c > 0 - and file_exists(self::DATA_DIR . 'admin.css') - ) { - unlink(self::DATA_DIR . 'admin.css'); - } - } - - // traitement d'erreur - $notification = $success ? helper::translate('Thème importé') : helper::translate('Erreur lors de l\'extraction, vérifiez les permissions'); - } else { - // pas une archive de thème - $success = false; - $notification = helper::translate('Archive de thème invalide'); - } - // Supprimer le dossier temporaire même si le thème est invalide - $this->removeDir(self::TEMP_DIR . $tempFolder); - $zip->close(); - } else { - // erreur à l'ouverture + if ( + $zipName !== '' && + file_exists($zipName) + ) { + // Init variables de retour $success = false; - $notification = helper::translate('Impossible d\'ouvrir l\'archive'); - } - return (['success' => $success, 'notification' => $notification]); - } + $notification = ''; + // Dossier temporaire + $tempFolder = uniqid(); + // Ouvrir le zip + $zip = new ZipArchive(); + if ($zip->open($zipName) === TRUE) { + mkdir(self::TEMP_DIR . $tempFolder, 0755); + $zip->extractTo(self::TEMP_DIR . $tempFolder); + $modele = ''; + // Archive de thème ? + if ( + file_exists(self::TEMP_DIR . $tempFolder . '/site/data/custom.css') + and file_exists(self::TEMP_DIR . $tempFolder . '/site/data/theme.css') + and file_exists(self::TEMP_DIR . $tempFolder . '/site/data/theme.json') + ) { + $modele = 'theme'; + } + if ( + file_exists(self::TEMP_DIR . $tempFolder . '/site/data/admin.json') + and file_exists(self::TEMP_DIR . $tempFolder . '/site/data/admin.css') + ) { + $modele = 'admin'; + } + if (!empty($modele)) { + // traiter l'archive + $success = $zip->extractTo('.'); - return (['success' => false, 'notification' => helper::translate('Archive non spécifiée ou introuvable')]); + // Substitution des fontes Google + if ($modele = 'theme') { + $c = $this->subFont(self::DATA_DIR . 'theme.json'); + // Un remplacement nécessite la régénération de la feuille de style + if ( + $c > 0 + and file_exists(self::DATA_DIR . 'theme.css') + ) { + unlink(self::DATA_DIR . 'theme.css'); + } + } + if ($modele = 'admin') { + $c = $this->subFont(self::DATA_DIR . 'admin.json'); + // Un remplacement nécessite la régénération de la feuille de style + if ( + $c > 0 + and file_exists(self::DATA_DIR . 'admin.css') + ) { + unlink(self::DATA_DIR . 'admin.css'); + } + } + + // traitement d'erreur + $notification = $success ? helper::translate('Thème importé') : helper::translate('Erreur lors de l\'extraction, vérifiez les permissions'); + } else { + // pas une archive de thème + $success = false; + $notification = helper::translate('Archive de thème invalide'); + } + // Supprimer le dossier temporaire même si le thème est invalide + $this->removeDir(self::TEMP_DIR . $tempFolder); + $zip->close(); + } else { + // erreur à l'ouverture + $success = false; + $notification = helper::translate('Impossible d\'ouvrir l\'archive'); + } + return (['success' => $success, 'notification' => $notification]); + } + + return (['success' => false, 'notification' => helper::translate('Archive non spécifiée ou introuvable')]); + } } diff --git a/core/module/user/user.php b/core/module/user/user.php index 89cb7f77..d01325da 100644 --- a/core/module/user/user.php +++ b/core/module/user/user.php @@ -1014,7 +1014,8 @@ class user extends common else { // Soumission du formulaire if ( - $this->getUser('permission', __CLASS__, __FUNCTION__) === true && + // Tous les suers peuvent réinitialiser + // $this->getUser('permission', __CLASS__, __FUNCTION__) === true && $this->isPost() ) { // Double vérification pour le mot de passe From befbd1438db28c9e621362be07ea0964ad7a9aab Mon Sep 17 00:00:00 2001 From: Fred Tempez Date: Tue, 4 Jul 2023 19:27:22 +0200 Subject: [PATCH 2/9] update enums --- module/blog/enum.json | 2 +- module/form/enum.json | 2 +- module/gallery/enum.json | 2 +- module/news/enum.json | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/module/blog/enum.json b/module/blog/enum.json index 7720ddcb..09ca60b1 100644 --- a/module/blog/enum.json +++ b/module/blog/enum.json @@ -1 +1 @@ -{"name":"blog","realName":"Blog","version":"6.8","update":"0.0","delete":true,"dataDirectory":""} \ No newline at end of file +{"name":"blog","realName":"Blog","version":"6.9","update":"0.0","delete":true,"dataDirectory":""} \ No newline at end of file diff --git a/module/form/enum.json b/module/form/enum.json index 6a438a67..7f3bfc11 100644 --- a/module/form/enum.json +++ b/module/form/enum.json @@ -1 +1 @@ -{"name":"form","realName":"Formulaire","version":"3.9","update":"0.0","delete":true,"dataDirectory":""} \ No newline at end of file +{"name":"form","realName":"Formulaire","version":"3.10","update":"0.0","delete":true,"dataDirectory":""} \ No newline at end of file diff --git a/module/gallery/enum.json b/module/gallery/enum.json index 2bc512f9..4d3e43e3 100644 --- a/module/gallery/enum.json +++ b/module/gallery/enum.json @@ -1 +1 @@ -{"name":"gallery","realName":"Galerie","version":"3.8","update":"0.0","delete":true,"dataDirectory":"site\/data\/gallery\/"} \ No newline at end of file +{"name":"gallery","realName":"Galerie","version":"3.9","update":"0.0","delete":true,"dataDirectory":"site\/data\/gallery\/"} \ No newline at end of file diff --git a/module/news/enum.json b/module/news/enum.json index 30c0fe1b..5ec740c8 100644 --- a/module/news/enum.json +++ b/module/news/enum.json @@ -1 +1 @@ -{"name":"news","realName":"News","version":"4.3","update":"0.0","delete":true,"dataDirectory":"site\/data\/news\/"} \ No newline at end of file +{"name":"news","realName":"News","version":"4.4","update":"0.0","delete":true,"dataDirectory":"site\/data\/news\/"} \ No newline at end of file From b72f16cb52523003c96adf6d21b50b65525af9be Mon Sep 17 00:00:00 2001 From: Fred Tempez Date: Tue, 4 Jul 2023 19:27:49 +0200 Subject: [PATCH 3/9] Bug sauvegarde plugins --- core/module/plugin/plugin.php | 32 +++++++++++++------------------- 1 file changed, 13 insertions(+), 19 deletions(-) diff --git a/core/module/plugin/plugin.php b/core/module/plugin/plugin.php index 88d83a7a..37209c77 100644 --- a/core/module/plugin/plugin.php +++ b/core/module/plugin/plugin.php @@ -580,7 +580,7 @@ class plugin extends common ]); } else { // Créer un dossier temporaire - $tmpFolder = self::TEMP_DIR . uniqid(); + $tmpFolder = self::TEMP_DIR . uniqid() . '/'; if (!is_dir($tmpFolder)) { mkdir($tmpFolder, 0755); } @@ -590,21 +590,19 @@ class plugin extends common // Descripteur de l'archive $infoModule = helper::getModules(); - //Nom de l'archive - $fileName = $moduleId . $infoModule[$moduleId]['version'] . '.zip'; - // Régénération du module - $success = file_put_contents(self::MODULE_DIR . $moduleId . '/enum.json', json_encode($infoModule[$moduleId], JSON_UNESCAPED_UNICODE)); + //Nom de l'archive + $fileName = $moduleId . str_replace('.', '-', $infoModule[$moduleId]['version']) . '.zip'; + + // Régénération du descripteur du module + file_put_contents(self::MODULE_DIR . $moduleId . '/enum.json', json_encode($infoModule[$moduleId], JSON_UNESCAPED_UNICODE)); // Construire l'archive - $this->makeZip(self::TEMP_DIR . $fileName, self::MODULE_DIR . $moduleId); + $this->makeZip( $tmpFolder . $fileName, self::MODULE_DIR . $moduleId); switch ($action) { case 'filemanager': - if (!file_exists(self::FILE_DIR . 'source/modules')) { - mkdir(self::FILE_DIR . 'source/modules'); - } - $success = $success || copy(self::TEMP_DIR . $fileName, self::FILE_DIR . 'source/modules/' . $moduleId . '.zip'); + $success = copy($tmpFolder . $fileName, self::FILE_DIR . 'source/modules/' . $fileName ); // Valeurs en sortie $this->addOutput([ @@ -612,24 +610,20 @@ class plugin extends common 'notification' => $success ? helper::translate('Archive copiée dans le dossier Modules du gestionnaire de fichier') : helper::translate('Erreur de copie'), 'state' => $success ]); - // Nettoyage - unlink(self::TEMP_DIR . $fileName); - $this->removeDir($tmpFolder); break; case 'download': - default: - // Téléchargement du ZIP 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(self::TEMP_DIR . $fileName)); - readfile(self::TEMP_DIR . $fileName); - // Nettoyage du dossier - unlink(self::TEMP_DIR . $fileName); + header('Content-Length: ' . filesize($tmpFolder. $fileName)); + readfile($tmpFolder . $fileName); exit(); } + // Nettoyage + unlink(self::TEMP_DIR . $fileName); + $this->removeDir($tmpFolder); } } From 433342c2a8626ef4289e92b4710f3f1c0a7b3da2 Mon Sep 17 00:00:00 2001 From: Fred Tempez Date: Tue, 4 Jul 2023 19:31:34 +0200 Subject: [PATCH 4/9] =?UTF-8?q?num=C3=A9ros=20de=20version?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CHANGES.md | 8 +++++++- LISEZMOI.md | 2 +- README.md | 2 +- 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index 8245b703..b92219d4 100755 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,10 +1,16 @@ # Changelog -## Version 12.4.00 +## Version 13.0.00 # Améliorations - Gestion des groupes de profils d'utilisateurs. +- Sécurise l'accès aux fonctions sensibles du CLMS. - Améliore la gestion de la base de données et la génération du fichier de journalisation. - Stockage des données JSON, forçage au format objet. +- Correction de bugs mineurs dans la sauvegarde des modules installés. + +## Version 12.4.00 +- L'ID de session n'est plus transmise dans l'URL, les modules distribués ont été actualisés. +- Corrections de bug dans le module Blog, merci de consulter le fichier changes.log du module. ## Version 12.3.11 - Interdit la création d'une langue autrement que par un administrateur. diff --git a/LISEZMOI.md b/LISEZMOI.md index 804505df..414d5e76 100644 --- a/LISEZMOI.md +++ b/LISEZMOI.md @@ -1,4 +1,4 @@ -# ZwiiCMS 12.3.11 +# ZwiiCMS 13.0.00 Zwii est un CMS sans base de données (flat-file) qui permet de créer et gérer facilement un site web sans aucune connaissance en programmation. diff --git a/README.md b/README.md index c2569faf..c2a03712 100755 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# ZwiiCMS 12.3.11 +# ZwiiCMS 13.0.00 Zwii is a database-less (flat-file) CMS that allows you to easily create and manage a web site without any programming knowledge. From 9f6202e639824e355bc9d807c19e3e4830577fc8 Mon Sep 17 00:00:00 2001 From: Fred Tempez Date: Wed, 5 Jul 2023 17:34:55 +0200 Subject: [PATCH 5/9] Check Modules --- module/blog/blog.php | 33 +++++++++++++++------------------ module/form/changes.md | 1 + module/form/form.php | 4 ++-- module/search/search.php | 1 - 4 files changed, 18 insertions(+), 21 deletions(-) diff --git a/module/blog/blog.php b/module/blog/blog.php index 16b23981..43a0b36f 100755 --- a/module/blog/blog.php +++ b/module/blog/blog.php @@ -904,24 +904,21 @@ class blog extends common */ public function signature($userId) { - if ($this->getUser('permission', __CLASS__, __FUNCTION__) !== true) { - switch ($this->getData(['user', $userId, 'signature'])) { - case 1: - return $userId; - break; - case 2: - return $this->getData(['user', $userId, 'pseudo']); - break; - case 3: - return $this->getData(['user', $userId, 'firstname']) . ' ' . $this->getData(['user', $userId, 'lastname']); - break; - case 4: - return $this->getData(['user', $userId, 'lastname']) . ' ' . $this->getData(['user', $userId, 'firstname']); - break; - default: - return $this->getData(['user', $userId, 'firstname']); - } + switch ($this->getData(['user', $userId, 'signature'])) { + case 1: + return $userId; + break; + case 2: + return $this->getData(['user', $userId, 'pseudo']); + break; + case 3: + return $this->getData(['user', $userId, 'firstname']) . ' ' . $this->getData(['user', $userId, 'lastname']); + break; + case 4: + return $this->getData(['user', $userId, 'lastname']) . ' ' . $this->getData(['user', $userId, 'firstname']); + break; + default: + return $this->getData(['user', $userId, 'firstname']); } - } } \ No newline at end of file diff --git a/module/form/changes.md b/module/form/changes.md index 91770236..3a42994b 100644 --- a/module/form/changes.md +++ b/module/form/changes.md @@ -1,6 +1,7 @@ # Version 3.10 - Bloque l'effacement selon le profil - Masque le code de vérification +- Export des données en CSV impossible # Version 3.9 - Redirection des pages orphelines # Version 3.8 diff --git a/module/form/form.php b/module/form/form.php index a3696501..6c851e55 100644 --- a/module/form/form.php +++ b/module/form/form.php @@ -235,7 +235,7 @@ class form extends common { $data = $this->getData(['module', $this->getUrl(0), 'data']); if ( - $this->getUser('permission', __CLASS__, __FUNCTION__) !== true && + $this->getUser('permission', __CLASS__, __FUNCTION__) === true && $data ) { // Pagination @@ -297,7 +297,7 @@ class form extends common fclose($fp); // Valeurs en sortie $this->addOutput([ - 'notification' => sprintf(helper::translate('Export CSV effectué dans %1 '), $csvfilename), + 'notification' => sprintf(helper::translate('Export CSV effectué dans %s '), $csvfilename ), 'redirect' => helper::baseUrl() . $this->getUrl(0) . '/data', 'state' => true ]); diff --git a/module/search/search.php b/module/search/search.php index 17fb043b..d19a11ca 100644 --- a/module/search/search.php +++ b/module/search/search.php @@ -177,7 +177,6 @@ class search extends common $this->update(); if ( - $this->getUser('permission', __CLASS__, __FUNCTION__) === true && $this->isPost() ) { //Initialisations variables From f915c591fabe51422c1ff00add4e7f7f9bcd88b1 Mon Sep 17 00:00:00 2001 From: Fred Tempez Date: Wed, 5 Jul 2023 17:57:18 +0200 Subject: [PATCH 6/9] =?UTF-8?q?mise=20=C3=A0=20jour=20des=20membres=20depu?= =?UTF-8?q?is=20versions=20pr=C3=A9c=C3=A9dentes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- core/include/update.inc.php | 24 ++++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-) diff --git a/core/include/update.inc.php b/core/include/update.inc.php index 39c1ce63..67bf6b79 100644 --- a/core/include/update.inc.php +++ b/core/include/update.inc.php @@ -974,8 +974,8 @@ if ($this->getData(['core', 'dataVersion']) < 12309) { // tableau des langues installées if (is_dir(self::DATA_DIR . $key)) { $d = json_decode(file_get_contents(self::DATA_DIR . $key . '/locale.json'), true); - $d = array_merge($d['locale'],['poweredPageLabel' => 'Motorisé par']); - $t ['locale'] = $d; + $d = array_merge($d['locale'], ['poweredPageLabel' => 'Motorisé par']); + $t['locale'] = $d; file_put_contents(self::DATA_DIR . $key . '/locale.json', json_encode($t)); } } @@ -986,7 +986,7 @@ if ($this->getData(['core', 'dataVersion']) < 12309) { // Version 12.4.00 if ($this->getData(['core', 'dataVersion']) < 12400) { - + // Nettoyage du dossier de langue d'installation' if (file_exists('core/vendor/tinymce/langs/langs.zip')) unlink('core/vendor/tinymce/langs/langs.zip'); @@ -999,15 +999,27 @@ if ($this->getData(['core', 'dataVersion']) < 12400) { if (file_exists('core/module/install/ressource/i18n/gr_GR.json')) unlink('core/module/install/ressource/i18n/gr_GR.json'); - // Création du dossier partga pour les nouveaux droits + // Création du dossier partage pour les nouveaux droits if (!is_dir(self::FILE_DIR . 'source/partage')) { mkdir(self::FILE_DIR . 'source/partage'); } // Efface le script router.php - if (file_exists('core/class/router.class.php')) - unlink('core/class/router.class.php'); + // if (file_exists('core/class/router.class.php')) + // unlink('core/class/router.class.php'); + // Ajouter le prénom comme pseudo et le pseudo comme signature + foreach ($this->getData(['user']) as $userId => $userIds) { + switch ($this->getData(['user', $userId, 'group'])) { + case '1': + case '2': + $this->setData(['user', $userId, 'profil', 1]); + break; + default: + $this->setData(['user', $userId, 'profil', $this->getData(['user', $userId, 'group'])]); + break; + } + } // Mise à jour $this->setData(['core', 'dataVersion', 12400]); } \ No newline at end of file From 0fe4c582a156a96e4da088511bc5b9c4ed6af55a Mon Sep 17 00:00:00 2001 From: Fred Tempez Date: Wed, 5 Jul 2023 17:58:01 +0200 Subject: [PATCH 7/9] Le profil des memebrs sans profil (bannis, visiteurs et admin, vaut 0) --- core/module/user/user.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/core/module/user/user.php b/core/module/user/user.php index d01325da..92872718 100644 --- a/core/module/user/user.php +++ b/core/module/user/user.php @@ -98,8 +98,8 @@ class user extends common // Profil $group = $this->getInput('userAddGroup', helper::FILTER_INT, true); - $profil = null; - if ($group > 1 || $group < 2) { + $profil = 0; + if ($group === 1 || $group === 2) { $profil = $this->getInput('userAddProfil' . $group, helper::FILTER_INT); } @@ -303,8 +303,8 @@ class user extends common $newlastname = $this->getData(['user', $this->getUrl(2), 'lastname']); } // Profil - $profil = null; - if ($newGroup > 1 || $newGroup < 2) { + $profil = 0; + if ($newGroup === 1 || $newGroup === 2) { $profil = $this->getInput('userEditProfil' . $newGroup, helper::FILTER_INT); } // Modifie l'utilisateur From a1096af3de0ad22f7414f263ce00d7139f8fcd71 Mon Sep 17 00:00:00 2001 From: Fred Tempez Date: Wed, 5 Jul 2023 18:00:20 +0200 Subject: [PATCH 8/9] =?UTF-8?q?Mise=20=C3=A0=20jour=20des=20membres=20le?= =?UTF-8?q?=20profil=20vaut=200=20pour=20les=20types=20membres=20et=20mode?= =?UTF-8?q?rateurs?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- core/include/update.inc.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/core/include/update.inc.php b/core/include/update.inc.php index 67bf6b79..3b415798 100644 --- a/core/include/update.inc.php +++ b/core/include/update.inc.php @@ -985,7 +985,7 @@ if ($this->getData(['core', 'dataVersion']) < 12309) { } // Version 12.4.00 -if ($this->getData(['core', 'dataVersion']) < 12400) { +if ($this->getData(['core', 'dataVersion']) < 13000) { // Nettoyage du dossier de langue d'installation' if (file_exists('core/vendor/tinymce/langs/langs.zip')) @@ -1016,10 +1016,10 @@ if ($this->getData(['core', 'dataVersion']) < 12400) { $this->setData(['user', $userId, 'profil', 1]); break; default: - $this->setData(['user', $userId, 'profil', $this->getData(['user', $userId, 'group'])]); + $this->setData(['user', $userId, 'profil', 0]); break; } } // Mise à jour - $this->setData(['core', 'dataVersion', 12400]); + $this->setData(['core', 'dataVersion', 13000]); } \ No newline at end of file From 92c8c0a6535a185f498063ede1e0cdcf5df6c3e8 Mon Sep 17 00:00:00 2001 From: Fred Tempez Date: Wed, 5 Jul 2023 18:04:42 +0200 Subject: [PATCH 9/9] Groupe MODERATOR devient EDITOR --- core/class/layout.class.php | 14 ++++++------- core/class/router.class.php | 2 +- core/core.php | 10 +++++----- core/module/install/ressource/defaultdata.php | 4 ++-- core/module/page/page.php | 12 +++++------ core/module/user/user.php | 8 ++++---- core/module/user/view/add/add.php | 10 +++++----- core/module/user/view/edit/edit.php | 10 +++++----- .../user/view/profilEdit/profilEdit.php | 2 +- module/blog/blog.php | 20 +++++++++---------- module/blog/view/article/article.php | 2 +- module/blog/view/index/index.php | 2 +- module/form/form.php | 12 +++++------ module/gallery/gallery.php | 18 ++++++++--------- module/news/news.php | 10 +++++----- module/redirection/redirection.php | 4 ++-- module/search/search.php | 2 +- 17 files changed, 71 insertions(+), 71 deletions(-) diff --git a/core/class/layout.class.php b/core/class/layout.class.php index 77256468..a2f63b9a 100644 --- a/core/class/layout.class.php +++ b/core/class/layout.class.php @@ -575,7 +575,7 @@ class layout extends common and $this->getUser('password') !== $this->getInput('ZWII_USER_PASSWORD') ) or ($this->getData(['page', $parentPageId, 'disable']) === true and $this->getUser('password') === $this->getInput('ZWII_USER_PASSWORD') - and $this->getUser('group') < self::GROUP_MODERATOR + and $this->getUser('group') < self::GROUP_EDITOR ) ) { $pageUrl = ($this->getData(['locale', 'homePageId']) === $this->getUrl(0)) ? helper::baseUrl(false) : helper::baseUrl() . $this->getUrl(0); @@ -641,7 +641,7 @@ class layout extends common and $this->getUser('password') !== $this->getInput('ZWII_USER_PASSWORD') ) or ($this->getData(['page', $childKey, 'disable']) === true and $this->getUser('password') === $this->getInput('ZWII_USER_PASSWORD') - and $this->getUser('group') < self::GROUP_MODERATOR + and $this->getUser('group') < self::GROUP_EDITOR ) ) { $pageUrl = ($this->getData(['locale', 'homePageId']) === $this->getUrl(0)) ? helper::baseUrl(false) : helper::baseUrl() . $this->getUrl(0); @@ -876,7 +876,7 @@ class layout extends common // Items de gauche $leftItems = ''; // Sélecteur de langues - if ($this->getUser('group') >= self::GROUP_MODERATOR) { + if ($this->getUser('group') >= self::GROUP_EDITOR) { $c = 0; $leftItem = ''; foreach (self::$languages as $key => $value) { @@ -893,7 +893,7 @@ class layout extends common } } // Liste des pages - if ($this->getUser('group') >= self::GROUP_MODERATOR) { + if ($this->getUser('group') >= self::GROUP_EDITOR) { $leftItems .= '