Completed
Push — master ( b5e39a...a9c0b3 )
by cam
01:07
created
ecrire/inc/texte_mini.php 1 patch
Indentation   +471 added lines, -471 removed lines patch added patch discarded remove patch
@@ -17,7 +17,7 @@  discard block
 block discarded – undo
17 17
  **/
18 18
 
19 19
 if (!defined('_ECRIRE_INC_VERSION')) {
20
-	return;
20
+    return;
21 21
 }
22 22
 include_spip('inc/filtres');
23 23
 include_spip('inc/lang');
@@ -39,21 +39,21 @@  discard block
 block discarded – undo
39 39
  **/
40 40
 function definir_puce() {
41 41
 
42
-	// Attention au sens, qui n'est pas defini de la meme facon dans
43
-	// l'espace prive (spip_lang est la langue de l'interface, lang_dir
44
-	// celle du texte) et public (spip_lang est la langue du texte)
45
-	$dir = _DIR_RESTREINT ? lang_dir() : lang_dir($GLOBALS['spip_lang']);
42
+    // Attention au sens, qui n'est pas defini de la meme facon dans
43
+    // l'espace prive (spip_lang est la langue de l'interface, lang_dir
44
+    // celle du texte) et public (spip_lang est la langue du texte)
45
+    $dir = _DIR_RESTREINT ? lang_dir() : lang_dir($GLOBALS['spip_lang']);
46 46
 
47
-	$p = 'puce' . (test_espace_prive() ? '_prive' : '');
48
-	if ($dir == 'rtl') {
49
-		$p .= '_rtl';
50
-	}
47
+    $p = 'puce' . (test_espace_prive() ? '_prive' : '');
48
+    if ($dir == 'rtl') {
49
+        $p .= '_rtl';
50
+    }
51 51
 
52
-	if (!isset($GLOBALS[$p])) {
53
-		$GLOBALS[$p] = '<span class="spip-puce ' . $dir . '"><b>–</b></span>';
54
-	}
52
+    if (!isset($GLOBALS[$p])) {
53
+        $GLOBALS[$p] = '<span class="spip-puce ' . $dir . '"><b>–</b></span>';
54
+    }
55 55
 
56
-	return $GLOBALS[$p];
56
+    return $GLOBALS[$p];
57 57
 }
58 58
 
59 59
 
@@ -61,14 +61,14 @@  discard block
 block discarded – undo
61 61
 // dont on souhaite qu'ils provoquent un saut de paragraphe
62 62
 
63 63
 if (!defined('_BALISES_BLOCS')) {
64
-	define(
65
-		'_BALISES_BLOCS',
66
-		'address|applet|article|aside|blockquote|button|center|d[ltd]|div|fieldset|fig(ure|caption)|footer|form|h[1-6r]|hgroup|head|header|iframe|li|map|marquee|nav|noscript|object|ol|pre|section|t(able|[rdh]|body|foot|extarea)|ul|script|style'
67
-	);
64
+    define(
65
+        '_BALISES_BLOCS',
66
+        'address|applet|article|aside|blockquote|button|center|d[ltd]|div|fieldset|fig(ure|caption)|footer|form|h[1-6r]|hgroup|head|header|iframe|li|map|marquee|nav|noscript|object|ol|pre|section|t(able|[rdh]|body|foot|extarea)|ul|script|style'
67
+    );
68 68
 }
69 69
 
70 70
 if (!defined('_BALISES_BLOCS_REGEXP')) {
71
-	define('_BALISES_BLOCS_REGEXP', ',</?(' . _BALISES_BLOCS . ')[>[:space:]],iS');
71
+    define('_BALISES_BLOCS_REGEXP', ',</?(' . _BALISES_BLOCS . ')[>[:space:]],iS');
72 72
 }
73 73
 
74 74
 //
@@ -79,106 +79,106 @@  discard block
 block discarded – undo
79 79
 // une $source differente ; le script detecte automagiquement si ce qu'on
80 80
 // echappe est un div ou un span
81 81
 function code_echappement($rempl, $source = '', $no_transform = false, $mode = null) {
82
-	if (!strlen($rempl)) {
83
-		return '';
84
-	}
85
-
86
-	// Tester si on echappe en span ou en div
87
-	if (is_null($mode) or !in_array($mode, ['div', 'span'])) {
88
-		$mode = preg_match(',</?(' . _BALISES_BLOCS . ')[>[:space:]],iS', $rempl) ? 'div' : 'span';
89
-	}
90
-
91
-	// Decouper en morceaux, base64 a des probleme selon la taille de la pile
92
-	$taille = 30000;
93
-	$return = '';
94
-	for ($i = 0; $i < strlen($rempl); $i += $taille) {
95
-		// Convertir en base64 et cacher dans un attribut
96
-		// utiliser les " pour eviter le re-encodage de ' et &#8217
97
-		$base64 = base64_encode(substr($rempl, $i, $taille));
98
-		$return .= "<$mode class=\"base64$source\" title=\"$base64\"></$mode>";
99
-	}
100
-
101
-	return $return;
82
+    if (!strlen($rempl)) {
83
+        return '';
84
+    }
85
+
86
+    // Tester si on echappe en span ou en div
87
+    if (is_null($mode) or !in_array($mode, ['div', 'span'])) {
88
+        $mode = preg_match(',</?(' . _BALISES_BLOCS . ')[>[:space:]],iS', $rempl) ? 'div' : 'span';
89
+    }
90
+
91
+    // Decouper en morceaux, base64 a des probleme selon la taille de la pile
92
+    $taille = 30000;
93
+    $return = '';
94
+    for ($i = 0; $i < strlen($rempl); $i += $taille) {
95
+        // Convertir en base64 et cacher dans un attribut
96
+        // utiliser les " pour eviter le re-encodage de ' et &#8217
97
+        $base64 = base64_encode(substr($rempl, $i, $taille));
98
+        $return .= "<$mode class=\"base64$source\" title=\"$base64\"></$mode>";
99
+    }
100
+
101
+    return $return;
102 102
 }
103 103
 
104 104
 
105 105
 // Echapper les <html>...</ html>
106 106
 function traiter_echap_html_dist($regs, $options = []) {
107
-	return $regs[3];
107
+    return $regs[3];
108 108
 }
