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]))
$GLOBALS[$var] = $val;
if (
isset($_REQUEST[$var])
AND $GLOBALS[$var] == $_REQUEST[$var]
)
die ("tester_variable: $var interdite");
}
// on initialise la puce ici car il serait couteux de faire le find_in_path()
// a chaque hit, alors qu'on n'a besoin de cette valeur que lors du calcul
// http://doc.spip.org/@definir_puce
function definir_puce() {
static $les_puces = array();
// 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($GLOBALS['spip_lang']) : $GLOBALS['lang_dir'];
$p = ($dir == 'rtl') ? 'puce_rtl' : 'puce';
if (!isset($les_puces[$p])) {
tester_variable($p, 'AUTO');
if ($GLOBALS[$p] == 'AUTO') {
list(,,,$size) = @getimagesize($img);
$img = '<img src="'.$img.'" '
Fil
a validé
.$size.' alt="-" />';
} else
$img = $GLOBALS[$p];
$les_puces[$p] = $img;
}
return $les_puces[$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 '';
// Convertir en base64
$base64 = base64_encode($rempl);
// Tester si on echappe en span ou en div
$mode = preg_match(',</?('._BALISES_BLOCS.')[>[:space:]],iS', $rempl) ?
'div' : 'span';
$nn = ($mode == 'div') ? "\n\n" : '';
Fil
a validé
return
inserer_attribut("<$mode class=\"base64$source\">", 'title', $base64)
."</$mode>$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 = entites_html($regs[3]);
// supprimer les sauts de ligne debut/fin
// (mais pas les espaces => ascii art).
$echap = ereg_replace("^\n+|\n+$", "", $echap);
// ne pas mettre le <div...> s'il n'y a qu'une ligne
if (is_int(strpos($echap,"\n"))) {
$echap = nl2br("<div style='text-align: left;' "
. "class='spip_code' dir='ltr'><code>"
.$echap."</code></div>");
$mode = 'div';
} else
$echap = "<code class='spip_code' "
."dir='ltr'>".$echap."</code>";
$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]));
$total_lignes = substr_count($echap, "\n") + 1;
$echap = "<form action=\"/\" method=\"get\"><div>"
."<textarea readonly='readonly' cols='40' rows='$total_lignes' "
."class='spip_cadre' dir='ltr'>"
.$echap
."</textarea></div></form>";
return $echap;
}
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) {
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';
if (preg_match_all(
$letexte, $matches, PREG_SET_ORDER))
foreach ($matches as $regs) {
// mode d'echappement :
// <span class='base64'> . base64_encode(contenu) . </span>
// ou 'div' selon les cas, pour refermer correctement les paragraphes
$mode = 'span';
// 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='') {
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.*></\1>,UmsS',
$letexte, $regs, PREG_SET_ORDER)) {
foreach ($regs as $reg) {
Fil
a validé
$rempl = base64_decode(extraire_attribut($reg[0], 'title'));
$letexte = str_replace($reg[0], $rempl, $letexte);
}
}
}
return $letexte;
esj
a validé
}
// http://doc.spip.org/@nettoyer_raccourcis_typo
function nettoyer_raccourcis_typo($texte){
$texte = pipeline('nettoyer_raccourcis_typo',$texte);
// remplacer les liens
if (preg_match_all(',[[]([^][]*)->(>?)([^][]*)[]],S', $texte, $regs, PREG_SET_ORDER))
foreach ($regs as $reg) {
$titre = supprimer_tags(traiter_raccourci_lien($reg));
$texte = str_replace($reg[0], $titre, $texte);
}
// supprimer les notes
$texte = preg_replace(",\[\[([^]]|\][^]])*\]\],sS", "", $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) {
$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 = ereg_replace("\n\n+", "\r", $texte);
$texte = ereg_replace("<(p|br)( [^>]*)?".">", "\r", $texte);
Fil
a validé
// supprimer les traits, lignes etc
$texte = ereg_replace("(^|\r|\n)(-[-#\*]*|_ )", "\r", $texte);
// 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 = ereg_replace("([^[:space:]][[:space:]]+)[^[:space:]]*\n?$", "\\1", $long);
$points = ' (...)';
// trop court ? ne pas faire de (...)
$points = '';
$texte = ereg_replace("([^[:space:]][[:space:]]+)[^[:space:]]*$", "\\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 = ereg_replace("\r+", "\n\n", $texte);
$texte = preg_replace('/&#?[a-z0-9]*$/S', '', $texte);
// prendre <intro>...</intro> sinon couper a la longueur demandee
// http://doc.spip.org/@couper_intro
$texte = extraire_multi(eregi_replace("(</?)intro>", "\\1intro>", $texte)); // minuscules
$intro = '';
while ($fin = strpos($texte, "</intro>")) {
$zone = substr($texte, 0, $fin);
$texte = substr($texte, $fin + strlen("</intro>"));
if ($deb = strpos($zone, "<intro>") OR substr($zone, 0, 7) == "<intro>")
$zone = substr($zone, $deb + 7);
$intro .= $zone;
}
if ($intro)
$intro = $intro.' (...)';
$intro = preg_replace(',([|]\s*)+,S', '; ', couper($texte, $long));
// supprimer un eventuel chapo redirecteur =http:/.....
// 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
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
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;
}
// 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;
// echapper les tags asp
$t = str_replace('<'.'%', '<%', $t);
// echapper le php
$t = str_replace('<'.'?', '<?', $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 $process, $test;
# attention safehtml nettoie deux ou trois caracteres de plus. A voir
if (strpos($t,'<')===false)
return str_replace("\x00", '', $t);
$t = interdire_scripts($t);
$t = echappe_js($t);
define('XML_HTMLSAX3', dirname($f).'/');
$process = new safehtml();
$process->deleteTags[] = 'param'; // sinon bug Firefox
if ($process)
$test = 1; # ok
else
$test = -1; # se rabattre sur interdire_scripts
}
if ($test > 0) {
# reset ($process->clear() ne vide que _xhtml...),
# on doit pouvoir programmer ca plus propremement
$process->_counter = array();
$process->_stack = array();
$process->_dcCounter = array();
$process->_dcStack = array();
$process->_listScope = 0;
$process->_liStack = array();
# $process->parse(''); # cas particulier ?
$t = $process->parse($t);
return interdire_scripts($t); # gere le < ?php > en plus
Antoine Pitrou
a validé
// Correction typographique francaise
// http://doc.spip.org/@typo_fr
// Nettoyer 160 = nbsp ; 187 = raquo ; 171 = laquo ; 176 = deg ; 147 = ldquo; 148 = rdquo
if (!$trans) {
$trans = array(
" " => "~",
"»" => "»",
"«" => "«",
"”" => "”",
"“" => "“",
$chars = array(160 => '~', 187 => '»', 171 => '«', 148 => '”', 147 => '“', 176 => '°');
$chars_trans = array_keys($chars);
$chars = array_values($chars);
$chars_trans = implode(' ',array_map('chr',$chars_trans));
$chars_trans = unicode2charset(charset2unicode($chars_trans, 'iso-8859-1', 'forcer'));
$chars_trans = explode(" ",$chars_trans);
foreach($chars as $k=>$r)
$trans[$chars_trans[$k]] = $r;
/* 1 */ '/((^|[^\#0-9a-zA-Z\&])[\#0-9a-zA-Z]*)\;/S',
/* 2 */ '/»| --?,|:([^0-9]|$)/S',
/* 3 */ '/([^[<!?])([!?])/S',
/* 4 */ '/«|(M(M?\.|mes?|r\.?)|[MnN]°) /S'
/* 1 */ '\1~;',
/* 2 */ '~\0',
/* 3 */ '\1~\2',
/* 4 */ '\0~'
$letexte = preg_replace($cherche1, $remplace1, $letexte);
$letexte = preg_replace("/ *~+ */S", "~", $letexte);
'/([^-\n]|^)--([^-]|$)/S',
'/(http|https|ftp|mailto)~:/S',
'\1—\2',
$letexte = preg_replace($cherche2, $remplace2, $letexte);
// rien sauf les "~" et "-,"
// http://doc.spip.org/@typo_en
function typo_en($letexte) {
$letexte = preg_replace($cherche1, $remplace1, $letexte);
$letexte = ereg_replace(" *~+ *", "~", $letexte);
$cherche2 = array(
'/([^-\n]|^)--([^-]|$)/',
'/~/'
);
$remplace2 = array(
'\1—\2',
$letexte = preg_replace($cherche2, $remplace2, $letexte);
return $letexte;
//
// Typographie generale
// note: $echapper = false lorsqu'on appelle depuis propre() [pour accelerer]
function typo($letexte, $echapper=true) {
// Plus vite !
if (!$letexte) return $letexte;
if ($echapper)
$letexte = echappe_html($letexte, 'TYPO');
// Appeler les fonctions de pre-traitement
$letexte = pipeline('pre_typo', $letexte);
// old style
if (function_exists('avant_typo'))
$letexte = avant_typo($letexte);
// Caracteres de controle "illegaux"
$letexte = corriger_caracteres($letexte);
// Proteger les caracteres typographiques a l'interieur des tags html
$protege = "!':;?~";
$illegal = "\x1\x2\x3\x4\x5\x6";
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);
}
}
// zouli apostrophe
$letexte = str_replace("'", "’", $letexte);
// typo francaise ou anglaise ?
// $lang_objet est fixee dans l'interface privee pour editer
// un texte anglais en interface francaise (ou l'inverse) ;
// sinon determiner la typo en fonction de la langue
if (!$lang = $GLOBALS['lang_objet'])
$lang = $GLOBALS['spip_lang'];
lang_select($lang);
switch (lang_typo($lang)) {
case 'fr':
$letexte = typo_fr($letexte);
break;
default:
$letexte = typo_en($letexte);
break;
// Retablir les caracteres proteges
$letexte = strtr($letexte, $illegal, $protege);
// Installer les modeles, notamment images et documents ;
//
// NOTE : dans propre() ceci s'execute avant les tableaux a cause du "|",
// et apres les liens a cause du traitement de [<imgXX|right>->URL]
$letexte = traiter_modeles($letexte);
// Appeler les fonctions de post-traitement
$letexte = pipeline('post_typo', $letexte);
// old style
if (function_exists('apres_typo'))
$letexte = apres_typo($letexte);
// remettre la langue precedente
lang_dselect();
// reintegrer les echappements
if ($echapper)
$letexte = echappe_retour($letexte, 'TYPO');
# un message pour abs_url - on est passe en mode texte
$GLOBALS['mode_abs_url'] = 'texte';
// Dans l'espace prive, securiser ici
if (!_DIR_RESTREINT)
$letexte = interdire_scripts($letexte);
return $letexte;
// http://doc.spip.org/@extraire_lien
list($lien, $class, $texte) = calculer_url($regs[3], $regs[1],'tout');
// Preparer le texte du lien ; attention s'il contient un <div>
// (ex: [<docXX|right>->lien]), il faut etre smart
$ref = "<a href=\"$lien\" class=\"$class\">$texte</a>";
return array($ref, $lien, $texte);
}
// traitement des raccourcis issus de [TITRE->RACCOURCInnn] et connexes
//
// Valeur retournee selon le parametre $pour:
// 'tout' : <a href="L">T</a>
// 'titre': seulement T ci-dessus (i.e. le TITRE ci-dessus ou dans table SQL)
// 'url': seulement L (i.e. generer_url_RACCOURCI)
// http://doc.spip.org/@calculer_url
function calculer_url ($lien, $texte='', $pour='url') {
$lien = vider_url($lien); # supprimer 'http://' ou 'mailto:'
// Cherche un lien du type [->raccourci 123]
// associe a une fonction generer_url_raccourci()
if (preg_match(',^(\S*?)\s*(\d+)(\?.*?)?(#[^\s]*)?$,S', trim($lien), $match)) {
list(,$objet,$id,$params,$ancre) = $match;
if (!$f = $objet) $f = 'article';
else if ($f == 'doc' OR $f == 'im' OR $f == 'img' OR $f == 'image' OR $f == 'emb')
else if (preg_match(',^br..?ve$,S', $f)) $f = 'breve'; # accents :(
// chercher la fonction nommee generer_url_$raccourci
// ou calculer_url_raccourci si on n'a besoin que du lien
$f=(($pour == 'url') ? 'generer' : 'calculer') . '_url_' . $f;
charger_generer_url();
if ($pour == 'url') {
$url = $f($id);
if ($params)
$url .= (strstr($url, '?') ? '&' : '?')
. substr($params,1);
return $url . $ancre;
}
$res = $f($id, $texte, $ancre);
$res[2] = $res[2];
if ($pour == 'titre')
return $res[2];
if ($params)
$res[0] .= (strstr($res[0], '?') ? '&' : '?')
. substr($params,1);
$res[0] .= $ancre;
return $res;
}
}
$lien = ltrim($lien);
if ($lien[0] == '?') {
if ($pour == 'titre') return $texte;
$lien = entites_html(substr($lien, 1));
return ($pour == 'url') ? $lien :
array($lien, 'spip_glossaire', $texte);
}
// 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;
$lien = vider_url($lien);
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, $lang);
// http://doc.spip.org/@calculer_url_article
$lien = generer_url_article($id);
$row = @spip_fetch_array(spip_query("SELECT titre,lang FROM spip_articles WHERE id_article=$id"));
if ($texte=='')
$texte = supprimer_numero($row['titre']);
return array($lien, 'spip_in', $texte, $row['lang']);
// http://doc.spip.org/@calculer_url_rubrique
$lien = generer_url_rubrique($id);
$row = @spip_fetch_array(spip_query("SELECT titre,lang FROM spip_rubriques WHERE id_rubrique=$id"));
if ($texte=='')
$texte = supprimer_numero($row['titre']);
return array($lien, 'spip_in', $texte, $row['lang']);
// http://doc.spip.org/@calculer_url_mot
$lien = generer_url_mot($id);
$row = @spip_fetch_array(spip_query("SELECT titre,lang FROM spip_mots WHERE id_mot=$id"));
if ($texte=='')
$texte = supprimer_numero($row['titre']);
return array($lien, 'spip_in', $texte, $row['lang']);
// http://doc.spip.org/@calculer_url_breve
$lien = generer_url_breve($id);
$row = @spip_fetch_array(spip_query("SELECT titre,lang FROM spip_breves WHERE id_breve=$id"));
if ($texte=='')
$texte = supprimer_numero($row['titre']);
return array($lien, 'spip_in', $texte, $row['lang']);
// http://doc.spip.org/@calculer_url_auteur
$lien = generer_url_auteur($id);
if ($texte=='') {
$row = @spip_fetch_array(spip_query("SELECT nom FROM spip_auteurs WHERE id_auteur=$id"));
$texte = $row['nom'];
return array($lien, 'spip_in', $texte); # pas de hreflang
// http://doc.spip.org/@calculer_url_document
$lien = generer_url_document($id);
if ($texte=='') {
$row = @spip_fetch_array(spip_query("SELECT titre,fichier FROM spip_documents WHERE id_document=$id"));
$texte = $row['titre'];
if ($texte=='')
$texte = preg_replace(",^.*/,","",$row['fichier']);
return array($lien, 'spip_in', $texte); # pas de hreflang
// http://doc.spip.org/@calculer_url_site
{
# 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 = @spip_fetch_array(spip_query("SELECT nom_site,url_site,lang FROM spip_syndic WHERE id_syndic=$id"));
if ($row) {
$lien = $row['url_site'];
if ($texte=='')
$texte = supprimer_numero($row['nom_site']);
return array($lien, 'spip_out', $texte, $row['lang']);
// 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);
// 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 (ereg("\n-[*#]", $ligne))
$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 class=\"spip\"$summary>\n"
. "</table>\n\n";
// Traitement des listes (merci a Michael Parienti)
// http://doc.spip.org/@traiter_listes
function traiter_listes ($texte) {
$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\">";
$pile_type[$niveau] = "</$type>";
$ajout .= "<li class=\"spip\">";
$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: