source: spip-zone/_core_/branches/spip-3.0/plugins/medias/inc/joindre_document.php

Last change on this file was 113381, checked in by spip.franck@…, 9 months ago

Bonne année spip 3.0

File size: 11.1 KB
Line 
1<?php
2
3/***************************************************************************\
4 *  SPIP, Systeme de publication pour l'internet                           *
5 *                                                                         *
6 *  Copyright (c) 2001-2019                                                *
7 *  Arnaud Martin, Antoine Pitrou, Philippe Riviere, Emmanuel Saint-James  *
8 *                                                                         *
9 *  Ce programme est un logiciel libre distribue sous licence GNU/GPL.     *
10 *  Pour plus de details voir le fichier COPYING.txt ou l'aide en ligne.   *
11\***************************************************************************/
12
13if (!defined("_ECRIRE_INC_VERSION")) return;
14
15
16/**
17 * Recuperer le nom du fichier selon le mode d'upload choisi
18 * et mettre cela au format $_FILES
19 *
20 * Renvoie une liste de fichier ou un message en cas d'erreur
21 *
22 * @return string/array
23 */
24function joindre_trouver_fichier_envoye(){
25        static $files = array();
26        // on est appele deux fois dans un hit, resservir ce qu'on a trouve a la verif
27        // lorsqu'on est appelle au traitement
28       
29        if (count($files))
30                return $files;
31       
32        if (_request('joindre_upload')){
33                $post = isset($_FILES) ? $_FILES : $GLOBALS['HTTP_POST_FILES'];
34                $files = array();
35                if (is_array($post)){
36                        include_spip('action/ajouter_documents');
37                  foreach ($post as $file) {
38                        if (is_array($file['name'])){
39                                while (count($file['name'])){
40                                                $test=array(
41                                                        'error'=>array_shift($file['error']),
42                                                        'name'=>array_shift($file['name']),
43                                                        'tmp_name'=>array_shift($file['tmp_name']),
44                                                        'type'=>array_shift($file['type']),
45                                                        );
46                                                if (!($test['error'] == 4)){
47                                                        if (is_string($err = joindre_upload_error($test['error'])))
48                                                                return $err; // un erreur upload
49                                                        if (!is_array(verifier_upload_autorise($test['name'])))
50                                                                return _T('medias:erreur_upload_type_interdit',array('nom'=>$test['name']));
51                                                        $files[]=$test;
52                                                }
53                                }
54                        }
55                        else {
56                                //UPLOAD_ERR_NO_FILE
57                                        if (!($file['error'] == 4)){
58                                                if (is_string($err = joindre_upload_error($file['error'])))
59                                                        return $err; // un erreur upload
60                                                if (!is_array(verifier_upload_autorise($file['name'])))
61                                                        return _T('medias:erreur_upload_type_interdit',array('nom'=>$file['name']));
62                                                $files[]=$file;
63                                        }
64                        }
65                        }
66                        if (!count($files))
67                                return _T('medias:erreur_indiquez_un_fichier');
68                }
69                return $files;
70        }
71        elseif (_request('joindre_distant')){
72                $path = _request('url');
73                if (!strlen($path) OR $path=='http://')
74                        return _T('medias:erreur_indiquez_un_fichier');
75                include_spip('inc/distant');
76                if (!valider_url_distante($path)) {
77                        return _T('medias:erreur_upload_type_interdit', array('nom' => $path));
78                }
79                include_spip('action/ajouter_documents');
80                $infos = renseigner_source_distante($path);
81                if (!is_array($infos))
82                        return $infos; // message d'erreur
83                else
84                        return array(
85                                array(
86                                        'name' => basename($path),
87                                        'tmp_name' => $path,
88                                        'distant' => true,
89                                )
90                        );
91        }
92        elseif (_request('joindre_ftp')){
93                $path = _request('cheminftp');
94                if (!$path || strstr($path, '..')) return _T('medias:erreur_indiquez_un_fichier');
95               
96                include_spip('inc/documents'); 
97                include_spip('inc/actions');
98                $upload = determine_upload();
99                if ($path != '/' AND $path != './') $upload .= $path;
100       
101                if (!is_dir($upload))
102                  // seul un fichier est demande
103                  return array(
104                        array (
105                                'name' => basename($upload),
106                                        'tmp_name' => $upload
107                                )
108                        );
109                else {
110                  // on upload tout un repertoire
111                  $files = array();
112                  foreach (preg_files($upload) as $fichier) {
113                                $files[]= array (
114                                        'name' => basename($fichier),
115                                        'tmp_name' => $fichier
116                                );
117                  }
118                  return $files;
119                }
120        }
121        elseif (_request('joindre_zip') and $token_zip = _request('chemin_zip')) {
122
123                $zip_to_clean = (isset($GLOBALS['visiteur_session']['zip_to_clean']) ? unserialize($GLOBALS['visiteur_session']['zip_to_clean']) : array());
124                if (!$zip_to_clean or !isset($zip_to_clean[$token_zip]) or !$path = $zip_to_clean[$token_zip]){
125                        return _T('avis_operation_impossible');
126                }
127
128                include_spip('inc/documents'); //pour creer_repertoire_documents
129                define('_tmp_zip', $path);
130                define('_tmp_dir', creer_repertoire_documents(md5($path.$GLOBALS['visiteur_session']['id_auteur'])));
131                if (_tmp_dir == _DIR_IMG)
132                        return _T('avis_operation_impossible');
133               
134                $files = array();
135                if (_request('options_upload_zip')=='deballe')
136                        $files = joindre_deballer_lister_zip($path,_tmp_dir);
137         
138                // si le zip doit aussi etre conserve, l'ajouter
139                if (_request('options_upload_zip')=='upload' OR _request('options_deballe_zip_conserver')){
140                $files[] = array(
141                                'name' => basename($path),
142                                'tmp_name' => $path,
143                );
144          }
145
146          return $files;
147               
148        }
149
150        return array();
151}
152
153
154// Erreurs d'upload
155// renvoie false si pas d'erreur
156// et true si erreur = pas de fichier
157// pour les autres erreurs renvoie le message d'erreur
158function joindre_upload_error($error) {
159
160        if (!$error) return false;
161        spip_log("Erreur upload $error -- cf. http://php.net/manual/fr/features.file-upload.errors.php");
162        switch ($error) {
163                       
164                case 4: /* UPLOAD_ERR_NO_FILE */
165                        return true;
166
167                # on peut affiner les differents messages d'erreur
168                case 1: /* UPLOAD_ERR_INI_SIZE */
169                        $msg = _T('medias:upload_limit',
170                        array('max' => ini_get('upload_max_filesize')));
171                        break;
172                case 2: /* UPLOAD_ERR_FORM_SIZE */
173                        $msg = _T('medias:upload_limit',
174                        array('max' => ini_get('upload_max_filesize')));
175                        break;
176                case 3: /* UPLOAD_ERR_PARTIAL  */
177                        $msg = _T('medias:upload_limit',
178                        array('max' => ini_get('upload_max_filesize')));
179                        break;
180                case 6: /* UPLOAD_ERR_NO_TMP_DIR  */
181                        $msg = _T('medias:erreur_dossier_tmp_manquant');
182                        break;
183                case 7: /* UPLOAD_ERR_CANT_WRITE */
184                        $msg = _T('medias:erreur_ecriture_fichier');
185
186                default: /* autre */
187                        if (!$msg)
188                        $msg = _T('pass_erreur').' '. $error
189                        . '<br />' . propre("[->http://php.net/manual/fr/features.file-upload.errors.php]");
190                        break;
191        }
192
193        spip_log ("erreur upload $error");
194        return $msg;
195       
196}
197
198/**
199 * Verifier si le fichier poste est un zip
200 * Si on sait le deballer, proposer les options necessaires
201 *
202 * @param array $files
203 * @return string
204 */
205function joindre_verifier_zip($files){
206        if (function_exists('gzopen')
207         AND (count($files) == 1)
208         AND !isset($files[0]['distant'])
209         AND 
210          (preg_match('/\.zip$/i', $files[0]['name']) 
211           OR (isset($files[0]['type']) AND $files[0]['type'] == 'application/zip'))
212          ){
213       
214          // on pose le fichier dans le repertoire zip
215          // (nota : copier_document n'ecrase pas un fichier avec lui-meme
216          // ca autorise a boucler)
217          include_spip('inc/getdocument');
218                $desc = $files[0];
219                $zip = copier_document("zip",
220                                        $desc['name'],
221                                        $desc['tmp_name']
222                                );
223               
224                // Est-ce qu'on sait le lire ?
225                include_spip('inc/pclzip');
226                if ($zip
227                        AND $archive = new PclZip($zip)
228                  AND $contenu = joindre_decrire_contenu_zip($archive)
229                        AND $tmp = sous_repertoire(_DIR_TMP,"zip")
230                  AND rename($zip, $tmp = $tmp.basename($zip))
231                  ){
232                        $zip_to_clean = (isset($GLOBALS['visiteur_session']['zip_to_clean'])?unserialize($GLOBALS['visiteur_session']['zip_to_clean']):array());
233                        $zip_to_clean[md5($tmp)] = $tmp;
234                        session_set('zip_to_clean',serialize($zip_to_clean));
235                        $contenu[] = $tmp;
236                        return $contenu;
237                 }
238        }
239       
240        // ce n'est pas un zip sur lequel il faut demander plus de precisions
241        return false;
242}
243
244/**
245 * Verifier et decrire les fichiers de l'archive, en deux listes :
246 * - une liste des noms de fichiers ajoutables
247 * - une liste des erreurs (fichiers refuses)
248 *
249 * @param object $zip
250 * @return array
251 */
252function joindre_decrire_contenu_zip($zip) {
253        include_spip('action/ajouter_documents');
254        // si pas possible de decompacter: installer comme fichier zip joint
255        if (!$list = $zip->listContent()) return false;
256
257        // Verifier si le contenu peut etre uploade (verif extension)
258        $fichiers = array();
259        $erreurs = array();
260        foreach ($list as $file) {
261                if (accepte_fichier_upload($f = $file['stored_filename']))
262                        $fichiers[$f] = $file;
263                else
264                        // pas de message pour les dossiers et fichiers caches
265                        if (substr($f,-1)!=='/' AND substr(basename($f),0,1)!=='.')
266                                $erreurs[] = _T('medias:erreur_upload_type_interdit',array('nom'=>$f));
267        }
268
269        // si aucun fichier uploadable : installer comme fichier zip joint
270        if (!count($fichiers))
271                return false;
272
273        ksort($fichiers);
274        return array($fichiers,$erreurs);
275}
276
277
278
279// https://code.spip.net/@joindre_deballes
280function joindre_deballer_lister_zip($path,$tmp_dir) {
281  include_spip('inc/pclzip');
282        $archive = new PclZip($path);
283        $archive->extract(
284                PCLZIP_OPT_PATH, _tmp_dir,
285                PCLZIP_CB_PRE_EXTRACT, 'callback_deballe_fichier'
286        );
287        if ($contenu = joindre_decrire_contenu_zip($archive)){
288                $files = array();
289                $fichiers = reset($contenu);           
290                foreach($fichiers as $fichier){
291                        $f = basename($fichier['filename']);
292                        $files[] = array('tmp_name'=>$tmp_dir. $f,'name'=>$f,'titrer'=>_request('options_deballe_zip_titrer'),'mode'=>_request('options_deballe_zip_mode_document')?'document':null);
293                }
294                return $files;
295        }
296        return _T('avis_operation_impossible');
297}
298
299if (!function_exists('fixer_extension_document')){
300/**
301 * Cherche dans la base le type-mime du tableau representant le document
302 * et corrige le nom du fichier ; retourne array(extension, nom corrige)
303 * s'il ne trouve pas, retourne '' et le nom inchange
304 *
305 * @param unknown_type $doc
306 * @return unknown
307 */
308// https://code.spip.net/@fixer_extension_document
309function fixer_extension_document($doc) {
310        $extension = '';
311        $name = $doc['name'];
312        if (preg_match(',\.([^.]+)$,', $name, $r)
313         AND $t = sql_fetsel("extension", "spip_types_documents",       "extension=" . sql_quote(corriger_extension($r[1])))
314         ) {
315                $extension = $t['extension'];
316                $name = preg_replace(',\.[^.]*$,', '', $doc['name']).'.'.$extension;
317        }
318        else if ($t = sql_fetsel("extension", "spip_types_documents",   "mime_type=" . sql_quote($doc['type']))) {
319                $extension = $t['extension'];
320                $name = preg_replace(',\.[^.]*$,', '', $doc['name']).'.'.$extension;
321        }
322
323        return array($extension,$name);
324}
325}
326
327//
328// Gestion des fichiers ZIP
329//
330// https://code.spip.net/@accepte_fichier_upload
331
332function accepte_fichier_upload ($f) {
333        if (!preg_match(",.*__MACOSX/,", $f)
334        AND !preg_match(",^\.,", basename($f))) {
335        include_spip('action/ajouter_documents');
336                $ext = corriger_extension((strtolower(substr(strrchr($f, "."), 1))));
337                return sql_countsel('spip_types_documents', "extension=" . sql_quote($ext) . " AND upload='oui'");
338        }
339}
340
341# callback pour le deballage d'un zip telecharge
342# http://www.phpconcept.net/pclzip/man/en/?options-pclzip_cb_pre_extractfunction
343// https://code.spip.net/@callback_deballe_fichier
344
345function callback_deballe_fichier($p_event, &$p_header) {
346        if (accepte_fichier_upload($p_header['filename'])) {
347                $p_header['filename'] = _tmp_dir . basename($p_header['filename']);
348                return 1;
349        } else {
350                return 0;
351        }
352}
353
354?>
Note: See TracBrowser for help on using the repository browser.