Newer
Older

marcimat@rezo.net
a validé
<?php
use Spip\Archiver\SpipArchiver;

marcimat@rezo.net
a validé
/***************************************************************************\
* SPIP, Système de publication pour l'internet *

marcimat@rezo.net
a validé
* *
* Copyright © avec tendresse depuis 2001 *
* Arnaud Martin, Antoine Pitrou, Philippe Rivière, Emmanuel Saint-James *

marcimat@rezo.net
a validé
* *
* Ce programme est un logiciel libre distribué sous licence GNU/GPL. *

marcimat@rezo.net
a validé
\***************************************************************************/
if (!defined('_ECRIRE_INC_VERSION')) {

marcimat@rezo.net
a validé
return;
}
/**
* Recuperer le nom du fichier selon le mode d'upload choisi
* et mettre cela au format $_FILES
*
* Renvoie une liste de fichier ou un message en cas d'erreur
*

marcimat@rezo.net
a validé
*/
function joindre_trouver_fichier_envoye() {

marcimat@rezo.net
a validé
// on est appele deux fois dans un hit, resservir ce qu'on a trouve a la verif
// lorsqu'on est appelle au traitement
if (is_countable($files) ? count($files) : 0) {

marcimat@rezo.net
a validé
return $files;
}
if (_request('joindre_upload')) {
$files = joindre_trouver_http_post_files();
// erreur ?
if (is_string($files)) {
return $files;
}
// rien envoye ?
if (!count($files)) {
return _T('medias:erreur_indiquez_un_fichier');
}
// verifions les types de fichier envoyes
include_spip('action/ajouter_documents');
foreach ($files as $file) {
if (!is_array(verifier_upload_autorise($file['name']))) {
return _T('medias:erreur_upload_type_interdit', ['nom' => $file['name']]);

marcimat@rezo.net
a validé
}
}
return $files;
} elseif (_request('joindre_distant')) {
$path = _request('url');
if (!strlen($path) or $path == 'http://') {
return _T('medias:erreur_indiquez_un_fichier');
}

cedric@yterium.com
a validé
include_spip('inc/distant');
if (!valider_url_distante($path)) {
return _T('medias:erreur_upload_type_interdit', ['nom' => $path]);

cedric@yterium.com
a validé
}

marcimat@rezo.net
a validé
include_spip('action/ajouter_documents');
$infos = renseigner_source_distante($path, 'valider_url_distante');

marcimat@rezo.net
a validé
if (!is_array($infos)) {
return $infos;
} // message d'erreur
else {

marcimat@rezo.net
a validé
'name' => basename($path),
'tmp_name' => $path,
'distant' => true,

marcimat@rezo.net
a validé
}
} elseif (_request('joindre_ftp')) {
$path = _request('cheminftp');
if (!$path || strstr($path, '..')) {
return _T('medias:erreur_indiquez_un_fichier');
}
include_spip('inc/documents');
include_spip('inc/actions');
$upload = determine_upload();
if ($path != '/' and $path != './') {
$upload .= $path;
}
if (!is_dir($upload)) {
// seul un fichier est demande

marcimat@rezo.net
a validé
'name' => basename($upload),
'tmp_name' => $upload

marcimat@rezo.net
a validé
} else {
// on upload tout un repertoire

marcimat@rezo.net
a validé
foreach (preg_files($upload) as $fichier) {

marcimat@rezo.net
a validé
'name' => basename($fichier),
'tmp_name' => $fichier

marcimat@rezo.net
a validé
}
return $files;
}

cedric@yterium.com
a validé
} elseif (_request('joindre_zip') and $token_zip = _request('chemin_zip')) {
$zip_to_clean = (isset($GLOBALS['visiteur_session']['zip_to_clean']) ?
unserialize($GLOBALS['visiteur_session']['zip_to_clean']) : []);
if (
!$zip_to_clean
or !isset($zip_to_clean[$token_zip])
or !$path = $zip_to_clean[$token_zip]
) {

cedric@yterium.com
a validé
return _T('avis_operation_impossible');
}

marcimat@rezo.net
a validé
include_spip('inc/documents'); //pour creer_repertoire_documents
define('_TMP_ZIP', $path);
define('_TMP_DIR', creer_repertoire_documents(md5($path . $GLOBALS['visiteur_session']['id_auteur'])));
if (_TMP_DIR == _DIR_IMG) {

marcimat@rezo.net
a validé
return _T('avis_operation_impossible');
}

marcimat@rezo.net
a validé
if (_request('options_upload_zip') == 'deballe') {
$files = joindre_deballer_lister_zip($path, _TMP_DIR);

marcimat@rezo.net
a validé
}
// si le zip doit aussi etre conserve, l'ajouter
if (_request('options_upload_zip') == 'upload' or _request('options_deballe_zip_conserver')) {

marcimat@rezo.net
a validé
'name' => basename($path),
'tmp_name' => $path,

marcimat@rezo.net
a validé
}
return $files;
}

marcimat@rezo.net
a validé
}
/**
* Récupérer et mettre en forme la liste des fichiers postes
* que ce soit via plusieurs input file ou via un input file multiple
* @param $name : nom de l'input qu'on veut recuperer si on ne veut pas tous les fichiers
* @return array|string
* string en cas d'erreur
*/
function joindre_trouver_http_post_files($name = null) {
$post = $_FILES;
$files = [];
if (is_array($post)) {
foreach ($post as $input_name => $file) {
if ($name and $input_name !== $name) {
continue;
}
if (is_array($file['name'])) {
while (is_countable($file['name']) ? count($file['name']) : 0) {
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
$test = [
'input_name' => $input_name,
'error' => array_shift($file['error']),
'name' => array_shift($file['name']),
'tmp_name' => array_shift($file['tmp_name']),
'type' => array_shift($file['type']),
];
//UPLOAD_ERR_NO_FILE
if (!($test['error'] == 4)) {
// un erreur upload
if (is_string($err = joindre_upload_error($test['error']))) {
return $err;
}
$files[] = $test;
}
}
} else {
//UPLOAD_ERR_NO_FILE
if (!($file['error'] == 4)) {
// un erreur upload
if (is_string($err = joindre_upload_error($file['error']))) {
return $err;
}
$file['input_name'] = $input_name;
$files[] = $file;
}
}
}
}
return $files;
}

