Completed
Push — master ( 8903eb...29ddd3 )
by cam
09:08
created

texte.php ➔ typo()   C

Complexity

Conditions 12
Paths 65

Size

Total Lines 60

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 12
nc 65
nop 4
dl 0
loc 60
rs 6.446
c 0
b 0
f 0

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
/***************************************************************************\
4
 *  SPIP, Systeme de publication pour l'internet                           *
5
 *                                                                         *
6
 *  Copyright (c) 2001-2018                                                *
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
/**
14
 * Gestion des textes et raccourcis SPIP
15
 *
16
 * @package SPIP\Core\Texte
17
 **/
18
19
if (!defined('_ECRIRE_INC_VERSION')) {
20
	return;
21
}
22
23
include_spip('inc/texte_mini');
24
include_spip('inc/lien');
25
26
/*************************************************************************************************************************
27
 * Fonctions inutilisees en dehors de inc/texte
28
 *
29
 */
30
31
/**
32
 * Raccourcis dépendant du sens de la langue
33
 *
34
 * @return array Tablea ('','')
0 ignored issues
show
Documentation introduced by
Consider making the return type a bit more specific; maybe use string[].

This check looks for the generic type array as a return type and suggests a more specific type. This type is inferred from the actual code.

Loading history...
35
 */
36
function definir_raccourcis_alineas() {
37
	return array('', '');
38
}
39
40
41
/**
42
 * Traitement des raccourcis de tableaux
43
 *
44
 * Ne fait rien ici. Voir plugin Textwheel.
45
 *
46
 * @param string $bloc
47
 * @return string
48
 */
49
function traiter_tableau($bloc) {
50
	return $bloc;
51
}
52
53
54
/**
55
 * Traitement des listes
56
 *
57
 * Ne fais rien. Voir Plugin Textwheel.
58
 * (merci a Michael Parienti)
59
 *
60
 * @param string $texte
61
 * @return string
62
 */
63
function traiter_listes($texte) {
64
	return $texte;
65
}
66
67
/**
68
 * Nettoie un texte, traite les raccourcis autre qu'URL, la typo, etc.
69
 *
70
 * Ne fais rien ici. Voir plugin Textwheel.
71
 *
72
 * @pipeline_appel pre_propre
73
 * @pipeline_appel post_propre
74
 *
75
 * @param string $letexte
76
 * @return string
77
 */
78
function traiter_raccourcis($letexte) {
79
80
	// Appeler les fonctions de pre_traitement
81
	$letexte = pipeline('pre_propre', $letexte);
82
83
	// APPELER ICI UN PIPELINE traiter_raccourcis ?
84
	// $letexte = pipeline('traiter_raccourcis', $letexte);
85
86
	// Appeler les fonctions de post-traitement
87
	$letexte = pipeline('post_propre', $letexte);
88
89
	return $letexte;
90
}
91
92
/*************************************************************************************************************************
93
 * Fonctions utilisees en dehors de inc/texte
94
 */
95
96
97
/**
98
 * Échapper et affichier joliement les `<script` et `<iframe`...
99
 *
100
 * @param string $t
101
 * @param string $class Attributs HTML du conteneur à ajouter
102
 * @return string
103
 */
104
function echappe_js($t, $class = ' class = "echappe-js"') {
105
	foreach (array('script', 'iframe') as $tag) {
106
		if (stripos($t, "<$tag") !== false
107
			and preg_match_all(',<' . $tag . '.*?($|</' . $tag . '.),isS', $t, $r, PREG_SET_ORDER)
108
		) {
109
			foreach ($r as $regs) {
110
				$t = str_replace($regs[0],
111
					"<code$class>" . nl2br(spip_htmlspecialchars($regs[0])) . '</code>',
112
					$t);
113
			}
114
		}
115
	}
116
117
	return $t;
118
}
119
120
121
/**
122
 * Empêcher l'exécution de code PHP et JS
123
 *
124
 * Sécurité : empêcher l'exécution de code PHP, en le transformant en joli code
125
 * dans l'espace privé. Cette fonction est aussi appelée par propre et typo.
126
 *
127
 * De la même manière, la fonction empêche l'exécution de JS mais selon le mode
128
 * de protection passe en argument
129
 *
130
 * Il ne faut pas désactiver globalement la fonction dans l'espace privé car elle protège
131
 * aussi les balises des squelettes qui ne passent pas forcement par propre ou typo après
132
 * si elles sont appelées en direct
133
 *
134
 * @param string $arg
135
 *     Code à protéger
136
 * @param int $mode_filtre
0 ignored issues
show
Documentation introduced by
Should the type for parameter $mode_filtre not be integer|null?

This check looks for @param annotations where the type inferred by our type inference engine differs from the declared type.

It makes a suggestion as to what type it considers more descriptive.

Most often this is a case of a parameter that can be null in addition to its declared types.

Loading history...
137
 *     Mode de protection
138
 *       -1 : protection dans l'espace privé et public
139
 *       0  : protection dans l'espace public
140
 *       1  : aucune protection
141
 *     utilise la valeur de la globale filtrer_javascript si non fourni
142
 * @return string
143
 *     Code protégé
144
 **/