109 109
 
110 110
 // Echapper les <pre>...</ pre>
111 111
 function traiter_echap_pre_dist($regs, $options = []) {
112
-	// echapper les <code> dans <pre>
113
-	$pre = $regs[3];
114
-
115
-	// echapper les < dans <code>
116
-	// on utilise _PROTEGE_BLOCS pour simplifier le code et la maintenance, mais on est interesse que par <code>
117
-	if (
118
-		strpos($pre, '<') !== false
119
-		and preg_match_all(_PROTEGE_BLOCS, $pre, $matches, PREG_SET_ORDER)
120
-	) {
121
-		foreach ($matches as $m) {
122
-			if ($m[1] === 'code') {
123
-				$code = '<code' . $m[2] . '>' . spip_htmlspecialchars($m[3]) . '</code>';
124
-				$pre = str_replace($m[0], $code, $pre);
125
-			}
126
-		}
127
-	}
128
-	return "<pre>$pre</pre>";
112
+    // echapper les <code> dans <pre>
113
+    $pre = $regs[3];
114
+
115
+    // echapper les < dans <code>
116
+    // on utilise _PROTEGE_BLOCS pour simplifier le code et la maintenance, mais on est interesse que par <code>
117
+    if (
118
+        strpos($pre, '<') !== false
119
+        and preg_match_all(_PROTEGE_BLOCS, $pre, $matches, PREG_SET_ORDER)
120
+    ) {
121
+        foreach ($matches as $m) {
122
+            if ($m[1] === 'code') {
123
+                $code = '<code' . $m[2] . '>' . spip_htmlspecialchars($m[3]) . '</code>';
124
+                $pre = str_replace($m[0], $code, $pre);
125
+            }
126
+        }
127
+    }
128
+    return "<pre>$pre</pre>";
129 129
 }
130 130
 
131 131
 // Echapper les <code>...</ code>
132 132
 function traiter_echap_code_dist($regs, $options = []) {
133
-	[, , $att, $corps] = $regs;
134
-	$echap = spip_htmlspecialchars($corps); // il ne faut pas passer dans entites_html, ne pas transformer les &#xxx; du code !
135
-
136
-	// ne pas mettre le <div...> s'il n'y a qu'une ligne
137
-	if (is_int(strpos($echap, "\n"))) {
138
-		// supprimer les sauts de ligne debut/fin
139
-		// (mais pas les espaces => ascii art).
140
-		$echap = preg_replace("/^[\n\r]+|[\n\r]+$/s", '', $echap);
141
-		$echap = nl2br($echap);
142
-		$echap = "<div style='text-align: left;' "
143
-			. "class='spip_code' dir='ltr'><code$att>"
144
-			. $echap . '</code></div>';
145
-	} else {
146
-		$echap = "<code$att class='spip_code' dir='ltr'>" . $echap . '</code>';
147
-	}
148
-
149
-	$echap = str_replace("\t", '&nbsp; &nbsp; &nbsp; &nbsp; ', $echap);
150
-	$echap = str_replace('  ', ' &nbsp;', $echap);
151
-
152
-	return $echap;
133
+    [, , $att, $corps] = $regs;
134
+    $echap = spip_htmlspecialchars($corps); // il ne faut pas passer dans entites_html, ne pas transformer les &#xxx; du code !
135
+
136
+    // ne pas mettre le <div...> s'il n'y a qu'une ligne
137
+    if (is_int(strpos($echap, "\n"))) {
138
+        // supprimer les sauts de ligne debut/fin
139
+        // (mais pas les espaces => ascii art).
140
+        $echap = preg_replace("/^[\n\r]+|[\n\r]+$/s", '', $echap);
141
+        $echap = nl2br($echap);
142
+        $echap = "<div style='text-align: left;' "
143
+            . "class='spip_code' dir='ltr'><code$att>"
144
+            . $echap . '</code></div>';
145
+    } else {
146
+        $echap = "<code$att class='spip_code' dir='ltr'>" . $echap . '</code>';
147
+    }
148
+
149
+    $echap = str_replace("\t", '&nbsp; &nbsp; &nbsp; &nbsp; ', $echap);
150
+    $echap = str_replace('  ', ' &nbsp;', $echap);
151
+
152
+    return $echap;
153 153
 }
154 154
 
155 155
 // Echapper les <cadre>...</ cadre> aka <frame>...</ frame>
156 156
 function traiter_echap_cadre_dist($regs, $options = []) {
157
-	$echap = trim(entites_html($regs[3]));
158
-	// compter les lignes un peu plus finement qu'avec les \n
159
-	$lignes = explode("\n", trim($echap));
160
-	$n = 0;
161
-	foreach ($lignes as $l) {
162
-		$n += floor(strlen($l) / 60) + 1;
163
-	}
164
-	$n = max($n, 2);
165
-	$echap = "\n<textarea readonly='readonly' cols='40' rows='$n' class='spip_cadre' dir='ltr'>$echap</textarea>";
166
-
167
-	return $echap;
157
+    $echap = trim(entites_html($regs[3]));
158
+    // compter les lignes un peu plus finement qu'avec les \n
159
+    $lignes = explode("\n", trim($echap));
160
+    $n = 0;
161
+    foreach ($lignes as $l) {
162
+        $n += floor(strlen($l) / 60) + 1;
163
+    }
164
+    $n = max($n, 2);
165
+    $echap = "\n<textarea readonly='readonly' cols='40' rows='$n' class='spip_cadre' dir='ltr'>$echap</textarea>";
166
+
167
+    return $echap;
168 168
 }
169 169
 
170 170
 function traiter_echap_frame_dist($regs, $options = []) {
171
-	return traiter_echap_cadre_dist($regs);
171
+    return traiter_echap_cadre_dist($regs);
172 172
 }
173 173
 
174 174
 function traiter_echap_script_dist($regs, $options = []) {
175
-	// rendre joli (et inactif) si c'est un script language=php
176
-	if (preg_match(',<script\b[^>]+php,ims', $regs[0])) {
177
-		return highlight_string($regs[0], true);
178
-	}
175
+    // rendre joli (et inactif) si c'est un script language=php
176
+    if (preg_match(',<script\b[^>]+php,ims', $regs[0])) {
177
+        return highlight_string($regs[0], true);
178
+    }
179 179
 
180
-	// Cas normal : le script passe tel quel
181
-	return $regs[0];
180
+    // Cas normal : le script passe tel quel
181
+    return $regs[0];
182 182
 }
