PageRenderTime 27ms CodeModel.GetById 27ms RepoModel.GetById 0ms app.codeStats 1ms

/_core_/tags/spip-3.0.5/plugins/medias/action/ajouter_documents.php

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