-
cedric@yterium.com a rédigé
Le media d'un document (image, video, audio, file) utilise par convenance dans l'interface ne peut dependre en dur de l'extension du fichier : avec oEmbed, on peut se retrouver a integrer toute sorte de media au format html Du coup on revoit la structure de la base : spip_types_documents porte un champ media_defaut (renommage de l'ancien media) utilise comme valeur par defaut du media si non renseigne quand un document est ajoute spip_documents porte son propre champ media, qui est peuple en fonction de media_defaut, sauf si renseigne lors de l'ajout du document (ie via fonction de description ou pipeline) Revision du code partout ou on referencait media, en dispatchant sur l'un ou l'autre selon les cas upgrade de la base (en deux fois)
cedric@yterium.com a rédigéLe media d'un document (image, video, audio, file) utilise par convenance dans l'interface ne peut dependre en dur de l'extension du fichier : avec oEmbed, on peut se retrouver a integrer toute sorte de media au format html Du coup on revoit la structure de la base : spip_types_documents porte un champ media_defaut (renommage de l'ancien media) utilise comme valeur par defaut du media si non renseigne quand un document est ajoute spip_documents porte son propre champ media, qui est peuple en fonction de media_defaut, sauf si renseigne lors de l'ajout du document (ie via fonction de description ou pipeline) Revision du code partout ou on referencait media, en dispatchant sur l'un ou l'autre selon les cas upgrade de la base (en deux fois)
ajouter_documents.php 12,81 Kio
<?php
/***************************************************************************\
* SPIP, Systeme de publication pour l'internet *
* *
* Copyright (c) 2001-2011 *
* 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://doc.spip.org/@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 :
* strin 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
*/
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("erreur_upload_type_interdit",array('nom'=>$file['name']));
$champs['inclus'] = $fichier['inclus'];
$champs['extension'] = $fichier['extension'];
$champs['fichier'] = $fichier['fichier'];
$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
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 '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(",\.([^.]+)$,", $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']);
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/charset');
$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);
return $row;
}
}
else
return $row; // retourner le message d'erreur
}
/**
* Verifier si le fichier respecte les contraintes de tailles
*
* @param $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;
}
?>