183 183
 
184 184
 define('_PROTEGE_BLOCS', ',<(html|pre|code|cadre|frame|script|style)(\b[^>]*)?>(.*)</\1>,UimsS');
@@ -197,73 +197,73 @@  discard block
 block discarded – undo
197 197
  * @return string|string[]
198 198
  */
199 199
 function echappe_html(
200
-	$letexte,
201
-	$source = '',
202
-	$no_transform = false,
203
-	$preg = '',
204
-	$callback_prefix = '',
205
-	$callback_options = []
200
+    $letexte,
201
+    $source = '',
202
+    $no_transform = false,
203
+    $preg = '',
204
+    $callback_prefix = '',
205
+    $callback_options = []
206 206
 ) {
207
-	if (!is_string($letexte) or !strlen($letexte)) {
208
-		return $letexte;
209
-	}
210
-
211
-	if (
212
-		($preg or strpos($letexte, '<') !== false)
213
-		and preg_match_all($preg ?: _PROTEGE_BLOCS, $letexte, $matches, PREG_SET_ORDER)
214
-	) {
215
-		foreach ($matches as $regs) {
216
-			// echappements tels quels ?
217
-			if ($no_transform) {
218
-				$echap = $regs[0];
219
-			} // sinon les traiter selon le cas
220
-			else {
221
-				$callback_secure_prefix = ($callback_options['secure_prefix'] ?? '');
222
-				if (
223
-					function_exists($f = $callback_prefix . $callback_secure_prefix . 'traiter_echap_' . strtolower($regs[1]))
224
-					or function_exists($f = $f . '_dist')
225
-					or ($callback_secure_prefix and (
226
-						function_exists($f = $callback_prefix . 'traiter_echap_' . strtolower($regs[1]))
227
-						or function_exists($f = $f . '_dist')
228
-					))
229
-				) {
230
-					$echap = $f($regs, $callback_options);
231
-				}
232
-			}
233
-
234
-			$p = strpos($letexte, (string) $regs[0]);
235
-			$letexte = substr_replace($letexte, code_echappement($echap, $source, $no_transform), $p, strlen($regs[0]));
236
-		}
237
-	}
238
-
239
-	if ($no_transform) {
240
-		return $letexte;
241
-	}
242
-
243
-	// Echapper le php pour faire joli (ici, c'est pas pour la securite)
244
-	// seulement si on a echappe les <script>
245
-	// (derogatoire car on ne peut pas faire passer < ? ... ? >
246
-	// dans une callback autonommee
247
-	if (strpos($preg ?: _PROTEGE_BLOCS, 'script') !== false) {
248
-		if (
249
-			strpos($letexte, '<' . '?') !== false and preg_match_all(
250
-				',<[?].*($|[?]>),UisS',
251
-				$letexte,
252
-				$matches,
253
-				PREG_SET_ORDER
254
-			)
255
-		) {
256
-			foreach ($matches as $regs) {
257
-				$letexte = str_replace(
258
-					$regs[0],
259
-					code_echappement(highlight_string($regs[0], true), $source),
260
-					$letexte
261
-				);
262
-			}
263
-		}
264
-	}
265
-
266
-	return $letexte;
207
+    if (!is_string($letexte) or !strlen($letexte)) {
208
+        return $letexte;
209
+    }
210
+
211
+    if (
212
+        ($preg or strpos($letexte, '<') !== false)
213
+        and preg_match_all($preg ?: _PROTEGE_BLOCS, $letexte, $matches, PREG_SET_ORDER)
214
+    ) {
215
+        foreach ($matches as $regs) {
216
+            // echappements tels quels ?
217
+            if ($no_transform) {
218
+                $echap = $regs[0];
219
+            } // sinon les traiter selon le cas
220
+            else {
221
+                $callback_secure_prefix = ($callback_options['secure_prefix'] ?? '');
222
+                if (
223
+                    function_exists($f = $callback_prefix . $callback_secure_prefix . 'traiter_echap_' . strtolower($regs[1]))
224
+                    or function_exists($f = $f . '_dist')
225
+                    or ($callback_secure_prefix and (
226
+                        function_exists($f = $callback_prefix . 'traiter_echap_' . strtolower($regs[1]))
227
+                        or function_exists($f = $f . '_dist')
228
+                    ))
229
+                ) {
230
+                    $echap = $f($regs, $callback_options);
231
+                }
232
+            }
233
+
234
+            $p = strpos($letexte, (string) $regs[0]);
235
+            $letexte = substr_replace($letexte, code_echappement($echap, $source, $no_transform), $p, strlen($regs[0]));
236
+        }
237
+    }
238
+
239
+    if ($no_transform) {
240
+        return $letexte;
241
+    }
242
+
243
+    // Echapper le php pour faire joli (ici, c'est pas pour la securite)
244
+    // seulement si on a echappe les <script>
245
+    // (derogatoire car on ne peut pas faire passer < ? ... ? >
246
+    // dans une callback autonommee
247
+    if (strpos($preg ?: _PROTEGE_BLOCS, 'script') !== false) {
248
+        if (
249
+            strpos($letexte, '<' . '?') !== false and preg_match_all(
250
+                ',<[?].*($|[?]>),UisS',
251
+                $letexte,
252
+                $matches,
253
+                PREG_SET_ORDER
254
+            )
255
+        ) {
256
+            foreach ($matches as $regs) {
257
+                $letexte = str_replace(
258
+                    $regs[0],
259
+                    code_echappement(highlight_string($regs[0], true), $source),
260
+                    $letexte
261
+                );
262
+            }
263
+        }
264
+    }
265
+
266
+    return $letexte;
267 267
 }
268 268
 
269 269
 //
@@ -271,57 +271,57 @@  discard block
 block discarded – undo
271 271
 // Rq: $source sert a faire des echappements "a soi" qui ne sont pas nettoyes
272 272
 // par propre() : exemple dans multi et dans typo()