145
function interdire_scripts($arg, $mode_filtre=null) {
146
	// on memorise le resultat sur les arguments non triviaux
147
	static $dejavu = array();
148
149
	// Attention, si ce n'est pas une chaine, laisser intact
150
	if (!$arg or !is_string($arg) or !strstr($arg, '<')) {
151
		return $arg;
152
	}
153
154
	if (is_null($mode_filtre) or !in_array($mode_filtre, array(-1, 0, 1))) {
155
		$mode_filtre = $GLOBALS['filtrer_javascript'];
156
	}
157
158
	if (isset($dejavu[$mode_filtre][$arg])) {
159
		return $dejavu[$mode_filtre][$arg];
160
	}
161
162
	// echapper les tags asp/php
163
	$t = str_replace('<' . '%', '&lt;%', $arg);
164
165
	// echapper le php
166
	$t = str_replace('<' . '?', '&lt;?', $t);
167
168
	// echapper le < script language=php >
169
	$t = preg_replace(',<(script\b[^>]+\blanguage\b[^\w>]+php\b),UimsS', '&lt;\1', $t);
170
171
	// Pour le js, trois modes : parano (-1), prive (0), ok (1)
172
	switch ($mode_filtre) {
173
		case 0:
174
			if (!_DIR_RESTREINT) {
175
				$t = echappe_js($t);
176
			}
177
			break;
178
		case -1:
179
			$t = echappe_js($t);
180
			break;
181
	}
182
183
	// pas de <base href /> svp !
184
	$t = preg_replace(',<(base\b),iS', '&lt;\1', $t);
185
186
	// Reinserer les echappements des modeles
187
	if (defined('_PROTEGE_JS_MODELES')) {
188
		$t = echappe_retour($t, "javascript" . _PROTEGE_JS_MODELES);
189
	}
190
	if (defined('_PROTEGE_PHP_MODELES')) {
191
		$t = echappe_retour($t, "php" . _PROTEGE_PHP_MODELES);
192
	}
193
194
	return $dejavu[$mode_filtre][$arg] = $t;
195
}
196
197
198
/**
199
 * Applique la typographie générale
200
 *
201
 * Effectue un traitement pour que les textes affichés suivent les règles
202
 * de typographie. Fait une protection préalable des balises HTML et SPIP.
203
 * Transforme les balises `<multi>`
204
 *
205
 * @filtre
206
 * @uses traiter_modeles()
207
 * @uses corriger_typo()
208
 * @uses echapper_faux_tags()
209
 * @see  propre()
210
 *
211
 * @param string $letexte
212
 *     Texte d'origine
213
 * @param bool $echapper
214
 *     Échapper ?
215
 * @param string|null $connect
216
 *     Nom du connecteur à la bdd
217
 * @param array $env
218
 *     Environnement (pour les calculs de modèles)
219
 * @return string $t
220
 *     Texte transformé
221
 **/
