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

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

version 1.6.9 : prise en charge des embeds facebook

File size: 12.3 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*'             => 'http://www.youtube.com/oembed',
28                'http://*.youtube.com/playlist*'          => 'http://www.youtube.com/oembed',
29                'http://youtu.be/*'                       => 'http://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/*'                 => 'http://soundcloud.com/oembed',
38                'http://mixcloud.com/*'                   => 'http://mixcloud.com/oembed',
39                'http://*.soundcloud.com/*'               => 'http://soundcloud.com/oembed',
40                'http://*.mixcloud.com/*'                 => 'http://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/*'                  => 'http://api.smugmug.com/services/oembed/',
55                'http://meetup.com/*'                     => 'http://api.meetup.com/oembed',
56                'http://meetup.ps/*'                      => 'http://api.meetup.com/oembed',
57                'http://*.wordpress.com/*'                => 'http://public-api.wordpress.com/oembed/1.0/',
58                'http://twitter.com/*/status/*'           => 'https://publish.twitter.com/oembed',
59                'http://techcrunch.com/*'                 => 'http://public-api.wordpress.com/oembed/1.0/',
60                'http://wp.me/*'                          => 'http://public-api.wordpress.com/oembed/1.0/',
61                'http://my.opera.com/*'                   => 'http://my.opera.com/service/oembed',
62                'http://www.collegehumor.com/video/*'     => 'http://www.collegehumor.com/oembed.json',
63                'http://imgur.com/*'                      => 'http://api.imgur.com/oembed',
64                'http://*.imgur.com/*'                    => 'http://api.imgur.com/oembed',
65                'http://*.onf.ca/*'                       => 'http://www.onf.ca/remote/services/oembed/',
66                'http://vine.co/v/*'                      => 'https://vine.co/oembed.json',
67                'http://*.tumblr.com/post/*'              => 'https://www.tumblr.com/oembed/1.0',
68                'http://*.kickstarter.com/projects/*'     => 'https://www.kickstarter.com/services/oembed',
69                'http://speakerdeck.com/*'                => 'https://speakerdeck.com/oembed.json',
70                'http://issuu.com/*'                      => 'http://issuu.com/oembed',
71                'http://www.facebook.com/*/posts/*'       => 'https://www.facebook.com/plugins/post/oembed.json/',
72                'http://www.facebook.com/*/activity/*'    => 'https://www.facebook.com/plugins/post/oembed.json/',
73                'http://www.facebook.com/*/photos/*'      => 'https://www.facebook.com/plugins/post/oembed.json/',
74                'http://www.facebook.com/media/*'         => 'https://www.facebook.com/plugins/post/oembed.json/',
75                'http://www.facebook.com/questions/*'     => 'https://www.facebook.com/plugins/post/oembed.json/',
76                'http://www.facebook.com/notes/*'         => 'https://www.facebook.com/plugins/post/oembed.json/',
77                'http://www.facebook.com/*/videos/*'      => 'https://www.facebook.com/plugins/video/oembed.json/',
78
79                'http://egliseinfo.catholique.fr/*'       => 'http://egliseinfo.catholique.fr/api/oembed',
80
81                #'https://gist.github.com/*' => 'http://github.com/api/oembed?format=json'
82        );
83
84        // pipeline pour permettre aux plugins d'ajouter/supprimer/modifier des providers
85        $providers = pipeline('oembed_lister_providers', $providers);
86
87        // merger avec la globale pour perso mes_options dans un site
88        // pour supprimer un scheme il suffit de le renseigner avec un endpoint vide
89        if (isset($GLOBALS['oembed_providers'])) {
90                $providers = array_merge($providers, $GLOBALS['oembed_providers']);
91                // retirer les providers avec un endpoint vide
92                $providers = array_filter($providers);
93        }
94
95        return $providers;
96}
97
98// Merci WordPress :)
99// http://core.trac.wordpress.org/browser/trunk/wp-includes/class-oembed.php
100
101/**
102 * Récupérer les données oembed d'une url
103 *
104 * @param string $url url de la page qui contient le document à récupérer avec oembed
105 * @param int $maxwidth largeur max du document
106 *   null : la valeur configuree par defaut ou pour le provider est utilisee
107 *   '' : pas de valeur max
108 * @param int $maxheight hauteur max du document
109 *   null : la valeur configuree par defaut ou pour le provider est utilisee
110 *   '' : pas de valeur max
111 * @param string $format format à utiliser pour la requete oembed (json ou xml)
112 * @param string $detecter_lien tenter la détection automatique de lien oembed dans la page indiquée
113 * @return bool|array false si aucun retour ou erreur ; tableau des éléménents de la réponse oembed
114 */
115function oembed_recuperer_data($url, $maxwidth = null, $maxheight = null, $format = 'json', $detecter_lien = 'non') {
116        static $cache = array();
117        $provider = false;
118
119        $provider = oembed_verifier_provider($url);
120
121        if ((!$provider)
122                and (($detecter_lien != 'non')
123                or lire_config('oembed/detecter_lien', 'non') == 'oui')) {
124                $provider = oembed_detecter_lien($url);
125        }
126
127        if (!$provider) {
128                return false;
129        }
130
131        $data_url = parametre_url(url_absolue($provider['endpoint'], url_de_base()), 'url', $url, '&');
132        include_spip('inc/config');
133        if (!$maxwidth) {
134                $maxwidth = lire_config('oembed/maxwidth', '600');
135        }
136        if (!$maxheight) {
137                $maxheight = lire_config('oembed/maxheight', '400');
138        }
139
140        $data_url = parametre_url($data_url, 'maxwidth', $maxwidth, '&');
141        $data_url = parametre_url($data_url, 'maxheight', $maxheight, '&');
142        $data_url = parametre_url($data_url, 'format', $format, '&');
143
144        // pre-traitement du provider si besoin
145        $endpoint = explode('//', $provider['endpoint']);
146        $endpoint = explode('/', $endpoint[1]);
147        $endpoint = reset($endpoint);
148        $endpoint = preg_replace(',\W+,', '_', $endpoint);
149        if ($oembed_endpoint_pretraite = charger_fonction("pretraite_$endpoint", 'oembed/input', true)) {
150                $a = func_get_args();
151                $args = array('url'=>array_shift($a));
152                if (count($a)) {
153                        $args['maxwidth'] = array_shift($a);
154                }
155                if (count($a)) {
156                        $args['maxheight'] = array_shift($a);
157                }
158                if (count($a)) {
159                        $args['format'] = array_shift($a);
160                }
161                $data_url = $oembed_endpoint_pretraite($data_url, $args);
162        }
163
164        if (isset($cache[$data_url])) {
165                return $cache[$data_url];
166        }
167
168        $oembed_cache = sous_repertoire(_DIR_CACHE, 'oembed').md5($data_url). '.'.$format;
169        // si cache oembed dispo et pas de recalcul demande, l'utiliser (perf issue)
170        if (file_exists($oembed_cache) and _VAR_MODE !== 'recalcul') {
171                lire_fichier($oembed_cache, $cache[$data_url]);
172                $cache[$data_url]=unserialize($cache[$data_url]);
173                return $cache[$data_url];
174        }
175
176        $oembed_recuperer_url = charger_fonction('oembed_recuperer_url', 'inc');
177        $cache[$data_url] = $oembed_recuperer_url($data_url, $url, $format);
178
179        // si une fonction de post-traitement est fourni pour ce provider+type, l'utiliser
180        if ($cache[$data_url]) {
181                $provider_name= str_replace(' ', '_', strtolower($cache[$data_url]['provider_name']));
182                $type = strtolower($cache[$data_url]['type']);
183                // securisons le nom de la fonction (provider peut contenir n'importe quoi)
184                $f1 = preg_replace(',\W,', '', "posttraite_{$provider_name}_$type");
185                $f2 = preg_replace(',\W,', '', "posttraite_{$provider_name}");
186                if ($oembed_provider_posttraite = charger_fonction($f1, 'oembed/input', true)
187                        or $oembed_provider_posttraite = charger_fonction($f2, 'oembed/input', true)) {
188                        $cache[$data_url] = $oembed_provider_posttraite($cache[$data_url], $url);
189                }
190
191                ecrire_fichier($oembed_cache, serialize($cache[$data_url]));
192        }
193        spip_log('infos oembed pour '.$url.' : '.var_export($cache[$data_url], true), 'oembed.'._LOG_DEBUG);
194
195        return $cache[$data_url];
196}
197
198/**
199 * Vérfier qu'une url est dans la liste des providers autorisés
200 *
201 * @param string $url l'url à tester
202 * @return bool|array
203 *   false si non ; details du provider dans un tabeau associatif si oui
204 */
205function oembed_verifier_provider($url) {
206        if (strncmp($url, $GLOBALS['meta']['adresse_site'], strlen($GLOBALS['meta']['adresse_site'])) == 0) {
207                return false;
208        }
209        $providers = oembed_lister_providers();
210        foreach ($providers as $scheme => $endpoint) {
211                $regex = '#' . str_replace('\*', '(.+)', preg_quote($scheme, '#')) . '#';
212                $regex = preg_replace('|^#http\\\://|', '#https?\://', $regex);
213                if (preg_match($regex, $url)) {
214                        return array('endpoint' => $endpoint);
215                }
216        }
217        return false;
218}
219
220/**
221 * Détecter les liens oembed dans le head d'une page web
222 *
223 * @param string $url url de la page à analyser
224 * @return bool|string false si pas de lien ; url du contenu oembed
225 */
226function oembed_detecter_lien($url) {
227        $providers = array();
228
229        // on recupere le contenu de la page
230        include_spip('inc/distant');
231        if ($html = recuperer_page($url)) {
232                // types de liens oembed à détecter
233                $linktypes = array(
234                        'application/json+oembed' => 'json',
235                        'text/json+oembed' => 'json', // ex de 500px
236                        'text/xml+oembed' => 'xml',
237                        'application/xml+oembed' => 'xml', // uniquement pour Vimeo
238                );
239
240                // on ne garde que le head de la page
241                $head = substr($html, 0, stripos($html, '</head>'));
242
243                // un test rapide...
244                $tagfound = false;
245                foreach ($linktypes as $linktype => $format) {
246                        if (stripos($head, $linktype)) {
247                                $tagfound = true;
248                                break;
249                        }
250                }
251
252                if ($tagfound && preg_match_all('/<link([^<>]+)>/i', $head, $links)) {
253                        foreach ($links[0] as $link) {
254                                $type = extraire_attribut($link, 'type');
255                                $href = extraire_attribut($link, 'href');
256                                if (!empty($type) and !empty($linktypes[$type]) and !empty($href)) {
257                                        $providers[$linktypes[$type]] = $href;
258                                        // on a le json, ça nous suffit
259                                        if ('json' == $linktypes[$type]) {
260                                                break;
261                                        }
262                                }
263                        }
264                }
265        }
266
267        // on préfère le json au xml
268        if (!empty($providers['json'])) {
269                return array('endpoint'=>$providers['json']);
270        } elseif (!empty($providers['xml'])) {
271                return array('endpoint' => $providers['xml']);
272        } else {
273                return false;
274        }
275}
276
277
278/**
279 * Embarquer un lien oembed si possible
280 * @param string $lien
281 * @return string
282 */
283function oembed_embarquer_lien($lien) {
284        static $base = null;
285
286        $url = extraire_attribut($lien, 'href');
287        $texte = null;
288        if ($url
289                and (
290                        oembed_verifier_provider($url)
291                        or (lire_config('oembed/detecter_lien', 'non') == 'oui'))
292                ) {
293                if (is_null($base)) {
294                        $base = url_de_base();
295                }
296                // on embarque jamais un lien de soi meme car c'est une mise en abime qui donne le tourni
297                // (et peut provoquer une boucle infinie de requetes http)
298                if (strncmp($url, $base, strlen($base)) != 0) {
299                        $fond = recuperer_fond('modeles/oembed', array('url' => $url, 'lien' => $lien));
300                        if ($fond = trim($fond)) {
301                                $texte = $fond;
302                        }
303                }
304        }
305
306        return $texte;
307}
Note: See TracBrowser for help on using the repository browser.