273 273
 function echappe_retour($letexte, $source = '', $filtre = '') {
274
-	if (strpos($letexte, (string) "base64$source")) {
275
-		# spip_log(spip_htmlspecialchars($letexte));  ## pour les curieux
276
-		$max_prof = 5;
277
-		while (
278
-			strpos($letexte, '<') !== false
279
-			and
280
-			preg_match_all(
281
-				',<(span|div)\sclass=[\'"]base64' . $source . '[\'"]\s(.*)>\s*</\1>,UmsS',
282
-				$letexte,
283
-				$regs,
284
-				PREG_SET_ORDER
285
-			)
286
-			and $max_prof--
287
-		) {
288
-			foreach ($regs as $reg) {
289
-				$rempl = base64_decode(extraire_attribut($reg[0], 'title'));
290
-				// recherche d'attributs supplementaires
291
-				$at = [];
292
-				foreach (['lang', 'dir'] as $attr) {
293
-					if ($a = extraire_attribut($reg[0], $attr)) {
294
-						$at[$attr] = $a;
295
-					}
296
-				}
297
-				if ($at) {
298
-					$rempl = '<' . $reg[1] . '>' . $rempl . '</' . $reg[1] . '>';
299
-					foreach ($at as $attr => $a) {
300
-						$rempl = inserer_attribut($rempl, $attr, $a);
301
-					}
302
-				}
303
-				if ($filtre) {
304
-					$rempl = $filtre($rempl);
305
-				}
306
-				$letexte = str_replace($reg[0], $rempl, $letexte);
307
-			}
308
-		}
309
-	}
310
-
311
-	return $letexte;
274
+    if (strpos($letexte, (string) "base64$source")) {
275
+        # spip_log(spip_htmlspecialchars($letexte));  ## pour les curieux
276
+        $max_prof = 5;
277
+        while (
278
+            strpos($letexte, '<') !== false
279
+            and
280
+            preg_match_all(
281
+                ',<(span|div)\sclass=[\'"]base64' . $source . '[\'"]\s(.*)>\s*</\1>,UmsS',
282
+                $letexte,
283
+                $regs,
284
+                PREG_SET_ORDER
285
+            )
286
+            and $max_prof--
287
+        ) {
288
+            foreach ($regs as $reg) {
289
+                $rempl = base64_decode(extraire_attribut($reg[0], 'title'));
290
+                // recherche d'attributs supplementaires
291
+                $at = [];
292
+                foreach (['lang', 'dir'] as $attr) {
293
+                    if ($a = extraire_attribut($reg[0], $attr)) {
294
+                        $at[$attr] = $a;
295
+                    }
296
+                }
297
+                if ($at) {
298
+                    $rempl = '<' . $reg[1] . '>' . $rempl . '</' . $reg[1] . '>';
299
+                    foreach ($at as $attr => $a) {
300
+                        $rempl = inserer_attribut($rempl, $attr, $a);
301
+                    }
302
+                }
303
+                if ($filtre) {
304
+                    $rempl = $filtre($rempl);
305
+                }
306
+                $letexte = str_replace($reg[0], $rempl, $letexte);
307
+            }
308
+        }
309
+    }
310
+
311
+    return $letexte;
312 312
 }
313 313
 
314 314
 // Reinserer le javascript de confiance (venant des modeles)
315 315
 
316 316
 function echappe_retour_modeles($letexte, $interdire_scripts = false) {
317
-	$letexte = echappe_retour($letexte);
317
+    $letexte = echappe_retour($letexte);
318 318
 
319
-	// Dans les appels directs hors squelette, securiser aussi ici
320
-	if ($interdire_scripts) {
321
-		$letexte = interdire_scripts($letexte);
322
-	}
319
+    // Dans les appels directs hors squelette, securiser aussi ici
320
+    if ($interdire_scripts) {
321
+        $letexte = interdire_scripts($letexte);
322
+    }
323 323
 
324
-	return trim($letexte);
324
+    return trim($letexte);
325 325
 }
326 326
 
327 327
 
@@ -349,131 +349,131 @@  discard block
 block discarded – undo
349 349
  *     Texte coupé
350 350
  **/
