[SPIP] ~2.1.12 -->2.1.25
[velocampus/web/www.git] / www / ecrire / inc / documents.php
1 <?php
2
3 /***************************************************************************\
4 * SPIP, Systeme de publication pour l'internet *
5 * *
6 * Copyright (c) 2001-2014 *
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/actions'); // *action_auteur et determine_upload
16 include_spip('inc/date');
17
18 // donne le chemin du fichier relatif a _DIR_IMG
19 // pour stockage 'tel quel' dans la base de donnees
20 // http://doc.spip.org/@set_spip_doc
21 function set_spip_doc($fichier) {
22 if (strpos($fichier, _DIR_IMG) === 0)
23 return substr($fichier, strlen(_DIR_IMG));
24 else
25 return $fichier; // ex: fichier distant
26 }
27
28 // donne le chemin complet du fichier
29 // http://doc.spip.org/@get_spip_doc
30 function get_spip_doc($fichier) {
31 // fichier distant
32 if (preg_match(',^\w+://,', $fichier))
33 return $fichier;
34
35 // gestion d'erreurs, fichier=''
36 if (!strlen($fichier))
37 return false;
38
39 $fichier = (strpos($fichier, _DIR_IMG) === false)
40 ? _DIR_IMG . $fichier
41 : $fichier ;
42
43 // fichier normal
44 return $fichier;
45 }
46
47 // Constante indiquant le charset probable des documents non utf-8 joints
48
49 if (!defined('CHARSET_JOINT')) define('CHARSET_JOINT', 'iso-8859-1');
50
51 // Filtre pour #FICHIER permettant d'incruster le contenu d'un document
52 // Si 2e arg fourni, conversion dans le charset du site si possible
53
54 // http://doc.spip.org/@contenu_document
55 function contenu_document($arg, $charset='')
56 {
57 if (is_numeric($arg)) {
58 $r = sql_fetsel("fichier,distant", "spip_documents", "id_document=".sql_quote($arg));
59 if (!$r) return '';
60 $f = $r['fichier'];
61 $f = ($r['distant'] =='oui') ? _DIR_RACINE . copie_locale($f) : get_spip_doc($f);
62 }
63 else {
64 if (!@file_exists($f=$arg)){
65 if (!$f = copie_locale($f))
66 return '';
67 $f = _DIR_RACINE . $f;
68 }
69 }
70
71 $r = spip_file_get_contents($f);
72
73 if ($charset) {
74 include_spip('inc/charset');
75 if ($charset !== 'auto') {
76 $r = importer_charset($r, $charset);
77 } elseif ($GLOBALS['meta']['charset'] == 'utf-8' AND !is_utf8($r))
78 $r = importer_charset($r, CHARSET_JOINT);
79 }
80 return $r;
81 }
82
83 // http://doc.spip.org/@generer_url_document_dist
84 function generer_url_document_dist($id_document, $args='', $ancre='') {
85
86 include_spip('inc/autoriser');
87 if (!autoriser('voir', 'document', $id_document)) return '';
88
89 $r = sql_fetsel("fichier,distant", "spip_documents", "id_document=".sql_quote($id_document));
90
91 if (!$r) return '';
92
93 $f = $r['fichier'];
94
95 if ($r['distant'] == 'oui') return $f;
96
97 // Si droit de voir tous les docs, pas seulement celui-ci
98 // il est inutilement couteux de rajouter une protection
99
100 $r = autoriser('voir', 'document');
101
102 if ($r AND $r !== 'htaccess') return get_spip_doc($f);
103
104 return generer_acceder_document($f, $id_document, $args, $ancre);
105 }
106
107 // cette action doit etre publique !
108 function generer_acceder_document($file, $id_document, $args='', $ancre='')
109 {
110 include_spip('inc/securiser_action');
111
112 return generer_url_action('acceder_document',
113 $args . ($args ? "&" : '')
114 . 'arg='.$id_document
115 . ($ancre ? "&ancre=$ancre" : '')
116 . '&cle=' . calculer_cle_action($id_document.','.$file)
117 . '&file=' . rawurlencode($file)
118 ,false,true);
119 }
120
121 // http://doc.spip.org/@document_et_vignette
122 function document_et_vignette($document, $url, $portfolio=false) {
123 $image = $document['id_vignette'];
124
125 if ($image)
126 $image = sql_fetsel("*", "spip_documents", "id_document = ".$image);
127 if ($image) {
128 if (!$portfolio OR !($GLOBALS['meta']['creer_preview'] == 'oui')) {
129 $x = $image['largeur'];
130 $y = $image['hauteur'];
131 } else {
132 $x = 120;
133 $y = 110;
134 }
135 $image = get_spip_doc($image['fichier']);
136 } else {
137 if ($portfolio) {
138 $x = 110;
139 $y = 120;
140 } else $x = $y =-1;
141 }
142 if (!$url) $url = generer_url_document_dist($document['id_document'], 'document');
143 return vignette_automatique($image, $document, $url, $x, $y, '', "miniature_document");
144 }
145
146 //
147 // Affiche le document avec sa vignette par defaut
148 //
149 // Attention : en mode 'doc', si c'est un fichier graphique on prefere
150 // afficher une vue reduite, quand c'est possible (presque toujours, donc)
151 // En mode 'image', l'image conserve sa taille
152 //
153 // A noter : dans le portfolio prive on pousse le vice jusqu'a reduire la taille
154 // de la vignette -> c'est a ca que sert la variable $portfolio
155 // http://doc.spip.org/@vignette_automatique
156 function vignette_automatique($img, $doc, $lien, $x=0, $y=0, $align='', $class='spip_logos')
157 {
158 include_spip('inc/distant');
159 include_spip('inc/texte');
160 include_spip('inc/filtres_images_mini');
161 $e = $doc['extension'];
162 if (!$img) {
163 if ($img = image_du_document($doc)) {
164 if (!$x AND !$y) // eviter une double reduction
165 $img = image_reduire($img);
166 }
167 else{
168 $f = charger_fonction('vignette','inc');
169 $img = $f($e, false);
170 $size = @getimagesize($img);
171 $img = "<img src='$img' ".$size[3]." />";
172 }
173 }
174 else{
175 $size = @getimagesize($img);
176 $img = "<img src='$img' ".$size[3]." />";
177 }
178 // on appelle image_reduire independamment de la presence ou non
179 // des librairies graphiques
180 // la fonction sait se debrouiller et faire de son mieux dans tous les cas
181 if ($x OR $y) {
182 $img = image_reduire($img, $x, $y);
183 }
184 $img = inserer_attribut($img, 'alt', '');
185 $img = inserer_attribut($img, 'class', $class);
186 if ($align) $img = inserer_attribut($img, 'align', $align);
187
188 if (!$lien) return $img;
189
190 $titre = supprimer_tags(typo($doc['titre']));
191 $titre = " - " .taille_en_octets($doc['taille'])
192 . ($titre ? " - $titre" : "");
193
194 $type = sql_fetsel('titre, mime_type','spip_types_documents', "extension = " . sql_quote($e));
195
196 $mime = $type['mime_type'];
197 $titre = attribut_html(couper($type['titre'] . $titre, 80));
198
199 return "<a href='$lien' type='$mime' title='$titre'>$img</a>";
200 }
201
202 // Trouve une image caracteristique d'un document.
203 // Si celui-ci est une image et que les outils graphiques sont dispos,
204 // retourner le document (en exploitant sa copie locale s'il est distant).
205 // Autrement retourner la vignette fournie par SPIP pour ce type MIME
206 // Resultat: un fichier local existant
207
208 function image_du_document($document)
209 {
210 $e = $document['extension'];
211 if ((strpos($GLOBALS['meta']['formats_graphiques'], $e) !== false)
212 AND (!test_espace_prive() OR $GLOBALS['meta']['creer_preview']=='oui')
213 AND $document['fichier']) {
214 if ($document['distant'] == 'oui') {
215 $image = _DIR_RACINE.copie_locale($document['fichier']);
216 }
217 else
218 $image = get_spip_doc($document['fichier']);
219 if (@file_exists($image)) return $image;
220 }
221 return '';
222 }
223
224 //
225 // Afficher un document dans la colonne de gauche
226 //
227
228 // http://doc.spip.org/@afficher_documents_colonne
229 function afficher_documents_colonne($id, $type="article",$script=NULL) {
230 include_spip('inc/autoriser');
231
232 // il faut avoir les droits de modif sur l'article pour pouvoir uploader !
233 if (!autoriser('joindredocument',$type,$id))
234 return "";
235
236 include_spip('inc/presentation'); // pour l'aide quand on appelle afficher_documents_colonne depuis un squelette
237 // seuls cas connus : article, breve ou rubrique
238 if ($script==NULL){
239 $script = $type.'s_edit';
240 if (!test_espace_prive())
241 $script = parametre_url(self(),"show_docs",'');
242 }
243 $id_document_actif = _request('show_docs');
244
245 $joindre = charger_fonction('joindre', 'inc');
246
247 define('_INTERFACE_DOCUMENTS', true);
248 if (!_INTERFACE_DOCUMENTS
249 OR $GLOBALS['meta']["documents_$type"]=='non') {
250
251 // Ajouter nouvelle image
252 $ret = "<div id='images'>\n"
253 . $joindre(array(
254 'cadre' => 'relief',
255 'icone' => 'image-24.gif',
256 'fonction' => 'creer.gif',
257 'titre' => majuscules(_T('bouton_ajouter_image')).aide("ins_img"),
258 'script' => $script,
259 'args' => "id_$type=$id",
260 'id' => $id,
261 'intitule' => _T('info_telecharger'),
262 'mode' => 'image',
263 'type' => $type,
264 'ancre' => '',
265 'id_document' => 0,
266 'iframe_script' => generer_url_ecrire("documents_colonne","id=$id&type=$type",true)
267 ))
268 . '</div><br />';
269
270 if (!_INTERFACE_DOCUMENTS) {
271 //// Images sans documents
272 $res = sql_select("D.id_document", "spip_documents AS D LEFT JOIN spip_documents_liens AS T ON T.id_document=D.id_document", "T.id_objet=" . intval($id) . " AND T.objet=" . sql_quote($type) . " AND D.mode='image'", "", "D.id_document");
273
274 $ret .= "\n<div id='liste_images'>";
275
276 while ($doc = sql_fetch($res)) {
277 $id_document = $doc['id_document'];
278 $deplier = ($id_document_actif==$id_document);
279 $ret .= afficher_case_document($id_document, $id, $script, $type, $deplier);
280 }
281
282 $ret .= "</div><br /><br />\n";
283 }
284 }
285
286 /// Ajouter nouveau document
287 $bouton = !_INTERFACE_DOCUMENTS
288 ? majuscules(_T('bouton_ajouter_document')).aide("ins_doc")
289 : (_T('bouton_ajouter_image_document')).aide("ins_doc");
290
291 $ret .= "<div id='documents'></div>\n<div id='portfolio'></div>\n";
292 if ($GLOBALS['meta']["documents_$type"]!='non') {
293 $ret .= $joindre(array(
294 'cadre' => _INTERFACE_DOCUMENTS ? 'relief' : 'enfonce',
295 'icone' => 'doc-24.gif',
296 'fonction' => 'creer.gif',
297 'titre' => $bouton,
298 'script' => $script,
299 'args' => "id_$type=$id",
300 'id' => $id,
301 'intitule' => _T('info_telecharger'),
302 'mode' => _INTERFACE_DOCUMENTS ? 'choix' : 'document',
303 'type' => $type,
304 'ancre' => '',
305 'id_document' => 0,
306 'iframe_script' => generer_url_ecrire("documents_colonne","id=$id&type=$type",true)
307 ));
308 }
309
310 // Afficher les documents lies
311 $ret .= "<br /><div id='liste_documents'>\n";
312
313 //// Documents associes
314 $res = sql_select("D.id_document", "spip_documents AS D LEFT JOIN spip_documents_liens AS T ON T.id_document=D.id_document", "T.id_objet=" . intval($id) . " AND T.objet=" . sql_quote($type)
315 . ((!_INTERFACE_DOCUMENTS)
316 ? " AND D.mode='document'"
317 : " AND D.mode IN ('image','document')"
318 ), "", "D.mode, D.id_document");
319
320 while($row = sql_fetch($res))
321 $ret .= afficher_case_document($row['id_document'], $id, $script, $type, ($id_document_actif==$row['id_document']));
322
323 $ret .= "</div>";
324 if (test_espace_prive()){
325 $ret .= http_script('', "async_upload.js")
326 . http_script('$("form.form_upload").async_upload(async_upload_article_edit)');
327 }
328
329 return $ret;
330 }
331
332 //
333 // Affiche le raccourci <doc123|left>
334 // et l'insere quand on le clique
335 //
336 // http://doc.spip.org/@affiche_raccourci_doc
337 function affiche_raccourci_doc($doc, $id, $align) {
338 static $num = 0;
339
340 if ($align) {
341 $pipe = "|$align";
342
343 if ($GLOBALS['browser_barre'])
344 $onclick = "\nondblclick=\"barre_inserer('\\x3C$doc$id$pipe&gt;', $('textarea[name=texte]')[0]);\"\ntitle=\"". str_replace('&amp;', '&', entites_html(_T('double_clic_inserer_doc')))."\"";
345 } else {
346 $align='center';
347 }
348
349 return
350 ((++$num > 1) ? "" : http_script('', "spip_barre.js"))
351 . "\n<div style='text-align: $align'$onclick>&lt;$doc$id$pipe&gt;</div>\n";
352 }
353
354
355 // Est-ce que le document est inclus dans le texte ?
356 // http://doc.spip.org/@est_inclus
357 function est_inclus($id_document) {
358 return isset($GLOBALS['doublons_documents_inclus']) ?
359 in_array($id_document,$GLOBALS['doublons_documents_inclus']) : false;
360 }
361
362 //
363 // Afficher un document sous forme de bloc depliable
364 // en donnant un apercu
365 // et en indiquer le raccourci permettant l'incrustation
366 // Pour les distant, donner un bouton pour rappatriement (trombone)
367 // Pour les images, donnner les boutons de rotations
368
369
370 // http://doc.spip.org/@afficher_case_document
371 function afficher_case_document($id_document, $id, $script, $type, $deplier=false) {
372 global $spip_lang_right;
373
374 $document = sql_fetsel("D.id_document, D.id_vignette,D.extension,D.titre,D.descriptif,D.fichier,D.largeur,D.hauteur,D.taille,D.mode,D.distant, D.date, L.vu", "spip_documents AS D INNER JOIN spip_documents_liens AS L ON L.id_document=D.id_document", "L.id_objet=".intval($id)." AND objet=".sql_quote($type)." AND L.id_document=".intval($id_document));
375
376 if (!$document) return "";
377
378 $id_vignette = $document['id_vignette'];
379 $extension = $document['extension'];
380 $descriptif = $document['descriptif'];
381 $fichier = $document['fichier'];
382 $largeur = $document['largeur'];
383 $hauteur = $document['hauteur'];
384 $mode = $document['mode'];
385 $distant = $document['distant'];
386 $titre = $document['titre'];
387 $legender = charger_fonction('legender', 'inc');
388 $dist = '';
389
390 $r = sql_fetsel("titre,inclus", "spip_types_documents", "extension=".sql_quote($extension));
391 if ($r) {
392 $type_inclus = $r['inclus'];
393 $type_titre = $r['titre'];
394 }
395
396 if ($mode == 'document') {
397
398 if ($distant == 'oui') {
399 include_spip('inc/tourner');
400 $dist = "\n<div class='verdana1' style='float: $spip_lang_right; text-align: $spip_lang_right;'>"
401 . "\n<img src='" . chemin_image('attachment.gif') . "'\n\talt=\"$fichier\"\n\ttitle=\"$fichier\" />\n"
402 . bouton_copier_local($document, $type, $id, $id_document, $script)
403 . "</div>\n";
404 }
405
406 if (est_inclus($id_document))
407 $raccourci = affiche_raccourci_doc('doc', $id_document, '');
408 else {
409 $vign= (($type_inclus == "embed" OR $type_inclus == "image") AND $largeur > 0 AND $hauteur > 0);
410 $raccourci = $vign ? ("<b>"._T('info_inclusion_vignette')."</b><br />") : '';
411
412 $raccourci .= "<div style='color: 333333'>"
413 . affiche_raccourci_doc('doc', $id_document, 'left')
414 . affiche_raccourci_doc('doc', $id_document, 'center')
415 . affiche_raccourci_doc('doc', $id_document, 'right')
416 . "</div>\n";
417
418 if ($vign) {
419 $raccourci .= "<div style='padding:2px; ' class='arial1 spip_xx-small'>";
420 $raccourci .= "<b>"._T('info_inclusion_directe')."</b><br />";
421 $raccourci .= "<div style='color: 333333'>"
422 . affiche_raccourci_doc('emb', $id_document, 'left')
423 . affiche_raccourci_doc('emb', $id_document, 'center')
424 . affiche_raccourci_doc('emb', $id_document, 'right')
425 . "</div>\n";
426 $raccourci .= "</div>";
427 }
428 }
429 $ninclus = false;
430 $icone = 'doc-24.gif';
431 $style = 'e';
432
433 } else if ($mode == 'image') {
434
435 $icone = 'image-24.gif';
436 $style = 'r';
437 $ninclus = ($type_inclus !== 'image');
438 $doc = ($descriptif OR $titre) ? 'doc' : 'img';
439
440 if (est_inclus($id_document))
441 $raccourci = affiche_raccourci_doc($doc, $id_document, '');
442 else {
443 $raccourci =
444 affiche_raccourci_doc($doc, $id_document, 'left')
445 . affiche_raccourci_doc($doc, $id_document, 'center')
446 . affiche_raccourci_doc($doc, $id_document, 'right');
447 }
448
449 }
450 if ($titre)
451 $cadre = $titre;
452 elseif (!$distant)
453 $cadre = basename($fichier);
454 else {
455 preg_match('@^[^/]*/*([^/]*)@', $fichier, $cadre);
456 $cadre = $cadre[1];
457 }
458 $cadre = lignes_longues($cadre, 20);
459 // encapsuler chaque document dans un container pour permettre son remplacement en ajax
460 return '<div>'
461 . debut_cadre($style, $icone, '', $cadre, "document$id_document")
462 . ($ninclus ? '' :
463 ("\n<div style='text-align: center'>"
464 . $dist
465 . document_et_vignette($document, '', true)
466 . '</div>'
467 . "\n<div class='verdana1' style='text-align: center; color: black;'>\n"
468 . ($type_titre ? $type_titre :
469 ( _T('info_document').' '.majuscules($extension)))
470 . "</div>"))
471 . $apercu
472 . "\n<div style='padding:2px;' class='arial1 spip_xx-small'>"
473 . $raccourci
474 . "</div>\n"
475 . $legender($id_document, $document, $script, $type, $id, "document$id_document", $deplier)
476 . fin_cadre($style)
477 . '</div>';
478 }
479
480 // Etablit la liste des documents orphelins, c'est-a-dire qui ne sont lies
481 // a rien ; renvoie un tableau (id_document)
482 // ici on ne join pas avec la table objet pour voir si l'objet existe vraiment
483 // on considere que c'est le role d'optimiser que de nettoyer les liens morts
484 // sinon eventuellement appeler avant une fonction nettoyer_liens_documents
485 // http://doc.spip.org/@lister_les_documents_orphelins
486 function lister_les_documents_orphelins() {
487 $s = sql_select("D.id_document, D.id_vignette", "spip_documents AS D LEFT JOIN spip_documents_liens AS L ON D.id_document=L.id_document", "(L.id_objet IS NULL)");
488
489 $orphelins = array();
490 while ($t = sql_fetch($s)) {
491 $orphelins[$t['id_document']] = true;
492 // la vignette d'un orphelin est orpheline
493 if ($t['id_vignette'])
494 $orphelins[$t['id_vignette']] = true;
495
496 }
497
498 // les vignettes qui n'appartiennent a aucun document sont aussi orphelines
499 $s = sql_select("V.id_document", "spip_documents AS V LEFT JOIN spip_documents AS D ON V.id_document=D.id_vignette", "V.mode='vignette' AND D.id_document IS NULL");
500 while ($t = sql_fetch($s))
501 $orphelins[$t['id_document']] = true;
502
503 return array_keys(array_filter($orphelins));
504 }
505
506 // Supprimer les documents de la table spip_documents,
507 // ainsi que les fichiers correspondants dans IMG/
508 // Fonction a n'appeler que sur des documents orphelins
509 // http://doc.spip.org/@supprimer_documents
510 function supprimer_documents($liste = array()) {
511 if (!count($liste))
512 return;
513
514 $in = sql_in('id_document', $liste);
515
516 // Supprimer les fichiers locaux et les copies locales
517 // des docs distants
518 $s = sql_select("fichier, distant", "spip_documents", $in);
519 while ($t = sql_fetch($s)) {
520 if ($t['distant'] == 'oui') {
521 include_spip('inc/distant');
522 if ($local = copie_locale($t['fichier'], 'test'))
523 spip_log("efface $local = ".$t['fichier']);
524 supprimer_fichier($local);
525 }
526 else {
527 if (@file_exists($f = get_spip_doc($t['fichier']))) {
528 spip_log("efface $f");
529 supprimer_fichier($f);
530 }
531 }
532 }
533
534 // Supprimer les entrees dans spip_documents et associees
535 sql_delete('spip_documents', $in);
536 // en principe il ne devrait rien y avoir ici si les documents sont bien orphelins
537 sql_delete('spip_documents_liens', $in);
538 }
539
540 ?>