source: spip-zone/_plugins_/ressource/inc/ressource.php @ 65573

Last change on this file since 65573 was 65573, checked in by brunobergot@…, 8 years ago

c'est à ressource de se brancher sur oembed et pas l'inverse :p

File size: 15.4 KB
Line 
1<?php
2
3/*
4 * transforme un raccourci de ressource en un joli html a embed
5 *
6 *
7 */
8
9define('_EXTRAIRE_RESSOURCES', ',' . '<"?(https?://|[\w -]+\.[\w -]+).*>'.',UimsS');
10
11
12function traiter_ressources($r) {
13        if ($ressource = charger_fonction('ressource', 'inc', true))
14                $html = $ressource($r[0]);
15        else
16                $html = htmlspecialchars($r[0]);
17
18        return '<html>'.$html.'</html>';
19}
20
21
22function inc_ressource_dist($r) {
23        // $r contient tout le texte définissant la ressource :
24        // <fichier.rtf option1 option2...>
25
26        // 1. phraser le raccourci
27        $attrs = phraser_tag('<res src='.substr($r,1));
28
29        # debug :)
30        $attrs['debug'] = $r;
31
32        // 2. keywords : right => align=right, etc
33        foreach(array(
34                'right' => 'align',
35                'left' => 'align',
36                'center' => 'align',
37        ) as $k => $v) {
38                if ($attrs[$k] == $k) {
39                        $attrs[$v] = $k;
40                        unset($attrs[$k]);
41                }
42        }
43
44        // 2. constituer les meta-donnees associees a $res[src]
45        $meta = ressource_meta($attrs);
46
47        // 4. traiter les parametres d'image / logo / vignette / resize
48        // supprimera le href si necessaire
49        $image = ressource_image($attrs, $meta);
50
51        $final = array_merge($meta, $attrs);
52
53        // renvoyer le html final
54        $final = array_merge($final, $image);
55
56        $html = embed_ressource($final);
57        return $html;
58}
59
60function ressource_meta($res) {
61        $meta = array();
62
63        // on va beaucoup travailler avec l'attribut src
64        $src = $res['src'];
65
66        // identifier la ressource
67        // s'agit-il d'un fichier decrit dans la mediathèque,
68        // d'un fichier local, d'un oembed, d'un doc distant connu, etc ?
69
70        // ressource fichier.rtf => rtf/fichier.rtf
71        if (preg_match(',^[^/]+\.([^.]+)$,', $src, $r))
72                $fichier = $r[1].'/'.$r[0];
73        else
74                $fichier = $src;
75
76        // determiner temporairement l'extension de la ressource (ca pourra changer
77        // si on en fait une copie locale et qu'elle indique un autre type mime)
78        if (preg_match(',\.(\w+)([?#].*)?$,S', $src, $r)) {
79                $meta['extension'] = strtolower($r[1]);
80
81                if ($meta['extension'] == 'jpeg')
82                        $meta['extension'] = 'jpg';
83        }
84
85        # d'abord fouiller la mediatheque
86        include_spip('base/abstract_sql');
87        if ($s = sql_fetsel('*', 'spip_documents', 'fichier='.sql_quote($fichier))) {
88                $meta = $s;
89                $meta['href'] = get_spip_doc($s['fichier']);
90                $meta['local'] = copie_locale($meta['href'], 'test');
91        }
92        else
93        if (preg_match(',^https?://,', $src)) {
94                $meta['href'] = $src;
95
96                /* pipeline ! */
97                /* exemple : traitement par autoembed */
98                include_spip('autoembed/autoembed');
99                if (function_exists('embed_url')
100                AND $u = embed_url($src)) {
101                        $meta['extract'] = $u;
102                }
103
104                /* autre exemple de traitement avec oembed */
105                include_spip('oembed_fonctions');
106                if (function_exists('oembed')
107                        AND $u = oembed($src)
108                        AND $u != $src) 
109                {
110                        $meta['extract'] = $u;
111                }
112
113                $meta = pipeline('ressource_meta',
114                        array(
115                                'args' => $res,
116                                'data' => $meta
117                        )
118                );
119               
120                /* chargement distant */
121                if (!isset($meta['html'])) {
122                        include_spip('inc/distant');
123                        if (!$local = copie_locale($src, 'test')
124                        AND !in_array($meta['extension'], array('mp3'))
125                        ) {
126                                include_spip('inc/queue');
127                                queue_add_job('copie_locale', 'copier', array($src), $file = 'inc/distant', $no_duplicate = true, $time=0, $priority=0);
128                        }
129                        if ($local = copie_locale($src, 'test')) {
130                                $meta['local'] = $local;
131                        }
132                }
133
134        }
135        // fichier dans IMG/ ?
136        else if (preg_match(',^[^/]+\.([^.]+)$,', $src, $r)
137        AND $h = _DIR_IMG.$r[1].'/'.$r[0]
138        AND @file_exists($h)
139        ) {
140                $meta['local'] = $h;
141                $meta['href'] = $h;
142        }
143
144        // si on l'a, renseigner ce qu'on peut dire du fichier
145        if (isset($meta['local'])
146        AND @file_exists($meta['local'])) {
147                $meta['extension'] = preg_replace(',^.*\.,', '', $meta['local']);
148                $meta['taille'] = @filesize($meta['local']);
149                if ($r = getimagesize($meta['local'])) {
150                        // donnees brutes du fichier
151                        $meta['width'] = $r[0];
152                        $meta['height'] = $r[1];
153                        $meta['largeur'] = $meta['width'];
154                        $meta['hauteur'] = $meta['height'];
155                }
156
157                if ($meta['extension'] == 'html') {
158                        // choper ce qu'on peut du html
159                        ressource_html($meta);
160                }
161
162                // extraire ses donnees !
163                if (!isset($meta['extract'])
164                AND $u = ressource_extract($meta)) {
165                        $meta['fullextract'] = $u;
166                        $meta['extract'] = propre(couper($u, 500));
167                }
168        }
169
170        // recupere le type mime de la ressource
171        if (isset($meta['extension']))
172                $meta['type_document'] = ressource_mime($meta['extension']);
173
174        return $meta;
175}
176
177// choper les trucs du genre meta opengraph ; meta description etc
178function ressource_html(&$meta) {
179
180        include_spip('fonctionsale');
181        if (function_exists('sale')) {
182                $u = sale(spip_file_get_contents($meta['local']));
183
184                $meta['fullextract'] = $u;
185                $meta['extract'] = propre(couper($u, 500));
186        }
187}
188
189function ressource_mime($e) {
190        global $tables_images, $tables_sequences, $tables_documents, $tables_mime, $mime_alias;
191        include_spip('base/typedoc');
192
193
194        $mime = $tables_mime[$e];
195        if (!$t = $tables_documents[$e]
196        AND !$t = $tables_images[$e]
197        AND !$t = $tables_sequences[$e])
198                $t = $e;
199
200        return $t;
201
202}
203
204/*
205 * recoit une chaine
206 * renvoie un array
207 * les valeurs par defaut sont mappees
208 * inspire de http://w-shadow.com/blog/2009/10/20/how-to-extract-html-tags-and-their-attributes-with-php/
209 */
210function phraser_tag($rr) {
211        $attribute_pattern =
212        '@
213        (
214        (?P<name>\w+)                    # attribute name
215        \s*=\s*
216        (
217            (?P<quote>[\"\'])(?P<value_quoted>.*?)(?P=quote)    # a quoted value
218            |                      # or
219            (?P<value_unquoted>[^\s"\']+?)(?:\s+)          # an unquoted value
220        )
221        |(?P<auto>\w+)
222        )
223        @xsiS';
224
225        // d'abord eliminer le type du tag et l'evntuelle fermeture auto
226        $res = array();
227        $rr = preg_replace(',^<\w+\s+,S', '', $rr);
228        $rr = preg_replace(',\s*/?'.'>$,S', ' ', $rr);
229
230        // ensuite parser le reste des attributs
231        preg_match_all($attribute_pattern, $rr, $z, PREG_SET_ORDER);
232
233        foreach($z as $t) {
234                if (isset($t['auto'])) {
235                        if (is_numeric($t['auto'])) # 200
236                                $res['width'] = $t['auto'];
237                        elseif (preg_match(',^\d+x\d+$,', $t['auto'])) # 200x300
238                                $res['geometry'] = $t['auto'];
239                        else
240                                $res[$t['auto']] = $t['auto'];
241                }
242                elseif (isset($t['value_unquoted'])) {
243                        $res[$t['name']] = $t['value_unquoted'];
244                }
245                elseif (isset($t['value_quoted'])) {
246                        $res[$t['name']] = $t['value_quoted'];
247                }
248        }
249
250        return $res;
251}
252
253function embed_ressource($res) {
254        // si la ressource est un document, renvoyer <doc1>
255        if (isset($res['id_document'])) {
256#               return recuperer_fond('modeles/doc', $res);
257        }
258
259        return
260#               "<pre>".var_export($res,true)."</pre>" .
261                recuperer_fond('modeles/ressource', $res);
262}
263
264/* ici c'est flou… */
265function ressource_image($attrs, $meta) {
266        $image = array();
267
268        // creer une vignette pour le doc ; si une largeur est exigee,
269        // adapter la taille.
270        if ($attrs['largeur'] OR $attrs['hauteur']) {
271                $resize = true;
272        }
273        // size
274        else {
275                if (!$attrs['size']) {
276                        if ($attrs['image']) # ???? c'est quoi ? le mode ?
277                                $attrs['size'] = 'd'; # ??? default
278                        else
279                                $attrs['size'] = 'd'; #
280                }
281                if (in_array($meta['extension'], array('gif', 'png', 'jpg'))) {
282                        $a = image_stdsize($attrs['src'], $attrs['size']);
283                        $resize = true;
284                }
285        }
286
287        // Verifier d'abord si le parametre 'icon' force l'icon
288# todo : icone => icon
289        if ($attrs['icon']) {
290                $f = charger_fonction('vignette','inc');
291                $img = $f($meta['extension'], false);
292                if ($resize)
293                        $a = image_reduire($img, $attrs['largeur'], $attrs['hauteur']);
294                else
295                        $a = '<img src="'.$img.'" />';
296
297        }
298        // methode normale : reduire l'image si possible, sinon icon
299        else {
300                if (!$a) {
301                        $w = sinon($attrs['largeur'],500);
302                        $h = sinon($attrs['hauteur'],700);
303                        $a = vignette_automatique($meta['id_vignette'], $meta,
304                                '' /*url*/, $w, $h, null /* align */);
305                }
306        }
307        $image['logodocument'] = $a;
308
309
310        // experimental : DEST (TODO: parametre à mieux nommer ?)
311        // parametre |dest=800 pour reduire l'image LIEE a 800px max
312        if ($attrs['dest']) {
313                $tmp = image_reduire($meta['local'], $attrs['dest']);
314                if ($tmp = extraire_attribut($tmp, 'src'))
315                        $image['href'] = $tmp;
316        }
317
318        return $image;
319}
320
321
322
323
324# s t m d z b o
325function image_stdsize($img, $s) {
326        include_spip('inc/filtres_images');
327
328        # intercepter les URLs flickr pour choper les jolies reductions
329        if (preg_match(',^(http://farm.*.staticflickr.com/(\d+/[0-9a-z_]+?))(_[zbo])?\.jpg$,', $img, $r)) {
330                if (in_array($s, array('s', 't', 'm', 'z', 'b') )){
331                        $img = $r[1].'_'.$s.'.jpg';
332                        return '<img src="'.$img.'" />';
333                }
334                if (in_array($s, array('d'))) {
335                        $img = $r[1].'.jpg';
336                        return '<img src="'.$img.'" />';
337                }
338        }
339
340
341
342        if (!is_numeric($s)) {
343        switch($s) {
344                case 's':
345                case 'square':
346                        # la c'est dur
347                        $d = 75;
348                        $img = image_passe_partout($img, $d, $d);
349                        $img = image_recadre($img, $d, $d);
350                        break;
351                case 't':
352                case 'thumb':
353                case 'thumbnail':
354                        $a = 100;
355                        break;
356                case 'm':
357                case 'small':
358                        $a = 240;
359                        break;
360                case 'z':
361                case 'medium640':
362                        $a = 640;
363                        break;
364                case 'b':
365                case 'large':
366                        $a = 1024;
367                        break;
368                case 'o':
369                case 'original':
370                        $a = null;
371                        break;
372                case '-':
373                case '':
374                case 'd':
375                case 'default':
376                default:
377                        $a = 500;
378                        break;
379        }
380        }
381
382        if ($a)
383                $img = image_reduire($img, $a);
384        else if (is_numeric($s))
385                $img = image_reduire($img, $s);
386
387        return $img;
388}
389
390
391
392function ressource_extract($meta) {
393        /*
394
395        global $extracteur;
396
397        $extension = $meta['extension'];
398
399        include_spip('extract/'.$extension);
400        if (function_exists($lire = $extracteur[$extension])) {
401                $charset = 'iso-8859-1';
402                $contenu = $lire($meta['local'], $charset);
403                var_dump($lire, $contenu);
404        }
405        */
406
407        switch($meta['extension']) {
408                case 'html':
409                case 'doc':
410                case 'docx':
411                case 'rtf':
412                case 'odt':
413                        $conv = converthtml($meta['local'], $err);
414                        include_spip('fonctionsale');
415                        if (function_exists('sale')) {
416                                $conv = sale($conv);
417                        }
418                        break;
419                default:
420                        break;
421        }
422
423        return $conv;
424}
425
426/**
427* Multiple Curl Handlers
428* @author Jorge Hebrard ( jorge.hebrard@gmail.com )
429**/
430class curlNode{
431    static private $listenerList;
432    private $callback;
433    public function __construct($url){
434        $new =& self::$listenerList[];
435        $new['url'] = $url;
436        $this->callback =& $new;
437    }
438    /**
439    * Callbacks needs 3 parameters: $url, $html (data of the url), and $lag (execution time)
440    **/
441    public function addListener($callback){
442        $this->callback['callback'] = $callback;
443    }
444    /**
445    * curl_setopt() wrapper. Enjoy!
446    **/
447    public function setOpt($key,$value){
448        $this->callback['opt'][$key] = $value;
449    }
450    /**
451    * Request all the created curlNode objects, and invoke associated callbacks.
452    **/
453    static public function request(){
454   
455        //create the multiple cURL handle
456        $mh = curl_multi_init();
457       
458        $running=null;
459       
460        # Setup all curl handles
461        # Loop through each created curlNode object.
462        foreach(self::$listenerList as &$listener){
463            $url = $listener['url'];
464            $current =& $ch[];
465           
466            # Init curl and set default options.
467            # This can be improved by creating
468            $current = curl_init();
469
470            curl_setopt($current, CURLOPT_URL, $url);
471            # Since we don't want to display multiple pages in a single php file, do we?
472            curl_setopt($current, CURLOPT_HEADER, 0);
473            curl_setopt($current, CURLOPT_RETURNTRANSFER, 1);
474           
475            # Set defined options, set through curlNode->setOpt();
476            if (isset($listener['opt'])){
477                foreach($listener['opt'] as $key => $value){
478                    curl_setopt($current, $key, $value);
479                }
480            }
481           
482            curl_multi_add_handle($mh,$current);
483           
484            $listener['handle'] = $current;
485            $listener['start'] = microtime(1);
486        } unset($listener);
487
488        # Main loop execution
489        do {
490            # Exec until there's no more data in this iteration.
491            # This function has a bug, it
492            while(($execrun = curl_multi_exec($mh, $running)) == CURLM_CALL_MULTI_PERFORM);
493            if($execrun != CURLM_OK) break; # This should never happen. Optional line.
494           
495            # Get information about the handle that just finished the work.
496            while($done = curl_multi_info_read($mh)) {
497                # Call the associated listener
498                foreach(self::$listenerList as $listener){
499                    # Strict compare handles.
500                    if ($listener['handle'] === $done['handle']) {
501                        # Get content
502                        $html = curl_multi_getcontent($done['handle']);
503                        # Call the callback.
504                        call_user_func($listener['callback'],
505                        $listener['url'],
506                        $html,(microtime(1)-$listener['start']));
507                        # Remove unnecesary handle (optional, script works without it).
508                        curl_multi_remove_handle($mh, $done['handle']);
509                    }
510                }
511               
512            }
513            # Required, or else we would end up with a endless loop.
514            # Without it, even when the connections are over, this script keeps running.
515            if (!$running) break;
516           
517            # I don't know what these lines do, but they are required for the script to work.
518            while (($res = curl_multi_select($mh)) === 0);
519            if ($res === false) break; # Select error, should never happen.
520        } while (true);
521
522        # Finish out our script ;)
523        curl_multi_close($mh);
524   
525    }
526}
527
528function converthtml($f, $err) {
529        define('_CONVERT_URL', 'http://office.rezo.net/office/v1/?email=fil@rezo.net&key=1223649b375bb98e1b57141f96643cd47a3029c3');
530
531        $signature = md5_file($f);
532
533        // 1. a-t-on le fichier en local
534        $html = sous_repertoire(_DIR_TMP,'converthtml').$signature.'.html';
535        if (file_exists($html))
536                return spip_file_get_contents($html);
537
538        // 2. sinon le chercher sur le serveur office.rezo
539        if (!defined('_CONVERT_URL'))
540                return false;
541
542        $url = parametre_url(_CONVERT_URL, 'signature', $signature, '&');
543
544        include_spip('inc/queue');
545        queue_add_job('convert_html_fetch', 'convert_html_fetch('.$f.')', array($url, $f, $html), $file = 'inc/ressource', $no_duplicate = true, $time=0, $priority=0);
546        #convert_html_fetch($url, $f);
547
548        return '';
549}
550
551function convert_html_fetch($url, $f, $html=null) {
552        if (!$html) return;
553        include_spip('inc/distant');
554        if ($rep = recuperer_page($url)
555        AND $rep = json_decode($rep)
556        AND isset($rep->content)) {
557                ecrire_fichier($html, $rep->content);
558                return;
559        }
560       
561
562        // 3. si 404, l'envoyer au serveur
563        #include_spip('inc/queue');
564        #queue_add_job('convert_html_send', 'convert_html_send('.$f.')', array($url, $f), $file = 'inc/ressource', $no_duplicate = true, $time=0, $priority=0);
565        convert_html_send($url, $f);
566
567}
568
569function convert_html_send($url, $f) {
570        include_spip('inc/filtres');
571        spip_log('curl @'.$f.' '.$url.' ('.taille_en_octets(filesize($f)).')');
572        $data = array('file' => '@'.$f);
573        $ch = curl_init();
574        curl_setopt($ch, CURLOPT_VERBOSE, 1);
575        curl_setopt($ch, CURLOPT_URL, $url);
576        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
577        curl_setopt($ch, CURLOPT_POST, true);
578        curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
579        $n = curl_exec($ch);
580        spip_log($n);
581        curl_close($ch);
582}
583
584
585function xconverthtml($f, &$err) {
586
587
588        $k = escapeshellarg($f);
589
590        exec("/usr/bin/textutil -convert html -stdout -noload -nostore $k", $ret, $err);
591
592        if ($err) {
593                spip_log($err);
594        } else {
595                $ret = join($ret, "\n");
596                // les notes de bas de page word sont parfois transformees en truc chelou
597                $ret = str_replace('<span class="Apple-converted-space"> </span>', '~', $ret);
598                return nettoyer_utf8($ret);
599        }
600}
601
602function nettoyer_utf8($t) {
603        if (!preg_match('!\S!u', $t))
604                $t = preg_replace_callback(',&#x([0-9a-f]+);,i', 'utf8_do', utf8_encode(utf8_decode($t)));
605        return $t;
606}
Note: See TracBrowser for help on using the repository browser.