Browse Source

Refactoring complet du plugin pour simplifier et fiabiliser le code en plus d'utiliser le plugin Archiviste.

master
Eric Lupinacci 1 year ago
parent
commit
bf2ee46a1c
  1. 26
      action/archive_mf_supprimer.php
  2. 34
      action/archive_mf_telecharger.php
  3. 46
      action/mes_fichiers_sauver.php
  4. 33
      action/mes_fichiers_telecharger.php
  5. 44
      formulaires/archive_mf_creer.html
  6. 63
      formulaires/archive_mf_creer.php
  7. 2
      formulaires/configurer_mes_fichiers.html
  8. 46
      formulaires/mes_fichiers_sauver.php
  9. 6
      genie/archive_mf_generer.php
  10. 18
      genie/archive_mf_nettoyer.php
  11. 17
      genie/mes_fichiers_cleaner.php
  12. 14
      genie/mes_fichiers_cron.php
  13. 300
      inc/mes_fichiers.php
  14. 254
      inc/mes_fichiers_archive_mf.php
  15. 68
      inc/mes_fichiers_cleaner.php
  16. 45
      inc/mes_fichiers_destinataires.php
  17. 98
      inc/mes_fichiers_sauver.php
  18. 274
      inc/mes_fichiers_utils.php
  19. 9
      lang/mes_fichiers_fr.php
  20. 48
      mes_fichiers_fonctions.php
  21. 16
      notifications/archive_mf_creer.php
  22. 35
      notifications/archive_mf_nettoyer.php
  23. 37
      notifications/mes_fichiers_cleaner.php
  24. 2
      paquet.xml
  25. 23
      prive/squelettes/contenu/mes_fichiers.html
  26. 29
      prive/squelettes/liste/archives_mf.html
  27. 6
      prive/squelettes/liste/archives_mf_fonctions.php
  28. 84
      prive/squelettes/liste/mes_fichiers_fonctions.php

26
action/archive_mf_supprimer.php

@ -0,0 +1,26 @@
<?php
if (!defined('_ECRIRE_INC_VERSION')) {
return;
}
function action_archive_mf_supprimer() {
// Securisation de l'argument nom de l'archive
$securiser_action = charger_fonction('securiser_action', 'inc');
$chemin_archive = $securiser_action();
// Si l'archive n'est pas accessible on renvoie une erreur
if (!@is_readable($chemin_archive)) {
spip_log("L'archive ${chemin_archive} n'est pas accessible pour le téléchargement", 'mes_fichiers' . _LOG_ERREUR);
redirige_par_entete(generer_url_ecrire('mes_fichiers', 'etat=nok_supp', true));
}
// Autorisation
if (!autoriser('webmestre')) {
include_spip('inc/minipres');
echo minipres();
exit;
}
include_spip('inc/flock');
supprimer_fichier($chemin_archive);
}

34
action/archive_mf_telecharger.php

@ -0,0 +1,34 @@
<?php
if (!defined('_ECRIRE_INC_VERSION')) {
return;
}
function action_archive_mf_telecharger() {
// Securisation de l'argument nom de l'archive
$securiser_action = charger_fonction('securiser_action', 'inc');
$chemin_archive = $securiser_action();
// Si l'archive n'est pas accessible on renvoie une erreur
if (!@is_readable($chemin_archive)) {
spip_log("L'archive ${chemin_archive} n'est pas accessible pour le téléchargement", 'mes_fichiers' . _LOG_ERREUR);
redirige_par_entete(generer_url_ecrire('mes_fichiers', 'etat=nok_tele', true));
}
// Autorisation
if (!autoriser('webmestre')) {
include_spip('inc/minipres');
echo minipres();
exit;
}
// Telechargement du fichier d'archive
header('Content-Description: File Transfer');
header('Content-type: application/zip');
header('Content-Disposition: attachment; filename="' . basename($chemin_archive) . '"');
header('Content-Transfer-Encoding: binary');
header('Pragma: public');
header('Expires: 0');
header('Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0');
header('Content-Length: ' . filesize($chemin_archive));
readfile($chemin_archive);
}

46
action/mes_fichiers_sauver.php

@ -1,46 +0,0 @@
<?php
if (!defined('_ECRIRE_INC_VERSION')) {
return;
}
function action_mes_fichiers_sauver() {
// Securisation: aucun argument attendu
// Autorisation
if (!autoriser('sauvegarder')) {
include_spip('inc/minipres');
echo minipres();
exit;
}
$liste = _request('a_sauver');
if (is_null($liste)) {
$liste = array();
}
$sauver = charger_fonction('mes_fichiers_sauver', 'inc');
$erreur = $sauver($liste);
if (_request('redirect')) {
// TODO : verifier si ce cas est encore utilise
if ($erreur) {
$redirect = parametre_url(
urldecode(_request('redirect')),
'etat',
'nok_sauve',
'&'
);
} else {
$redirect = parametre_url(
urldecode(_request('redirect')),
'etat',
'ok_sauve',
'&'
);
}
include_spip('inc/headers');
redirige_par_entete($redirect);
} else {
return $erreur;
}
}

33
action/mes_fichiers_telecharger.php

@ -1,33 +0,0 @@
<?php
if (!defined('_ECRIRE_INC_VERSION')) {
return;
}
function action_mes_fichiers_telecharger() {
// Securisation de l'argument nom de l'archive
$securiser_action = charger_fonction('securiser_action', 'inc');
$arg = $securiser_action();
// Si l'archive n'est pas accessible on renvoie une erreur
if (!@is_readable($arg)) {
spip_log("L'archive ${arg} n'est pas accessible pour le téléchargement", 'mes_fichiers' . _LOG_ERREUR);
redirige_par_entete(generer_url_ecrire('mes_fichiers', 'etat=nok_tele', true));
}
// Autorisation
if (!autoriser('sauvegarder')) {
include_spip('inc/minipres');
echo minipres();
exit;
}
// Telechargement du fichier
header('Content-type: application/force-download;');
header('Content-Transfer-Encoding: application/zip');
header('Content-Length: ' . filesize($arg));
header('Content-Disposition: attachment; filename="' . basename($arg) . '"');
header('Pragma: no-cache');
header('Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0, public');
header('Expires: 0');
readfile($arg);
}

44
formulaires/mes_fichiers_sauver.html → formulaires/archive_mf_creer.html

