123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433 |
- <?php
- /***************************************************************************\
- * SPIP, Systeme de publication pour l'internet *
- * *
- * Copyright (c) 2001-2014 *
- * Arnaud Martin, Antoine Pitrou, Philippe Riviere, Emmanuel Saint-James *
- * *
- * Ce programme est un logiciel libre distribue sous licence GNU/GPL. *
- * Pour plus de details voir le fichier COPYING.txt ou l'aide en ligne. *
- \***************************************************************************/
- if (!defined("_ECRIRE_INC_VERSION")) return;
- include_spip('inc/getdocument');
- include_spip('inc/documents');
- include_spip('inc/choisir_mode_document'); // compat core
- include_spip('inc/renseigner_document');
- /**
- * Ajouter des documents
- *
- * @param int $id_document
- * document a remplacer, ou pour une vignette, l'id_document de maman
- * 0 ou 'new' pour une insertion
- * @param $files
- * tableau de taleau de propriete pour chaque document a inserer
- * @param $objet
- * objet auquel associer le document
- * @param $id_objet
- * id_objet
- * @param $mode
- * mode par defaut si pas precise pour le document
- * @return array
- * liste des id_documents inseres
- */
- function action_ajouter_documents_dist($id_document, $files, $objet, $id_objet, $mode){
- $ajouter_un_document = charger_fonction('ajouter_un_document','action');
- $ajoutes = array();
- // on ne peut mettre qu'un seul document a la place d'un autre ou en vignette d'un autre
- if (intval($id_document)){
- $ajoutes[] = $ajouter_un_document($id_document, reset($files), $objet, $id_objet, $mode);
- }
- else
- foreach($files as $file){
- $ajoutes[] = $ajouter_un_document('new', $file, $objet, $id_objet, $mode);
- }
- return $ajoutes;
- }
- /**
- * Ajouter un document (au format $_FILES)
- *
- * http://code.spip.net/@ajouter_un_document
- *
- * @param int $id_document
- * document a remplacer, ou pour une vignette, l'id_document de maman
- * 0 ou 'new' pour une insertion
- * @param array $file
- * proprietes au format $_FILE etendu :
- * string tmp_name : source sur le serveur
- * string name : nom du fichier envoye
- * bool titrer : donner ou non un titre a partir du nom du fichier
- * bool distant : pour utiliser une source distante sur internet
- * string mode : vignette|image|documents|choix
- * @param string $objet
- * objet auquel associer le document
- * @param int $id_objet
- * id_objet
- * @param string $mode
- * mode par defaut si pas precise pour le document
- * @return array|bool|int|mixed|string|unknown
- * si int : l'id_document ajouté (opération réussie)
- * si string : une erreur s'est produit, la chaine est le message d'erreur
- *
- */
- function action_ajouter_un_document_dist($id_document, $file, $objet, $id_objet, $mode) {
- $source = $file['tmp_name'];
- $nom_envoye = $file['name'];
- // passer en minuscules le nom du fichier, pour eviter les collisions
- // si le file system fait la difference entre les deux il ne detectera
- // pas que Toto.pdf et toto.pdf
- // et on aura une collision en cas de changement de file system
- $file['name'] = strtolower(translitteration($file['name']));
-
- // Pouvoir definir dans mes_options.php que l'on veut titrer tous les documents par d?faut
- if (!defined('_TITRER_DOCUMENTS')) { define('_TITRER_DOCUMENTS', false); }
- $titrer = isset($file['titrer'])?$file['titrer']:_TITRER_DOCUMENTS;
- $mode = ((isset($file['mode']) AND $file['mode'])?$file['mode']:$mode);
- include_spip('inc/modifier');
- if (isset($file['distant']) AND $file['distant'] AND !in_array($mode,array('choix','auto','image','document'))) {
- include_spip('inc/distant');
- $file['tmp_name'] = _DIR_RACINE . copie_locale($source);
- $source = $file['tmp_name'];
- unset($file['distant']);
- }
- // Documents distants : pas trop de verifications bloquantes, mais un test
- // via une requete HEAD pour savoir si la ressource existe (non 404), si le
- // content-type est connu, et si possible recuperer la taille, voire plus.
- if (isset($file['distant']) AND $file['distant']) {
- include_spip('inc/distant');
- if (is_array($a = renseigner_source_distante($source))) {
- $champs = $a;
- # NB: dans les bonnes conditions (fichier autorise et pas trop gros)
- # $a['fichier'] est une copie locale du fichier
- unset($champs['type_image']);
- }
- // on ne doit plus arriver ici, car l'url distante a ete verifiee a la saisie !
- else {
- spip_log("Echec du lien vers le document $source, abandon");
- return $a; // message d'erreur
- }
- }
- else { // pas distant
- $champs = array(
- 'distant' => 'non'
- );
-
- $type_image = ''; // au pire
- $champs['titre'] = '';
- if ($titrer){
- $titre = substr($nom_envoye,0, strrpos($nom_envoye, ".")); // Enlever l'extension du nom du fichier
- $titre = preg_replace(',[[:punct:][:space:]]+,u', ' ', $titre);
- $champs['titre'] = preg_replace(',\.([^.]+)$,', '', $titre);
- }
- if (!is_array($fichier = fixer_fichier_upload($file, $mode)))
- return is_string($fichier)?$fichier:_T("medias:erreur_upload_type_interdit",array('nom'=>$file['name']));
-
- $champs['inclus'] = $fichier['inclus'];
- $champs['extension'] = $fichier['extension'];
- $champs['fichier'] = $fichier['fichier'];
- /**
- * Récupère les informations du fichier
- * -* largeur
- * -* hauteur
- * -* type_image
- * -* taille
- * -* ses metadonnées si une fonction de metadatas/ est présente
- */
- $infos = renseigner_taille_dimension_image($champs['fichier'],$champs['extension']);
- if (is_string($infos))
- return $infos; // c'est un message d'erreur !
-
- $champs = array_merge($champs,$infos);
- // Si mode == 'choix', fixer le mode image/document
- if (in_array($mode,array('choix','auto'))) {
- $choisir_mode_document = charger_fonction('choisir_mode_document','inc');
- $mode = $choisir_mode_document($champs, $champs['inclus'] == 'image', $objet);
- }
- $champs['mode'] = $mode;
- if (($test = verifier_taille_document_acceptable($champs))!==true){
- spip_unlink($champs['fichier']);
- return $test; // erreur sur les dimensions du fichier
- }
- unset($champs['type_image']);
- unset($champs['inclus']);
- $champs['fichier'] = set_spip_doc($champs['fichier']);
- }
- // si le media est pas renseigne, le faire, en fonction de l'extension
- if (!isset($champs['media'])){
- $champs['media'] = sql_getfetsel('media_defaut','spip_types_documents','extension='.sql_quote($champs['extension']));
- }
-
- // lier le parent si necessaire
- if ($id_objet=intval($id_objet) AND $objet)
- $champs['parents'][] = "$objet|$id_objet";
- // "mettre a jour un document" si on lui
- // passe un id_document
- if ($id_document=intval($id_document)){
- unset($champs['titre']); // garder le titre d'origine
- unset($champs['date']); // garder la date d'origine
- unset($champs['descriptif']); // garder la desc d'origine
- // unset($a['distant']); # on peut remplacer un doc statique par un doc distant
- // unset($a['mode']); # on peut remplacer une image par un document ?
- }
- include_spip('action/editer_document');
- // Installer le document dans la base
- if (!$id_document){
- if ($id_document = document_inserer())
- spip_log ("ajout du document ".$file['tmp_name']." ".$file['name']." (M '$mode' T '$objet' L '$id_objet' D '$id_document')",'medias');
- else
- 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);
- }
- if (!$id_document)
- return _T('medias:erreur_insertion_document_base',array('fichier'=>"<em>".$file['name']."</em>"));
-
- document_modifier($id_document,$champs);
- // permettre aux plugins de faire des modifs a l'ajout initial
- // ex EXIF qui tourne les images si necessaire
- // Ce plugin ferait quand même mieux de se placer dans metadata/jpg.php
- pipeline('post_edition',
- array(
- 'args' => array(
- 'table' => 'spip_documents', // compatibilite
- 'table_objet' => 'documents',
- 'spip_table_objet' => 'spip_documents',
- 'type' =>'document',
- 'id_objet' => $id_document,
- 'champs' => array_keys($champs),
- 'serveur' => '', // serveur par defaut, on ne sait pas faire mieux pour le moment
- 'action' => 'ajouter_document',
- 'operation' => 'ajouter_document', // compat <= v2.0
- ),
- 'data' => $champs
- )
- );
- return $id_document ;
- }
- /**
- * Corrige l'extension du fichier dans quelques cas particuliers
- * (a passer dans ecrire/base/typedoc)
- * A noter : une extension 'pdf ' passe dans la requete de controle
- * mysql> SELECT * FROM spip_types_documents WHERE extension="pdf ";
- *
- * @param string $ext
- * @return string
- */
- function corriger_extension($ext) {
- $ext = preg_replace(',[^a-z0-9],i', '', $ext);
- switch ($ext) {
- case 'htm':
- $ext='html';
- break;
- case 'jpeg':
- $ext='jpg';
- break;
- case 'tiff':
- $ext='tif';
- break;
- case 'aif':
- $ext='aiff';
- break;
- case 'mpeg':
- $ext='mpg';
- break;
- }
- return $ext;
- }
- /**
- * Verifie la possibilite d'uploader une extension
- * renvoie un tableau descriptif si l'extension est acceptee
- * avec un index 'autozip' si il faut zipper
- * false ou message d'erreur si l'extension est refusee
- * Verifie aussi si l'extension est autorisee pour le mode demande
- * si on connait le mode a ce moment la
- *
- */
- function verifier_upload_autorise($source, $mode=''){
- $infos = array('fichier'=>$source);
- $res = false;
- if (preg_match(",\.([a-z0-9]+)(\?.*)?$,i", $source, $match)
- AND $ext = $match[1]){
-
- $ext = corriger_extension(strtolower($ext));
- if ($res = sql_fetsel("extension,inclus,media_defaut as media", "spip_types_documents", "extension=" . sql_quote($ext) . " AND upload='oui'"))
- $infos = array_merge($infos,$res);
- }
- if (!$res){
- if ($res = sql_fetsel("extension,inclus,media_defaut as media", "spip_types_documents", "extension='zip' AND upload='oui'")){
- $infos = array_merge($infos,$res);
- $res['autozip'] = true;
- }
- }
- if ($mode AND $res){
- // verifier en fonction du mode si une fonction est proposee
- if ($verifier_document_mode = charger_fonction("verifier_document_mode_".$mode,"inc",true)){
- $check = $verifier_document_mode($infos); // true ou message d'erreur sous forme de chaine
- if ($check!==true)
- $res = $check;
- }
- }
- if (!$res OR is_string($res)) {
- spip_log("Upload $source interdit ($res)",_LOG_INFO_IMPORTANTE);
- }
- return $res;
- }
- /**
- * tester le type de document :
- * - interdit a l'upload ?
- * - quelle extension dans spip_types_documents ?
- * - est-ce "inclus" comme une image ?
- *
- * le zipper si necessaire
- *
- * @param array $file //format $_FILES
- * @return array
- */
- function fixer_fichier_upload($file, $mode=''){
- if (is_array($row=verifier_upload_autorise($file['name'], $mode))) {
- if (!isset($row['autozip'])){
- $row['fichier'] = copier_document($row['extension'], $file['name'], $file['tmp_name']);
-
- /**
- * On vérifie que le fichier a une taille
- * si non, on le supprime et on affiche une erreur
- */
- if($row['fichier'] && (!$taille = @intval(filesize(get_spip_doc($row['fichier']))))) {
- spip_log ("Echec copie du fichier ".$file['tmp_name']." (taille de fichier indéfinie)");
- spip_unlink(get_spip_doc($row['fichier']));
- return _T('medias:erreur_copie_fichier',array('nom'=> $file['tmp_name']));
- }else
- return $row;
- }
- // creer un zip comme demande
- // pour encapsuler un fichier dont l'extension n'est pas supportee
- else{
-
- unset($row['autozip']);
- $ext = 'zip';
- if (!$tmp_dir = tempnam(_DIR_TMP, 'tmp_upload'))
- return false;
- spip_unlink($tmp_dir);
- @mkdir($tmp_dir);
- include_spip('inc/charsets');
- $tmp = $tmp_dir.'/'.translitteration($file['name']);
- $file['name'] .= '.'.$ext; # conserver l'extension dans le nom de fichier, par exemple toto.js => toto.js.zip
- // deplacer le fichier tmp_name dans le dossier tmp
- deplacer_fichier_upload($file['tmp_name'], $tmp, true);
- include_spip('inc/pclzip');
- $source = _DIR_TMP . basename($tmp_dir) . '.'.$ext;
- $archive = new PclZip($source);
- $v_list = $archive->create($tmp,
- PCLZIP_OPT_REMOVE_PATH, $tmp_dir,
- PCLZIP_OPT_ADD_PATH, '');
- effacer_repertoire_temporaire($tmp_dir);
- if (!$v_list) {
- spip_log("Echec creation du zip ");
- return false;
- }
- $row['fichier'] = copier_document($row['extension'], $file['name'], $source);
- spip_unlink($source);
-
- /**
- * On vérifie que le fichier zip créé a une taille
- * si non, on le supprime et on affiche une erreur
- */
- if($row['fichier'] && (!$taille = @intval(filesize(get_spip_doc($row['fichier']))))) {
- spip_log ("Echec copie du fichier ".$file['tmp_name']." (taille de fichier indéfinie)");
- spip_unlink(get_spip_doc($row['fichier']));
- return _T('medias:erreur_copie_fichier',array('nom'=> $file['tmp_name']));
- }else
- return $row;
- }
- }
- else
- return $row; // retourner le message d'erreur
- }
- /**
- * Verifier si le fichier respecte les contraintes de tailles
- *
- * @param array $infos
- * @return bool|mixed|string
- */
- function verifier_taille_document_acceptable($infos){
-
- // si ce n'est pas une image
- if (!$infos['type_image']) {
- if (_DOC_MAX_SIZE > 0
- AND $infos['taille'] > _DOC_MAX_SIZE*1024)
- return _T('medias:info_doc_max_poids', array('maxi' => taille_en_octets(_DOC_MAX_SIZE*1024), 'actuel' => taille_en_octets($infos['taille'])));
- }
-
- // si c'est une image
- else {
- if (_IMG_MAX_SIZE > 0
- AND $infos['taille'] > _IMG_MAX_SIZE*1024)
- return _T('medias:info_image_max_poids', array('maxi' => taille_en_octets(_IMG_MAX_SIZE*1024), 'actuel' => taille_en_octets($infos['taille'])));
-
- if (_IMG_MAX_WIDTH * _IMG_MAX_HEIGHT
- AND ($infos['largeur'] > _IMG_MAX_WIDTH
- OR $infos['hauteur'] > _IMG_MAX_HEIGHT))
- return _T('medias:info_logo_max_taille',
- array(
- 'maxi' =>
- _T('info_largeur_vignette',
- array('largeur_vignette' => _IMG_MAX_WIDTH,
- 'hauteur_vignette' => _IMG_MAX_HEIGHT)),
- 'actuel' =>
- _T('info_largeur_vignette',
- array('largeur_vignette' => $infos['largeur'],
- 'hauteur_vignette' => $infos['hauteur']))
- ));
- }
- // verifier en fonction du mode si une fonction est proposee
- if ($verifier_document_mode = charger_fonction("verifier_document_mode_".$infos['mode'],"inc",true))
- return $verifier_document_mode($infos);
- return true;
- }
- ?>
|