PageRenderTime 35ms CodeModel.GetById 33ms RepoModel.GetById 0ms app.codeStats 1ms

/class.xfiledef.inc

https://github.com/jcplat/console-seolan
PHP | 1560 lines | 1383 code | 74 blank | 103 comment | 291 complexity | b6c21925187ad431547e037c84508d23 MD5 | raw file
Possible License(s): LGPL-2.0, LGPL-2.1, GPL-3.0, Apache-2.0, BSD-3-Clause
  1. <?php
  2. /// Gestion d'un champ fichier, y compris images et videos
  3. class XFileDef extends XFieldDef {
  4. public $maxlength='';
  5. public $usealt=true;
  6. public $accept='.*';
  7. public $secured=false;
  8. public $crypt=false;
  9. public $sourcemodule=NULL;
  10. public $nocopydup=false;
  11. public $image_crop_ration='';
  12. public $image_geometry='640x480%3E';
  13. public $image_max_geometry=null;
  14. public $video_geometry='320x240%3E';
  15. public $video_bitrate='512';
  16. public $audio_geometry='300x30';
  17. public $audio_bitrate='128';
  18. public $autoplay=false;
  19. public $usemimehtml=false;
  20. public $viewlink=true;
  21. public $gzipped=false;
  22. public $indexable=true;
  23. public $auto_write_meta=false;
  24. static $html5_video_format = array(
  25. 'webm' => array('ffmpeg_opts' => FFMPEG_WEBM_OPTS),
  26. 'ogg' => array('ffmpeg_opts' => FFMPEG_OGG_OPTS),
  27. 'mp4' => array('ffmpeg_opts' => FFMPEG_MP4_OPTS),
  28. );
  29. function __construct($obj=NULL) {
  30. parent::__construct($obj);
  31. $this->thumb_geometry = TZR_THUMB_SIZE.'x'.TZR_THUMB_SIZE;
  32. $this->multivalued=false;
  33. if(empty($this->image_max_geometry) && defined('XFILEDEF_IMAGE_MAX_GEOMETRY')) $this->image_max_geometry=XFILEDEF_IMAGE_MAX_GEOMETRY;
  34. }
  35. /// Retourne l'extention d'un type mime
  36. static function mime2extension($mime) {
  37. $mimeClasse=XMimeTypes::getInstance();
  38. return $mimeClasse->get_extension($mime);
  39. }
  40. /// Retourne vrai si le type mime représente une image
  41. static public function isImage($mime){
  42. $mimeClasse=XMimeTypes::getInstance();
  43. return $mimeClasse->isImage($mime);
  44. }
  45. /// Retourne vrai si le type mime représente une vidéo
  46. static public function isVideo($mime){
  47. $mimeClasse=XMimeTypes::getInstance();
  48. return $mimeClasse->isVideo($mime);
  49. }
  50. /// Retourne vrai si le type mime représente un fichier audio
  51. static public function isAudio($mime){
  52. $mimeClasse = XMimeTypes::getInstance();
  53. return $mimeClasse->isAudio($mime);
  54. }
  55. /**
  56. * Function isEmpty
  57. * @return true si le champ n'est pas remplit
  58. */
  59. public function isEmpty($r) {
  60. if (property_exists($r, 'filename'))
  61. return empty($r->filename) && empty($r->externalUrl);
  62. else return true;
  63. }
  64. static function mkfilename($str, $mime) {
  65. $s=preg_replace('@([^\/0-9a-zA-Z_-]+)@','',$str);
  66. $mimeClasse = XMimeTypes::getInstance();
  67. $ext=$mimeClasse->get_extension($mime);
  68. return $s.'.'.$ext;
  69. }
  70. public function hasExternals() {
  71. return true;
  72. }
  73. /// Retourne le nom du fichier
  74. public function externals($value) {
  75. list($file,$mime,$originalname,$title)=explode(';',$value);
  76. $files=$this->filename($file,false,true);
  77. if(!empty($files)) return array($files);
  78. else return NULL;
  79. }
  80. /// Copie le fichier d'une fiche vers une autre fiche
  81. public function copyExternalsTo($value,$oidsrc,$oiddst,$upd=NULL) {
  82. if(empty($value) || empty($oiddst)) return NULL;
  83. if($value==TZR_UNCHANGED) return $value;
  84. @list($file,$mime,$originalname,$title) = explode(';',$value);
  85. if(strpos($file,'.')) list($lang)=explode('.',$file);
  86. $files=$this->filename($file,false,true);
  87. if(!empty($files) && file_exists($GLOBALS['DATA_DIR'].$files)) {
  88. list($table,$idd) = explode(':',$oiddst);
  89. if(!empty($lang)) $idd=$lang.'.'.$idd;
  90. // 1er appel : creation de l'arbo / 2eme appel : recupereation du nom du fichier
  91. $nfiles=$this->filename($idd,true,false,$upd);
  92. $nfiles=$this->filename($idd,false,false,$upd);
  93. copy($GLOBALS['DATA_DIR'].$files,$GLOBALS['DATA_DIR'].$nfiles);
  94. return $idd.';'.$mime.';'.$originalname.';'.$title;
  95. }else{
  96. return TZR_UNCHANGED;
  97. }
  98. }
  99. function initOptions() {
  100. parent::initOptions();
  101. $this->_options->setOpt(XLabels::getSysLabel('xfielddef','xfileviewlink'), 'viewlink','boolean');
  102. $this->_options->setOpt(XLabels::getSysLabel('xfielddef','usemimehtml'), 'usemimehtml','boolean');
  103. $this->_options->setOpt(XLabels::getSysLabel('xfielddef','maxlength'), 'maxlength', 'text');
  104. $this->_options->setOpt(XLabels::getSysLabel('xfielddef','usealt'), 'usealt', 'boolean');
  105. $this->_options->setOpt(XLabels::getSysLabel('xfielddef','accept'), 'accept', 'text');
  106. $this->_options->setOpt(XLabels::getSysLabel('xfielddef','browsemods'), 'browsemods', 'boolean');
  107. $this->_options->setOpt(XLabels::getSysLabel('xfielddef','sourcemodule'), 'sourcemodule', 'module');
  108. $this->_options->setOpt(XLabels::getSysLabel('xfielddef','secured'), 'secured', 'boolean');
  109. $this->_options->setOpt(XLabels::getSysLabel('xfielddef','crypt'), 'crypt', 'boolean');
  110. $this->_options->setOpt(XLabels::getSysLabel('xfielddef','image_crop_ratio'), 'image_crop_ratio', 'text');
  111. $this->_options->setOpt(XLabels::getSysLabel('xfielddef','image_geometry'), 'image_geometry', 'text');
  112. $this->_options->setOpt(XLabels::getSysLabel('xfielddef','image_max_geometry'), 'image_max_geometry', 'text');
  113. $this->_options->setOpt(XLabels::getSysLabel('xfielddef','video_geometry'), 'video_geometry', 'text');
  114. $this->_options->setOpt(XLabels::getSysLabel('xfielddef','video_bitrate'), 'video_bitrate', 'text');
  115. $this->_options->setOpt(XLabels::getSysLabel('xfielddef','audio_bitrate'), 'audio_bitrate', 'text');
  116. $this->_options->setOpt(XLabels::getSysLabel('xfielddef','autoplay'), 'autoplay', 'boolean');
  117. $this->_options->setOpt(XLabels::getSysLabel('xfielddef','gzipped'), 'gzipped', 'boolean');
  118. $this->_options->setOpt(XLabels::getSysLabel('xfielddef','allow_externalfile'), 'allow_externalfile', 'boolean');
  119. $this->_options->setOpt(XLabels::getSysLabel('xfielddef','xfiledef_autowritemeta'),'auto_write_meta','boolean');
  120. $querygroup=XLabels::getSysLabel('general','query','text');
  121. $this->_options->setOpt(XLabels::getSysLabel('xfielddef.indexable'), 'indexable', 'boolean', NULL, true, $querygroup);
  122. }
  123. // Verification que les repertoires qui contiennent les fichiers n'existent pas, sinon on les cree
  124. function _checkDir() {
  125. global $DATA_DIR;
  126. umask(0000);
  127. $root=$DATA_DIR.$this->table.'/'.$this->field;
  128. if(!is_dir($root)) {
  129. if(!is_dir($DATA_DIR.$this->table)) {
  130. @mkdir($DATA_DIR.$this->table,0777);
  131. }
  132. if(!is_dir($DATA_DIR.$this->table.'/'.$this->field)) {
  133. @mkdir($DATA_DIR.$this->table.'/'.$this->field,0777);
  134. }
  135. }
  136. }
  137. /// Suppression du champ, i.e. suppression du repertoire et des donnees incluses dans ce repertoire
  138. function delfield() {
  139. global $DATA_DIR;
  140. XDir::unlink($DATA_DIR.$this->table.'/'.$this->field);
  141. }
  142. /// Ecriture dans un fichier excel
  143. function writeXLS(&$xl,$i,$j,&$value,$format=0,&$ss=NULL) {
  144. if(!empty($value->url)){
  145. $lab=$value->text;
  146. if(empty($lab)) $lab='Link';
  147. convert_charset($lab,TZR_INTERNAL_CHARSET,'UTF-8');
  148. $xl->setCellValueByColumnAndRow($j,$i,$lab);
  149. $xl->getCellByColumnAndRow($j,$i)->getHyperlink()->setUrl($GLOBALS['HOME_ROOT_URL'].$value->url);
  150. if(is_array($format)) $xl->getStyleByColumnAndRow($j,$i)->applyFromArray($format);
  151. }
  152. }
  153. /// Ecriture dans un csv
  154. function writeCSV(&$o,$textsep){
  155. return $textsep.$o->originalname.$textsep;
  156. }
  157. /// Affiche dans le mode parcourir
  158. function my_browse(&$value,&$options) {
  159. $r=&$this->my_display($value,$options);
  160. if($this->usemimehtml && !empty($options['admin'])) {
  161. $r->html=$r->html_preview;
  162. }
  163. return $r;
  164. }
  165. /// Retourne la taille du fichier
  166. function getFileSize($r){
  167. if(empty($r->filesize)) $r->filesize=filesize($r->filename);
  168. return $r->filesize;
  169. }
  170. /// Affichage du champ
  171. function my_display($value,&$options) {
  172. global $DATA_DIR;
  173. $langdata = XShell::getLangData();
  174. $resizer=TZR_RESIZER;
  175. $r=$this->_newXFieldVal($options, true);
  176. $r->type = NULL;
  177. $r->resizer = NULL;
  178. $r->mime = NULL;
  179. $r->isImage = false;
  180. $r->isVideo = false;
  181. if($value=='' || $value==TZR_UNCHANGED)
  182. return $r;
  183. @list($file,$mime,$originalname,$title) = explode(';',$value);
  184. if (strpos($file, ':') !== false)
  185. return $this->displayExternal($r, $file, $value, $options);
  186. if(empty($originalname)) {
  187. $originalname = 'download';
  188. $mimeClasse = XMimeTypes::getInstance();
  189. $originalname .= '.'.$mimeClasse->get_extension($mime);
  190. }
  191. $files=$this->filename($file,false,false,@$options['_archive']);
  192. if(!$files) return $r;
  193. $filename=$DATA_DIR.$files;
  194. $originalname_corrected=preg_replace('@([^\._a-zA-Z0-9-]+)@','_',$originalname);
  195. $downloader=$this->getDownloader($files, $mime, $originalname_corrected, $title, @$options['fmoid']);
  196. $r->filename=$filename;
  197. $r->shortfilename=$files;
  198. $r->mime=$mime;
  199. $r->title=$title;
  200. $r->originalname=$originalname;
  201. $r->raw=$value;
  202. $r->url=$downloader[0];
  203. $r->text=$r->title?$r->title:$r->originalname;
  204. $r->mimepicto=XLabels::getSysLabel('mime',$mime, 'both', 'mime', 'unknown/unknown');
  205. $r->html_default='<a bt-xpath="'.TZR_AJAX8.'?class=xfiledef&function=xfiledef_getfilesize&file='.$files.'&_='.XShell::uniqid().'" class="tzr-hottip-c tzr-file" href="'.$r->url.'" target="_self">'.$r->mimepicto.(empty($title)?$originalname:$title).'</a>';
  206. $r->html_preview=$r->html_default;
  207. $r->html=$r->html_default;
  208. if(XFileDef::isVideo($mime)) $this->displayVideo($r,$value,$options);
  209. elseif(XFileDef::isImage($mime)) $this->displayImage($r,$value,$options);
  210. elseif($mime=='application/pdf') $this->displayPDF($r,$value,$options);
  211. elseif(XFileDef::isAudio($mime)) $this->displayAudio($r,$value,$options);
  212. return $r;
  213. }
  214. /// Affichage d'un fichier externe
  215. function displayExternal(&$r, $file, $value, $options) {
  216. $r->file = $file;
  217. $r->raw = $value;
  218. list($r->type, $r->id) = explode(':', $file, 2);
  219. $r->isExternal = true;
  220. $displayFunction = 'display'.$r->type;
  221. if (method_exists($this, $displayFunction))
  222. return $this->$displayFunction($r, $options);
  223. $r->externalUrl = $r->id;
  224. return $r;
  225. }
  226. /* Image */
  227. /// Complete l'objet d'affichage dans le cas d'une image
  228. function displayImage(&$r,&$value,$options){
  229. $resizer=$this->getResizer($r->shortfilename,$r->mime,$r->originalname);
  230. if(!empty($resizer) && !empty($resizer['resizer'])) {
  231. $r->resizer=$resizer['resizer'];
  232. $r->weresizer=$resizer['weresizer'];
  233. }
  234. $r->isImage=true;
  235. if($this->usemimehtml){
  236. $r->html = '<img class="tzr-image" src="'.$r->resizer.'&geometry='.$this->image_geometry.'" alt="'.$r->title.'" title="'.$r->title.'">';
  237. if ($this->viewlink) $r->html.='<br>'.$r->html_default;
  238. }
  239. $r->html_preview = '<img class="tzr-image" src="'.$r->resizer.'&geometry='.TZR_THUMB_SIZE.'x'.TZR_THUMB_SIZE.'%3E" alt="'.$r->title.'" title="'.$r->title.'">';
  240. if ($this->viewlink) $r->html_preview.='<br>'.$r->html_default;
  241. }
  242. /// Retourne le code html du preview d'une image
  243. function html_previewImage($r, $options=array()) {
  244. $options = array_merge(array('title' => $r->title, 'geometry' => $this->thumb_geometry), $options);
  245. return $this->htmlImage($r, $options);
  246. }
  247. /// Retourne le code html d'une image
  248. function htmlImage($r, $options=array()) {
  249. $options = array_merge(array('title' => $r->title, 'geometry' => $this->image_geometry), $options);
  250. $geometry = $options['geometry'];
  251. $this->getImageSize($r);
  252. list($w, $h) = explode('x', str_replace('>', '', $geometry));
  253. $w = (integer)$w;
  254. $h = (integer)$h;
  255. $ratio = $r->fullheight / $r->fullwidth;
  256. if (isset($options['gravity'])) { // on peux croper
  257. $geometry = (integer)($ratio * $r->fullwidth).'x'.(integer)($ratio * $r->fullheight);
  258. $crop = '&amp;crop='.$w.'x'.$h.'&amp;gravity='.$options['gravity'];
  259. } else {
  260. if ($w < $r->fullwidth || $h < $r->fullheight) {
  261. if ($ratio < 1)
  262. $h = (integer)($w*$ratio);
  263. else
  264. $w = (integer)($h/$ratio);
  265. } else {
  266. $w = $r->fullwidth;
  267. $h = $r->fullheight;
  268. }
  269. $geometry = $w.'x'.$h;
  270. }
  271. return '<img class="tzr-image" src="'.$r->resizer.'&amp;geometry='.$geometry.@$crop.'" '.(isset($options['title']) ? ' alt="'.@$options['title'].'" title="'.@$options['title'].'"':'').(isset($w)?' width="'.$w.'" height="'.$h.'"':'').'>';
  272. }
  273. /// Retourne le code html
  274. function completeHTML($r, $options=array(), $alt){
  275. if (empty($r) || $r->raw == '')
  276. return '';
  277. if (is_string($options)) { // from template
  278. parse_str($options, $options);
  279. }
  280. if (count($options)==1 && current($options) == '') // compatibilité
  281. $options = array('geometry' => key($options));
  282. if ($r->isExternal) {
  283. $htmlFunction = 'html'.$r->type;
  284. if (method_exists($this, $htmlFunction))
  285. $html = $this->$htmlFunction($r, $options);
  286. }
  287. elseif ($r->isImage || $r->isPDF)
  288. $html = $this->htmlImage($r, $options);
  289. elseif ($r->isVideo)
  290. $html = $this->htmlVideo($r, $options);
  291. elseif ($r->isAudio)
  292. $html = $this->htmlAudio($r, $options, $alt);
  293. else
  294. $html = $r->html_default;
  295. return $html;
  296. }
  297. /// Retourne l'url des reiszer
  298. protected function getResizer($filename,$mime="null/null",$originalname=NULL){
  299. $mimedst=$mime;
  300. if($mime=='image/x-png') $mime=$mimedst='image/png';
  301. if(($mime!='image/gif') && ($mime!='image/png')) $mimedst='image/jpeg';
  302. $mimedst=rawurlencode($mimedst);
  303. $fmime = '';
  304. $mimeClasse=XMimeTypes::getInstance();
  305. if($mime=='application/pdf'){
  306. $fmime=$mime;
  307. }elseif($mimeClasse->isImage($mime)) {
  308. $fmime=$mimedst;
  309. }
  310. if(!empty($fmime)){
  311. $str = '?filename='.$filename.'&amp;mime='.$fmime.'&amp;';
  312. if($originalname) $str .= '&amp;originalname='.rawurlencode($originalname);
  313. $resizer=TZR_RESIZER.$str;
  314. $weresizer=TZR_WERESIZER.$str;
  315. }else{
  316. $resizer=$weresizer='';
  317. }
  318. return array('resizer'=>$resizer,'weresizer'=>$weresizer);
  319. }
  320. /// Retourne la taille en px d'une image
  321. function getImageSize($r,$dim=NULL){
  322. if(!isset($r->fullwidth)){
  323. if($r->isImage) $t=getimagesize($r->filename);
  324. elseif($r->isVideo) $t=getimagesize($r->filename.'-fullsizeimage');
  325. elseif($r->isPDF) {
  326. if (!file_exists($r->filename.'-fullsizeimage'))
  327. exec(TZR_MOGRIFY_RESIZER . ' ' . $r->filename . '[0] jpeg:' . $r->filename . '-fullsizeimage');
  328. $t=getimagesize($r->filename.'-fullsizeimage');
  329. }
  330. else $t=array(0,0);
  331. $r->fullwidth=$t[0];
  332. $r->fullheight=$t[1];
  333. }
  334. if($dim) return $r->$dim;
  335. }
  336. /// Recupere la largeur ou la hauteur finale d'une image en fonction d'une géométrie passée au resizer
  337. function getImageResize($r,$geometry,$dim){
  338. if(empty($r->_cache['size'][$geometry])){
  339. $this->getImageSize($r);
  340. $t=array($r->fullwidth,$r->fullheight);
  341. $oratio=$t[0]/$t[1];
  342. $size=explode('x',$geometry);
  343. if(!is_numeric($size[0])) $size[0]=0;
  344. if(empty($size[1]) || !is_numeric($size[1])) $size[1]=0;
  345. $ratio=$size[0]/$size[1];
  346. if(!empty($size[0]) && ($oratio>$ratio || empty($size[1]))){
  347. $w=$size[0];
  348. $h=round($t[1]*$size[0]/$t[0]);
  349. }else{
  350. $w=round($t[0]*$size[1]/$t[1]);
  351. $h=$size[1];
  352. }
  353. $r->_cache['size'][$geometry]=array('width'=>$w,'height'=>$h);
  354. }
  355. return $r->_cache['size'][$geometry][$dim];
  356. }
  357. /// Retourne une propriété iptc ou l'objet iptc de l'image
  358. function getIPTC($r,$prop=NULL){
  359. if($r->mime=='image/jpeg'){
  360. if(empty($r->meta_data)) $r->meta_data=XFileDef::loadMeta($r->filename);
  361. if(!$prop) return $r->meta_data;
  362. else return $r->meta_data->getIPTCProperty($prop);
  363. }
  364. return NULL;
  365. }
  366. /// Retourne une propriété exif ou l'objet exif de l'image
  367. function getEXIF($r,$prop=NULL){
  368. if($r->mime=='image/jpeg'){
  369. if(empty($r->exif_data)) $r->exif_data=exif_read_data($r->filename);
  370. if(!$prop) return $r->exif_data;
  371. else return $r->exif_data[$prop];
  372. }
  373. return NULL;
  374. }
  375. /// Retourne une propriété XMP ou l'objet XMP de l'image
  376. function getXMP($r,$prop=NULL){
  377. if($r->mime=='image/jpeg'){
  378. if(empty($r->meta_data)) $r->meta_data=XFileDef::loadMeta($r->filename);
  379. if(!$prop) return $r->meta_data;
  380. else return $r->meta_data->getXMPProperty($prop,array('Alt'=>array('lang'=>array(XShell::getLangData(),'x-default'))));
  381. }
  382. return NULL;
  383. }
  384. /// Charge l'objet meta du fichier
  385. static function loadMeta($file){
  386. return new MetaAnalyser($file);
  387. }
  388. /// Redimensione une image
  389. function resizeImage($file,$geo=null){
  390. if(!$geo) return false;
  391. // Verifie si l'image est plus grande qua la taille max ou pas
  392. $s=getimagesize($file);
  393. list($w,$h)=explode('x',$geo);
  394. if(!is_numeric($w)) $w=99999;
  395. if(empty($h) || !is_numeric($h)) $h=99999;
  396. if($s[0]<$w && $s[1]<$h) return false;
  397. // Redimensionne l'image
  398. $geo=rawurldecode($geo);
  399. exec(TZR_MOGRIFY_RESIZER.' -resize "'.$geo.'" '.$file.' '.$file);
  400. return true;
  401. }
  402. /// Applique rotate et flip à un fichier selon son orientation exif
  403. function rotateAndFlip($filename,$mime){
  404. $r=(object)array('filename'=>$filename,'mime'=>$mime);
  405. $o=$this->getExif($r,'Orientation');
  406. if(!empty($o) && $o!=1){
  407. switch ($o){
  408. case 2:
  409. $opt='-flop';
  410. break;
  411. case 3:
  412. $opt='-rotate 180';
  413. break;
  414. case 4:
  415. $opt='-flip';
  416. break;
  417. case 5:
  418. $opt='-flip -rotate "90"';
  419. break;
  420. case 6:
  421. $opt='-rotate "90"';
  422. break;
  423. case 7:
  424. $opt='-flop -rotate "90"';
  425. break;
  426. case 8:
  427. $opt='-rotate "-90"';
  428. break;
  429. }
  430. exec(TZR_MOGRIFY_RESIZER.' '.$opt.' '.$filename.' '.$filename);
  431. }
  432. }
  433. /* Video */
  434. /// Complete l'objet d'affichage dans le cas d'une video
  435. function displayVideo(&$r,&$value,&$options){
  436. $r->isVideo=true;
  437. $r->resizer=TZR_VIDEOCONVERT.'?filename='.$r->shortfilename;
  438. $r->preview=TZR_VIDEOCONVERT.'?preview=true&filename='.$r->shortfilename;
  439. if ($this->usemimehtml) {
  440. $r->html_preview = $this->html_previewVideo($r, $options);
  441. $r->html = $this->htmlVideo($r, $options);
  442. if ($this->viewlink) {
  443. $r->html .= '<br>'.$r->html_default;
  444. $r->html_preview .= '<br>'.$r->html_default;
  445. }
  446. } else
  447. $r->html = $r->html_preview;
  448. }
  449. /// Code html du preview d'une vidéo
  450. function html_previewVideo($r, $options=array()) {
  451. $options = array_merge(array('title' => $r->title, 'geometry' => $this->thumb_geometry), $options);
  452. $geometry = XFileDef::videoGetGeometry($r->filename, $options['geometry']);
  453. list($width, $height) = explode('x', $geometry);
  454. return '<img class="tzr-image" src="'.$r->preview.'&geometry='.$geometry.'" alt="'.$options['title'].'" title="'.$options['title'].'" width="'.$width.'" height="'.$height.'">';
  455. }
  456. /// Code html de l'affichage d'une vidéo
  457. function htmlVideo(&$r, $options=array(1=>1)) {
  458. global $DATA_URL;
  459. $options = array_merge(array('title' => $r->title, 'geometry' => $this->video_geometry, 'video_bitrate' => $this->video_bitrate, 'autoplay' => $this->autoplay, 'fullscreen' => 1), $options);
  460. $geometry = XFileDef::videoGetGeometry($r->filename, $options['geometry']);
  461. list($width, $height) = explode('x', $geometry);
  462. $r->video_bitrate = $options['video_bitrate'];
  463. if ($this->videoReady($r, $geometry, true, $options['video_bitrate'])) {
  464. if (defined('HTML5MEDIA')) {
  465. $html = '
  466. <div class="tzr-video-div">
  467. <video id="'.$r->varid.'" class="tzr-video" '.($options['autoplay'] ? ' autoplay="autoplay"' : '').' width="'.$width.'" height="'.$height.'" controls poster="'.$r->preview.'&geometry='.$geometry.'" preload="none">';
  468. foreach (XFileDef::$html5_video_format as $format => $opts) {
  469. $html .= '
  470. <source src="'.$r->resizer.'&geometry='.$geometry.'&bitrate='.$options['video_bitrate'].'&format='.$format.'&type=.'.$format.'" type="video/'.$format.'"/>';
  471. }
  472. $html .= '
  473. </video>
  474. <script type="text/javascript">
  475. jQuery("#'.$r->varid.'").mediaelementplayer({pluginPath: "'.TZR_SHARE_URL.'js/jmediaelement/"});
  476. </script>
  477. </div>';
  478. } else {
  479. $html = '<div style="width='.$width.'px;height:'.$height.'px"><div id="'.$r->varid.'"></div></div><script type="text/javascript">swfobject.embedSWF("'.TZR_SHARE_URL.'flash/player_flv_maxi.swf","'.$r->varid.'","'.$width.'","'.$height.'","8","",{flv:"'.urlencode($r->resizer.'&geometry='.$geometry.'&bitrate='.$options['video_bitrate']).'",startimage:"'.urlencode($r->preview.'&geometry='.$geometry).'",autoplay:'.($options['autoplay']?'1':'0').',showfullscreen:'.($options['fullscreen']?'1':'0').',margin:0,showstop:1,showvolume:1,showtime:1,ondoubleclick:"fullscreen"},{allowFullScreen:true, wmode:"transparent"});</script>';
  480. }
  481. }
  482. else {
  483. $html = '<img src="'.$r->preview.'&geometry='.$geometry.'" alt="'.$title.'" title="'.$title.'" width="'.$width.'" height="'.$height.'">';
  484. }
  485. return $html;
  486. }
  487. /// Determine si le fichier est directement disponible dans le format.
  488. /// Si 'force' a true et fichier non disponible, lance la tache de conversion.
  489. function videoReady($r,$geometry,$forceConvert=true) {
  490. if(!XFileDef::isVideo($r->mime))
  491. return false;
  492. $geometry=XFileDef::videoGetGeometry($r->filename,$geometry);
  493. $ready = true;
  494. $ffmpeg = '';
  495. if (defined('HTML5MEDIA')) { // html5 video tag
  496. foreach (XFileDef::$html5_video_format as $format => $opts) {
  497. $hash = md5($geometry.$r->video_bitrate.'video/'.$format);
  498. $filename_cache = $r->filename.'-'.$hash.'-cache';
  499. if (!file_exists($filename_cache) || (filemtime($filename)>filemtime($filename_cache))) {
  500. $ready = false;
  501. if ($forceConvert) {
  502. $ffmpeg .= FFMPEG." -y -i {$r->filename} {$opts['ffmpeg_opts']} -vb {$r->video_bitrate}k -s $geometry $filename_cache ;\n";
  503. }
  504. }
  505. }
  506. }
  507. else {
  508. $hash = md5($geometry.$r->video_bitrate.'video/x-flv');
  509. $filename_cache=$r->filename.'-'.$hash.'-cache';
  510. if (!file_exists($filename_cache) || (filemtime($filename)>filemtime($filename_cache))) {
  511. $ready = false;
  512. if ($forceConvert) {
  513. $ffmpeg .= FFMPEG." -y -i {$r->filename} -ab 64k -ar 22050 -f flv -vb {$r->video_bitrate}k -s $geometry $filename_cache ";
  514. }
  515. }
  516. }
  517. if ($ffmpeg) {
  518. $s=new XModScheduler(array('tplentry'=>TZR_RETURN_DATA));
  519. $s->createIdleShellJob(md5($ffmpeg),'Video encoding',$ffmpeg,'');
  520. }
  521. return $ready;
  522. }
  523. /// Affichage d'une video youtube
  524. function displayYoutube(&$r, $value, $options) {
  525. require_once 'Zend/Loader.php'; // the Zend dir must be in your include_path
  526. Zend_Loader::loadClass('Zend_Gdata_YouTube');
  527. $r->videoid = $r->id;
  528. $r->videourl = 'http://www.youtube.com/watch?v='.$r->videoid;
  529. $r->isVideo = true;
  530. $r->videoReady = true;
  531. $r->resizer = '';
  532. $yt = new Zend_Gdata_YouTube();
  533. $yt->setMajorProtocolVersion(2);
  534. try {
  535. $videoEntry = $yt->getVideoEntry($r->videoid);
  536. $r->externalUrl = $videoEntry->getVideoWatchPageUrl();
  537. $r->embedUrl = 'http://www.youtube.com/embed/' . $r->videoid;
  538. $thumbnails = $videoEntry->getVideoThumbnails();
  539. $r->flashplayer = $videoEntry->getFlashPlayerUrl();
  540. $r->preview = $thumbnails[0]; /// TODO: choose best size
  541. $r->title = $videoEntry->getVideoTitle();
  542. $r->text = $r->title;
  543. $r->error = false;
  544. } catch(Zend_Gdata_App_HttpException $e) {
  545. $r->error = true;
  546. XLogs::notice('XFileDef::displayYoutube', "Error : " . $e->getMessage());
  547. }
  548. $r->fullwidth = 1600;
  549. $r->fullheight = 900;
  550. $r->html_preview = $this->html_previewYoutube($r, $options);
  551. if ($this->usemimehtml)
  552. $r->html = $this->htmlYoutube($r, $options);
  553. else
  554. $r->html = $r->html_preview;
  555. return $r;
  556. }
  557. /// html du preview d'une video youtube
  558. function html_previewYoutube($r, $options=array()) {
  559. if ($r->error)
  560. return '';
  561. if (isset($options['geometry']))
  562. list($width, $height) = explode('x', str_replace('>', '', $options['geometry']));
  563. else
  564. $width = $height = TZR_THUMB_SIZE;
  565. $margin = (int) -($width * $r->preview['height']/$r->preview['width'] - $height) /2;
  566. return '<div style="width:'.$width.'px;height:'.$height.'px;overflow:hidden;display:inline"><img src="'.$r->preview['url'].'" alt="'.$r->title.'" width="'.$width.'" class="tzr-externalfile" rel="'.$r->file.'"'.($margin<0?'style="margin-top:'.$margin.'px"':'').'></div>';
  567. }
  568. /// html d'une video youtube
  569. function htmlYoutube($r, $options=array()) {
  570. if ($r->error)
  571. return '';
  572. $options = array_merge(array('autoplay' => $this->autoplay, 'geometry' => $this->video_geometry), $options);
  573. list($width, $height) = explode('x', str_replace('>', '', rawurldecode($options['geometry'])));
  574. return '<iframe id="'.$r->varid.'" width="'.$width.'" height="'.$height.'" style="width:'.$width.'px;height:'.$height.'px" src="'.$r->embedUrl.'?enablejsapi=1&origin='.$GLOBALS['TZR_SESSION_MANAGER']::makeDomainName().'&wmode=transparent'.($options['autoplay']?'&autoplay=1':'').'"></iframe>';
  575. }
  576. /// Affichage d'une video Daily Motion
  577. function displayDailyMotion(&$r, $file, $value, $options) {
  578. $videoid = substr($file, 12);
  579. $r->videoid = $r->id;
  580. $r->videourl = 'http://www.dailymotion.com/video/'.$r->videoid;
  581. $r->isVideo = true;
  582. $r->videoReady = true;
  583. $r->resizer = '';
  584. if (!$videoEntry = file_get_contents('https://api.dailymotion.com/video/'.$r->videoid.'?fields=allow_embed,url,embed_url,thumbnail_medium_url,title')) {
  585. XLogs::notice('XFileDef::displayDailyMotion', "Error : cannot retreive video information ");
  586. $r->error = true;
  587. return $r;
  588. }
  589. $videoEntry = json_decode($videoEntry);
  590. if ($videoEntry->error) {
  591. XLogs::notice('XFileDef::displayDailyMotion', "Error : " . $videoEntry->error->message);
  592. $r->error = true;
  593. return $r;
  594. }
  595. if (!$videoEntry->allow_embed) {
  596. XLogs::notice('XFileDef::displayDailyMotion', "Error : {$r->videoid} embed not allowed");
  597. return $r;
  598. }
  599. $r->preview = array(
  600. 'url' => $videoEntry->thumbnail_medium_url,
  601. 'width' => 160,
  602. 'height' => 120
  603. );
  604. $r->title = $videoEntry->title;
  605. $r->externalUrl = $videoEntry->url;
  606. $r->embedUrl = $videoEntry->embed_url;
  607. $r->html_preview = $this->html_previewDailyMotion($r, $options);
  608. if ($this->usemimehtml)
  609. $r->html = $this->htmlDailyMotion($r, $options);
  610. else
  611. $r->html = $r->html_preview;
  612. return $r;
  613. }
  614. /// html du preview d'une video Daily Motion
  615. function html_previewDailyMotion($r, $options=array()) {
  616. return $this->html_previewYoutube($r, $options=array());
  617. }
  618. /// html d'une video Daily Motion
  619. function htmlDailyMotion($r, $options=array()) {
  620. return $this->htmlYoutube($r, $options=array());
  621. }
  622. /// Gestion de la geometrie d'une video
  623. static function videoGetGeometry($filename,$geometry){
  624. if(strpos($filename,$GLOBALS['DATA_DIR'])===false) $filename=$GLOBALS['DATA_DIR'].$filename;
  625. $geometry=rawurldecode($geometry);
  626. if(substr($geometry,-1)=='>')
  627. $geometry=substr($geometry,0,-1);
  628. $filefullsizeimage=$filename.'-fullsizeimage';
  629. if(!($t=@getimagesize($filefullsizeimage))){
  630. exec(FFMPEG.' -y -i "'.$filename.'" -f image2 -vcodec mjpeg -vframes 1 -an "'.$filefullsizeimage.'"');
  631. $t=@getimagesize($filefullsizeimage);
  632. }
  633. $oratio=$t[0]/$t[1];
  634. $size=explode('x',$geometry);
  635. $ratio=$size[0]/$size[1];
  636. if (!$size[0] || !$size[1])
  637. XLogs::critical('videoGetGeometry geometry imcomplete definition: '.$size[0].'x'.$size[1], '', true);
  638. if($oratio>$ratio){
  639. $w=$size[0];
  640. $h=round($t[1]*$size[0]/$t[0]);
  641. }else{
  642. $w=round($t[0]*$size[1]/$t[1]);
  643. $h=$size[1];
  644. }
  645. if($w%2) $w--;
  646. if($h%2) $h--;
  647. $geometry=$w.'x'.$h;
  648. return $geometry;
  649. }
  650. /* Audio */
  651. /// Complete l'objet d'affichage dans le cas d'un fichier audio
  652. function displayAudio(&$r,&$value,&$options){
  653. global $DATA_URL;
  654. $r->isAudio=true;
  655. $r->audio_bitrate = $this->audio_bitrate;
  656. $r->prehear = TZR_AUDIOCONVERT.'?prehear=true&filename='.$r->shortfilename.'&type=.mp3';
  657. $r->fullaudio = TZR_AUDIOCONVERT.'?filename='.$r->shortfilename.'&type=.mp3';
  658. if (defined('HTML5MEDIA')) {
  659. $r->prehear_ogg = TZR_AUDIOCONVERT.'?mime=audio/ogg&prehear=true&filename='.$r->shortfilename.'&type=.ogg';
  660. $r->fullaudio_ogg = TZR_AUDIOCONVERT.'?mime=audio/ogg&filename='.$r->shortfilename.'&type=.ogg';
  661. }
  662. if ($this->usemimehtml) {
  663. $r->html_preview = $this->html_previewAudio($r, $options);
  664. $r->html = $this->htmlAudio($r, $options);
  665. if ($this->viewlink) {
  666. $r->html .= '<br>'.$r->html_default;
  667. $r->html_preview .= '<br>'.$r->html_default;
  668. }
  669. } else
  670. $r->html = $r->html_preview;
  671. return $r;
  672. }
  673. /// html preview audio, $alt est un media alternatif (image)
  674. function html_previewAudio($r, $options=array(), $alt) {
  675. $options = array_merge(array('title' => $r->title, 'geometry' => $this->thumb_geometry, 'img' => TZR_SHARE_URL.'ico/mime/big-mp3.gif'), $options);
  676. if ($alt && is_object($alt) && $alt->raw)
  677. return $this->html_previewImage($alt, $options);
  678. $html = '<img src="'.$options['img'].'" alt="'.$r->title.'">';
  679. return $html;
  680. }
  681. /// html audio, $alt est un media alternatif (image)
  682. function htmlAudio(&$r, $options=array(), $alt) {
  683. $options = array_merge(array('audio_bitrate' => $this->audio_bitrate, 'audio_geometry' => $this->audio_geometry, 'geometry' => $this->geometry, 'autoplay' => $this->autoplay), $options);
  684. list($width, $height) = explode('x', str_replace('>', '', $options['audio_geometry']));
  685. list($altwidth, $altheight) = explode('x', str_replace('>', '', $options['geometry']));
  686. if ($options['audio_bitrate'] != $this->audio_bitrate) {
  687. $r->audio_bitrate = $options['audio_bitrate'];
  688. $this->displayAudio($r);
  689. }
  690. if ($alt && is_object($alt) && $alt->raw) {
  691. $options['geometry'] = $altwidth.'x'.($altheight-$height);
  692. $img = '<div class="tzr-audio-alt">' . $this->htmlImage($alt, $options) . '</div>';
  693. }
  694. if (defined('HTML5MEDIA')) {
  695. if ($this->audioReady($r, true))
  696. $audio = '
  697. <audio id="'.$r->varid.'" class="tzr-audio" '.($options['autoplay'] ? ' autoplay="autoplay"' : '').' controls="controls" height="'.$height.'" width="'.$width.'" style="height:'.$height.'px;width:'.$width.'px" preload="none">
  698. <source src="'.$r->fullaudio_ogg.'" type="audio/ogg" />
  699. <source src="'.$r->fullaudio.'" type="audio/mp3" />
  700. </audio>';
  701. else
  702. $audio = '
  703. <audio id="'.$r->varid.'" class="tzr-audio" '.($options['autoplay'] ? ' autoplay="autoplay"' : '').' controls="controls" height="'.$height.'" width="'.$width.'" style="height:'.$height.'px;width:'.$width.'px">
  704. <source src="'.$r->prehear_ogg.'" type="audio/ogg" />
  705. <source src="'.$r->prehear.'" type="audio/mp3" />
  706. </audio>';
  707. $html = '
  708. <div class="tzr-audio-div">
  709. '.@$img.$audio.'
  710. <script type="text/javascript">
  711. jQuery("#'.$r->varid.'").mediaelementplayer({pluginPath: "'.TZR_SHARE_URL.'js/jmediaelement/build/"});
  712. </script>
  713. </div>';
  714. }
  715. else
  716. $html = @$img.'<div style="height:27px;width:'.$width.'px;"><div id="'.$r->varid.'"></div></div><script type="text/javascript">swfobject.embedSWF("'.TZR_SHARE_URL.'flash/mpw_player.swf","'.$r->varid.'","'.$width.'","27","8","",{mp3:"'.urlencode(($this->audioReady($r,true)?$r->fullaudio:$r->prehear.'&bitrate='.$r->audio_bitrate)).'",autoplay:'.($options['autoplay']?'1':'0').'},{bgcolor:"000000"});</script>';
  717. return $html;
  718. }
  719. /// Determine si le fichier est directement disponible dans la format. Si 'force' a true et fichier non disponible, lance la tache
  720. function audioReady($r, $forceConvert=true){
  721. if(!XFileDef::isAudio($r->mime))
  722. return false;
  723. $ready = true;
  724. $filename_cache = $r->filename.'-'.md5($r->audio_bitrate.'audio/mpeg').'-cache';
  725. if(!file_exists($filename_cache) || (filemtime($r->filename)>filemtime($filename_cache))){
  726. $ready = false;
  727. if($forceConvert){
  728. $ffmpeg = FFMPEG.' -y -i '.$r->filename.' -ab '.$r->audio_bitrate.'k -ar 44100 -f mp3 '.$filename_cache.';';
  729. }
  730. }
  731. if (defined('HTML5MEDIA')) {
  732. $filename_cache=$r->filename.'-'.md5($r->audio_bitrate.'audio/ogg').'-cache';
  733. if(!file_exists($filename_cache) || (filemtime($r->filename)>filemtime($filename_cache))){
  734. $ready = false;
  735. if($forceConvert){
  736. $ffmpeg .= FFMPEG.' -y-i '.$r->filename.' -ab '.$r->audio_bitrate.'k -acodec libvorbis -f ogg '.$filename_cache;
  737. }
  738. }
  739. }
  740. if ($ffmpeg) {
  741. $s=new XModScheduler(array('tplentry'=>TZR_RETURN_DATA));
  742. $s->createIdleShellJob(md5($ffmpeg),'Audio encoding',$ffmpeg,'');
  743. }
  744. return $ready;
  745. }
  746. /// Renvoie la duree d'une video ou d'un audio en secondes
  747. function getDuration($file,$mime){
  748. if(!$file || !file_exists($file)) return 0;
  749. elseif(XFileDef::isVideo($mime) || XFileDef::isAudio($mime)){
  750. $ffmpeg=exec(FFMPEG.' -i '.$file.' 2>&1|grep "Duration"|sed \'s/^.*Duration: \(.*\)\.[0-9],.*$/\1/\'');
  751. if(!empty($ffmpeg)) list($h,$m,$s)=explode(':',$ffmpeg);
  752. else return 0;
  753. if($h && $m && $s) return intval($h)*3600+intval($m)*60+intval($s);
  754. }
  755. return 0;
  756. }
  757. /* PDF */
  758. /// Complete l'objet d'affichage dans le cas d'une image
  759. function displayPDF(&$r,&$value,&$options){
  760. $resizer=$this->getResizer($r->shortfilename,$r->mime,$r->originalname);
  761. if(!empty($resizer) && !empty($resizer['resizer'])) {
  762. $r->resizer=$resizer['resizer'];
  763. $r->weresizer=$resizer['weresizer'];
  764. }
  765. $r->isPDF = true;
  766. $r->html = $r->html_default;
  767. return $r;
  768. }
  769. /// Affichage d'un pdf Calaméo
  770. function displayCalameo(&$r, $value, $options) {
  771. $book_id = substr($r->file, 8);
  772. $params = array(
  773. 'action' => 'API.getBookInfos',
  774. 'apikey' => CALAMEO_PUBLIC_KEY, // a définir dans le local.inc
  775. 'book_id' => $book_id,
  776. 'output' => 'PHP'
  777. );
  778. $url = 'http://api.calameo.com/1.0?';
  779. $signature = CALAMEO_SECRET_KEY; // a définir dans le local.inc
  780. foreach ($params as $key => $value) {
  781. $url .= "$key=$value&";
  782. $signature .= "$key$value";
  783. }
  784. $url .= 'signature=' . md5($signature);
  785. $response = unserialize(file_get_contents($url));
  786. $response = $response['response'];
  787. if ($response['status'] == 'error') {
  788. XLogs::notice(__CLASS__.'::'.__FUNCTION__, "error code {$response['error']['code']}, {$response['error']['message']}");
  789. $r->error = true;
  790. return $r;
  791. }
  792. $r->error = false;
  793. $r->isCalameo = true;
  794. $r->mime = 'application/pdf';
  795. $r->resizer = '';
  796. $r->preview = $response['content']['ThumbUrl'];
  797. $r->title = $response['content']['Name'];
  798. $r->text = $r->title;
  799. $r->externalUrl = $response['content']['ViewUrl'];
  800. $r->downloadUrl = str_replace('read', 'download', $response['content']['ViewUrl']);
  801. $r->fullwidth = $response['content']['Width'];
  802. $r->fullheight = $response['content']['Height'];
  803. $r->dltarget = 'calameo'; // target pour le lien download, si pdf non dispo
  804. $r->html_preview = $this->html_previewCalameo($r, $options);
  805. if ($this->usemimehtml)
  806. $r->html = $this->htmlCalameo($r, $options);
  807. else
  808. $r->html = $r->html_preview;
  809. return $r;
  810. }
  811. /// html preview calaméo
  812. function html_previewCalameo($r, $options=array()) {
  813. if ($r->error)
  814. return '';
  815. if (isset($options['geometry'])) {
  816. list($width, $height) = explode('x', str_replace('>', '', $options['geometry']));
  817. $width = (integer)$width;
  818. $height = (integer)$height;
  819. $ratio = min($width / $r->fullwidth, $height / $r->fullheight);
  820. $width = (integer)($ratio * $r->fullwidth);
  821. $height = (integer)($ratio * $r->fullwidth);
  822. } else {
  823. $width = TZR_THUMB_SIZE;
  824. $height = TZR_THUMB_SIZE;
  825. }
  826. return '<img src="'.$r->preview.'" width="'.$width.'" height="'.$height.'" alt="'.$r->title.'" class="tzr-externalfile" rel="'.$r->file.'">';
  827. }
  828. /// html calaméo
  829. function htmlCalameo($r, $options=array()) {
  830. if ($r->error)
  831. return '';
  832. $geometry = @$options['geometry'] ? $options['geometry'] : $this->image_geometry;
  833. list($width, $height) = explode('x', $geometry);
  834. $width = (integer)$width;
  835. $height = (integer)$height;
  836. return '<iframe id="'.$r->varid.'" src="'.$r->externalUrl.'" wmode="transparent" style="width:'.$width.'px;height:'.$height.'px"></iframe>';
  837. }
  838. /// Tag les valeurs IPTC/XMP d'un fichier via un tableau de donnée
  839. static function setFileMetaWithArray($data,$file,$tmpfile=NULL,$clean=false){
  840. if(empty($file)) return false;
  841. if($tmpfile=='auto'){
  842. $infos=pathinfo($file);
  843. $tmpfile=TZR_TMP_DIR.uniqid('metafile').'.'.$infos['extension'];
  844. copy($file,$tmpfile);
  845. }elseif($tmpfile){
  846. copy($file,$tmpfile);
  847. }else{
  848. $tmpfile=$file;
  849. }
  850. if($clean) XFileDef::cleanFileMeta($tmpfile);
  851. $mimeClasse=XMimeTypes::getInstance();
  852. $mime=$mimeClasse->getValidMime(NULL,$tmpfile,NULL);
  853. if($mime=='image/jpeg'){
  854. $meta=XFileDef::loadMeta($tmpfile);
  855. if(!empty($data['IPTC'])){
  856. foreach($data['IPTC'] as $tag=>$value){
  857. $meta->setIPTCProperty($tag,$value);
  858. }
  859. }
  860. if(!empty($data['XMP'])){
  861. foreach($data['XMP'] as $tag=>$value){
  862. $meta->setXMPProperty($tag,$value);
  863. }
  864. }
  865. $meta->save();
  866. }
  867. return $tmpfile;
  868. }
  869. /// Tag les valeurs IPTC/XMP d'un fichier via un template
  870. static function setFileMetaWithTemplate($tpl,$file,$tmpfile=NULL,$standards=array('IPTC','XMP'),$clean=false){
  871. if(empty($file)) return false;
  872. if($tmpfile=='auto'){
  873. $infos=pathinfo($file);
  874. $tmpfile=TZR_TMP_DIR.uniqid('metafile').'.'.$infos['extension'];
  875. copy($file,$tmpfile);
  876. }elseif($tmpfile){
  877. copy($file,$tmpfile);
  878. }else{
  879. $tmpfile=$file;
  880. }
  881. if($clean) XFileDef::cleanFileMeta($tmpfile);
  882. $mimeClasse=XMimeTypes::getInstance();
  883. $mime=$mimeClasse->getValidMime(NULL,$tmpfile,NULL);
  884. if($mime=='image/jpeg' && !empty($standards)){
  885. $tplmeta=XFileDef::loadMeta($tpl);
  886. $meta=XFileDef::loadMeta($tmpfile);
  887. // Traitement des tags IPTC
  888. if(in_array('IPTC',$standards)){
  889. $tags=$tplmeta->getIPTCAll();
  890. foreach($tags as $tag=>$value){
  891. $meta->setIPTCProperty($value['IPTC_Type'],$value['RecData']);
  892. }
  893. }
  894. // Traitement des tags XMP
  895. if(in_array('XMP',$standards)){
  896. $tags=$tplmeta->xmp_xpath->query($tplmeta->xmp_descr_path.'/'.$tplmeta->xmp_descr_node.'/*');
  897. foreach($tags as $tag){
  898. list($prefix,$foo)=explode(':',$tag->nodeName);
  899. if($prefix!='dc') continue;
  900. $n=$meta->xmp_xpath->query($meta->xmp_descr_path.'/'.$meta->xmp_descr_node.'/'.$tag->nodeName);
  901. if($n->length){
  902. $p=$n->parentNode;
  903. $p->removeChild($n);
  904. }else{
  905. $d=$meta->getXMPDescriptionFromPrefix($prefix);
  906. if(empty($d)) $d=$meta->addXMPDescription($prefix,$tag->parentNode->lookupNamespaceURI($prefix));
  907. $p=$d;
  908. }
  909. $p->appendChild($meta->xmp_dom->importNode($tag,true));
  910. }
  911. }
  912. $meta->save();
  913. }
  914. return $tmpfile;
  915. }
  916. /// Tag les valeurs IPTC/XMP d'un fichier via un display
  917. static function setFileMetaWithDisplay($d,$file,$tmpfile=NULL,$standards=array('IPTC','XMP'),$clean=false){
  918. if(empty($file)) return false;
  919. if($tmpfile=='auto'){
  920. $infos=pathinfo($file);
  921. $tmpfile=TZR_TMP_DIR.uniqid('metafile').'.'.$infos['extension'];
  922. copy($file,$tmpfile);
  923. }elseif($tmpfile){
  924. copy($file,$tmpfile);
  925. }else{
  926. $tmpfile=$file;
  927. }
  928. if($clean) XFileDef::cleanFileMeta($tmpfile);
  929. $mimeClasse=XMimeTypes::getInstance();
  930. $mime=$mimeClasse->getValidMime(NULL,$file,NULL);
  931. if($mime=='image/jpeg' && !empty($standards)){
  932. $meta=XFileDef::loadMeta($tmpfile);
  933. if(!isset($d['fields_object'])){
  934. foreach($d as $i=>&$dd){
  935. foreach($dd['fields_object'] as $i=>&$f){
  936. $fdef=&$f->fielddef;
  937. $fdef->setMetaFromValue($meta,$dd['o'.$fdef->field],$standards);
  938. }
  939. }
  940. }else{
  941. foreach($d['fields_object'] as $i=>&$f){
  942. $fdef=&$f->fielddef;
  943. $fdef->setMetaFromValue($meta,$d['o'.$fdef->field],$standards);
  944. }
  945. }
  946. $meta->save();
  947. }
  948. return $tmpfile;
  949. }
  950. /// Nettoie tous les metas d'un fichier
  951. static function cleanFileMeta($file){
  952. $mimeClasse=XMimeTypes::getInstance();
  953. $mime=$mimeClasse->getValidMime(NULL,$file,NULL);
  954. if($mime=='image/jpeg'){
  955. system(TZR_MOGRIFY_RESIZER.' +profile "*" '.$file.' '.$file.';'. TZR_MOGRIFY_RESIZER.' +profile "*" '.$file.'_ld '.$file.'_ld');
  956. }
  957. }
  958. // generation du nom du fichier
  959. //
  960. function filename($value,$test=false,$testfinal=false,$secondaryroot=NULL) {
  961. global $DATA_DIR;
  962. $ar=NULL;
  963. if($value=='') return NULL;
  964. if($value==TZR_UNCHANGED) return NULL;
  965. $langdata = XShell::getLangData();
  966. @list($file,$mime,$originalname) = @explode(';',$value);
  967. if($file=='') return NULL;
  968. if($test) $this->_checkDir();
  969. umask(0000);
  970. $root=$this->table;
  971. if(!empty($secondaryroot)) {
  972. $root='A_'.$this->table.'/'.$secondaryroot;
  973. }
  974. $root.='/'.$this->field;
  975. $subdir=md5($file);
  976. while(strlen($subdir)>=16) {
  977. $tmp=substr($subdir,0,2);
  978. $root.='/'.$tmp;
  979. $subdir=substr($subdir,16);
  980. }
  981. if($test) XDir::mkdir($DATA_DIR.$root, false);
  982. $filename=$root.'/'.$file;
  983. if($test || $testfinal) {
  984. if(file_exists($DATA_DIR.$filename)) {
  985. $ar=$filename;
  986. } elseif($test) {
  987. $ar=NULL;
  988. }
  989. } else {
  990. $ar=$filename;
  991. }
  992. return $ar;
  993. }
  994. /// Generation du champ pour modification du fichier
  995. function my_edit(&$value,&$options) {
  996. $lang = XShell::getLangUser();
  997. $r=$this->_newXFieldVal($options,true);
  998. if(isset($options['intable'])) {
  999. return $r;
  1000. $o = $options['intable'];
  1001. $fname=$this->field.'['.$o.']';
  1002. $hiddenname=$this->field.'_HID['.$o.']';
  1003. } elseif(!empty($options['fieldname'])) {
  1004. $fname=$options['fieldname'];
  1005. $hiddenname=$options['fieldname'].'_HID';
  1006. } else {
  1007. $fname=$this->field;
  1008. $hiddenname=$this->field.'_HID';
  1009. }
  1010. $r->raw=$value;
  1011. $this->_checkDir();
  1012. $varid=$r->varid;
  1013. $disp=$this->my_display($value,$options);
  1014. // Titre à part
  1015. $txt='<table class="tzr-xfiledef"><tr>';
  1016. if($this->usealt)
  1017. $txt.='<td><label>'.XLabels::getSysLabel('general','title','text').'</label></td><td id="'.$varid.'-tdtitle"><input type="text" name="'.$fname.'_title" value="'.$disp->title.'"/></td></tr><tr><td><label>'.XLabels::getSysLabel('xfielddef','xfiledef','text').'</label></td>';
  1018. // Input fichier + bouton parcourir console
  1019. $txt.='<td id="'.$varid.'-tdfile"'.($disp->isExternal?' style="display:none"':'').'><input type="file" name="'.$fname.'" accept="'.$this->accept.'"'.(!empty($this->maxlength)?' maxlength="'.$this->maxlength.'"':'').' id="'.$varid.'"><br/>';
  1020. if(XShell::admini_mode() && $this->browsemods) {
  1021. $url=$GLOBALS['TZR_SESSION_MANAGER']::complete_self().'moid='.XModule::getMoid(XMODADMIN_TOID).'&function=modulesList&tplentry=br&_nonav=1&_nohistory=1&template=basic/source-file.html'.
  1022. '&skip=1&ajaxurl='.rawurlencode($GLOBALS['TZR_SESSION_MANAGER']::complete_self().'&function=browseFiles&tplentry=br&template=basic/source-file-ajax.html'.
  1023. '&pagesize=20&skip=1&recipientid='.$varid.'&_nonav=1&_nohistory=1&selectedprops[published]=1'.
  1024. '&selectedtypes[]=XFileDef&selectedtypes[]=XFolderDef&selectedop=OR');
  1025. if($this->sourcemodule) $url.='&toid=xx&ajaxmoid='.$this->sourcemodule;
  1026. else $url.='&toid[]=25&toid[]=8001';
  1027. $txt.='<input type="button" value="'.XLabels::getSysLabel('xmodule','browsemods','text').'" onclick="window.open(\''.$url.'\',\'\',\'width=655,height=550,menubar=0,resizable=1,scrollbars=1\');">';
  1028. }
  1029. // Fichier externe
  1030. if ($this->allow_externalfile) {
  1031. $txt .= '<input type="button" value="'.XLabels::getSysLabel('xfielddef','externalfile').'" onclick="jQuery(\'#'.$r->varid.'-tdfile, #'.$r->varid.'-tdexternal, #'.$r->varid.'-trcancel\').toggle()">';
  1032. }
  1033. $txt.='</td>';
  1034. if (XShell::admini_mode() && $this->browsemods) {
  1035. $txt .= '<td id="'.$r->varid.'-tdbrowsemods"></td>';
  1036. }
  1037. if ($this->allow_externalfile) {
  1038. $txt .= '<td id="'.$r->varid.'-tdexternal"'.($disp->isExternal?'':' style="display:none"').'>'.XLabels::getSysLabel('xfielddef','externalfile').' : <input type="text" id="'.$r->varid.'-external" value="'.$disp->externalUrl.'" name="'.$hiddenname.'[external]" size="50" maxsize="200"/></td>';
  1039. }
  1040. $txt.='</tr>';
  1041. if (XShell::admini_mode() && $this->browsemods || $this->allow_externalfile) {
  1042. $txt.='<tr '.($disp->isExternal?'':' style="display:none"').' id="'.$r->varid.'-trcancel"><td colspan="4"><input type="button" value="'.XLabels::getSysLabel('general','cancel').'" onclick="jQuery(\'#'.$r->varid.'-tdexternal,#'.$r->varid.'-trcancel\').hide();jQuery(\'#'.$r->varid.'-tdbrowsemods\').html(\'\').hide();jQuery(\'#'.$r->varid.'-tdfile\').show();jQuery(\'#'.$r->varid.'-from, #'.$r->varid.'-external\').val(\'\')"></td></tr>';
  1043. }
  1044. $txt.='</tr></table>';
  1045. $txt.='<input type="hidden" id="'.$r->varid.'-old" name="'.$hiddenname.'[old]" value="'.$value.'"/>';
  1046. $txt.='<input id="'.$varid.'-from" type="hidden" name="'.$hiddenname.'[from]" value=""/>';
  1047. // Bouton de supression
  1048. if($disp->html!='' && !$this->compulsory)
  1049. $txt.=' '.XLabels::getSysLabel('xfielddef','detach_file').' : <input type="checkbox" name="'.$fname.'_del" class="checkbox"/><br/>';
  1050. if ($this->compulsory) {
  1051. $txt .= '<script type="text/javascript">TZR.addValidator(["'.$r->varid.'","","'.addslashes($this->label).'","'.XIni::get('error_color').'","XFileDef","","'.$this->browsemods.'","'.$this->allow_externalfile.'"]);</script>';
  1052. }
  1053. $r->html=$txt;
  1054. $r->originalname=$disp->originalname;
  1055. $r->filename=$disp->filename;
  1056. $r->mime=$disp->mime;
  1057. if(XFileDef::isImage($r->mime) || get_class($this)=='XImageDef')
  1058. $this->editImage($r,$value,$options,$disp,$fname,$hiddenname);
  1059. elseif($disp->mime=='text/html' || $disp->mime=='text/plain')
  1060. $this->editHTML($r,$value,$options,$disp,$fname,$hiddenname);
  1061. else
  1062. $r->html .= $disp->html_preview;
  1063. return $r;
  1064. }
  1065. /// Complete l'objet d'edition dans le cas d'une image
  1066. function editImage(&$r,&$value,&$options,&$disp,$fname,$hiddenname){
  1067. $r->isImage=true;
  1068. if(!empty($this->image_crop_ratio)){
  1069. $r->html.='<div id="'.$r->varid.'-cropinfo" class="tzr-xfiledef-cropinfo"><a href="#" onclick="return false;">'.XLabels::getSysLabel('xfielddef','image_crop').'</a></div>';
  1070. $r->html.='<script type="text/javascript">TZR.Image.activeCrop(\''.$r->varid.'\',\''.$this->image_crop_ratio.'\');</script>';
  1071. }
  1072. if($disp->html){
  1073. $px=' '.XLabels::getSysLabel('general','pixels','text');
  1074. $r->html='<table><tr><td colspan="2">'.$r->html.'</td></tr><tr><td><img src="'.$disp->resizer.'&geometry='.TZR_THUMB_SIZE.'x'.TZR_THUMB_SIZE.'%3E"></td><td>'.
  1075. $disp->html_default.'<br>'.
  1076. XLabels::getSysLabel('xfielddef','file_size').' : '.round($this->getFileSize($r)/1024).' Ko<br>'.
  1077. XLabels::getSysLabel('general','width','text').' : '.$this->getImageSize($r,'fullwidth').$px.'<br>'.
  1078. XLabels::getSysLabel('general','height','text').' : '.$this->getImageSize($r,'fullheight').$px.
  1079. '</td></tr></table>';
  1080. }
  1081. }
  1082. /// Complete l'objet d'édition dans le cas d'un fichier HTML
  1083. function editHTML(&$r,&$value,&$options,&$disp,$fname,$hiddenname){
  1084. if($options['fmoid']){
  1085. $edition='';
  1086. $tmpname=md5(session_id().$disp->table.$disp->field.$options['oid']);
  1087. copy($disp->filename, TZR_TMP_DIR.$tmpname);
  1088. $dla=$this->getDownloader($tmpname, $disp->mime, $disp->originalname, $disp->originalname, $options['fmoid']);
  1089. $dl=$dla[0].'&tmp=1&disp=inline';
  1090. $url=$GLOBALS['TZR_SESSION_MANAGER']::complete_self(true,true).'&function=edit&selectedfields[]='.$this->field.'&moid='.$options['fmoid'].'&template=popfileedit.html&field='.$this->field.'&tplentry=br&oid='.$options['oid'];
  1091. $upl=TZR_FILE_EDITOR_UPLOADER.'?moid='.$options['fmoid'].'&table='.$disp->table.'&field='.$disp->field.'&oid='.$options['oid'].'&moid='.$options['fmoid'];
  1092. $edition.='<input type="hidden" name="'.$hiddenname.'[editflag]" value="no"/>';
  1093. $edition.=' <a href="#" onclick="TZR.openhtmlfileeditor({uniqid:\''.XShell::uniqid().'\',url:\''.$url.'\',uploader:\''.$upl.'\', editflag:\''.$hiddenname.'[editflag]\'}); return false;">'.XLabels::getSysLabel('general','edit','text').'</a>';
  1094. $r->html.=$disp->html.$edition;
  1095. }else{
  1096. $r->html.=$disp->html;
  1097. }
  1098. }
  1099. function sqltype() {
  1100. return 'varchar(200)';
  1101. }
  1102. /// Suppression de la donnee
  1103. function delete($value, $oid) {
  1104. global $DATA_DIR;
  1105. $langdata = XShell::getLangData();
  1106. // calcul du nom du fichier associe
  1107. $filename= $this->filename($value,true);
  1108. if($filename) {
  1109. if(file_exists($DATA_DIR.$filename)) {
  1110. XLogs::debug('[XFileDef::delete]unlink('.$DATA_DIR.$filename.')');
  1111. @unlink($DATA_DIR.$filename);
  1112. }
  1113. }
  1114. return 1;
  1115. }
  1116. function post_edit($value,$options) {
  1117. global $DATA_DIR;
  1118. $p=new XParam($options,array('del'=>true));
  1119. $r=$this->_newXFieldVal($options);
  1120. $langdata=XShell::getLangData();
  1121. $hidden=$options[$this->field.'_HID'];
  1122. $del=$p->get('del');
  1123. $mimeClasse=XMimeTypes::getInstance();
  1124. // Verification que les repertoires existent
  1125. $oid=$p->get('oid');
  1126. // Calcul du nom du fichier associe
  1127. list($t,$f)=explode(':',$oid);
  1128. if($this->translatable) $retval=$langdata.'.'.$f;
  1129. else $retval=$f;
  1130. $oldfile=$this->filename($retval,true);
  1131. $file=$this->filename($retval,false);
  1132. if($file) $filename=$DATA_DIR.$file;
  1133. $oldfilename='';
  1134. if($oldfile) $oldfilename=$DATA_DIR.$oldfile;
  1135. $from=$hidden['from'];
  1136. $link=(@$hidden['link']?true:false);
  1137. if(!empty($from)) {
  1138. // Le fichier est déjà sur le serveur et doit etre dupliqué
  1139. @list($url,$mime,$name)=@explode(';',$from);
  1140. parse_str($url,$infos);
  1141. $infos=pathinfo($url);
  1142. if(empty($mime)) $mime=@$infos['mime'];
  1143. if(substr($url,0,1)!='/') $url=TZR_WWW_DIR.$url;
  1144. if($link) $tmp_name=$from;
  1145. else {
  1146. $tmp_name=TZR_TMP_DIR.uniqid();
  1147. copy($url,$tmp_name);
  1148. }
  1149. $upload_type=$mime;
  1150. $upload_filename=$tmp_name;
  1151. if(!empty($name)){
  1152. $upload_name=$name;
  1153. $upload_type=$mimeClasse->getValidMime(NULL,$upload_filename,NULL);
  1154. }elseif(!empty($infos['extension'])){
  1155. $upload_name=$infos['basename'];
  1156. $upload_type='';
  1157. }else{
  1158. $upload_type=$mimeClasse->getValidMime(NULL,$upload_filename,NULL);
  1159. $upload_name=$infos['basename'].'.'.$mimeClasse->get_extension($upload_type);
  1160. }
  1161. $upload_filename_del='off';
  1162. $upload_title=$p->get($this->field.'_title');
  1163. $upload_size=@filesize($tmp_name);
  1164. } elseif(is_string($value) && substr($value,0,7)=='http://') {
  1165. // Le fichier est une url
  1166. $tmp_name=TZR_TMP_DIR.uniqid();
  1167. $content=file_get_contents($value);
  1168. file_put_contents($tmp_name,$content);
  1169. $upload_filename=$tmp_name;
  1170. $infos=parse_url($value);
  1171. $infos=pathinfo($infos['path']);
  1172. $headers = get_headers($value,1);
  1173. if($headers && $headers['Content-disposition'] && preg_match('/filename=(.*)$/',$headers['Content-disposition'],$eregs) && $eregs[1]){
  1174. $upload_name = $eregs[1];
  1175. $upload_type = $mimeClasse->getValidMime($headers['Content-Type'],$upload_filename,$upload_name);
  1176. }elseif($infos['extension']){
  1177. $upload_name = $infos['basename'];
  1178. $upload_type = '';
  1179. }else{
  1180. $upload_type = $mimeClasse->getValidMime(NULL,$upload_filename,NULL);
  1181. $upload_name = $infos['basename'].'.'.$mimeClasse->get_extension($upload_type);
  1182. }
  1183. $upload_filename_del='off';
  1184. $upload_title=NULL;
  1185. $upload_size=@filesize($tmp_name);
  1186. } elseif(is_string($value) && file_exists($value)) {
  1187. // Le fichier est un chemin sur le serveur
  1188. $infos=pathinfo($value);
  1189. $upload_filename=$value;
  1190. if($infos['extension']){
  1191. $upload_name=$infos['basename'];
  1192. $upload_type='';
  1193. }else{
  1194. $upload_type=$mimeClasse->getValidMime(NULL,$upload_filename,NULL);
  1195. $upload_name=$infos['basename'].'.'.$mimeClasse->get_extension($upload_type);
  1196. }
  1197. $upload_filename_del='off';
  1198. $upload_title=NULL;
  1199. $upload_size=@filesize($value);
  1200. } elseif(is_array($value)) {
  1201. $upload_filename=$value['tmp_name'];
  1202. $upload_type=$value['type'];
  1203. $upload_name=$value['name'];
  1204. $upload_filename_del='off';
  1205. $upload_title=$value['title'];
  1206. $upload_size=$value['size'];
  1207. } elseif(isset($hidden['editflag']) && $hidden['editflag']=='yes'){
  1208. // cas d'un fichier édité (dans l'admin)
  1209. $tmpfile=TZR_TMP_DIR.md5(session_id().$this->table.$this->field.$options['oid']);
  1210. $upload_filename=$tmpfile;
  1211. list($void, $upload_type , $upload_name) = explode(';', $hidden['old']);
  1212. $upload_filename_del='off';
  1213. $upload_title=NULL;
  1214. $upload_size=@filesize($tmpfile);
  1215. } elseif($hidden['external']){
  1216. return $this->post_editExternal($value,$options);
  1217. } else {
  1218. // Fichier uploadé via formulaire
  1219. $upload_filename=@$_FILES[$this->field]['tmp_name'];
  1220. $upload_type=@$_FILES[$this->field]['type'];
  1221. $upload_name=@$_FILES[$this->field]['name'];
  1222. $upload_size=@$_FILES[$this->field]['size'];
  1223. $upload_filename_del=$p->get($this->field.'_del');
  1224. $upload_title=$p->get($this->field.'_title');
  1225. }
  1226. // Recupere un type mime fiable
  1227. $upload_type=$mimeClasse->getValidMime($upload_type,$upload_filename,$upload_name);
  1228. XLogs::debug('[XFileDef::post_edit] '.$upload_type);
  1229. // Renseigne la taille si non renseigné
  1230. if(empty($upload_size)) $upload_size=@filesize($upload_filename);
  1231. // On verifie qu'on est dans les types acceptés
  1232. $ok = ($upload_filename!='none' && !empty($upload_filename)) && ($mimeClasse->isAccepted($upload_type,$this->accept));
  1233. // Verification de la taille du fichier
  1234. $maxlength=trim($this->maxlength);
  1235. if(!empty($maxlength) && ($upload_size > $maxlength)) $ok=false;
  1236. if($upload_filename_del=='on') {
  1237. if(isset($GLOBALS['XREPLI'])) $GLOBALS['XREPLI']->journalize('del',$oldfilename);
  1238. XLogs::debug('[XFileDef::post_edit]unlink('.$oldfilename.')');
  1239. $this->trace($options['old'],$r, '[-]file deleted');
  1240. @unlink($oldfilename);
  1241. $retval='';
  1242. }else{
  1243. if(XFileDef::isImage($upload_type) && !$link){
  1244. $this->rotateAndFlip($upload_filename,$upload_type);
  1245. $this->resizeImage($upload_filename,$this->image_max_geometry);
  1246. }
  1247. if($ok && ($upload_filename!='none') && !empty($upload_filename)){
  1248. if(!empty($oldfilename) && file_exists($oldfilename)) {
  1249. XLogs::debug('[XFileDef::post_edit]unlink('.$oldfilename.')');
  1250. unlink($oldfilename);
  1251. }
  1252. if(file_exists($filename)) {
  1253. XLogs::debug('[XFileDef::post_edit]unlink('.$filename.')');
  1254. unlink($filename);
  1255. }
  1256. if(!empty($hidden['crop'])){
  1257. $upload_filename_crop=$upload_filename.'_crop';
  1258. exec(TZR_MOGRIFY_RESIZER.' +profile "*" -crop "'.$hidden['crop']['w'].'x'.$hidden['crop']['h'].'+'.$hidden['crop']['x'].'+'.$hidden['crop']['y'].'" "'.
  1259. $upload_filename.'" "'.$upload_filename_crop.'" 2>&1 > /dev/null');
  1260. $upload_filename=$upload_filename_crop;
  1261. }
  1262. // Cryptage/Signature des fichiers
  1263. if($this->crypt) cryptAndSignFile($upload_filename);
  1264. // gzip
  1265. if ($this->gzipped == 1) {
  1266. $content = file_get_contents($upload_filename);
  1267. $fh = gzopen($filename, 'w');
  1268. gzwrite($fh, $content);
  1269. gzclose($fh);
  1270. } elseif($link) {
  1271. link($upload_filename,$filename);
  1272. } else
  1273. copy($upload_filename, $filename);
  1274. // calcul de l'image réduite de reference pour le jpeg
  1275. if ($upload_type == 'image/jpeg') {
  1276. exec(TZR_MOGRIFY_RESIZER.' -resize "'.TZR_LD_IMAGE_SIZE.'>" -density 72x72 '.$filename.' '.$filename.'_ld 2>&1 > /dev/null');
  1277. }
  1278. $this->trace(@$options['old'],$r, (!empty($upload_name)?$upload_name:'file changed'));
  1279. $r->filename=$filename;
  1280. $r->mime=$upload_type;
  1281. if(isset($GLOBALS['XREPLI'])) $GLOBALS['XREPLI']->journalize('upd',$filename);
  1282. $retval=$retval.';'.$upload_type.';'.$upload_name.';'.$upload_title;
  1283. if(!$link && $del && empty($options['editbatch'])){
  1284. XLogs::debug('[XFileDef::post_edit]unlink('.$upload_filename.')');
  1285. @unlink($upload_filename);
  1286. }
  1287. if(!empty($upload_filename_crop)) @unlink($upload_filename_crop);
  1288. }else{
  1289. // Modification du libellé seulement
  1290. $oldvalue=rawurldecode($hidden['old']);
  1291. $values=explode(';',$oldvalue);
  1292. if($values[3]!=$upload_title) {
  1293. $values[3]=$upload_title;
  1294. $retval=implode(';',$values);
  1295. $this->trace($options['old'],$r, 'file label changed -> '.$upload_title);
  1296. } else {
  1297. $retval = TZR_UNCHANGED;
  1298. }
  1299. }
  1300. }
  1301. $r->raw=$retval;
  1302. return $r;
  1303. }
  1304. /// traitement apres saisie en duplication
  1305. function post_editExternal($value,$options) {
  1306. $r = $this->_newXFieldVal($options);
  1307. $hidden = $options[$this->field.'_HID'];
  1308. $url = preg_replace('@^http(s)?://@', '', $hidden['external']);
  1309. $upload_filename_del='off';
  1310. if (preg_match('@^(www.youtube.com/watch\?v=|www.youtube.com/embed/|youtu.be/|www.youtube.com/v/|youtube:)([A-Za-z0-9_-]{11})@', $url, $matches)) {
  1311. $videoid = $matches[2];
  1312. $r->raw = 'youtube:'.$videoid.';video/x-flv;;';
  1313. return $r;
  1314. }
  1315. if (preg_match('@(calameo.com/[^\/]*/|calameo:)([0-9a-z]*)@', $url, $matches)) {
  1316. $book_id = $matches[2];
  1317. $r->raw = 'calameo:'.$book_id.';application/pdf;;';
  1318. return $r;
  1319. }
  1320. if (preg_match('@(www.dailymotion.com/video/|dailymotion:)([0-9a-z]*)@', $url, $matches)) {
  1321. $videoid = $matches[2];
  1322. $r->raw = 'dailymotion:'.$videoid.';video/x-flv;;';
  1323. return $r;
  1324. }
  1325. return $r;
  1326. }
  1327. /// traitement apres saisie en duplication
  1328. function post_edit_dup($value,$options) {
  1329. global $DATA_DIR;
  1330. $p = new XParam($options,array());
  1331. $langdata = XShell::getLangData();
  1332. $oidsrc=$p->get('oidsrc');
  1333. $oiddst=$p->get('oiddst');
  1334. // Si on a renseigné le champ pour un nouveau fichier
  1335. if(!empty($_FILES[$this->field]['tmp_name']) || $p->get('filepub_del')){
  1336. $options['oid' ]=$oiddst;
  1337. $r=$this->post_edit($value,$options,NULL);
  1338. return $r->raw;
  1339. }elseif(!$this->nocopydup){
  1340. $oldvalue=$p->get($this->field.'_HID');
  1341. return $this->copyExternalsTo($oldvalue['old'],$oidsrc,$oiddst);
  1342. }
  1343. }
  1344. /// nettoyage des repertoires de données
  1345. function chk(&$messages) {
  1346. // verification que les images renseignees en base existent sur le disque
  1347. $rs=selectQuery('SELECT KOID,'.$this->field.',LANG FROM '.$this->table. ' WHERE '.$this->field.'!="'.TZR_UNCHANGED.'"');
  1348. while($rs && ($ors=$rs->fetch())) {
  1349. $opts=array();
  1350. $val=$this->my_display($ors[$this->field],$opts);
  1351. if(!$val->isExternal && !file_exists($val->filename)) {
  1352. updateQuery('UPDATE '.$this->table.' SET UPD=UPD,'.$this->field.'="'.TZR_UNCHANGED.'" WHERE KOID="'.$ors['KOID'].'" AND LANG="'.$ors['LANG'].'"');
  1353. }
  1354. unset($val);
  1355. }
  1356. // verification de x000 images au hasard que les images sur le disque sont rattachees en base
  1357. $root=$GLOBALS['DATA_DIR'].$this->table.'/'.$this->field;
  1358. $files1 = XDir::scan($root);
  1359. if(!empty($files1)) {
  1360. $files = array_rand($files1, min(10000,count($files1)));
  1361. // dans le cas ou il n'y a qu'un element dans $files1, array_rand ne rend pas un tableau
  1362. if(!is_array($files)) { $f1=$files;unset($files);$files=array($f1);}
  1363. $list=$listtodelete=array();
  1364. foreach($files as $i => $file1) {
  1365. $file=$files1[$file1];
  1366. $names=explode('/',$file);
  1367. $names=array_reverse($names);
  1368. $idx=$names[0];
  1369. if(preg_match("@cache([\.a-z0-9]+)-([a-z0-9]+)@i",$names[0],$eregs)) {
  1370. $idx=$eregs[1];
  1371. }
  1372. if(preg_match("@([\.a-z0-9_]+)-(([a-z0-9]+)-cache|fullsizeimage)@i",$names[0],$eregs)) {
  1373. $idx=$eregs[1];
  1374. }
  1375. $idf=$idx;
  1376. if(preg_match('@([a-z]+)\.([a-z0-9]+)@i',$idx,$eregs)) {
  1377. $idx=$eregs[2];
  1378. }
  1379. $list[]=array($idx, $file,$idf);
  1380. }
  1381. foreach($list as $i => $o) {
  1382. $fname=$o[0];
  1383. $filename=$o[1];
  1384. $o2=$o[2];
  1385. $cnt=countSelectQuery('SELECT COUNT(KOID) FROM '.$this->table.' WHERE '.$this->field.' like \''.$o2.'%\' LIMIT 1');
  1386. if($cnt<=0) {
  1387. $listtodelete[]=$filename;
  1388. }
  1389. }
  1390. foreach($listtodelete as $filename) {
  1391. $flag=@unlink($filename);
  1392. XLogs::notice('XFileDef::chk','unlinking '.$filename);
  1393. if(!$flag) $messages.='unlinking '.$filename.':nok'."\n";
  1394. }
  1395. $dirs=XDir::scan($root, true, false, true);
  1396. $do=true;
  1397. while($do) {
  1398. $do=false;
  1399. foreach($dirs as $i=>$dirname) {
  1400. if(@rmdir($dirname)) {
  1401. unset($dirs[$i]);
  1402. $do=true;
  1403. }
  1404. }
  1405. }
  1406. }
  1407. }
  1408. /// Prepare la recherche rapide sur le champ
  1409. function my_quickquery($value,$options=NULL) {
  1410. $r=$this->my_query($value,$options);
  1411. $r->html.='<input type="hidden" value="'.$this->field.'" name="_FIELDS['.$this->field.']">';
  1412. return $r;
  1413. }
  1414. /// Prepare la recherche sur le champ
  1415. function my_query($value,$options=NULL) {
  1416. if(is_array($value)){
  1417. $v=$value['name'];
  1418. $mime=$value['mime'];
  1419. }else{
  1420. $v=$value;
  1421. $mime='';
  1422. }
  1423. $v=htmlspecialchars($v);
  1424. $labelin=@$options['labelin'];
  1425. $r=$this->_newXFieldVal($options,true);
  1426. $fname=(isset($options['fieldname'])?$options['fieldname']:$this->field);
  1427. $varid=$r->varid;
  1428. $t='<input type="text" id="'.$fname.$varid.'" name="'.$fname.'[name]" size="'.($this->fcount>30?30:$this->fcount).'" value="'.$v.'"/>';
  1429. $t.='<select name="'.$fname.'[mime]">';
  1430. $t.='<option value="">---</option>';
  1431. $t.='<option value="image/*"'.($mime=='image/*'?' selected':'').'>'.XLabels::getSysLabel('mime','image/*','text').'</option>';
  1432. $t.='<option value="*video*"'.($mime=='*video*'?' selected':'').'>'.XLabels::getSysLabel('mime','video/*','text').'</option>';
  1433. $t.='<option value="*audio*"'.($mime=='*audio*'?' selected':'').'>'.XLabels::getSysLabel('mime','audio/*','text').'</option>';
  1434. $t.='<option value="text/html"'.($mime=='text/html'?' selected':'').'>'.XLabels::getSysLabel('mime','text/html','text').'</option>';
  1435. $t.='<option value="application/pdf"'.($mime=='application/pdf'?' selected':'').'>'.XLabels::getSysLabel('mime','application/pdf','text').'</option>';
  1436. $t.='</select>';
  1437. if(!empty($labelin)) $t.='<script type="text/javascript">inputInit("'.$fname.$varid.'","'.addslashes($this->label).'");</script>';
  1438. $r->varid=$varid;
  1439. $r->html=$t;
  1440. $r->raw=$value;
  1441. return $r;
  1442. }
  1443. function post_query($o,$ar){
  1444. if(is_array($o->value)){
  1445. $v=addslashes($o->value['name']);
  1446. $mime=str_replace('*','.*',addslashes($o->value['mime']));
  1447. if(!empty($v) || !empty($mime)){
  1448. if(empty($mime)) $mime='.+';
  1449. $sql='^(.+;'.$mime.';.*'.$v.'.*;.*)|(.+;'.$mime.';.+;.*'.$v.'.*)$';
  1450. $o->op='regexp';
  1451. $o->value=$sql;
  1452. }else{
  1453. $o->value='';
  1454. }
  1455. }
  1456. return parent::post_query($o,$ar);
  1457. }
  1458. /// Recupere le type du champ dans un webservice (name : type xml, descr : description du type pour l'ajour d'une type complexe)
  1459. function getSoapType(){
  1460. return array('name'=>'tns:file','descr'=>array('file'=>array(array('name'=>'mime','minOccurs'=>0,'maxOccurs'=>1,'type'=>'xsd:string'),
  1461. array('name'=>'url','minOccurs'=>1,'maxOccurs'=>1,'type'=>'xsd:string'),
  1462. array('name'=>'originalname','minOccurs'=>1,'maxOccurs'=>1,'type'=>'xsd:string'))));
  1463. }
  1464. /// Recupere la valeur formattée pour le service SOAP
  1465. function getSoapValue($r){
  1466. if($r->url) return array('mime'=>$r->mime,'url'=>$GLOBALS['TZR_SESSION_MANAGER']::makeDomainName().$r->url,'originalname'=>$r->originalname);
  1467. else return;
  1468. }
  1469. }
  1470. function xfiledef_getfilesize(){
  1471. $file=$_REQUEST['file'];
  1472. $s=filesize($GLOBALS['DATA_DIR'].$file);
  1473. echo XLabels::getSysLabel('xfielddef','file_size').' : '.getStringBytes($s);
  1474. }
  1475. function xfiledef_uploadfiletopreview(){
  1476. $keys=array_keys($_FILES);
  1477. $new=uniqid('file_');
  1478. move_uploaded_file($_FILES[$keys[0]]['tmp_name'],TZR_TMP_DIR.$new);
  1479. $s=getimagesize(TZR_TMP_DIR.$new);
  1480. echo json_encode(array('file'=>$new,'w'=>$s[0],'h'=>$s[1],'r'=>$s[0]/$s[1]));
  1481. }
  1482. function xfiledef_preview(){
  1483. $file=str_replace('..','',$_REQUEST['file']);
  1484. echo file_get_contents(TZR_TMP_DIR.$file);
  1485. }
  1486. ?>