@ -6,33 +6,20 @@
<form method="post" action="#ENV{action}"><div>
#ACTION_FORMULAIRE{#ENV{action}}
<p><:mes_fichiers:info_liste_a_sauver:></p>
#SET{name,a_sauver}#SET{obli,''}#SET{erreurs,#ENV**{erreurs/#GET{name}}}
<B_sauver>
<ul>
<li id="liste_a_sauver">
<div class="editer-groupe">
<div class="editer pleine_largeur editer_[(#GET{name})][ (#GET{obli})][ (#GET{erreurs}|oui)erreur]" id="liste_a_sauver">
<label class="label"><:mes_fichiers:info_liste_a_sauver:></label>[
<span class='erreur_message'>(#GET{erreurs})</span>]
<BOUCLE_sauver(DATA){source table, #ENV**{_fichiers}}>
[(#SET{taille_config,[(#CONFIG{mes_fichiers/taille_max_rep,500})]})]
[(#SET{taille_max,[(#GET{taille_config}|mult{1000}|mult{1000})]})]
[(#VALEUR|is_dir|oui)
[(#SET{taille,[(#VALEUR|mes_fichiers_dirsize)]})]
[(#SET{disabled,[(#GET{taille}|>{#GET{taille_max}}|?{'disabled="disabled"',''})]})]
]
[(#VALEUR|is_dir|non)
[(#SET{taille,[(#VALEUR|filesize)]})]
[(#SET{disabled,''})]
]
<div class="choix">
[(#GET{disabled}|oui)
<span class="erreur_message">
]
<input type="checkbox" name="a_sauver[]" class="checkbox" id="champ_#COMPTEUR_BOUCLE" value="#VALEUR"[ (#GET{disabled})] />
<input type="checkbox" name="#GET{name}\[\]" class="checkbox" id="champ_#COMPTEUR_BOUCLE" value="#CLE"[(#VALEUR{disable}|oui) disabled="disabled"] />
[<label for="champ_#COMPTEUR_BOUCLE">
(#VALEUR|mes_fichiers_joli_repertoire)
[(#VALEUR|is_dir|oui)[((#GET{taille}|mes_fichiers_size_readable))]]
[(#VALEUR|is_dir|non)[((#GET{taille}|mes_fichiers_size_readable))]]</label>]
[(#GET{disabled}|oui)
<br /><:mes_fichiers:erreur_repertoire_trop_grand{taille_max=#GET{taille_config}}:></span>
]
(#CLE|mes_fichiers_afficher_dossier)
[((#VALEUR{taille})[(#VALEUR{disable}|oui) <:mes_fichiers:erreur_repertoire_trop_grand{taille_max=#ENV{limite_max}}:>])]
</label>]
</div>
</BOUCLE_sauver>
<p>
@ -41,16 +28,15 @@
<a id="decocher_tout" href="#liste_a_sauver"><:mes_fichiers:bouton_tout_decocher:></a>
</small>
</p>
</li>
</ul>
</div>
</div>
[(#EDITABLE|oui)
<p class="boutons">
<input type="submit" class="submit" value="<:mes_fichiers:bouton_sauver:>" />
</p>
</p>]
</B_sauver>
#BOITE_OUVRIR{'', notice}
<:mes_fichiers:message_rien_a_sauver:>
#BOITE_FERMER
[(#ALERTE_MESSAGE{<:mes_fichiers:message_rien_a_sauver:>, '', notice})]
<//B_sauver>
</div></form>
</div>

63
formulaires/archive_mf_creer.php

@ -0,0 +1,63 @@
<?php
if (!defined('_ECRIRE_INC_VERSION')) {
return;
}
function formulaires_archive_mf_creer_charger_dist() {
// On charge la liste de tous fichiers/dossiers pouvant être archivés sans filtrer par la taille max
include_spip('inc/mes_fichiers');
$liste = mes_fichiers_lister();
// Taille max des fichiers/dossiers autorisés
$megaoctets_max = intval(lire_config('mes_fichiers/taille_max_rep', '75'));
// Convertir la taille max de Mo en octets pour comparaison
$octets_max = taille_convertir_en_octets($megaoctets_max);
// On prépare la liste des fichiers/dossiers pour un affichage simple dans le formulaire
include_spip('mes_fichiers_fonctions');
$chemins = [];
foreach ($liste as $_chemin) {
// Calcul de la taille des fichiers/dossiers
$octets = mes_fichiers_lire_taille($_chemin);
$chemins[$_chemin]['taille'] = mes_fichiers_afficher_taille($octets);
$chemins[$_chemin]['disable'] = ($octets_max > 0) && ($octets > $octets_max);
}
return [
'_fichiers' => $chemins,
'limite_max' => mes_fichiers_afficher_taille($octets_max),
'editable' => autoriser('sauvegarder')
];
}
function formulaires_archive_mf_creer_verifier_dist() {
// Initialisation des erreurs de saisie
$erreurs = [];
// Il devient obligatoire de saisir une liste non vide à archiver
if (!_request('a_sauver')) {
$erreurs['a_sauver'] = _T('info_obligatoire');
}
return $erreurs;
}
function formulaires_archive_mf_creer_traiter_dist() {
// Récupération de la liste des fichiers à archiver
$chemins = _request('a_sauver');
// Lancement de l'archivage
include_spip('inc/mes_fichiers_archive_mf');
$erreur = archive_mf_creer($chemins);
if ($erreur) {
$retour['message_erreur'] = _T('mes_fichiers:message_sauvegarde_nok', ['erreur' => $erreur]);
} else {
$retour['message_ok'] = _T('mes_fichiers:message_sauvegarde_ok');
}
return $retour;
}

2
formulaires/configurer_mes_fichiers.html

@ -10,7 +10,7 @@
<li class="editer editer_prefixe obligatoire">
<p class="explication"><:mes_fichiers:explication_cfg_prefixe:></p>
<label for="prefixe"><:mes_fichiers:label_cfg_prefixe:></label>
<input type="text" name="prefixe" class="text" id="prefixe" value="[(#ENV{prefixe, mf2})]" />
<input type="text" name="prefixe" class="text" id="prefixe" value="[(#ENV{prefixe, mf3})]" />
</li>
<li class="editer editer_taille_max_rep obligatoire">
<p class="explication"><:mes_fichiers:explication_cfg_taille_max_rep:></p>

46
formulaires/mes_fichiers_sauver.php

@ -1,46 +0,0 @@
<?php
if (!defined('_ECRIRE_INC_VERSION')) {
return;
}
function formulaires_mes_fichiers_sauver_charger_dist() {
// On charge la liste des fichiers pouvant être archivés
include_spip('inc/mes_fichiers_utils');
return [
'_fichiers' => mes_fichiers_a_sauver(),
'editable' => autoriser('sauvegarder')
];
}
function formulaires_mes_fichiers_sauver_verifier_dist() {
// Initialisation des erreurs de saisie
$erreurs = [];
// Il devient obligatoire de saisir une liste non vide à archiver
if (!_request('a_sauver')) {
$erreurs['a_sauver'] = _T('info_obligatoire');
}
return $erreurs;
}
function formulaires_mes_fichiers_sauver_traiter_dist() {
// Récupération de la liste des fichiers à archiver
$chemins = _request('a_sauver');
// Lancement de l'archivage
$archiver = charger_fonction('mes_fichiers_sauver', 'inc');
$erreur = $archiver($chemins);
if ($erreur) {
$retour['message_erreur'] = _T('mes_fichiers:message_sauvegarde_nok', ['erreur' => $erreur]);
} else {
$retour['message_ok'] = _T('mes_fichiers:message_sauvegarde_ok');
}
return $retour;
}

6
genie/mes_fichiers_sauver.php → genie/archive_mf_generer.php

@ -10,11 +10,11 @@ if (!defined('_ECRIRE_INC_VERSION')) {
*
* @return int
*/
function genie_mes_fichiers_sauver_dist($last) {
function genie_archive_mf_generer_dist($last) {
// On lance la sauvegarde périodique de tous les fichiers possibles avec comme auteur le CRON
$archiver = charger_fonction('mes_fichiers_sauver', 'inc');
$archiver(null, array('auteur' => 'cron'));
include_spip('inc/mes_fichiers_archive_mf');
archive_mf_creer(null, ['auteur' => 'cron']);
return 1;
}

18
genie/archive_mf_nettoyer.php

@ -0,0 +1,18 @@
<?php
if (!defined('_ECRIRE_INC_VERSION')) {
return;
}
/**
* Nettoyage journalier des archives obsolètes.
*
* @param timestamp $last
*/
function genie_archive_mf_nettoyer_dist($last) {
// On supprime les archives obsolètes en fonction de la duree de conservation.
include_spip('inc/mes_fichiers_archive_mf');
archive_mf_nettoyer(['auteur' => 'cron']);
return 1;
}

17
genie/mes_fichiers_cleaner.php

@ -1,17 +0,0 @@
<?php
if (!defined('_ECRIRE_INC_VERSION')) {
return;
}
/**
* Nettoyage journalier des fichiers obsoletes.
*
* @param timestamp $last
*/
function genie_mes_fichiers_cleaner_dist($last) {
// On supprime les fichiers obsoletes en fonction de la duree de conservation
$supprimer_obsoletes = charger_fonction('mes_fichiers_cleaner', 'inc');
$supprimer_obsoletes(array('auteur' => 'cron'));
return 1;
}

14
genie/mes_fichiers_cron.php

@ -11,17 +11,17 @@ if (!defined('_ECRIRE_INC_VERSION')) {
* @param array $taches_generales
*/
function mes_fichiers_taches_generales_cron($taches_generales) {
include_spip('inc/config');
$sauver_auto = (lire_config('mes_fichiers/sauvegarde_reguliere', 'non') == 'oui');
if ($sauver_auto) {
include_spip('inc/config');
if (lire_config('mes_fichiers/sauvegarde_reguliere', 'non') === 'oui') {
// Archivage journalière de tous les fichiers possibles
$jour = lire_config('mes_fichiers/frequence', 1);
$taches_generales['mes_fichiers_sauver'] = $jour * 24 * 3600;
$taches_generales['archive_mf_generer'] = $jour * 24 * 3600;
}
$laver_auto = (lire_config('mes_fichiers/nettoyage_journalier', 'oui') == 'oui');
if ($laver_auto) {
$taches_generales['mes_fichiers_cleaner'] = 24 * 3600;
if (lire_config('mes_fichiers/nettoyage_journalier', 'oui') === 'oui') {
// Nettoyage journalier des archives obsolètes
$taches_generales['archive_mf_nettoyer'] = 24 * 3600;
}
return $taches_generales;

300
inc/mes_fichiers.php

@ -0,0 +1,300 @@
<?php
if (!defined('_ECRIRE_INC_VERSION')) {
return;
}
/**
* Renvoie la liste des fichiers et repertoires pouvant être sauvegarder, en filtrant ou pas selon une taille
* maximale.
*
* @api
*
* @uses dossier_trouver_fichier_recent()
* @uses mes_fichiers_filtrer()
*
* @param bool $filtrer_max_octets Indique si la liste doit être filtrée en fonction d'une taille maximale
* (configurée).
*
* @return array Liste des fichiers et repertoires pouvant être sauvegarder
*/
function mes_fichiers_lister($filtrer_max_octets = false) {
// Constituer la liste des fichiers et dossiers pouvant être sauvegardés
// -- on garde en statique la liste complète non filtrée
static $liste = array();
if (!$liste) {
// Dans le cas de la mutu, les fichiers de personnalisation sont places
// - soit dans le site d'un sous-domaine, il faut donc aller les chercher a la racine de ce sous-domaine
// en utilisant _DIR_SITE
// - soit dans le site principal, il faut dans ce cas utiliser _DIR_RACINE
$dir_site = defined('_DIR_SITE')
? _DIR_SITE
: _DIR_RACINE;
// Rechercher le fichier sqlite le plus récent depuis config/bases
$tmp_db = defined('_DIR_DB') ? _DIR_DB : $dir_site . 'config/bases/';
if ($fichier_db = dossier_trouver_fichier_recent($tmp_db)) {
$liste[] = $fichier_db;
}
// le fichier d'options si il existe
if (
@is_readable($f = $dir_site . _NOM_PERMANENTS_INACCESSIBLES . _NOM_CONFIG . '.php')
or (!defined('_DIR_SITE') && @is_readable($f = _FILE_OPTIONS))
) {
$liste[] = $f;
}
// le fichier .htaccess a la racine qui peut contenir des persos
$htaccess = defined('_ACCESS_FILE_NAME') ? _DIR_RACINE . _ACCESS_FILE_NAME : _DIR_RACINE . '.htaccess';
if (@is_readable($htaccess)) {
$liste[] = $htaccess;
}
// le fameux repertoire des documents et images
$IMG = defined('_DIR_IMG') ? _DIR_IMG : $dir_site . 'IMG/';
if (@is_dir($IMG)) {
$liste[] = $IMG;
}
// le(s) dossier(s) des squelettes nommes
if (strlen($GLOBALS['dossier_squelettes'])) {
// Dans le cas d'une mutu, la globale est toujours mise à jour sous la forme sites/domaine/squelettes
// Cela revient donc au même que pour une install non mutualisée, il faut donc utiliser _DIR_RACINE
foreach (explode(':', $GLOBALS['dossier_squelettes']) as $_dir) {
$dir = ($_dir[0] == '/' ? '' : _DIR_RACINE) . $_dir . '/';
if (@is_dir($dir)) {
$liste[] = $dir;
}
}
} elseif (@is_dir($dir_site . 'squelettes/')) {
$liste[] = $dir_site . 'squelettes/';
}
// le dernier fichier de dump de la base
$tmp_dump = defined('_DIR_DUMP')
? _DIR_DUMP
: $dir_site . 'tmp/dump/';
if ($fichier_dump = dossier_trouver_fichier_recent($tmp_dump)) {
$liste[] = $fichier_dump;
}
// On ajoute via un pipeline pour déclarer des fichiers à sauvegarder provenant de plugins
// et on renvoie la liste complète sans doublons.
$liste_en_plus = pipeline('mes_fichiers_a_sauver', []);
$liste = array_unique(array_merge($liste, $liste_en_plus));
}
// Filtrage de la liste si demandé
if ($filtrer_max_octets) {
$liste = mes_fichiers_filtrer($liste);
}
return $liste;
}
/**
* Filtre la liste des fichiers et dossiers à archiver selon la taille maximale configurée.
* Si aucune limite n'est précisée en configuration, la liste n'est pas filtrée.
*
* @api
*
* @uses taille_convertir_en_octets()
* @uses mes_fichiers_lire_taille()
*
* @param array $liste Liste des fichiers et repertoires pouvant être sauvegarder quelque soit leur taille
*
* @return array Liste des fichiers/dossiers filtrée selon la taille
*/
function mes_fichiers_filtrer($liste) {
// Extraction de la taille max en mega octets et vérification de la nécessité de filtrer la liste
include_spip('inc/config');
$megaoctets_max = intval(lire_config('mes_fichiers/taille_max_rep', '75'));
if ($megaoctets_max > 0) {
// Convertir la taille max de Mo en octets pour comparaison
$octets_max = taille_convertir_en_octets($megaoctets_max);
// Exclusion des fichiers ou dossiers trop volumineux
foreach ($liste as $_cle => $_chemin) {
// Calcul de la taille du fichier ou dossier
$taille_octets = mes_fichiers_lire_taille($_chemin);
if ($taille_octets > $octets_max) {
unset($liste[$_cle]);
}
}
}
return $liste;
}
/**
* Renvoie la taille d'un fichier ou d'un répertoire exprimée en octets.
*
* @uses dossier_calculer_taille()
*
* @param string $chemin Chemin vers le fichier ou le dossier concerné
*
* @return int Taille du dossier ou du fichier en octets
*/
function mes_fichiers_lire_taille($chemin) {
return is_dir($chemin)
? dossier_calculer_taille($chemin)
: filesize($chemin);
}
/**
* Renvoie un chemin de dossier le plus propre possible en gérant le cas d'un SPIP mutualisé ou non.
*
* @uses joli_repertoire()
*
* @param string $dossier Chemin du dossier à afficher d'une manière la plus lisible.
*/
function mes_fichiers_afficher_dossier($dossier) {
if (
defined('_DIR_SITE')
and preg_match(',' . _DIR_SITE . ',', $dossier)
) {
$joli_repertoire = str_replace(_DIR_SITE, '', $dossier);
} else {
include_spip('inc/utils');
$joli_repertoire = joli_repertoire($dossier);
}
return $joli_repertoire;
}
// ----------------------------
/**
* Renvoie le fichier le plus récent d'un dossier donné.
* Le dossier ne doit contenir que des fichiers concernant le même sujet.
*
* @param $dossier
*
* @return string
*/
function dossier_trouver_fichier_recent($dossier) {
// Par défaut, si le dossier est vide on renvoie un nom de fichier vide
$fichier_recent = '';
// On considère que dans le dossier tous les fichiers concernent le même sujet, il est donc inutile
// d'utiliser un pattern pour le fichier.
include_spip('inc/flock');
$fichiers = preg_files($dossier);
$mtime_recent = 0;
foreach ($fichiers as $_fichier) {
if (($mtime = filemtime($_fichier)) > $mtime_recent) {
$fichier_recent = $_fichier;
$mtime_recent = $mtime;
}
}
return $fichier_recent;
}
/**
* Calculer la taille d'un répertoire en itérant sur son contenu.
*
* @link http://aidanlister.com/repos/v/function.dirsize.php
*
* @param string $path Chemin vers le dossier concerné
*
* @return int
*/
function dossier_calculer_taille($path) {
// Par défaut, erreur ou pas, le dossier est vide
$size = 0;
// Trailing slash
if (substr($path, -1, 1) !== DIRECTORY_SEPARATOR) {
$path .= DIRECTORY_SEPARATOR;
}
// Sanity check
if (is_file($path)) {
$size = filesize($path);
} elseif (is_dir($path)) {
// Iterate queue
$queue = array($path);
for ($i = 0, $j = count($queue); $i < $j; ++$i) {
// Open directory
if (is_dir($queue[$i]) && $dir = @dir($queue[$i])) {
$subdirs = array();
while (false !== ($entry = $dir->read())) {
// Skip pointers
if ($entry == '.' || $entry == '..') {
continue;
}
// Get list of directories or filesizes
$path = $queue[$i] . $entry;
if (is_dir($path)) {
$path .= DIRECTORY_SEPARATOR;
$subdirs[] = $path;
} elseif (is_file($path)) {
$size += filesize($path);
}
}
// Add subdirectories to start of queue
unset($queue[0]);
$queue = array_merge($subdirs, $queue);
// Recalculate stack size
$i = -1;
$j = count($queue);
// Clean up
$dir->close();
unset($dir);
}
}
}
return $size;
}
/**
* Convertit en octets une taille exprimée en multiple d'octets, en considérant le système d'unité utilisé, à savoir,
* le système international en base 10 ou le système binaire.
*
* @param int $taille Taille dans l'unité spécifiée en second argument
* @param string $unite Abbréviation de l'unité, à savoir, `K`, `M` (défaut), `G` ou `T`.
* @param string $systeme Système d'unité dans lequel calculer et afficher la taille lisble. Vaut `BI` (défaut) ou `SI`.
*
* @return int
*/
function taille_convertir_en_octets($taille, $unite = 'M', $systeme = 'BI') {
static $puissances = [
'k' => 1,
'm' => 2,
'g' => 3,
't' => 4,
];
static $bases = [
'si' => 1000,
'bi' => 1024
];
// Si l'unité est incorrecte on renvoie 0
$taille_octets = 0;
if (
($unite = strtolower($unite))
and array_key_exists($unite, $puissances)
and ($systeme = strtolower($systeme))
and array_key_exists($systeme, $bases)
) {
return (int)$taille * pow($bases[$systeme], $puissances[$unite]);
}
return $taille_octets;
}

254
inc/mes_fichiers_archive_mf.php

@ -0,0 +1,254 @@
<?php
if (!defined('_ECRIRE_INC_VERSION')) {
return;
}
if (!defined('_MES_FICHIERS_DOSSIER')) {
/**
* Repertoire de stockage des archives
*/
define('_MES_FICHIERS_DOSSIER', _DIR_TMP . 'mes_fichiers/');
}
/**
* La fonction de sauvegarde des fichiers.
*
* @api
*
* @param array|null $liste Liste des dossiers ou fichiers à archiver ou null pour archiver tout ce qui est possible
* @param array $options Options d'archivage. Pour l'instant uniquement l'auteur ayant déclenché l'archivage.
*
* @return string Message d'erreur éventuel ou chaine vide sinon.
*/
function archive_mf_creer($liste = null, $options = array()) {
// Message d'erreur en retour de la fonction : chaine si pas d'erreur
$erreur = '';
// Si on a passé null pour la liste des fichiers, c'est que l'on veut sauvegarder tout ce qui est possible
// En effet, ce peut être un array vide dans le cas d'un problème de config.
include_spip('inc/mes_fichiers');
if (is_null($liste)) {
// Les répertoires et fichiers qui excèdent la taille maximale configurée sont exclus
$liste = mes_fichiers_lister(true);
}
// Identification de l'auteur ayant déclenché l'archivage
$auteur = !empty($options['auteur'])
? $options['auteur']
: $GLOBALS['visiteur_session']['id_auteur'];
// Si il y a quelque chose à archiver
if (count($liste) > 0) {
// On stocke les fichiers et répertoires source pour insérer cette liste en commentaire de l'archive
$liste_finale = [];
foreach ($liste as $_chemin) {
$liste_finale[] = mes_fichiers_afficher_dossier($_chemin);
}
// On construit le nom de l'archive et on crée le répertoire d'accueil si il n'existe pas déjà.
$dir = sous_repertoire(_MES_FICHIERS_DOSSIER);
$prefixe = lire_config('mes_fichiers/prefixe', 'mf3');
$chemin_archive = $dir . $prefixe . '_' . date('Ymd_His') . '.zip';
// On prépare le commentaire
if ($auteur === 'cron') {
$auteur = 'SPIP';
}
$meta = [
'auteur' => $auteur,
'contenu' => $liste_finale
];
// On lance l'archivage du contenu.
include_spip('inc/archives');
$archive = new Spip\Archives\SpipArchives($chemin_archive);
if (!$archive->emballer($liste)) {
// -- on renvoie le message d'erreur provenant de la librairie d'archivage
$erreur = $archive->message();
} else {
// -- si pas d'erreur, on ajoute le commentaire
$archive->commenter(serialize($meta));
}
} else {
$erreur = _T('mes_fichiers:erreur_aucun_fichier_sauver');
}
// Un pipeline post_sauvegarde pour que d'autres plugins puissent agir à ce moment là.
pipeline(
'post_sauvegarde',
array(
'args' => array(
'err' => $erreur,
'auteur' => $auteur,
'type' => 'mes_fichiers_sauver'
),
'data' => ''
)
);
// Notifications si nécessaire.
if ($notifications = charger_fonction('notifications', 'inc')) {
$notifications(
'archive_mf_creer',
'',
array(
'auteur' => $auteur,
'err' => $erreur)
);
}
return $erreur;
}
/**
* Supprime les fichiers d'archive considérés comme obsolètes.
* La fonction retourne la liste des archives effectivement supprimées.
*
* @api
*
* @param array $options
*
* @return array Liste des archives effectivement supprimées.
*/
function archive_mf_nettoyer($options = array()) {
// Initialiser la liste des archives supprimées fournie en retour
$liste = [];
// Supprimer les archives dont l'échéance de garde est échue
include_spip('inc/config');
$duree_sauvegarde = intval(lire_config('mes_fichiers/duree_sauvegarde', 15));
if ($duree_sauvegarde > 0) {
// Stocker la date actuelle pour calculer l'obsolescence
$temps = time();
// Identification du préfixe des archives
$prefixe = lire_config('mes_fichiers/prefixe', 'mf3') . '_';
// Scan des archives existantes et suppression des obsolètes
include_spip('inc/flock');
$archives = preg_files(_MES_FICHIERS_DOSSIER, "${prefixe}.+[.](zip)$");
$liste = array();
foreach ($archives as $_archive) {
$date_fichier = filemtime($_archive);
if ($temps > ($date_fichier + $duree_sauvegarde * 3600 * 24)) {
supprimer_fichier($_archive);
$liste[] = $_archive;
}
}
}
// Identification de l'auteur ayant déclenché l'archivage
$auteur = $options['auteur'] ?: $GLOBALS['visiteur_session']['id_auteur'];
if ($auteur == 'cron') {
$auteur = 'SPIP';
}
// Pipeline de post sauvegarde si besoin
pipeline(
'post_sauvegarde',
array(
'args' => array(
'liste' => $liste,
'auteur' => $auteur,
'type' => 'mes_fichiers_cleaner'
),
'data' => ''
)
);
// Notification de l'action
if ($notifications = charger_fonction('notifications', 'inc')) {
$notifications(
'archive_mf_nettoyer',
'',
array('liste' => $liste, 'auteur' => $auteur)
);
}
return $liste;
}
/**
* Renvoie la liste des archives disponibles au telechargement par date inverse
*
* @api
*
* @return array
*/
function archive_mf_lister() {
include_spip('inc/config');
$prefixe = lire_config('mes_fichiers/prefixe', 'mf3');
$laver_auto = (lire_config('mes_fichiers/nettoyage_journalier', 'oui') == 'oui');
$pattern = "${prefixe}.*\.zip$";
include_spip('inc/flock');
if ($laver_auto) {
$liste = preg_files(_MES_FICHIERS_DOSSIER, $pattern);
} else {
$liste = preg_files(_MES_FICHIERS_DOSSIER, $pattern, 50);
}
// On filtre les fichiers vides ou corrompues qui sont des résultats d'erreur lors de l'archivage
foreach ($liste as $_cle => $_archive) {
if (!is_file($_archive)
or !is_readable($_archive)
or (filesize($_archive) === 0)) {
unset($liste[$_cle]);
}
}
return array_reverse($liste);
}
/**
* Renvoie les informations sur le contenu de l'archive
*
* @api
*
* @param string $zip Chemin de l'archive
*
* @return string
*/
function archive_mf_informer($zip) {
// Extraction des informations sur l'archive
include_spip('inc/archives');
$archive = new Spip\Archives\SpipArchives($zip);
$informations = $archive->informer();
$resume = '';
if (empty($informations['commentaire'])) {
$resume .= _T('mes_fichiers:message_zip_propriete_nok');
spip_log('Commentaire de l\'archive absente ou d\'un format obsolète', 'mes_fichiers' . _LOG_ERREUR);
} else {
$commentaire = unserialize($informations['commentaire']);
if (
!empty($commentaire['contenu'])
and !empty($commentaire['auteur'])
) {
$liste = $commentaire['contenu'];
$id_auteur = $commentaire['auteur'];
// On gere le cas où l'auteur est le cron
if (intval($id_auteur)) {
$auteur = sql_getfetsel('nom', 'spip_auteurs', 'id_auteur=' . intval($id_auteur));
} else {
$auteur = $id_auteur;
}
$resume .= _T('mes_fichiers:resume_zip_auteur') . ' : ' . $auteur . '<br />';
$resume .= _T('mes_fichiers:resume_zip_compteur') . ' : ' . count($informations['fichiers']) . '<br />';
$resume .= _T('mes_fichiers:resume_zip_contenu') . ' : ' . '<br />';
$resume .= '<ul class="spip">';
foreach ($liste as $_fichier) {
$resume .= '<li>' . $_fichier . '</li>';
}
$resume .= '</ul>';
}
}
return $resume;
}

68
inc/mes_fichiers_cleaner.php

@ -1,68 +0,0 @@
<?php
if (!defined('_ECRIRE_INC_VERSION')) {
return;
}
/**
* Supprime les fichiers d'archive considérés comme obsolètes.
* La fonction retourne la liste des archives effectivement supprimées.
*
* @param array $options
*
* @return array Liste des archives effectivement supprimées.
*/
function inc_mes_fichiers_cleaner_dist($options = array()) {
// Initialiser la liste des archives supprimées fournie en retour
$liste = [];
// Supprimer les archives dont l'échéance de garde est échue
include_spip('inc/config');
$jours_obso = intval(lire_config('mes_fichiers/duree_sauvegarde', 15));
if ($jours_obso > 0) {
// Stocker la date actuelle pour calculer l'obsolescence
$temps = time();
// Scan des archives existantes
include_spip('inc/mes_fichiers_utils');
$prefixe = lire_config('mes_fichiers/prefixe', 'mf2') . '_';
$archives = preg_files(_MES_FICHIERS_DOSSIER, "${prefixe}.+[.](zip)$");
$liste = array();
foreach ($archives as $_archive) {
$date_fichier = filemtime($_archive);
if ($temps > ($date_fichier + $jours_obso * 3600 * 24)) {
$liste[] = $_archive;
supprimer_fichier($_archive);
}
}
}
// Identification de l'auteur ayant déclenché l'archivage
$auteur = $options['auteur'] ?: $GLOBALS['visiteur_session']['id_auteur'];
if ($auteur == 'cron') {
$auteur = 'SPIP';
}
// Pipeline de post sauvegarde si besoin
pipeline(
'post_sauvegarde',
array(
'args' => array(
'liste' => $liste,
'auteur' => $auteur,
'type' => 'mes_fichiers_cleaner'
),
'data' => ''
)
);
// Notification de l'action
if ($notifications = charger_fonction('notifications', 'inc')) {
$notifications(
'mes_fichiers_cleaner',
'',
array('liste' => $liste, 'auteur' => $auteur)
);
}
return $liste;
}

45
inc/mes_fichiers_destinataires.php

@ -0,0 +1,45 @@
<?php
if (!defined('_ECRIRE_INC_VERSION')) {
return;
}
/**
* @param $quoi
* @param $id
* @param $options
*
* @return null|mixed
*/
function inc_mes_fichiers_destinataires_dist($quoi, $id, $options) {
// Recuperation des destinataires configurés
include_spip('inc/config');
$mails_configures = lire_config('mes_fichiers/notif_mail', []);
if ($mails_configures) {
$mails_configures = explode(',', $mails_configures);
}
// On ajoute systématiquement le webmestre
if (!empty($GLOBALS['meta']['email_webmaster'])) {
$mails_configures[] = $GLOBALS['meta']['email_webmaster'];
}
// On ajoute les éventuels destinataires supplémentaires fournis par des plugins
$destinataires = pipeline(
'notifications_destinataires',
[
'args'=> [
'quoi' => $quoi,
'id' => $id,
'options'=> $options
],
'data'=> $mails_configures
]
);
// Nettoyage de la liste d'emails en vérifiant les doublons
// et la validité des emails
include_spip('inc/notifications');
notifications_nettoyer_emails($destinataires);
return $destinataires;
}

98
inc/mes_fichiers_sauver.php

@ -1,98 +0,0 @@
<?php
if (!defined('_ECRIRE_INC_VERSION')) {
return;
}
/**
* La fonction de sauvegarde des fichiers.
*
* @param array|null $liste Liste des dossiers ou fichiers à archiver ou null pour archiver tout ce qui est possible
* @param array $options Options d'archivage. Pour l'instant uniquement l'auteur ayant déclenché l'archivage.
*
* @return string Message d'erreur éventuel ou chaine vide sinon.
*/
function inc_mes_fichiers_sauver_dist($liste = null, $options = array()) {
// Message d'erreur en retour de la fonction : chaine si pas d'erreur
$erreur = '';
// Si on a passé null pour la liste des fichiers, c'est que l'on veut sauvegarder tout ce qui est possible
// En effet, ce peut être un array vide dans le cas d'un problème de config.
include_spip('inc/mes_fichiers_utils');
if (is_null($liste)) {
$liste = mes_fichiers_a_sauver();
}
// Identification de l'auteur ayant déclenché l'archivage
$auteur = !empty($options['auteur'])
? $options['auteur']
: $GLOBALS['visiteur_session']['id_auteur'];
// Si il y a quelque chose à archiver
if (count($liste) > 0) {
// On vérifie que les répertoires n'excèdent pas la taille maximale configurée
// et on stocke les fichiers et répertoires pour insérer cette liste en commentaire de l'archive
include_spip('inc/config');
$taille_max = intval(lire_config('mes_fichiers/taille_max_rep', 75)) * 1000 * 1000;
$liste_finale = [];
foreach ($liste as $_cle => $_chemin) {
if (is_dir($_chemin) and (mes_fichiers_dirsize($_chemin) > $taille_max)) {
unset($liste[$_cle]);
} else {
$liste_finale[] = mes_fichiers_joli_repertoire($_chemin);
}
}
// On construit le nom de l'archive et on crée le répertoire d'accueil si il n'existe pas déjà.
$dir = sous_repertoire(_MES_FICHIERS_DOSSIER);
$prefixe = lire_config('mes_fichiers/prefixe', 'mf2');
$chemin_archive = $dir . $prefixe . '_' . date('Ymd_His') . '.zip';
// On prépare le commentaire
if ($auteur === 'cron') {
$auteur = 'SPIP';
}
$meta = [
'auteur' => $auteur,
'contenu' => $liste_finale
];
// On lance l'archivage du contenu.
include_spip('inc/archives');
$archive = new Spip\Archives\SpipArchives($chemin_archive);
if (!$archive->emballer($liste)) {
// -- on renvoie le message d'erreur provenant de la librairie d'archivage
$erreur = $archive->message();
} else {
// -- si pas d'erreur, on ajoute le commentaire
$archive->commenter(serialize($meta));
}
} else {
$erreur = _T('mes_fichiers:erreur_aucun_fichier_sauver');
}
// Un pipeline post_sauvegarde pour que d'autres plugins puissent agir à ce moment là.
pipeline(
'post_sauvegarde',
array(
'args' => array(
'err' => $erreur,
'auteur' => $auteur,
'type' => 'mes_fichiers_sauver'
),
'data' => ''
)
);
// Notifications si nécessaire.
if ($notifications = charger_fonction('notifications', 'inc')) {
$notifications(
'mes_fichiers_sauver',
'',
array(
'auteur' => $auteur,
'err' => $erreur)
);
}
return $erreur;
}

274
inc/mes_fichiers_utils.php

@ -1,274 +0,0 @@
<?php
if (!defined('_ECRIRE_INC_VERSION')) {
return;
}
if (!defined('_MES_FICHIERS_DOSSIER')) {
/**
* Repertoire de stockage des archives creees
*/
define('_MES_FICHIERS_DOSSIER', _DIR_TMP . 'mes_fichiers/');
}
/**
* Renvoie la liste des fichiers et repertoires pouvant être sauvegarder.
*
* @return array
*/
function mes_fichiers_a_sauver() {
// Dans le cas de la mutu, les fichiers de personnalisation sont places
// - soit dans le site d'un sous-domaine, il faut donc aller les chercher a la racine de ce sous-domaine
// en utilisant _DIR_SITE
// - soit dans le site principal, il faut dans ce cas utiliser _DIR_RACINE
if (defined('_DIR_SITE')) {
// C'est une mutu
$dir_site = _DIR_SITE;
} else {
$dir_site = _DIR_RACINE;
}
// Constituer la liste des fichiers et dossiers pouvant être sauvegardés
$liste = array();
// Rechercher le fichier sqlite le plus récent depuis config/bases
$tmp_db = defined('_DIR_DB') ? _DIR_DB : $dir_site . 'config/bases/';
if ($fichier_db = mes_fichiers_fichier_recent($tmp_db)) {
$liste[] = $fichier_db;
}
// le fichier d'options si il existe
if (
@is_readable($f = $dir_site . _NOM_PERMANENTS_INACCESSIBLES . _NOM_CONFIG . '.php')
or (!defined('_DIR_SITE') && @is_readable($f = _FILE_OPTIONS))
) {
$liste[] = $f;
}
// le fichier .htaccess a la racine qui peut contenir des persos
$htaccess = defined('_ACCESS_FILE_NAME') ? _DIR_RACINE . _ACCESS_FILE_NAME : _DIR_RACINE . '.htaccess';
if (@is_readable($htaccess)) {
$liste[] = $htaccess;
}
// le fameux repertoire des documents et images
$IMG = defined('_DIR_IMG') ? _DIR_IMG : $dir_site . 'IMG/';
if (@is_dir($IMG)) {
$liste[] = $IMG;
}
// le(s) dossier(s) des squelettes nommes
if (strlen($GLOBALS['dossier_squelettes'])) {
// Dans le cas d'une mutu, la globale est toujours mise à jour sous la forme sites/domaine/squelettes
// Cela revient donc au même que pour une install non mutualisée, il faut donc utiliser _DIR_RACINE
foreach (explode(':', $GLOBALS['dossier_squelettes']) as $_dir) {
$dir = ($_dir[0] == '/' ? '' : _DIR_RACINE) . $_dir . '/';
if (@is_dir($dir)) {
$liste[] = $dir;
}
}
} elseif (@is_dir($dir_site . 'squelettes/')) {
$liste[] = $dir_site . 'squelettes/';
}
// le dernier fichier de dump de la base
$tmp_dump = defined('_DIR_DUMP') ? _DIR_DUMP : $dir_site . 'tmp/dump/';
if ($fichier_dump = mes_fichiers_fichier_recent($tmp_dump)) {
$liste[] = $fichier_dump;
}
// On ajoute via un pipeline pour déclarer des fichiers à sauvegarder provenant de plugins
// et on renvoie la liste complète sans doublons.
$liste_en_plus = pipeline('mes_fichiers_a_sauver', []);
return array_unique(array_merge($liste, $liste_en_plus));
}
/**
* Renvoie un chemin de dossier le plus propre possible en gérant le cas d'un SPIP mutualisé ou non.
*
* @param string $dossier Chemin du dossier à afficher d'une manière la plus lisible.
*/
function mes_fichiers_joli_repertoire($dossier) {
if (
defined('_DIR_SITE')
and preg_match(',' . _DIR_SITE . ',', $dossier)
) {
$joli_repertoire = str_replace(_DIR_SITE, '', $dossier);
} else {
$joli_repertoire = joli_repertoire($dossier);
}
return $joli_repertoire;
}
/**
* Calculer la taille d'un répertoire en itérant sur son contenu.
*
* @link http://aidanlister.com/repos/v/function.dirsize.php
*
* @param string $path Chemin vers le dossier concerné
*
* @return int
*/
function mes_fichiers_dirsize($path) {
// Par défaut, erreur ou pas, le dossier est vide
$size = 0;
// Trailing slash
if (substr($path, -1, 1) !== DIRECTORY_SEPARATOR) {
$path .= DIRECTORY_SEPARATOR;
}
// Sanity check
if (is_file($path)) {
$size = filesize($path);
} elseif (is_dir($path)) {
// Iterate queue
$queue = array($path);
for ($i = 0, $j = count($queue); $i < $j; ++$i) {
// Open directory
if (is_dir($queue[$i]) && $dir = @dir($queue[$i])) {
$subdirs = array();
while (false !== ($entry = $dir->read())) {
// Skip pointers
if ($entry == '.' || $entry == '..') {
continue;
}
// Get list of directories or filesizes
$path = $queue[$i] . $entry;
if (is_dir($path)) {
$path .= DIRECTORY_SEPARATOR;
$subdirs[] = $path;
} elseif (is_file($path)) {
$size += filesize($path);
}
}
// Add subdirectories to start of queue
unset($queue[0]);
$queue = array_merge($subdirs, $queue);
// Recalculate stack size
$i = -1;
$j = count($queue);
// Clean up
$dir->close();
unset($dir);
}
}
}
return $size;
}
/**
* Renvoie une taille de dossier ou de fichier humainement lisible.
*
* @link http://aidanlister.com/repos/v/function.size_readable.php
*
* @param int $size Taille en octets
* @param string $max Unité maximale
* @param string $system Système d'unités : `si` pour le système international, `bi` pour des unités binaires
* @param string $format Format de retour
*
* @return string Chaine compréhensible pour une taille de fichier ou dossier
*/
function mes_fichiers_size_readable($size, $max = null, $system = 'si', $format = '%01.2f %s') {
// Pick units
$systems['si']['prefix'] = array('B', 'K', 'MB', 'GB', 'TB', 'PB');
$systems['si']['size'] = 1000;
$systems['bi']['prefix'] = array('B', 'KiB', 'MiB', 'GiB', 'TiB', 'PiB');
$systems['bi']['size'] = 1024;
// Système choisi
$sys = $systems[$system] ?? $systems['si'];
// Max unit to display
$depth = count($sys['prefix']) - 1;
if ($max && false !== $d = array_search($max, $sys['prefix'])) {
$depth = $d;
}
// Loop
$i = 0;
while ($size >= $sys['size'] && $i < $depth) {
$size /= $sys['size'];
$i++;
}
return sprintf($format, $size, $sys['prefix'][$i]);
}
/**
* Renvoie le fichier le plus récent d'un dossier donné.
* Le dossier ne doit contenir que des fichiers concernant le même sujet.
*
* @param $dossier
*
* @return string
*/
function mes_fichiers_fichier_recent($dossier) {
// Par défaut, si le dossier est vide on renvoie un nom de fichier vide
$fichier_recent = '';
// On considère que dans le dossier tous les fichiers concernent le même sujet, il est donc inutile
// d'utiliser un pattern pour le fichier.
include_spip('inc/flock');
$fichiers = preg_files($dossier);
$mtime_recent = 0;
foreach ($fichiers as $_fichier) {
if (($mtime = filemtime($_fichier)) > $mtime_recent) {
$fichier_recent = $_fichier;
$mtime_recent = $mtime;
}
}
return $fichier_recent;
}
/**
* @param $quoi
* @param $id
* @param $options
*
* @return mixed|null
*/
function mes_fichiers_preparer_destinataires($quoi, $id, $options) {
// Recuperation des destinataires configurés
include_spip('inc/config');
$mails_configures = lire_config('mes_fichiers/notif_mail', []);
if ($mails_configures) {
$mails_configures = explode(',', $mails_configures);
}
// On ajoute systématiquement le webmestre
if (!empty($GLOBALS['meta']['email_webmaster'])) {
$mails_configures[] = $GLOBALS['meta']['email_webmaster'];
}
// On ajoute les éventuels destinataires supplémentaires fournis par des plugins
$destinataires = pipeline(
'notifications_destinataires',
[
'args'=> [
'quoi'=>$quoi,
'id'=>$id,
'options'=>$options
],
'data'=> $mails_configures
]
);
// Nettoyage de la liste d'emails en vérifiant les doublons
// et la validité des emails
notifications_nettoyer_emails($destinataires);
return $destinataires;
}

9
lang/mes_fichiers_fr.php

@ -20,7 +20,7 @@ $GLOBALS[$GLOBALS['idx_lang']] = array(
// E
'erreur_aucun_fichier_sauver' => 'Il n’y a aucun fichier à sauvegarder',
'erreur_repertoire_trop_grand' => 'Ce répertoire dépasse la limite de @taille_max@ MB et ne peut être sauvegardé.',
'erreur_repertoire_trop_grand' => '> à la limite de @taille_max@',
'explication_cfg_duree_sauvegarde' => 'Saisir la durée de conservation des sauvegardes en jours',
'explication_cfg_frequence' => 'Saisir la fréquence des sauvegardes en jours',
'explication_cfg_notif_mail' => 'Saisir les adresses en les séparant par des virgules ",". Ces adresses s’ajoutent à celle du webmestre du site.',
@ -55,7 +55,8 @@ $GLOBALS[$GLOBALS['idx_lang']] = array(
'message_sauvegarde_nok' => 'Erreur lors de la sauvegarde. Le fichier d’archives n’a pas été créé (@erreur@).',
'message_sauvegarde_ok' => 'Le fichier d’archives a bien été créé.',
'message_sauver_sujet' => 'Sauvegarde',
'message_telechargement_nok' => 'Erreur lors du téléchargement.',
'message_suppression_nok' => 'Erreur lors de la suppression de l\'archive.',
'message_telechargement_nok' => 'Erreur lors du téléchargement de l\'archive.',
'message_zip_auteur_indetermine' => 'Non déterminé',
'message_zip_propriete_nok' => 'Aucune propriété n’est disponible sur cette archive.',
'message_zip_sans_contenu' => 'Aucune information n’est disponible sur le contenu de cette archive.',
@ -67,6 +68,10 @@ $GLOBALS[$GLOBALS['idx_lang']] = array(
'resume_zip_statut' => 'Statut',
// T
'taille_go_bi' => '@taille@ Gio',
'taille_ko_bi' => '@taille@ kio',
'taille_mo_bi' => '@taille@ Mio',
'taille_octets_bi' => '@taille@ octets',
'titre_boite_sauver' => 'Créer une archive',
'titre_boite_telecharger' => 'Liste des archives disponibles au téléchargement',
'titre_page_configurer' => 'Configuration du plugin Mes fichiers',

48
mes_fichiers_fonctions.php

@ -0,0 +1,48 @@
<?php
if (!defined('_ECRIRE_INC_VERSION')) {
return;
}
/**
* Renvoie une taille de dossier ou de fichier humainement lisible en ajustant le format et l'unité.
*
* @param int $octets Taille d'un dossier ou fichier en octets
* @param string $systeme Système d'unité dans lequel calculer et afficher la taille lisble. Vaut `BI` (défaut) ou `SI`.
*
* @return string Taille affichée de manière humainement lisible
*/
function mes_fichiers_afficher_taille($octets, $systeme = 'BI') {
// Texte à afficher pour la taille
$affichage = '';
static $unites = ['octets', 'ko', 'mo', 'go'];
static $precisions = [0, 1, 1, 2];
if ($octets >= 1) {
// Déterminer le nombre d'octets représentant le kilo en fonction du système choisi
$systeme = strtolower($systeme);
if ($systeme === 'bi') {
$kilo = 1024;
$suffixe_item = "_$systeme";
$module = 'mes_fichiers';
} else {
$kilo = 1000;
$suffixe_item = '';
$module = 'spip';
}
// Identification de la puissance en "kilo" correspondant à l'unité la plus appropriée
$puissance = floor(log($octets, $kilo));
// Calcul de la taille et choix de l'unité
$affichage = _T(
$module . ':taille_' . $unites[$puissance] . $suffixe_item,
[
'taille' => round($octets / pow($kilo, $puissance), $precisions[$puissance])
]
);
}
return $affichage;
}

16
notifications/mes_fichiers_sauver.php → notifications/archive_mf_creer.php

@ -2,15 +2,16 @@
if (!defined('_ECRIRE_INC_VERSION')) {
return;
}
function notifications_mes_fichiers_sauver_dist($quoi, $id, $options) {
include_spip('inc/config');
$notif_active = (lire_config('mes_fichiers/notif_active', 'non') == 'oui');
function notifications_archive_mf_creer_dist($quoi, $id, $options) {
if ($notif_active
and !$options['err']) {
if (
include_spip('inc/config')
and (lire_config('mes_fichiers/notif_active', 'non') === 'oui')
and !$options['err']
) {
// preparation de la liste des destinataires
include_spip('inc/mes_fichiers_utils');
$destinataires = mes_fichiers_preparer_destinataires($quoi, $id, $options);
$preparer_destinataires = charger_fonction('mes_fichiers_destinataires', 'inc');
$destinataires = $preparer_destinataires($quoi, $id, $options);
// Determination de l'auteur de la sauvegarde
if (intval($options['auteur'])) {
@ -29,6 +30,7 @@ function notifications_mes_fichiers_sauver_dist($quoi, $id, $options) {
$msg_mail = _T('mes_fichiers:message_notif_sauver_intro', array('auteur' => $auteur));
// Envoi de la notification
include_spip('inc/notifications');
notifications_envoyer_mails($destinataires, $msg_mail, $sujet_mail);
}
}

35
notifications/archive_mf_nettoyer.php

@ -0,0 +1,35 @@
<?php
if (!defined('_ECRIRE_INC_VERSION')) {
return;
}
function notifications_archive_mf_nettoyer_dist($quoi, $id, $options) {
if (
include_spip('inc/config')
and (lire_config('mes_fichiers/notif_active', 'non') === 'oui')
and is_array($options['liste'])
and !empty($options['liste'])
) {
// preparation de la liste des destinataires
$preparer_destinataires = charger_fonction('mes_fichiers_destinataires', 'inc');
$destinataires = $preparer_destinataires($quoi, $id, $options);
// Construction du sujet du mail
include_spip('inc/texte');
$sujet_mail = '[' . typo($GLOBALS['meta']['nom_site'])
. '][mes_fichiers] '
. _T('mes_fichiers:message_cleaner_sujet');