351 351
 function couper($texte, $taille = 50, $suite = null) {
352
-	if (!($length = strlen($texte)) or $taille <= 0) {
353
-		return '';
354
-	}
355
-	$offset = 400 + 2 * $taille;
356
-	while (
357
-		$offset < $length
358
-		and strlen(preg_replace(',<(!--|\w|/)[^>]+>,Uims', '', substr($texte, 0, $offset))) < $taille
359
-	) {
360
-		$offset = 2 * $offset;
361
-	}
362
-	if (
363
-		$offset < $length
364
-		&& ($p_tag_ouvrant = strpos($texte, '<', $offset)) !== null
365
-	) {
366
-		$p_tag_fermant = strpos($texte, '>', $offset);
367
-		if ($p_tag_fermant && ($p_tag_fermant < $p_tag_ouvrant)) {
368
-			$offset = $p_tag_fermant + 1;
369
-		} // prolonger la coupe jusqu'au tag fermant suivant eventuel
370
-	}
371
-	$texte = substr($texte, 0, $offset); /* eviter de travailler sur 10ko pour extraire 150 caracteres */
372
-
373
-	if (!function_exists('nettoyer_raccourcis_typo')) {
374
-		include_spip('inc/lien');
375
-	}
376
-	$texte = nettoyer_raccourcis_typo($texte);
377
-
378
-	// balises de sauts de ligne et paragraphe
379
-	$texte = preg_replace('/<p( [^>]*)?' . '>/', "\r", $texte);
380
-	$texte = preg_replace('/<br( [^>]*)?' . '>/', "\n", $texte);
381
-
382
-	// on repasse les doubles \n en \r que nettoyer_raccourcis_typo() a pu modifier
383
-	$texte = str_replace("\n\n", "\r", $texte);
384
-
385
-	// supprimer les tags
386
-	$texte = supprimer_tags($texte);
387
-	$texte = trim(str_replace("\n", ' ', $texte));
388
-	$texte .= "\n";  // marquer la fin
389
-
390
-	// corriger la longueur de coupe
391
-	// en fonction de la presence de caracteres utf
392
-	if ($GLOBALS['meta']['charset'] == 'utf-8') {
393
-		$long = charset2unicode($texte);
394
-		$long = spip_substr($long, 0, max($taille, 1));
395
-		$nbcharutf = preg_match_all('/(&#[0-9]{3,6};)/S', $long, $matches);
396
-		$taille += $nbcharutf;
397
-	}
398
-
399
-
400
-	// couper au mot precedent
401
-	$long = spip_substr($texte, 0, max($taille - 4, 1));
402
-	$u = $GLOBALS['meta']['pcre_u'];
403
-	$court = preg_replace("/([^\s][\s]+)[^\s]*\n?$/" . $u, "\\1", $long);
404
-	if (is_null($suite)) {
405
-		$suite = (defined('_COUPER_SUITE') ? _COUPER_SUITE : '&nbsp;(...)');
406
-	}
407
-	$points = $suite;
408
-
409
-	// trop court ? ne pas faire de (...)
410
-	if (spip_strlen($court) < max(0.75 * $taille, 2)) {
411
-		$points = '';
412
-		$long = spip_substr($texte, 0, $taille);
413
-		$texte = preg_replace("/([^\s][\s]+)[^\s]*\n?$/" . $u, "\\1", $long);
414
-		// encore trop court ? couper au caractere
415
-		if (spip_strlen($texte) < 0.75 * $taille) {
416
-			$texte = $long;
417
-		}
418
-	} else {
419
-		$texte = $court;
420
-	}
421
-
422
-	if (strpos($texte, "\n")) {  // la fin est encore la : c'est qu'on n'a pas de texte de suite
423
-	$points = '';
424
-	}
425
-
426
-	// remettre les paragraphes
427
-	$texte = preg_replace("/\r+/", "\n\n", $texte);
428
-
429
-	// supprimer l'eventuelle entite finale mal coupee
430
-	$texte = preg_replace('/&#?[a-z0-9]*$/S', '', $texte);
431
-
432
-	return quote_amp(trim($texte)) . $points;
352
+    if (!($length = strlen($texte)) or $taille <= 0) {
353
+        return '';
354
+    }
355
+    $offset = 400 + 2 * $taille;
356
+    while (
357
+        $offset < $length
358
+        and strlen(preg_replace(',<(!--|\w|/)[^>]+>,Uims', '', substr($texte, 0, $offset))) < $taille
359
+    ) {
360
+        $offset = 2 * $offset;
361
+    }
362
+    if (
363
+        $offset < $length
364
+        && ($p_tag_ouvrant = strpos($texte, '<', $offset)) !== null
365
+    ) {
366
+        $p_tag_fermant = strpos($texte, '>', $offset);
367
+        if ($p_tag_fermant && ($p_tag_fermant < $p_tag_ouvrant)) {
368
+            $offset = $p_tag_fermant + 1;
369
+        } // prolonger la coupe jusqu'au tag fermant suivant eventuel
370
+    }
371
+    $texte = substr($texte, 0, $offset); /* eviter de travailler sur 10ko pour extraire 150 caracteres */
372
+
373
+    if (!function_exists('nettoyer_raccourcis_typo')) {
374
+        include_spip('inc/lien');
375
+    }
376
+    $texte = nettoyer_raccourcis_typo($texte);
377
+
378
+    // balises de sauts de ligne et paragraphe
379
+    $texte = preg_replace('/<p( [^>]*)?' . '>/', "\r", $texte);
380
+    $texte = preg_replace('/<br( [^>]*)?' . '>/', "\n", $texte);
381
+
382
+    // on repasse les doubles \n en \r que nettoyer_raccourcis_typo() a pu modifier
383
+    $texte = str_replace("\n\n", "\r", $texte);
384
+
385
+    // supprimer les tags
386
+    $texte = supprimer_tags($texte);
387
+    $texte = trim(str_replace("\n", ' ', $texte));
388
+    $texte .= "\n";  // marquer la fin
389
+
390
+    // corriger la longueur de coupe
391
+    // en fonction de la presence de caracteres utf
392
+    if ($GLOBALS['meta']['charset'] == 'utf-8') {
393
+        $long = charset2unicode($texte);
394
+        $long = spip_substr($long, 0, max($taille, 1));
395
+        $nbcharutf = preg_match_all('/(&#[0-9]{3,6};)/S', $long, $matches);
396
+        $taille += $nbcharutf;
397
+    }
398
+
399
+
400
+    // couper au mot precedent
401
+    $long = spip_substr($texte, 0, max($taille - 4, 1));
402
+    $u = $GLOBALS['meta']['pcre_u'];
403
+    $court = preg_replace("/([^\s][\s]+)[^\s]*\n?$/" . $u, "\\1", $long);
404
+    if (is_null($suite)) {
405
+        $suite = (defined('_COUPER_SUITE') ? _COUPER_SUITE : '&nbsp;(...)');
406
+    }
407
+    $points = $suite;
408
+
409
+    // trop court ? ne pas faire de (...)
410
+    if (spip_strlen($court) < max(0.75 * $taille, 2)) {
411
+        $points = '';
412
+        $long = spip_substr($texte, 0, $taille);
413
+        $texte = preg_replace("/([^\s][\s]+)[^\s]*\n?$/" . $u, "\\1", $long);
414
+        // encore trop court ? couper au caractere
415
+        if (spip_strlen($texte) < 0.75 * $taille) {
416
+            $texte = $long;
417
+        }
418
+    } else {
419
+        $texte = $court;
420
+    }
421
+
422
+    if (strpos($texte, "\n")) {  // la fin est encore la : c'est qu'on n'a pas de texte de suite
423
+    $points = '';
424
+    }
425
+
426
+    // remettre les paragraphes
427
+    $texte = preg_replace("/\r+/", "\n\n", $texte);
428
+
429
+    // supprimer l'eventuelle entite finale mal coupee
430
+    $texte = preg_replace('/&#?[a-z0-9]*$/S', '', $texte);
431
+
432
+    return quote_amp(trim($texte)) . $points;
433 433
 }
434 434
 
435 435
 
436 436
 function protege_js_modeles($t) {
437
-	if (isset($GLOBALS['visiteur_session'])) {
438
-		if (preg_match_all(',<script.*?($|</script.),isS', $t, $r, PREG_SET_ORDER)) {
439
-			if (!defined('_PROTEGE_JS_MODELES')) {
440
-				include_spip('inc/acces');
441
-				define('_PROTEGE_JS_MODELES', creer_uniqid());
442
-			}
443
-			foreach ($r as $regs) {
444
-				$t = str_replace($regs[0], code_echappement($regs[0], 'javascript' . _PROTEGE_JS_MODELES), $t);
445
-			}
446
-		}
447
-		if (preg_match_all(',<\?php.*?($|\?' . '>),isS', $t, $r, PREG_SET_ORDER)) {
448
-			if (!defined('_PROTEGE_PHP_MODELES')) {
449
-				include_spip('inc/acces');
450
-				define('_PROTEGE_PHP_MODELES', creer_uniqid());
451
-			}
452
-			foreach ($r as $regs) {
453
-				$t = str_replace($regs[0], code_echappement($regs[0], 'php' . _PROTEGE_PHP_MODELES), $t);
454
-			}
455
-		}
456
-	}
457
-
458
-	return $t;
437
+    if (isset($GLOBALS['visiteur_session'])) {
438
+        if (preg_match_all(',<script.*?($|</script.),isS', $t, $r, PREG_SET_ORDER)) {
439
+            if (!defined('_PROTEGE_JS_MODELES')) {
440
+                include_spip('inc/acces');
441
+                define('_PROTEGE_JS_MODELES', creer_uniqid());
442
+            }
443
+            foreach ($r as $regs) {
444
+                $t = str_replace($regs[0], code_echappement($regs[0], 'javascript' . _PROTEGE_JS_MODELES), $t);
445
+            }
446
+        }
447
+        if (preg_match_all(',<\?php.*?($|\?' . '>),isS', $t, $r, PREG_SET_ORDER)) {
448
+            if (!defined('_PROTEGE_PHP_MODELES')) {
449
+                include_spip('inc/acces');
450
+                define('_PROTEGE_PHP_MODELES', creer_uniqid());
451
+            }
452
+            foreach ($r as $regs) {
453
+                $t = str_replace($regs[0], code_echappement($regs[0], 'php' . _PROTEGE_PHP_MODELES), $t);
454
+            }
455
+        }
456
+    }
457
+
458
+    return $t;
459 459
 }
460 460
 
461 461
 
462 462
 function echapper_faux_tags($letexte) {
463
-	if (strpos($letexte, '<') === false) {
464
-		return $letexte;
465
-	}
466
-	$textMatches = preg_split(',(</?[a-z!][^<>]*>),', $letexte, -1, PREG_SPLIT_DELIM_CAPTURE);
467
-
468
-	$letexte = '';
469
-	while (is_countable($textMatches) ? count($textMatches) : 0) {
470
-		// un texte a echapper
471
-		$letexte .= str_replace('<', '&lt;', array_shift($textMatches));
472
-		// un tag html qui a servit a faite le split
473
-		$letexte .= array_shift($textMatches);
474
-	}
475
-
476
-	return $letexte;
463
+    if (strpos($letexte, '<') === false) {
464
+        return $letexte;
465
+    }
466
+    $textMatches = preg_split(',(</?[a-z!][^<>]*>),', $letexte, -1, PREG_SPLIT_DELIM_CAPTURE);
467
+
468
+    $letexte = '';
469
+    while (is_countable($textMatches) ? count($textMatches) : 0) {
470
+        // un texte a echapper
471
+        $letexte .= str_replace('<', '&lt;', array_shift($textMatches));
472
+        // un tag html qui a servit a faite le split
473
+        $letexte .= array_shift($textMatches);
474
+    }
475
+
476
+    return $letexte;
477 477
 }
478 478
 
479 479
 /**
@@ -493,104 +493,104 @@  discard block
 block discarded – undo
493 493
  * @return string
494 494
  */
