Compare commits

..

1 Commits

  1. 66
      .gitattributes
  2. 10
      .gitignore
  3. 40
      action/api_oembed.php
  4. 101
      action/oembed_nettoyer_iframes.php
  5. 20
      composer.json
  6. 6
      css/oembed.css
  7. 28
      formulaires/configurer_oembed.html
  8. 222
      inc/oembed.php
  9. 59
      inc/oembed_recuperer_url.php
  10. 24
      inc/ressource.php
  11. 3
      lang/oembed.xml
  12. 49
      lang/oembed_it.php
  13. 3
      lang/paquet-oembed.xml
  14. 15
      lang/paquet-oembed_it.php
  15. 6
      modeles/oembed.html
  16. 1
      modeles/oembed_fonctions.php
  17. 4
      modeles/oembed_link.html
  18. 6
      modeles/oembed_photo.html
  19. 6
      modeles/oembed_rich.html
  20. 8
      modeles/oembed_video.html
  21. 35
      modeles/text_oembed.html
  22. 4
      modeles/toot.html
  23. 9
      oembed/input/posttraite_api_arte_tv.php
  24. 41
      oembed/input/posttraite_facebook_video.php
  25. 1
      oembed/input/posttraite_huffduffer_rich.php
  26. 27
      oembed/input/posttraite_instagram_rich.php
  27. 1
      oembed/input/posttraite_issuu.php
  28. 44
      oembed/input/posttraite_mastodon.php
  29. 1
      oembed/input/posttraite_oeproxy_default_rich.php
  30. 1
      oembed/input/posttraite_oeproxy_imdb_rich.php
  31. 1
      oembed/input/posttraite_office_national_du_film_du_canada_video.php
  32. 1
      oembed/input/posttraite_rdio_rich.php
  33. 1
      oembed/input/posttraite_slideshare_rich.php
  34. 3
      oembed/input/posttraite_soundcloud_rich.php
  35. 163
      oembed/input/posttraite_twitter.php
  36. 45
      oembed/input/posttraite_vimeo_video.php
  37. 19
      oembed/input/posttraite_youtube_video.php
  38. 1
      oembed/input/pretraite_api_arte_tv.php
  39. 3
      oembed/input/pretraite_publish_twitter_com.php
  40. 18
      oembed/input/pretraite_vimeo_com.php
  41. 1
      oembed/input/pretraite_www_youtube_com.php
  42. BIN
      oembed/input/vignettes/soundcloud.png
  43. 112
      oembed/input/vignettes/soundcloud.svg
  44. 5
      oembed/output/json.php
  45. 12
      oembed/output/modeles/article-photo.json.html
  46. 15
      oembed/output/xml.php
  47. 15
      oembed_administrations.php
  48. 165
      oembed_fonctions.php
  49. 196
      oembed_pipelines.php
  50. 15
      paquet.xml
  51. 20
      phpcs.xml.dist
  52. 617
      phpstan-baseline.neon
  53. 11
      phpstan-constants.php
  54. 13
      phpstan.neon.dist
  55. 2
      prive/objets/liste/oembed_providers.html
  56. BIN
      prive/themes/spip/images/oembed-16.png
  57. BIN
      prive/themes/spip/images/oembed-24.png
  58. BIN
      prive/themes/spip/images/oembed-32.png
  59. BIN
      prive/themes/spip/images/oembed-64.png
  60. 6
      prive/themes/spip/images/oembed-xx.svg
  61. 8
      spip-cli/OembedRecupererData.php

66
.gitattributes vendored

@ -0,0 +1,66 @@
* text=auto !eol
action/api_oembed.php -text
action/oembed_nettoyer_iframes.php -text
css/oembed.css -text
formulaires/configurer_oembed.html -text
inc/oembed.php -text
inc/oembed_recuperer_url.php -text
inc/ressource.php -text
javascript/oembed_restaurer_clics_sanitises.js -text
lang/oembed.xml -text
lang/oembed_de.php -text
lang/oembed_en.php -text
lang/oembed_es.php -text
lang/oembed_fr.php -text
lang/oembed_sk.php -text
lang/paquet-oembed.xml -text
lang/paquet-oembed_de.php -text
lang/paquet-oembed_en.php -text
lang/paquet-oembed_es.php -text
lang/paquet-oembed_fr.php -text
lang/paquet-oembed_sk.php -text
lib/php-emoji/emoji.css -text
lib/php-emoji/emoji.php -text
lib/php-emoji/emoji.png -text
modeles/oembed.html -text
modeles/oembed_fonctions.php -text
modeles/oembed_link.html -text
modeles/oembed_photo.html -text
modeles/oembed_rich.html -text
modeles/oembed_video.html -text
modeles/text_oembed.html -text
modeles/toot.html -text
oembed/input/posttraite_api_arte_tv.php -text
oembed/input/posttraite_facebook_video.php -text
oembed/input/posttraite_huffduffer_rich.php -text
oembed/input/posttraite_instagram_rich.php -text
oembed/input/posttraite_issuu.php -text
oembed/input/posttraite_mastodon.php -text
oembed/input/posttraite_oeproxy_default_rich.php -text
oembed/input/posttraite_oeproxy_imdb_rich.php -text
oembed/input/posttraite_office_national_du_film_du_canada_video.php -text
oembed/input/posttraite_rdio_rich.php -text
oembed/input/posttraite_slideshare_rich.php -text
oembed/input/posttraite_soundcloud_rich.php -text
oembed/input/posttraite_twitter.php -text
oembed/input/posttraite_youtube_video.php -text
oembed/input/pretraite_api_arte_tv.php -text
oembed/input/pretraite_publish_twitter_com.php -text
oembed/input/pretraite_www_youtube_com.php -text
oembed/input/vignettes/soundcloud.png -text
oembed/output/json.php -text
oembed/output/modeles/article-photo.json.html -text
oembed/output/modeles/article.json.html -text
oembed/output/xml.php -text
/oembed_administrations.php -text
/oembed_fonctions.php -text
/oembed_pipelines.php -text
/paquet.xml -text
prive/objets/liste/oembed_providers.html -text
prive/squelettes/contenu/configurer_oembed.html -text
prive/themes/spip/images/oembed-16.png -text
prive/themes/spip/images/oembed-24.png -text
prive/themes/spip/images/oembed-32.png -text
prive/themes/spip/images/oembed-64.png -text svneol=unset#unset
prive/themes/spip/images/oembed-xx.svg -text
spip-cli/OembedRecupererData.php -text

10
.gitignore vendored

@ -1,10 +0,0 @@
/vendor/
/composer.phar
/composer.lock
/phpcs.xml
/phpstan.neon
/.php_cs.cache
/.php_cs.txt
/.phpunit.cache
/phpunit.xml
/rector.php

40
action/api_oembed.php