222
function typo($letexte, $echapper = true, $connect = null, $env = array()) {
223
	// Plus vite !
224
	if (!$letexte) {
225
		return $letexte;
226
	}
227
228
	// les appels directs a cette fonction depuis le php de l'espace
229
	// prive etant historiquement ecrit sans argment $connect
230
	// on utilise la presence de celui-ci pour distinguer les cas
231
	// ou il faut passer interdire_script explicitement
232
	// les appels dans les squelettes (de l'espace prive) fournissant un $connect
233
	// ne seront pas perturbes
234
	$interdire_script = false;
235
	if (is_null($connect)) {
236
		$connect = '';
237
		$interdire_script = true;
238
		$env['espace_prive'] = test_espace_prive();
239
	}
240
241
	// Echapper les codes <html> etc
242
	if ($echapper) {
243
		$letexte = echappe_html($letexte, 'TYPO');
244
	}
245
246
	//
247
	// Installer les modeles, notamment images et documents ;
248
	//
249
	// NOTE : propre() ne passe pas par ici mais directement par corriger_typo
250
	// cf. inc/lien
251
252
	$letexte = traiter_modeles($mem = $letexte, false, $echapper ? 'TYPO' : '', $connect, null, $env);
253
	if ($letexte != $mem) {
254
		$echapper = true;
255
	}
256
	unset($mem);
257
258
	$letexte = corriger_typo($letexte);
259
	$letexte = echapper_faux_tags($letexte);
260
261
	// reintegrer les echappements
262
	if ($echapper) {
263
		$letexte = echappe_retour($letexte, 'TYPO');
264
	}
265
266
	// Dans les appels directs hors squelette, securiser ici aussi
267
	if ($interdire_script) {
268
		$letexte = interdire_scripts($letexte);
269
	}
270
271
	// Dans l'espace prive on se mefie de tout contenu dangereux
272
	// https://core.spip.net/issues/3371
273
	// et aussi dans l'espace public si la globale filtrer_javascript = -1
274
	// https://core.spip.net/issues/4166
275
	if ($GLOBALS['filtrer_javascript'] == -1
276
	  or (isset($env['espace_prive']) and $env['espace_prive'] and $GLOBALS['filtrer_javascript']<=0)) {
277
		$letexte = echapper_html_suspect($letexte);
278
	}
279
280
	return $letexte;
281
}
282
283
// Correcteur typographique
284
define('_TYPO_PROTEGER', "!':;?~%-");
285
define('_TYPO_PROTECTEUR', "\x1\x2\x3\x4\x5\x6\x7\x8");
286
287
define('_TYPO_BALISE', ",</?[a-z!][^<>]*[" . preg_quote(_TYPO_PROTEGER) . "][^<>]*>,imsS");
288
289
/**
290
 * Corrige la typographie
291
 *
292
 * Applique les corrections typographiques adaptées à la langue indiquée.
293
 *
294
 * @pipeline_appel pre_typo
295
 * @pipeline_appel post_typo
296
 * @uses corriger_caracteres()
297
 * @uses corriger_caracteres()
298
 *
299
 * @param string $letexte Texte
300
 * @param string $lang Langue
301
 * @return string Texte
302
 */
303
function corriger_typo($letexte, $lang = '') {
304
305
	// Plus vite !
306
	if (!$letexte) {
307
		return $letexte;
308
	}
309
310
	$letexte = pipeline('pre_typo', $letexte);
311
312
	// Caracteres de controle "illegaux"
313
	$letexte = corriger_caracteres($letexte);
314
315
	// Proteger les caracteres typographiques a l'interieur des tags html
316
	if (preg_match_all(_TYPO_BALISE, $letexte, $regs, PREG_SET_ORDER)) {
317
		foreach ($regs as $reg) {
318
			$insert = $reg[0];
319
			// hack: on transforme les caracteres a proteger en les remplacant
320
			// par des caracteres "illegaux". (cf corriger_caracteres())
321
			$insert = strtr($insert, _TYPO_PROTEGER, _TYPO_PROTECTEUR);
322
			$letexte = str_replace($reg[0], $insert, $letexte);
323
		}
324
	}
325
326
	// trouver les blocs idiomes et les traiter à part
327
	$letexte = extraire_idiome($ei = $letexte, $lang, true);
328
	$ei = ($ei !== $letexte);
329
330
	// trouver les blocs multi et les traiter a part
331
	$letexte = extraire_multi($em = $letexte, $lang, true);
332
	$em = ($em !== $letexte);
333
334
	// Charger & appliquer les fonctions de typographie
335
	$typographie = charger_fonction(lang_typo($lang), 'typographie');
336
	$letexte = $typographie($letexte);
337
338
	// Les citations en une autre langue, s'il y a lieu
339
	if ($em) {
340
		$letexte = echappe_retour($letexte, 'multi');
341
	}
342
	if ($ei) {
343
		$letexte = echappe_retour($letexte, 'idiome');
344
	}
345
346
	// Retablir les caracteres proteges
347
	$letexte = strtr($letexte, _TYPO_PROTECTEUR, _TYPO_PROTEGER);
348
349
	// pipeline
350
	$letexte = pipeline('post_typo', $letexte);
351
352
	# un message pour abs_url - on est passe en mode texte
353
	$GLOBALS['mode_abs_url'] = 'texte';
354
355
	return $letexte;
356
}
357
358
359
/**
360
 * Paragrapher seulement
361
 *
362
 * /!\ appelée dans inc/filtres et public/composer
363
 *
364
 * Ne fait rien ici. Voir plugin Textwheel
365
 *
366
 * @param string $letexte
367
 * @param null $forcer
0 ignored issues
show
Documentation introduced by
Should the type for parameter $forcer not be boolean|null?

This check looks for @param annotations where the type inferred by our type inference engine differs from the declared type.

It makes a suggestion as to what type it considers more descriptive.

Most often this is a case of a parameter that can be null in addition to its declared types.

Loading history...
368
 * @return string
369
 */