495 495
 function echapper_html_suspect($texte, $options = [], $connect = null, $env = []) {
496
-	static $echapper_html_suspect;
497
-	if (!$texte or !is_string($texte)) {
498
-		return $texte;
499
-	}
500
-
501
-	if (!isset($echapper_html_suspect)) {
502
-		$echapper_html_suspect = charger_fonction('echapper_html_suspect', 'inc', true);
503
-	}
504
-	// si fonction personalisee, on delegue
505
-	if ($echapper_html_suspect) {
506
-		// on collecte le tableau d'arg minimal pour ne pas casser un appel a une fonction inc_echapper_html_suspect() selon l'ancienne signature
507
-		$args = [$texte, $options];
508
-		if ($connect or !empty($env)) {
509
-			$args[] = $connect;
510
-		}
511
-		if (!empty($env)) {
512
-			$args[] = $env;
513
-		}
514
-		return $echapper_html_suspect(...$args);
515
-	}
516
-
517
-	if (is_bool($options)) {
518
-		$options = ['strict' => $options];
519
-	}
520
-	$strict = $options['strict'] ?? true;
521
-
522
-	// pas de balise html ou pas d'attribut sur les balises ? c'est OK
523
-	if (
524
-		strpos($texte, '<') === false
525
-		or strpos($texte, '=') === false
526
-	) {
527
-		return $texte;
528
-	}
529
-
530
-	// dans le prive, on veut afficher tout echappé pour la moderation
531
-	if (!isset($env['espace_prive'])) {
532
-		// conserver le comportement historique en cas d'appel court sans env
533
-		$env['espace_prive'] = test_espace_prive();
534
-	}
535
-	if (!empty($env['espace_prive']) or !empty($env['wysiwyg'])) {
536
-
537
-		// quand c'est du texte qui passe par propre on est plus coulant tant qu'il y a pas d'attribut du type onxxx=
538
-		// car sinon on declenche sur les modeles ou ressources
539
-		if (
540
-			!$strict and
541
-			(strpos($texte, 'on') === false or !preg_match(",<\w+.*\bon\w+\s*=,UimsS", $texte))
542
-		) {
543
-			return $texte;
544
-		}
545
-
546
-		[$texte, $markidmodeles] = modeles_echapper_raccourcis($texte, false);
547
-		$texte = echappe_js($texte);
548
-
549
-		$texte_to_check = $texte;
550
-		// si les raccourcis liens vont etre interprétés, il faut les expanser avant de vérifier que le html est safe
551
-		// car un raccourci peut etre utilisé pour faire un lien malin
552
-		// et un raccourci est potentiellement modifié par safehtml, ce qui fait un faux positif dans is_html_safe
553
-		if (!empty($options['expanser_liens'])) {
554
-			$texte_to_check = expanser_liens($texte_to_check, $env['connect'] ?? '', $env['env'] ?? []);
555
-		}
556
-		if (!is_html_safe($texte_to_check)) {
557
-			$texte = $options['texte_source_affiche'] ?? $texte;
558
-			$texte = preg_replace(",<(/?\w+\b[^>]*>),", "<tt>&lt;\\1</tt>", $texte);
559
-			$texte = str_replace('<', '&lt;', $texte);
560
-			$texte = str_replace('&lt;tt>', '<tt>', $texte);
561
-			$texte = str_replace('&lt;/tt>', '</tt>', $texte);
562
-			if (!function_exists('attribut_html')) {
563
-				include_spip('inc/filtres');
564
-			}
565
-			if (!empty($options['wrap_suspect'])) {
566
-				$texte = wrap($texte, $options['wrap_suspect']);
567
-			}
568
-			$texte = "<mark class='danger-js' title='" . attribut_html(_T('erreur_contenu_suspect')) . "'>⚠️</mark> " . $texte;
569
-		}
570
-		$texte = modele_retablir_raccourcis_echappes($texte, $markidmodeles);
571
-	}
572
-
573
-	// si on est là dans le public c'est le mode parano
574
-	// on veut donc un rendu propre et secure, et virer silencieusement ce qui est dangereux
575
-	else {
576
-		$markidmodeles = $markidliens = null;
577
-		if (!empty($options['expanser_liens'])) {
578
-			$texte = expanser_liens($texte, $env['connect'] ?? '', $env['env'] ?? []);
579
-		}
580
-		else {
581
-			[$texte, $markidliens] = liens_echapper_raccourcis($texte, 'safehtml');
582
-			[$texte, $markidmodeles] = modeles_echapper_raccourcis($texte, false);
583
-		}
584
-		$texte = safehtml($texte);
585
-		if ($markidmodeles) {
586
-			$texte = modele_retablir_raccourcis_echappes($texte, $markidmodeles);
587
-		}
588
-		if ($markidliens) {
589
-			$texte = liens_retablir_raccourcis_echappes($texte, $markidliens);
590
-		}
591
-	}
592
-
593
-	return $texte;
496
+    static $echapper_html_suspect;
497
+    if (!$texte or !is_string($texte)) {
498
+        return $texte;
499
+    }
500
+
501
+    if (!isset($echapper_html_suspect)) {
502
+        $echapper_html_suspect = charger_fonction('echapper_html_suspect', 'inc', true);
503
+    }
504
+    // si fonction personalisee, on delegue
505
+    if ($echapper_html_suspect) {
506
+        // on collecte le tableau d'arg minimal pour ne pas casser un appel a une fonction inc_echapper_html_suspect() selon l'ancienne signature
507
+        $args = [$texte, $options];
508
+        if ($connect or !empty($env)) {
509
+            $args[] = $connect;
510
+        }
511
+        if (!empty($env)) {
512
+            $args[] = $env;
513
+        }
514
+        return $echapper_html_suspect(...$args);
515
+    }
516
+
517
+    if (is_bool($options)) {
518
+        $options = ['strict' => $options];
519
+    }
520
+    $strict = $options['strict'] ?? true;
521
+
522
+    // pas de balise html ou pas d'attribut sur les balises ? c'est OK
523
+    if (
524
+        strpos($texte, '<') === false
525
+        or strpos($texte, '=') === false
526
+    ) {
527
+        return $texte;
528
+    }
529
+
530
+    // dans le prive, on veut afficher tout echappé pour la moderation
531
+    if (!isset($env['espace_prive'])) {
532
+        // conserver le comportement historique en cas d'appel court sans env
533
+        $env['espace_prive'] = test_espace_prive();
534
+    }
535
+    if (!empty($env['espace_prive']) or !empty($env['wysiwyg'])) {
536
+
537
+        // quand c'est du texte qui passe par propre on est plus coulant tant qu'il y a pas d'attribut du type onxxx=
538
+        // car sinon on declenche sur les modeles ou ressources
539
+        if (
540
+            !$strict and
541
+            (strpos($texte, 'on') === false or !preg_match(",<\w+.*\bon\w+\s*=,UimsS", $texte))
542
+        ) {
543
+            return $texte;
544
+        }
545
+
546
+        [$texte, $markidmodeles] = modeles_echapper_raccourcis($texte, false);
547
+        $texte = echappe_js($texte);
548
+
549
+        $texte_to_check = $texte;
550
+        // si les raccourcis liens vont etre interprétés, il faut les expanser avant de vérifier que le html est safe
551
+        // car un raccourci peut etre utilisé pour faire un lien malin
552
+        // et un raccourci est potentiellement modifié par safehtml, ce qui fait un faux positif dans is_html_safe
553
+        if (!empty($options['expanser_liens'])) {
554
+            $texte_to_check = expanser_liens($texte_to_check, $env['connect'] ?? '', $env['env'] ?? []);
555
+        }
556
+        if (!is_html_safe($texte_to_check)) {
557
+            $texte = $options['texte_source_affiche'] ?? $texte;
558
+            $texte = preg_replace(",<(/?\w+\b[^>]*>),", "<tt>&lt;\\1</tt>", $texte);
559
+            $texte = str_replace('<', '&lt;', $texte);
560
+            $texte = str_replace('&lt;tt>', '<tt>', $texte);
561
+            $texte = str_replace('&lt;/tt>', '</tt>', $texte);
562
+            if (!function_exists('attribut_html')) {
563
+                include_spip('inc/filtres');
564
+            }
565
+            if (!empty($options['wrap_suspect'])) {
566
+                $texte = wrap($texte, $options['wrap_suspect']);
567
+            }
568
+            $texte = "<mark class='danger-js' title='" . attribut_html(_T('erreur_contenu_suspect')) . "'>⚠️</mark> " . $texte;
569
+        }
570
+        $texte = modele_retablir_raccourcis_echappes($texte, $markidmodeles);
571
+    }
572
+
573
+    // si on est là dans le public c'est le mode parano
574
+    // on veut donc un rendu propre et secure, et virer silencieusement ce qui est dangereux
575
+    else {
576
+        $markidmodeles = $markidliens = null;
577
+        if (!empty($options['expanser_liens'])) {
578
+            $texte = expanser_liens($texte, $env['connect'] ?? '', $env['env'] ?? []);
579
+        }
580
+        else {
581
+            [$texte, $markidliens] = liens_echapper_raccourcis($texte, 'safehtml');
582
+            [$texte, $markidmodeles] = modeles_echapper_raccourcis($texte, false);
583
+        }
584
+        $texte = safehtml($texte);
585
+        if ($markidmodeles) {
586
+            $texte = modele_retablir_raccourcis_echappes($texte, $markidmodeles);
587
+        }
588
+        if ($markidliens) {
589
+            $texte = liens_retablir_raccourcis_echappes($texte, $markidliens);
590
+        }
591
+    }
592
+
593
+    return $texte;
594 594
 }
