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