Newer
Older

marcimat@rezo.net
a validé
<?php
/***************************************************************************\
* 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. *
* Pour plus de détails voir le fichier COPYING.txt ou l'aide en ligne. *

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

marcimat@rezo.net
a validé
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
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
*
* @return string/array
*/
function joindre_trouver_fichier_envoye() {
static $files = array();
// on est appele deux fois dans un hit, resservir ce qu'on a trouve a la verif
// lorsqu'on est appelle au traitement
if (count($files)) {
return $files;
}
if (_request('joindre_upload')) {
$post = isset($_FILES) ? $_FILES : $GLOBALS['HTTP_POST_FILES'];
$files = array();
if (is_array($post)) {
include_spip('action/ajouter_documents');
foreach ($post as $file) {
if (is_array($file['name'])) {
while (count($file['name'])) {
$test = array(
'error' => array_shift($file['error']),
'name' => array_shift($file['name']),
'tmp_name' => array_shift($file['tmp_name']),
'type' => array_shift($file['type']),
);
if (!($test['error'] == 4)) {
if (is_string($err = joindre_upload_error($test['error']))) {
return $err;
} // un erreur upload
if (!is_array(verifier_upload_autorise($test['name']))) {

cedric@yterium.com
a validé
return _T('medias:erreur_upload_type_interdit', array('nom' => $test['name']));

marcimat@rezo.net
a validé
}
$files[] = $test;
}
}
} else {
//UPLOAD_ERR_NO_FILE
if (!($file['error'] == 4)) {
if (is_string($err = joindre_upload_error($file['error']))) {
return $err;
} // un erreur upload
if (!is_array(verifier_upload_autorise($file['name']))) {

cedric@yterium.com
a validé
return _T('medias:erreur_upload_type_interdit', array('nom' => $file['name']));

marcimat@rezo.net
a validé
}
$files[] = $file;
}
}
}
if (!count($files)) {
return _T('medias:erreur_indiquez_un_fichier');
}
}
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', array('nom' => $path));
}

marcimat@rezo.net
a validé
include_spip('action/ajouter_documents');
$infos = renseigner_source_distante($path);
if (!is_array($infos)) {
return $infos;
} // message d'erreur
else {
return array(
array(
'name' => basename($path),
'tmp_name' => $path,
'distant' => true,
)
);
}
} 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é
return array(
array(
'name' => basename($upload),
'tmp_name' => $upload
)
);
} else {
// on upload tout un repertoire
$files = array();
foreach (preg_files($upload) as $fichier) {
$files[] = array(
'name' => basename($fichier),
'tmp_name' => $fichier
);
}
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']) : array());
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');
}
$files = array();
if (_request('options_upload_zip') == 'deballe') {
$files = joindre_deballer_lister_zip($path, _TMP_DIR);

marcimat@rezo.net
a validé
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
}
// si le zip doit aussi etre conserve, l'ajouter
if (_request('options_upload_zip') == 'upload' or _request('options_deballe_zip_conserver')) {
$files[] = array(
'name' => basename($path),
'tmp_name' => $path,
);
}
return $files;
}
return array();
}
// 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) {
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',
array('max' => ini_get('upload_max_filesize'))
);

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

marcimat@rezo.net
a validé
break;
case 3: /* UPLOAD_ERR_PARTIAL */
$msg = _T(
'medias:upload_limit',
array('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
*
* @param array $files
* @return string
*/
function joindre_verifier_zip($files) {
if (function_exists('gzopen')
and (count($files) == 1)
and !isset($files[0]['distant'])
and
(preg_match('/\.zip$/i', $files[0]['name'])
or (isset($files[0]['type']) and $files[0]['type'] == 'application/zip'))
) {
// 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 ?
include_spip('inc/pclzip');
if ($zip
and $archive = new PclZip($zip)
and $contenu = joindre_decrire_contenu_zip($archive)
and $tmp = sous_repertoire(_DIR_TMP, 'zip')

marcimat@rezo.net
a validé
and rename($zip, $tmp = $tmp . basename($zip))
) {
$zip_to_clean = (isset($GLOBALS['visiteur_session']['zip_to_clean']) ?
unserialize($GLOBALS['visiteur_session']['zip_to_clean']) : array());

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

marcimat@rezo.net
a validé
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
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 array
*/
function joindre_decrire_contenu_zip($zip) {
include_spip('action/ajouter_documents');
// si pas possible de decompacter: installer comme fichier zip joint
if (!$list = $zip->listContent()) {
return false;
}
// Verifier si le contenu peut etre uploade (verif extension)
$fichiers = array();
$erreurs = array();
foreach ($list as $file) {
if (accepte_fichier_upload($f = $file['stored_filename'])) {
$fichiers[$f] = $file;
} else // pas de message pour les dossiers et fichiers caches
{
if (substr($f, -1) !== '/' and substr(basename($f), 0, 1) !== '.') {

cedric@yterium.com
a validé
$erreurs[] = _T('medias:erreur_upload_type_interdit', array('nom' => $f));

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

marcimat@rezo.net
a validé
function joindre_deballer_lister_zip($path, $tmp_dir) {
include_spip('inc/pclzip');
$archive = new PclZip($path);
$archive->extract(

cedric@yterium.com
a validé
$tmp_dir,
PCLZIP_CB_PRE_EXTRACT,
'callback_deballe_fichier'

marcimat@rezo.net
a validé
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
);
if ($contenu = joindre_decrire_contenu_zip($archive)) {
$files = array();
$fichiers = reset($contenu);
foreach ($fichiers as $fichier) {
$f = basename($fichier['filename']);
$files[] = array(
'tmp_name' => $tmp_dir . $f,
'name' => $f,
'titrer' => _request('options_deballe_zip_titrer'),
'mode' => _request('options_deballe_zip_mode_document') ? 'document' : null
);
}
return $files;
}
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 unknown_type $doc
* @return unknown
*/
// https://code.spip.net/@fixer_extension_document

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 array($extension, $name);
}
}
//
// Gestion des fichiers ZIP
//
// https://code.spip.net/@accepte_fichier_upload

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'"
);

marcimat@rezo.net
a validé
}
}
# callback pour le deballage d'un zip telecharge
# http://www.phpconcept.net/pclzip/man/en/?options-pclzip_cb_pre_extractfunction
// https://code.spip.net/@callback_deballe_fichier

marcimat@rezo.net
a validé
function callback_deballe_fichier($p_event, &$p_header) {
if (accepte_fichier_upload($p_header['filename'])) {
$p_header['filename'] = _TMP_DIR . basename($p_header['filename']);

marcimat@rezo.net
a validé
return 1;
} else {
return 0;
}
}