595 595
 
596 596
 
@@ -611,30 +611,30 @@  discard block
 block discarded – undo
611 611
  *      Texte sécurisé
612 612
  **/
613 613
 function safehtml($t) {
614
-	static $safehtml;
615
-
616
-	if (!$t or !is_string($t)) {
617
-		return $t;
618
-	}
619
-	# attention safehtml nettoie deux ou trois caracteres de plus. A voir
620
-	if (strpos($t, '<') === false) {
621
-		return str_replace("\x00", '', $t);
622
-	}
623
-
624
-	if (!function_exists('interdire_scripts')) {
625
-		include_spip('inc/texte');
626
-	}
627
-	$t = interdire_scripts($t); // jolifier le php
628
-	$t = echappe_js($t);
629
-
630
-	if (!isset($safehtml)) {
631
-		$safehtml = charger_fonction('safehtml', 'inc', true);
632
-	}
633
-	if ($safehtml) {
634
-		$t = $safehtml($t);
635
-	}
636
-
637
-	return interdire_scripts($t); // interdire le php (2 precautions)
614
+    static $safehtml;
615
+
616
+    if (!$t or !is_string($t)) {
617
+        return $t;
618
+    }
619
+    # attention safehtml nettoie deux ou trois caracteres de plus. A voir
620
+    if (strpos($t, '<') === false) {
621
+        return str_replace("\x00", '', $t);
622
+    }
623
+
624
+    if (!function_exists('interdire_scripts')) {
625
+        include_spip('inc/texte');
626
+    }
627
+    $t = interdire_scripts($t); // jolifier le php
628
+    $t = echappe_js($t);
629
+
630
+    if (!isset($safehtml)) {
631
+        $safehtml = charger_fonction('safehtml', 'inc', true);
632
+    }
633
+    if ($safehtml) {
634
+        $t = $safehtml($t);
635
+    }
636
+
637
+    return interdire_scripts($t); // interdire le php (2 precautions)
638 638
 }
639 639
 
640 640
 
@@ -642,25 +642,25 @@  discard block
 block discarded – undo
642 642
  * Detecter si un texte est "safe" ie non modifie significativement par safehtml()
643 643
  */
644 644
 function is_html_safe(string $texte): bool {
645
-	if ($is_html_safe = charger_fonction('is_html_safe', 'inc', true)) {
646
-		return $is_html_safe($texte);
647
-	}
648
-
649
-	// simplifier les retour ligne pour etre certain de ce que l'on compare
650
-	$texte = str_replace("\r\n", "\n", $texte);
651
-	// safehtml reduit aussi potentiellement les &nbsp;
652
-	$texte = str_replace("&nbsp;", " ", $texte);
653
-	// safehtml remplace les entités numériques
654
-	if (strpos($texte, '&#') !== false) {
655
-		$texte = unicode2charset($texte);
656
-	}
657
-
658
-	$texte_safe = safehtml($texte);
659
-
660
-	// on teste sur strlen car safehtml supprime le contenu dangereux
661
-	// mais il peut aussi changer des ' en " sur les attributs html,
662
-	// donc un test d'egalite est trop strict
663
-	return strlen($texte_safe) === strlen($texte);
645
+    if ($is_html_safe = charger_fonction('is_html_safe', 'inc', true)) {
646
+        return $is_html_safe($texte);
647
+    }
648
+
649
+    // simplifier les retour ligne pour etre certain de ce que l'on compare
650
+    $texte = str_replace("\r\n", "\n", $texte);
651
+    // safehtml reduit aussi potentiellement les &nbsp;
652
+    $texte = str_replace("&nbsp;", " ", $texte);
653
+    // safehtml remplace les entités numériques
654
+    if (strpos($texte, '&#') !== false) {
655
+        $texte = unicode2charset($texte);
656
+    }
657
+
658
+    $texte_safe = safehtml($texte);
659
+
660
+    // on teste sur strlen car safehtml supprime le contenu dangereux
661
+    // mais il peut aussi changer des ' en " sur les attributs html,
662
+    // donc un test d'egalite est trop strict
663
+    return strlen($texte_safe) === strlen($texte);
664 664
 }
665 665
 
666 666
 /**
@@ -681,13 +681,13 @@  discard block
 block discarded – undo
681 681
  *     Texte sans les modèles d'image
682 682
  **/
683 683
 function supprime_img($letexte, $message = null) {
684
-	if ($message === null) {
685
-		$message = '(' . _T('img_indisponible') . ')';
686
-	}
687
-
688
-	return preg_replace(
689
-		',<(img|doc|emb)([0-9]+)(\|([^>]*))?' . '\s*/?' . '>,i',
690
-		$message,
691
-		$letexte
692
-	);
684
+    if ($message === null) {
685
+        $message = '(' . _T('img_indisponible') . ')';
686
+    }
687
+
688
+    return preg_replace(
689
+        ',<(img|doc|emb)([0-9]+)(\|([^>]*))?' . '\s*/?' . '>,i',
690
+        $message,
691
+        $letexte
692
+    );
693 693
 }
Please login to merge, or discard this patch.