From a75537e1eb0099875bc7b1e3b12db04b5e3c36e9 Mon Sep 17 00:00:00 2001 From: "Committo,Ergo:sum" <esj@rezo.net> Date: Tue, 23 Sep 2008 08:19:22 +0000 Subject: [PATCH] =?UTF-8?q?Les=20fonctions=20malnomm=C3=A9s=20{{{calculer?= =?UTF-8?q?=5Furl=5F}}}*=20avaient=20=C3=A9t=C3=A9=20introduites=20pour=20?= =?UTF-8?q?palier=20les=20d=C3=A9ficiences=20du=20raccourci=20des=20gloses?= =?UTF-8?q?,=20ce=20qui=20amenait=20des=20comportements=20d=C3=A9tourn?= =?UTF-8?q?=C3=A9s=20et=20m=C3=AAme=20un=20=20bug=20(l'URL=20d'un=20site?= =?UTF-8?q?=20r=C3=A9f=C3=A9renc=C3=A9=20n'=C3=A9tait=20pas=20toujours=20r?= =?UTF-8?q?etourn=C3=A9e).=20Maintenant=20que=20le=20raccourci=20des=20glo?= =?UTF-8?q?ses=20est=20=C3=A9tendu,=20ces=20fonctions=20disparaissent=20et?= =?UTF-8?q?=20sont=20remplac=C3=A9es=20par=20une=20utilisation=20syst?= =?UTF-8?q?=C3=A9matique=20de=20l'entr=C3=A9e=20{{{=20titre=20}}}=20dans?= =?UTF-8?q?=20la=20description=20des=20tables=20retourn=C3=A9e=20par=20{{{?= =?UTF-8?q?=C2=A0trouver=5Ftable=20}}}=C2=A0depuis=20[12748]=20et=20[12749?= =?UTF-8?q?].?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Le fichier inc/lien.php qui ne contenait que ces fonctions est maintenant dévolu aux fonctions qui produisent des URL et qui auparavant figuraient dans inc/texte.php, lequel est maintenant plus conforme à son nom en traitant plus strictement les questions de typographie. --- ecrire/inc/lien.php | 474 ++++++++++++++++++++++++++++++++++++------- ecrire/inc/texte.php | 411 +------------------------------------ 2 files changed, 407 insertions(+), 478 deletions(-) diff --git a/ecrire/inc/lien.php b/ecrire/inc/lien.php index 078cbe2224..a01432953c 100644 --- a/ecrire/inc/lien.php +++ b/ecrire/inc/lien.php @@ -14,99 +14,437 @@ if (!defined("_ECRIRE_INC_VERSION")) return; include_spip('base/abstract_sql'); -// http://doc.spip.org/@calculer_url_article_dist -function calculer_url_article_dist($id, $texte='', $lien='', $connect='') { - - $row = sql_fetsel('titre,lang', 'spip_articles', "id_article=$id",'','','','',$connect); - if (!trim($texte)) - $texte = supprimer_numero($row['titre']); - if (!trim($texte)) - $texte = _T('article') . $id; - return array($lien, 'spip_in', $texte, $row['lang']); -} -// http://doc.spip.org/@calculer_url_rubrique_dist -function calculer_url_rubrique_dist($id, $texte='', $lien='', $connect='') +// +// Raccourcis liens [xxx->url] +// Note : complique car c'est ici qu'on applique typo(), +// et en plus on veut pouvoir les passer en pipeline +// + +// Regexp des raccouris, aussi utilisee pour la fusion de sauvegarde Spip +// Laisser passer des paires de crochets pour la balise multi +// mais refuser plus d'imbrications ou de mauvaises imbrications +// sinon les crochets ne peuvent plus servir qu'a ce type de raccourci +define('_RACCOURCI_LIEN', ",\[([^][]*?([[]\w*[]][^][]*)*)->(>?)([^]]*)\],msS"); + +// http://doc.spip.org/@expanser_liens +function expanser_liens($letexte, $connect='') { - $row = sql_fetsel('titre,lang', 'spip_rubriques', "id_rubrique=$id",'','','','',$connect); - if (!trim($texte)) { - $texte = supprimer_numero($row['titre']); - if (!trim($texte)) $texte = $id; + $letexte = pipeline('pre_liens', $letexte); + + $inserts = array(); + if (preg_match_all(_RACCOURCI_LIEN, $letexte, $matches, PREG_SET_ORDER)) { + $i = 0; + foreach ($matches as $regs) { + $n = count($regs); + list($texte, $bulle, $hlang) = traiter_raccourci_lien_atts($regs[1]); + list ($lien, $class, $texte, $lang) = + calculer_url($regs[$n-1], $texte, 'tout', $connect); + $inserts[++$i] = traiter_raccourci_lien_lang($lien, $class, $texte, $hlang, $lang, $bulle, $connect); + + $letexte = str_replace($regs[0], "@@SPIP_ECHAPPE_LIEN_$i@@", + $letexte); + } } - return array($lien, 'spip_in', $texte, $row['lang']); + $letexte = corriger_typo(traiter_modeles($letexte, false, false, $connect)); + foreach ($inserts as $i => $insert) { + $letexte = str_replace("@@SPIP_ECHAPPE_LIEN_$i@@", $insert, $letexte); + } + return $letexte; } -// http://doc.spip.org/@calculer_url_breve_dist -function calculer_url_breve_dist($id, $texte='', $lien='', $connect='') -{ - $row = sql_fetsel('titre,lang', 'spip_breves', "id_breve=$id",'','','','',$connect); - if (!trim($texte)) { - $texte = supprimer_numero($row['titre']); - if (!trim($texte)) $texte = $id; +// http://doc.spip.org/@traiter_raccourci_lien_lang +function traiter_raccourci_lien_lang($lien, $class, $texte, $hlang, $lang, $bulle, $connect='') +{ + // Si l'objet n'est pas de la langue courante, on ajoute hreflang + if (!$hlang AND $lang!=$GLOBALS['spip_lang']) + $hlang = $lang; + $lang = ($hlang ? ' hreflang="'.$hlang.'"' : '') . $bulle; + + # ceci s'execute heureusement avant les tableaux et leur "|". + # Attention, le texte initial est deja echappe mais pas forcement + # celui retourne par calculer_url. + + # Penser au cas [<imgXX|right>->URL], qui exige typo('<a>...</a>') + return typo('<a href="'.$lien + . ($class ? '" class="'.$class : '') + . '"'.$lang.'>' + . $texte.'</a>', true, $connect); +} + +// Repere dans la partie texte d'un raccourci [texte->...] +// la langue et la bulle eventuelles + +// http://doc.spip.org/@traiter_raccourci_lien_atts +function traiter_raccourci_lien_atts($texte) { + + $bulle = $hlang = ''; + // title et hreflang donnes par le raccourci ? + if (preg_match(',^(.*?)([|]([^<>]*?))?([{]([a-z_]+)[}])?$,', $texte, $m)) { + + $n =count($m); + // |infobulle ? + if ($n > 2) { + $bulle = ' title="'.texte_backend($m[3]).'"'; + // {hreflang} ? + if ($n > 4) { + // si c'est un code de langue connu, on met un hreflang + if (traduire_nom_langue($m[5]) <> $m[5]) { + $hlang = $m[5]; + } + // sinon c'est un italique + else { + $m[1] .= $m[4]; + } + + // S'il n'y a pas de hreflang sous la forme {}, ce qui suit le | + // est peut-etre une langue + } else if (preg_match(',^[a-z_]+$,', $m[3])) { + // si c'est un code de langue connu, on met un hreflang + // mais on laisse le title (c'est arbitraire tout ca...) + if (traduire_nom_langue($m[3]) <> $m[3]) { + $hlang = $m[3]; + } + } + } + $texte = $m[1]; } - return array($lien, 'spip_in', $texte, $row['lang']); + + return array(trim($texte), $bulle, $hlang); } -// http://doc.spip.org/@calculer_url_auteur_dist -function calculer_url_auteur_dist($id, $texte='', $lien='', $connect='') -{ - if ($texte=='') { - $row = sql_fetsel('nom', 'spip_auteurs', "id_auteur=$id",'','','','',$connect); - $texte = $row['nom']; +// callback pour la fonction traiter_raccourci_liens() +// http://doc.spip.org/@autoliens_callback +function autoliens_callback($r) { + if (strlen($l = $r[1])) { + // reperer le protocole + $protocol = 'http'; + if (preg_match(',^((https?):/*),S', $l, $m)) { + $l = substr($l, strlen($m[1])); + $protocol = $m[2]; + } + // valider le nom de domaine + if (preg_match( + '/^(?:[^\W_]((?:[^\W_]|-){0,61}[^\W_,])?\.)+[a-z]{2,6}\b/Si', $l)) { + // supprimer les ponctuations a la fin d'une URL + preg_match('/^(.*?)([,.;?]?)$/', $l, $k); + $l = inserer_attribut( + expanser_liens('[->'.$protocol.'://'.$k[1].']'), + 'rel', 'nofollow') + .$k[2]; + // si le texte ne contenait pas le 'http:' on le supprime aussi + if (!$m) + $l = str_replace('>http://', '>', $l); + return $l; + } } - return array($lien, 'spip_in', $texte); # pas de hreflang + return $r[0]; +} + +// extraire les liens ecrits en mode texte brut +// http://doc.spip.org/@traiter_raccourci_liens +function traiter_raccourci_liens($texte) { + return preg_replace_callback( + ';\[[^\[\]]*(?:<-|->).*?\]|<a\b.*?</a\b|<.*?>|' + .'((?:https?:/|www\.)[^"\'\s\[\]\}\)<>]*);imsS', + 'autoliens_callback', $texte); + return $texte; } -// http://doc.spip.org/@calculer_url_mot_dist -function calculer_url_mot_dist($id, $texte='', $lien='', $connect='') +// http://doc.spip.org/@nettoyer_raccourcis_typo +function nettoyer_raccourcis_typo($texte, $connect=''){ + $texte = pipeline('nettoyer_raccourcis_typo',$texte); + // remplacer les liens + if (preg_match_all(',[[]([^][]*)->(>?)([^][]*)[]],S', $texte, $regs, PREG_SET_ORDER)) + foreach ($regs as $reg) { + list ($titre,,)= traiter_raccourci_lien_atts($reg[1]); + $titre = calculer_url($reg[3], $titre, 'titre', $connect); + $titre = corriger_typo(supprimer_tags($titre)); + $texte = str_replace($reg[0], $titre, $texte); + } + + // supprimer les notes + $texte = preg_replace(",[[][[]([^]]|[]][^]])*[]][]],UimsS","",$texte); + + // supprimer les codes typos + $texte = str_replace(array('}','{'), '', $texte); + + // supprimer les tableaux + $texte = preg_replace(",(^|\r)\|.*\|\r,s", "\r", $texte); + return $texte; +} + +// Fonction pour les champs chapo commencant par =, redirection qui peut etre: +// 1. un raccourci Spip habituel (premier If) [texte->TYPEnnn] +// 2. un ultra raccourci TYPEnnn voire nnn (article) (deuxieme If) +// 3. une URL std +// renvoie une tableau structure comme ci-dessus mais sans calcul d'URL +// (cf fusion de sauvegardes) + +define('_RACCOURCI_CHAPO', ',^(\W*)(\W*)(\w*\d+([?#].*)?)$,'); + +// http://doc.spip.org/@chapo_redirige +function chapo_redirige($chapo, $url=false) { - if (!trim($texte)) { - $row = sql_fetsel('titre', 'spip_mots', "id_mot=$id",'','','','',$connect); - $texte = supprimer_numero($row['titre']); - if (!trim($texte)) $texte = $id; + if (!preg_match(_RACCOURCI_LIEN, $chapo, $m)) + if (!preg_match(_RACCOURCI_CHAPO, $chapo, $m)) + return $chapo; + return !$url ? $m[3] : calculer_url($m[3]); +} + +// Ne pas afficher le chapo si article virtuel +// http://doc.spip.org/@nettoyer_chapo +function nettoyer_chapo($chapo){ + return (substr($chapo,0,1) == "=") ? '' : $chapo; +} + +// http://doc.spip.org/@chapo_redirigetil +function chapo_redirigetil($chapo) { return $chapo && $chapo[0] == '=';} + +// Cherche un lien du type [->raccourci 123] +// associe a une fonction generer_url_raccourci() definie explicitement +// ou implicitement par le jeu de type_urls courant. +// +// Valeur retournee selon le parametre $pour: +// 'tout' : tableau [U,C,T,L] (vise <a href="U" class='C' hreflang='L'>T</a>) +// 'titre': seulement T ci-dessus (i.e. le TITRE ci-dessus ou dans table SQL) +// 'url': seulement U (i.e. generer_url_RACCOURCI) + +// http://doc.spip.org/@calculer_url +function calculer_url ($ref, $texte='', $pour='url', $connect='') { + if ($match = typer_raccourci($ref)) { + @list($type,,$id,,$args,,$ancre) = $match; +# 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 + if ($type == 'site') + $url = sql_getfetsel('url_site', 'spip_syndic', "id_syndic=$id",'','','','',$connect); + else $url = generer_url_entite($id,$type,$args,$ancre, $connect ? $connect : NULL); + if ($url) + return ($pour === 'url') + ? $url + : calculer_url_lien($type, $id, $url, $texte, $pour, $connect); } - return array($lien, 'spip_in', $texte); + if (preg_match(",^\s*(http:?/?/?|mailto:?)\s*$,iS", $ref)) + return ($pour != 'tout') ? '' : array('','','',''); + + $lien = entites_html(trim($ref)); + + // Liens explicites + if (!$texte) { + $texte = str_replace('"', '', $lien); + if (strlen($texte)>40) + $texte = substr($texte,0,35).'...'; + $texte = "<html>$texte</html>"; + $class = "spip_url spip_out"; + } else $class = "spip_out"; + + if ($pour == 'titre') return $texte; + + // petites corrections d'URL + if (preg_match(",^www\.[^@]+$,S",$lien)) + $lien = "http://".$lien; + else if (strpos($lien, "@") && email_valide($lien)) + $lien = "mailto:".$lien; + + if (preg_match(",^\s*mailto:,",$lien)) + $class = "spip_mailto"; + + // class spip_ancre sur les ancres pures (internes a la page) + if (substr($lien,0,1) == '#') + $class = 'spip_ancre'; + + return ($pour == 'url') ? $lien : array($lien, $class, $texte, ''); } -// http://doc.spip.org/@calculer_url_document_dist -function calculer_url_document_dist($id, $texte='', $lien='', $connect='') +// analyse des raccourcis issus de [TITRE->RACCOURCInnn] et connexes + +define('_RACCOURCI_URL', ',^\s*(\w*?)\s*(\d+)(\?(.*?))?(#([^\s]*))?\s*$,S'); + +// http://doc.spip.org/@typer_raccourci +function typer_raccourci ($lien) { + if (!preg_match(_RACCOURCI_URL, $lien, $match)) return array(); + $f = $match[1]; + // valeur par defaut et alias historiques + if (!$f) $f = 'article'; + else if ($f == 'art') $f = 'article'; + else if ($f == 'br') $f = 'breve'; + else if ($f == 'rub') $f = 'rubrique'; + else if ($f == 'aut') $f = 'auteur'; + else if ($f == 'doc' OR $f == 'im' OR $f == 'img' OR $f == 'image' OR $f == 'emb') + $f = 'document'; + else if (preg_match(',^br..?ve$,S', $f)) $f = 'breve'; # accents :( + $match[0] = $f; + $match[2] = entites_html($match[2]); + return $match; +} + +function calculer_url_lien($type, $id, $url, $texte, $pour, $connect) { - if ($texte=='') { - $row = sql_fetsel('titre,fichier', 'spip_documents', "id_document=$id",'','','','',$connect); - - $texte = $row['titre']; - if (!trim($texte)) - $texte = preg_replace(",^.*/,","",$row['fichier']); - if (!trim($texte)) - $texte = $id; + $trouver_table = charger_fonction('trouver_table', 'base'); + $desc = $trouver_table(table_objet($type)); + $lang = ''; + if ($desc AND $s = $desc['titre']) { + $_id = $desc['key']['PRIMARY KEY']; + $t = $desc['table']; + $r = sql_fetsel($s, $t, "$_id=$id", '','','','',$connect); + $texte = trim($texte); + if ($r AND !$texte) { + $texte = supprimer_numero($r['titre']); + if (!$texte) $texte = $r['surnom']; + if (!$texte) $texte = $id; + $lang = $r['lang']; + } + $style = 'spip_in'; + } else $style = 'spip_out'; + + return ($pour=='titre') ? $texte : array($url, $style, $texte, $lang); +} + +// traite les modeles (dans la fonction typo), en remplacant +// le raccourci <modeleN|parametres> par la page calculee a +// partir du squelette modeles/modele.html +// Le nom du modele doit faire au moins trois caracteres (evite <h2>) +// Si $doublons==true, on repere les documents sans calculer les modeles +// mais on renvoie les params (pour l'indexation par le moteur de recherche) +// http://doc.spip.org/@traiter_modeles + +define('_RACCOURCI_MODELE', + '(<([a-z_-]{3,})' # <modele + .'\s*([0-9]*)\s*' # id + .'([|](?:<[^<>]*>|[^>])*?)?' # |arguments (y compris des tags <...>) + .'\s*/?'.'>)' # fin du modele > + .'\s*(<\/a>)?' # eventuel </a> + ); + +define('_RACCOURCI_MODELE_DEBUT', '@^' . _RACCOURCI_MODELE .'@is'); + +// http://doc.spip.org/@traiter_modeles +function traiter_modeles($texte, $doublons=false, $echap='', $connect='') { + // detecter les modeles (rapide) + if (preg_match_all('/<[a-z_-]{3,}\s*[0-9|]+/iS', + $texte, $matches, PREG_SET_ORDER)) { + include_spip('public/assembler'); + foreach ($matches as $match) { + // Recuperer l'appel complet (y compris un eventuel lien) + + $a = strpos($texte,$match[0]); + preg_match(_RACCOURCI_MODELE_DEBUT, substr($texte, $a), $regs); + $regs[]=""; // s'assurer qu'il y a toujours un 5e arg, eventuellement vide + list(,$mod, $type, $id, $params, $fin) = $regs; + if ($fin AND preg_match( + ',<a\s[^<>]*>\s*$,i', substr($texte, 0, $a), $r)) { + $lien = array( + extraire_attribut($r[0],'href'), + extraire_attribut($r[0],'class') + ); + $n = strlen($r[0]); + $a -= $n; + $cherche = $n + strlen($regs[0]); + } else { + $lien = false; + $cherche = strlen($mod); + } + + // calculer le modele + # hack articles_edit, breves_edit, indexation + if ($doublons) + $texte .= preg_replace(',[|][^|=]*,s',' ',$params); + # version normale + else { + $modele = inclure_modele($type, $id, $params, $lien, $connect); + + // le remplacer dans le texte + if ($modele !== false) { + $modele = protege_js_modeles($modele); + $rempl = code_echappement($modele, $echap); + $texte = substr($texte, 0, $a) + . $rempl + . substr($texte, $a+$cherche); + } + } + + // hack pour tout l'espace prive + if (((!_DIR_RESTREINT) OR ($doublons)) AND ($id) AND (in_array($type,array('doc','emb','img')))) + $GLOBALS['doublons_documents_inclus'][] = $id; + } } - return array($lien, 'spip_in', $texte); # pas de hreflang + + return $texte; } -// http://doc.spip.org/@calculer_url_site_dist -function calculer_url_site_dist($id, $texte='', $lien='', $connect='') +// +// Raccourcis ancre [#ancre<-] +// + +define('_RACCOURCI_ANCRE', "|\[#?([^][]*)<-\]|S"); + +// http://doc.spip.org/@traiter_raccourci_ancre +function traiter_raccourci_ancre($letexte) { - # attention dans le cas des sites le lien pointe non pas sur - # la page locale du site, mais directement sur le site lui-meme - $row =sql_fetsel('nom_site,url_site', 'spip_syndic', "id_syndic=$id",'','','','',$connect); - if ($row) { - $lien = $row['url_site']; - if (!trim($texte)) - $texte = supprimer_numero($row['nom_site']); - if (!trim($texte)) $texte = $id; + if (preg_match_all(_RACCOURCI_ANCRE, $letexte, $m, PREG_SET_ORDER)) + foreach ($m as $regs) + $letexte = str_replace($regs[0], + '<a name="'.entites_html($regs[1]).'"></a>', $letexte); + return $letexte; +} + +// +// Raccourcis automatiques [?SPIP] vers un glossaire +// Wikipedia par defaut, avec ses contraintes techniques +// cf. http://fr.wikipedia.org/wiki/Wikip%C3%A9dia:Conventions_sur_les_titres + +define('_RACCOURCI_GLOSSAIRE', "|\[\?+\s*([^][<>]+)\]|S"); + +// http://doc.spip.org/@traiter_raccourci_glossaire +function traiter_raccourci_glossaire($letexte) +{ + if (!preg_match_all(_RACCOURCI_GLOSSAIRE, $letexte, $m, PREG_SET_ORDER)) + return $letexte; + + include_spip('inc/charsets'); + + foreach ($m as $regs) { + // Eviter les cas particulier genre "[?!?]" + // et isoler le lexeme a gloser de ses accessoires + // (#:url du glossaire, | bulle d'aide, {} lang) + + if (preg_match(',^([^|#{]*\w[^|#{]*)([^#]*)(#([^|{}]*))?(.*)$,', $regs[1], $r)) { + + list($terme, $bulle, $hlang) = traiter_raccourci_lien_atts($r[1] . $r[2] . $r[5]); + + $terme = unicode2charset(charset2unicode($terme), 'utf-8'); + + if ($r[4] AND function_exists($f = 'glossaire_' . $r[4])) + $glose = $f($terme); + else $glose = glossaire_std($terme); + $ref = traiter_raccourci_lien_lang($glose, 'spip_glossaire', $terme, $hlang, '', $bulle); + $letexte = str_replace($regs[0], $ref, $letexte); + } } - return array($lien, 'spip_out', $texte, $row['lang']); + return $letexte; } -// http://doc.spip.org/@calculer_url_forum_dist -function calculer_url_forum_dist($id, $texte='', $lien='', $connect='') +function glossaire_std($terme) { - if (!trim($texte)) { - $row = sql_fetsel('titre', 'spip_forum', "id_forum=$id AND statut='publie'",'','','','',$connect); - $texte = $row['titre']; - if (!trim($texte)) $texte = $id; + global $url_glossaire_externe; + static $pcre = NULL; + + if ($pcre === NULL) { + $pcre = isset($GLOBALS['meta']['pcre_u']) + ? $GLOBALS['meta']['pcre_u'] + : ''; + if (strpos($url_glossaire_externe, "%s") === false) + $url_glossaire_externe .= '%s'; } - return array($lien, 'spip_in', $texte); # pas de hreflang + + $glosateur = str_replace("@lang@", + $GLOBALS['spip_lang'], + $GLOBALS['url_glossaire_externe']); + + $terme = rawurlencode(preg_replace(',\s+,'.$pcre, '_', $terme)); + + return str_replace("%s", $terme, $glosateur); } + ?> diff --git a/ecrire/inc/texte.php b/ecrire/inc/texte.php index 19da34a42d..139c7f3b53 100644 --- a/ecrire/inc/texte.php +++ b/ecrire/inc/texte.php @@ -14,6 +14,7 @@ if (!defined("_ECRIRE_INC_VERSION")) return; include_spip('inc/filtres'); include_spip('inc/lang'); +include_spip('inc/lien'); // // Gerer les variables de personnalisation, qui peuvent provenir @@ -124,12 +125,6 @@ define('_BALISES_BLOCS', .'d[ltd]|script|noscript|map|button|fieldset'); -// Ne pas afficher le chapo si article virtuel -// http://doc.spip.org/@nettoyer_chapo -function nettoyer_chapo($chapo){ - return (substr($chapo,0,1) == "=") ? '' : $chapo; -} - // // Echapper les les elements perilleux en les passant en base64 @@ -314,28 +309,6 @@ function echappe_retour_modeles($letexte) return trim($letexte); } -// http://doc.spip.org/@nettoyer_raccourcis_typo -function nettoyer_raccourcis_typo($texte, $connect=''){ - $texte = pipeline('nettoyer_raccourcis_typo',$texte); - // remplacer les liens - if (preg_match_all(',[[]([^][]*)->(>?)([^][]*)[]],S', $texte, $regs, PREG_SET_ORDER)) - foreach ($regs as $reg) { - list ($titre,,)= traiter_raccourci_lien_atts($reg[1]); - $titre = calculer_url($reg[3], $titre, 'titre', $connect); - $titre = corriger_typo(supprimer_tags($titre)); - $texte = str_replace($reg[0], $titre, $texte); - } - - // supprimer les notes - $texte = preg_replace(",[[][[]([^]]|[]][^]])*[]][]],UimsS","",$texte); - - // supprimer les codes typos - $texte = str_replace(array('}','{'), '', $texte); - - // supprimer les tableaux - $texte = preg_replace(",(^|\r)\|.*\|\r,s", "\r", $texte); - return $texte; -} // http://doc.spip.org/@couper function couper($texte, $taille=50, $suite = ' (...)') { @@ -602,83 +575,6 @@ function corriger_typo($letexte) { } -// analyse des raccourcis issus de [TITRE->RACCOURCInnn] et connexes - -define('_RACCOURCI_URL', ',^\s*(\w*?)\s*(\d+)(\?(.*?))?(#([^\s]*))?\s*$,S'); - -// http://doc.spip.org/@typer_raccourci -function typer_raccourci ($lien) { - if (!preg_match(_RACCOURCI_URL, $lien, $match)) return array(); - $f = $match[1]; - // valeur par defaut et alias historiques - if (!$f) $f = 'article'; - else if ($f == 'art') $f = 'article'; - else if ($f == 'br') $f = 'breve'; - else if ($f == 'rub') $f = 'rubrique'; - else if ($f == 'aut') $f = 'auteur'; - else if ($f == 'doc' OR $f == 'im' OR $f == 'img' OR $f == 'image' OR $f == 'emb') - $f = 'document'; - else if (preg_match(',^br..?ve$,S', $f)) $f = 'breve'; # accents :( - $match[0] = $f; - $match[2] = entites_html($match[2]); - return $match; -} - -// Cherche un lien du type [->raccourci 123] -// associe a une fonction generer_url_raccourci() definie explicitement -// ou implicitement par le jeu de type_urls courant. -// -// Valeur retournee selon le parametre $pour: -// 'tout' : tableau [U,C,T,L] (vise <a href="U" class='C' hreflang='L'>T</a>) -// 'titre': seulement T ci-dessus (i.e. le TITRE ci-dessus ou dans table SQL) -// 'url': seulement U (i.e. generer_url_RACCOURCI) - -// http://doc.spip.org/@calculer_url -function calculer_url ($ref, $texte='', $pour='url', $connect='') { - if ($match = typer_raccourci($ref)) { - @list($type,,$id,,$args,,$ancre) = $match; - $r = generer_url_entite($id,$type,$args,$ancre, $connect ? $connect : NULL); - if ($r) { - if ($pour === 'url') return $r; - include_spip('inc/lien'); - $g = 'calculer_url_' . $type; - if (!(function_exists($g) OR function_exists($g .= '_dist'))) - $r = array($r, '', $texte); - else $r = $g($id, $texte, $r, $connect); - return ($pour=='tout') ? $r : $r[2]; - } - } - if (preg_match(",^\s*(http:?/?/?|mailto:?)\s*$,iS", $ref)) - return ($pour != 'tout') ? '' : array('','','',''); - - $lien = entites_html(trim($ref)); - - // Liens explicites - if (!$texte) { - $texte = str_replace('"', '', $lien); - if (strlen($texte)>40) - $texte = substr($texte,0,35).'...'; - $texte = "<html>$texte</html>"; - $class = "spip_url spip_out"; - } else $class = "spip_out"; - - if ($pour == 'titre') return $texte; - - // petites corrections d'URL - if (preg_match(",^www\.[^@]+$,S",$lien)) - $lien = "http://".$lien; - else if (strpos($lien, "@") && email_valide($lien)) - $lien = "mailto:".$lien; - - if (preg_match(",^\s*mailto:,",$lien)) - $class = "spip_mailto"; - - // class spip_ancre sur les ancres pures (internes a la page) - if (substr($lien,0,1) == '#') - $class = 'spip_ancre'; - - return ($pour == 'url') ? $lien : array($lien, $class, $texte, ''); -} // // Tableaux @@ -913,79 +809,6 @@ function supprime_img($letexte, $message=NULL) { $message, $letexte); } -// traite les modeles (dans la fonction typo), en remplacant -// le raccourci <modeleN|parametres> par la page calculee a -// partir du squelette modeles/modele.html -// Le nom du modele doit faire au moins trois caracteres (evite <h2>) -// Si $doublons==true, on repere les documents sans calculer les modeles -// mais on renvoie les params (pour l'indexation par le moteur de recherche) -// http://doc.spip.org/@traiter_modeles - -define('_RACCOURCI_MODELE', - '(<([a-z_-]{3,})' # <modele - .'\s*([0-9]*)\s*' # id - .'([|](?:<[^<>]*>|[^>])*?)?' # |arguments (y compris des tags <...>) - .'\s*/?'.'>)' # fin du modele > - .'\s*(<\/a>)?' # eventuel </a> - ); - -define('_RACCOURCI_MODELE_DEBUT', '@^' . _RACCOURCI_MODELE .'@is'); - -// http://doc.spip.org/@traiter_modeles -function traiter_modeles($texte, $doublons=false, $echap='', $connect='') { - // detecter les modeles (rapide) - if (preg_match_all('/<[a-z_-]{3,}\s*[0-9|]+/iS', - $texte, $matches, PREG_SET_ORDER)) { - include_spip('public/assembler'); - foreach ($matches as $match) { - // Recuperer l'appel complet (y compris un eventuel lien) - - $a = strpos($texte,$match[0]); - preg_match(_RACCOURCI_MODELE_DEBUT, substr($texte, $a), $regs); - $regs[]=""; // s'assurer qu'il y a toujours un 5e arg, eventuellement vide - list(,$mod, $type, $id, $params, $fin) = $regs; - if ($fin AND preg_match( - ',<a\s[^<>]*>\s*$,i', substr($texte, 0, $a), $r)) { - $lien = array( - extraire_attribut($r[0],'href'), - extraire_attribut($r[0],'class') - ); - $n = strlen($r[0]); - $a -= $n; - $cherche = $n + strlen($regs[0]); - } else { - $lien = false; - $cherche = strlen($mod); - } - - // calculer le modele - # hack articles_edit, breves_edit, indexation - if ($doublons) - $texte .= preg_replace(',[|][^|=]*,s',' ',$params); - # version normale - else { - $modele = inclure_modele($type, $id, $params, $lien, $connect); - - // le remplacer dans le texte - if ($modele !== false) { - $modele = protege_js_modeles($modele); - $rempl = code_echappement($modele, $echap); - $texte = substr($texte, 0, $a) - . $rempl - . substr($texte, $a+$cherche); - } - } - - // hack pour tout l'espace prive - if (((!_DIR_RESTREINT) OR ($doublons)) AND ($id) AND (in_array($type,array('doc','emb','img')))) - $GLOBALS['doublons_documents_inclus'][] = $id; - } - } - - return $texte; -} - - // // Une fonction pour fermer les paragraphes ; on essaie de preserver // des paragraphes indiques a la main dans le texte @@ -1036,200 +859,6 @@ function paragrapher($letexte, $forcer=true) { return $letexte; } -// -// Raccourcis ancre [#ancre<-] -// - -define('_RACCOURCI_ANCRE', "|\[#?([^][]*)<-\]|S"); - -// http://doc.spip.org/@traiter_raccourci_ancre -function traiter_raccourci_ancre($letexte) -{ - if (preg_match_all(_RACCOURCI_ANCRE, $letexte, $m, PREG_SET_ORDER)) - foreach ($m as $regs) - $letexte = str_replace($regs[0], - '<a name="'.entites_html($regs[1]).'"></a>', $letexte); - return $letexte; -} - -// -// Raccourcis automatiques [?SPIP] vers un glossaire -// Wikipedia par defaut, avec ses contraintes techniques -// cf. http://fr.wikipedia.org/wiki/Wikip%C3%A9dia:Conventions_sur_les_titres - -define('_RACCOURCI_GLOSSAIRE', "|\[\?+\s*([^][<>]+)\]|S"); - -// http://doc.spip.org/@traiter_raccourci_glossaire -function traiter_raccourci_glossaire($letexte) -{ - if (!preg_match_all(_RACCOURCI_GLOSSAIRE, $letexte, $m, PREG_SET_ORDER)) - return $letexte; - - include_spip('inc/charsets'); - - foreach ($m as $regs) { - // Eviter les cas particulier genre "[?!?]" - // et isoler le lexeme a gloser de ses accessoires - // (#:url du glossaire, | bulle d'aide, {} lang) - - if (preg_match(',^([^|#{]*\w[^|#{]*)([^#]*)(#([^|{}]*))?(.*)$,', $regs[1], $r)) { - - list($terme, $bulle, $hlang) = traiter_raccourci_lien_atts($r[1] . $r[2] . $r[5]); - - $terme = unicode2charset(charset2unicode($terme), 'utf-8'); - - if ($r[4] AND function_exists($f = 'glossaire_' . $r[4])) - $glose = $f($terme); - else $glose = glossaire_std($terme); - $ref = traiter_raccourci_lien_lang($glose, 'spip_glossaire', $terme, $hlang, '', $bulle); - $letexte = str_replace($regs[0], $ref, $letexte); - } - } - return $letexte; -} - -function glossaire_std($terme) -{ - global $url_glossaire_externe; - static $pcre = NULL; - - if ($pcre === NULL) { - $pcre = isset($GLOBALS['meta']['pcre_u']) - ? $GLOBALS['meta']['pcre_u'] - : ''; - if (strpos($url_glossaire_externe, "%s") === false) - $url_glossaire_externe .= '%s'; - } - - $glosateur = str_replace("@lang@", - $GLOBALS['spip_lang'], - $GLOBALS['url_glossaire_externe']); - - $terme = rawurlencode(preg_replace(',\s+,'.$pcre, '_', $terme)); - - return str_replace("%s", $terme, $glosateur); -} - -// -// Raccourcis liens [xxx->url] -// Note : complique car c'est ici qu'on applique typo(), -// et en plus on veut pouvoir les passer en pipeline -// - -// Regexp des raccouris, aussi utilisee pour la fusion de sauvegarde Spip -// Laisser passer des paires de crochets pour la balise multi -// mais refuser plus d'imbrications ou de mauvaises imbrications -// sinon les crochets ne peuvent plus servir qu'a ce type de raccourci -define('_RACCOURCI_LIEN', ",\[([^][]*?([[]\w*[]][^][]*)*)->(>?)([^]]*)\],msS"); - -// http://doc.spip.org/@expanser_liens -function expanser_liens($letexte, $connect='') -{ - $letexte = pipeline('pre_liens', $letexte); - - $inserts = array(); - if (preg_match_all(_RACCOURCI_LIEN, $letexte, $matches, PREG_SET_ORDER)) { - $i = 0; - foreach ($matches as $regs) { - $n = count($regs); - list($texte, $bulle, $hlang) = traiter_raccourci_lien_atts($regs[1]); - list ($lien, $class, $texte, $lang) = - calculer_url($regs[$n-1], $texte, 'tout', $connect); - $inserts[++$i] = traiter_raccourci_lien_lang($lien, $class, $texte, $hlang, $lang, $bulle, $connect); - - $letexte = str_replace($regs[0], "@@SPIP_ECHAPPE_LIEN_$i@@", - $letexte); - } - } - - $letexte = corriger_typo(traiter_modeles($letexte, false, false, $connect)); - foreach ($inserts as $i => $insert) { - $letexte = str_replace("@@SPIP_ECHAPPE_LIEN_$i@@", $insert, $letexte); - } - return $letexte; -} - -// http://doc.spip.org/@traiter_raccourci_lien_lang -function traiter_raccourci_lien_lang($lien, $class, $texte, $hlang, $lang, $bulle, $connect='') -{ - // Si l'objet n'est pas de la langue courante, on ajoute hreflang - if (!$hlang AND $lang!=$GLOBALS['spip_lang']) - $hlang = $lang; - $lang = ($hlang ? ' hreflang="'.$hlang.'"' : '') . $bulle; - - # ceci s'execute heureusement avant les tableaux et leur "|". - # Attention, le texte initial est deja echappe mais pas forcement - # celui retourne par calculer_url. - - # Penser au cas [<imgXX|right>->URL], qui exige typo('<a>...</a>') - return typo('<a href="'.$lien - . ($class ? '" class="'.$class : '') - . '"'.$lang.'>' - . $texte.'</a>', true, $connect); -} - -// Repere dans la partie texte d'un raccourci [texte->...] -// la langue et la bulle eventuelles - -// http://doc.spip.org/@traiter_raccourci_lien_atts -function traiter_raccourci_lien_atts($texte) { - - $bulle = $hlang = ''; - // title et hreflang donnes par le raccourci ? - if (preg_match(',^(.*?)([|]([^<>]*?))?([{]([a-z_]+)[}])?$,', $texte, $m)) { - - $n =count($m); - // |infobulle ? - if ($n > 2) { - $bulle = ' title="'.texte_backend($m[3]).'"'; - // {hreflang} ? - if ($n > 4) { - // si c'est un code de langue connu, on met un hreflang - if (traduire_nom_langue($m[5]) <> $m[5]) { - $hlang = $m[5]; - } - // sinon c'est un italique - else { - $m[1] .= $m[4]; - } - - // S'il n'y a pas de hreflang sous la forme {}, ce qui suit le | - // est peut-etre une langue - } else if (preg_match(',^[a-z_]+$,', $m[3])) { - // si c'est un code de langue connu, on met un hreflang - // mais on laisse le title (c'est arbitraire tout ca...) - if (traduire_nom_langue($m[3]) <> $m[3]) { - $hlang = $m[3]; - } - } - } - $texte = $m[1]; - } - - return array($texte, $bulle, $hlang); -} - -// Fonction pour les champs chapo commencant par =, redirection qui peut etre: -// 1. un raccourci Spip habituel (premier If) [texte->TYPEnnn] -// 2. un ultra raccourci TYPEnnn voire nnn (article) (deuxieme If) -// 3. une URL std -// renvoie une tableau structure comme ci-dessus mais sans calcul d'URL -// (cf fusion de sauvegardes) - -define('_RACCOURCI_CHAPO', ',^(\W*)(\W*)(\w*\d+([?#].*)?)$,'); - -// http://doc.spip.org/@chapo_redirige -function chapo_redirige($chapo, $url=false) -{ - if (!preg_match(_RACCOURCI_LIEN, $chapo, $m)) - if (!preg_match(_RACCOURCI_CHAPO, $chapo, $m)) - return $chapo; - return !$url ? $m[3] : calculer_url($m[3]); -} - -// http://doc.spip.org/@chapo_redirigetil -function chapo_redirigetil($chapo) { return $chapo && $chapo[0] == '=';} - // http://doc.spip.org/@traiter_poesie function traiter_poesie($letexte) { @@ -1248,44 +877,6 @@ function traiter_poesie($letexte) return $letexte; } -// callback pour la fonction traiter_raccourci_liens() -// http://doc.spip.org/@autoliens_callback -function autoliens_callback($r) { - if (strlen($l = $r[1])) { - // reperer le protocole - $protocol = 'http'; - if (preg_match(',^((https?):/*),S', $l, $m)) { - $l = substr($l, strlen($m[1])); - $protocol = $m[2]; - } - // valider le nom de domaine - if (preg_match( - '/^(?:[^\W_]((?:[^\W_]|-){0,61}[^\W_,])?\.)+[a-z]{2,6}\b/Si', $l)) { - // supprimer les ponctuations a la fin d'une URL - preg_match('/^(.*?)([,.;?]?)$/', $l, $k); - $l = inserer_attribut( - expanser_liens('[->'.$protocol.'://'.$k[1].']'), - 'rel', 'nofollow') - .$k[2]; - // si le texte ne contenait pas le 'http:' on le supprime aussi - if (!$m) - $l = str_replace('>http://', '>', $l); - return $l; - } - } - return $r[0]; -} - -// extraire les liens ecrits en mode texte brut -// http://doc.spip.org/@traiter_raccourci_liens -function traiter_raccourci_liens($texte) { - return preg_replace_callback( - ';\[[^\[\]]*(?:<-|->).*?\]|<a\b.*?</a\b|<.*?>|' - .'((?:https?:/|www\.)[^"\'\s\[\]\}\)<>]*);imsS', - 'autoliens_callback', $texte); - return $texte; -} - // Harmonise les retours chariots et mange les paragraphes html // http://doc.spip.org/@traiter_retours_chariots function traiter_retours_chariots($letexte) { -- GitLab