marcimat@rezo.net
a validé
// Erreurs d'upload
// renvoie false si pas d'erreur
// et true si erreur = pas de fichier
// pour les autres erreurs renvoie le message d'erreur
function joindre_upload_error($error) {

marcimat@rezo.net
a validé
if (!$error) {
return false;
}
spip_log("Erreur upload $error -- cf. http://php.net/manual/fr/features.file-upload.errors.php");
switch ($error) {
case 4: /* UPLOAD_ERR_NO_FILE */
return true;
# on peut affiner les differents messages d'erreur
case 1: /* UPLOAD_ERR_INI_SIZE */
$msg = _T(
'medias:upload_limit',
['max' => ini_get('upload_max_filesize')]

marcimat@rezo.net
a validé
break;
case 2: /* UPLOAD_ERR_FORM_SIZE */
$msg = _T(
'medias:upload_limit',
['max' => ini_get('upload_max_filesize')]

marcimat@rezo.net
a validé
break;
case 3: /* UPLOAD_ERR_PARTIAL */
$msg = _T(
'medias:upload_limit',
['max' => ini_get('upload_max_filesize')]

marcimat@rezo.net
a validé
break;
case 6: /* UPLOAD_ERR_NO_TMP_DIR */
$msg = _T('medias:erreur_dossier_tmp_manquant');
break;
case 7: /* UPLOAD_ERR_CANT_WRITE */
$msg = _T('medias:erreur_ecriture_fichier');

marcimat@rezo.net
a validé
default: /* autre */
if (!$msg) {
$msg = _T('pass_erreur') . ' ' . $error
. '<br />' . propre('[->http://php.net/manual/fr/features.file-upload.errors.php]');

marcimat@rezo.net
a validé
}
break;
}
spip_log("erreur upload $error", 'medias');

marcimat@rezo.net
a validé
return $msg;
}
/**
* Verifier si le fichier poste est un zip
* Si on sait le deballer, proposer les options necessaires
*
* Retourne [liste des fichiers, liste des erreurs, chemin du zip]
*

marcimat@rezo.net
a validé
* @param array $files
* @return false|array<array<string,array>, array<int,string>, string>

marcimat@rezo.net
a validé
*/
function joindre_verifier_zip($files) {
if (
function_exists('gzopen')
&& (count($files) == 1)
&& !isset($files[0]['distant'])
&& (
preg_match('/\.zip$/i', $files[0]['name'])
|| (isset($files[0]['type']) && $files[0]['type'] == 'application/zip')
)

marcimat@rezo.net
a validé
) {
// on pose le fichier dans le repertoire zip
// (nota : copier_document n'ecrase pas un fichier avec lui-meme
// ca autorise a boucler)
include_spip('inc/getdocument');
$desc = $files[0];
$zip = copier_document(
'zip',

marcimat@rezo.net
a validé
$desc['name'],
$desc['tmp_name']
);
// Est-ce qu'on sait le lire ?
&& ($archive = new SpipArchiver($zip))
&& ($infos = $archive->informer())
&& ($contenu = joindre_decrire_contenu_zip($infos))
&& ($tmp = sous_repertoire(_DIR_TMP, 'zip'))
&& rename($zip, $tmp = $tmp . basename($zip))

marcimat@rezo.net
a validé
) {
$zip_to_clean = (isset($GLOBALS['visiteur_session']['zip_to_clean']) ?
unserialize($GLOBALS['visiteur_session']['zip_to_clean']) : []);

cedric@yterium.com
a validé
$zip_to_clean[md5($tmp)] = $tmp;

marcimat@rezo.net
a validé
session_set('zip_to_clean', serialize($zip_to_clean));
$contenu[] = $tmp;
return $contenu;
}
}
// ce n'est pas un zip sur lequel il faut demander plus de precisions
return false;
}
/**
* Verifier et decrire les fichiers de l'archive, en deux listes :
* - une liste des noms de fichiers ajoutables
* - une liste des erreurs (fichiers refuses)
*
* @param object $zip
* @return false|array<array<string,array>, array<int,string>>

marcimat@rezo.net
a validé
*/
function joindre_decrire_contenu_zip($infos) {

marcimat@rezo.net
a validé
include_spip('action/ajouter_documents');
// si pas possible de decompacter: installer comme fichier zip joint
if (empty($infos['fichiers'])) {

marcimat@rezo.net
a validé
return false;
}
// Verifier si le contenu peut etre uploade (verif extension)
$fichiers = [];
$erreurs = [];
foreach ($infos['fichiers'] as $file) {
if (accepte_fichier_upload($f = $file['filename'])) {

marcimat@rezo.net
a validé
$fichiers[$f] = $file;
} else // pas de message pour les dossiers et fichiers caches
{
if (substr($f, -1) !== '/' and substr(basename($f), 0, 1) !== '.') {
$erreurs[] = _T('medias:erreur_upload_type_interdit', ['nom' => $f]);

marcimat@rezo.net
a validé
}
}
}
// si aucun fichier uploadable : installer comme fichier zip joint
if (!count($fichiers)) {
return false;
}
ksort($fichiers);
return [$fichiers, $erreurs];

marcimat@rezo.net
a validé
}
function joindre_deballer_lister_zip($path, $tmp_dir) {
$archive = new SpipArchiver($path);
if (
$infos = $archive->informer()
and $contenu = joindre_decrire_contenu_zip($infos)
) {

marcimat@rezo.net
a validé
$fichiers = reset($contenu);
$fichiers = array_column($fichiers, 'filename');
if ($archive->deballer($tmp_dir, $fichiers)) {
$files = [];
foreach ($fichiers as $fichier) {
$f = basename($fichier);
'tmp_name' => $tmp_dir . $fichier,
'name' => $f,
'titrer' => _request('options_deballe_zip_titrer'),
'mode' => null
}
return $files;

marcimat@rezo.net
a validé
}
}
return _T('avis_operation_impossible');
}
if (!function_exists('fixer_extension_document')) {
/**
* Cherche dans la base le type-mime du tableau representant le document
* et corrige le nom du fichier ; retourne array(extension, nom corrige)
* s'il ne trouve pas, retourne '' et le nom inchange
*
* @param array $doc
* @return array

marcimat@rezo.net
a validé
*/
function fixer_extension_document($doc) {
$extension = '';
$name = $doc['name'];
if (
preg_match(',\.([^.]+)$,', $name, $r)
and $t = sql_fetsel(
'extension',
'spip_types_documents',
'extension=' . sql_quote(corriger_extension($r[1]))
)

marcimat@rezo.net
a validé
) {
$extension = $t['extension'];
$name = preg_replace(',\.[^.]*$,', '', $doc['name']) . '.' . $extension;
} else {
if ($t = sql_fetsel('extension', 'spip_types_documents', 'mime_type=' . sql_quote($doc['type']))) {

marcimat@rezo.net
a validé
$extension = $t['extension'];
$name = preg_replace(',\.[^.]*$,', '', $doc['name']) . '.' . $extension;
}
}
return [$extension, $name];

marcimat@rezo.net
a validé
}
}
/**
* Gestion des fichiers ZIP
*
* @param string $f
* @return bool|int
*/

marcimat@rezo.net
a validé
function accepte_fichier_upload($f) {
if (
!preg_match(',.*__MACOSX/,', $f)
and !preg_match(',^\.,', basename($f))

marcimat@rezo.net
a validé
) {
include_spip('action/ajouter_documents');
$ext = corriger_extension((strtolower(substr(strrchr($f, '.'), 1))));

marcimat@rezo.net
a validé
return sql_countsel(
'spip_types_documents',
'extension=' . sql_quote($ext) . " AND upload='oui'"
);