@ -1,61 +1,55 @@
<?php
/**
* Plugin oEmbed
* Licence GPL3
*
*/
if (!defined('_ECRIRE_INC_VERSION')) {
if (!defined('_ECRIRE_INC_VERSION')){
return;
}
function action_api_oembed_dist() {
function action_api_oembed_dist(){
$args = [
$args = array(
'url' => $url = _request('url'),
'maxheight' => _request('maxheight'),
'maxwidth' => _request('maxwidth'),
'format' => _request('format'),
// support du jsonp: http://json-p.org/
'callback_jsonp' => _request('callback_jsonp'),
];
);
// Un pipeline pour pouvoir manipuler les arguments (en ajouter des spécifiques par ex.)
$args = pipeline('oembed_liste_arguments', $args);
$format = ($args['format'] == 'xml' ? 'xml' : 'json');
$format = ($args['format']=='xml' ? 'xml' : 'json');
$md5 = md5(serialize($args));
$oembed_cache = sous_repertoire(_DIR_CACHE, substr($md5, 0, 1)) . 'oe-' . $md5 . '.' . $format;
// si cache oembed dispo et pas de recalcul demande, l'utiliser (perf issue)
$res = '';
if (
file_exists($oembed_cache)
and _VAR_MODE !== 'recalcul'
if (file_exists($oembed_cache)
and _VAR_MODE!=='recalcul'
and (!defined('_VAR_NOCACHE')
or !_VAR_NOCACHE)
) {
or !_VAR_NOCACHE)){
lire_fichier($oembed_cache, $res);
} else {
include_spip('inc/urls');
defined('_DEFINIR_CONTEXTE_TYPE_PAGE') || define('_DEFINIR_CONTEXTE_TYPE_PAGE', true);
[$fond, $contexte, $url_redirect] = urls_decoder_url($url, '', $args);
if (
!isset($contexte['type-page'])
or !$type = $contexte['type-page']
) {
define('_DEFINIR_CONTEXTE_TYPE_PAGE', true);
list($fond, $contexte, $url_redirect) = urls_decoder_url($url, '', $args);
if (!isset($contexte['type-page'])
or !$type = $contexte['type-page']){
return '';
}
$res = '';
// chercher le modele json si il existe
if (trouver_fond($f = "oembed/output/modeles/$type.json")) {
if (trouver_fond($f = "oembed/output/modeles/$type.json")){
$res = trim(recuperer_fond($f, $contexte));
if ($format == 'xml') {
$res = json_decode($res, true, 512, JSON_THROW_ON_ERROR);
if ($format=='xml'){
$res = json_decode($res, true);
$output = charger_fonction('xml', 'oembed/output');
$res = $output($res, false);
}
@ -63,12 +57,12 @@ function action_api_oembed_dist() {
ecrire_fichier($oembed_cache, $res);
}
if (!$res) {
if (!$res){
include_spip('inc/headers');
http_status(404);
echo '404 Not Found';
} else {
$content_type = ($format == 'xml' ? 'text/xml' : 'application/json');
$content_type = ($format=='xml' ? 'text/xml' : 'application/json');
header("Content-type: $content_type; charset=utf-8");
echo $res;
}

101
action/oembed_nettoyer_iframes.php

@ -1,12 +1,11 @@
<?php
/**
* Plugin oEmbed
* Licence GPL3
*
*/
if (!defined('_ECRIRE_INC_VERSION')) {
if (!defined('_ECRIRE_INC_VERSION')){
return;
}
@ -16,71 +15,71 @@ if (!defined('_ECRIRE_INC_VERSION')) {
* appeler manuellement avec ?action=oembed_nettoyer_iframes
* autorise pour les seuls webmestres
*/
function action_oembed_nettoyer_iframes_dist() {
function action_oembed_nettoyer_iframes_dist(){
include_spip('inc/autoriser');
include_spip('inc/filtres');
include_spip('action/editer_objet');
if (!autoriser('webmestre')) {
if (!autoriser('webmestre')){
die('Pas autorise');
}
echo '<h1>Conversion des &lt;iframe&gt; en liens oembed</h1>';
$simu = true;
if (_request('modif')) {
if (_request('modif')){
$simu = false;
}
if ($simu) {
if ($simu){
echo "<p><strong>mode SIMULATION</strong> (ajoutez &modif=1 dans l'url pour modifier les contenus)</p>";
}
$tables = [
'spip_articles' => ['descriptif', 'chapo', 'texte', 'ps'],
];
$tables = array(
'spip_articles' => array('descriptif', 'chapo', 'texte', 'ps'),
);
foreach ($tables as $table => $champs) {
foreach ($tables as $table => $champs){
$objet = objet_type($table);
foreach ($champs as $champ) {
foreach ($champs as $champ){
$primary = id_table_objet($table);
$res = sql_select("$primary,$champ", $table, "$champ LIKE '%iframe%' OR $champ LIKE '%object%'");
while ($row = sql_fetch($res)) {
while ($row = sql_fetch($res)){
$pre = "$primary=" . $row[$primary] . ":$champ:";
$texte = $row[$champ];
$iframes = extraire_balises($texte, 'iframe');
if (count($iframes)) {
foreach ($iframes as $iframe) {
if (count($iframes)){
foreach ($iframes as $iframe){
$url = '';
$src = extraire_attribut($iframe, 'src');
if (strncmp($src, '//', 2) == 0) {
if (strncmp($src, '//', 2)==0){
$src = 'http:' . $src;
}
if (strpos($iframe, 'youtube') !== false) {
if (strpos($src, '/embed/') !== false) {
if (strpos($iframe, 'youtube')!==false){
if (strpos($src, '/embed/')!==false){
$url = str_replace('?', '&', $src);
$url = str_replace('/embed/videoseries&', '/playlist?', $url);
$url = str_replace('/embed/', '/watch?v=', $url);
$url = str_replace('&feature=player_embedded', '', $url);
echo "$pre Youtube $url<br />";
}
if (!$url) {
if (!$url){
var_dump($row);
var_dump(entites_html($iframe));
die('youtube inconnue');
}
} elseif (strpos($iframe, 'dailymotion') !== false) {
if (strpos($src, '/embed/') !== false) {
} elseif (strpos($iframe, 'dailymotion')!==false) {
if (strpos($src, '/embed/')!==false){
$url = str_replace('/embed/', '/', $src);
$url = explode('?', $url);
$url = reset($url);
#var_dump($url);
echo "$pre DailyMotion $url<br />";
}
if (!$url) {
if (!$url){
var_dump($row);
var_dump($iframe);
die('dailymotion inconnue');
}
} elseif (strpos($iframe, 'player.vimeo') !== false) {
if (strpos($src, '/video/') !== false) {
} elseif (strpos($iframe, 'player.vimeo')!==false) {
if (strpos($src, '/video/')!==false){
$url = str_replace('/video/', '/', $src);
$url = str_replace('player.vimeo', 'vimeo', $url);
$url = explode('?', $url);
@ -88,7 +87,7 @@ function action_oembed_nettoyer_iframes_dist() {
#var_dump($url);
echo "$pre Vimeo $url<br />";
}
if (!$url) {
if (!$url){
var_dump($row);
var_dump($iframe);
die('vimeo inconnue');
@ -118,77 +117,75 @@ function action_oembed_nettoyer_iframes_dist() {
}
} */ else {
echo "$pre iframe inconnue : " . entites_html($iframe) . '<br />';
}
if ($url) {
}
if ($url){
$texte = str_replace($iframe, "\n\n" . $url . "\n\n", $texte);
if (preg_match(',<center>\s*' . preg_quote($url, ',') . '.*</center>,Uims', $texte, $m)) {
if (preg_match(',<center>\s*' . preg_quote($url, ',') . '.*</center>,Uims', $texte, $m)){
$texte = str_replace($m[0], "\n\n" . $url . "\n\n", $texte);
}
$texte = preg_replace(',\s+' . preg_quote($url, ',') . '\s+,ims', "\n\n" . $url . "\n\n", $texte);
}
}
if ($texte !== $row[$champ]) {
if ($texte!==$row[$champ]){
echo "$pre Corrige $champ <br />";
if (!$simu) {
if (!$simu){
echo "$pre Corrige $champ <br />";
objet_modifier($objet, $row[$primary], [$champ => $texte]);
objet_modifier($objet, $row[$primary], array($champ => $texte));
} else {
echo "SIMU : $pre Corrige $champ <br />";
}
}
}
$objects = extraire_balises($texte, 'object');
if (count($objects)) {
foreach ($objects as $object) {
if (count($objects)){
foreach ($objects as $object){
$url = '';
$embed = extraire_balise($object, 'embed');
$src = extraire_attribut($embed, 'src');
if (strncmp($src, '//', 2) == 0) {
if (strncmp($src, '//', 2)==0){
$src = 'http:' . $src;
}
if (strpos($embed, 'youtube') !== false) {
if (strpos($src, '/v/') !== false) {
if (strpos($embed, 'youtube')!==false){
if (strpos($src, '/v/')!==false){
$url = str_replace('?', '&', $src);
$url = str_replace('/v/', '/watch?v=', $url);
echo "$pre Youtube $url<br />";
} elseif (strpos($src, '/embed/') !== false) {
} elseif (strpos($src, '/embed/')!==false) {
$url = str_replace('?', '&', $src);
$url = str_replace('/embed/', '/watch?v=', $url);
echo "$pre Youtube $url<br />";
}
if (!$url) {
if (!$url){
var_dump($row);
var_dump(entites_html($object));
die('youtube inconnue');
}
} elseif (strpos($embed, 'dailymotion') !== false) {
if (strpos($src, '/swf/video/') !== false) {
} elseif (strpos($embed, 'dailymotion')!==false) {
if (strpos($src, '/swf/video/')!==false){
$url = str_replace('/swf/video/', '/video/', $src);
$url = explode('?', $url);
$url = reset($url);
#var_dump($url);
echo "$pre DailyMotion $url<br />";
} elseif (strpos($src, '/swf/') !== false) {
} elseif (strpos($src, '/swf/')!==false) {
$url = str_replace('/swf/', '/video/', $src);
$url = explode('?', $url);
$url = reset($url);
#var_dump($url);
echo "$pre DailyMotion $url<br />";
}
if (!$url) {
if (!$url){
var_dump($row);
var_dump($object);
die('dailymotion inconnue');
}
} elseif (strpos($embed, 'vimeo.com') !== false) {
if (
strpos($src, 'moogaloop') !== false
and $id = parametre_url($src, 'clip_id')
) {
} elseif (strpos($embed, 'vimeo.com')!==false) {
if (strpos($src, 'moogaloop')!==false
and $id = parametre_url($src, 'clip_id')){
$url = "https://vimeo.com/$id";
echo "$pre Vimeo $url<br />";
}
if (!$url) {
if (!$url){
var_dump($row);
var_dump(entites_html($object));
die('vimeo inconnue');
@ -199,18 +196,18 @@ function action_oembed_nettoyer_iframes_dist() {
} else {
echo "$pre object inconnue : " . entites_html($object) . '<br />';
}
if ($url) {
if ($url){
$texte = str_replace($object, "\n\n" . $url . "\n\n", $texte);
if (preg_match(',<center>\s*' . preg_quote($url, ',') . '.*</center>,Uims', $texte, $m)) {
if (preg_match(',<center>\s*' . preg_quote($url, ',') . '.*</center>,Uims', $texte, $m)){
$texte = str_replace($m[0], "\n\n" . $url . "\n\n", $texte);
}
$texte = preg_replace(',\s+' . preg_quote($url, ',') . '\s+,ims', "\n\n" . $url . "\n\n", $texte);
}
}
if ($texte !== $row[$champ]) {
if (!$simu) {
if ($texte!==$row[$champ]){
if (!$simu){
echo "$pre Corrige $champ <br />";
objet_modifier($objet, $row[$primary], [$champ => $texte]);
objet_modifier($objet, $row[$primary], array($champ => $texte));
} else {
echo "SIMU : $pre Corrige $champ <br />";
}

20
composer.json

@ -1,20 +0,0 @@
{
"autoload": {
},
"autoload-dev": {
},
"require": {
"php": "^7.3 || ^8.0"
},
"require-dev": {
"spip/coding-standards": "^1.2",
"phpstan/phpstan": "^1.4",
"dealerdirect/phpcodesniffer-composer-installer": "^0.7.1",
"rector/rector": "^0.12.13"
},
"config": {
"allow-plugins": {
"dealerdirect/phpcodesniffer-composer-installer": true
}
}
}

6
css/oembed.css

@ -98,7 +98,7 @@ figure.oe-image-block figcaption {background:#eee;padding: 10px;text-align: left
.oembed_mastodon .rwd-rich-container {height: auto !important;}
.oembed_mastodon .oembed-source {display: none;}
.oembed_mastodon .spip_doc_titre {display: none;}
.mastodon-toot {padding:0;margin:0;border:0;padding-left:63px;font-family: Arial,Helvetica,Sans-Serif;font-size: 1.0em;line-height: 1.5em;text-align: inherit}
.mastodon-toot {padding:0;margin:0;border:0;padding-left:63px;font-family: Arial,Helvetica,Sans-Serif;font-size: 1.0em;line-height: 1.5em;}
.mastodon-toot a {background: transparent !important;text-decoration: none !important;}
.mastodon-toot .emoji-sizer {vertical-align: top;}
.mastodon-toot .toot-published {float: right;color:#9baec8;}
@ -107,12 +107,12 @@ figure.oe-image-block figcaption {background:#eee;padding: 10px;text-align: left
.mastodon-toot .toot-author-thumbnail {float: left;margin-left:-63px;margin-top:4px;width: 48px;height: 48px;border-radius: 4px;}
.mastodon-toot .toot-author-screen-name {color:#282c37;}
.mastodon-toot .toot-author-url:active .toot-author-screen-name,.mastodon-toot .toot-author-url:focus .toot-author-screen-name,.mastodon-toot .toot-author-url:hover .toot-author-screen-name {text-decoration: underline;}
.mastodon-toot .toot-content {display:block;margin: 0.75em 0 0.25em;text-align: inherit;max-width: 80em;}
.mastodon-toot .toot-content {display:block;margin: 0.75em 0 0.25em;}
.mastodon-toot .toot-content p {margin-bottom: 0.75em;}
.mastodon-toot .toot-content p:last-child {margin-bottom: 0;}
.mastodon-toot .toot-content a {color:#2b90d9;}
.mastodon-toot .toot-content a:active,.mastodon-toot .toot-content a:focus,.mastodon-toot .toot-content a:hover {text-decoration: underline !important;}
.mastodon-toot .invisible {display: none}
.mastodon-toot .ellipsis::after {display: inline;content:'\2026'}
.mastodon-toot .toot-enclosure {display: inline-block;position: relative;width: 100%;height: 0;padding-bottom:50%;margin: 0.25em 0;}
.mastodon-toot .toot-enclosure {display: inline-block;position: relative;width: 100%;height: 0;padding-bottom:40%;margin: 0.25em 0;}
.mastodon-toot .toot-enclosure .toot-enclosure-inner {display:block;position:absolute;top:0;left: 0;height: 100%;width: 100%;vertical-align: middle;overflow: hidden;background-position: center;background-repeat: no-repeat;background-size: cover;}

28
formulaires/configurer_oembed.html

@ -1,27 +1,27 @@
<!-- presentation=non -->
<!-- nom=oembed -->
<div class="formulaire_spip formulaire_cfg formulaire_configurer formulaire_#FORM">
<h3 class='titrem'><img src="#CHEMIN_IMAGE{oembed-24.svg}" class="cadre-icone" /><:oembed:titre_configurer_oembed:></h3>
<h3 class='titrem'><img src="#CHEMIN_IMAGE{oembed-24.png}" class="cadre-icone" /><:oembed:titre_configurer_oembed:></h3>
[<p class="reponse_formulaire reponse_formulaire_ok">(#ENV*{message_ok})</p>]
[<p class="reponse_formulaire reponse_formulaire_erreur">(#ENV*{message_erreur})</p>]
<form method='post' action='#ENV{action}'><div>
#ACTION_FORMULAIRE{#ENV{action}}
<div class="editer-groupe">
<ul>
#SET{fl,oembed}
#SET{name,maxwidth}#SET{obli,''}#SET{erreurs,#ENV**{erreurs}|table_valeur{#GET{name}}}
<div class="editer editer_[(#GET{name})][ (#GET{obli})][ (#GET{erreurs}|oui)erreur]">
<li class="editer editer_[(#GET{name})][ (#GET{obli})][ (#GET{erreurs}|oui)erreur]">
<label for="#GET{name}">[(#GET{fl}|concat{':label_',#GET{name}}|_T)]</label>[
<span class='erreur_message'>(#GET{erreurs})</span>
]<input type="text" name="#GET{name}" class="text" value="#ENV*{#GET{name},600}" id="#GET{name}"/>
</div>
</li>
#SET{name,maxheight}#SET{obli,''}#SET{erreurs,#ENV**{erreurs}|table_valeur{#GET{name}}}
<div class="editer editer_[(#GET{name})][ (#GET{obli})][ (#GET{erreurs}|oui)erreur]">
<li class="editer editer_[(#GET{name})][ (#GET{obli})][ (#GET{erreurs}|oui)erreur]">
<label for="#GET{name}">[(#GET{fl}|concat{':label_',#GET{name}}|_T)]</label>[
<span class='erreur_message'>(#GET{erreurs})</span>
]<input type="text" name="#GET{name}" class="text" value="#ENV*{#GET{name},400}" id="#GET{name}"/>
</div>
</li>
#SET{name,embed_auto}#SET{erreurs,#ENV**{erreurs}|table_valeur{#GET{name}}}
<div class="editer long_label editer_[(#GET{name})][ (#GET{obli})][ (#GET{erreurs}|oui)erreur]">
<li class="editer long_label editer_[(#GET{name})][ (#GET{obli})][ (#GET{erreurs}|oui)erreur]">
<label for="#GET{name}"><:oembed:label_embed_auto:></label>[
<span class='erreur_message'>(#GET{erreurs})</span>
]<div class="choix">
@ -31,9 +31,9 @@
<input type="radio" name="#GET{name}" class="radio" id="#GET{name}_non" value="non"
[(#ENV{#GET{name},oui}|=={oui}|non)checked="checked"] /><label for="#GET{name}_non"><:item_non:></label>
</div>
</div>
</li>
#SET{name,detecter_lien}#SET{erreurs,#ENV**{erreurs}|table_valeur{#GET{name}}}
<div class="editer long_label editer_[(#GET{name})][ (#GET{obli})][ (#GET{erreurs}|oui)erreur]">
<li class="editer long_label editer_[(#GET{name})][ (#GET{obli})][ (#GET{erreurs}|oui)erreur]">
<label for="#GET{name}"><:oembed:label_detecter_lien:></label>[
<span class='erreur_message'>(#GET{erreurs})</span>
]<div class="choix">
@ -43,9 +43,9 @@
<input type="radio" name="#GET{name}" class="radio" id="#GET{name}_non" value="non"
[(#ENV{#GET{name},non}|=={oui}|non)checked="checked"] /><label for="#GET{name}_non"><:item_non:></label>
</div>
</div>
</li>
#SET{name,inserer_head}#SET{erreurs,#ENV**{erreurs}|table_valeur{#GET{name}}}
<div class="editer long_label editer_[(#GET{name})][ (#GET{obli})][ (#GET{erreurs}|oui)erreur]">
<li class="editer long_label editer_[(#GET{name})][ (#GET{obli})][ (#GET{erreurs}|oui)erreur]">
<label for="#GET{name}"><:oembed:label_inserer_head:></label>[
<span class='erreur_message'>(#GET{erreurs})</span>
]<div class="choix">
@ -55,10 +55,10 @@
<input type="radio" name="#GET{name}" class="radio" id="#GET{name}_non" value="non"
[(#ENV{#GET{name},oui}|=={oui}|non)checked="checked"] /><label for="#GET{name}_non"><:item_non:></label>
</div>
</div>
</div>
</li>
</ul>
[(#REM) ajouter les saisies supplementaires : extra et autre, a cet endroit ]
<!--extra-->
<p class='boutons'><span class='image_loading'>&nbsp;</span><input type='submit' class='submit' value='<:bouton_enregistrer:>' /></p>
</div></form>
</div>
</div>

222
inc/oembed.php

@ -1,12 +1,11 @@
<?php
/**
* Plugin oEmbed
* Licence GPL3
*
*/
if (!defined('_ECRIRE_INC_VERSION')) {
if (!defined('_ECRIRE_INC_VERSION')){
return;
}
@ -14,7 +13,7 @@ if (!defined('_ECRIRE_INC_VERSION')) {
* Lister les providers connus
* @return array
*/
function oembed_lister_providers($avec_provider_interdits = false) {
function oembed_lister_providers(){
// liste des providers par defaut
@ -24,7 +23,7 @@ function oembed_lister_providers($avec_provider_interdits = false) {
// https://github.com/starfishmod/jquery-oembed-all/blob/master/jquery.oembed.js
// https://github.com/panzi/oembedendpoints/blob/master/endpoints-simple.json
// voir aussi http://embed.ly/providers qui donne les scheme mais pas les endpoint
$providers = [
$providers = array(
'http://*.youtube.com/watch*' => 'https://www.youtube.com/oembed',
'http://*.youtube.com/playlist*' => 'https://www.youtube.com/oembed',
'http://youtu.be/*' => 'https://www.youtube.com/oembed',
@ -41,6 +40,10 @@ function oembed_lister_providers($avec_provider_interdits = false) {
'http://*.mixcloud.com/*' => 'https://mixcloud.com/oembed',
'http://*.slideshare.net/*/*' => 'https://www.slideshare.net/api/oembed/2',
'http://www.slideshare.net/*/*' => 'https://www.slideshare.net/api/oembed/2',
'http://instagr.am/*' => 'https://api.instagram.com/oembed',
'http://*.instagr.am/*' => 'https://api.instagram.com/oembed',
'http://instagram.com/*' => 'https://api.instagram.com/oembed',
'http://*.instagram.com/*' => 'https://api.instagram.com/oembed',
'http://huffduffer.com/*/*' => 'http://huffduffer.com/oembed',
'http://nfb.ca/film/*' => 'http://www.nfb.ca/remote/services/oembed/',
'http://dotsub.com/view/*' => 'http://dotsub.com/services/oembed',
@ -71,66 +74,34 @@ function oembed_lister_providers($avec_provider_interdits = false) {
'http://issuu.com/*/docs/*' => 'https://issuu.com/oembed',
'http://*.calameo.com/books/*' => 'https://www.calameo.com/services/oembed',
'http://*.calameo.com/read/*' => 'https://www.calameo.com/services/oembed',
'http://www.facebook.com/*/posts/*' => 'https://www.facebook.com/plugins/post/oembed.json/',
'http://www.facebook.com/*/activity/*' => 'https://www.facebook.com/plugins/post/oembed.json/',
'http://www.facebook.com/*/photos/*' => 'https://www.facebook.com/plugins/post/oembed.json/',
'http://www.facebook.com/media/*' => 'https://www.facebook.com/plugins/post/oembed.json/',
'http://www.facebook.com/questions/*' => 'https://www.facebook.com/plugins/post/oembed.json/',
'http://www.facebook.com/notes/*' => 'https://www.facebook.com/plugins/post/oembed.json/',
'http://www.facebook.com/*/videos/*' => 'https://www.facebook.com/plugins/video/oembed.json/',
'http://*.arte.tv/*/videos/*' => 'https://api.arte.tv/api/player/v1/oembed/',
'http://egliseinfo.catholique.fr/*' => 'http://egliseinfo.catholique.fr/api/oembed',
#'https://gist.github.com/*' => 'http://github.com/api/oembed?format=json'
];
);
// pipeline pour permettre aux plugins d'ajouter/supprimer/modifier des providers
$providers = pipeline('oembed_lister_providers', $providers);
// merger avec la globale pour perso mes_options dans un site
// pour supprimer un scheme il suffit de le renseigner avec un endpoint vide
if (isset($GLOBALS['oembed_providers'])) {
if (isset($GLOBALS['oembed_providers'])){
$providers = array_merge($providers, $GLOBALS['oembed_providers']);
}
if (!$avec_provider_interdits) {
// retirer les providers avec un endpoint vide
$providers = array_filter($providers);
}
return $providers;
}
/**
* @param string $url
* @param bool|null $detecter_lien
* false : bloque la detection des liens quelle que soit la config du plugin
* true : force la detection des liens quelle que soit la config du plugin
* null : utilise la config du plugin
* @return array|null
*/
function oembed_provider_from_url($url, bool $detecter_lien = null) {
static $providers = [];
if (!isset($providers[$detecter_lien])) {
$providers[$detecter_lien] = [];
}
if (isset($providers[$detecter_lien][$url])) {
return $providers[$detecter_lien][$url];
}
include_spip('inc/config');
$provider = oembed_verifier_provider($url);
// inconnu ?
if (!$provider and $detecter_lien !== false) {
if ($detecter_lien or lire_config('oembed/detecter_lien', 'non') == 'oui') {
$provider = oembed_detecter_lien($url);
}
}
// inconnu ou interdit ?
if (!$provider or empty($provider['endpoint'])) {
return $providers[$detecter_lien][$url] = null;
}
return $providers[$detecter_lien][$url] = $provider;
}
// Merci WordPress :)
// http://core.trac.wordpress.org/browser/trunk/wp-includes/class-oembed.php
@ -145,40 +116,36 @@ function oembed_provider_from_url($url, bool $detecter_lien = null) {
* null : la valeur configuree par defaut ou pour le provider est utilisee
* '' : pas de valeur max
* @param string $format format à utiliser pour la requete oembed (json ou xml)
* @param bool|null $detecter_lien tenter la détection automatique de lien oembed dans la page indiquée
* false : bloque la detection des liens quelle que soit la config du plugin
* true : force la detection des liens quelle que soit la config du plugin
* null : utilise la config du plugin
* @param string $detecter_lien tenter la détection automatique de lien oembed dans la page indiquée
* @param bool $force_reload forcer le rechargement de l'oembed depuis la source sans utiliser le cache local
* @return bool|array false si aucun retour ou erreur ; tableau des éléménents de la réponse oembed
*/
function oembed_recuperer_data($url, $maxwidth = null, $maxheight = null, $format = 'json', $detecter_lien = null, $force_reload = false) {
static $cache = [];
function oembed_recuperer_data($url, $maxwidth = null, $maxheight = null, $format = 'json', $detecter_lien = 'non', $force_reload = false){
static $cache = array();
$provider = false;
include_spip('inc/config');
// compatibilite avec l'ancienne signature de la fonction : non equivalait a 'auto' (c'est a dire on applique la config du plugin)
if ($detecter_lien === 'non') {
$detecter_lien = null;
}
elseif ($detecter_lien) {
$detecter_lien = true;
$provider = oembed_verifier_provider($url);
if ((!$provider)
and (($detecter_lien!='non')
or lire_config('oembed/detecter_lien', 'non')=='oui')){
$provider = oembed_detecter_lien($url);
}
$provider = oembed_provider_from_url($url, $detecter_lien);
// inconnu ou interdit ?
if (!$provider) {
if (!$provider){
return false;
}
$data_url = url_absolue($provider['endpoint'], url_de_base());
// certains oembed fournissent un endpoint qui contient deja l'URL, parfois differente de celle de la page
if (!parametre_url($data_url, 'url')) {
if (!parametre_url($data_url, 'url')){
$data_url = parametre_url($data_url, 'url', $url, '&');
}
if (!$maxwidth) {
if (!$maxwidth){
$maxwidth = lire_config('oembed/maxwidth', '600');
}
if (!$maxheight) {
if (!$maxheight){
$maxheight = lire_config('oembed/maxheight', '400');
}
@ -186,7 +153,7 @@ function oembed_recuperer_data($url, $maxwidth = null, $maxheight = null, $forma
$data_url = parametre_url($data_url, 'maxheight', $maxheight, '&');
$data_url = parametre_url($data_url, 'format', $format, '&');
if (isset($provider['provider_name']) and $provider['provider_name']) {
if (isset($provider['provider_name']) and $provider['provider_name']){
$provider_name = $provider['provider_name'];
} else {
// pre-traitement du provider si besoin
@ -195,29 +162,29 @@ function oembed_recuperer_data($url, $maxwidth = null, $maxheight = null, $forma
$provider_name = reset($provider_name);
}
$provider_name = preg_replace(',\W+,', '_', strtolower($provider_name));
if ($oembed_endpoint_pretraite = charger_fonction("pretraite_$provider_name", 'oembed/input', true)) {
if ($oembed_endpoint_pretraite = charger_fonction("pretraite_$provider_name", 'oembed/input', true)){
$a = func_get_args();
$args = ['url' => array_shift($a)];
if (count($a)) {
$args = array('url' => array_shift($a));
if (count($a)){
$args['maxwidth'] = array_shift($a);
}
if (count($a)) {
if (count($a)){
$args['maxheight'] = array_shift($a);
}
if (count($a)) {
if (count($a)){
$args['format'] = array_shift($a);
}
$args['endpoint'] = $provider['endpoint'];
$data_url = $oembed_endpoint_pretraite($data_url, $args);
}
if (isset($cache[$data_url])) {
if (isset($cache[$data_url])){
return $cache[$data_url];
}
$oembed_cache = sous_repertoire(_DIR_CACHE, 'oembed') . md5($data_url) . '.' . $format;
// si cache oembed dispo et pas de recalcul demande, l'utiliser (perf issue)
if (!$force_reload and file_exists($oembed_cache) and _VAR_MODE !== 'recalcul') {
if (!$force_reload and file_exists($oembed_cache) and _VAR_MODE!=='recalcul'){
lire_fichier($oembed_cache, $cache[$data_url]);
$cache[$data_url] = unserialize($cache[$data_url]);
return $cache[$data_url];
@ -226,12 +193,8 @@ function oembed_recuperer_data($url, $maxwidth = null, $maxheight = null, $forma
$oembed_recuperer_url = charger_fonction('oembed_recuperer_url', 'inc');
$cache[$data_url] = $oembed_recuperer_url($data_url, $url, $format);
// si une fonction de post-traitement est fourni pour ce provider+type, l'utiliser
if ($cache[$data_url]) {
if (isset($cache[$data_url]['provider_name']) and $cache[$data_url]['provider_name']) {
$provider_name2 = str_replace(' ', '_', strtolower($cache[$data_url]['provider_name']));
} else {
$provider_name2 = '';
}
if ($cache[$data_url]){
$provider_name2 = str_replace(' ', '_', strtolower($cache[$data_url]['provider_name']));
$type = strtolower($cache[$data_url]['type']);
// securisons le nom de la fonction (provider peut contenir n'importe quoi)
$f1 = preg_replace(',\W,', '', "posttraite_{$provider_name2}_$type");
@ -242,8 +205,7 @@ function oembed_recuperer_data($url, $maxwidth = null, $maxheight = null, $forma
$oembed_provider_posttraite = charger_fonction($f1, 'oembed/input', true)
or $oembed_provider_posttraite = charger_fonction($f2, 'oembed/input', true)
or $oembed_provider_posttraite = charger_fonction($f3, 'oembed/input', true)
or $oembed_provider_posttraite = charger_fonction($f4, 'oembed/input', true)
) {
or $oembed_provider_posttraite = charger_fonction($f4, 'oembed/input', true)){
$cache[$data_url] = $oembed_provider_posttraite($cache[$data_url], $url);
}
ecrire_fichier($oembed_cache, serialize($cache[$data_url]));
@ -258,25 +220,18 @@ function oembed_recuperer_data($url, $maxwidth = null, $maxheight = null, $forma
*
* @param string $url l'url à tester
* @return bool|array
* false si l'url n'est pas dans la liste (provider inconnu) ; details du
* provider dans un tabeau associatif si oui (avec un endpoint vide si
* le provider est explicitement interdit)
* false si non ; details du provider dans un tabeau associatif si oui
*/
function oembed_verifier_provider($url) {
static $base = null;
if (is_null($base)) {
$base = url_de_base();
}
if (strpos($url, (string) $GLOBALS['meta']['adresse_site']) === 0 or strpos($url, (string) $base) === 0) {
return ['endpoint' => ''];
function oembed_verifier_provider($url){
if (strncmp($url, $GLOBALS['meta']['adresse_site'], strlen($GLOBALS['meta']['adresse_site']))==0){
return false;
}
$providers = oembed_lister_providers(true);
foreach ($providers as $scheme => $endpoint) {
$providers = oembed_lister_providers();
foreach ($providers as $scheme => $endpoint){
$regex = '#' . str_replace('\*', '(.+)', preg_quote($scheme, '#')) . '#';
$regex = preg_replace('|^#http\\\://|', '#https?\://', $regex);
if (preg_match($regex, $url)) {
return ['endpoint' => $endpoint];
if (preg_match($regex, $url)){
return array('endpoint' => $endpoint);
}
}
return false;
@ -286,66 +241,45 @@ function oembed_verifier_provider($url) {
* Détecter les liens oembed dans le head d'une page web
*
* @param string $url url de la page à analyser
* @return bool|array false si pas de lien ; description du provider oembed associe au lien
* @return bool|string false si pas de lien ; url du contenu oembed
*/
function oembed_detecter_lien($url) {
$providers = [];
// s'assurer que l'URL n'est pas une url direct vers un media mais ressemble bien à l'URL d'une page HTML
// pour eviter de faire des
$parts = parse_url($url);
// si on trouve une extension, verifier que c'est html ou htm, le reste ne nous interesse pas
if (!empty($parts['path'])) {
if (preg_match(',\.(\w+)$,', $parts['path'], $m)) {
if (!in_array(strtolower($m[1]), ['html', 'htm'])) {
spip_log("oembed_detecter_lien $url : on ignore l'extension " . $m[1], 'oembed' . _LOG_DEBUG);
return false;
}
}
}
function oembed_detecter_lien($url){
$providers = array();
$oembed_recuperer_url = charger_fonction('oembed_recuperer_url', 'inc');
// on recupere le contenu de la page
// on utilise recuperer_url_cache() avec un cache 24h pour ne pas passer son temps à faire de la detection sur les memes liens
include_spip('inc/distant');
$options = [
'delai_cache' => in_array(_VAR_MODE, ['preview', 'recalcul']) ? 0 : 24 * 3600,
'taille_max' => min(_INC_DISTANT_MAX_SIZE, 256000),
];
$res = recuperer_url_cache($url, $options);
$html = '';
if ($res and intval($res['status'] / 100) < 4 and !empty($res['page'])) {
$html = $res['page'];
if ($html = $oembed_recuperer_url($url, $url, 'html')){
// types de liens oembed à détecter
$linktypes = [
$linktypes = array(
'application/json+oembed' => 'json',
'text/json+oembed' => 'json', // ex de 500px
'text/xml+oembed' => 'xml',
'application/xml+oembed' => 'xml', // uniquement pour Vimeo
];
);
// on ne garde que le head de la page
$head = substr($html, 0, stripos($html, '</head>'));
// un test rapide...
$tagfound = false;
foreach ($linktypes as $linktype => $format) {
if (stripos($head, $linktype)) {
foreach ($linktypes as $linktype => $format){
if (stripos($head, $linktype)){
$tagfound = true;
break;
}
}
if ($tagfound && preg_match_all('/<link([^<>]+)>/i', $head, $links)) {
if (!function_exists('extraire_attribut')) {
if ($tagfound && preg_match_all('/<link([^<>]+)>/i', $head, $links)){
if (!function_exists('extraire_attribut')){
include_spip('inc/filtres');
}
foreach ($links[0] as $link) {
foreach ($links[0] as $link){
$type = extraire_attribut($link, 'type');
$href = extraire_attribut($link, 'href');
if (!empty($type) and !empty($linktypes[$type]) and !empty($href)) {
if (!empty($type) and !empty($linktypes[$type]) and !empty($href)){
$providers[$linktypes[$type]] = $href;
// on a le json, ça nous suffit
if ('json' == $linktypes[$type]) {
if ('json'==$linktypes[$type]){
break;
}
}
@ -353,10 +287,10 @@ function oembed_detecter_lien($url) {
}
}
$res = [];
$res = array();
// on préfère le json au xml
if (!empty($providers['json'])) {
if (!empty($providers['json'])){
$res['endpoint'] = $providers['json'];
} elseif (!empty($providers['xml'])) {
$res['endpoint'] = $providers['xml'];
@ -365,7 +299,7 @@ function oembed_detecter_lien($url) {
}
// detecter certains providers specifiques : ex mastodon, chaque instance a son nom et on peut pas l'identifier par son URL
if (strpos($html, '//github.com/tootsuite/mastodon') !== false or strpos($html, '//joinmastodon.org') !== false) {
if (strpos($html, '//github.com/tootsuite/mastodon')!==false or strpos($html, '//joinmastodon.org')!==false){
$res['provider_name'] = 'Mastodon';
}
@ -378,14 +312,26 @@ function oembed_detecter_lien($url) {
* @param string $lien
* @return string
*/
function oembed_embarquer_lien($lien) {
function oembed_embarquer_lien($lien){
static $base = null;
$url = extraire_attribut($lien, 'href');
$texte = null;
if ($url and oembed_provider_from_url($url)) {
$fond = recuperer_fond('modeles/oembed', ['url' => $url, 'lien' => $lien]);
if ($fond = trim($fond)) {
$texte = $fond;
if ($url
and (
oembed_verifier_provider($url)
or (lire_config('oembed/detecter_lien', 'non')=='oui'))
){
if (is_null($base)){
$base = url_de_base();
}
// on embarque jamais un lien de soi meme car c'est une mise en abime qui donne le tourni
// (et peut provoquer une boucle infinie de requetes http)
if (strncmp($url, $base, strlen($base))!=0){
$fond = recuperer_fond('modeles/oembed', array('url' => $url, 'lien' => $lien));
if ($fond = trim($fond)){
$texte = $fond;
}
}
}

59
inc/oembed_recuperer_url.php

@ -1,12 +1,11 @@
<?php
/**
* Plugin oEmbed
* Licence GPL3
*
*/
if (!defined('_ECRIRE_INC_VERSION')) {
if (!defined('_ECRIRE_INC_VERSION')){
return;
}
@ -18,12 +17,13 @@ if (!defined('_ECRIRE_INC_VERSION')) {
* @param string $format
* @return bool|mixed|string
*/
function inc_oembed_recuperer_url($oembed_url, $url, $format) {
$erreur = '';
function inc_oembed_recuperer_url($oembed_url, $url, $format){
$erreur = "";
// on recupere le contenu de la page
// si possible via curl en IPv4 car youtube bug en IPv6
if (function_exists('curl_init')) {
// uniquement si PHP >= 5.3.0 pour utiliser l'option CURLOPT_IPRESOLVE
if (function_exists('curl_init') and version_compare(phpversion(), '5.3.0', '>=')){
spip_log('Requete oembed (curl) pour ' . $url . ' : ' . $oembed_url, 'oembed.' . _LOG_DEBUG);
$c = curl_init();
curl_setopt($c, CURLOPT_RETURNTRANSFER, 1);
@ -35,19 +35,14 @@ function inc_oembed_recuperer_url($oembed_url, $url, $format) {
curl_setopt($c, CURLOPT_USERAGENT, $browser);
//curl_setopt($c, CURLOPT_SSLVERSION, 1);
// essayer d'eviter l'erreur 35 sur le protocole SSL
// https://stackoverflow.com/questions/58342699/php-curl-curl-error-35-error1414d172ssl-routinestls12-check-peer-sigalgwr
// non supporte partout, provoque une erreur 59
// curl_setopt($c, CURLOPT_SSL_CIPHER_LIST, 'DEFAULT@SECLEVEL=1');
// indiquer un referer : si jamais la diffusion du contenu est limitee au site, ca permet d'en recuperer les infos
// ou en tout cas ca donne plus de chance...
$referer = $GLOBALS['meta']['adresse_site'] . '/';
curl_setopt($c, CURLOPT_REFERER, $referer);
if (isset($GLOBALS['meta']['http_proxy']) and $GLOBALS['meta']['http_proxy']) {
if (isset($GLOBALS['meta']['http_proxy']) and $GLOBALS['meta']['http_proxy']){
curl_setopt($c, CURLOPT_PROXY, $GLOBALS['meta']['http_proxy']);
if (isset($GLOBALS['meta']['http_noproxy'])) {
if (isset($GLOBALS['meta']['http_noproxy'])){
curl_setopt($c, CURLOPT_NOPROXY, $GLOBALS['meta']['http_proxy']);
}
}
@ -56,50 +51,42 @@ function inc_oembed_recuperer_url($oembed_url, $url, $format) {
// http://stackoverflow.com/questions/26089067/youtube-oembed-api-302-then-503-errors
curl_setopt($c, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4);
$data = curl_exec($c);
/** code mort : vieux patch introduit par https://git.spip.net/spip-contrib-extensions/oembed/commit/9146311a
* pour fixer les erreurs SSL sur certains serveurs masto mais pas très viable en prod
$status = curl_getinfo($c, CURLINFO_HTTP_CODE);
if (!$data or intval($status / 100) == 4) {
if (!$data or intval($status/100)==4){
$errno = curl_errno($c);
$erreur = "Status $status Error $errno " . curl_error($c);
$erreur = "Status $status Error " . curl_errno($c) . " " . curl_error($c);
// si c'est une erreur de protocole SSL, on tente avec un exec mechant car ca peut venir de la version de CURL PHP
// (ca marche au moins en local)
if (!$data and $errno == 35 and function_exists('exec')) {
exec('curl --silent --location ' . escapeshellarg($oembed_url), $output);
if (!$data and $errno==35){
exec('curl "' . $oembed_url . '"', $output);
$data = implode("\n", $output);
} else {
$data = '';
}
}
*/
}
curl_close($c);
} else {
spip_log('Requete oembed (recuperer_page / recuperer_url) pour ' . $url . ' : ' . $oembed_url, 'oembed.' . _LOG_DEBUG);
spip_log('Requete oembed (recuperer_page) pour ' . $url . ' : ' . $oembed_url, 'oembed.' . _LOG_DEBUG);
include_spip('inc/distant');
// recuperer_page utilise par defaut l'adresse du site comme $referer
$data = recuperer_url($oembed_url);
$data = ($data['page'] ?? null);
$data = recuperer_page($oembed_url);
}
if (!$data) {
if (!$data){
spip_log('infos oembed brutes pour ' . "$url | $oembed_url" . ' : ' . "ECHEC $erreur", 'oembed.' . _LOG_ERREUR);
} else {
spip_log('infos oembed brutes pour ' . "$url | $oembed_url" . ' : ' . (($format == 'html') ? substr($data, 0, 100) : $data), 'oembed.' . _LOG_DEBUG);
spip_log('infos oembed brutes pour ' . "$url | $oembed_url" . ' : ' . (($format=='html') ? substr($data, 0, 100) : $data), 'oembed.' . _LOG_DEBUG);
}
if ($data) {
if ($format == 'json') {
try {
$data = json_decode($data, true, 512, JSON_THROW_ON_ERROR);
$data['oembed_url_source'] = $url;
$data['oembed_url'] = $oembed_url;
} catch (JsonException $e) {
$data = null;
spip_log('Failed to parse Json data : ' . $e->getMessage(), 'oembed.' . _LOG_ERREUR);
}
if ($data){
if ($format=='json'){
$data = json_decode($data, true);
$data['oembed_url_source'] = $url;
$data['oembed_url'] = $oembed_url;
}
// TODO : format xml
//if ($format == 'xml')

24
inc/ressource.php

@ -10,17 +10,17 @@ define('_EXTRAIRE_RESSOURCES', ',' . '<"?(https?://|[\w][\w -]*\.[\w -]+).*>' .
/* pipeline pour typo, evitons une erreur dans les logs */
function tw_post_typo($t) {
function tw_post_typo($t){
return $t;
}
/* pipeline pour propre, evitons une erreur dans les logs */
function tw_pre_liens($t) {
function tw_pre_liens($t){
return $t;
}
function traiter_ressources($r) {
if ($ressource = charger_fonction('ressource', 'inc', true)) {
function traiter_ressources($r){
if ($ressource = charger_fonction('ressource', 'inc', true)){
$html = $ressource($r[0]);
} else {
$html = htmlspecialchars($r[0]);
@ -29,29 +29,27 @@ function traiter_ressources($r) {
return $html;
}
function inc_ressource_dist($html) {
return tw_traiter_ressources([0 => $html]);
function inc_ressource_dist($html){
return tw_traiter_ressources(array(0 => $html));
}
function tw_traiter_ressources($r) {
function tw_traiter_ressources($r){
$html = null;
include_spip('inc/lien');
$url = explode(' ', trim($r[0], '<>'));
$url = $url[0];
# <http://url/absolue>
if (preg_match(',^https?://,i', $url)) {
if (preg_match(',^https?://,i', $url)){
$html = PtoBR(propre("<span class='ressource spip_out'>&lt;[->" . $url . ']&gt;</span>'));
} # <url/relative>
else {
if (false !== strpos($url, '/')) {
if (false!==strpos($url, '/')){
$html = PtoBR(propre("<span class='ressource spip_in'>&lt;[->" . $url . ']&gt;</span>'));
} # <fichier.rtf>
else {
if (
preg_match(',\.([^.]+)$,', $url, $regs)
and file_exists($f = _DIR_IMG . $regs[1] . '/' . $url)
) {
if (preg_match(',\.([^.]+)$,', $url, $regs)
and file_exists($f = _DIR_IMG . $regs[1] . '/' . $url)){
$html = PtoBR(propre("<span class='ressource spip_in'>&lt;[" . $url . '->' . $f . ']&gt;</span>'));
} else {
$html = PtoBR(propre("<span class='ressource'>&lt;" . $url . '&gt;</span>'));

3
lang/oembed.xml

@ -17,9 +17,6 @@
<traducteur nom="Raquel S. Bujaldón" lien="https://trad.spip.net/auteur/raquel-s-bujaldon" />
</langue>
<langue code="fr" url="https://trad.spip.net/tradlang_module/oembed?lang_cible=fr" total="22" traduits="22" relire="0" modifs="0" nouveaux="0" pourcent="100.00" />
<langue code="it" url="https://trad.spip.net/tradlang_module/oembed?lang_cible=it" total="22" traduits="22" relire="0" modifs="0" nouveaux="0" pourcent="100.00">
<traducteur nom="Alberto" lien="https://trad.spip.net/auteur/alberto" />
</langue>
<langue code="sk" url="https://trad.spip.net/tradlang_module/oembed?lang_cible=sk" total="22" traduits="19" relire="0" modifs="1" nouveaux="2" pourcent="86.36">
<traducteur nom="jaro" lien="https://trad.spip.net/auteur/jaro" />
</langue>

49
lang/oembed_it.php

@ -1,49 +0,0 @@
<?php
// This is a SPIP language file -- Ceci est un fichier langue de SPIP
// extrait automatiquement de https://trad.spip.net/tradlang_module/oembed?lang_cible=it
// ** ne pas modifier le fichier **
if (!defined('_ECRIRE_INC_VERSION')) {
return;
}
$GLOBALS[$GLOBALS['idx_lang']] = array(
// A
'aucun_provider' => 'Nessun provider',
// B
'bouton_lecture' => 'Lettura',
// E
'erreur_ajout_provider' => 'Errore durante l’aggiunta del provider.',
'erreur_scheme_doublon' => 'Questo schema è già presente nell’elenco.',
'explication_scheme' => 'usa * come carattere jolly',
'explication_upload_url' => 'Inserisci semplicemente l’URL della pagina che contiene il documento per <a href="https://contrib.spip.net/4595"> i siti più popolari</a>.',
// I
'info_1_provider' => '1 provider',
'info_nb_providers' => '@nb@ provider',
// L
'label_detecter_lien' => 'Rileva automaticamente i provider (ignora la whitelist)?',
'label_embed_auto' => 'Trasforma automaticamente gli URL inseriti nel testo?',
'label_endpoint' => 'Endpoint',
'label_inserer_head' => 'Il sito stesso è un provider oEmbed',
'label_maxheight' => 'Altezza massima predefinita (px)',
'label_maxwidth' => 'Larghezza massima predefinita (px)',
'label_scheme' => 'Schema',
// O
'ok_ajout_provider' => 'Provider aggiunto',
// S
'supprimer_provider' => 'Eliminare',
// T
'titre_ajouter_provider' => 'Aggiungi un provider',
'titre_configuration_avancee_providers' => 'Accedi alla configurazione avanzata dei provider oEmbed',
'titre_configurer_oembed' => 'Configura oEmbed',
'titre_configurer_providers' => 'Provider oEmbed',
'titre_oembed' => 'oEmbed'
);

3
lang/paquet-oembed.xml

@ -15,9 +15,6 @@
<traducteur nom="Raquel S. Bujaldón" lien="https://trad.spip.net/auteur/raquel-s-bujaldon" />
</langue>
<langue code="fr" url="https://trad.spip.net/tradlang_module/paquet-oembed?lang_cible=fr" total="2" traduits="2" relire="0" modifs="0" nouveaux="0" pourcent="100.00" />
<langue code="it" url="https://trad.spip.net/tradlang_module/paquet-oembed?lang_cible=it" total="2" traduits="2" relire="0" modifs="0" nouveaux="0" pourcent="100.00">
<traducteur nom="Alberto" lien="https://trad.spip.net/auteur/alberto" />
</langue>
<langue code="sk" url="https://trad.spip.net/tradlang_module/paquet-oembed?lang_cible=sk" total="2" traduits="2" relire="0" modifs="0" nouveaux="0" pourcent="100.00">
<traducteur nom="jaro" lien="https://trad.spip.net/auteur/jaro" />
</langue>

15
lang/paquet-oembed_it.php

@ -1,15 +0,0 @@
<?php
// This is a SPIP language file -- Ceci est un fichier langue de SPIP
// extrait automatiquement de https://trad.spip.net/tradlang_module/paquet-oembed?lang_cible=it
// ** ne pas modifier le fichier **
if (!defined('_ECRIRE_INC_VERSION')) {
return;
}
$GLOBALS[$GLOBALS['idx_lang']] = array(
// O
'oembed_description' => 'oEmbed client/provider per SPIP.',
'oembed_slogan' => 'oEmbed client/provider per SPIP'
);

6
modeles/oembed.html

@ -1,8 +1,6 @@
#CACHE{7*24*3600}
[(#SET{data,#ENV**{url}|oembed_recuperer_data{#ENV{maxwidth,0},#ENV{maxheight,0}}})
][(#GET{data}|oui)
<div class='spip_documents spip_documents_[(#ENV{align,center})] ressource oembed[ oembed_(#GET{data}|table_valeur{type})][ oembed_(#GET{data}|table_valeur{media}|replace{sound,audio})][ oembed_(#GET{data}|table_valeur{provider_name}|strtolower|replace{'\W','_'})]'>
<figure class="spip_doc_inner">
<figure class='spip_documents spip_documents_[(#ENV{align,center})] ressource oembed[ oembed_(#GET{data}|table_valeur{type})][ oembed_(#GET{data}|table_valeur{media}|replace{sound,audio})][ oembed_(#GET{data}|table_valeur{provider_name}|strtolower|replace{'\W','_'})]'>
[(#INCLURE{fond=modeles/oembed_[(#GET{data}|table_valeur{type,link})],data=#GET{data},url,align,lien,async})]
</figure>
</div>]
</figure>]

1
modeles/oembed_fonctions.php

@ -1,5 +1,4 @@
<?php
/**
* Plugin oEmbed
* Licence GPL3

4
modeles/oembed_link.html

@ -4,6 +4,4 @@
(#ENV{data}|table_valeur{html})
</span>]
</span>]
#SET{legende,''}[(#ID_DOCUMENT|oui)[(#SET{legende,#INCLURE{fond=modeles/document_legende,env,titre=#INFO_TITRE*{document,#ID_DOCUMENT}|oembed_lier_titre{#ENV*{url}}}|trim})]]
[(#GET{legende}|non)
[<figcaption class="spip_doc_legende"><div class="spip_doc_titre oembed-source">(#ENV*{lien}|echappe_retour)</div></figcaption>]][(#GET{legende})]
[<figcaption><div class="spip_doc_titre oembed-source">(#ENV*{lien}|echappe_retour)</div></figcaption>]

6
modeles/oembed_photo.html

@ -3,10 +3,8 @@
(#ENV{data}|table_valeur{url}|sinon{#ENV{data}|table_valeur{thumbnail_url}}|balise_img{#ENV{data}|table_valeur{title}})
</a>
</span>]
#SET{legende,''}[(#ID_DOCUMENT|oui)[(#SET{legende,#INCLURE{fond=modeles/document_legende,env,titre=#INFO_TITRE*{document,#ID_DOCUMENT}|oembed_lier_titre{#ENV*{url}}}|trim})]]
[(#GET{legende}|non)
<figcaption class="spip_doc_legende">
<figcaption>
[<div class="spip_doc_titre" style="max-width:#ENV{data/width}px;"><a href="#ENV*{url}" class="oe-title">(#ENV*{data/title})</a>[(#ENV*{data/author_name}|oui)
<span class="oe-author"><br/><span class="oe-author_par"><:par_auteur:></span>[(#ENV*{data/author_url}|?{[<a class="oe-author_name" href="#ENV*{data/author_url}">(#ENV*{data/author_name})</a>],<span class="oe-author_name">#ENV*{data/author_name}</span>})]</span>]</div>]
[<div class="spip_doc_titre oembed-source">(#ENV*{lien}|echappe_retour)</div>]
</figcaption>][(#GET{legende})]
</figcaption>

6
modeles/oembed_rich.html

@ -11,10 +11,8 @@
</div>
<style><!--/**/.oe-rich .loading {background-image:url("#CHEMIN_IMAGE{searching.gif}")!important;background-size:auto !important;}/**/--></style>
</div>
#SET{legende,''}[(#ID_DOCUMENT|oui)[(#SET{legende,#INCLURE{fond=modeles/document_legende,env,titre=#INFO_TITRE*{document,#ID_DOCUMENT}|oembed_lier_titre{#ENV*{url}}}|trim})]]
[(#GET{legende}|non)
<figcaption class="spip_doc_legende">
<figcaption>
[<div class="spip_doc_titre" style="max-width:#ENV{data/width}px;"><a href="#ENV*{url}" class="oe-title">(#ENV*{data/title})</a>[(#ENV*{data/author_name}|oui)
<span class="oe-author"><br/><span class="oe-author_par"><:par_auteur:></span>[(#ENV*{data/author_url}|?{[<a class="oe-author_name" href="#ENV*{data/author_url}">(#ENV*{data/author_name})</a>],<span class="oe-author_name">#ENV*{data/author_name}</span>})]</span>]</div>]
[<div class="spip_doc_titre oembed-source">(#ENV*{lien}|echappe_retour)</div>]
</figcaption>][(#GET{legende})]
</figcaption>

8
modeles/oembed_video.html

@ -11,10 +11,8 @@
</div>
<style><!--/**/.oe-video .loading {background-image:url("#CHEMIN_IMAGE{searching.gif}")!important;background-size:auto !important;}/**/--></style>
</div>
#SET{legende,''}[(#ID_DOCUMENT|oui)[(#SET{legende,#INCLURE{fond=modeles/document_legende,env,titre=#INFO_TITRE*{document,#ID_DOCUMENT}|oembed_lier_titre{#ENV*{url}}}|trim})]]
[(#GET{legende}|non)
<figcaption class="spip_doc_legende">
<figcaption>
[<div class="spip_doc_titre" style="max-width:#ENV{data/width}px;"><a href="#ENV*{url}" class="oe-title">(#ENV*{data/title})</a>[(#ENV*{data/author_name}|oui)
<span class="oe-author"><br/><span class="oe-author_par"><:par_auteur:></span>[(#ENV*{data/author_url}|?{[<a href="#ENV*{data/author_url}" class="oe-author_name">(#ENV*{data/author_name})</a>],<span class="oe-author_name">#ENV*{data/author_name}</span>})]</span>]</div>]
<span class="oe-author"><br/><span class="oe-author_par"><:par_auteur:></span>[(#ENV*{data/author_url}|?{[<a class="oe-author_name" href="#ENV*{data/author_url}">(#ENV*{data/author_name})</a>],<span class="oe-author_name">#ENV*{data/author_name}</span>})]</span>]</div>]
[<div class="spip_doc_titre oembed-source">(#ENV*{lien}|echappe_retour)</div>]
</figcaption>][(#GET{legende})]
</figcaption>

35
modeles/text_oembed.html

@ -1,18 +1,17 @@
<BOUCLE_tous (DOCUMENTS types_documents) {id_document=#ID} {tout}
>[(#SET{html,[(#FICHIER|contenu_document{#ENV{charset,auto}})]})]
[(#SET{data,[(#ARRAY{
type,[(#ARRAY{image,photo,video,video,audio,rich,sound,rich,file,rich}|table_valeur{#MEDIA})],
html,[(#GET{html})],
width,[(#GET{html}|extraire_attribut{width})],
height,[(#GET{html}|extraire_attribut{height})],
title,[(#TITRE)],
media,[(#MEDIA)],
author_name,[(#CREDITS)],
thumbnail_url,[(#LOGO_DOCUMENT|extraire_attribut{src})]})]})
]
<div class='spip_documents spip_documents_[(#ENV{align,center})] ressource oembed[ oembed_(#GET{data}|table_valeur{type})][ oembed_(#GET{data}|table_valeur{media}|replace{sound,audio})][ oembed_(#GET{data}|table_valeur{provider_name}|strtolower|replace{'\W','_'})]'>
<figure class="spip_doc_inner">
[(#INCLURE{fond=modeles/oembed_[(#GET{data}|table_valeur{type,link})],data=#GET{data},url=#OEMBED,lien=#OEMBED,align,async,autoplay,id_document})]
</figure>
</div>
</BOUCLE_tous>
<BOUCLE_tous (DOCUMENTS types_documents) {id_document=#ID} {tout}
>[(#SET{html,[(#FICHIER|contenu_document{#ENV{charset,auto}})]})]
[(#SET{data,[(#ARRAY{
type,[(#ARRAY{image,photo,video,video,audio,rich,sound,rich,file,rich}|table_valeur{#MEDIA})],
html,[(#GET{html})],
width,[(#GET{html}|extraire_attribut{width})],
height,[(#GET{html}|extraire_attribut{height})],
title,[(#TITRE)],
media,[(#MEDIA)],
author_name,[(#CREDITS)],
thumbnail_url,[(#LOGO_DOCUMENT|extraire_attribut{src})]})]})
]
<div class='spip_documents spip_documents_center ressource oembed[ oembed_(#GET{data}|table_valeur{type})][ oembed_(#GET{data}|table_valeur{media}|replace{sound,audio})][ oembed_(#GET{data}|table_valeur{provider_name}|strtolower|replace{'\W','_'})]'>
[(#INCLURE{fond=modeles/oembed_[(#GET{data}|table_valeur{type,link})],data=#GET{data},url=#OEMBED,align,async,autoplay})]
[<div class="spip_doc_titre oembed-source">(#OEMBED|echappe_retour)</div>]
</div>
</BOUCLE_tous>

4
modeles/toot.html

@ -1,9 +1,9 @@
<blockquote class="mastodon-toot">
<blockquote class="mastodon-toot" style="[max-width:(#ENV{width})px;]">
<span class="toot-author">
[<a href="#ENV{url}" class="toot-published">(#ENV{published}|affdate_heure)</a>]
<a href="#ENV{author_url}" class="toot-author-url">
[(#ENV{author_thumbnail}|image_reduire{96,96}|balise_img{'',toot-author-thumbnail,48x48}|liens_absolus)]
[(#ENV{author_thumbnail}|image_reduire{48,48}|liens_absolus|inserer_attribut{class,toot-author-thumbnail})]
[<span class="toot-author-screen-name">(#ENV*{author_screen_name})</span>]
[<span class="toot-author-name">(#ENV{author_name})</span>]
</a>

9
oembed/input/posttraite_api_arte_tv.php

@ -1,5 +1,4 @@