Newer
Older
/***************************************************************************\
* SPIP, Systeme de publication pour l'internet *
* *
* Arnaud Martin, Antoine Pitrou, Philippe Riviere, Emmanuel Saint-James *
* *
* Ce programme est un logiciel libre distribue sous licence GNU/GPL. *
* Pour plus de details voir le fichier COPYING.txt ou l'aide en ligne. *
\***************************************************************************/
if (!defined("_ECRIRE_INC_VERSION")) return;
//
// Gerer les variables de personnalisation, qui peuvent provenir
// des fichiers d'appel, en verifiant qu'elles n'ont pas ete passees
// par le visiteur (sinon, pas de cache)
//
// http://doc.spip.org/@tester_variable
function tester_variable($var, $val){
if (!isset($GLOBALS[$var]))
return $GLOBALS[$var] = $val;
if (
isset($_REQUEST[$var])
AND $GLOBALS[$var] == $_REQUEST[$var]
)
die ("tester_variable: $var interdite");
return $GLOBALS[$var];
// Init des globales reglant la typo de propre
// voir aussi traiter_raccourci_glossaire et traiter_raccourci_notes
// Retourne aussi un double tableau raccourci / texte-clair les utilisant.
global $class_spip, $class_spip_plus;
// class_spip : savoir si on veut class="spip" sur p i strong & li
// class_spip_plus : class="spip" sur les ul ol h3 hr quote table...
// la difference c'est que des css specifiques existent pour les seconds
tester_variable('class_spip', ''); /*' class="spip"'*/
tester_variable('class_spip_plus', ' class="spip"');
tester_variable('toujours_paragrapher', true);
return array(array(
/* 0 */ "/\n(----+|____+)/S",
/* 1 */ "/\n-- */S",
/* 2 */ "/\n- */S", /* DOIT rester a cette position */
/* 3 */ "/\n_ +/S",
/* 4 */ "/(^|[^{])[{][{][{]/S",
/* 5 */ "/[}][}][}]($|[^}])/S",
/* 6 */ "/(( *)\n){2,}(<br\s*\/?".">)?/S",
/* 7 */ "/[{][{]/S",
/* 8 */ "/[}][}]/S",
/* 9 */ "/[{]/S",
/* 10 */ "/[}]/S",
/* 11 */ "/(?:<br\s*\/?".">){2,}/S",
/* 12 */ "/<p>\n*(?:<br\s*\/?".">\n*)*/S",
/* 13 */ "/<quote>/S",
/* 14 */ "/<\/quote>/S",
/* 15 */ "/<\/?intro>/S"
),
array(
/* 0 */ "\n\n" . tester_variable('ligne_horizontale', "\n<hr$class_spip_plus />\n") . "\n\n",
/* 1 */ "\n<br />— ",
/* 3 */ "\n<br />",
/* 4 */ "\$1\n\n" . tester_variable('debut_intertitre', "\n<h3$class_spip_plus>"),
/* 5 */ tester_variable('fin_intertitre', "</h3>\n") ."\n\n\$1",
/* 6 */ "<p>",
/* 7 */ tester_variable('debut_gras', "<strong$class_spip>"),
/* 8 */ tester_variable('fin_gras', '</strong>'),
/* 9 */ tester_variable('debut_italique', "<i$class_spip>"),
/* 10 */ tester_variable('fin_italique', '</i>'),
/* 11 */ "<p>",
/* 12 */ "<p>",
/* 13 */ "<blockquote$class_spip_plus><p>",
/* 14 */ "</blockquote><p>",
/* 15 */ ""
)
);
}
// On initialise la puce pour eviter find_in_path() a chaque rencontre de \n-
// Mais attention elle depend de la direction et de X_fonctions.php, ainsi que
// de l'espace choisi (public/prive)
// http://doc.spip.org/@definir_puce
function definir_puce() {
// Attention au sens, qui n'est pas defini de la meme facon dans
// l'espace prive (spip_lang est la langue de l'interface, lang_dir
// celle du texte) et public (spip_lang est la langue du texte)
$dir = _DIR_RESTREINT ? lang_dir() : lang_dir($GLOBALS['spip_lang']);
$p = 'puce' . (test_espace_prive() ? '_prive' : '');
if ($dir == 'rtl') $p .= '_rtl';
tester_variable($p, 'AUTO');
if ($GLOBALS[$p] == 'AUTO') {
$img = find_in_path($p.'.gif');
list(,,,$size) = @getimagesize($img);
$GLOBALS[$p] = '<img src="'.$img.'" '
.$size.' alt="-" />';
}
return $GLOBALS[$p];
// Diverses fonctions essentielles
// XHTML - Preserver les balises-bloc : on liste ici tous les elements
// dont on souhaite qu'ils provoquent un saut de paragraphe
define('_BALISES_BLOCS',
.'t(able|[rdh]|body|foot|extarea)|'
.'form|object|center|marquee|address|'
.'d[ltd]|script|noscript|map|button|fieldset');
// Ne pas afficher le chapo si article virtuel
// http://doc.spip.org/@nettoyer_chapo
return (substr($chapo,0,1) == "=") ? '' : $chapo;
//
// Echapper les les elements perilleux en les passant en base64
//
// Creer un bloc base64 correspondant a $rempl ; au besoin en marquant
// une $source differente ; le script detecte automagiquement si ce qu'on
// echappe est un div ou un span
// http://doc.spip.org/@code_echappement
function code_echappement($rempl, $source='') {
if (!strlen($rempl)) return '';
// Tester si on echappe en span ou en div
$mode = preg_match(',</?('._BALISES_BLOCS.')[>[:space:]],iS', $rempl) ?
'div' : 'span';
$nn = ($mode == 'div') ? "\n\n" : '';
$return = '';
// Decouper en morceaux, base64 a des probleme selon la taille de la pile
$taille = 30000;
for($i = 0; $i < strlen($rempl); $i += $taille) {
// Convertir en base64
$base64 = base64_encode(substr($rempl, $i, $taille));
$return .=
inserer_attribut("<$mode class=\"base64$source\">", 'title', $base64)
."</$mode>";
}
Fil
a validé
return $return . $nn;
Fil
a validé
// Echapper les <html>...</ html>
Christian Lefebvre
a validé
// http://doc.spip.org/@traiter_echap_html_dist
Fil
a validé
function traiter_echap_html_dist($regs) {
return $regs[3];
}
// Echapper les <code>...</ code>
Christian Lefebvre
a validé
// http://doc.spip.org/@traiter_echap_code_dist
Fil
a validé
function traiter_echap_code_dist($regs) {
$echap = htmlspecialchars($regs[3]); // il ne faut pas passer dans entites_html, ne pas transformer les &#xxx; du code !
Fil
a validé
// ne pas mettre le <div...> s'il n'y a qu'une ligne
if (is_int(strpos($echap,"\n"))) {
// supprimer les sauts de ligne debut/fin
// (mais pas les espaces => ascii art).
$echap = preg_replace("/^[\n\r]+|[\n\r]+$/s", "", $echap);
$echap = nl2br($echap);
$echap = "<div style='text-align: left;' "
Fil
a validé
. "class='spip_code' dir='ltr'><code>"
.$echap."</code></div>";
} else {
Fil
a validé
$echap = "<code class='spip_code' "
."dir='ltr'>".$echap."</code>";
Fil
a validé
$echap = str_replace("\t",
" ", $echap);
$echap = str_replace(" ", " ", $echap);
return $echap;
}
// Echapper les <cadre>...</ cadre> aka <frame>...</ frame>
Christian Lefebvre
a validé
// http://doc.spip.org/@traiter_echap_cadre_dist
Fil
a validé
function traiter_echap_cadre_dist($regs) {
$echap = trim(entites_html($regs[3]));
$n = substr_count($echap, "\n") + 1;
$echap = "\n<textarea readonly='readonly' cols='40' rows='$n' class='spip_cadre' dir='ltr'>$echap</textarea>";
return generer_form_ecrire('', $echap, " method='get'");
Fil
a validé
}
Christian Lefebvre
a validé
// http://doc.spip.org/@traiter_echap_frame_dist
Fil
a validé
function traiter_echap_frame_dist($regs) {
return traiter_echap_cadre_dist($regs);
}
Christian Lefebvre
a validé
// http://doc.spip.org/@traiter_echap_script_dist
Fil
a validé
function traiter_echap_script_dist($regs) {
// rendre joli (et inactif) si c'est un script language=php
if (preg_match(',<script\b[^>]+php,ims',
$regs[0]))
return highlight_string($regs[0],true);
// Cas normal : le script passe tel quel
Fil
a validé
return $regs[0];
}
// - pour $source voir commentaire infra (echappe_retour)
// - pour $no_transform voir le filtre post_autobr dans inc_filtres.php3
// http://doc.spip.org/@echappe_html
function echappe_html($letexte, $source='', $no_transform=false,
if (!strlen($letexte)) return '';
if (!$preg) $preg = ',<(html|code|cadre|frame|script)'
.'(\s[^>]*)?'
.'>(.*)</\1>,UimsS';
$letexte, $matches, PREG_SET_ORDER))
foreach ($matches as $regs) {
// echappements tels quels ?
if ($no_transform) {
$echap = $regs[0];
// sinon les traiter selon le cas
Fil
a validé
else if (function_exists($f = 'traiter_echap_'.strtolower($regs[1])))
$echap = $f($regs);
else if (function_exists($f = $f.'_dist'))
$echap = $f($regs);
$letexte = str_replace($regs[0],
code_echappement($echap, $source),
// Gestion du TeX
if (strpos($letexte, "<math>") !== false) {
$letexte = traiter_math($letexte, $source);
// Echapper le php pour faire joli (ici, c'est pas pour la securite)
if (preg_match_all(
',<[?].*($|[?]>),UisS',
$letexte, $matches, PREG_SET_ORDER))
foreach ($matches as $regs) {
$letexte = str_replace($regs[0],
code_echappement(highlight_string($regs[0],true), $source),
$letexte);
}
// Traitement final des echappements
// Rq: $source sert a faire des echappements "a soi" qui ne sont pas nettoyes
// par propre() : exemple dans ecrire/inc_articles_ortho.php, $source='ORTHO'
// ou encore dans typo()
// http://doc.spip.org/@echappe_retour
function echappe_retour($letexte, $source='', $filtre = "") {
Fil
a validé
if (strpos($letexte,"base64$source")) {
# spip_log(htmlspecialchars($letexte)); ## pour les curieux
if (preg_match_all(
',<(span|div) class=[\'"]base64'.$source.'[\'"]\s.*>\s*</\1>,UmsS',
$letexte, $regs, PREG_SET_ORDER)) {
foreach ($regs as $reg) {
Fil
a validé
$rempl = base64_decode(extraire_attribut($reg[0], 'title'));
if ($filtre) $rempl = $filtre($rempl);
$letexte = str_replace($reg[0], $rempl, $letexte);
}
}
}
return $letexte;
esj
a validé
}
// Reinserer le javascript de confiance (venant des modeles)
function echappe_retour_modeles($letexte)
{
$letexte = echappe_retour($letexte);
// Dans l'espace prive, securiser ici
if (!_DIR_RESTREINT)
$letexte = interdire_scripts($letexte);
// Reinserer les echappements des modeles
if (defined('_PROTEGE_JS_MODELES'))
$letexte = echappe_retour($letexte,"javascript"._PROTEGE_JS_MODELES);
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 = ' (...)') {
if (!strlen($texte) OR $taille <= 0) return '';
$offset = 400 + 2*$taille;
if ( $offset<strlen($texte)
&& ($p_tag_ouvrant = strpos($texte,'<',$offset))!==NULL){
$p_tag_fermant = strpos($texte,'>',$offset);
if ($p_tag_fermant<$p_tag_ouvrant)
$offset += $p_tag_fermant; // prolonger la coupe jusqu'au tag fermant suivant eventuel
}
$texte = substr($texte, 0, $offset); /* eviter de travailler sur 10ko pour extraire 150 caracteres */
// on utilise les \r pour passer entre les gouttes
Fil
a validé
$texte = str_replace("\r\n", "\n", $texte);
$texte = str_replace("\r", "\n", $texte);
// sauts de ligne et paragraphes
$texte = preg_replace("/<(p|br)( [^>]*)?".">/", "\r", $texte);
Fil
a validé
// supprimer les traits, lignes etc
$texte = preg_replace("/(^|\r|\n)(-[-#\*]*|_ )/", "\r", $texte);
Fil
a validé
// supprimer les tags
$texte = supprimer_tags($texte);
$texte = trim(str_replace("\n"," ", $texte));
$texte .= "\n"; // marquer la fin
// travailler en accents charset
$texte = unicode2charset(html2unicode($texte, /* secure */ true));
$texte = nettoyer_raccourcis_typo($texte);
// corriger la longueur de coupe
// en fonction de la presence de caracteres utf
if ($GLOBALS['meta']['charset']=='utf-8'){
$long = charset2unicode($texte);
$long = spip_substr($long, 0, max($taille,1));
$nbcharutf = preg_match_all("/(&#[0-9]{3,5};)/S",$long,$matches);
$taille += $nbcharutf;
}
// couper au mot precedent
$court = preg_replace("/([^\s][\s]+)[^\s]*\n?$/", "\\1", $long);
$points = $suite;
// trop court ? ne pas faire de (...)
$points = '';
$texte = preg_replace("/([^\s][\s]+)[^\s]*\n?$/", "\\1", $long);
// encore trop court ? couper au caractere
$texte = $long;
} else
$texte = $court;
if (strpos($texte, "\n")) // la fin est encore la : c'est qu'on n'a pas de texte de suite
$points = '';
// remettre les paragraphes
$texte = preg_replace("/\r+/", "\n\n", $texte);
$texte = preg_replace('/&#?[a-z0-9]*$/S', '', $texte);
// Les elements de propre()
// Securite : empecher l'execution de code PHP ou javascript ou autre malice
// http://doc.spip.org/@interdire_scripts
function interdire_scripts($source) {
$source = preg_replace(",<(\%|\?|/?[[:space:]]*(script|base)),imsS", "<\\1", $source);
return $source;
*/
// afficher joliment les <script>
Christian Lefebvre
a validé
// http://doc.spip.org/@echappe_js
function echappe_js($t,$class='') {
if (preg_match_all(',<script.*?($|</script.),isS', $t, $r, PREG_SET_ORDER))
foreach ($r as $regs)
$t = str_replace($regs[0],
"<code$class>".nl2br(htmlspecialchars($regs[0])).'</code>',
$t);
return $t;
}
function protege_js_modeles($t) {
if (isset($GLOBALS['auteur_session'])){
if (!defined('_PROTEGE_JS_MODELES')){
include_spip('inc/acces');
define('_PROTEGE_JS_MODELES',creer_uniqid());
}
if (preg_match_all(',<script.*?($|</script.),isS', $t, $r, PREG_SET_ORDER))
foreach ($r as $regs)
$t = str_replace($regs[0],code_echappement($regs[0],'javascript'._PROTEGE_JS_MODELES),$t);
}
return $t;
}
// Securite : empecher l'execution de code PHP, en le transformant en joli code
// http://doc.spip.org/@interdire_scripts
function interdire_scripts($t) {
// rien ?
if (!$t OR !strstr($t, '<')) return $t;
$t = str_replace('<'.'%', '<%', $t);
// echapper le php
$t = str_replace('<'.'?', '<?', $t);
// echapper le < script language=php >
$t = preg_replace(',<(script\b[^>]+\blanguage\b[^\w>]+php\b),UimsS', '<\1', $t);
// Pour le js, trois modes : parano (-1), prive (0), ok (1)
switch($GLOBALS['filtrer_javascript']) {
case 0:
if (!_DIR_RESTREINT)
$t = echappe_js($t,' style="color:red"');
break;
case -1:
$t = echappe_js($t);
break;
}
// pas de <base href /> svp !
$t = preg_replace(',<(base\s),iS', '<\1', $t);
return $t;
}
// Securite : utiliser SafeHTML s'il est present dans ecrire/safehtml/
// http://doc.spip.org/@safehtml
function safehtml($t) {
static $safehtml;
# attention safehtml nettoie deux ou trois caracteres de plus. A voir
if (strpos($t,'<')===false)
return str_replace("\x00", '', $t);
$t = interdire_scripts($t); // jolifier le php
$t = echappe_js($t);
if (!isset($safehtml))
$safehtml = charger_fonction('safehtml', 'inc');
if ($safehtml)
$t = $safehtml($t);
return interdire_scripts($t); // interdire le php (2 precautions)
Antoine Pitrou
a validé
// Typographie generale
// avec protection prealable des balises HTML et SPIP
function typo($letexte, $echapper=true, $connect='') {
// Plus vite !
if (!$letexte) return $letexte;
if ($echapper)
$letexte = echappe_html($letexte, 'TYPO');
//
// Installer les modeles, notamment images et documents ;
//
// NOTE : propre() l'a deja fait
// sauf pour les textes renvoyes par calculer_url()
$letexte = traiter_modeles($mem = $letexte, false, $echapper ? 'TYPO' : '', $connect);
if ($letexte != $mem) $echapper = true;
unset($mem);
$letexte = corriger_typo($letexte);
// reintegrer les echappements
if ($echapper)
$letexte = echappe_retour($letexte, 'TYPO');
// Dans l'espace prive, securiser ici
if (!_DIR_RESTREINT)
$letexte = interdire_scripts($letexte);
return $letexte;
}
// Correcteur typographique
function corriger_typo($letexte) {
// Plus vite !
if (!$letexte) return $letexte;
// Caracteres de controle "illegaux"
$letexte = corriger_caracteres($letexte);
// Charger & appliquer la fonction de typographie
if ($typographie = charger_fonction(lang_typo(), 'typographie')) {
// Proteger les caracteres typographiques a l'interieur des tags html
$protege = "!':;?~%";
$illegal = "\x1\x2\x3\x4\x5\x6\x7";
if (preg_match_all(",</?[a-z!][^<>]*[!':;\?~%][^<>]*>,imsS",
$letexte, $regs, PREG_SET_ORDER)) {
foreach ($regs as $reg) {
$insert = $reg[0];
// hack: on transforme les caracteres a proteger en les remplacant
// par des caracteres "illegaux". (cf corriger_caracteres())
$insert = strtr($insert, $protege, $illegal);
$letexte = str_replace($reg[0], $insert, $letexte);
}
$letexte = $typographie($letexte);
// Retablir les caracteres proteges
$letexte = strtr($letexte, $illegal, $protege);
}
# un message pour abs_url - on est passe en mode texte
$GLOBALS['mode_abs_url'] = 'texte';
// analyse des raccourcis issus de [TITRE->RACCOURCInnn] et connexes
define('_RACCOURCI_URL', ',^\s*(\w*?)\s*(\d+)(\?(.*?))?(#([^\s]*))?\s*$,S');
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()
//
// 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 ($lien, $texte='', $pour='url', $connect='') {
include_spip('base/abstract_sql');
if ($match = typer_raccourci($lien)) {
@list($f,,$id,,$param,,$ancre) = $match;
$res = '';
if ($connect) {
$id_type = ($f != 'site') ? "id_$f" : 'id_syndic';
$res = get_spip_script('./')
. "?page=$f&$id_type=$id&connect=$connect"
. (!$param ? '' : "&$param");
} else {
charger_generer_url();
$g = 'generer_url_' . $f;
if (function_exists($g) OR function_exists($g .= '_dist'))
$res = $g($id, $param, $ancre);
}
if ($res) {
if ($pour == 'url') return $res;
$g = 'calculer_url_' . $f;
if (function_exists($g) OR function_exists($g .= '_dist')) {
if ($pour == 'tout')
return $g($id, $texte, $res, $connect);
$res = $g($id, $texte, $res, $connect);
return $res[2];
}
}
spip_log("raccourci indefini $f");
return calculer_url_sans_rac($lien, $texte, $pour);
}
// cf specif ci-dessus
function calculer_url_sans_rac ($lien, $texte='', $pour='url') {
if (preg_match(",^\s*(http:?/?/?|mailto:?)\s*$,iS", $lien))
return ($pour != 'tout') ? '' : array('','','','');
$lien = entites_html(trim($lien));
// 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;
// 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, '');
function calculer_url_article_dist($id, $texte='', $lien='', $connect='') {
$row = sql_fetsel('titre,lang', 'spip_articles', "id_article=$id",'','','','','','','',$connect);
$texte = supprimer_numero($row['titre']);
$texte = _T('article') . $id;
return array($lien, 'spip_in', $texte, $row['lang']);
function calculer_url_rubrique_dist($id, $texte='', $lien='', $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;
}
return array($lien, 'spip_in', $texte, $row['lang']);
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;
}
return array($lien, 'spip_in', $texte, $row['lang']);
function calculer_url_auteur_dist($id, $texte='', $lien='', $connect='')
if ($texte=='') {
$row = sql_fetsel('nom', 'spip_auteurs', "id_auteur=$id",'','','','','','','',$connect);
return array($lien, 'spip_in', $texte); # pas de hreflang
// http://doc.spip.org/@calculer_url_mot_dist
function calculer_url_mot_dist($id, $texte='', $lien='', $connect='')
{
if (!trim($texte)) {
$row = sql_fetsel('titre', 'spip_mots', "id_mot=$id",'','','','','','','',$connect);
$texte = supprimer_numero($row['titre']);
if (!trim($texte)) $texte = $id;
}
return array($lien, 'spip_in', $texte);
}
function calculer_url_document_dist($id, $texte='', $lien='', $connect='')
if ($texte=='') {
$row = sql_fetsel('titre,fichier', 'spip_documents', "id_document=$id",'','','','','','','',$connect);
$texte = preg_replace(",^.*/,","",$row['fichier']);
return array($lien, 'spip_in', $texte); # pas de hreflang
function calculer_url_site_dist($id, $texte='', $lien='', $connect='')
{
# 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'];
$texte = supprimer_numero($row['nom_site']);
if (!trim($texte)) $texte = $id;
return array($lien, 'spip_out', $texte, $row['lang']);
function calculer_url_forum_dist($id, $texte='', $lien='', $connect='')
Fil
a validé
{
$row = sql_fetsel('titre', 'spip_forum', "id_forum=$id AND statut='publie'",'','','','','','','',$connect);
if (!trim($texte)) $texte = $id;
Fil
a validé
}
return array($lien, 'spip_in', $texte); # pas de hreflang
}
// http://doc.spip.org/@traiter_tableau
function traiter_tableau($bloc) {
// Decouper le tableau en lignes
preg_match_all(',([|].*)[|]\n,UmsS', $bloc, $regs, PREG_PATTERN_ORDER);
$debut_table = $summary = '';
$l = 0;
// Traiter chaque ligne
foreach ($regs[1] as $ligne) {
$l ++;
// Gestion de la premiere ligne :
if ($l == 1) {
// - <caption> et summary dans la premiere ligne :
// || caption | summary || (|summary est optionnel)
if (preg_match(',^\|\|([^|]*)(\|(.*))?\|$,sS', $ligne, $cap)) {
if ($caption = trim($cap[1]))
$debut_table .= "<caption>".$caption."</caption>\n";
$summary = ' summary="'.entites_html(trim($cap[3])).'"';
}
// - <thead> sous la forme |{{titre}}|{{titre}}|
// Attention thead oblige a avoir tbody
else if (preg_match(',^(\|([[:space:]]*(:?{{[^}]+}}[[:space:]]*)?|<))+$,sS',
preg_match_all("/\|([^|]*)/S", $ligne, $cols);
$ligne='';$cols= $cols[1];
$colspan=1;
for($c=count($cols)-1; $c>=0; $c--) {
$attr='';
if($cols[$c]=='<') {
$colspan++;
} else {
if($colspan>1) {
$attr= " colspan='$colspan'";
$colspan=1;
}
$ligne= "<th scope='col'$attr>$cols[$c]</th>$ligne";
}
}
$debut_table .= "<thead><tr class='row_first'>".
$ligne."</tr></thead>\n";
$l = 0;
}
}
// Sinon ligne normale
if ($l) {
// Gerer les listes a puce dans les cellules
if (strpos($ligne,"\n-*")!==false OR strpos($ligne,"\n-#")!==false)
$ligne = traiter_listes($ligne);
$ligne = preg_replace("/\n{2,}/", "<br />\n", $ligne);
// tout mettre dans un tableau 2d
preg_match_all("/\|([^|]*)/S", $ligne, $cols);
$lignes[]= $cols[1];
}
}
// maintenant qu'on a toutes les cellules
// on prepare une liste de rowspan par defaut, a partir
// du nombre de colonnes dans la premiere ligne
$rowspans = array();
for ($i=0; $i<count($lignes[0]); $i++)
$rowspans[] = 1;
// et on parcourt le tableau a l'envers pour ramasser les
// colspan et rowspan en passant
for($l=count($lignes)-1; $l>=0; $l--) {
$cols= $lignes[$l];
$colspan=1;
$ligne='';
for($c=count($cols)-1; $c>=0; $c--) {
$attr='';
if($cols[$c]=='<') {
$colspan++;
} elseif($cols[$c]=='^') {
$rowspans[$c]++;
} else {
if($colspan>1) {
$attr.= " colspan='$colspan'";
$colspan=1;
}
if($rowspans[$c]>1) {
$attr.= " rowspan='$rowspans[$c]'";
$rowspans[$c]=1;
}
$ligne= '<td'.$attr.'>'.$cols[$c].'</td>'.$ligne;
}
// ligne complete
$class = 'row_'.alterner($l+1, 'even', 'odd');
$html = "<tr class=\"$class\">" . $ligne . "</tr>\n".$html;
return "\n\n<table".$GLOBALS['class_spip_plus'].$summary.">\n"
. "</table>\n\n";
// Traitement des listes (merci a Michael Parienti)
// http://doc.spip.org/@traiter_listes
function traiter_listes ($texte) {
global $class_spip, $class_spip_plus;
$parags = preg_split(",\n[[:space:]]*\n,S", $texte);
// chaque paragraphe est traite a part
while (list(,$para) = each($parags)) {
$niveau = 0;
$lignes = explode("\n-", "\n" . $para);
// ne pas toucher a la premiere ligne
list(,$debut) = each($lignes);
$texte .= $debut;
// chaque item a sa profondeur = nb d'etoiles
while (list(,$item) = each($lignes)) {
preg_match(",^([*]*|[#]*)([^*#].*)$,sS", $item, $regs);
$profond = strlen($regs[1]);
if ($profond > 0) {
// changement de type de liste au meme niveau : il faut
// descendre un niveau plus bas, fermer ce niveau, et
// remonter
$nouv_type = (substr($item,0,1) == '*') ? 'ul' : 'ol';
$change_type = ($type AND ($type <> $nouv_type) AND ($profond == $niveau)) ? 1 : 0;
$type = $nouv_type;
// d'abord traiter les descentes
while ($niveau > $profond - $change_type) {
$ajout .= $pile_li[$niveau];
$ajout .= $pile_type[$niveau];
// puis les identites (y compris en fin de descente)
if ($niveau == $profond && !$change_type) {
}
// puis les montees (y compris apres une descente un cran trop bas)
while ($niveau < $profond) {
if ($niveau == 0) $ajout .= "\n\n";
$ajout .= "<$type$class_spip_plus>";
$pile_type[$niveau] = "</$type>";
$pile_li[$profond] = "</li>";
Fil
a validé
$ajout = "\n-"; // puce normale ou <hr>
Fil
a validé
$texte .= $ajout . $regs[2];
}
// retour sur terre
while ($niveau > 0) {
$ajout .= $pile_li[$niveau];
$ajout .= $pile_type[$niveau];
$niveau --;
}
$texte .= $ajout;
// paragraphe
$texte .= "\n\n";
}
// sucrer les deux derniers \n
return substr($texte, 0, -2);
}
// fonction en cas de texte extrait d'un serveur distant:
// on ne sait pas (encore) rapatrier les documents joints
// TODO: gerer les modeles ?
// http://doc.spip.org/@supprime_img
function supprime_img($letexte) {
$message = _T('img_indisponible');
return preg_replace(',<(img|doc|emb)([0-9]+)(\|([^>]*))?'.'\s*/?'.'>,i',
"($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');
function traiter_modeles($texte, $doublons=false, $echap='', $connect='') {
// detecter les modeles (rapide)
Fil
a validé
if (preg_match_all('/<[a-z_-]{3,}\s*[0-9|]+/iS',
$texte, $matches, PREG_SET_ORDER)) {