Browse Source

chores: synchronisation du code avec celui de textwheel car toute la partie traiter_modele() est forkee sans raison

remotes/checkIfPRContentChanged-1659714283585166050/refactor_texte_safety
Cerdic 2 months ago
parent
commit
8f5be2c5fa
  1. 153
      ecrire/inc/lien.php

153
ecrire/inc/lien.php

@ -16,12 +16,24 @@ if (!defined('_ECRIRE_INC_VERSION')) {
include_spip('base/abstract_sql');
//
// Production de la balise A+href a partir des raccourcis [xxx->url] etc.
// Note : complique car c'est ici qu'on applique typo(),
// et en plus on veut pouvoir les passer en pipeline
//
/**
* Production de la balise a+href à partir des raccourcis `[xxx->url]` etc.
*
* @note
* Compliqué car c'est ici qu'on applique typo(),
* et en plus, on veut pouvoir les passer en pipeline
*
* @see typo()
* @param string $lien
* @param string $texte
* @param string $class
* @param string $title
* @param string $hlang
* @param string $rel
* @param string $connect
* @param array $env
* @return string
*/
function inc_lien_dist(
$lien,
$texte = '',
@ -151,43 +163,73 @@ function liens_implicite_glose_dist($texte, $id, $type, $args, $ancre, string $c
return $url;
}
function traiter_lien_implicite($ref, $texte = '', $pour = 'url', string $connect = '') {
$url = null;
/**
* Transformer un lien raccourci art23 en son URL
* Par defaut la fonction produit une url prive si on est dans le prive
* ou publique si on est dans le public.
* La globale lien_implicite_cible_public permet de forcer un cas ou l'autre :
* $GLOBALS['lien_implicite_cible_public'] = true;
* => tous les liens raccourcis pointent vers le public
* $GLOBALS['lien_implicite_cible_public'] = false;
* => tous les liens raccourcis pointent vers le prive
* unset($GLOBALS['lien_implicite_cible_public']);
* => retablit le comportement automatique
*
* @param string $ref
* @param string $texte
* @param string $pour
* @param string $connect
* @return array|bool|string
*/
function traiter_lien_implicite($ref, $texte = '', $pour = 'url', $connect = '') {
$cible = $GLOBALS['lien_implicite_cible_public'] ?? null;
if (!($match = typer_raccourci($ref))) {
return false;
}
[$type, , $id, , $args, , $ancre] = array_pad($match, 7, null);
// attention dans le cas des sites le lien doit pointer non pas sur
// la page locale du site, mais directement sur le site lui-meme
# attention dans le cas des sites le lien doit pointer non pas sur
# la page locale du site, mais directement sur le site lui-meme
$url = '';
if ($f = charger_fonction("implicite_$type", 'liens', true)) {
$url = $f($texte, $id, $type, $args, $ancre, $connect);
}
if (!$url) {
$url = generer_objet_url($id, $type, $args ?? '', $ancre ?? '', null, '', $connect);
$url = generer_objet_url($id, $type, $args ?? '', $ancre ?? '', $cible, '', $connect ?? '');
}
if (!$url) {
return false;
}
if (is_array($url)) {
[$type, $id] = array_pad($url, 2, null);
$url = generer_objet_url($id, $type, $args ?? '', $ancre ?? '', null, '', $connect);
$url = generer_objet_url($id, $type, $args ?? '', $ancre ?? '', $cible, '', $connect ?? '');
}
if ($pour === 'url') {
return $url;
}
$r = traiter_raccourci_titre($id, $type, $connect);
if ($r) {
$r['class'] = ($type == 'site') ? 'spip_out' : 'spip_in';
}
if ($texte = trim($texte)) {
$r['titre'] = $texte;
}
if (!@$r['titre']) {
$r['titre'] = _T($type) . " $id";
}
if ($pour == 'titre') {
return $r['titre'];
}
$r['url'] = $url;
// dans le cas d'un lien vers un doc, ajouter le type='mime/type'
@ -218,6 +260,7 @@ function typer_raccourci($lien) {
if (!preg_match(_RACCOURCI_URL, $lien, $match)) {
return [];
}
$f = $match[1];
// valeur par defaut et alias historiques
if (!$f) {
@ -239,14 +282,15 @@ function typer_raccourci($lien) {
$f = 'document';
} else {
if (preg_match('/^br..?ve$/S', $f)) {
$f = 'breve';
$f = 'breve'; # accents :(
}
}
}
}
}
}
} # accents :(
}
$match[0] = $f;
return $match;
@ -266,18 +310,24 @@ function typer_raccourci($lien) {
function traiter_raccourci_titre($id, $type, $connect = null) {
$trouver_table = charger_fonction('trouver_table', 'base');
$desc = $trouver_table(table_objet($type));
if (!($desc and $s = $desc['titre'])) {
return [];
}
$_id = $desc['key']['PRIMARY KEY'];
$r = sql_fetsel($s, $desc['table'], "$_id=$id", '', '', '', '', $connect);
if (!$r) {
return [];
}
$r['titre'] = supprimer_numero($r['titre']);
if (!$r['titre'] and !empty($r['surnom'])) {
$r['titre'] = $r['surnom'];
}
if (!isset($r['lang'])) {
$r['lang'] = '';
}
@ -293,11 +343,16 @@ function traiter_raccourci_titre($id, $type, $connect = null) {
// mais on renvoie les params (pour l'indexation par le moteur de recherche)
define(
'_RACCOURCI_MODELE',
'_PREG_MODELE',
'(<([a-z_-]{3,})' # <modele
. '\s*([0-9]*)\s*' # id
. '([|](?:<[^<>]*>|[^>])*?)?' # |arguments (y compris des tags <...>)
. '\s*/?' . '>)' # fin du modele >
);
define(
'_RACCOURCI_MODELE',
_PREG_MODELE
. '\s*(<\/a>)?' # eventuel </a>
);
@ -308,31 +363,30 @@ function traiter_modeles($texte, $doublons = false, $echap = '', string $connect
if ($doublons === true) {
$doublons = ['documents' => ['doc', 'emb', 'img']];
}
// detecter les modeles (rapide)
if (
strpos($texte, '<') !== false and
preg_match_all('/<[a-z_-]{3,}\s*[0-9|]+/iS', $texte, $matches, PREG_SET_ORDER)
strpos($texte, '<') !== false
and preg_match_all('/<[a-z_-]{3,}\s*[0-9|]+/iS', $texte, $matches, PREG_SET_ORDER)
) {
include_spip('public/assembler');
$wrap_embed_html = charger_fonction('wrap_embed_html', 'inc', true);
foreach ($matches as $match) {
// Recuperer l'appel complet (y compris un eventuel lien)
// Recuperer l'appel complet (y compris un eventuel lien)
foreach ($matches as $match) {
$a = strpos($texte, (string) $match[0]);
preg_match(
_RACCOURCI_MODELE_DEBUT,
substr($texte, $a),
$regs
);
$regs[] = ''; // s'assurer qu'il y a toujours un 5e arg, eventuellement vide
preg_match(_RACCOURCI_MODELE_DEBUT, substr($texte, $a), $regs);
// s'assurer qu'il y a toujours un 5e arg, eventuellement vide
while (count($regs) < 6) {
$regs[] = '';
}
[, $mod, $type, $id, $params, $fin] = $regs;
if (
$fin and
preg_match(
'/<a\s[^<>]*>\s*$/i',
substr($texte, 0, $a),
$r
)
$fin
and preg_match('/<a\s[^<>]*>\s*$/i', substr($texte, 0, $a), $r)
) {
$lien = [
'href' => extraire_attribut($r[0], 'href'),
@ -360,30 +414,31 @@ function traiter_modeles($texte, $doublons = false, $echap = '', string $connect
if (!is_null($liens)) {
$params = str_replace($liens[0], $liens[1], $params);
}
$modele = inclure_modele($type, $id, $params, $lien, $connect, $env);
$modele = inclure_modele($type, $id, $params, $lien, $connect ?? '', $env);
// en cas d'echec,
// si l'objet demande a une url,
// creer un petit encadre vers elle
if ($modele === false) {
if (!$lien) {
$lien = traiter_lien_implicite("$type$id", '', 'tout', $connect);
$modele = substr($texte, $a, $cherche);
if (!is_null($liens)) {
$modele = str_replace($liens[0], $liens[1], $modele);
}
$contexte = array_merge($env, ['id' => $id, 'type' => $type, 'modele' => $modele]);
if ($lien) {
$modele = '<a href="'
. $lien['url']
. '" class="spip_modele'
. '">'
. sinon($lien['titre'], _T('ecrire:info_sans_titre'))
. '</a>';
} else {
$modele = '';
if (test_espace_prive()) {
$modele = entites_html(substr($texte, $a, $cherche));
if (!is_null($liens)) {
$modele = '<pre>' . str_replace($liens[0], $liens[1], $modele) . '</pre>';
}
# un eventuel guillemet (") sera reechappe par #ENV
$contexte['lien'] = str_replace('&quot;', '"', $lien['href']);
$contexte['lien_class'] = $lien['class'];
$contexte['lien_mime'] = $lien['mime'];
$contexte['lien_title'] = $lien['title'];
$contexte['lien_hreflang'] = $lien['hreflang'];
}
}
$modele = recuperer_fond('modeles/dist', $contexte, [], $connect ?? '');
}
// le remplacer dans le texte
if ($modele !== false) {
@ -401,7 +456,7 @@ function traiter_modeles($texte, $doublons = false, $echap = '', string $connect
// hack pour tout l'espace prive
if (((!_DIR_RESTREINT) or ($doublons)) and ($id)) {
foreach ($doublons ?: ['documents' => ['doc', 'emb', 'img']] as $quoi => $modeles) {
if (in_array($type, $modeles)) {
if (in_array(strtolower($type), $modeles)) {
$GLOBALS["doublons_{$quoi}_inclus"][] = $id;
}
}

Loading…
Cancel
Save