[SPIP] ~v3.0.20-->v3.0.25
[lhc/web/clavette_www.git] / www / plugins-dist / medias / inc / joindre_document.php
1 <?php
2
3 /***************************************************************************\
4 * SPIP, Systeme de publication pour l'internet *
5 * *
6 * Copyright (c) 2001-2016 *
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
13 if (!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 */
24 function 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('action/ajouter_documents');
76 $infos = renseigner_source_distante($path);
77 if (!is_array($infos))
78 return $infos; // message d'erreur
79 else
80 return array(
81 array(
82 'name' => basename($path),
83 'tmp_name' => $path,
84 'distant' => true,
85 )
86 );
87 }
88 elseif (_request('joindre_ftp')){
89 $path = _request('cheminftp');
90 if (!$path || strstr($path, '..')) return _T('medias:erreur_indiquez_un_fichier');
91
92 include_spip('inc/documents');
93 include_spip('inc/actions');
94 $upload = determine_upload();
95 if ($path != '/' AND $path != './') $upload .= $path;
96
97 if (!is_dir($upload))
98 // seul un fichier est demande
99 return array(
100 array (
101 'name' => basename($upload),
102 'tmp_name' => $upload
103 )
104 );
105 else {
106 // on upload tout un repertoire
107 $files = array();
108 foreach (preg_files($upload) as $fichier) {
109 $files[]= array (
110 'name' => basename($fichier),
111 'tmp_name' => $fichier
112 );
113 }
114 return $files;
115 }
116 }
117 elseif (_request('joindre_zip') and $token_zip = _request('chemin_zip')) {
118
119 $zip_to_clean = (isset($GLOBALS['visiteur_session']['zip_to_clean']) ? unserialize($GLOBALS['visiteur_session']['zip_to_clean']) : array());
120 if (!$zip_to_clean or !isset($zip_to_clean[$token_zip]) or !$path = $zip_to_clean[$token_zip]){
121 return _T('avis_operation_impossible');
122 }
123
124 include_spip('inc/documents'); //pour creer_repertoire_documents
125 define('_tmp_zip', $path);
126 define('_tmp_dir', creer_repertoire_documents(md5($path.$GLOBALS['visiteur_session']['id_auteur'])));
127 if (_tmp_dir == _DIR_IMG)
128 return _T('avis_operation_impossible');
129
130 $files = array();
131 if (_request('options_upload_zip')=='deballe')
132 $files = joindre_deballer_lister_zip($path,_tmp_dir);
133
134 // si le zip doit aussi etre conserve, l'ajouter
135 if (_request('options_upload_zip')=='upload' OR _request('options_deballe_zip_conserver')){
136 $files[] = array(
137 'name' => basename($path),
138 'tmp_name' => $path,
139 );
140 }
141
142 return $files;
143
144 }
145
146 return array();
147 }
148
149
150 // Erreurs d'upload
151 // renvoie false si pas d'erreur
152 // et true si erreur = pas de fichier
153 // pour les autres erreurs renvoie le message d'erreur
154 function joindre_upload_error($error) {
155
156 if (!$error) return false;
157 spip_log("Erreur upload $error -- cf. http://php.net/manual/fr/features.file-upload.errors.php");
158 switch ($error) {
159
160 case 4: /* UPLOAD_ERR_NO_FILE */
161 return true;
162
163 # on peut affiner les differents messages d'erreur
164 case 1: /* UPLOAD_ERR_INI_SIZE */
165 $msg = _T('medias:upload_limit',
166 array('max' => ini_get('upload_max_filesize')));
167 break;
168 case 2: /* UPLOAD_ERR_FORM_SIZE */
169 $msg = _T('medias:upload_limit',
170 array('max' => ini_get('upload_max_filesize')));
171 break;
172 case 3: /* UPLOAD_ERR_PARTIAL */
173 $msg = _T('medias:upload_limit',
174 array('max' => ini_get('upload_max_filesize')));
175 break;
176 case 6: /* UPLOAD_ERR_NO_TMP_DIR */
177 $msg = _T('medias:erreur_dossier_tmp_manquant');
178 break;
179 case 7: /* UPLOAD_ERR_CANT_WRITE */
180 $msg = _T('medias:erreur_ecriture_fichier');
181
182 default: /* autre */
183 if (!$msg)
184 $msg = _T('pass_erreur').' '. $error
185 . '<br />' . propre("[->http://php.net/manual/fr/features.file-upload.errors.php]");
186 break;
187 }
188
189 spip_log ("erreur upload $error");
190 return $msg;
191
192 }
193
194 /**
195 * Verifier si le fichier poste est un zip
196 * Si on sait le deballer, proposer les options necessaires
197 *
198 * @param array $files
199 * @return string
200 */
201 function joindre_verifier_zip($files){
202 if (function_exists('gzopen')
203 AND (count($files) == 1)
204 AND !isset($files[0]['distant'])
205 AND
206 (preg_match('/\.zip$/i', $files[0]['name'])
207 OR (isset($files[0]['type']) AND $files[0]['type'] == 'application/zip'))
208 ){
209
210 // on pose le fichier dans le repertoire zip
211 // (nota : copier_document n'ecrase pas un fichier avec lui-meme
212 // ca autorise a boucler)
213 include_spip('inc/getdocument');
214 $desc = $files[0];
215 $zip = copier_document("zip",
216 $desc['name'],
217 $desc['tmp_name']
218 );
219
220 // Est-ce qu'on sait le lire ?
221 include_spip('inc/pclzip');
222 if ($zip
223 AND $archive = new PclZip($zip)
224 AND $contenu = joindre_decrire_contenu_zip($archive)
225 AND $tmp = sous_repertoire(_DIR_TMP,"zip")
226 AND rename($zip, $tmp = $tmp.basename($zip))
227 ){
228 $zip_to_clean = (isset($GLOBALS['visiteur_session']['zip_to_clean'])?unserialize($GLOBALS['visiteur_session']['zip_to_clean']):array());
229 $zip_to_clean[md5($tmp)] = $tmp;
230 session_set('zip_to_clean',serialize($zip_to_clean));
231 $contenu[] = $tmp;
232 return $contenu;
233 }
234 }
235
236 // ce n'est pas un zip sur lequel il faut demander plus de precisions
237 return false;
238 }
239
240 /**
241 * Verifier et decrire les fichiers de l'archive, en deux listes :
242 * - une liste des noms de fichiers ajoutables
243 * - une liste des erreurs (fichiers refuses)
244 *
245 * @param object $zip
246 * @return array
247 */
248 function joindre_decrire_contenu_zip($zip) {
249 include_spip('action/ajouter_documents');
250 // si pas possible de decompacter: installer comme fichier zip joint
251 if (!$list = $zip->listContent()) return false;
252
253 // Verifier si le contenu peut etre uploade (verif extension)
254 $fichiers = array();
255 $erreurs = array();
256 foreach ($list as $file) {
257 if (accepte_fichier_upload($f = $file['stored_filename']))
258 $fichiers[$f] = $file;
259 else
260 // pas de message pour les dossiers et fichiers caches
261 if (substr($f,-1)!=='/' AND substr(basename($f),0,1)!=='.')
262 $erreurs[] = _T('medias:erreur_upload_type_interdit',array('nom'=>$f));
263 }
264
265 // si aucun fichier uploadable : installer comme fichier zip joint
266 if (!count($fichiers))
267 return false;
268
269 ksort($fichiers);
270 return array($fichiers,$erreurs);
271 }
272
273
274
275 // http://code.spip.net/@joindre_deballes
276 function joindre_deballer_lister_zip($path,$tmp_dir) {
277 include_spip('inc/pclzip');
278 $archive = new PclZip($path);
279 $archive->extract(
280 PCLZIP_OPT_PATH, _tmp_dir,
281 PCLZIP_CB_PRE_EXTRACT, 'callback_deballe_fichier'
282 );
283 if ($contenu = joindre_decrire_contenu_zip($archive)){
284 $files = array();
285 $fichiers = reset($contenu);
286 foreach($fichiers as $fichier){
287 $f = basename($fichier['filename']);
288 $files[] = array('tmp_name'=>$tmp_dir. $f,'name'=>$f,'titrer'=>_request('options_deballe_zip_titrer'),'mode'=>_request('options_deballe_zip_mode_document')?'document':null);
289 }
290 return $files;
291 }
292 return _T('avis_operation_impossible');
293 }
294
295 if (!function_exists('fixer_extension_document')){
296 /**
297 * Cherche dans la base le type-mime du tableau representant le document
298 * et corrige le nom du fichier ; retourne array(extension, nom corrige)
299 * s'il ne trouve pas, retourne '' et le nom inchange
300 *
301 * @param unknown_type $doc
302 * @return unknown
303 */
304 // http://code.spip.net/@fixer_extension_document
305 function fixer_extension_document($doc) {
306 $extension = '';
307 $name = $doc['name'];
308 if (preg_match(',\.([^.]+)$,', $name, $r)
309 AND $t = sql_fetsel("extension", "spip_types_documents", "extension=" . sql_quote(corriger_extension($r[1])))
310 ) {
311 $extension = $t['extension'];
312 $name = preg_replace(',\.[^.]*$,', '', $doc['name']).'.'.$extension;
313 }
314 else if ($t = sql_fetsel("extension", "spip_types_documents", "mime_type=" . sql_quote($doc['type']))) {
315 $extension = $t['extension'];
316 $name = preg_replace(',\.[^.]*$,', '', $doc['name']).'.'.$extension;
317 }
318
319 return array($extension,$name);
320 }
321 }
322
323 //
324 // Gestion des fichiers ZIP
325 //
326 // http://code.spip.net/@accepte_fichier_upload
327
328 function accepte_fichier_upload ($f) {
329 if (!preg_match(",.*__MACOSX/,", $f)
330 AND !preg_match(",^\.,", basename($f))) {
331 include_spip('action/ajouter_documents');
332 $ext = corriger_extension((strtolower(substr(strrchr($f, "."), 1))));
333 return sql_countsel('spip_types_documents', "extension=" . sql_quote($ext) . " AND upload='oui'");
334 }
335 }
336
337 # callback pour le deballage d'un zip telecharge
338 # http://www.phpconcept.net/pclzip/man/en/?options-pclzip_cb_pre_extractfunction
339 // http://code.spip.net/@callback_deballe_fichier
340
341 function callback_deballe_fichier($p_event, &$p_header) {
342 if (accepte_fichier_upload($p_header['filename'])) {
343 $p_header['filename'] = _tmp_dir . basename($p_header['filename']);
344 return 1;
345 } else {
346 return 0;
347 }
348 }
349
350 ?>