1.7.09 fonction secureFilePutContents

This commit is contained in:
Fred Tempez 2024-04-05 16:33:46 +02:00
parent 56f8f03581
commit 24f679d531
12 changed files with 187 additions and 103 deletions

View File

@ -193,7 +193,10 @@ class JsonDb extends \Prowebcraft\Dot
fclose($lockHandle); fclose($lockHandle);
return false; return false;
} }
// Supprimer le fichier de verrouillage
if (file_exists($lockFile)) {
unlink($lockFile);
}
return true; return true;
} }

View File

@ -61,17 +61,17 @@ class core extends common
// Crée le fichier de personnalisation avancée // Crée le fichier de personnalisation avancée
if (file_exists(self::DATA_DIR . 'custom.css') === false) { if (file_exists(self::DATA_DIR . 'custom.css') === false) {
file_put_contents(self::DATA_DIR . 'custom.css', ('core/module/theme/resource/custom.css')); $this->secureFilePutContents(self::DATA_DIR . 'custom.css', 'core/module/theme/resource/custom.css');
chmod(self::DATA_DIR . 'custom.css', 0755); chmod(self::DATA_DIR . 'custom.css', 0755);
} }
// Crée le fichier de personnalisation // Crée le fichier de personnalisation
if (file_exists(self::DATA_DIR . self::$siteContent . '/theme.css') === false) { if (file_exists(self::DATA_DIR . self::$siteContent . '/theme.css') === false) {
file_put_contents(self::DATA_DIR . self::$siteContent . '/theme.css', ''); $this->secureFilePutContents(self::DATA_DIR . self::$siteContent . '/theme.css', '');
chmod(self::DATA_DIR . self::$siteContent . '/theme.css', 0755); chmod(self::DATA_DIR . self::$siteContent . '/theme.css', 0755);
} }
// Crée le fichier de personnalisation de l'administration // Crée le fichier de personnalisation de l'administration
if (file_exists(self::DATA_DIR . 'admin.css') === false) { if (file_exists(self::DATA_DIR . 'admin.css') === false) {
file_put_contents(self::DATA_DIR . 'admin.css', ''); $this->secureFilePutContents(self::DATA_DIR . 'admin.css', '');
chmod(self::DATA_DIR . 'admin.css', 0755); chmod(self::DATA_DIR . 'admin.css', 0755);
} }
@ -273,7 +273,7 @@ class core extends common
$css .= '#footerCopyright{text-align:' . $this->getData(['theme', 'footer', 'copyrightAlign']) . '}'; $css .= '#footerCopyright{text-align:' . $this->getData(['theme', 'footer', 'copyrightAlign']) . '}';
// Enregistre la personnalisation // Enregistre la personnalisation
file_put_contents(self::DATA_DIR . self::$siteContent . '/theme.css', $css); $this->secureFilePutContents(self::DATA_DIR . self::$siteContent . '/theme.css', $css);
// Effacer le cache pour tenir compte de la couleur de fond TinyMCE // Effacer le cache pour tenir compte de la couleur de fond TinyMCE
header("Expires: Tue, 01 Jan 2000 00:00:00 GMT"); header("Expires: Tue, 01 Jan 2000 00:00:00 GMT");
@ -368,7 +368,7 @@ class core extends common
// Bordure du contour TinyMCE // Bordure du contour TinyMCE
$css .= '.mce-tinymce{border: 1px solid ' . $this->getData(['admin', 'borderBlockColor']) . '!important;}'; $css .= '.mce-tinymce{border: 1px solid ' . $this->getData(['admin', 'borderBlockColor']) . '!important;}';
// Enregistre la personnalisation // Enregistre la personnalisation
file_put_contents(self::DATA_DIR . 'admin.css', $css); $this->secureFilePutContents(self::DATA_DIR . 'admin.css', $css);
} }
} }
/** /**

View File

@ -60,6 +60,18 @@ class common
// Valeurs possibles multiple de 10, 10 autorise 9 profils, 100 autorise 99 profils // Valeurs possibles multiple de 10, 10 autorise 9 profils, 100 autorise 99 profils
const MAX_PROFILS = 10; const MAX_PROFILS = 10;
const MAX_FILE_WRITE_ATTEMPTS = 5;
/**
* Nombre maximal de tentatives d'encodage JSON
*/
const MAX_JSON_ENCODE_ATTEMPTS = 3;
/**
* Temps d'attente entre les tentatives en secondes
*/
const RETRY_DELAY_SECONDS = 1;
// Constantes pourles contenus // Constantes pourles contenus
// Modalités d'ouverture // Modalités d'ouverture
@ -447,7 +459,7 @@ class common
} }
// Mise à jour des données core // Mise à jour des données core
include('core/include/update.inc.php'); include ('core/include/update.inc.php');
} }
@ -595,7 +607,7 @@ class common
public function setPage($page, $value, $path) public function setPage($page, $value, $path)
{ {
return file_put_contents(self::DATA_DIR . $path . '/content/' . $page . '.html', $value); return $this->secureFilePutContents(self::DATA_DIR . $path . '/content/' . $page . '.html', $value);
} }
@ -634,7 +646,7 @@ class common
{ {
// Tableau avec les données vierges // Tableau avec les données vierges
require_once('core/module/install/ressource/defaultdata.php'); require_once ('core/module/install/ressource/defaultdata.php');
// L'arborescence // L'arborescence
if (!file_exists(self::DATA_DIR . $path)) { if (!file_exists(self::DATA_DIR . $path)) {
@ -669,7 +681,7 @@ class common
public function saveConfig($module) public function saveConfig($module)
{ {
// Tableau avec les données vierges // Tableau avec les données vierges
require_once('core/module/install/ressource/defaultdata.php'); require_once ('core/module/install/ressource/defaultdata.php');
// Installation des données des autres modules cad theme profil font config, admin et core // Installation des données des autres modules cad theme profil font config, admin et core
$this->setData([$module, init::$defaultData[$module]]); $this->setData([$module, init::$defaultData[$module]]);
common::$coreNotices[] = $module; common::$coreNotices[] = $module;
@ -705,65 +717,134 @@ class common
* Fonction pour construire le tableau des pages * Fonction pour construire le tableau des pages
*/ */
private function buildHierarchy() private function buildHierarchy()
{ {
$pages = helper::arrayColumn($this->getData(['page']), 'position', 'SORT_ASC'); $pages = helper::arrayColumn($this->getData(['page']), 'position', 'SORT_ASC');
// Parents // Parents
foreach ($pages as $pageId => $pagePosition) { foreach ($pages as $pageId => $pagePosition) {
if ( if (
// Page parent // Page parent
$this->getData(['page', $pageId, 'parentPageId']) === "" $this->getData(['page', $pageId, 'parentPageId']) === ""
// Ignore les pages dont l'utilisateur n'a pas accès // Ignore les pages dont l'utilisateur n'a pas accès
and ($this->getData(['page', $pageId, 'group']) === self::GROUP_VISITOR and ($this->getData(['page', $pageId, 'group']) === self::GROUP_VISITOR
or ($this->getUser('password') === $this->getInput('ZWII_USER_PASSWORD') or ($this->getUser('password') === $this->getInput('ZWII_USER_PASSWORD')
//and $this->getUser('group') >= $this->getData(['page', $pageId, 'group']) //and $this->getUser('group') >= $this->getData(['page', $pageId, 'group'])
// Modification qui tient compte du profil de la page // Modification qui tient compte du profil de la page
and ($this->getUser('group') * self::MAX_PROFILS + $this->getUser('profil')) >= ($this->getData(['page', $pageId, 'group']) * self::MAX_PROFILS + $this->getData(['page', $pageId, 'profil'])) and ($this->getUser('group') * self::MAX_PROFILS + $this->getUser('profil')) >= ($this->getData(['page', $pageId, 'group']) * self::MAX_PROFILS + $this->getData(['page', $pageId, 'profil']))
) )
) )
) { ) {
if ($pagePosition !== 0) { if ($pagePosition !== 0) {
$this->hierarchy['visible'][$pageId] = []; $this->hierarchy['visible'][$pageId] = [];
} }
if ($this->getData(['page', $pageId, 'block']) === 'bar') { if ($this->getData(['page', $pageId, 'block']) === 'bar') {
$this->hierarchy['bar'][$pageId] = []; $this->hierarchy['bar'][$pageId] = [];
} }
$this->hierarchy['all'][$pageId] = []; $this->hierarchy['all'][$pageId] = [];
} }
} }
// Enfants // Enfants
foreach ($pages as $pageId => $pagePosition) { foreach ($pages as $pageId => $pagePosition) {
if (
// Page parent
$parentId = $this->getData(['page', $pageId, 'parentPageId'])
// Ignore les pages dont l'utilisateur n'a pas accès
and (
(
$this->getData(['page', $pageId, 'group']) === self::GROUP_VISITOR
and
$this->getData(['page', $parentId, 'group']) === self::GROUP_VISITOR
)
or (
$this->getUser('password') === $this->getInput('ZWII_USER_PASSWORD')
and
$this->getUser('group') * self::MAX_PROFILS + $this->getUser('profil')) >= ($this->getData(['page', $pageId, 'group']) * self::MAX_PROFILS + $this->getData(['page', $pageId, 'profil'])
)
)
) {
if ($pagePosition !== 0) {
$this->hierarchy['visible'][$parentId][] = $pageId;
}
if ($this->getData(['page', $pageId, 'block']) === 'bar') {
$this->hierarchy['bar'][$pageId] = [];
}
$this->hierarchy['all'][$parentId][] = $pageId;
}
}
}
/**
* Nombre maximal de tentatives d'écriture dans le fichier
*/
/**
* Écriture sécurisée dans un fichier en utilisant un verrouillage de fichier pour éviter les accès concurrents.
* Les données sont encodées au format JSON si l'extension du fichier est JSON.
*
* @param string $filename Le chemin du fichier dans lequel écrire les données.
* @param mixed $data Les données à écrire dans le fichier.
* @param int $options Les options pour la fonction file_put_contents, par défaut 0.
*
* @return bool Retourne true si l'écriture dans le fichier est réussie, false sinon.
*/
public static function secureFilePutContents($filename, $data, $options = 0)
{
// Vérifier si l'extension du fichier est JSON
$extension = pathinfo($filename, PATHINFO_EXTENSION);
$encodeJson = strtolower($extension) === 'json';
// Tentatives d'encodage JSON si nécessaire
if ($encodeJson) {
$jsonData = null;
$attempts = 0;
while ($attempts < self::MAX_JSON_ENCODE_ATTEMPTS) {
$jsonData = json_encode($data, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT);
if ($jsonData !== false) {
break; // Sortir de la boucle si l'encodage réussit
}
$attempts++;
error_log('Erreur d\'encodage JSON (tentative ' . $attempts . ') : ' . json_last_error_msg());
sleep(self::RETRY_DELAY_SECONDS); // Attendre avant de réessayer
}
if ($jsonData === false) {
error_log('Impossible d\'encoder les données en format JSON.');
return false;
}
} else {
// Pas d'encodage JSON nécessaire
$jsonData = $data;
}
// Écriture sécurisée dans le fichier avec un verrouillage
$attempts = 0;
while ($attempts < self::MAX_FILE_WRITE_ATTEMPTS) {
$lockHandle = fopen($filename . '.lock', 'w');
if (flock($lockHandle, LOCK_EX)) {
$bytesWritten = file_put_contents($filename, $jsonData, $options);
flock($lockHandle, LOCK_UN);
fclose($lockHandle);
if ($bytesWritten !== false && $bytesWritten === strlen($jsonData)) {
return true; // Écriture réussie
}
} else {
fclose($lockHandle);
}
$attempts++;
error_log('Erreur d\'écriture (tentative ' . $attempts . ') : impossible de sauvegarder les données dans ' . $filename);
sleep(self::RETRY_DELAY_SECONDS); // Attendre avant de réessayer
}
error_log('Impossible d\'écrire dans le fichier ' . $filename . ' après ' . self::MAX_FILE_WRITE_ATTEMPTS . ' tentatives.');
return false;
}
if (
// Page parent
$parentId = $this->getData(['page', $pageId, 'parentPageId'])
// Ignore les pages dont l'utilisateur n'a pas accès
and (
(
$this->getData(['page', $pageId, 'group']) === self::GROUP_VISITOR
and
$this->getData(['page', $parentId, 'group']) === self::GROUP_VISITOR
)
or (
$this->getUser('password') === $this->getInput('ZWII_USER_PASSWORD')
and
$this->getUser('group') * self::MAX_PROFILS + $this->getUser('profil')) >= ($this->getData(['page', $pageId, 'group']) * self::MAX_PROFILS + $this->getData(['page', $pageId, 'profil'])
)
)
) {
if ($pagePosition !== 0) {
$this->hierarchy['visible'][$parentId][] = $pageId;
}
if ($this->getData(['page', $pageId, 'block']) === 'bar') {
$this->hierarchy['bar'][$pageId] = [];
}
$this->hierarchy['all'][$parentId][] = $pageId;
}
}
}
/** /**
* Génère un fichier json avec la liste des pages * Génère un fichier json avec la liste des pages
@ -826,7 +907,7 @@ class common
// Enregistrement : 3 tentatives // Enregistrement : 3 tentatives
for ($i = 0; $i < 3; $i++) { for ($i = 0; $i < 3; $i++) {
if (file_put_contents('core/vendor/tinymce/link_list.json', json_encode($parents, JSON_UNESCAPED_UNICODE), LOCK_EX) !== false) { if ($this->secureFilePutContents('core/vendor/tinymce/link_list.json', json_encode($parents, JSON_UNESCAPED_UNICODE), LOCK_EX) !== false) {
break; break;
} }
// Pause de 10 millisecondes // Pause de 10 millisecondes
@ -1118,7 +1199,7 @@ class common
} }
$sitemap->updateRobots(); $sitemap->updateRobots();
} else { } else {
file_put_contents('robots.txt', 'User-agent: *' . PHP_EOL . 'Disallow: /'); $this->secureFilePutContents('robots.txt', 'User-agent: *' . PHP_EOL . 'Disallow: /');
} }
// Submit your sitemaps to Google, Yahoo, Bing and Ask.com // Submit your sitemaps to Google, Yahoo, Bing and Ask.com
@ -1408,7 +1489,7 @@ class common
$dataLog .= $message ? $this->getUrl() . ';' . $message : $this->getUrl(); $dataLog .= $message ? $this->getUrl() . ';' . $message : $this->getUrl();
$dataLog .= PHP_EOL; $dataLog .= PHP_EOL;
if ($this->getData(['config', 'connect', 'log'])) { if ($this->getData(['config', 'connect', 'log'])) {
file_put_contents(self::DATA_DIR . 'journal.log', $dataLog, FILE_APPEND); $this->secureFilePutContents(self::DATA_DIR . 'journal.log', $dataLog, FILE_APPEND);
} }
} }
@ -1435,8 +1516,8 @@ class common
foreach ($courses as $courseId => $value) { foreach ($courses as $courseId => $value) {
// Affiche les espaces gérés par l'éditeur, les espaces où il participe et les espaces anonymes // Affiche les espaces gérés par l'éditeur, les espaces où il participe et les espaces anonymes
if ( if (
// le membre est inscrit // le membre est inscrit
( $this->getData(['enrolment', $courseId]) && array_key_exists($this->getUser('id'), $this->getData(['enrolment', $courseId])) ) ($this->getData(['enrolment', $courseId]) && array_key_exists($this->getUser('id'), $this->getData(['enrolment', $courseId])))
// Il est l'auteur // Il est l'auteur
|| $this->getUser('id') === $this->getData(['course', $courseId, 'author']) || $this->getUser('id') === $this->getData(['course', $courseId, 'author'])
// Le cours est ouvert // Le cours est ouvert
@ -1450,7 +1531,7 @@ class common
foreach ($courses as $courseId => $value) { foreach ($courses as $courseId => $value) {
// Affiche les espaces du participant et les espaces anonymes // Affiche les espaces du participant et les espaces anonymes
if ( if (
($this->getData(['enrolment', $courseId]) && array_key_exists($this->getUser('id'), $this->getData(['enrolment', $courseId])) ) ($this->getData(['enrolment', $courseId]) && array_key_exists($this->getUser('id'), $this->getData(['enrolment', $courseId])))
|| $this->getData(['course', $courseId, 'enrolment']) === self::COURSE_ENROLMENT_GUEST || $this->getData(['course', $courseId, 'enrolment']) === self::COURSE_ENROLMENT_GUEST
) { ) {
$filter[$courseId] = $courses[$courseId]; $filter[$courseId] = $courses[$courseId];

View File

@ -567,7 +567,7 @@ class config extends common
'</IfModule>' . PHP_EOL . '</IfModule>' . PHP_EOL .
'# URL rewriting' . PHP_EOL; '# URL rewriting' . PHP_EOL;
$fileContent = str_replace('# URL rewriting', $rewriteData, $fileContent); $fileContent = str_replace('# URL rewriting', $rewriteData, $fileContent);
file_put_contents( $this->secureFilePutContents(
'.htaccess', '.htaccess',
$fileContent $fileContent
); );
@ -583,7 +583,7 @@ class config extends common
$fileContent = file_get_contents('.htaccess'); $fileContent = file_get_contents('.htaccess');
$fileContent = explode('# URL rewriting', $fileContent); $fileContent = explode('# URL rewriting', $fileContent);
$fileContent = $fileContent[0] . '# URL rewriting' . $fileContent[2]; $fileContent = $fileContent[0] . '# URL rewriting' . $fileContent[2];
file_put_contents( $this->secureFilePutContents(
'.htaccess', '.htaccess',
$fileContent $fileContent
); );
@ -709,10 +709,10 @@ class config extends common
) { ) {
// Ecrire les fichiers de script // Ecrire les fichiers de script
if ($this->geturl(2) === 'head') { if ($this->geturl(2) === 'head') {
file_put_contents(self::DATA_DIR . 'head.inc.html', $this->getInput('configScriptHead', null)); $this->secureFilePutContents(self::DATA_DIR . 'head.inc.html', $this->getInput('configScriptHead', null));
} }
if ($this->geturl(2) === 'body') { if ($this->geturl(2) === 'body') {
file_put_contents(self::DATA_DIR . 'body.inc.html', $this->getInput('configScriptBody', null)); $this->secureFilePutContents(self::DATA_DIR . 'body.inc.html', $this->getInput('configScriptBody', null));
} }
// Valeurs en sortie // Valeurs en sortie
$this->addOutput([ $this->addOutput([
@ -754,7 +754,7 @@ class config extends common
unlink(self::DATA_DIR . 'journal.log'); unlink(self::DATA_DIR . 'journal.log');
// Créer les en-têtes des journaux // Créer les en-têtes des journaux
$d = 'Date;Heure;IP;Id;Action' . PHP_EOL; $d = 'Date;Heure;IP;Id;Action' . PHP_EOL;
file_put_contents(self::DATA_DIR . 'journal.log', $d); $this->secureFilePutContents(self::DATA_DIR . 'journal.log', $d);
// Valeurs en sortie // Valeurs en sortie
$this->addOutput([ $this->addOutput([
'title' => helper::translate('Configuration'), 'title' => helper::translate('Configuration'),
@ -830,7 +830,7 @@ class config extends common
ob_start(); ob_start();
$fileName = self::TEMP_DIR . 'blacklist.log'; $fileName = self::TEMP_DIR . 'blacklist.log';
$d = 'Date dernière tentative;Heure dernière tentative;Id;Adresse IP;Nombre d\'échecs' . PHP_EOL; $d = 'Date dernière tentative;Heure dernière tentative;Id;Adresse IP;Nombre d\'échecs' . PHP_EOL;
file_put_contents($fileName, $d); $this->secureFilePutContents($fileName, $d);
if (file_exists($fileName)) { if (file_exists($fileName)) {
$d = $this->getData(['blacklist']); $d = $this->getData(['blacklist']);
$data = ''; $data = '';
@ -838,7 +838,7 @@ class config extends common
$data .= helper::dateUTF8('%Y %m %d', $item['lastFail'], self::$i18nUI) . ' - ' . helper::dateUTF8('%H:%M', time(), self::$i18nUI); $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; $data .= $key . ';' . $item['ip'] . ';' . $item['connectFail'] . PHP_EOL;
} }
file_put_contents($fileName, $data, FILE_APPEND); $this->secureFilePutContents($fileName, $data, FILE_APPEND);
header('Content-Description: File Transfer'); header('Content-Description: File Transfer');
header('Content-Type: application/octet-stream'); header('Content-Type: application/octet-stream');
header('Content-Transfer-Encoding: binary'); header('Content-Transfer-Encoding: binary');

View File

@ -1597,17 +1597,17 @@ class course extends common
// Participants avec historiques // Participants avec historiques
$enrolment = $this->getData(['enrolment', $courseId]); $enrolment = $this->getData(['enrolment', $courseId]);
// Générer un fichier dans le dossier de l'espace // Générer un fichier dans le dossier de l'espace
file_put_contents(self::DATA_DIR . $courseId . '/enrolment.json', json_encode([$courseId => $enrolment], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT)); $this->secureFilePutContents(self::DATA_DIR . $courseId . '/enrolment.json', [$courseId => $enrolment]);
// Idem pour les données du cours // Idem pour les données du cours
$course = $this->getData(['course', $courseId]); $course = $this->getData(['course', $courseId]);
// Générer un fichier dans le dossier de l'espace // Générer un fichier dans le dossier de l'espace
file_put_contents(self::DATA_DIR . $courseId . '/course.json', json_encode([$courseId => $course], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT)); $this->secureFilePutContents(self::DATA_DIR . $courseId . '/course.json',[$courseId => $course]);
// Idem pour la catégorie // Idem pour la catégorie
$category = $this->getData(['category', $this->getData(['course', $courseId, 'category'])]); $category = $this->getData(['category', $this->getData(['course', $courseId, 'category'])]);
// Générer un fichier dans le dossier de l'espace // Générer un fichier dans le dossier de l'espace
file_put_contents(self::DATA_DIR . $courseId . '/category.json', json_encode([$this->getData(['course', $courseId, 'category']) => $category], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT)); $this->secureFilePutContents(self::DATA_DIR . $courseId . '/category.json', [$this->getData(['course', $courseId, 'category']) => $category]);
// Génère une archive ZIP // Génère une archive ZIP

View File

@ -278,7 +278,7 @@ class install extends common
case 2: case 2:
$success = true; $success = true;
$message = ''; $message = '';
file_put_contents(self::TEMP_DIR . 'update.tar.gz', helper::getUrlContents(common::ZWII_UPDATE_URL . common::ZWII_UPDATE_CHANNEL . '/update.tar.gz')); $this->secureFilePutContents(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 = helper::getUrlContents(common::ZWII_UPDATE_URL . common::ZWII_UPDATE_CHANNEL . '/update.md5');
$md5origin = explode(' ', $md5origin); $md5origin = explode(' ', $md5origin);
$md5target = md5_file(self::TEMP_DIR . 'update.tar.gz'); $md5target = md5_file(self::TEMP_DIR . 'update.tar.gz');
@ -387,7 +387,7 @@ class install extends common
'</IfModule>' . PHP_EOL . '</IfModule>' . PHP_EOL .
'# URL rewriting' . PHP_EOL; '# URL rewriting' . PHP_EOL;
$fileContent = str_replace('# URL rewriting', $rewriteData, $fileContent); $fileContent = str_replace('# URL rewriting', $rewriteData, $fileContent);
$success = file_put_contents( $success = $this->secureFilePutContents(
'.htaccess', '.htaccess',
$fileContent $fileContent
); );

View File

@ -99,7 +99,7 @@ class language extends common
is_array($descripteur['language'][$lang]) is_array($descripteur['language'][$lang])
) { ) {
if ($this->setData(['language', $lang, $descripteur['language'][$lang]])) { if ($this->setData(['language', $lang, $descripteur['language'][$lang]])) {
$success = file_put_contents(self::I18N_DIR . $lang . '.json', json_encode($languageData, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT)); $success = $this->secureFilePutContents(self::I18N_DIR . $lang . '.json', $languageData);
$success = is_int($success) ? true : false; $success = is_int($success) ? true : false;
} }
} }
@ -419,7 +419,7 @@ class language extends common
$this->setData(['locale', $data['locale']]); $this->setData(['locale', $data['locale']]);
} else { } else {
// Sauver sur le disque // Sauver sur le disque
file_put_contents(self::DATA_DIR . $lang . '/locale.json', json_encode($data, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT), LOCK_EX); $this->secureFilePutContents(self::DATA_DIR . $lang . '/locale.json', $data);
} }
// Valeurs en sortie // Valeurs en sortie
@ -501,7 +501,7 @@ class language extends common
$data[$key] = $target; $data[$key] = $target;
} }
} }
file_put_contents(self::I18N_DIR . $lang . '.json', json_encode($data, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT), LOCK_EX); $this->secureFilePutContents(self::I18N_DIR . $lang . '.json', $data);
// Mettre à jour le descripteur // Mettre à jour le descripteur
$this->setData([ $this->setData([
@ -535,7 +535,7 @@ class language extends common
$data[$key] = ''; $data[$key] = '';
} }
} }
file_put_contents(self::I18N_DIR . $lang . '.json', json_encode($data, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT), LOCK_EX); $this->secureFilePutContents(self::I18N_DIR . $lang . '.json', $data);
// Tableau des chaines à traduire dans la langue sélectionnée // Tableau des chaines à traduire dans la langue sélectionnée
foreach ($data as $key => $value) { foreach ($data as $key => $value) {

View File

@ -317,7 +317,7 @@ class plugin extends common
mkdir(self::FILE_DIR . 'source/modules', 0755); mkdir(self::FILE_DIR . 'source/modules', 0755);
} }
// Sauver les données du fichiers // Sauver les données du fichiers
file_put_contents(self::FILE_DIR . 'source/modules/' . $moduleFile, $moduleData); $this->secureFilePutContents(self::FILE_DIR . 'source/modules/' . $moduleFile, $moduleData);
// Installation directe // Installation directe
if (file_exists(self::FILE_DIR . 'source/modules/' . $moduleFile)) { if (file_exists(self::FILE_DIR . 'source/modules/' . $moduleFile)) {
@ -597,7 +597,7 @@ class plugin extends common
$fileName = $moduleId . str_replace('.', '-', $infoModule[$moduleId]['version']) . '.zip'; $fileName = $moduleId . str_replace('.', '-', $infoModule[$moduleId]['version']) . '.zip';
// Régénération du descripteur du module // Régénération du descripteur du module
file_put_contents(self::MODULE_DIR . $moduleId . '/enum.json', json_encode($infoModule[$moduleId], JSON_UNESCAPED_UNICODE)); $this->secureFilePutContents(self::MODULE_DIR . $moduleId . '/enum.json',$infoModule[$moduleId]);
// Construire l'archive // Construire l'archive
$this->makeZip($tmpFolder . $fileName, self::MODULE_DIR . $moduleId); $this->makeZip($tmpFolder . $fileName, self::MODULE_DIR . $moduleId);

View File

@ -304,7 +304,7 @@ class theme extends common
$this->isPost() $this->isPost()
) { ) {
// Enregistre le CSS // Enregistre le CSS
file_put_contents(self::DATA_DIR . 'custom.css', $this->getInput('themeAdvancedCss', null)); $this->secureFilePutContents(self::DATA_DIR . 'custom.css', $this->getInput('themeAdvancedCss', null));
// Valeurs en sortie // Valeurs en sortie
$this->addOutput([ $this->addOutput([
'notification' => helper::translate('Modifications enregistrées'), 'notification' => helper::translate('Modifications enregistrées'),
@ -1305,7 +1305,7 @@ class theme extends common
} }
// Sauvegarder la chaîne modifiée // Sauvegarder la chaîne modifiée
if ($count > 0) { if ($count > 0) {
file_put_contents($file, $data); $this->secureFilePutContents($file, $data);
} }
// Retourner le nombre d'occurrences // Retourner le nombre d'occurrences
return ($count); return ($count);
@ -1411,8 +1411,8 @@ class theme extends common
} }
// Enregistre la personnalisation // Enregistre la personnalisation
file_put_contents(self::DATA_DIR . 'font/font.html', $fileContent); $this->secureFilePutContents(self::DATA_DIR . 'font/font.html', $fileContent);
// Enregistre la personnalisation // Enregistre la personnalisation
file_put_contents(self::DATA_DIR . 'font/font.css', $fileContentCss); $this->secureFilePutContents(self::DATA_DIR . 'font/font.css', $fileContentCss);
} }
} }

View File

@ -260,7 +260,7 @@ class gallery extends common
$content = str_replace('#legendBgColor#', $this->getData(['module', $this->getUrl(0), 'theme', 'legendBgColor']), $content); $content = str_replace('#legendBgColor#', $this->getData(['module', $this->getUrl(0), 'theme', 'legendBgColor']), $content);
// Ecriture de la feuille de style // Ecriture de la feuille de style
file_put_contents(self::DATADIRECTORY . $this->getUrl(0) . '/theme.css', $content . $themeCss); $this->secureFilePutContents(self::DATADIRECTORY . $this->getUrl(0) . '/theme.css', $content . $themeCss);
// Nom de la feuille de style // Nom de la feuille de style
$this->setData(['module', $this->getUrl(0), 'theme', 'style', $fileCSS]); $this->setData(['module', $this->getUrl(0), 'theme', 'style', $fileCSS]);
} }
@ -894,7 +894,7 @@ class gallery extends common
$content = str_replace('#legendHeight#', $this->getinput('galleryThemeLegendHeight'), $content); $content = str_replace('#legendHeight#', $this->getinput('galleryThemeLegendHeight'), $content);
$content = str_replace('#legendTextColor#', $this->getinput('galleryThemeLegendTextColor'), $content); $content = str_replace('#legendTextColor#', $this->getinput('galleryThemeLegendTextColor'), $content);
$content = str_replace('#legendBgColor#', $this->getinput('galleryThemeLegendBgColor'), $content); $content = str_replace('#legendBgColor#', $this->getinput('galleryThemeLegendBgColor'), $content);
$success = is_int(file_put_contents(self::DATADIRECTORY . $this->getUrl(0) . '/theme.css', $content . $themeCss)); $success = is_int($this->secureFilePutContents(self::DATADIRECTORY . $this->getUrl(0) . '/theme.css', $content . $themeCss));
// Valeurs en sortie // Valeurs en sortie
$this->addOutput([ $this->addOutput([
'redirect' => helper::baseUrl() . $this->getUrl() . '/theme', 'redirect' => helper::baseUrl() . $this->getUrl() . '/theme',

View File

@ -281,7 +281,7 @@ class news extends common
mkdir(self::DATADIRECTORY . $this->getUrl(0) . '/theme.css', 0755, true); mkdir(self::DATADIRECTORY . $this->getUrl(0) . '/theme.css', 0755, true);
} }
$success = is_int(file_put_contents(self::DATADIRECTORY . $this->getUrl(0) . '/theme.css', $style)); $success = is_int($this->secureFilePutContents(self::DATADIRECTORY . $this->getUrl(0) . '/theme.css', $style));
// Fin feuille de style // Fin feuille de style
@ -643,7 +643,7 @@ class news extends common
$style .= '}'; $style .= '}';
// Sauver la feuille de style // Sauver la feuille de style
file_put_contents(self::DATADIRECTORY . $this->getUrl(0) . '/theme.css', $style); $this->secureFilePutContents(self::DATADIRECTORY . $this->getUrl(0) . '/theme.css', $style);
// Stocker le nom de la feuille de style // Stocker le nom de la feuille de style
$this->setData(['module', $this->getUrl(0), 'theme', 'style', self::DATADIRECTORY . $this->getUrl(0) . '/theme.css']); $this->setData(['module', $this->getUrl(0), 'theme', 'style', self::DATADIRECTORY . $this->getUrl(0) . '/theme.css']);
} }

View File

@ -106,7 +106,7 @@ class search extends common
// Générer la feuille de CSS // Générer la feuille de CSS
$style = '.keywordColor {background: ' . $this->getData(['module', $this->getUrl(0), 'theme', 'keywordColor']) . ';}'; $style = '.keywordColor {background: ' . $this->getData(['module', $this->getUrl(0), 'theme', 'keywordColor']) . ';}';
// Sauver la feuille de style // Sauver la feuille de style
file_put_contents(self::DATADIRECTORY . $this->getUrl(0) . '/theme.css', $style); $this->secureFilePutContents(self::DATADIRECTORY . $this->getUrl(0) . '/theme.css', $style);
// Stocker le nom de la feuille de style // Stocker le nom de la feuille de style
$this->setData(['module', $this->getUrl(0), 'theme', 'style', $fileCSS]); $this->setData(['module', $this->getUrl(0), 'theme', 'style', $fileCSS]);
} }
@ -128,7 +128,7 @@ class search extends common
// Générer la feuille de CSS // Générer la feuille de CSS
$style = '.keywordColor {background:' . $this->getInput('searchKeywordColor') . ';}'; $style = '.keywordColor {background:' . $this->getInput('searchKeywordColor') . ';}';
$success = is_int(file_put_contents(self::DATADIRECTORY . $this->getUrl(0) . '/theme.css', $style)); $success = is_int($this->secureFilePutContents(self::DATADIRECTORY . $this->getUrl(0) . '/theme.css', $style));
// Fin feuille de style // Fin feuille de style
// Soumission du formulaire // Soumission du formulaire