source: spip-zone/_plugins_/oembed/inc/oembed.php

Last change on this file was 108139, checked in by cedric@…, 10 months ago

Quand on essaye d'inserer une URL oembed dans l'upload de document il faut aller chercher les infos oembed a la source, sans utiliser le cache
(permet de recommencer l'upload si jamais le provider n'a pas repondu le premier coup, car sinon on retombait a chaque fois sur le cache vide et c'etait mort)

File size: 13.8 KB
Line 
1<?php
2/**
3 * Plugin oEmbed
4 * Licence GPL3
5 *
6 */
7
8if (!defined('_ECRIRE_INC_VERSION')) {
9        return;
10}
11
12/**
13 * Lister les providers connus
14 * @return array
15 */
16function oembed_lister_providers() {
17
18        // liste des providers par defaut
19
20        // voir
21        // http://oembed.com/
22        // http://code.google.com/p/oohembed/source/browse/app/provider/endpoints.json
23        // https://github.com/starfishmod/jquery-oembed-all/blob/master/jquery.oembed.js
24        // https://github.com/panzi/oembedendpoints/blob/master/endpoints-simple.json
25        // voir aussi http://embed.ly/providers qui donne les scheme mais pas les endpoint
26        $providers = array(
27                'http://*.youtube.com/watch*'             => 'https://www.youtube.com/oembed',
28                'http://*.youtube.com/playlist*'          => 'https://www.youtube.com/oembed',
29                'http://youtu.be/*'                       => 'https://www.youtube.com/oembed',
30                'http://*.vimeo.com/*'                    => 'https://vimeo.com/api/oembed.json',
31                'http://vimeo.com/*'                      => 'https://vimeo.com/api/oembed.json',
32                'http://*.dailymotion.com/*'              => 'https://www.dailymotion.com/services/oembed',
33                'http://dai.ly/*'                         => 'https://www.dailymotion.com/services/oembed',
34                'http://*.flickr.com/*'                   => 'https://www.flickr.com/services/oembed/',
35                'http://flickr.com/*'                     => 'https://www.flickr.com/services/oembed/',
36                'http://flic.kr/*'                        => 'https://www.flickr.com/services/oembed/',
37                'http://soundcloud.com/*'                 => 'https://soundcloud.com/oembed',
38                'http://mixcloud.com/*'                   => 'https://mixcloud.com/oembed',
39                'http://*.soundcloud.com/*'               => 'https://soundcloud.com/oembed',
40                'http://*.mixcloud.com/*'                 => 'https://mixcloud.com/oembed',
41                'http://*.slideshare.net/*/*'             => 'https://www.slideshare.net/api/oembed/2',
42                'http://www.slideshare.net/*/*'           => 'https://www.slideshare.net/api/oembed/2',
43                'http://instagr.am/*'                     => 'https://api.instagram.com/oembed',
44                'http://*.instagr.am/*'                   => 'https://api.instagram.com/oembed',
45                'http://instagram.com/*'                  => 'https://api.instagram.com/oembed',
46                'http://*.instagram.com/*'                => 'https://api.instagram.com/oembed',
47                'http://huffduffer.com/*/*'               => 'http://huffduffer.com/oembed',
48                'http://nfb.ca/film/*'                    => 'http://www.nfb.ca/remote/services/oembed/',
49                'http://dotsub.com/view/*'                => 'http://dotsub.com/services/oembed',
50                'http://clikthrough.com/theater/video/*'  => 'http://clikthrough.com/services/oembed',
51                'http://kinomap.com/*'                    => 'http://www.kinomap.com/oembed',
52                'http://photobucket.com/albums/*'         => 'http://api.photobucket.com/oembed',
53                'http://photobucket.com/groups/*'         => 'http://api.photobucket.com/oembed',
54                'http://*.smugmug.com/*'                  => 'https://api.smugmug.com/services/oembed/',
55                'http://meetup.com/*'                     => 'https://api.meetup.com/oembed',
56                'http://meetup.ps/*'                      => 'http://api.meetup.com/oembed',
57                'http://*.wordpress.com/*'                => 'https://public-api.wordpress.com/oembed/1.0/',
58                'http://twitter.com/*/status/*'           => 'https://publish.twitter.com/oembed',
59                'http://twitter.com/*/likes'              => 'https://publish.twitter.com/oembed',
60                'http://twitter.com/*/lists/*'            => 'https://publish.twitter.com/oembed',
61                'http://twitter.com/*/timelines/*'        => 'https://publish.twitter.com/oembed',
62                'http://twitter.com/i/moments/*'          => 'https://publish.twitter.com/oembed',
63                'http://techcrunch.com/*'                 => 'http://public-api.wordpress.com/oembed/1.0/',
64                'http://wp.me/*'                          => 'http://public-api.wordpress.com/oembed/1.0/',
65                'http://my.opera.com/*'                   => 'http://my.opera.com/service/oembed',
66                'http://www.collegehumor.com/video/*'     => 'http://www.collegehumor.com/oembed.json',
67                'http://imgur.com/*'                      => 'http://api.imgur.com/oembed',
68                'http://*.imgur.com/*'                    => 'http://api.imgur.com/oembed',
69                'http://*.onf.ca/*'                       => 'http://www.onf.ca/remote/services/oembed/',
70                'http://vine.co/v/*'                      => 'https://vine.co/oembed.json',
71                'http://*.tumblr.com/post/*'              => 'https://www.tumblr.com/oembed/1.0',
72                'http://*.kickstarter.com/projects/*'     => 'https://www.kickstarter.com/services/oembed',
73                'http://speakerdeck.com/*'                => 'https://speakerdeck.com/oembed.json',
74                'http://issuu.com/*'                      => 'https://issuu.com/oembed',
75                'http://www.facebook.com/*/posts/*'       => 'https://www.facebook.com/plugins/post/oembed.json/',
76                'http://www.facebook.com/*/activity/*'    => 'https://www.facebook.com/plugins/post/oembed.json/',
77                'http://www.facebook.com/*/photos/*'      => 'https://www.facebook.com/plugins/post/oembed.json/',
78                'http://www.facebook.com/media/*'         => 'https://www.facebook.com/plugins/post/oembed.json/',
79                'http://www.facebook.com/questions/*'     => 'https://www.facebook.com/plugins/post/oembed.json/',
80                'http://www.facebook.com/notes/*'         => 'https://www.facebook.com/plugins/post/oembed.json/',
81                'http://www.facebook.com/*/videos/*'      => 'https://www.facebook.com/plugins/video/oembed.json/',
82
83                'http://egliseinfo.catholique.fr/*'       => 'http://egliseinfo.catholique.fr/api/oembed',
84
85                #'https://gist.github.com/*' => 'http://github.com/api/oembed?format=json'
86        );
87
88        // pipeline pour permettre aux plugins d'ajouter/supprimer/modifier des providers
89        $providers = pipeline('oembed_lister_providers', $providers);
90
91        // merger avec la globale pour perso mes_options dans un site
92        // pour supprimer un scheme il suffit de le renseigner avec un endpoint vide
93        if (isset($GLOBALS['oembed_providers'])) {
94                $providers = array_merge($providers, $GLOBALS['oembed_providers']);
95                // retirer les providers avec un endpoint vide
96                $providers = array_filter($providers);
97        }
98
99        return $providers;
100}
101
102// Merci WordPress :)
103// http://core.trac.wordpress.org/browser/trunk/wp-includes/class-oembed.php
104
105/**
106 * Récupérer les données oembed d'une url
107 *
108 * @param string $url url de la page qui contient le document à récupérer avec oembed
109 * @param int $maxwidth largeur max du document
110 *   null : la valeur configuree par defaut ou pour le provider est utilisee
111 *   '' : pas de valeur max
112 * @param int $maxheight hauteur max du document
113 *   null : la valeur configuree par defaut ou pour le provider est utilisee
114 *   '' : pas de valeur max
115 * @param string $format format à utiliser pour la requete oembed (json ou xml)
116 * @param string $detecter_lien tenter la détection automatique de lien oembed dans la page indiquée
117 * @param bool $force_reload forcer le rechargement de l'oembed depuis la source sans utiliser le cache local
118 * @return bool|array false si aucun retour ou erreur ; tableau des éléménents de la réponse oembed
119 */
120function oembed_recuperer_data($url, $maxwidth = null, $maxheight = null, $format = 'json', $detecter_lien = 'non', $force_reload = false) {
121        static $cache = array();
122        $provider = false;
123
124        $provider = oembed_verifier_provider($url);
125        if ((!$provider)
126                and (($detecter_lien != 'non')
127                or lire_config('oembed/detecter_lien', 'non') == 'oui')) {
128                $provider = oembed_detecter_lien($url);
129        }
130
131        if (!$provider) {
132                return false;
133        }
134
135        $data_url = url_absolue($provider['endpoint'], url_de_base());
136        // certains oembed fournissent un endpoint qui contient deja l'URL, parfois differente de celle de la page
137        if (!parametre_url($data_url, 'url')) {
138                $data_url = parametre_url($data_url, 'url', $url, '&');
139        }
140
141        include_spip('inc/config');
142        if (!$maxwidth) {
143                $maxwidth = lire_config('oembed/maxwidth', '600');
144        }
145        if (!$maxheight) {
146                $maxheight = lire_config('oembed/maxheight', '400');
147        }
148
149        $data_url = parametre_url($data_url, 'maxwidth', $maxwidth, '&');
150        $data_url = parametre_url($data_url, 'maxheight', $maxheight, '&');
151        $data_url = parametre_url($data_url, 'format', $format, '&');
152
153        if (isset($provider['provider_name']) and $provider['provider_name']) {
154                $provider_name = $provider['provider_name'];
155        }
156        else {
157                // pre-traitement du provider si besoin
158                $provider_name = explode('//', $provider['endpoint']);
159                $provider_name = explode('/', $provider_name[1]);
160                $provider_name = reset($provider_name);
161        }
162        $provider_name = preg_replace(',\W+,', '_', strtolower($provider_name));
163        if ($oembed_endpoint_pretraite = charger_fonction("pretraite_$provider_name", 'oembed/input', true)) {
164                $a = func_get_args();
165                $args = array('url'=>array_shift($a));
166                if (count($a)) {
167                        $args['maxwidth'] = array_shift($a);
168                }
169                if (count($a)) {
170                        $args['maxheight'] = array_shift($a);
171                }
172                if (count($a)) {
173                        $args['format'] = array_shift($a);
174                }
175                $args['endpoint'] = $provider['endpoint'];
176                $data_url = $oembed_endpoint_pretraite($data_url, $args);
177        }
178
179        if (isset($cache[$data_url])) {
180                return $cache[$data_url];
181        }
182
183        $oembed_cache = sous_repertoire(_DIR_CACHE, 'oembed').md5($data_url). '.'.$format;
184        // si cache oembed dispo et pas de recalcul demande, l'utiliser (perf issue)
185        if (!$force_reload and file_exists($oembed_cache) and _VAR_MODE !== 'recalcul') {
186                lire_fichier($oembed_cache, $cache[$data_url]);
187                $cache[$data_url]=unserialize($cache[$data_url]);
188                return $cache[$data_url];
189        }
190
191        $oembed_recuperer_url = charger_fonction('oembed_recuperer_url', 'inc');
192        $cache[$data_url] = $oembed_recuperer_url($data_url, $url, $format);
193        // si une fonction de post-traitement est fourni pour ce provider+type, l'utiliser
194        if ($cache[$data_url]) {
195                $provider_name2= str_replace(' ', '_', strtolower($cache[$data_url]['provider_name']));
196                $type = strtolower($cache[$data_url]['type']);
197                // securisons le nom de la fonction (provider peut contenir n'importe quoi)
198                $f1 = preg_replace(',\W,', '', "posttraite_{$provider_name2}_$type");
199                $f2 = preg_replace(',\W,', '', "posttraite_{$provider_name2}");
200                $f3 = preg_replace(',\W,', '', "posttraite_{$provider_name}_$type");
201                $f4 = preg_replace(',\W,', '', "posttraite_{$provider_name}");
202                if (
203                        $oembed_provider_posttraite = charger_fonction($f1, 'oembed/input', true)
204                        or $oembed_provider_posttraite = charger_fonction($f2, 'oembed/input', true)
205                        or $oembed_provider_posttraite = charger_fonction($f3, 'oembed/input', true)
206                        or $oembed_provider_posttraite = charger_fonction($f4, 'oembed/input', true) ) {
207                        $cache[$data_url] = $oembed_provider_posttraite($cache[$data_url], $url);
208                }
209                ecrire_fichier($oembed_cache, serialize($cache[$data_url]));
210        }
211        spip_log('infos oembed pour '.$url.' : '.var_export($cache[$data_url], true), 'oembed.'._LOG_DEBUG);
212
213        return $cache[$data_url];
214}
215
216/**
217 * Vérfier qu'une url est dans la liste des providers autorisés
218 *
219 * @param string $url l'url à tester
220 * @return bool|array
221 *   false si non ; details du provider dans un tabeau associatif si oui
222 */
223function oembed_verifier_provider($url) {
224        if (strncmp($url, $GLOBALS['meta']['adresse_site'], strlen($GLOBALS['meta']['adresse_site'])) == 0) {
225                return false;
226        }
227        $providers = oembed_lister_providers();
228        foreach ($providers as $scheme => $endpoint) {
229                $regex = '#' . str_replace('\*', '(.+)', preg_quote($scheme, '#')) . '#';
230                $regex = preg_replace('|^#http\\\://|', '#https?\://', $regex);
231                if (preg_match($regex, $url)) {
232                        return array('endpoint' => $endpoint);
233                }
234        }
235        return false;
236}
237
238/**
239 * Détecter les liens oembed dans le head d'une page web
240 *
241 * @param string $url url de la page à analyser
242 * @return bool|string false si pas de lien ; url du contenu oembed
243 */
244function oembed_detecter_lien($url) {
245        $providers = array();
246
247        $oembed_recuperer_url = charger_fonction('oembed_recuperer_url', 'inc');
248        // on recupere le contenu de la page
249        if ($html = $oembed_recuperer_url($url, $url, 'html')) {
250                // types de liens oembed à détecter
251                $linktypes = array(
252                        'application/json+oembed' => 'json',
253                        'text/json+oembed' => 'json', // ex de 500px
254                        'text/xml+oembed' => 'xml',
255                        'application/xml+oembed' => 'xml', // uniquement pour Vimeo
256                );
257
258                // on ne garde que le head de la page
259                $head = substr($html, 0, stripos($html, '</head>'));
260
261                // un test rapide...
262                $tagfound = false;
263                foreach ($linktypes as $linktype => $format) {
264                        if (stripos($head, $linktype)) {
265                                $tagfound = true;
266                                break;
267                        }
268                }
269
270                if ($tagfound && preg_match_all('/<link([^<>]+)>/i', $head, $links)) {
271                        foreach ($links[0] as $link) {
272                                $type = extraire_attribut($link, 'type');
273                                $href = extraire_attribut($link, 'href');
274                                if (!empty($type) and !empty($linktypes[$type]) and !empty($href)) {
275                                        $providers[$linktypes[$type]] = $href;
276                                        // on a le json, ça nous suffit
277                                        if ('json' == $linktypes[$type]) {
278                                                break;
279                                        }
280                                }
281                        }
282                }
283        }
284
285        $res = array();
286
287        // on préfère le json au xml
288        if (!empty($providers['json'])) {
289                $res['endpoint'] = $providers['json'];
290        } elseif (!empty($providers['xml'])) {
291                $res['endpoint'] = $providers['xml'];
292        } else {
293                return false;
294        }
295
296        // detecter certains providers specifiques : ex mastodon, chaque instance a son nom et on peut pas l'identifier par son URL
297        if (strpos($html, '//github.com/tootsuite/mastodon') !== false or strpos($html, '//joinmastodon.org') !== false) {
298                $res['provider_name'] = 'Mastodon';
299        }
300
301        return $res;
302}
303
304
305/**
306 * Embarquer un lien oembed si possible
307 * @param string $lien
308 * @return string
309 */
310function oembed_embarquer_lien($lien) {
311        static $base = null;
312
313        $url = extraire_attribut($lien, 'href');
314        $texte = null;
315        if ($url
316                and (
317                        oembed_verifier_provider($url)
318                        or (lire_config('oembed/detecter_lien', 'non') == 'oui'))
319                ) {
320                if (is_null($base)) {
321                        $base = url_de_base();
322                }
323                // on embarque jamais un lien de soi meme car c'est une mise en abime qui donne le tourni
324                // (et peut provoquer une boucle infinie de requetes http)
325                if (strncmp($url, $base, strlen($base)) != 0) {
326                        $fond = recuperer_fond('modeles/oembed', array('url' => $url, 'lien' => $lien));
327                        if ($fond = trim($fond)) {
328                                $texte = $fond;
329                        }
330                }
331        }
332
333        return $texte;
334}
Note: See TracBrowser for help on using the repository browser.