PageRenderTime 56ms CodeModel.GetById 24ms RepoModel.GetById 1ms app.codeStats 0ms

/spip/ecrire/inc/ajouter_documents.php

https://github.com/eyeswebcrea/espace-couture-sittler.fr
PHP | 554 lines | 387 code | 67 blank | 100 comment | 76 complexity | 2c4cbf80a432316f615a6b0f9327fc82 MD5 | raw file
Possible License(s): LGPL-2.1, GPL-3.0
  1. <?php
  2. /***************************************************************************\
  3. * SPIP, Systeme de publication pour l'internet *
  4. * *
  5. * Copyright (c) 2001-2011 *
  6. * Arnaud Martin, Antoine Pitrou, Philippe Riviere, Emmanuel Saint-James *
  7. * *
  8. * Ce programme est un logiciel libre distribue sous licence GNU/GPL. *
  9. * Pour plus de details voir le fichier COPYING.txt ou l'aide en ligne. *
  10. \***************************************************************************/
  11. if (!defined('_ECRIRE_INC_VERSION')) return;
  12. include_spip('inc/getdocument');
  13. include_spip('inc/documents');
  14. // Joindre un document ou un Zip a deballer (fonction pour action/joindre)
  15. // Distinguer les deux cas pour commencer
  16. // http://doc.spip.org/@inc_ajouter_documents_dist
  17. function inc_ajouter_documents_dist ($sources, $file, $type, $id, $mode, $id_document, &$actifs, $hout='', $redirect='', $iframe_redirect='')
  18. {
  19. if (is_array($sources))
  20. return liste_archive_jointe($sources, $file, $type, $id, $mode, $id_document, $hout, $redirect, $iframe_redirect);
  21. else
  22. return ajouter_un_document($sources, $file, $type, $id, $mode, $id_document, $actifs, $hout);
  23. }
  24. /**
  25. * Choisir le mode du document : image/document
  26. * fonction surchargeable
  27. *
  28. * @param unknown_type $fichier
  29. * @param unknown_type $type_image
  30. * @param unknown_type $largeur
  31. * @param unknown_type $hauteur
  32. */
  33. function inc_choisir_mode_document_dist($fichier, $type_lien, $type_image, $largeur, $hauteur){
  34. // si ce n'est pas une image, c'est forcement un document
  35. if (!in_array($type_image, array('gif', 'png', 'jpg')))
  36. return 'document';
  37. // si on a pas le droit d'ajouter de document a l'objet, c'est donc un mode image
  38. if ($type_lien AND isset($GLOBALS['meta']["documents_$type_lien"]) AND ($GLOBALS['meta']["documents_$type_lien"]=='non'))
  39. return 'image';
  40. // _INTERFACE_DOCUMENTS
  41. // en fonction de la taille de l'image
  42. // par defaut l'affectation en fonction de la largeur de l'image
  43. // est desactivee car pas comprehensible par le novice
  44. // il suffit de faire dans mes_options
  45. // define('_LARGEUR_MODE_IMAGE', 450);
  46. // pour beneficier de cette detection auto
  47. if (!defined('_LARGEUR_MODE_IMAGE')) define('_LARGEUR_MODE_IMAGE', 0);
  48. if (!_LARGEUR_MODE_IMAGE)
  49. return 'image';
  50. if ($largeur > 0
  51. AND $largeur < _LARGEUR_MODE_IMAGE)
  52. return 'image';
  53. else
  54. return 'document';
  55. }
  56. //
  57. // Ajouter un document (au format $_FILES)
  58. //
  59. # $source, # le fichier sur le serveur (/var/tmp/xyz34)
  60. # $nom_envoye, # son nom chez le client (portequoi.pdf)
  61. # $type_lien, # lie a un article, une breve ou une rubrique ?
  62. # $id_lien, # identifiant de l'article (ou rubrique) lie
  63. # $mode, # 'image' => image en mode image
  64. # # 'vignette' => personnalisee liee a un document
  65. # 'document' => doc ou image en mode document
  66. # 'distant' => lien internet
  67. # $id_document, # pour une vignette, l'id_document de maman
  68. # $actifs # les documents dont il faudra ouvrir la boite de dialogue
  69. // http://doc.spip.org/@ajouter_un_document
  70. function ajouter_un_document($source, $nom_envoye, $type_lien, $id_lien, $mode, $id_document, &$documents_actifs, $titrer=false) {
  71. include_spip('inc/modifier');
  72. // Documents distants : pas trop de verifications bloquantes, mais un test
  73. // via une requete HEAD pour savoir si la ressource existe (non 404), si le
  74. // content-type est connu, et si possible recuperer la taille, voire plus.
  75. if ($mode == 'distant') {
  76. include_spip('inc/distant');
  77. if ($a = recuperer_infos_distantes($source)) {
  78. # NB: dans les bonnes conditions (fichier autorise et pas trop gros)
  79. # $a['fichier'] est une copie locale du fichier
  80. $type_image = $a['type_image'];
  81. unset($a['type_image']);
  82. unset($a['body']);
  83. $a['date'] = date('Y-m-d H:i:s');
  84. $a['distant'] = 'oui';
  85. $a['mode'] = 'document';
  86. $a['fichier'] = set_spip_doc($source);
  87. }
  88. else {
  89. spip_log("Echec du lien vers le document $source, abandon");
  90. return;
  91. }
  92. } else { // pas distant
  93. $type_image = ''; // au pire
  94. // tester le type de document :
  95. // - interdit a l'upload ?
  96. // - quelle extension dans spip_types_documents ?
  97. // - est-ce "inclus" comme une image ?
  98. preg_match(",^(.*)\.([^.]+)$,", $nom_envoye, $match);
  99. @list(,$titre,$ext) = $match;
  100. // securite : pas de . en dehors de celui separant l'extension
  101. // sinon il est possible d'injecter du php dans un toto.php.txt
  102. $nom_envoye = str_replace('.','-',$titre).'.'.$ext;
  103. if ($titrer) {
  104. $titre = preg_replace(',[[:punct:][:space:]]+,u', ' ', $titre);
  105. } else $titre = '';
  106. $ext = corriger_extension(strtolower($ext));
  107. $row = sql_fetsel("inclus", "spip_types_documents", "extension=" . sql_quote($ext) . " AND upload='oui'");
  108. if ($row) {
  109. $type_inclus_image = ($row['inclus'] == 'image');
  110. $fichier = copier_document($ext, $nom_envoye, $source);
  111. } else {
  112. /* STOCKER LES DOCUMENTS INCONNUS AU FORMAT .ZIP */
  113. $type_inclus_image = false;
  114. if (!sql_countsel("spip_types_documents", "extension='zip' AND upload='oui'")) {
  115. spip_log("Extension $ext interdite a l'upload");
  116. return;
  117. }
  118. $ext = 'zip';
  119. if (!$tmp_dir = tempnam(_DIR_TMP, 'tmp_upload')) return;
  120. spip_unlink($tmp_dir); @mkdir($tmp_dir);
  121. $tmp = $tmp_dir.'/'.translitteration($nom_envoye);
  122. $nom_envoye .= '.zip'; # conserver l'extension dans le nom de fichier, par exemple toto.js => toto.js.zip
  123. deplacer_fichier_upload($source, $tmp);
  124. include_spip('inc/pclzip');
  125. $source = _DIR_TMP . 'archive.zip';
  126. $archive = new PclZip($source);
  127. $v_list = $archive->create($tmp,
  128. PCLZIP_OPT_REMOVE_PATH, $tmp_dir,
  129. PCLZIP_OPT_ADD_PATH, '');
  130. effacer_repertoire_temporaire($tmp_dir);
  131. if (!$v_list) {
  132. spip_log("Echec creation du zip ");
  133. return;
  134. }
  135. $fichier = copier_document($ext, $nom_envoye, $source);
  136. spip_unlink($source);
  137. }
  138. // Prevoir traitement specifique pour videos
  139. // (http://www.getid3.org/ peut-etre
  140. if ($ext == "mov") {
  141. $largeur = 0;
  142. $hauteur = 0;
  143. } else if ($ext == "svg") {
  144. // recuperer les dimensions et supprimer les scripts
  145. list($largeur,$hauteur)= traite_svg($fichier);
  146. } else { // image ?
  147. // Si c'est une image, recuperer sa taille et son type (detecte aussi swf)
  148. $size_image = @getimagesize($fichier);
  149. $largeur = intval($size_image[0]);
  150. $hauteur = intval($size_image[1]);
  151. $type_image = decoder_type_image($size_image[2]);
  152. }
  153. // Quelques infos sur le fichier
  154. if (!$fichier OR !@file_exists($fichier)
  155. OR !$taille = @intval(filesize($fichier))) {
  156. spip_log ("Echec copie du fichier $fichier");
  157. return;
  158. }
  159. // _INTERFACE_DOCUMENTS
  160. // Si mode == 'choix', fixer le mode image/document
  161. if ($mode == 'choix') {
  162. $choisir_mode_document = charger_fonction('choisir_mode_document','inc');
  163. $mode = $choisir_mode_document($fichier, $type_lien, $type_image, $largeur, $hauteur);
  164. }
  165. if (!$type_image) {
  166. if (_DOC_MAX_SIZE > 0
  167. AND $taille > _DOC_MAX_SIZE*1024) {
  168. spip_unlink ($fichier);
  169. check_upload_error(6,
  170. _T('info_logo_max_poids',
  171. array('maxi' => taille_en_octets(_DOC_MAX_SIZE*1024),
  172. 'actuel' => taille_en_octets($taille))));
  173. }
  174. if ($mode == 'image') {
  175. spip_log ("le format de $fichier ne convient pas pour une image");
  176. spip_unlink($fichier);
  177. return;
  178. }
  179. }
  180. else { // image
  181. if (_IMG_MAX_SIZE > 0
  182. AND $taille > _IMG_MAX_SIZE*1024) {
  183. spip_unlink ($fichier);
  184. check_upload_error(6,
  185. _T('info_logo_max_poids',
  186. array('maxi' => taille_en_octets(_IMG_MAX_SIZE*1024),
  187. 'actuel' => taille_en_octets($taille))));
  188. }
  189. if (_IMG_MAX_WIDTH * _IMG_MAX_HEIGHT
  190. AND ($size_image[0] > _IMG_MAX_WIDTH
  191. OR $size_image[1] > _IMG_MAX_HEIGHT)) {
  192. spip_unlink ($fichier);
  193. check_upload_error(6,
  194. _T('info_logo_max_taille',
  195. array(
  196. 'maxi' =>
  197. _T('info_largeur_vignette',
  198. array('largeur_vignette' => _IMG_MAX_WIDTH,
  199. 'hauteur_vignette' => _IMG_MAX_HEIGHT)),
  200. 'actuel' =>
  201. _T('info_largeur_vignette',
  202. array('largeur_vignette' => $size_image[0],
  203. 'hauteur_vignette' => $size_image[1]))
  204. )));
  205. }
  206. }
  207. // Si on veut uploader une vignette, il faut qu'elle ait ete bien lue
  208. if ($mode == 'vignette') {
  209. if (!$type_inclus_image) {
  210. spip_log ("le format de $fichier ne convient pas pour une image"); # SVG
  211. spip_unlink($fichier);
  212. return;
  213. }
  214. if (!($largeur OR $hauteur)) {
  215. spip_log('erreur upload vignette '.$fichier);
  216. spip_unlink($fichier);
  217. return;
  218. }
  219. } elseif (!in_array($mode, array('distant', 'image', 'document'))) {
  220. if ($type_image AND $type_inclus_image)
  221. $mode = 'image';
  222. else
  223. $mode = 'document';
  224. }
  225. $a = array(
  226. 'date' => date('Y-m-d H:i:s'),
  227. 'distant' => 'non',
  228. 'mode' => $mode,
  229. 'titre'=> $titre,
  230. 'largeur' => $largeur,
  231. 'hauteur' => $hauteur,
  232. 'taille' => $taille,
  233. 'extension'=> $ext,
  234. 'fichier' => set_spip_doc($fichier));
  235. }
  236. if (($id_document=intval($id_document)) AND $mode!='vignette') {
  237. // Mise a jour des descripteurs d'un vieux doc
  238. unset($a['titre']);
  239. unset($a['date']);
  240. unset($a['distant']);
  241. unset($a['mode']);
  242. sql_updateq('spip_documents', $a, "id_document=$id_document");
  243. $id = $id_document;
  244. } else {
  245. // Installer le document dans la base
  246. // attention piege semantique : les images s'installent en mode 'vignette'
  247. // note : la fonction peut "mettre a jour un document" si on lui
  248. // passe "mode=document" et "id_document=.." (pas utilise)
  249. // Envoyer aux plugins
  250. $a = pipeline('pre_insertion',
  251. array(
  252. 'args' => array(
  253. 'table' => 'spip_documents',
  254. ),
  255. 'data' => $a
  256. )
  257. );
  258. $id = sql_insertq("spip_documents", $a);
  259. pipeline('post_insertion',
  260. array(
  261. 'args' => array(
  262. 'table' => 'spip_documents',
  263. 'id_objet' => $id_document
  264. ),
  265. 'data' => $a
  266. )
  267. );
  268. spip_log ("ajout du document $source $nom_envoye (M '$mode' T '$type_lien' L '$id_lien' D '$id')");
  269. if ($id_lien AND $id
  270. AND preg_match('/^[a-z0-9_]+$/i', $type_lien) # securite
  271. ) {
  272. sql_insertq('spip_documents_liens',
  273. array('id_document' => $id,
  274. 'id_objet' => $id_lien,
  275. 'objet' => $type_lien));
  276. } else spip_log("Pb d'insertion $id_lien $type_lien");
  277. if ($id_document) {
  278. sql_updateq("spip_documents", array("id_vignette" => $id, "mode" => 'document'), "id_document=$id_document");
  279. } else $id_document = $id;
  280. // Appliquer l'exif orientation
  281. // http://trac.rezo.net/trac/spip/ticket/1494
  282. define('_TOURNER_SELON_EXIF', false); # par defaut non, risque memoire
  283. if (defined('_TOURNER_SELON_EXIF')
  284. AND _TOURNER_SELON_EXIF
  285. AND $mode == 'document'
  286. AND $a['distant'] == 'non'
  287. AND $a['extension'] == 'jpg') {
  288. include_spip('action/tourner');
  289. tourner_selon_exif_orientation($id_document, $fichier);
  290. }
  291. }
  292. // pour que le retour vers ecrire/ active le bon doc.
  293. $documents_actifs[$fichier] = $id_document;
  294. // Notifications, gestion des revisions, reindexation...
  295. pipeline('post_edition',
  296. array(
  297. 'args' => array(
  298. 'operation' => 'ajouter_document',
  299. 'table' => 'spip_documents',
  300. 'id_objet' => $id,
  301. 'type_image' => $type_image
  302. ),
  303. 'data' => null
  304. )
  305. );
  306. return $id ;
  307. }
  308. // http://doc.spip.org/@verifier_compactes
  309. function verifier_compactes($zip) {
  310. if (!$list = $zip->listContent()) return array();
  311. // si pas possible de decompacter: installer comme fichier zip joint
  312. // Verifier si le contenu peut etre uploade (verif extension)
  313. $aff_fichiers = array();
  314. foreach ($list as $file) {
  315. if (accepte_fichier_upload($f = $file['stored_filename']))
  316. $aff_fichiers[$f] = $file;
  317. else spip_log("chargement de $f interdit");
  318. }
  319. ksort($aff_fichiers);
  320. return $aff_fichiers;
  321. }
  322. //
  323. // Convertit le type numerique retourne par getimagesize() en extension fichier
  324. //
  325. // http://doc.spip.org/@decoder_type_image
  326. function decoder_type_image($type, $strict = false) {
  327. switch ($type) {
  328. case 1:
  329. return "gif";
  330. case 2:
  331. return "jpg";
  332. case 3:
  333. return "png";
  334. case 4:
  335. return $strict ? "" : "swf";
  336. case 5:
  337. return "psd";
  338. case 6:
  339. return "bmp";
  340. case 7:
  341. case 8:
  342. return "tif";
  343. default:
  344. return "";
  345. }
  346. }
  347. // http://doc.spip.org/@traite_svg
  348. function traite_svg($file)
  349. {
  350. $texte = spip_file_get_contents($file);
  351. // Securite si pas admin : virer les scripts et les references externes
  352. // sauf si on est en mode javascript 'ok' (1), cf. inc_version
  353. if ($GLOBALS['filtrer_javascript'] < 1
  354. AND !autoriser('televerser','script')) {
  355. include_spip('inc/texte');
  356. $new = trim(safehtml($texte));
  357. // petit bug safehtml
  358. if (substr($new,0,2) == ']>') $new = ltrim(substr($new,2));
  359. if ($new != $texte) ecrire_fichier($file, $texte = $new);
  360. }
  361. $width = $height = 150;
  362. if (preg_match(',<svg[^>]+>,', $texte, $s)) {
  363. $s = $s[0];
  364. if (preg_match(',\WviewBox\s*=\s*.\s*(\d+)\s+(\d+)\s+(\d+)\s+(\d+),i', $s, $r)){
  365. $width = $r[3];
  366. $height = $r[4];
  367. } else {
  368. // si la taille est en centimetre, estimer le pixel a 1/64 de cm
  369. if (preg_match(',\Wwidth\s*=\s*.(\d+)([^"\']*),i', $s, $r)){
  370. if ($r[2] != '%') {
  371. $width = $r[1];
  372. if ($r[2] == 'cm') $width <<=6;
  373. }
  374. }
  375. if (preg_match(',\Wheight\s*=\s*.(\d+)([^"\']*),i', $s, $r)){
  376. if ($r[2] != '%') {
  377. $height = $r[1];
  378. if ($r[2] == 'cm') $height <<=6;
  379. }
  380. }
  381. }
  382. }
  383. return array($width, $height);
  384. }
  385. //
  386. // Corrige l'extension du fichier dans quelques cas particuliers
  387. // (a passer dans ecrire/base/typedoc)
  388. // A noter : une extension 'pdf ' passe dans la requete de controle
  389. // mysql> SELECT * FROM spip_types_documents WHERE extension="pdf ";
  390. // http://doc.spip.org/@corriger_extension
  391. function corriger_extension($ext) {
  392. $ext = preg_replace(',[^a-z0-9],i', '', $ext);
  393. switch ($ext) {
  394. case 'htm':
  395. return 'html';
  396. case 'jpeg':
  397. return 'jpg';
  398. case 'tiff':
  399. return 'tif';
  400. case 'mpeg':
  401. return 'mpg';
  402. default:
  403. return $ext;
  404. }
  405. }
  406. // Cherche dans la base le type-mime du tableau representant le document
  407. // et corrige le nom du fichier ; retourne array(extension, nom corrige)
  408. // s'il ne trouve pas, retourne '' et le nom inchange
  409. // http://doc.spip.org/@fixer_extension_document
  410. function fixer_extension_document($doc) {
  411. $extension = '';
  412. $name = $doc['name'];
  413. if (preg_match(',[.]([^.]+)$,', $name, $r)
  414. AND $t = sql_fetsel("extension", "spip_types_documents",
  415. "extension=" . sql_quote(corriger_extension($r[1])))) {
  416. $extension = $t['extension'];
  417. $name = preg_replace(',[.][^.]*$,', '', $doc['name']).'.'.$extension;
  418. }
  419. else if ($t = sql_fetsel("extension", "spip_types_documents",
  420. "mime_type=" . sql_quote($doc['type']))) {
  421. $extension = $t['extension'];
  422. $name = preg_replace(',[.][^.]*$,', '', $doc['name']).'.'.$extension;
  423. }
  424. return array($extension,$name);
  425. }
  426. // Afficher un formulaire de choix: decompacter et/ou garder tel quel
  427. // et reconstruire un generer_action_auteur.
  428. // Passer ca en squelette un de ces jours.
  429. // http://doc.spip.org/@liste_archive_jointe
  430. function liste_archive_jointe($valables, $zip, $type, $id, $mode, $id_document, $hash, $redirect, $iframe_redirect)
  431. {
  432. include_spip('inc/layer');
  433. $arg = (intval($id) .'/' .intval($id_document) . "/$mode/$type");
  434. $texte = "<div style='text-align: left'>
  435. <input type='hidden' name='redirect' value='$redirect' />
  436. <input type='hidden' name='iframe_redirect' value='$iframe_redirect' />
  437. <input type='hidden' name='hash' value='$hash' />
  438. <input type='hidden' name='chemin' value='$zip' />
  439. <input type='hidden' name='arg' value='$arg' />
  440. <input type='radio' checked='checked' name='sousaction5' id='sousaction5_5' value='5' onchange='jQuery(\"#options_deballe_zip\").slideUp();' />" .
  441. "<label for='sousaction5_5'>" . _T('upload_zip_telquel'). "</label>" .
  442. "<br />".
  443. "<input type='radio' name='sousaction5' id='sousaction5_6' value='6' onchange='jQuery(\"#options_deballe_zip\").slideDown();' />".
  444. "<label for='sousaction5_6'>" . _T('upload_zip_decompacter') . "</label>" .
  445. "<ol>" .
  446. liste_archive_taille($valables) .
  447. "</ol>"
  448. . debut_block_depliable(false,'options_deballe_zip')
  449. . "<input type='checkbox' name='sousaction4' id='sousaction4_4' value='4' />".
  450. "<label for='sousaction4_4'>" . _T('upload_zip_conserver') . "</label>" .
  451. "<br /><input type='checkbox' name='titrer' id='titrer' />"
  452. . "<label for='titrer'>" . _T('upload_zip_titrer') .
  453. "</label>".
  454. "</div></div>"
  455. . fin_block()
  456. . "<div style='text-align: right;'><input type='submit' value='".
  457. _T('bouton_valider').
  458. "' />";
  459. $texte = "<p>" .
  460. _T('upload_fichier_zip_texte') .
  461. "</p><p>" .
  462. _T('upload_fichier_zip_texte2') .
  463. "</p>" .
  464. generer_form_action('joindre', $texte,' method="post"');
  465. if(_request("iframe")=="iframe") {
  466. return "<p>build form $iframe_redirect</p>" .
  467. "<div class='upload_answer upload_zip_list'>" .
  468. $texte .
  469. "</div>";
  470. } else { return minipres(_T('upload_fichier_zip'), $texte); }
  471. }
  472. // http://doc.spip.org/@liste_archive_taille
  473. function liste_archive_taille($files) {
  474. $res = '';
  475. foreach ($files as $nom => $file) {
  476. $date = date_interface(date("Y-m-d H:i:s", $file['mtime']));
  477. $taille = taille_en_octets($file['size']);
  478. $res .= "<li title=\"".texte_backend($title)."\"><b>$nom</b> &ndash; $taille<br />&nbsp; $date</li>\n";
  479. }
  480. return $res;
  481. }
  482. ?>