370
function paragrapher($letexte, $forcer = true) {
0 ignored issues
show
Unused Code introduced by
The parameter $forcer is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
371
	return $letexte;
372
}
373
374
/**
375
 * Harmonise les retours chariots et mange les paragraphes HTML
376
 *
377
 * Ne sert plus
378
 *
379
 * @param string $letexte Texte
380
 * @return string Texte
381
 **/
382
function traiter_retours_chariots($letexte) {
383
	$letexte = preg_replace(",\r\n?,S", "\n", $letexte);
384
	$letexte = preg_replace(",<p[>[:space:]],iS", "\n\n\\0", $letexte);
385
	$letexte = preg_replace(",</p[>[:space:]],iS", "\\0\n\n", $letexte);
386
387
	return $letexte;
388
}
389
390
391
/**
392
 * Transforme les raccourcis SPIP, liens et modèles d'un texte en code HTML
393
 *
394
 * Filtre à appliquer aux champs du type `#TEXTE*`
395
 *
396
 * @filtre
397
 * @uses echappe_html()
398
 * @uses expanser_liens()
399
 * @uses traiter_raccourcis()
400
 * @uses echappe_retour_modeles()
401
 * @see  typo()
402
 *
403
 * @param string $t
404
 *     Texte avec des raccourcis SPIP
405
 * @param string|null $connect
406
 *     Nom du connecteur à la bdd
407
 * @param array $env
408
 *     Environnement (pour les calculs de modèles)
409
 * @return string $t
410
 *     Texte transformé
411
 **/
412
function propre($t, $connect = null, $env = array()) {
413
	// les appels directs a cette fonction depuis le php de l'espace
414
	// prive etant historiquement ecrits sans argment $connect
415
	// on utilise la presence de celui-ci pour distinguer les cas
416
	// ou il faut passer interdire_script explicitement
417
	// les appels dans les squelettes (de l'espace prive) fournissant un $connect
418
	// ne seront pas perturbes
419
	$interdire_script = false;
420
	if (is_null($connect)) {
421
		$connect = '';
422
		$interdire_script = true;
423
	}
424
425
	if (!$t) {
426
		return strval($t);
427
	}
428
429
	// Dans l'espace prive on se mefie de tout contenu dangereux
430
	// avant echappement des balises <html>
431
	// https://core.spip.net/issues/3371
432
	// et aussi dans l'espace public si la globale filtrer_javascript = -1
433
	// https://core.spip.net/issues/4166
434
	if ($interdire_script
435
		or $GLOBALS['filtrer_javascript'] == -1
436
		or (isset($env['espace_prive']) and $env['espace_prive'] and $GLOBALS['filtrer_javascript']<=0)
437
		or (isset($env['wysiwyg']) and $env['wysiwyg'] and $GLOBALS['filtrer_javascript']<=0)) {
438
		$t = echapper_html_suspect($t, false);
439
	}
440
	$t = echappe_html($t);
441
	$t = expanser_liens($t, $connect, $env);
442
	$t = traiter_raccourcis($t);
443
	$t = echappe_retour_modeles($t, $interdire_script);
444
445
	return $t;
446
}
447