texte.php 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593
  1. <?php
  2. /***************************************************************************\
  3. * SPIP, Systeme de publication pour l'internet *
  4. * *
  5. * Copyright (c) 2001-2014 *
  6. * Arnaud Martin, Antoine Pitrou, Philippe Riviere, Emmanuel Saint-James *
  7. * *
  8. * Ce programme est un logiciel libre distribue sous licence GNU/GPL. *
  9. * Pour plus de details voir le fichier COPYING.txt ou l'aide en ligne. *
  10. \***************************************************************************/
  11. if (!defined('_ECRIRE_INC_VERSION')) return;
  12. include_spip('inc/texte_mini');
  13. include_spip('inc/lien');
  14. include_spip('inc/textwheel');
  15. defined('_AUTOBR')||define('_AUTOBR', "<br class='autobr' />");
  16. define('_AUTOBR_IGNORER', _AUTOBR?"<!-- ig br -->":"");
  17. // Avec cette surcharge, cette globale n'est plus définie, et du coup ça plante dans les plugins qui font un foreach dessus comme ZPIP
  18. $GLOBALS['spip_raccourcis_typo'] = array();
  19. if (!isset($GLOBALS['toujours_paragrapher']))
  20. $GLOBALS['toujours_paragrapher'] = true;
  21. // class_spip : savoir si on veut class="spip" sur p i strong & li
  22. // class_spip_plus : class="spip" sur les ul ol h3 hr quote table...
  23. // la difference c'est que des css specifiques existent pour les seconds
  24. //
  25. if (!isset($GLOBALS['class_spip']))
  26. $GLOBALS['class_spip'] = '';
  27. if (!isset($GLOBALS['class_spip_plus']))
  28. $GLOBALS['class_spip_plus'] = ' class="spip"';
  29. /**
  30. * echapper les < script ...
  31. *
  32. * @param string $t
  33. * @return string
  34. */
  35. function echappe_js($t) {
  36. static $wheel = null;
  37. if (!isset($wheel))
  38. $wheel = new TextWheel(
  39. SPIPTextWheelRuleset::loader($GLOBALS['spip_wheels']['echappe_js'])
  40. );
  41. return $wheel->text($t);
  42. }
  43. /**
  44. * paragrapher seulement
  45. *
  46. * @param string $t
  47. * @param null $toujours_paragrapher
  48. * @return string
  49. */
  50. function paragrapher($t, $toujours_paragrapher = null) {
  51. static $wheel = array();
  52. if (is_null($toujours_paragrapher))
  53. $toujours_paragrapher = $GLOBALS['toujours_paragrapher'];
  54. if (!isset($wheel[$toujours_paragrapher])) {
  55. $ruleset = SPIPTextWheelRuleset::loader($GLOBALS['spip_wheels']['paragrapher']);
  56. if (!$toujours_paragrapher
  57. AND $rule=$ruleset->getRule('toujours-paragrapher')) {
  58. $rule->disabled = true;
  59. $ruleset->addRules(array('toujours-paragrapher'=>$rule));
  60. }
  61. $wheel[$toujours_paragrapher] = new TextWheel($ruleset);
  62. }
  63. return $wheel[$toujours_paragrapher]->text($t);
  64. }
  65. /**
  66. * Securite : empecher l'execution de code PHP, en le transformant en joli code
  67. * dans l'espace prive, cette fonction est aussi appelee par propre et typo
  68. * si elles sont appelees en direct
  69. * il ne faut pas desactiver globalement la fonction dans l'espace prive car elle protege
  70. * aussi les balises des squelettes qui ne passent pas forcement par propre ou typo apres
  71. *
  72. * http://code.spip.net/@interdire_scripts
  73. *
  74. * @param string $arg
  75. * @return string
  76. */
  77. function interdire_scripts($arg) {
  78. // on memorise le resultat sur les arguments non triviaux
  79. static $dejavu = array();
  80. static $wheel = array();
  81. // Attention, si ce n'est pas une chaine, laisser intact
  82. if (!$arg OR !is_string($arg) OR !strstr($arg, '<')) return $arg;
  83. if (isset($dejavu[$GLOBALS['filtrer_javascript']][$arg])) return $dejavu[$GLOBALS['filtrer_javascript']][$arg];
  84. if (!isset($wheel[$GLOBALS['filtrer_javascript']])){
  85. $ruleset = SPIPTextWheelRuleset::loader(
  86. $GLOBALS['spip_wheels']['interdire_scripts']
  87. );
  88. // Pour le js, trois modes : parano (-1), prive (0), ok (1)
  89. // desactiver la regle echappe-js si besoin
  90. if ($GLOBALS['filtrer_javascript']==1
  91. OR ($GLOBALS['filtrer_javascript']==0 AND !test_espace_prive()))
  92. $ruleset->addRules (array('securite-js'=>array('disabled'=>true)));
  93. $wheel[$GLOBALS['filtrer_javascript']] = new TextWheel($ruleset);
  94. }
  95. $t = $wheel[$GLOBALS['filtrer_javascript']]->text($arg);
  96. // Reinserer les echappements des modeles
  97. if (defined('_PROTEGE_JS_MODELES'))
  98. $t = echappe_retour($t,"javascript"._PROTEGE_JS_MODELES);
  99. if (defined('_PROTEGE_PHP_MODELES'))
  100. $t = echappe_retour($t,"php"._PROTEGE_PHP_MODELES);
  101. return $dejavu[$GLOBALS['filtrer_javascript']][$arg] = $t;
  102. }
  103. /**
  104. * Typographie generale
  105. * avec protection prealable des balises HTML et SPIP
  106. *
  107. * http://code.spip.net/@typo
  108. *
  109. * @param string $letexte
  110. * @param bool $echapper
  111. * @param null $connect
  112. * @param array $env
  113. * @return string
  114. */
  115. function typo($letexte, $echapper=true, $connect=null, $env=array()) {
  116. // Plus vite !
  117. if (!$letexte) return $letexte;
  118. // les appels directs a cette fonction depuis le php de l'espace
  119. // prive etant historiquement ecrit sans argment $connect
  120. // on utilise la presence de celui-ci pour distinguer les cas
  121. // ou il faut passer interdire_script explicitement
  122. // les appels dans les squelettes (de l'espace prive) fournissant un $connect
  123. // ne seront pas perturbes
  124. $interdire_script = false;
  125. if (is_null($connect)){
  126. $connect = '';
  127. $interdire_script = true;
  128. }
  129. $echapper = ($echapper?'TYPO':false);
  130. // Echapper les codes <html> etc
  131. if ($echapper)
  132. $letexte = echappe_html($letexte, $echapper);
  133. //
  134. // Installer les modeles, notamment images et documents ;
  135. //
  136. // NOTE : propre() ne passe pas par ici mais directement par corriger_typo
  137. // cf. inc/lien
  138. $letexte = traiter_modeles($mem = $letexte, false, $echapper ? $echapper : '', $connect, null, $env);
  139. if (!$echapper AND $letexte != $mem) $echapper = '';
  140. unset($mem);
  141. $letexte = corriger_typo($letexte);
  142. $letexte = echapper_faux_tags($letexte);
  143. // reintegrer les echappements
  144. if ($echapper!==false)
  145. $letexte = echappe_retour($letexte, $echapper);
  146. // Dans les appels directs hors squelette, securiser ici aussi
  147. if ($interdire_script)
  148. $letexte = interdire_scripts($letexte);
  149. return $letexte;
  150. }
  151. // Correcteur typographique
  152. define('_TYPO_PROTEGER', "!':;?~%-");
  153. define('_TYPO_PROTECTEUR', "\x1\x2\x3\x4\x5\x6\x7\x8");
  154. define('_TYPO_BALISE', ",</?[a-z!][^<>]*[".preg_quote(_TYPO_PROTEGER)."][^<>]*>,imsS");
  155. /**
  156. * http://code.spip.net/@corriger_typo
  157. *
  158. * @param string $t
  159. * @param string $lang
  160. * @return string
  161. */
  162. function corriger_typo($t, $lang='') {
  163. static $typographie = array();
  164. // Plus vite !
  165. if (!$t) return $t;
  166. $t = pipeline('pre_typo', $t);
  167. // Caracteres de controle "illegaux"
  168. $t = corriger_caracteres($t);
  169. // Proteger les caracteres typographiques a l'interieur des tags html
  170. if (preg_match_all(_TYPO_BALISE, $t, $regs, PREG_SET_ORDER)) {
  171. foreach ($regs as $reg) {
  172. $insert = $reg[0];
  173. // hack: on transforme les caracteres a proteger en les remplacant
  174. // par des caracteres "illegaux". (cf corriger_caracteres())
  175. $insert = strtr($insert, _TYPO_PROTEGER, _TYPO_PROTECTEUR);
  176. $t = str_replace($reg[0], $insert, $t);
  177. }
  178. }
  179. // trouver les blocs multi et les traiter a part
  180. $t = extraire_multi($e = $t, $lang, true);
  181. $e = ($e === $t);
  182. // Charger & appliquer les fonctions de typographie
  183. $idxl = "$lang:" . (isset($GLOBALS['lang_objet'])? $GLOBALS['lang_objet']: $GLOBALS['spip_lang']);
  184. if (!isset($typographie[$idxl]))
  185. $typographie[$idxl] = charger_fonction(lang_typo($lang), 'typographie');
  186. $t = $typographie[$idxl]($t);
  187. // Les citations en une autre langue, s'il y a lieu
  188. if (!$e) $t = echappe_retour($t, 'multi');
  189. // Retablir les caracteres proteges
  190. $t = strtr($t, _TYPO_PROTECTEUR, _TYPO_PROTEGER);
  191. // pipeline
  192. $t = pipeline('post_typo', $t);
  193. # un message pour abs_url - on est passe en mode texte
  194. $GLOBALS['mode_abs_url'] = 'texte';
  195. return $t;
  196. }
  197. //
  198. // Tableaux
  199. //
  200. define('_RACCOURCI_TH_SPAN', '\s*(:?{{[^{}]+}}\s*)?|<');
  201. /**
  202. * http://code.spip.net/@traiter_tableau
  203. *
  204. * @param sring $bloc
  205. * @return string
  206. */
  207. function traiter_tableau($bloc) {
  208. // id "unique" pour les id du tableau
  209. $tabid = substr(md5($bloc),0,4);
  210. // Decouper le tableau en lignes
  211. preg_match_all(',([|].*)[|]\n,UmsS', $bloc, $regs, PREG_PATTERN_ORDER);
  212. $lignes = array();
  213. $debut_table = $summary = '';
  214. $l = 0;
  215. $numeric = true;
  216. // Traiter chaque ligne
  217. $reg_line1 = ',^(\|(' . _RACCOURCI_TH_SPAN . '))+$,sS';
  218. $reg_line_all = ',^(' . _RACCOURCI_TH_SPAN . ')$,sS';
  219. $hc = $hl = array();
  220. foreach ($regs[1] as $ligne) {
  221. $l ++;
  222. // Gestion de la premiere ligne :
  223. if ($l == 1) {
  224. // - <caption> et summary dans la premiere ligne :
  225. // || caption | summary || (|summary est optionnel)
  226. if (preg_match(',^\|\|([^|]*)(\|(.*))?$,sS', rtrim($ligne,'|'), $cap)) {
  227. $l = 0;
  228. if ($caption = trim($cap[1]))
  229. $debut_table .= "<caption>".$caption."</caption>\n";
  230. $summary = ' summary="'.entites_html(trim($cap[3])).'"';
  231. }
  232. // - <thead> sous la forme |{{titre}}|{{titre}}|
  233. // Attention thead oblige a avoir tbody
  234. else if (preg_match($reg_line1, $ligne, $thead)) {
  235. preg_match_all('/\|([^|]*)/S', $ligne, $cols);
  236. $ligne='';$cols= $cols[1];
  237. $colspan=1;
  238. for($c=count($cols)-1; $c>=0; $c--) {
  239. $attr='';
  240. if($cols[$c]=='<') {
  241. $colspan++;
  242. } else {
  243. if($colspan>1) {
  244. $attr= " colspan='$colspan'";
  245. $colspan=1;
  246. }
  247. // inutile de garder le strong qui n'a servi que de marqueur
  248. $cols[$c] = str_replace(array('{','}'), '', $cols[$c]);
  249. $ligne= "<th id='id{$tabid}_c$c'$attr>$cols[$c]</th>$ligne";
  250. $hc[$c] = "id{$tabid}_c$c"; // pour mettre dans les headers des td
  251. }
  252. }
  253. $debut_table .= "<thead><tr class='row_first'>".
  254. $ligne."</tr></thead>\n";
  255. $l = 0;
  256. }
  257. }
  258. // Sinon ligne normale
  259. if ($l) {
  260. // Gerer les listes a puce dans les cellules
  261. // on declenche simplement sur \n- car il y a les
  262. // -* -# -? -! (qui produisent des -&nbsp;!)
  263. if (strpos($ligne,"\n-")!==false)
  264. $ligne = traiter_listes($ligne);
  265. // tout mettre dans un tableau 2d
  266. preg_match_all('/\|([^|]*)/S', $ligne, $cols);
  267. // Pas de paragraphes dans les cellules
  268. foreach ($cols[1] as &$col) {
  269. if (strlen($col = trim($col))) {
  270. $col = preg_replace("/\n{2,}/S", "<br /> <br />", $col);
  271. if (_AUTOBR)
  272. $col = str_replace("\n", _AUTOBR."\n", $col);
  273. }
  274. }
  275. // assembler le tableau
  276. $lignes[]= $cols[1];
  277. }
  278. }
  279. // maintenant qu'on a toutes les cellules
  280. // on prepare une liste de rowspan par defaut, a partir
  281. // du nombre de colonnes dans la premiere ligne.
  282. // Reperer egalement les colonnes numeriques pour les cadrer a droite
  283. $rowspans = $numeric = array();
  284. $n = count($lignes[0]);
  285. $k = count($lignes);
  286. // distinguer les colonnes numeriques a point ou a virgule,
  287. // pour les alignements eventuels sur "," ou "."
  288. $numeric_class = array('.'=>'point',','=>'virgule');
  289. for($i=0;$i<$n;$i++) {
  290. $align = true;
  291. for ($j=0;$j<$k;$j++) {
  292. $rowspans[$j][$i] = 1;
  293. if ($align AND preg_match('/^[+-]?(?:\s|\d)*([.,]?)\d*$/', trim($lignes[$j][$i]), $r)){
  294. if ($r[1])
  295. $align = $r[1];
  296. }
  297. else
  298. $align = '';
  299. }
  300. $numeric[$i] = $align ? (" class='numeric ".$numeric_class[$align]."'") : '';
  301. }
  302. for ($j=0;$j<$k;$j++) {
  303. if (preg_match($reg_line_all, $lignes[$j][0])) {
  304. $hl[$j] = "id{$tabid}_l$j"; // pour mettre dans les headers des td
  305. }
  306. else
  307. unset($hl[0]);
  308. }
  309. if (!isset($hl[0]))
  310. $hl = array(); // toute la colonne ou rien
  311. // et on parcourt le tableau a l'envers pour ramasser les
  312. // colspan et rowspan en passant
  313. $html = '';
  314. for($l=count($lignes)-1; $l>=0; $l--) {
  315. $cols= $lignes[$l];
  316. $colspan=1;
  317. $ligne='';
  318. for($c=count($cols)-1; $c>=0; $c--) {
  319. $attr= $numeric[$c];
  320. $cell = trim($cols[$c]);
  321. if($cell=='<') {
  322. $colspan++;
  323. } elseif($cell=='^') {
  324. $rowspans[$l-1][$c]+=$rowspans[$l][$c];
  325. } else {
  326. if($colspan>1) {
  327. $attr .= " colspan='$colspan'";
  328. $colspan=1;
  329. }
  330. if(($x=$rowspans[$l][$c])>1) {
  331. $attr.= " rowspan='$x'";
  332. }
  333. $b = ($c==0 AND isset($hl[$l]))?'th':'td';
  334. $h = (isset($hc[$c])?$hc[$c]:'').' '.(($b=='td' AND isset($hl[$l]))?$hl[$l]:'');
  335. if ($h=trim($h))
  336. $attr.=" headers='$h'";
  337. // inutile de garder le strong qui n'a servi que de marqueur
  338. if ($b=='th') {
  339. $attr.=" id='".$hl[$l]."'";
  340. $cols[$c] = str_replace(array('{','}'), '', $cols[$c]);
  341. }
  342. $ligne= "\n<$b".$attr.'>'.$cols[$c]."</$b>".$ligne;
  343. }
  344. }
  345. // ligne complete
  346. $class = alterner($l+1, 'odd', 'even');
  347. $html = "<tr class='row_$class $class'>$ligne</tr>\n$html";
  348. }
  349. return "\n\n<table".$GLOBALS['class_spip_plus'].$summary.">\n"
  350. . $debut_table
  351. . "<tbody>\n"
  352. . $html
  353. . "</tbody>\n"
  354. . "</table>\n\n";
  355. }
  356. /**
  357. * Traitement des listes
  358. * on utilise la wheel correspondante
  359. *
  360. * http://code.spip.net/@traiter_listes
  361. *
  362. * @param string $t
  363. * @return string
  364. */
  365. function traiter_listes ($t) {
  366. static $wheel = null;
  367. if (!isset($wheel))
  368. $wheel = new TextWheel(
  369. SPIPTextWheelRuleset::loader($GLOBALS['spip_wheels']['listes'])
  370. );
  371. return $wheel->text($t);
  372. }
  373. // Ces deux constantes permettent de proteger certains caracteres
  374. // en les remplacanat par des caracteres "illegaux". (cf corriger_caracteres)
  375. define('_RACCOURCI_PROTEGER', "{}_-");
  376. define('_RACCOURCI_PROTECTEUR', "\x1\x2\x3\x4");
  377. define('_RACCOURCI_BALISE', ",</?[a-z!][^<>]*[".preg_quote(_RACCOURCI_PROTEGER)."][^<>]*>,imsS");
  378. /**
  379. * mais d'abord, une callback de reconfiguration des raccourcis
  380. * a partir de globales (est-ce old-style ? on conserve quand meme
  381. * par souci de compat ascendante)
  382. *
  383. * @param $ruleset
  384. */
  385. function personnaliser_raccourcis(&$ruleset){
  386. if (isset($GLOBALS['debut_intertitre']) AND $rule=$ruleset->getRule('intertitres')){
  387. $rule->replace[0] = preg_replace(',<[^>]*>,Uims',$GLOBALS['debut_intertitre'],$rule->replace[0]);
  388. $rule->replace[1] = preg_replace(',<[^>]*>,Uims',$GLOBALS['fin_intertitre'],$rule->replace[1]);
  389. $ruleset->addRules(array('intertitres'=>$rule));
  390. }
  391. if (isset($GLOBALS['debut_gras']) AND $rule=$ruleset->getRule('gras')){
  392. $rule->replace[0] = preg_replace(',<[^>]*>,Uims',$GLOBALS['debut_gras'],$rule->replace[0]);
  393. $rule->replace[1] = preg_replace(',<[^>]*>,Uims',$GLOBALS['fin_gras'],$rule->replace[1]);
  394. $ruleset->addRules(array('gras'=>$rule));
  395. }
  396. if (isset($GLOBALS['debut_italique']) AND $rule=$ruleset->getRule('italiques')){
  397. $rule->replace[0] = preg_replace(',<[^>]*>,Uims',$GLOBALS['debut_italique'],$rule->replace[0]);
  398. $rule->replace[1] = preg_replace(',<[^>]*>,Uims',$GLOBALS['fin_italique'],$rule->replace[1]);
  399. $ruleset->addRules(array('italiques'=>$rule));
  400. }
  401. if (isset($GLOBALS['ligne_horizontale']) AND $rule=$ruleset->getRule('ligne-horizontale')){
  402. $rule->replace = preg_replace(',<[^>]*>,Uims',$GLOBALS['ligne_horizontale'],$rule->replace);
  403. $ruleset->addRules(array('ligne-horizontale'=>$rule));
  404. }
  405. if (isset($GLOBALS['toujours_paragrapher']) AND !$GLOBALS['toujours_paragrapher']
  406. AND $rule=$ruleset->getRule('toujours-paragrapher')) {
  407. $rule->disabled = true;
  408. $ruleset->addRules(array('toujours-paragrapher'=>$rule));
  409. }
  410. }
  411. /**
  412. * Nettoie un texte, traite les raccourcis autre qu'URL, la typo, etc.
  413. *
  414. * http://code.spip.net/@traiter_raccourcis
  415. *
  416. * @param string $t
  417. * @param bool $show_autobr
  418. * @return string
  419. */
  420. function traiter_raccourcis($t, $show_autobr = false) {
  421. static $wheel, $notes;
  422. static $img_br_auto,$img_br_manuel,$img_br_no;
  423. // hack1: respecter le tag ignore br
  424. if (_AUTOBR_IGNORER
  425. AND strncmp($t, _AUTOBR_IGNORER, strlen(_AUTOBR_IGNORER))==0) {
  426. $ignorer_autobr = true;
  427. $t = substr($t, strlen(_AUTOBR_IGNORER));
  428. } else
  429. $ignorer_autobr = false;
  430. // Appeler les fonctions de pre_traitement
  431. $t = pipeline('pre_propre', $t);
  432. if (!isset($wheel)) {
  433. $ruleset = SPIPTextWheelRuleset::loader(
  434. $GLOBALS['spip_wheels']['raccourcis'],'personnaliser_raccourcis'
  435. );
  436. $wheel = new TextWheel($ruleset);
  437. if (_request('var_mode') == 'wheel'
  438. AND autoriser('debug')) {
  439. $f = $wheel->compile();
  440. echo "<pre>\n".spip_htmlspecialchars($f)."</pre>\n";
  441. exit;
  442. }
  443. $notes = charger_fonction('notes', 'inc');
  444. }
  445. // Gerer les notes (ne passe pas dans le pipeline)
  446. list($t, $mes_notes) = $notes($t);
  447. $t = $wheel->text($t);
  448. // Appeler les fonctions de post-traitement
  449. $t = pipeline('post_propre', $t);
  450. if ($mes_notes)
  451. $notes($mes_notes,'traiter',$ignorer_autobr);
  452. // hack2: wrap des autobr dans l'espace prive, pour affichage css
  453. // car en css on ne sait pas styler l'element BR
  454. if ($ignorer_autobr AND _AUTOBR) {
  455. if (is_null($img_br_no))
  456. $img_br_no = ($show_autobr?http_img_pack("br-no-10.png",_T("tw:retour_ligne_ignore"),"class='br-no'",_T("tw:retour_ligne_ignore")):"");
  457. $t = str_replace(_AUTOBR, $img_br_no, $t);
  458. }
  459. if ($show_autobr AND _AUTOBR) {
  460. if (is_null($img_br_manuel))
  461. $img_br_manuel = http_img_pack("br-manuel-10.png",_T("tw:retour_ligne_manuel"),"class='br-manuel'",_T("tw:retour_ligne_manuel"));
  462. if (is_null($img_br_auto))
  463. $img_br_auto = http_img_pack("br-auto-10.png",_T("tw:retour_ligne_auto"),"class='br-auto'",_T("tw:retour_ligne_auto"));
  464. if (false !== strpos(strtolower($t), '<br')) {
  465. $t = preg_replace("/<br\b.*>/UiS", "$img_br_manuel\\0", $t);
  466. $t = str_replace($img_br_manuel._AUTOBR, $img_br_auto._AUTOBR, $t);
  467. }
  468. }
  469. return $t;
  470. }
  471. /**
  472. * Filtre a appliquer aux champs du type #TEXTE*
  473. * http://code.spip.net/@propre
  474. *
  475. * @param string $t
  476. * @param string $connect
  477. * @param array $env
  478. * @return string
  479. */
  480. function propre($t, $connect=null, $env=array()) {
  481. // les appels directs a cette fonction depuis le php de l'espace
  482. // prive etant historiquement ecrits sans argment $connect
  483. // on utilise la presence de celui-ci pour distinguer les cas
  484. // ou il faut passer interdire_script explicitement
  485. // les appels dans les squelettes (de l'espace prive) fournissant un $connect
  486. // ne seront pas perturbes
  487. $interdire_script = false;
  488. if (is_null($connect) AND test_espace_prive()){
  489. $connect = '';
  490. $interdire_script = true;
  491. }
  492. if (!$t) return strval($t);
  493. $t = pipeline('pre_echappe_html_propre', $t);
  494. $t = echappe_html($t);
  495. $t = expanser_liens($t,$connect, $env);
  496. $t = traiter_raccourcis($t, (isset($env['wysiwyg']) AND $env['wysiwyg'])?true:false);
  497. $t = echappe_retour_modeles($t, $interdire_script);
  498. return $t;
  499. }
  500. ?>