[SPIP] ~v3.0.20-->v3.0.25
[lhc/web/clavette_www.git] / www / ecrire / inc / texte.php
1 <?php
2
3 /***************************************************************************\
4 * SPIP, Systeme de publication pour l'internet *
5 * *
6 * Copyright (c) 2001-2016 *
7 * Arnaud Martin, Antoine Pitrou, Philippe Riviere, Emmanuel Saint-James *
8 * *
9 * Ce programme est un logiciel libre distribue sous licence GNU/GPL. *
10 * Pour plus de details voir le fichier COPYING.txt ou l'aide en ligne. *
11 \***************************************************************************/
12
13 if (!defined('_ECRIRE_INC_VERSION')) return;
14
15 include_spip('inc/texte_mini');
16 include_spip('inc/lien');
17
18 /*************************************************************************************************************************
19 * Fonctions inutilisees en dehors de inc/texte
20 *
21 */
22
23 // Raccourcis dependant du sens de la langue
24 function definir_raccourcis_alineas(){
25 return array('','');
26 }
27
28
29 //
30 // Tableaux
31 //
32 // http://doc.spip.org/@traiter_tableau
33 function traiter_tableau($bloc) {
34 return $bloc;
35 }
36
37
38 //
39 // Traitement des listes (merci a Michael Parienti)
40 //
41 // http://doc.spip.org/@traiter_listes
42 function traiter_listes ($texte) {
43 return $texte;
44 }
45
46 // Nettoie un texte, traite les raccourcis autre qu'URL, la typo, etc.
47 // http://doc.spip.org/@traiter_raccourcis
48 function traiter_raccourcis($letexte) {
49
50 // Appeler les fonctions de pre_traitement
51 $letexte = pipeline('pre_propre', $letexte);
52
53 // APPELER ICI UN PIPELINE traiter_raccourcis ?
54 // $letexte = pipeline('traiter_raccourcis', $letexte);
55
56 // Appeler les fonctions de post-traitement
57 $letexte = pipeline('post_propre', $letexte);
58
59 return $letexte;
60 }
61
62 /*************************************************************************************************************************
63 * Fonctions utilisees en dehors de inc/texte
64 */
65
66 // afficher joliment les <script>
67 // http://doc.spip.org/@echappe_js
68 function echappe_js($t,$class=' class="echappe-js"') {
69 if (preg_match_all(',<script.*?($|</script.),isS', $t, $r, PREG_SET_ORDER))
70 foreach ($r as $regs)
71 $t = str_replace($regs[0],
72 "<code$class>".nl2br(spip_htmlspecialchars($regs[0])).'</code>',
73 $t);
74 return $t;
75 }
76
77
78
79 /**
80 * Empêcher l'exécution de code PHP et JS
81 *
82 * Sécurité : empêcher l'exécution de code PHP, en le transformant en joli code
83 * dans l'espace privé. Cette fonction est aussi appelée par propre et typo.
84 *
85 * De la même manière, la fonction empêche l'exécution de JS mais selon le mode
86 * de protection déclaré par la globale filtrer_javascript :
87 * - -1 : protection dans l'espace privé et public
88 * - 0 : protection dans l'espace public
89 * - 1 : aucune protection
90 *
91 * Il ne faut pas désactiver globalement la fonction dans l'espace privé car elle protège
92 * aussi les balises des squelettes qui ne passent pas forcement par propre ou typo après
93 * si elles sont appelées en direct
94 *
95 * @param string $arg
96 * Code à protéger
97 * @return string
98 * Code protégé
99 **/
100 function interdire_scripts($arg) {
101 // on memorise le resultat sur les arguments non triviaux
102 static $dejavu = array();
103
104 // Attention, si ce n'est pas une chaine, laisser intact
105 if (!$arg OR !is_string($arg) OR !strstr($arg, '<')) return $arg;
106
107 if (isset($dejavu[$GLOBALS['filtrer_javascript']][$arg])) return $dejavu[$GLOBALS['filtrer_javascript']][$arg];
108
109 // echapper les tags asp/php
110 $t = str_replace('<'.'%', '&lt;%', $arg);
111
112 // echapper le php
113 $t = str_replace('<'.'?', '&lt;?', $t);
114
115 // echapper le < script language=php >
116 $t = preg_replace(',<(script\b[^>]+\blanguage\b[^\w>]+php\b),UimsS', '&lt;\1', $t);
117
118 // Pour le js, trois modes : parano (-1), prive (0), ok (1)
119 switch($GLOBALS['filtrer_javascript']) {
120 case 0:
121 if (!_DIR_RESTREINT)
122 $t = echappe_js($t);
123 break;
124 case -1:
125 $t = echappe_js($t);
126 break;
127 }
128
129 // pas de <base href /> svp !
130 $t = preg_replace(',<(base\b),iS', '&lt;\1', $t);
131
132 // Reinserer les echappements des modeles
133 if (defined('_PROTEGE_JS_MODELES'))
134 $t = echappe_retour($t,"javascript"._PROTEGE_JS_MODELES);
135 if (defined('_PROTEGE_PHP_MODELES'))
136 $t = echappe_retour($t,"php"._PROTEGE_PHP_MODELES);
137
138 return $dejavu[$GLOBALS['filtrer_javascript']][$arg] = $t;
139 }
140
141 // Typographie generale
142 // avec protection prealable des balises HTML et SPIP
143
144 // http://doc.spip.org/@typo
145 function typo($letexte, $echapper=true, $connect=null, $env=array()) {
146 // Plus vite !
147 if (!$letexte) return $letexte;
148
149 // les appels directs a cette fonction depuis le php de l'espace
150 // prive etant historiquement ecrit sans argment $connect
151 // on utilise la presence de celui-ci pour distinguer les cas
152 // ou il faut passer interdire_script explicitement
153 // les appels dans les squelettes (de l'espace prive) fournissant un $connect
154 // ne seront pas perturbes
155 $interdire_script = false;
156 if (is_null($connect)){
157 $connect = '';
158 $interdire_script = true;
159 $env['espace_prive'] = 1;
160 }
161
162 // Echapper les codes <html> etc
163 if ($echapper)
164 $letexte = echappe_html($letexte, 'TYPO');
165
166 //
167 // Installer les modeles, notamment images et documents ;
168 //
169 // NOTE : propre() ne passe pas par ici mais directement par corriger_typo
170 // cf. inc/lien
171
172 $letexte = traiter_modeles($mem = $letexte, false, $echapper ? 'TYPO' : '', $connect, null, $env);
173 if ($letexte != $mem) $echapper = true;
174 unset($mem);
175
176 $letexte = corriger_typo($letexte);
177 $letexte = echapper_faux_tags($letexte);
178
179 // reintegrer les echappements
180 if ($echapper)
181 $letexte = echappe_retour($letexte, 'TYPO');
182
183 // Dans les appels directs hors squelette, securiser ici aussi
184 if ($interdire_script)
185 $letexte = interdire_scripts($letexte);
186
187 // Dans l'espace prive on se mefie de tout contenu dangereux
188 // https://core.spip.net/issues/3371
189 if (isset($env['espace_prive']) AND $env['espace_prive']){
190 $letexte = echapper_html_suspect($letexte);
191 }
192
193 return $letexte;
194 }
195
196 // Correcteur typographique
197 define('_TYPO_PROTEGER', "!':;?~%-");
198 define('_TYPO_PROTECTEUR', "\x1\x2\x3\x4\x5\x6\x7\x8");
199
200 define('_TYPO_BALISE', ",</?[a-z!][^<>]*[".preg_quote(_TYPO_PROTEGER)."][^<>]*>,imsS");
201
202 // http://doc.spip.org/@corriger_typo
203 function corriger_typo($letexte, $lang='') {
204
205 // Plus vite !
206 if (!$letexte) return $letexte;
207
208 $letexte = pipeline('pre_typo', $letexte);
209
210 // Caracteres de controle "illegaux"
211 $letexte = corriger_caracteres($letexte);
212
213 // Proteger les caracteres typographiques a l'interieur des tags html
214 if (preg_match_all(_TYPO_BALISE, $letexte, $regs, PREG_SET_ORDER)) {
215 foreach ($regs as $reg) {
216 $insert = $reg[0];
217 // hack: on transforme les caracteres a proteger en les remplacant
218 // par des caracteres "illegaux". (cf corriger_caracteres())
219 $insert = strtr($insert, _TYPO_PROTEGER, _TYPO_PROTECTEUR);
220 $letexte = str_replace($reg[0], $insert, $letexte);
221 }
222 }
223
224 // trouver les blocs multi et les traiter a part
225 $letexte = extraire_multi($e = $letexte, $lang, true);
226 $e = ($e === $letexte);
227
228 // Charger & appliquer les fonctions de typographie
229 $typographie = charger_fonction(lang_typo($lang), 'typographie');
230 $letexte = $typographie($letexte);
231
232 // Les citations en une autre langue, s'il y a lieu
233 if (!$e) $letexte = echappe_retour($letexte, 'multi');
234
235 // Retablir les caracteres proteges
236 $letexte = strtr($letexte, _TYPO_PROTECTEUR, _TYPO_PROTEGER);
237
238 // pipeline
239 $letexte = pipeline('post_typo', $letexte);
240
241 # un message pour abs_url - on est passe en mode texte
242 $GLOBALS['mode_abs_url'] = 'texte';
243
244 return $letexte;
245 }
246
247
248
249
250 //
251 // Une fonction pour fermer les paragraphes ; on essaie de preserver
252 // des paragraphes indiques a la main dans le texte
253 // (par ex: on ne modifie pas un <p align='center'>)
254 //
255 // deuxieme argument : forcer les <p> meme pour un seul paragraphe
256 //
257 // http://doc.spip.org/@paragrapher
258 // /!\ appelee dans inc/filtres et public/composer
259 function paragrapher($letexte, $forcer=true) {
260 return $letexte;
261 }
262
263 // Harmonise les retours chariots et mange les paragraphes html
264 // http://doc.spip.org/@traiter_retours_chariots
265 // ne sert plus
266 function traiter_retours_chariots($letexte) {
267 $letexte = preg_replace(",\r\n?,S", "\n", $letexte);
268 $letexte = preg_replace(",<p[>[:space:]],iS", "\n\n\\0", $letexte);
269 $letexte = preg_replace(",</p[>[:space:]],iS", "\\0\n\n", $letexte);
270 return $letexte;
271 }
272
273
274 // Filtre a appliquer aux champs du type #TEXTE*
275 // http://doc.spip.org/@propre
276 function propre($t, $connect=null, $env=array()) {
277 // les appels directs a cette fonction depuis le php de l'espace
278 // prive etant historiquement ecrits sans argment $connect
279 // on utilise la presence de celui-ci pour distinguer les cas
280 // ou il faut passer interdire_script explicitement
281 // les appels dans les squelettes (de l'espace prive) fournissant un $connect
282 // ne seront pas perturbes
283 $interdire_script = false;
284 if (is_null($connect)){
285 $connect = '';
286 $interdire_script = true;
287 }
288
289 if (!$t) return strval($t);
290
291 $t = echappe_html($t);
292 $t = expanser_liens($t,$connect, $env);
293 $t = traiter_raccourcis($t);
294 $t = echappe_retour_modeles($t, $interdire_script);
295
296 return $t;
297 }
298
299 ?>