source: spip-zone/_core_/plugins/medias/action/ajouter_documents.php @ 47630

Last change on this file since 47630 was 47630, checked in by kent1@…, 10 years ago

prendre en compte les fichiers avec extension mpeg comme des mpg

File size: 12.6 KB
Line 
1<?php
2
3/***************************************************************************\
4 *  SPIP, Systeme de publication pour l'internet                           *
5 *                                                                         *
6 *  Copyright (c) 2001-2011                                                *
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
15include_spip('inc/getdocument');
16include_spip('inc/documents');
17include_spip('inc/ajouter_documents'); // compat core
18include_spip('inc/choisir_mode_document'); // compat core
19include_spip('inc/renseigner_document');
20
21/**
22 * Ajouter des documents
23 *
24 * @param int $id_document
25 *   document a remplacer, ou pour une vignette, l'id_document de maman
26 *   0 ou 'new' pour une insertion
27 * @param  $files
28 *   tableau de taleau de propriete pour chaque document a inserer
29 * @param  $objet
30 *   objet auquel associer le document
31 * @param  $id_objet
32 *   id_objet
33 * @param  $mode
34 *   mode par defaut si pas precise pour le document
35 * @return array
36 *   liste des id_documents inseres
37 */
38function action_ajouter_documents_dist($id_document, $files, $objet, $id_objet, $mode){
39        $ajouter_un_document = charger_fonction('ajouter_un_document','action');
40        $ajoutes = array();
41
42        // on ne peut mettre qu'un seul document a la place d'un autre ou en vignette d'un autre
43        if (intval($id_document)){
44                $ajoutes[] = $ajouter_un_document($id_document, reset($files), $objet, $id_objet, $mode);
45        }
46        else
47                foreach($files as $file){
48                        $ajoutes[] = $ajouter_un_document('new', $file, $objet, $id_objet, $mode);
49                }
50        return $ajoutes;
51}
52
53/**
54 * Ajouter un document (au format $_FILES)
55 *
56 * http://doc.spip.org/@ajouter_un_document
57 *
58 * @param int $id_document
59 *   document a remplacer, ou pour une vignette, l'id_document de maman
60 *   0 ou 'new' pour une insertion
61 * @param array $file
62 *   proprietes au format $_FILE etendu :
63 *     strin tmp_name : source sur le serveur
64 *     string name : nom du fichier envoye
65 *     bool titrer : donner ou non un titre a partir du nom du fichier
66 *     bool distant : pour utiliser une source distante sur internet
67 *     string mode : vignette|image|documents|choix
68 * @param string $objet
69 *   objet auquel associer le document
70 * @param int $id_objet
71 *   id_objet
72 * @param string $mode
73 *   mode par defaut si pas precise pour le document
74 * @return array|bool|int|mixed|string|unknown
75 */
76function action_ajouter_un_document_dist($id_document, $file, $objet, $id_objet, $mode) {
77       
78        $source = $file['tmp_name'];
79        $nom_envoye = $file['name'];
80
81        // passer en minuscules le nom du fichier, pour eviter les collisions
82        // si le file system fait la difference entre les deux il ne detectera
83        // pas que Toto.pdf et toto.pdf
84        // et on aura une collision en cas de changement de file system
85        $file['name'] = strtolower(translitteration($file['name']));
86       
87        // Pouvoir definir dans mes_options.php que l'on veut titrer tous les documents par d?faut
88        if (!defined('_TITRER_DOCUMENTS')) { define('_TITRER_DOCUMENTS', false); }
89
90        $titrer = isset($file['titrer'])?$file['titrer']:_TITRER_DOCUMENTS;
91        $mode = ((isset($file['mode']) AND $file['mode'])?$file['mode']:$mode);
92
93        include_spip('inc/modifier');
94        if (isset($file['distant']) AND $file['distant'] AND !in_array($mode,array('choix','auto','image','document'))) {
95                include_spip('inc/distant');
96                $file['tmp_name'] = _DIR_RACINE . copie_locale($source);
97                $source = $file['tmp_name'];
98                unset($file['distant']);
99        }
100
101        // Documents distants : pas trop de verifications bloquantes, mais un test
102        // via une requete HEAD pour savoir si la ressource existe (non 404), si le
103        // content-type est connu, et si possible recuperer la taille, voire plus.
104        if (isset($file['distant']) AND $file['distant']) {
105                include_spip('inc/distant');
106                if (is_array($a = renseigner_source_distante($source))) {
107
108                        $champs = $a;
109                        # NB: dans les bonnes conditions (fichier autorise et pas trop gros)
110                        # $a['fichier'] est une copie locale du fichier
111
112                        unset($champs['type_image']);
113                }
114                // on ne doit plus arriver ici, car l'url distante a ete verifiee a la saisie !
115                else {
116                        spip_log("Echec du lien vers le document $source, abandon");
117                        return $a; // message d'erreur
118                }
119        }
120        else { // pas distant
121
122                $champs = array(
123                        'distant' => 'non'
124                );
125               
126                $type_image = ''; // au pire
127                $champs['titre'] = '';
128                if ($titrer){
129                        $titre = substr($nom_envoye,0, strrpos($nom_envoye, ".")); // Enlever l'extension du nom du fichier
130                        $titre = preg_replace(',[[:punct:][:space:]]+,u', ' ', $titre);
131                        $champs['titre'] = preg_replace(',\.([^.]+)$,', '', $titre);
132                }
133
134                if (!is_array($fichier = fixer_fichier_upload($file, $mode)))
135                        return is_string($fichier)?$fichier:_T("erreur_upload_type_interdit",array('nom'=>$file['name']));
136               
137                $champs['inclus'] = $fichier['inclus'];
138                $champs['extension'] = $fichier['extension'];
139                $champs['fichier'] = $fichier['fichier'];
140
141
142                $infos = renseigner_taille_dimension_image($champs['fichier'],$champs['extension']);
143                if (is_string($infos))
144                        return $infos; // c'est un message d'erreur !
145               
146                $champs = array_merge($champs,$infos);
147
148                // Si mode == 'choix', fixer le mode image/document
149                if (in_array($mode,array('choix','auto'))) {
150                        $choisir_mode_document = charger_fonction('choisir_mode_document','inc');
151                        $mode = $choisir_mode_document($champs, $champs['inclus'] == 'image', $objet);
152                }
153                $champs['mode'] = $mode;
154
155                if (($test = verifier_taille_document_acceptable($champs))!==true){
156                        spip_unlink($champs['fichier']);
157                        return $test; // erreur sur les dimensions du fichier
158                }
159
160               
161                unset($champs['type_image']);
162                unset($champs['inclus']);
163                $champs['fichier'] = set_spip_doc($champs['fichier']);
164        }
165       
166        // lier le parent si necessaire
167        if ($id_objet=intval($id_objet) AND $objet)
168                $champs['parents'][] = "$objet|$id_objet";
169
170        // "mettre a jour un document" si on lui
171        // passe un id_document
172        if ($id_document=intval($id_document)){
173                unset($champs['titre']); // garder le titre d'origine
174                unset($champs['date']); // garder la date d'origine
175                unset($champs['descriptif']); // garder la desc d'origine
176                // unset($a['distant']); # on peut remplacer un doc statique par un doc distant
177                // unset($a['mode']); # on peut remplacer une image par un document ?
178        }
179
180        include_spip('action/editer_document');
181        // Installer le document dans la base
182        if (!$id_document){
183                if ($id_document = insert_document())
184                        spip_log ("ajout du document ".$file['tmp_name']." ".$file['name']."  (M '$mode' T '$objet' L '$id_objet' D '$id_document')",'medias');
185                else
186                        spip_log ("Echec insert_document() du document ".$file['tmp_name']." ".$file['name']."  (M '$mode' T '$objet' L '$id_objet' D '$id_document')",'medias'._LOG_ERREUR);
187        }
188        if (!$id_document)
189                return _T('medias:erreur_insertion_document_base',array('fichier'=>"<em>".$file['name']."</em>"));
190       
191        document_modifier($id_document,$champs);
192
193        // permettre aux plugins de faire des modifs a l'ajout initial
194        // ex EXIF qui tourne les images si necessaire
195        pipeline('post_edition',
196                array(
197                        'args' => array(
198                                'table' => 'spip_documents', // compatibilite
199                                'table_objet' => 'documents',
200                                'spip_table_objet' => 'spip_documents',
201                                'type' =>'document',
202                                'id_objet' => $id_document,
203                                'champs' => array_keys($champs),
204                                'serveur' => '', // serveur par defaut, on ne sait pas faire mieux pour le moment
205                                'action' => 'ajouter_document',
206                                'operation' => 'ajouter_document', // compat <= v2.0
207                        ),
208                        'data' => $champs
209                )
210        );
211
212        return $id_document ;
213}
214
215
216/**
217 * Corrige l'extension du fichier dans quelques cas particuliers
218 * (a passer dans ecrire/base/typedoc)
219 * A noter : une extension 'pdf ' passe dans la requete de controle
220 * mysql> SELECT * FROM spip_types_documents WHERE extension="pdf ";
221 *
222 * @param string $ext
223 * @return string
224 */
225function corriger_extension($ext) {
226        $ext = preg_replace(',[^a-z0-9],i', '', $ext);
227        switch ($ext) {
228                case 'htm':
229                        $ext='html';
230                        break;
231                case 'jpeg':
232                        $ext='jpg';
233                        break;
234                case 'tiff':
235                        $ext='tif';
236                        break;
237                case 'mpeg':
238                        $ext='mpg';
239                        break;
240        }
241        return $ext;
242}
243
244/**
245 * Verifie la possibilite d'uploader une extension
246 * renvoie un tableau descriptif si l'extension est acceptee
247 * avec un index 'autozip' si il faut zipper
248 * false ou message d'erreur si l'extension est refusee
249 * Verifie aussi si l'extension est autorisee pour le mode demande
250 * si on connait le mode a ce moment la
251 *
252 */
253function verifier_upload_autorise($source, $mode=''){
254        $infos = array('fichier'=>$source);
255        $res = false;
256        if (preg_match(",\.([^.]+)$,", $source, $match)
257          AND $ext = $match[1]){
258               
259          $ext = corriger_extension(strtolower($ext));
260                if ($res = sql_fetsel("extension,inclus,media", "spip_types_documents", "extension=" . sql_quote($ext) . " AND upload='oui'"))
261                        $infos = array_merge($infos,$res);
262        }
263        if (!$res){
264                if ($res = sql_fetsel("extension,inclus,media", "spip_types_documents", "extension='zip' AND upload='oui'")){
265                        $infos = array_merge($infos,$res);
266                        $res['autozip'] = true;
267                }
268        }
269        if ($mode AND $res){
270                // verifier en fonction du mode si une fonction est proposee
271                if ($verifier_document_mode = charger_fonction("verifier_document_mode_".$mode,"inc",true)){
272                        $check = $verifier_document_mode($infos); // true ou message d'erreur sous forme de chaine
273                        if ($check!==true)
274                                $res = $check;
275                }
276        }
277
278        if (!$res OR is_string($res));
279                spip_log("Upload $source interdit ($res)",_LOG_INFO_IMPORTANTE);
280        return $res;
281}
282
283
284/**
285 * tester le type de document :
286 * - interdit a l'upload ?
287 * - quelle extension dans spip_types_documents ?
288 * - est-ce "inclus" comme une image ?
289 *
290 * le zipper si necessaire
291 *
292 * @param array $file //format $_FILES
293 * @return array
294 */
295function fixer_fichier_upload($file, $mode=''){
296
297        if (is_array($row=verifier_upload_autorise($file['name'], $mode))) {
298                if (!isset($row['autozip'])){
299                        $row['fichier'] = copier_document($row['extension'], $file['name'], $file['tmp_name']);
300                        return $row;
301                }
302                // creer un zip comme demande
303                // pour encapsuler un fichier dont l'extension n'est pas supportee
304                else{
305               
306                        unset($row['autozip']);
307
308                        $ext = 'zip';
309                        if (!$tmp_dir = tempnam(_DIR_TMP, 'tmp_upload'))
310                                return false;
311
312                        spip_unlink($tmp_dir);
313                        @mkdir($tmp_dir);
314
315                        include_spip('inc/charset');
316                        $tmp = $tmp_dir.'/'.translitteration($file['name']);
317
318                        $file['name'] .= '.'.$ext; # conserver l'extension dans le nom de fichier, par exemple toto.js => toto.js.zip
319
320                        // deplacer le fichier tmp_name dans le dossier tmp
321                        deplacer_fichier_upload($file['tmp_name'], $tmp, true);
322
323                        include_spip('inc/pclzip');
324                        $source = _DIR_TMP . basename($tmp_dir) . '.'.$ext;
325                        $archive = new PclZip($source);
326
327                        $v_list = $archive->create($tmp,
328                                        PCLZIP_OPT_REMOVE_PATH, $tmp_dir,
329                                        PCLZIP_OPT_ADD_PATH, '');
330
331                        effacer_repertoire_temporaire($tmp_dir);
332                        if (!$v_list) {
333                                spip_log("Echec creation du zip ");
334                                return false;
335                        }
336
337                        $row['fichier']  = copier_document($row['extension'], $file['name'], $source);
338                        spip_unlink($source);
339                        return $row;
340                }
341        }
342        else
343                return $row; // retourner le message d'erreur
344}
345
346/**
347 * Verifier si le fichier respecte les contraintes de tailles
348 *
349 * @param  $infos
350 * @return bool|mixed|string
351 */
352function verifier_taille_document_acceptable($infos){
353       
354        // si ce n'est pas une image
355        if (!$infos['type_image']) {
356                if (_DOC_MAX_SIZE > 0
357                 AND $infos['taille'] > _DOC_MAX_SIZE*1024)
358                        return _T('medias:info_doc_max_poids', array('maxi' => taille_en_octets(_DOC_MAX_SIZE*1024), 'actuel' => taille_en_octets($infos['taille'])));
359        }
360       
361        // si c'est une image
362        else {
363
364                if (_IMG_MAX_SIZE > 0
365                 AND $infos['taille'] > _IMG_MAX_SIZE*1024)
366                        return _T('medias:info_image_max_poids', array('maxi' => taille_en_octets(_IMG_MAX_SIZE*1024), 'actuel' => taille_en_octets($infos['taille'])));
367       
368                if (_IMG_MAX_WIDTH * _IMG_MAX_HEIGHT
369                 AND ($infos['largeur'] > _IMG_MAX_WIDTH
370                 OR $infos['hauteur'] > _IMG_MAX_HEIGHT))
371
372                        return _T('medias:info_logo_max_taille',
373                                        array(
374                                        'maxi' =>
375                                                _T('info_largeur_vignette',
376                                                        array('largeur_vignette' => _IMG_MAX_WIDTH,
377                                                        'hauteur_vignette' => _IMG_MAX_HEIGHT)),
378                                        'actuel' =>
379                                                _T('info_largeur_vignette',
380                                                        array('largeur_vignette' => $infos['largeur'],
381                                                        'hauteur_vignette' => $infos['hauteur']))
382                                ));
383        }
384
385  // verifier en fonction du mode si une fonction est proposee
386        if ($verifier_document_mode = charger_fonction("verifier_document_mode_".$infos['mode'],"inc",true))
387                return $verifier_document_mode($infos);
388
389        return true;
390}
391
392
393?>
Note: See TracBrowser for help on using the repository browser.