Completed
Push — master ( cacd66...717daf )
by cam
02:37 queued 21s
created
ecrire/inc/modifier.php 1 patch
Indentation   +259 added lines, -259 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
 
23 23
 /**
@@ -39,28 +39,28 @@  discard block
 block discarded – undo
39 39
  *     Tableau des champs et valeurs collectées
40 40
  */
41 41
 function collecter_requests($include_list, $exclude_list = [], $set = null, $tous = false) {
42
-	$c = $set;
43
-	if (!$c) {
44
-		$c = [];
45
-		foreach ($include_list as $champ) {
46
-			// on ne collecte que les champs reellement envoyes par defaut.
47
-			// le cas d'un envoi de valeur NULL peut du coup poser probleme.
48
-			$val = _request($champ);
49
-			if ($tous or $val !== null) {
50
-				$c[$champ] = $val;
51
-			}
52
-		}
53
-		// on ajoute toujours la lang en saisie possible
54
-		// meme si pas prevu au depart pour l'objet concerne
55
-		if ($l = _request('changer_lang')) {
56
-			$c['lang'] = $l;
57
-		}
58
-	}
59
-	foreach ($exclude_list as $champ) {
60
-		unset($c[$champ]);
61
-	}
62
-
63
-	return $c;
42
+    $c = $set;
43
+    if (!$c) {
44
+        $c = [];
45
+        foreach ($include_list as $champ) {
46
+            // on ne collecte que les champs reellement envoyes par defaut.
47
+            // le cas d'un envoi de valeur NULL peut du coup poser probleme.
48
+            $val = _request($champ);
49
+            if ($tous or $val !== null) {
50
+                $c[$champ] = $val;
51
+            }
52
+        }
53
+        // on ajoute toujours la lang en saisie possible
54
+        // meme si pas prevu au depart pour l'objet concerne
55
+        if ($l = _request('changer_lang')) {
56
+            $c['lang'] = $l;
57
+        }
58
+    }
59
+    foreach ($exclude_list as $champ) {
60
+        unset($c[$champ]);
61
+    }
62
+
63
+    return $c;
64 64
 }
65 65
 
66 66
 /**
@@ -97,240 +97,240 @@  discard block
 block discarded – undo
97 97
  *     - chaîne : Texte d'un message d'erreur
98 98
  */
99 99
 function objet_modifier_champs($objet, $id_objet, $options, $c = null, $serveur = '') {
100
-	if (!$id_objet = intval($id_objet)) {
101
-		spip_log('Erreur $id_objet non defini', 'warn');
102
-
103
-		return _T('erreur_technique_enregistrement_impossible');
104
-	}
105
-
106
-	include_spip('inc/filtres');
107
-
108
-	$table_objet = table_objet($objet, $serveur);
109
-	$spip_table_objet = table_objet_sql($objet, $serveur);
110
-	$id_table_objet = id_table_objet($objet, $serveur);
111
-	$trouver_table = charger_fonction('trouver_table', 'base');
112
-	$desc = $trouver_table($spip_table_objet, $serveur);
113
-
114
-	// Appels incomplets (sans $c)
115
-	if (!is_array($c)) {
116
-		spip_log('erreur appel objet_modifier_champs(' . $objet . '), manque $c');
117
-
118
-		return _T('erreur_technique_enregistrement_impossible');
119
-	}
120
-
121
-	// Securite : certaines variables ne sont jamais acceptees ici
122
-	// car elles ne relevent pas de autoriser(xxx, modifier) ;
123
-	// il faut passer par instituer_XX()
124
-	// TODO: faut-il passer ces variables interdites
125
-	// dans un fichier de description separe ?
126
-	unset($c['statut']);
127
-	unset($c['id_parent']);
128
-	unset($c['id_rubrique']);
129
-	unset($c['id_secteur']);
130
-
131
-	// Gerer les champs non vides
132
-	if (isset($options['nonvide']) and is_array($options['nonvide'])) {
133
-		foreach ($options['nonvide'] as $champ => $sinon) {
134
-			if (isset($c[$champ]) and $c[$champ] === '') {
135
-				$c[$champ] = $sinon;
136
-			}
137
-		}
138
-	}
139
-
140
-	// N'accepter que les champs qui existent dans la table
141
-	$champs = array_intersect_key($c, $desc['field']);
142
-	// et dont la valeur n'est pas null
143
-	$champs = array_filter($champs, static function($var){return $var !== null;} );
144
-	// TODO: ici aussi on peut valider les contenus
145
-	// en fonction du type
146
-
147
-	// Nettoyer les valeurs
148
-	$champs = array_map('corriger_caracteres', $champs);
149
-
150
-	// On récupère l'état avant toute modification
151
-	$row = sql_fetsel('*', $spip_table_objet, $id_table_objet . '=' . $id_objet);
152
-
153
-	// Envoyer aux plugins
154
-	$champs = pipeline(
155
-		'pre_edition',
156
-		[
157
-			'args' => [
158
-				'table' => $spip_table_objet, // compatibilite
159
-				'table_objet' => $table_objet,
160
-				'spip_table_objet' => $spip_table_objet,
161
-				'desc' => $desc,
162
-				'type' => $objet,
163
-				'id_objet' => $id_objet,
164
-				'data' => $options['data'] ?? null,
165
-				'champs' => $options['champs'] ?? [], // [doc] c'est quoi ?
166
-				'champs_anciens' => $row, // état du contenu avant modif
167
-				'serveur' => $serveur,
168
-				'action' => $options['action'] ?? 'modifier'
169
-			],
170
-			'data' => $champs
171
-		]
172
-	);
173
-
174
-	if (!$champs) {
175
-		return false;
176
-	}
177
-
178
-
179
-	// marquer le fait que l'objet est travaille par toto a telle date
180
-	include_spip('inc/config');
181
-	if (lire_config('articles_modif', 'non') !== 'non') {
182
-		include_spip('inc/drapeau_edition');
183
-		signale_edition($id_objet, $GLOBALS['visiteur_session'], $objet);
184
-	}
185
-
186
-	// Verifier si les mises a jour sont pertinentes, datees, en conflit etc
187
-	include_spip('inc/editer');
188
-	if (!isset($options['data']) or is_null($options['data'])) {
189
-		$options['data'] = &$_POST;
190
-	}
191
-	$conflits = controler_md5($champs, $options['data'], $objet, $id_objet, $serveur);
192
-	// cas hypothetique : normalement inc/editer verifie en amont le conflit edition
193
-	// et gere l'interface
194
-	// ici on ne renvoie donc qu'un messsage d'erreur, au cas ou on y arrive quand meme
195
-	if ($conflits) {
196
-		return _T('titre_conflit_edition');
197
-	}
198
-
199
-	if ($champs) {
200
-		// cas particulier de la langue : passer par instituer_langue_objet
201
-		if (isset($champs['lang'])) {
202
-			if ($changer_lang = $champs['lang']) {
203
-				$id_rubrique = 0;
204
-				if (isset($desc['field']['id_rubrique'])) {
205
-					$parent = ($objet == 'rubrique') ? 'id_parent' : 'id_rubrique';
206
-					$id_rubrique = sql_getfetsel($parent, $spip_table_objet, "$id_table_objet=" . intval($id_objet));
207
-				}
208
-				$instituer_langue_objet = charger_fonction('instituer_langue_objet', 'action');
209
-				$champs['lang'] = $instituer_langue_objet($objet, $id_objet, $id_rubrique, $changer_lang, $serveur);
210
-			}
211
-			// on laisse 'lang' dans $champs,
212
-			// ca permet de passer dans le pipeline post_edition et de journaliser
213
-			// et ca ne gene pas qu'on refasse un sql_updateq dessus apres l'avoir
214
-			// deja pris en compte
215
-		}
216
-
217
-		// la modif peut avoir lieu
218
-
219
-		// faut-il ajouter date_modif ?
220
-		if (
221
-			!empty($options['date_modif'])
222
-			and !isset($champs[$options['date_modif']])
223
-		) {
224
-			$champs[$options['date_modif']] = date('Y-m-d H:i:s');
225
-		}
226
-
227
-		// allez on commit la modif
228
-		sql_updateq($spip_table_objet, $champs, "$id_table_objet=" . intval($id_objet), [], $serveur);
229
-
230
-		// on verifie si elle est bien passee
231
-		$moof = sql_fetsel(
232
-			array_keys($champs),
233
-			$spip_table_objet,
234
-			"$id_table_objet=" . intval($id_objet),
235
-			[],
236
-			[],
237
-			'',
238
-			[],
239
-			$serveur
240
-		);
241
-		// si difference entre les champs, reperer les champs mal enregistres
242
-		if ($moof != $champs) {
243
-			$liste = [];
244
-			foreach ($moof as $k => $v) {
245
-				if (
246
-					$v !== $champs[$k]
247
-					// ne pas alerter si le champ est numerique est que les valeurs sont equivalentes
248
-					and (!is_numeric($v) or intval($v) !== intval($champs[$k]))
249
-					// ne pas alerter si le champ est date, qu'on a envoye une valeur vide et qu'on recupere une date nulle
250
-					and (strlen($champs[$k]) or !in_array($v, ['0000-00-00 00:00:00', '0000-00-00']))
251
-				) {
252
-					$liste[] = $k;
253
-					$conflits[$k]['post'] = $champs[$k];
254
-					$conflits[$k]['save'] = $v;
255
-
256
-					// cas specifique MySQL+emoji : si l'un est la
257
-					// conversion utf8_noplanes de l'autre alors c'est OK
258
-					if (defined('_MYSQL_NOPLANES') && _MYSQL_NOPLANES) {
259
-						include_spip('inc/charsets');
260
-						if ($v == utf8_noplanes($champs[$k])) {
261
-							array_pop($liste);
262
-						}
263
-					}
264
-				}
265
-			}
266
-			// si un champ n'a pas ete correctement enregistre, loger et retourner une erreur
267
-			// c'est un cas exceptionnel
268
-			if (count($liste)) {
269
-				spip_log(
270
-					"Erreur enregistrement en base $objet/$id_objet champs :" . var_export($conflits, true),
271
-					'modifier.' . _LOG_CRITIQUE
272
-				);
273
-
274
-				return _T(
275
-					'erreur_technique_enregistrement_champs',
276
-					['champs' => "<i>'" . implode("'</i>,<i>'", $liste) . "'</i>"]
277
-				);
278
-			}
279
-		}
280
-
281
-		// Invalider les caches
282
-		if (isset($options['invalideur']) and $options['invalideur']) {
283
-			include_spip('inc/invalideur');
284
-			if (is_array($options['invalideur'])) {
285
-				array_map('suivre_invalideur', $options['invalideur']);
286
-			} else {
287
-				suivre_invalideur($options['invalideur']);
288
-			}
289
-		}
290
-
291
-		// Notifications, gestion des revisions...
292
-		// en standard, appelle |nouvelle_revision ci-dessous
293
-		pipeline(
294
-			'post_edition',
295
-			[
296
-				'args' => [
297
-					'table' => $spip_table_objet,
298
-					'table_objet' => $table_objet,
299
-					'spip_table_objet' => $spip_table_objet,
300
-					'desc' => $desc,
301
-					'type' => $objet,
302
-					'id_objet' => $id_objet,
303
-					'champs' => $options['champs'] ?? [], // [doc] kesako ?
304
-					'champs_anciens' => $row, // état du contenu avant modif
305
-					'serveur' => $serveur,
306
-					'action' => $options['action'] ?? 'modifier'
307
-				],
308
-				'data' => $champs
309
-			]
310
-		);
311
-	}
312
-
313
-	// journaliser l'affaire
314
-	// message a affiner :-)
315
-	include_spip('inc/filtres_mini');
316
-	$qui = '';
317
-	if (!empty($GLOBALS['visiteur_session']['id_auteur'])) {
318
-		$qui .= ' #id_auteur:' . $GLOBALS['visiteur_session']['id_auteur'] . '#';
319
-	}
320
-	if (!empty($GLOBALS['visiteur_session']['nom'])) {
321
-		$qui .= ' #nom:' . $GLOBALS['visiteur_session']['nom'] . '#';
322
-	}
323
-	if ($qui == '') {
324
-		$qui = '#ip:' . $GLOBALS['ip'] . '#';
325
-	}
326
-	journal(_L($qui . ' a édité ' . $objet . ' ' . $id_objet . ' (' . join(
327
-		'+',
328
-		array_diff(array_keys($champs), ['date_modif'])
329
-	) . ')'), [
330
-		'faire' => 'modifier',
331
-		'quoi' => $objet,
332
-		'id' => $id_objet
333
-	]);
334
-
335
-	return '';
100
+    if (!$id_objet = intval($id_objet)) {
101
+        spip_log('Erreur $id_objet non defini', 'warn');
102
+
103
+        return _T('erreur_technique_enregistrement_impossible');
104
+    }
105
+
106
+    include_spip('inc/filtres');
107
+
108
+    $table_objet = table_objet($objet, $serveur);
109
+    $spip_table_objet = table_objet_sql($objet, $serveur);
110
+    $id_table_objet = id_table_objet($objet, $serveur);
111
+    $trouver_table = charger_fonction('trouver_table', 'base');
112
+    $desc = $trouver_table($spip_table_objet, $serveur);
113
+
114
+    // Appels incomplets (sans $c)
115
+    if (!is_array($c)) {
116
+        spip_log('erreur appel objet_modifier_champs(' . $objet . '), manque $c');
117
+
118
+        return _T('erreur_technique_enregistrement_impossible');
119
+    }
120
+
121
+    // Securite : certaines variables ne sont jamais acceptees ici
122
+    // car elles ne relevent pas de autoriser(xxx, modifier) ;
123
+    // il faut passer par instituer_XX()
124
+    // TODO: faut-il passer ces variables interdites
125
+    // dans un fichier de description separe ?
126
+    unset($c['statut']);
127
+    unset($c['id_parent']);
128
+    unset($c['id_rubrique']);
129
+    unset($c['id_secteur']);
130
+
131
+    // Gerer les champs non vides
132
+    if (isset($options['nonvide']) and is_array($options['nonvide'])) {
133
+        foreach ($options['nonvide'] as $champ => $sinon) {
134
+            if (isset($c[$champ]) and $c[$champ] === '') {
135
+                $c[$champ] = $sinon;
136
+            }
137
+        }
138
+    }
139
+
140
+    // N'accepter que les champs qui existent dans la table
141
+    $champs = array_intersect_key($c, $desc['field']);
142
+    // et dont la valeur n'est pas null
143
+    $champs = array_filter($champs, static function($var){return $var !== null;} );
144
+    // TODO: ici aussi on peut valider les contenus
145
+    // en fonction du type
146
+
147
+    // Nettoyer les valeurs
148
+    $champs = array_map('corriger_caracteres', $champs);
149
+
150
+    // On récupère l'état avant toute modification
151
+    $row = sql_fetsel('*', $spip_table_objet, $id_table_objet . '=' . $id_objet);
152
+
153
+    // Envoyer aux plugins
154
+    $champs = pipeline(
155
+        'pre_edition',
156
+        [
157
+            'args' => [
158
+                'table' => $spip_table_objet, // compatibilite
159
+                'table_objet' => $table_objet,
160
+                'spip_table_objet' => $spip_table_objet,
161
+                'desc' => $desc,
162
+                'type' => $objet,
163
+                'id_objet' => $id_objet,
164
+                'data' => $options['data'] ?? null,
165
+                'champs' => $options['champs'] ?? [], // [doc] c'est quoi ?
166
+                'champs_anciens' => $row, // état du contenu avant modif
167
+                'serveur' => $serveur,
168
+                'action' => $options['action'] ?? 'modifier'
169
+            ],
170
+            'data' => $champs
171
+        ]
172
+    );
173
+
174
+    if (!$champs) {
175
+        return false;
176
+    }
177
+
178
+
179
+    // marquer le fait que l'objet est travaille par toto a telle date
180
+    include_spip('inc/config');
181
+    if (lire_config('articles_modif', 'non') !== 'non') {
182
+        include_spip('inc/drapeau_edition');
183
+        signale_edition($id_objet, $GLOBALS['visiteur_session'], $objet);
184
+    }
185
+
186
+    // Verifier si les mises a jour sont pertinentes, datees, en conflit etc
187
+    include_spip('inc/editer');
188
+    if (!isset($options['data']) or is_null($options['data'])) {
189
+        $options['data'] = &$_POST;
190
+    }
191
+    $conflits = controler_md5($champs, $options['data'], $objet, $id_objet, $serveur);
192
+    // cas hypothetique : normalement inc/editer verifie en amont le conflit edition
193
+    // et gere l'interface
194
+    // ici on ne renvoie donc qu'un messsage d'erreur, au cas ou on y arrive quand meme
195
+    if ($conflits) {
196
+        return _T('titre_conflit_edition');
197
+    }
198
+
199
+    if ($champs) {
200
+        // cas particulier de la langue : passer par instituer_langue_objet
201
+        if (isset($champs['lang'])) {
202
+            if ($changer_lang = $champs['lang']) {
203
+                $id_rubrique = 0;
204
+                if (isset($desc['field']['id_rubrique'])) {
205
+                    $parent = ($objet == 'rubrique') ? 'id_parent' : 'id_rubrique';
206
+                    $id_rubrique = sql_getfetsel($parent, $spip_table_objet, "$id_table_objet=" . intval($id_objet));
207
+                }
208
+                $instituer_langue_objet = charger_fonction('instituer_langue_objet', 'action');
209
+                $champs['lang'] = $instituer_langue_objet($objet, $id_objet, $id_rubrique, $changer_lang, $serveur);
210
+            }
211
+            // on laisse 'lang' dans $champs,
212
+            // ca permet de passer dans le pipeline post_edition et de journaliser
213
+            // et ca ne gene pas qu'on refasse un sql_updateq dessus apres l'avoir
214
+            // deja pris en compte
215
+        }
216
+
217
+        // la modif peut avoir lieu
218
+
219
+        // faut-il ajouter date_modif ?
220
+        if (
221
+            !empty($options['date_modif'])
222
+            and !isset($champs[$options['date_modif']])
223
+        ) {
224
+            $champs[$options['date_modif']] = date('Y-m-d H:i:s');
225
+        }
226
+
227
+        // allez on commit la modif
228
+        sql_updateq($spip_table_objet, $champs, "$id_table_objet=" . intval($id_objet), [], $serveur);
229
+
230
+        // on verifie si elle est bien passee
231
+        $moof = sql_fetsel(
232
+            array_keys($champs),
233
+            $spip_table_objet,
234
+            "$id_table_objet=" . intval($id_objet),
235
+            [],
236
+            [],
237
+            '',
238
+            [],
239
+            $serveur
240
+        );
241
+        // si difference entre les champs, reperer les champs mal enregistres
242
+        if ($moof != $champs) {
243
+            $liste = [];
244
+            foreach ($moof as $k => $v) {
245
+                if (
246
+                    $v !== $champs[$k]
247
+                    // ne pas alerter si le champ est numerique est que les valeurs sont equivalentes
248
+                    and (!is_numeric($v) or intval($v) !== intval($champs[$k]))
249
+                    // ne pas alerter si le champ est date, qu'on a envoye une valeur vide et qu'on recupere une date nulle
250
+                    and (strlen($champs[$k]) or !in_array($v, ['0000-00-00 00:00:00', '0000-00-00']))
251
+                ) {
252
+                    $liste[] = $k;
253
+                    $conflits[$k]['post'] = $champs[$k];
254
+                    $conflits[$k]['save'] = $v;
255
+
256
+                    // cas specifique MySQL+emoji : si l'un est la
257
+                    // conversion utf8_noplanes de l'autre alors c'est OK
258
+                    if (defined('_MYSQL_NOPLANES') && _MYSQL_NOPLANES) {
259
+                        include_spip('inc/charsets');
260
+                        if ($v == utf8_noplanes($champs[$k])) {
261
+                            array_pop($liste);
262
+                        }
263
+                    }
264
+                }
265
+            }
266
+            // si un champ n'a pas ete correctement enregistre, loger et retourner une erreur
267
+            // c'est un cas exceptionnel
268
+            if (count($liste)) {
269
+                spip_log(
270
+                    "Erreur enregistrement en base $objet/$id_objet champs :" . var_export($conflits, true),
271
+                    'modifier.' . _LOG_CRITIQUE
272
+                );
273
+
274
+                return _T(
275
+                    'erreur_technique_enregistrement_champs',
276
+                    ['champs' => "<i>'" . implode("'</i>,<i>'", $liste) . "'</i>"]
277
+                );
278
+            }
279
+        }
280
+
281
+        // Invalider les caches
282
+        if (isset($options['invalideur']) and $options['invalideur']) {
283
+            include_spip('inc/invalideur');
284
+            if (is_array($options['invalideur'])) {
285
+                array_map('suivre_invalideur', $options['invalideur']);
286
+            } else {
287
+                suivre_invalideur($options['invalideur']);
288
+            }
289
+        }
290
+
291
+        // Notifications, gestion des revisions...
292
+        // en standard, appelle |nouvelle_revision ci-dessous
293
+        pipeline(
294
+            'post_edition',
295
+            [
296
+                'args' => [
297
+                    'table' => $spip_table_objet,
298
+                    'table_objet' => $table_objet,
299
+                    'spip_table_objet' => $spip_table_objet,
300
+                    'desc' => $desc,
301
+                    'type' => $objet,
302
+                    'id_objet' => $id_objet,
303
+                    'champs' => $options['champs'] ?? [], // [doc] kesako ?
304
+                    'champs_anciens' => $row, // état du contenu avant modif
305
+                    'serveur' => $serveur,
306
+                    'action' => $options['action'] ?? 'modifier'
307
+                ],
308
+                'data' => $champs
309
+            ]
310
+        );
311
+    }
312
+
313
+    // journaliser l'affaire
314
+    // message a affiner :-)
315
+    include_spip('inc/filtres_mini');
316
+    $qui = '';
317
+    if (!empty($GLOBALS['visiteur_session']['id_auteur'])) {
318
+        $qui .= ' #id_auteur:' . $GLOBALS['visiteur_session']['id_auteur'] . '#';
319
+    }
320
+    if (!empty($GLOBALS['visiteur_session']['nom'])) {
321
+        $qui .= ' #nom:' . $GLOBALS['visiteur_session']['nom'] . '#';
322
+    }
323
+    if ($qui == '') {
324
+        $qui = '#ip:' . $GLOBALS['ip'] . '#';
325
+    }
326
+    journal(_L($qui . ' a édité ' . $objet . ' ' . $id_objet . ' (' . join(
327
+        '+',
328
+        array_diff(array_keys($champs), ['date_modif'])
329
+    ) . ')'), [
330
+        'faire' => 'modifier',
331
+        'quoi' => $objet,
332
+        'id' => $id_objet
333
+    ]);
334
+
335
+    return '';
336 336
 }
Please login to merge, or discard this patch.
ecrire/lang/spip_it.php 1 patch
Indentation   +669 added lines, -669 removed lines patch added patch discarded remove patch
@@ -4,248 +4,248 @@  discard block
 block discarded – undo
4 4
 // ** ne pas modifier le fichier **
5 5
 
6 6
 if (!defined('_ECRIRE_INC_VERSION')) {
7
-	return;
7
+    return;
8 8
 }
9 9
 
10 10
 $GLOBALS[$GLOBALS['idx_lang']] = array(
11 11
 
12
-	// A
13
-	'access_interface_graphique' => 'Ritorna all’interfaccia grafica completa',
14
-	'access_mode_texte' => 'Visualizza l’interfaccia testuale semplificata',
15
-	'admin_debug' => 'debug',
16
-	'admin_modifier_article' => 'Modifica l’articolo',
17
-	'admin_modifier_auteur' => 'Modifica l’autore',
18
-	'admin_modifier_breve' => 'Modifica la breve',
19
-	'admin_modifier_mot' => 'Modifica la parola chiave',
20
-	'admin_modifier_rubrique' => 'Modifica la rubrica',
21
-	'admin_recalculer' => 'Rigenera la pagina',
22
-	'afficher_calendrier' => 'Mostra il calendario',
23
-	'afficher_trad' => 'visualizzare le traduzioni',
24
-	'alerte_maj_impossible' => '<b>Attenzione!</b> L’aggiornamento del database SQL alla versione @version@ è impossibile, forse a causa di un problema con i diritti di modifica nel database. Contattare il proprio fornitore di hosting.',
25
-	'alerte_modif_info_concourante' => 'ATTENZIONE: Questa informazione è stata modificata altrove. Il valore attuale è:',
26
-	'analyse_xml' => 'Analisi XML',
27
-	'annuler' => 'Annulla',
28
-	'antispam_champ_vide' => 'Si prega di lasciare vuoto questo campo:',
29
-	'articles_recents' => 'Articoli più recenti',
30
-	'attention_champ_mini_nb_caractères' => 'Attenzione! Minimo @nb@ caratteri',
31
-	'avis_1_erreur_saisie' => 'C’è un errore nell’input, verificare le informazioni.',
32
-	'avis_archive_incorrect' => 'il file archivio non è un file SPIP',
33
-	'avis_archive_invalide' => 'il file archivio non è valido',
34
-	'avis_attention' => 'ATTENZIONE!',
35
-	'avis_champ_incorrect_type_objet' => 'Nome di campo errato @name@ per oggetto di tipo @type@',
36
-	'avis_colonne_inexistante' => 'La colonna @col@ non esiste',
37
-	'avis_erreur' => 'Errore: vedi sopra',
38
-	'avis_erreur_connexion' => 'Errore di connessione',
39
-	'avis_erreur_cookie' => 'problema di cookie',
40
-	'avis_erreur_fonction_contexte' => 'Errore di programmazione. Questa funzione non deve essere chiamata in questo contesto.',
41
-	'avis_erreur_mysql' => 'Errore SQL ',
42
-	'avis_erreur_sauvegarde' => 'Errore nel salvataggio (@type@ @id_objet@)! ',
43
-	'avis_erreur_visiteur' => 'Problema di accesso all’area riservata',
44
-	'avis_nb_erreurs_saisie' => 'Ci sono @nb@ errori nell’input, verificare le informazioni.',
12
+    // A
13
+    'access_interface_graphique' => 'Ritorna all’interfaccia grafica completa',
14
+    'access_mode_texte' => 'Visualizza l’interfaccia testuale semplificata',
15
+    'admin_debug' => 'debug',
16
+    'admin_modifier_article' => 'Modifica l’articolo',
17
+    'admin_modifier_auteur' => 'Modifica l’autore',
18
+    'admin_modifier_breve' => 'Modifica la breve',
19
+    'admin_modifier_mot' => 'Modifica la parola chiave',
20
+    'admin_modifier_rubrique' => 'Modifica la rubrica',
21
+    'admin_recalculer' => 'Rigenera la pagina',
22
+    'afficher_calendrier' => 'Mostra il calendario',
23
+    'afficher_trad' => 'visualizzare le traduzioni',
24
+    'alerte_maj_impossible' => '<b>Attenzione!</b> L’aggiornamento del database SQL alla versione @version@ è impossibile, forse a causa di un problema con i diritti di modifica nel database. Contattare il proprio fornitore di hosting.',
25
+    'alerte_modif_info_concourante' => 'ATTENZIONE: Questa informazione è stata modificata altrove. Il valore attuale è:',
26
+    'analyse_xml' => 'Analisi XML',
27
+    'annuler' => 'Annulla',
28
+    'antispam_champ_vide' => 'Si prega di lasciare vuoto questo campo:',
29
+    'articles_recents' => 'Articoli più recenti',
30
+    'attention_champ_mini_nb_caractères' => 'Attenzione! Minimo @nb@ caratteri',
31
+    'avis_1_erreur_saisie' => 'C’è un errore nell’input, verificare le informazioni.',
32
+    'avis_archive_incorrect' => 'il file archivio non è un file SPIP',
33
+    'avis_archive_invalide' => 'il file archivio non è valido',
34
+    'avis_attention' => 'ATTENZIONE!',
35
+    'avis_champ_incorrect_type_objet' => 'Nome di campo errato @name@ per oggetto di tipo @type@',
36
+    'avis_colonne_inexistante' => 'La colonna @col@ non esiste',
37
+    'avis_erreur' => 'Errore: vedi sopra',
38
+    'avis_erreur_connexion' => 'Errore di connessione',
39
+    'avis_erreur_cookie' => 'problema di cookie',
40
+    'avis_erreur_fonction_contexte' => 'Errore di programmazione. Questa funzione non deve essere chiamata in questo contesto.',
41
+    'avis_erreur_mysql' => 'Errore SQL ',
42
+    'avis_erreur_sauvegarde' => 'Errore nel salvataggio (@type@ @id_objet@)! ',
43
+    'avis_erreur_visiteur' => 'Problema di accesso all’area riservata',
44
+    'avis_nb_erreurs_saisie' => 'Ci sono @nb@ errori nell’input, verificare le informazioni.',
45 45
 
46
-	// B
47
-	'barre_a_accent_grave' => 'Inserire una A maiscola con accento grave',
48
-	'barre_aide' => 'Utilizzare le scorciatoie tipografiche di SPIP per migliorare l\\’impaginazione del testo',
49
-	'barre_e_accent_aigu' => 'Inserire una E maiscola con accento acuto',
50
-	'barre_eo' => 'Inserire una E nell’O',
51
-	'barre_eo_maj' => 'Inserire una E nell’O maiuscola',
52
-	'barre_euro' => 'Inserire il simbolo €',
53
-	'barre_gras' => 'Formattare in {{grassetto}}',
54
-	'barre_guillemets' => 'Porre il testo fra « virgolette basse francesi »',
55
-	'barre_guillemets_simples' => 'Porre il testo fra „virgolette“',
56
-	'barre_intertitre' => 'Trasformare in {{{titolo di paragrafo}}}',
57
-	'barre_italic' => 'Formattare in {corsivo}',
58
-	'barre_lien' => 'Trasformare in un [link ipertestuale->http://...]',
59
-	'barre_lien_input' => 'Indicare l’indirizzo del link (è possibile indicare l’indirizzo Web come http://www.ilmiosito.com o semplicemente indicare il numero di un singolo articolo).',
60
-	'barre_note' => 'Trasformare in [[Nota a fondo pagina]]',
61
-	'barre_paragraphe' => 'Crea un paragrafo',
62
-	'barre_quote' => '<quote>Citare un messaggio</quote>',
63
-	'bouton_changer' => 'Cambia',
64
-	'bouton_chercher' => 'Cerca',
65
-	'bouton_choisir' => 'Scegli',
66
-	'bouton_deplacer' => 'Sposta',
67
-	'bouton_download' => 'Download',
68
-	'bouton_enregistrer' => 'Salva',
69
-	'bouton_radio_desactiver_messagerie_interne' => 'Disattiva la messaggistica interna',
70
-	'bouton_radio_envoi_annonces' => 'Invia gli annunci editoriali',
71
-	'bouton_radio_non_envoi_annonces' => 'Non inviare annunci',
72
-	'bouton_radio_non_envoi_liste_nouveautes' => 'Non inviare l’elenco delle novità',
73
-	'bouton_recharger_page' => 'ricaricare questa pagina',
74
-	'bouton_telecharger' => 'Upload',
75
-	'bouton_upload' => 'Upload',
76
-	'bouton_valider' => 'Invia',
46
+    // B
47
+    'barre_a_accent_grave' => 'Inserire una A maiscola con accento grave',
48
+    'barre_aide' => 'Utilizzare le scorciatoie tipografiche di SPIP per migliorare l\\’impaginazione del testo',
49
+    'barre_e_accent_aigu' => 'Inserire una E maiscola con accento acuto',
50
+    'barre_eo' => 'Inserire una E nell’O',
51
+    'barre_eo_maj' => 'Inserire una E nell’O maiuscola',
52
+    'barre_euro' => 'Inserire il simbolo €',
53
+    'barre_gras' => 'Formattare in {{grassetto}}',
54
+    'barre_guillemets' => 'Porre il testo fra « virgolette basse francesi »',
55
+    'barre_guillemets_simples' => 'Porre il testo fra „virgolette“',
56
+    'barre_intertitre' => 'Trasformare in {{{titolo di paragrafo}}}',
57
+    'barre_italic' => 'Formattare in {corsivo}',
58
+    'barre_lien' => 'Trasformare in un [link ipertestuale->http://...]',
59
+    'barre_lien_input' => 'Indicare l’indirizzo del link (è possibile indicare l’indirizzo Web come http://www.ilmiosito.com o semplicemente indicare il numero di un singolo articolo).',
60
+    'barre_note' => 'Trasformare in [[Nota a fondo pagina]]',
61
+    'barre_paragraphe' => 'Crea un paragrafo',
62
+    'barre_quote' => '<quote>Citare un messaggio</quote>',
63
+    'bouton_changer' => 'Cambia',
64
+    'bouton_chercher' => 'Cerca',
65
+    'bouton_choisir' => 'Scegli',
66
+    'bouton_deplacer' => 'Sposta',
67
+    'bouton_download' => 'Download',
68
+    'bouton_enregistrer' => 'Salva',
69
+    'bouton_radio_desactiver_messagerie_interne' => 'Disattiva la messaggistica interna',
70
+    'bouton_radio_envoi_annonces' => 'Invia gli annunci editoriali',
71
+    'bouton_radio_non_envoi_annonces' => 'Non inviare annunci',
72
+    'bouton_radio_non_envoi_liste_nouveautes' => 'Non inviare l’elenco delle novità',
73
+    'bouton_recharger_page' => 'ricaricare questa pagina',
74
+    'bouton_telecharger' => 'Upload',
75
+    'bouton_upload' => 'Upload',
76
+    'bouton_valider' => 'Invia',
77 77
 
78
-	// C
79
-	'cal_apresmidi' => 'pomeriggio',
80
-	'cal_jour_entier' => 'giorno intero',
81
-	'cal_matin' => 'mattina',
82
-	'cal_par_jour' => 'calendario giornaliero',
83
-	'cal_par_mois' => 'calendario mensile',
84
-	'cal_par_semaine' => 'calendario settimanale',
85
-	'choix_couleur_interface' => 'colore',
86
-	'choix_interface' => 'scelta dell’interfaccia',
87
-	'colonne' => 'Colonna',
88
-	'confirm_changer_statut' => 'Attenzione, è stato chiesto di modificare lo status di questo elemento. Continuare?',
89
-	'correcte' => 'corretto',
78
+    // C
79
+    'cal_apresmidi' => 'pomeriggio',
80
+    'cal_jour_entier' => 'giorno intero',
81
+    'cal_matin' => 'mattina',
82
+    'cal_par_jour' => 'calendario giornaliero',
83
+    'cal_par_mois' => 'calendario mensile',
84
+    'cal_par_semaine' => 'calendario settimanale',
85
+    'choix_couleur_interface' => 'colore',
86
+    'choix_interface' => 'scelta dell’interfaccia',
87
+    'colonne' => 'Colonna',
88
+    'confirm_changer_statut' => 'Attenzione, è stato chiesto di modificare lo status di questo elemento. Continuare?',
89
+    'correcte' => 'corretto',
90 90
 
91
-	// D
92
-	'date_aujourdhui' => 'oggi',
93
-	'date_avant_jc' => 'a.C.',
94
-	'date_dans' => 'tra @delai@',
95
-	'date_de_mois_1' => '@j@ gennaio',
96
-	'date_de_mois_10' => '@j@ ottobre',
97
-	'date_de_mois_11' => '@j@ novembre',
98
-	'date_de_mois_12' => '@j@ dicembre',
99
-	'date_de_mois_2' => '@j@ febbraio',
100
-	'date_de_mois_3' => '@j@ marzo',
101
-	'date_de_mois_4' => '@j@ aprile',
102
-	'date_de_mois_5' => '@j@ maggio',
103
-	'date_de_mois_6' => '@j@ giugno',
104
-	'date_de_mois_7' => '@j@ luglio',
105
-	'date_de_mois_8' => '@j@ agosto',
106
-	'date_de_mois_9' => '@j@ settembre',
107
-	'date_demain' => 'domani',
108
-	'date_fmt_heures_minutes' => '@h@:@m@',
109
-	'date_fmt_heures_minutes_court' => '@h@h@m@',
110
-	'date_fmt_jour' => '@nomjour@ @jour@',
111
-	'date_fmt_jour_heure' => '@jour@ ore @heure@',
112
-	'date_fmt_jour_heure_debut_fin' => 'Il @jour@ dalle @heure_debut@ alle @heure_fin@',
113
-	'date_fmt_jour_heure_debut_fin_abbr' => 'Il @dtstart@@jour@ dalle @heure_debut@@dtabbr@ alle @dtstart@@heure_fin@@dtend@',
114
-	'date_fmt_jour_mois' => '@jourmois@',
115
-	'date_fmt_jour_mois_annee' => '@jourmois@ @annee@',
116
-	'date_fmt_mois_annee' => '@nommois@ @annee@',
117
-	'date_fmt_nomjour' => '@nomjour@ @date@',
118
-	'date_fmt_nomjour_date' => 'il @nomjour@ @date@',
119
-	'date_fmt_periode' => 'Dal @date_debut@ al @date_fin@',
120
-	'date_fmt_periode_abbr' => 'Dal @dtart@@date_debut@@dtabbr@ al @dtend@@date_fin@@dtabbr@',
121
-	'date_fmt_periode_from' => 'Dal',
122
-	'date_fmt_periode_to' => 'a',
123
-	'date_fmt_saison_annee' => '@saison@ @annee@',
124
-	'date_heures' => 'ore',
125
-	'date_hier' => 'ieri',
126
-	'date_il_y_a' => '@delai@ fa',
127
-	'date_jnum1' => '1',
128
-	'date_jnum10' => '10',
129
-	'date_jnum11' => '11',
130
-	'date_jnum12' => '12',
131
-	'date_jnum13' => '13',
132
-	'date_jnum14' => '14',
133
-	'date_jnum15' => '15',
134
-	'date_jnum16' => '16',
135
-	'date_jnum17' => '17',
136
-	'date_jnum18' => '18',
137
-	'date_jnum19' => '19',
138
-	'date_jnum2' => '2',
139
-	'date_jnum20' => '20',
140
-	'date_jnum21' => '21',
141
-	'date_jnum22' => '22',
142
-	'date_jnum23' => '23',
143
-	'date_jnum24' => '24',
144
-	'date_jnum25' => '25',
145
-	'date_jnum26' => '26',
146
-	'date_jnum27' => '27',
147
-	'date_jnum28' => '28',
148
-	'date_jnum29' => '29',
149
-	'date_jnum3' => '3',
150
-	'date_jnum30' => '30',
151
-	'date_jnum31' => '31',
152
-	'date_jnum4' => '4',
153
-	'date_jnum5' => '5',
154
-	'date_jnum6' => '6',
155
-	'date_jnum7' => '7',
156
-	'date_jnum8' => '8',
157
-	'date_jnum9' => '9',
158
-	'date_jour_1' => 'domenica',
159
-	'date_jour_1_abbr' => 'dom',
160
-	'date_jour_1_initiale' => 'd',
161
-	'date_jour_2' => 'lunedì',
162
-	'date_jour_2_abbr' => 'lun',
163
-	'date_jour_2_initiale' => 'l',
164
-	'date_jour_3' => 'martedì',
165
-	'date_jour_3_abbr' => 'mar',
166
-	'date_jour_3_initiale' => 'm',
167
-	'date_jour_4' => 'mercoledì',
168
-	'date_jour_4_abbr' => 'mer',
169
-	'date_jour_4_initiale' => 'm',
170
-	'date_jour_5' => 'giovedì',
171
-	'date_jour_5_abbr' => 'giov',
172
-	'date_jour_5_initiale' => 'g',
173
-	'date_jour_6' => 'venerdì',
174
-	'date_jour_6_abbr' => 'ven',
175
-	'date_jour_6_initiale' => 'v',
176
-	'date_jour_7' => 'sabato',
177
-	'date_jour_7_abbr' => 'sab',
178
-	'date_jour_7_initiale' => 's',
179
-	'date_jours' => 'giorni',
180
-	'date_minutes' => 'minuti',
181
-	'date_mois' => 'mesi',
182
-	'date_mois_1' => 'Gennaio',
183
-	'date_mois_10' => 'Ottobre',
184
-	'date_mois_10_abbr' => 'ott',
185
-	'date_mois_11' => 'Novembre',
186
-	'date_mois_11_abbr' => 'nov',
187
-	'date_mois_12' => 'Dicembre',
188
-	'date_mois_12_abbr' => 'dic',
189
-	'date_mois_1_abbr' => 'gen',
190
-	'date_mois_2' => 'Febbraio',
191
-	'date_mois_2_abbr' => 'feb',
192
-	'date_mois_3' => 'Marzo',
193
-	'date_mois_3_abbr' => 'mar',
194
-	'date_mois_4' => 'Aprile',
195
-	'date_mois_4_abbr' => 'apr',
196
-	'date_mois_5' => 'Maggio',
197
-	'date_mois_5_abbr' => 'mag',
198
-	'date_mois_6' => 'Giugno',
199
-	'date_mois_6_abbr' => 'giu',
200
-	'date_mois_7' => 'Luglio',
201
-	'date_mois_7_abbr' => 'lug',
202
-	'date_mois_8' => 'Agosto',
203
-	'date_mois_8_abbr' => 'ago',
204
-	'date_mois_9' => 'Settembre',
205
-	'date_mois_9_abbr' => 'set',
206
-	'date_saison_1' => 'inverno',
207
-	'date_saison_2' => 'primavera',
208
-	'date_saison_3' => 'estate',
209
-	'date_saison_4' => 'autunno',
210
-	'date_secondes' => 'secondi',
211
-	'date_semaines' => 'settimane',
212
-	'date_un_mois' => 'mese',
213
-	'date_une_heure' => 'ora',
214
-	'date_une_minute' => 'minuto',
215
-	'date_une_seconde' => 'secondo',
216
-	'date_une_semaine' => 'settimana',
217
-	'dirs_commencer' => ' per iniziare realmente l’installazione',
218
-	'dirs_preliminaire' => 'Prima di iniziare: <b>impostare i diritti di accesso</b>',
219
-	'dirs_probleme_droits' => 'Problema nei diritti di accesso',
220
-	'dirs_repertoires_absents' => '<p><b>Le seguenti cartelle non sono state trovate: </b></p><ul>@bad_dirs@.</ul>
91
+    // D
92
+    'date_aujourdhui' => 'oggi',
93
+    'date_avant_jc' => 'a.C.',
94
+    'date_dans' => 'tra @delai@',
95
+    'date_de_mois_1' => '@j@ gennaio',
96
+    'date_de_mois_10' => '@j@ ottobre',
97
+    'date_de_mois_11' => '@j@ novembre',
98
+    'date_de_mois_12' => '@j@ dicembre',
99
+    'date_de_mois_2' => '@j@ febbraio',
100
+    'date_de_mois_3' => '@j@ marzo',
101
+    'date_de_mois_4' => '@j@ aprile',
102
+    'date_de_mois_5' => '@j@ maggio',
103
+    'date_de_mois_6' => '@j@ giugno',
104
+    'date_de_mois_7' => '@j@ luglio',
105
+    'date_de_mois_8' => '@j@ agosto',
106
+    'date_de_mois_9' => '@j@ settembre',
107
+    'date_demain' => 'domani',
108
+    'date_fmt_heures_minutes' => '@h@:@m@',
109
+    'date_fmt_heures_minutes_court' => '@h@h@m@',
110
+    'date_fmt_jour' => '@nomjour@ @jour@',
111
+    'date_fmt_jour_heure' => '@jour@ ore @heure@',
112
+    'date_fmt_jour_heure_debut_fin' => 'Il @jour@ dalle @heure_debut@ alle @heure_fin@',
113
+    'date_fmt_jour_heure_debut_fin_abbr' => 'Il @dtstart@@jour@ dalle @heure_debut@@dtabbr@ alle @dtstart@@heure_fin@@dtend@',
114
+    'date_fmt_jour_mois' => '@jourmois@',
115
+    'date_fmt_jour_mois_annee' => '@jourmois@ @annee@',
116
+    'date_fmt_mois_annee' => '@nommois@ @annee@',
117
+    'date_fmt_nomjour' => '@nomjour@ @date@',
118
+    'date_fmt_nomjour_date' => 'il @nomjour@ @date@',
119
+    'date_fmt_periode' => 'Dal @date_debut@ al @date_fin@',
120
+    'date_fmt_periode_abbr' => 'Dal @dtart@@date_debut@@dtabbr@ al @dtend@@date_fin@@dtabbr@',
121
+    'date_fmt_periode_from' => 'Dal',
122
+    'date_fmt_periode_to' => 'a',
123
+    'date_fmt_saison_annee' => '@saison@ @annee@',
124
+    'date_heures' => 'ore',
125
+    'date_hier' => 'ieri',
126
+    'date_il_y_a' => '@delai@ fa',
127
+    'date_jnum1' => '1',
128
+    'date_jnum10' => '10',
129
+    'date_jnum11' => '11',
130
+    'date_jnum12' => '12',
131
+    'date_jnum13' => '13',
132
+    'date_jnum14' => '14',
133
+    'date_jnum15' => '15',
134
+    'date_jnum16' => '16',
135
+    'date_jnum17' => '17',
136
+    'date_jnum18' => '18',
137
+    'date_jnum19' => '19',
138
+    'date_jnum2' => '2',
139
+    'date_jnum20' => '20',
140
+    'date_jnum21' => '21',
141
+    'date_jnum22' => '22',
142
+    'date_jnum23' => '23',
143
+    'date_jnum24' => '24',
144
+    'date_jnum25' => '25',
145
+    'date_jnum26' => '26',
146
+    'date_jnum27' => '27',
147
+    'date_jnum28' => '28',
148
+    'date_jnum29' => '29',
149
+    'date_jnum3' => '3',
150
+    'date_jnum30' => '30',
151
+    'date_jnum31' => '31',
152
+    'date_jnum4' => '4',
153
+    'date_jnum5' => '5',
154
+    'date_jnum6' => '6',
155
+    'date_jnum7' => '7',
156
+    'date_jnum8' => '8',
157
+    'date_jnum9' => '9',
158
+    'date_jour_1' => 'domenica',
159
+    'date_jour_1_abbr' => 'dom',
160
+    'date_jour_1_initiale' => 'd',
161
+    'date_jour_2' => 'lunedì',
162
+    'date_jour_2_abbr' => 'lun',
163
+    'date_jour_2_initiale' => 'l',
164
+    'date_jour_3' => 'martedì',
165
+    'date_jour_3_abbr' => 'mar',
166
+    'date_jour_3_initiale' => 'm',
167
+    'date_jour_4' => 'mercoledì',
168
+    'date_jour_4_abbr' => 'mer',
169
+    'date_jour_4_initiale' => 'm',
170
+    'date_jour_5' => 'giovedì',
171
+    'date_jour_5_abbr' => 'giov',
172
+    'date_jour_5_initiale' => 'g',
173
+    'date_jour_6' => 'venerdì',
174
+    'date_jour_6_abbr' => 'ven',
175
+    'date_jour_6_initiale' => 'v',
176
+    'date_jour_7' => 'sabato',
177
+    'date_jour_7_abbr' => 'sab',
178
+    'date_jour_7_initiale' => 's',
179
+    'date_jours' => 'giorni',
180
+    'date_minutes' => 'minuti',
181
+    'date_mois' => 'mesi',
182
+    'date_mois_1' => 'Gennaio',
183
+    'date_mois_10' => 'Ottobre',
184
+    'date_mois_10_abbr' => 'ott',
185
+    'date_mois_11' => 'Novembre',
186
+    'date_mois_11_abbr' => 'nov',
187
+    'date_mois_12' => 'Dicembre',
188
+    'date_mois_12_abbr' => 'dic',
189
+    'date_mois_1_abbr' => 'gen',
190
+    'date_mois_2' => 'Febbraio',
191
+    'date_mois_2_abbr' => 'feb',
192
+    'date_mois_3' => 'Marzo',
193
+    'date_mois_3_abbr' => 'mar',
194
+    'date_mois_4' => 'Aprile',
195
+    'date_mois_4_abbr' => 'apr',
196
+    'date_mois_5' => 'Maggio',
197
+    'date_mois_5_abbr' => 'mag',
198
+    'date_mois_6' => 'Giugno',
199
+    'date_mois_6_abbr' => 'giu',
200
+    'date_mois_7' => 'Luglio',
201
+    'date_mois_7_abbr' => 'lug',
202
+    'date_mois_8' => 'Agosto',
203
+    'date_mois_8_abbr' => 'ago',
204
+    'date_mois_9' => 'Settembre',
205
+    'date_mois_9_abbr' => 'set',
206
+    'date_saison_1' => 'inverno',
207
+    'date_saison_2' => 'primavera',
208
+    'date_saison_3' => 'estate',
209
+    'date_saison_4' => 'autunno',
210
+    'date_secondes' => 'secondi',
211
+    'date_semaines' => 'settimane',
212
+    'date_un_mois' => 'mese',
213
+    'date_une_heure' => 'ora',
214
+    'date_une_minute' => 'minuto',
215
+    'date_une_seconde' => 'secondo',
216
+    'date_une_semaine' => 'settimana',
217
+    'dirs_commencer' => ' per iniziare realmente l’installazione',
218
+    'dirs_preliminaire' => 'Prima di iniziare: <b>impostare i diritti di accesso</b>',
219
+    'dirs_probleme_droits' => 'Problema nei diritti di accesso',
220
+    'dirs_repertoires_absents' => '<p><b>Le seguenti cartelle non sono state trovate: </b></p><ul>@bad_dirs@.</ul>
221 221
   <p>Probabilmente ciò è dovuto a un’errata formattazione delle lettere maiuscole o minuscole.
222 222
   Verificare che le maiuscole e le minuscole delle cartelle coincidano con quelle visualizzate
223 223
   qui sopra; se non è così, rinominare le cartelle utilizzando il software FTP.</p>
224 224
   <p>Una volta effettuata questa correzione, si potrà',
225
-	'dirs_repertoires_suivants' => '<p><b>Le seguenti cartelle non sono accessibili in scrittura:</b></p> <ul>@bad_dirs@</ul>
225
+    'dirs_repertoires_suivants' => '<p><b>Le seguenti cartelle non sono accessibili in scrittura:</b></p> <ul>@bad_dirs@</ul>
226 226
 <p>Per risolvere il problema, utilizzare un client FTP per impostare i diritti di accesso
227 227
 di ciascuna di queste cartelle. La procedura è spiegata in dettaglio nella guida d’installazione.</p>
228 228
 <p>Una volta attribuiti i permessi, si potrà ',
229
-	'double_occurrence' => 'Doppia occorrenza',
229
+    'double_occurrence' => 'Doppia occorrenza',
230 230
 
231
-	// E
232
-	'en_cours' => 'in corso',
233
-	'envoi_via_le_site' => 'Invio tramite il sito',
234
-	'erreur' => 'Errore',
235
-	'erreur_balise_non_fermee' => 'ultimo tag non chiuso:',
236
-	'erreur_technique_ajaxform' => 'Ops. Un’errore inaspettato non ti consente di inviare il form. Puoi provare di nuovo.',
237
-	'erreur_technique_enregistrement_champs' => 'Un errore tecnico ha impedito la corretta registrazione del campo @champs@.',
238
-	'erreur_technique_enregistrement_impossible' => 'Un errore tecnico ha impedito la registrazione.',
239
-	'erreur_texte' => 'errore/i',
240
-	'etape' => 'Fase',
231
+    // E
232
+    'en_cours' => 'in corso',
233
+    'envoi_via_le_site' => 'Invio tramite il sito',
234
+    'erreur' => 'Errore',
235
+    'erreur_balise_non_fermee' => 'ultimo tag non chiuso:',
236
+    'erreur_technique_ajaxform' => 'Ops. Un’errore inaspettato non ti consente di inviare il form. Puoi provare di nuovo.',
237
+    'erreur_technique_enregistrement_champs' => 'Un errore tecnico ha impedito la corretta registrazione del campo @champs@.',
238
+    'erreur_technique_enregistrement_impossible' => 'Un errore tecnico ha impedito la registrazione.',
239
+    'erreur_texte' => 'errore/i',
240
+    'etape' => 'Fase',
241 241
 
242
-	// F
243
-	'fichier_introuvable' => 'File @fichier@ non trovato',
244
-	'fonction_introuvable' => 'Funzione @fonction@() non trovata',
245
-	'form_auteur_confirmation' => 'Per cortesia conferma il tuo indirizzo email',
246
-	'form_auteur_email_modifie' => 'Il tuo indirizzo email è stato modificato',
247
-	'form_auteur_envoi_mail_confirmation' => 'Una email di conferma è stata inviata a  @email@. È necessario visitare l’URL indicata nel messaggio per convalidare il tuo indirizzo email.',
248
-	'form_auteur_mail_confirmation' => 'Ciao,
242
+    // F
243
+    'fichier_introuvable' => 'File @fichier@ non trovato',
244
+    'fonction_introuvable' => 'Funzione @fonction@() non trovata',
245
+    'form_auteur_confirmation' => 'Per cortesia conferma il tuo indirizzo email',
246
+    'form_auteur_email_modifie' => 'Il tuo indirizzo email è stato modificato',
247
+    'form_auteur_envoi_mail_confirmation' => 'Una email di conferma è stata inviata a  @email@. È necessario visitare l’URL indicata nel messaggio per convalidare il tuo indirizzo email.',
248
+    'form_auteur_mail_confirmation' => 'Ciao,
249 249
 
250 250
 Hai chiesto di modificare l’indirizzo email.
251 251
 Per confermare la tua nuova email, devi connetterti all’
@@ -253,346 +253,346 @@  discard block
 block discarded – undo
253 253
 
254 254
     @url@
255 255
 ',
256
-	'form_deja_inscrit' => 'Sei già iscritto.',
257
-	'form_email_non_valide' => 'L’indirizzo email non è valido.',
258
-	'form_forum_access_refuse' => 'Non hai più accesso a questo sito.',
259
-	'form_forum_bonjour' => 'Buongiorno @nom@,',
260
-	'form_forum_confirmer_email' => 'Puoi confermare il tuo indirizzo email,vai a questo indirizzo: @url_confirm@',
261
-	'form_forum_email_deja_enregistre' => 'Questo indirizzo email è già registrato, puoi dunque utilizzare la tua password abituale.',
262
-	'form_forum_identifiant_mail' => 'Il nuovo codice identificativo (ID) ti è stato appena inviato tramite email.',
263
-	'form_forum_identifiants' => 'Dati personali',
264
-	'form_forum_indiquer_nom_email' => 'Indica qui nome e indirizzo email.  L’ID personale ti verrà recapitato tramite email a breve.',
265
-	'form_forum_login' => 'login:',
266
-	'form_forum_message_auto' => '(questo è un messaggio generato automaticamente)',
267
-	'form_forum_pass' => 'password:',
268
-	'form_forum_probleme_mail' => 'Problema di posta: l’ID non può essere inviato.',
269
-	'form_forum_voici1' => 'Ecco i dati per poter partecipare ai forum
256
+    'form_deja_inscrit' => 'Sei già iscritto.',
257
+    'form_email_non_valide' => 'L’indirizzo email non è valido.',
258
+    'form_forum_access_refuse' => 'Non hai più accesso a questo sito.',
259
+    'form_forum_bonjour' => 'Buongiorno @nom@,',
260
+    'form_forum_confirmer_email' => 'Puoi confermare il tuo indirizzo email,vai a questo indirizzo: @url_confirm@',
261
+    'form_forum_email_deja_enregistre' => 'Questo indirizzo email è già registrato, puoi dunque utilizzare la tua password abituale.',
262
+    'form_forum_identifiant_mail' => 'Il nuovo codice identificativo (ID) ti è stato appena inviato tramite email.',
263
+    'form_forum_identifiants' => 'Dati personali',
264
+    'form_forum_indiquer_nom_email' => 'Indica qui nome e indirizzo email.  L’ID personale ti verrà recapitato tramite email a breve.',
265
+    'form_forum_login' => 'login:',
266
+    'form_forum_message_auto' => '(questo è un messaggio generato automaticamente)',
267
+    'form_forum_pass' => 'password:',
268
+    'form_forum_probleme_mail' => 'Problema di posta: l’ID non può essere inviato.',
269
+    'form_forum_voici1' => 'Ecco i dati per poter partecipare ai forum
270 270
  del sito"@nom_site_spip@" (@adresse_site@):',
271
-	'form_forum_voici2' => 'Ecco i dati per poter proporre degli articoli sul sito
271
+    'form_forum_voici2' => 'Ecco i dati per poter proporre degli articoli sul sito
272 272
 "@nom_site_spip@" (@adresse_login@):',
273
-	'form_indiquer_email' => 'Indica il tuo indirizzo email.',
274
-	'form_indiquer_nom' => 'Indica il tuo nome.',
275
-	'form_indiquer_nom_site' => 'Indica il nome del tuo sito.',
276
-	'form_pet_deja_enregistre' => 'Questo sito è già registrato',
277
-	'form_pet_signature_pasprise' => 'La tua adesione non è stata presa in considerazione.',
278
-	'form_prop_confirmer_envoi' => 'Conferma l’invio',
279
-	'form_prop_description' => 'Descrizione/commento',
280
-	'form_prop_enregistre' => 'La tua proposta è stata registrata ed apparirà on line dopo l’approvazione del responsabile del sito.',
281
-	'form_prop_envoyer' => 'Invia un messaggio',
282
-	'form_prop_indiquer_email' => 'Indica un indirizzo email valido',
283
-	'form_prop_indiquer_nom_site' => 'Indica il nome del sito.',
284
-	'form_prop_indiquer_sujet' => 'Indica un argomento',
285
-	'form_prop_message_envoye' => 'Messaggio inviato',
286
-	'form_prop_non_enregistre' => 'La tua proposta non è stata registrata.',
287
-	'form_prop_sujet' => 'Argomento',
288
-	'form_prop_url_site' => 'Indirizzo (URL) del sito',
289
-	'format_date_attendu' => 'Inserire una data nel formato gg/mm/aaaa.',
290
-	'format_date_incorrecte' => 'La data (o il suo formato) non è corretta',
291
-	'format_heure_attendu' => 'Inserire un’ora nel formato hh:mm.',
292
-	'format_heure_incorrecte' => 'L’ora (o il suo formato) non è corretta',
293
-	'forum_non_inscrit' => 'Non sei iscritto, oppure l’indirizzo o la password inseriti non sono corretti.',
294
-	'forum_par_auteur' => 'di @auteur@',
295
-	'forum_titre_erreur' => 'Errore...',
273
+    'form_indiquer_email' => 'Indica il tuo indirizzo email.',
274
+    'form_indiquer_nom' => 'Indica il tuo nome.',
275
+    'form_indiquer_nom_site' => 'Indica il nome del tuo sito.',
276
+    'form_pet_deja_enregistre' => 'Questo sito è già registrato',
277
+    'form_pet_signature_pasprise' => 'La tua adesione non è stata presa in considerazione.',
278
+    'form_prop_confirmer_envoi' => 'Conferma l’invio',
279
+    'form_prop_description' => 'Descrizione/commento',
280
+    'form_prop_enregistre' => 'La tua proposta è stata registrata ed apparirà on line dopo l’approvazione del responsabile del sito.',
281
+    'form_prop_envoyer' => 'Invia un messaggio',
282
+    'form_prop_indiquer_email' => 'Indica un indirizzo email valido',
283
+    'form_prop_indiquer_nom_site' => 'Indica il nome del sito.',
284
+    'form_prop_indiquer_sujet' => 'Indica un argomento',
285
+    'form_prop_message_envoye' => 'Messaggio inviato',
286
+    'form_prop_non_enregistre' => 'La tua proposta non è stata registrata.',
287
+    'form_prop_sujet' => 'Argomento',
288
+    'form_prop_url_site' => 'Indirizzo (URL) del sito',
289
+    'format_date_attendu' => 'Inserire una data nel formato gg/mm/aaaa.',
290
+    'format_date_incorrecte' => 'La data (o il suo formato) non è corretta',
291
+    'format_heure_attendu' => 'Inserire un’ora nel formato hh:mm.',
292
+    'format_heure_incorrecte' => 'L’ora (o il suo formato) non è corretta',
293
+    'forum_non_inscrit' => 'Non sei iscritto, oppure l’indirizzo o la password inseriti non sono corretti.',
294
+    'forum_par_auteur' => 'di @auteur@',
295
+    'forum_titre_erreur' => 'Errore...',
296 296
 
297
-	// I
298
-	'ical_texte_rss_articles' => 'Il file di "backend" degli articoli di questo sito si trova al seguente indirizzo:',
299
-	'ical_texte_rss_articles2' => 'È anche possibile ottenere un file di "backend" per gli articoli di una singola rubrica:',
300
-	'ical_texte_rss_breves' => 'Inoltre esiste un file per l’insieme delle brevi del sito. Precisando un numero di rubrica ci si può limitare alle brevi in essa contenute.',
301
-	'icone_a_suivre' => 'Pannello di controllo',
302
-	'icone_admin_site' => 'Amministrazione del sito',
303
-	'icone_agenda' => 'Agenda',
304
-	'icone_aide_ligne' => 'Guida in linea',
305
-	'icone_articles' => 'Articoli',
306
-	'icone_auteurs' => 'Autori',
307
-	'icone_brouteur' => 'Navigazione rapida',
308
-	'icone_configuration_site' => 'Configurazione del sito',
309
-	'icone_configurer_site' => 'Configura il sito',
310
-	'icone_creer_nouvel_auteur' => 'Crea un nuovo autore',
311
-	'icone_creer_rubrique' => 'Crea una rubrica',
312
-	'icone_creer_sous_rubrique' => 'Crea una sottorubrica',
313
-	'icone_deconnecter' => 'Esci',
314
-	'icone_discussions' => 'Discussioni',
315
-	'icone_doc_rubrique' => 'Documenti delle rubriche',
316
-	'icone_ecrire_article' => 'Scrivi un articolo',
317
-	'icone_edition_site' => 'Redazione del sito',
318
-	'icone_gestion_langues' => 'Gestione delle lingue',
319
-	'icone_informations_personnelles' => 'Dati personali',
320
-	'icone_interface_complet' => 'Interfaccia completa',
321
-	'icone_interface_simple' => 'Interfaccia semplificata',
322
-	'icone_maintenance_site' => 'Manutenzione tecnica',
323
-	'icone_messagerie_personnelle' => 'Messaggi personali',
324
-	'icone_repartition_debut' => 'Mostra la ripartizione dall’inizio',
325
-	'icone_rubriques' => 'Rubriche',
326
-	'icone_sauver_site' => 'Backup del sito',
327
-	'icone_site_entier' => 'Tutto il sito',
328
-	'icone_sites_references' => 'Siti repertoriati',
329
-	'icone_statistiques' => 'Statistiche del sito',
330
-	'icone_suivi_activite' => 'Monitorare l’attività del sito',
331
-	'icone_suivi_actualite' => 'Evoluzione del sito',
332
-	'icone_suivi_pettions' => 'Gestione delle petizioni',
333
-	'icone_suivi_revisions' => 'Modifiche agli articoli',
334
-	'icone_supprimer_document' => 'Elimina il documento',
335
-	'icone_supprimer_image' => 'Elimina l’immagine',
336
-	'icone_tous_articles' => 'Tutti i tuoi articoli',
337
-	'icone_tous_auteur' => 'Tutti gli autori',
338
-	'icone_tous_visiteur' => 'Tutti i visitatori',
339
-	'icone_visiter_site' => 'Visita il sito',
340
-	'icone_voir_en_ligne' => 'Vedi on line',
341
-	'img_indisponible' => 'immagine non disponibile',
342
-	'impossible' => 'impossibile',
343
-	'info_a_suivre' => 'PANNELLO DI CONTROLLO »',
344
-	'info_acces_interdit' => 'Accesso vietato',
345
-	'info_acces_refuse' => 'Accesso rifiutato',
346
-	'info_action' => 'Azione: @action@',
347
-	'info_administrer_rubriques' => 'Puoi amministrare questa rubrica e le relative sottorubriche',
348
-	'info_adresse_non_indiquee' => 'Non hai indicato l’indirizzo da testare!',
349
-	'info_aide' => 'AIUTO:',
350
-	'info_ajouter_mot' => 'Aggiungi questa parola',
351
-	'info_annonce' => 'ANNUNCIO',
352
-	'info_annonces_generales' => 'Annunci generali:',
353
-	'info_article_propose' => 'Articolo proposto',
354
-	'info_article_publie' => 'Articolo pubblicato',
355
-	'info_article_redaction' => 'Articolo in corso di redazione',
356
-	'info_article_refuse' => 'Articolo rifiutato',
357
-	'info_article_supprime' => 'Articolo eliminato',
358
-	'info_articles' => 'Articoli',
359
-	'info_articles_a_valider' => 'Articoli da convalidare',
360
-	'info_articles_nb' => '@nb@ articoli',
361
-	'info_articles_proposes' => 'Articoli proposti',
362
-	'info_articles_un' => '1 articolo',
363
-	'info_auteurs_nombre' => 'autore(i):',
364
-	'info_authentification_ftp' => 'Autenticazione (via FTP).',
365
-	'info_breves_2' => 'brevi',
366
-	'info_breves_nb' => '@nb@ notizie',
367
-	'info_breves_un' => '1 notizia',
368
-	'info_connexion_refusee' => 'Connessione rifiutata',
369
-	'info_contact_developpeur' => 'Contatta un programmatore.',
370
-	'info_contenance' => 'Questo sito contiene:',
371
-	'info_contribution' => 'contributi dei forum',
372
-	'info_copyright' => '@spip@ è un software libero distribuito @lien_gpl@.',
373
-	'info_copyright_doc' => 'Per maggiori informazioni, vedi il sito <a href="@spipnet@">@spipnet_affiche@</a>.',
374
-	'info_copyright_gpl' => 'sotto licenza GPL',
375
-	'info_cours_edition' => 'Articoli in fase di redazione',
376
-	'info_creer_repertoire' => 'Creare un file o una cartella chiamata:',
377
-	'info_creer_repertoire_2' => 'all’interno della sottocartella <b>@repertoire@</b>, poi:',
378
-	'info_creer_vignette' => 'creazione automatica dell’anteprima',
379
-	'info_creerdansrubrique_non_autorise' => 'Non si dispone di diritti sufficienti per creare contenuti in questa rubrica',
380
-	'info_deplier' => 'Espandi',
381
-	'info_descriptif_nombre' => 'descrizione(i):',
382
-	'info_description' => 'Descrizione:',
383
-	'info_description_2' => 'Descrizione:',
384
-	'info_dimension' => 'Dimensioni:',
385
-	'info_documents_nb' => '@nb@ documenti',
386
-	'info_documents_un' => '1 documento',
387
-	'info_ecire_message_prive' => 'Scrivi un messaggio privato',
388
-	'info_email_invalide' => 'Indirizzo email non valido.',
389
-	'info_en_cours_validation' => 'I tuoi articoli in corso di redazione',
390
-	'info_en_ligne' => 'Attualmente on line:',
391
-	'info_envoyer_message_prive' => 'Invia un messaggio privato a questo autore',
392
-	'info_erreur_requete' => 'Errore nella richiesta: ',
393
-	'info_erreur_squelette2' => 'Nessun modello di layout <b>@fichier@</b> trovato...',
394
-	'info_erreur_systeme' => 'Errore di sistema (errno @errsys@)',
395
-	'info_erreur_systeme2' => 'Il disco rigido potrebbe essere pieno o la base dati danneggiata.<br />
297
+    // I
298
+    'ical_texte_rss_articles' => 'Il file di "backend" degli articoli di questo sito si trova al seguente indirizzo:',
299
+    'ical_texte_rss_articles2' => 'È anche possibile ottenere un file di "backend" per gli articoli di una singola rubrica:',
300
+    'ical_texte_rss_breves' => 'Inoltre esiste un file per l’insieme delle brevi del sito. Precisando un numero di rubrica ci si può limitare alle brevi in essa contenute.',
301
+    'icone_a_suivre' => 'Pannello di controllo',
302
+    'icone_admin_site' => 'Amministrazione del sito',
303
+    'icone_agenda' => 'Agenda',
304
+    'icone_aide_ligne' => 'Guida in linea',
305
+    'icone_articles' => 'Articoli',
306
+    'icone_auteurs' => 'Autori',
307
+    'icone_brouteur' => 'Navigazione rapida',
308
+    'icone_configuration_site' => 'Configurazione del sito',
309
+    'icone_configurer_site' => 'Configura il sito',
310
+    'icone_creer_nouvel_auteur' => 'Crea un nuovo autore',
311
+    'icone_creer_rubrique' => 'Crea una rubrica',
312
+    'icone_creer_sous_rubrique' => 'Crea una sottorubrica',
313
+    'icone_deconnecter' => 'Esci',
314
+    'icone_discussions' => 'Discussioni',
315
+    'icone_doc_rubrique' => 'Documenti delle rubriche',
316
+    'icone_ecrire_article' => 'Scrivi un articolo',
317
+    'icone_edition_site' => 'Redazione del sito',
318
+    'icone_gestion_langues' => 'Gestione delle lingue',
319
+    'icone_informations_personnelles' => 'Dati personali',
320
+    'icone_interface_complet' => 'Interfaccia completa',
321
+    'icone_interface_simple' => 'Interfaccia semplificata',
322
+    'icone_maintenance_site' => 'Manutenzione tecnica',
323
+    'icone_messagerie_personnelle' => 'Messaggi personali',
324
+    'icone_repartition_debut' => 'Mostra la ripartizione dall’inizio',
325
+    'icone_rubriques' => 'Rubriche',
326
+    'icone_sauver_site' => 'Backup del sito',
327
+    'icone_site_entier' => 'Tutto il sito',
328
+    'icone_sites_references' => 'Siti repertoriati',
329
+    'icone_statistiques' => 'Statistiche del sito',
330
+    'icone_suivi_activite' => 'Monitorare l’attività del sito',
331
+    'icone_suivi_actualite' => 'Evoluzione del sito',
332
+    'icone_suivi_pettions' => 'Gestione delle petizioni',
333
+    'icone_suivi_revisions' => 'Modifiche agli articoli',
334
+    'icone_supprimer_document' => 'Elimina il documento',
335
+    'icone_supprimer_image' => 'Elimina l’immagine',
336
+    'icone_tous_articles' => 'Tutti i tuoi articoli',
337
+    'icone_tous_auteur' => 'Tutti gli autori',
338
+    'icone_tous_visiteur' => 'Tutti i visitatori',
339
+    'icone_visiter_site' => 'Visita il sito',
340
+    'icone_voir_en_ligne' => 'Vedi on line',
341
+    'img_indisponible' => 'immagine non disponibile',
342
+    'impossible' => 'impossibile',
343
+    'info_a_suivre' => 'PANNELLO DI CONTROLLO »',
344
+    'info_acces_interdit' => 'Accesso vietato',
345
+    'info_acces_refuse' => 'Accesso rifiutato',
346
+    'info_action' => 'Azione: @action@',
347
+    'info_administrer_rubriques' => 'Puoi amministrare questa rubrica e le relative sottorubriche',
348
+    'info_adresse_non_indiquee' => 'Non hai indicato l’indirizzo da testare!',
349
+    'info_aide' => 'AIUTO:',
350
+    'info_ajouter_mot' => 'Aggiungi questa parola',
351
+    'info_annonce' => 'ANNUNCIO',
352
+    'info_annonces_generales' => 'Annunci generali:',
353
+    'info_article_propose' => 'Articolo proposto',
354
+    'info_article_publie' => 'Articolo pubblicato',
355
+    'info_article_redaction' => 'Articolo in corso di redazione',
356
+    'info_article_refuse' => 'Articolo rifiutato',
357
+    'info_article_supprime' => 'Articolo eliminato',
358
+    'info_articles' => 'Articoli',
359
+    'info_articles_a_valider' => 'Articoli da convalidare',
360
+    'info_articles_nb' => '@nb@ articoli',
361
+    'info_articles_proposes' => 'Articoli proposti',
362
+    'info_articles_un' => '1 articolo',
363
+    'info_auteurs_nombre' => 'autore(i):',
364
+    'info_authentification_ftp' => 'Autenticazione (via FTP).',
365
+    'info_breves_2' => 'brevi',
366
+    'info_breves_nb' => '@nb@ notizie',
367
+    'info_breves_un' => '1 notizia',
368
+    'info_connexion_refusee' => 'Connessione rifiutata',
369
+    'info_contact_developpeur' => 'Contatta un programmatore.',
370
+    'info_contenance' => 'Questo sito contiene:',
371
+    'info_contribution' => 'contributi dei forum',
372
+    'info_copyright' => '@spip@ è un software libero distribuito @lien_gpl@.',
373
+    'info_copyright_doc' => 'Per maggiori informazioni, vedi il sito <a href="@spipnet@">@spipnet_affiche@</a>.',
374
+    'info_copyright_gpl' => 'sotto licenza GPL',
375
+    'info_cours_edition' => 'Articoli in fase di redazione',
376
+    'info_creer_repertoire' => 'Creare un file o una cartella chiamata:',
377
+    'info_creer_repertoire_2' => 'all’interno della sottocartella <b>@repertoire@</b>, poi:',
378
+    'info_creer_vignette' => 'creazione automatica dell’anteprima',
379
+    'info_creerdansrubrique_non_autorise' => 'Non si dispone di diritti sufficienti per creare contenuti in questa rubrica',
380
+    'info_deplier' => 'Espandi',
381
+    'info_descriptif_nombre' => 'descrizione(i):',
382
+    'info_description' => 'Descrizione:',
383
+    'info_description_2' => 'Descrizione:',
384
+    'info_dimension' => 'Dimensioni:',
385
+    'info_documents_nb' => '@nb@ documenti',
386
+    'info_documents_un' => '1 documento',
387
+    'info_ecire_message_prive' => 'Scrivi un messaggio privato',
388
+    'info_email_invalide' => 'Indirizzo email non valido.',
389
+    'info_en_cours_validation' => 'I tuoi articoli in corso di redazione',
390
+    'info_en_ligne' => 'Attualmente on line:',
391
+    'info_envoyer_message_prive' => 'Invia un messaggio privato a questo autore',
392
+    'info_erreur_requete' => 'Errore nella richiesta: ',
393
+    'info_erreur_squelette2' => 'Nessun modello di layout <b>@fichier@</b> trovato...',
394
+    'info_erreur_systeme' => 'Errore di sistema (errno @errsys@)',
395
+    'info_erreur_systeme2' => 'Il disco rigido potrebbe essere pieno o la base dati danneggiata.<br />
396 396
 <span style="color:red;">Tenta di <a href=\'@script@\'>ripristinare la base dati</a>, o contatta il tuo hoster.</span>',
397
-	'info_fini' => 'Finito!',
398
-	'info_format_image' => 'Formati di file immagine utilizzabili per la creazione delle etichette: @gd_formats@.',
399
-	'info_format_non_defini' => 'formato non definito',
400
-	'info_grand_ecran' => 'Layout per monitor grandi',
401
-	'info_image_aide' => 'AIUTO',
402
-	'info_image_process_titre' => 'Metodo per generare thumbnail',
403
-	'info_impossible_lire_page' => '<b>Errore!</b> Impossibile  leggere la pagina <tt><html>@test_proxy@</html></tt> attraverso il proxy ',
404
-	'info_installation_systeme_publication' => 'Installazione del sistema di pubblicazione...',
405
-	'info_installer_documents' => 'È possibile installare automaticamente tutti i documenti contenuti nella cartella @upload@.',
406
-	'info_installer_ftp' => 'In qualità di amministratore, puoi installare file (via FTP) nella cartella @upload@ per poi selezionarli direttamente.',
407
-	'info_installer_images' => 'È possibile installare delle immagini in formato JPEG, GIF e PNG.',
408
-	'info_installer_images_dossier' => 'Installare delle immagini nella cartella @upload@ per poterle selezionare direttamente.',
409
-	'info_interface_complete' => 'Interfaccia completa',
410
-	'info_interface_simple' => 'Interfaccia semplificata',
411
-	'info_joindre_document_article' => 'Puoi allegare a questo articolo dei documenti del tipo',
412
-	'info_joindre_document_rubrique' => 'Puoi aggiungere a questa rubrica documenti del tipo',
413
-	'info_joindre_documents_article' => 'Puoi allegare all’articolo documenti del tipo: ',
414
-	'info_l_article' => 'l’articolo',
415
-	'info_la_breve' => 'la breve',
416
-	'info_la_rubrique' => 'la sezione',
417
-	'info_langue_principale' => 'Lingua predefinita del sito',
418
-	'info_largeur_vignette' => '@largeur_vignette@ x @hauteur_vignette@ pixel',
419
-	'info_les_auteurs_1' => 'di @les_auteurs@ ',
420
-	'info_logo_format_interdit' => 'Solo i logo in formato @formats@ sono permessi.',
421
-	'info_logo_max_poids' => 'I logo devono obbligatoriamente avere una dimensione inferiore a @maxi@ (questo file è di @actuel@).',
422
-	'info_mail_fournisseur' => '[email protected]',
423
-	'info_message_2' => 'MESSAGGIO',
424
-	'info_message_supprime' => 'MESSAGGIO ELIMINATO',
425
-	'info_messages_nb' => '@nb@ messaggi',
426
-	'info_messages_un' => '1 messaggio',
427
-	'info_mise_en_ligne' => 'Data di pubblicazione on line:',
428
-	'info_modification_parametres_securite' => 'modifiche dei parametri di sicurezza',
429
-	'info_mois_courant' => 'Durante il mese:',
430
-	'info_mot_cle_ajoute' => 'La seguente parola chiave è stata aggiunta a',
431
-	'info_multi_herit' => 'Lingua predefinita',
432
-	'info_multi_langues_soulignees' => 'Le <u>lingue sottolineate</u> hanno la traduzione parziale o totale per tutti i testi dell’interfaccia. Se si seleziona una di queste lingue, molti elementi del sito pubblico (date, form) verranno tradotti automaticamente. Per le lingue che non sono sottolineate, invece, tali elementi rimarranno nella lingua principale del sito.',
433
-	'info_multilinguisme' => 'Multilinguismo',
434
-	'info_nom_non_utilisateurs_connectes' => 'Il tuo nome non appare nella lista degli utenti collegati.',
435
-	'info_nom_utilisateurs_connectes' => 'Il tuo nome è visibile nella lista degli utenti collegati.',
436
-	'info_nombre_en_ligne' => 'Attualmente on line:',
437
-	'info_non_resultat' => 'Nessun risultato per "@cherche_mot@"',
438
-	'info_non_utilisation_messagerie' => 'Il sistema di messaggistica interna di questo sito non viene utilizzato.',
439
-	'info_nouveau_message' => 'HAI UN NUOVO MESSAGGIO',
440
-	'info_nouveaux_messages' => 'HAI @total_messages@ NUOVI MESSAGGI',
441
-	'info_numero_abbreviation' => 'N. ',
442
-	'info_obligatoire' => 'Questa informazione è obbligatoria',
443
-	'info_page_actuelle' => 'Pagina corrente',
444
-	'info_pense_bete' => 'MEMO',
445
-	'info_petit_ecran' => 'Layout per monitor piccoli',
446
-	'info_petition_close' => 'Petizione chiusa',
447
-	'info_pixels' => 'pixels',
448
-	'info_plusieurs_mots_trouves' => 'Numerose parole chiave trovate per "@cherche_mot@":',
449
-	'info_portfolio_automatique' => 'Portfolio automatico:',
450
-	'info_premier_resultat' => '[@debut_limit@ primi risultati su @total@]',
451
-	'info_premier_resultat_sur' => '[@debut_limit@ primi risultati su @total@]',
452
-	'info_propose_1' => '[@nom_site_spip@] Propone: @titre@',
453
-	'info_propose_2' => 'Articolo proposto
397
+    'info_fini' => 'Finito!',
398
+    'info_format_image' => 'Formati di file immagine utilizzabili per la creazione delle etichette: @gd_formats@.',
399
+    'info_format_non_defini' => 'formato non definito',
400
+    'info_grand_ecran' => 'Layout per monitor grandi',
401
+    'info_image_aide' => 'AIUTO',
402
+    'info_image_process_titre' => 'Metodo per generare thumbnail',
403
+    'info_impossible_lire_page' => '<b>Errore!</b> Impossibile  leggere la pagina <tt><html>@test_proxy@</html></tt> attraverso il proxy ',
404
+    'info_installation_systeme_publication' => 'Installazione del sistema di pubblicazione...',
405
+    'info_installer_documents' => 'È possibile installare automaticamente tutti i documenti contenuti nella cartella @upload@.',
406
+    'info_installer_ftp' => 'In qualità di amministratore, puoi installare file (via FTP) nella cartella @upload@ per poi selezionarli direttamente.',
407
+    'info_installer_images' => 'È possibile installare delle immagini in formato JPEG, GIF e PNG.',
408
+    'info_installer_images_dossier' => 'Installare delle immagini nella cartella @upload@ per poterle selezionare direttamente.',
409
+    'info_interface_complete' => 'Interfaccia completa',
410
+    'info_interface_simple' => 'Interfaccia semplificata',
411
+    'info_joindre_document_article' => 'Puoi allegare a questo articolo dei documenti del tipo',
412
+    'info_joindre_document_rubrique' => 'Puoi aggiungere a questa rubrica documenti del tipo',
413
+    'info_joindre_documents_article' => 'Puoi allegare all’articolo documenti del tipo: ',
414
+    'info_l_article' => 'l’articolo',
415
+    'info_la_breve' => 'la breve',
416
+    'info_la_rubrique' => 'la sezione',
417
+    'info_langue_principale' => 'Lingua predefinita del sito',
418
+    'info_largeur_vignette' => '@largeur_vignette@ x @hauteur_vignette@ pixel',
419
+    'info_les_auteurs_1' => 'di @les_auteurs@ ',
420
+    'info_logo_format_interdit' => 'Solo i logo in formato @formats@ sono permessi.',
421
+    'info_logo_max_poids' => 'I logo devono obbligatoriamente avere una dimensione inferiore a @maxi@ (questo file è di @actuel@).',
422
+    'info_mail_fournisseur' => '[email protected]',
423
+    'info_message_2' => 'MESSAGGIO',
424
+    'info_message_supprime' => 'MESSAGGIO ELIMINATO',
425
+    'info_messages_nb' => '@nb@ messaggi',
426
+    'info_messages_un' => '1 messaggio',
427
+    'info_mise_en_ligne' => 'Data di pubblicazione on line:',
428
+    'info_modification_parametres_securite' => 'modifiche dei parametri di sicurezza',
429
+    'info_mois_courant' => 'Durante il mese:',
430
+    'info_mot_cle_ajoute' => 'La seguente parola chiave è stata aggiunta a',
431
+    'info_multi_herit' => 'Lingua predefinita',
432
+    'info_multi_langues_soulignees' => 'Le <u>lingue sottolineate</u> hanno la traduzione parziale o totale per tutti i testi dell’interfaccia. Se si seleziona una di queste lingue, molti elementi del sito pubblico (date, form) verranno tradotti automaticamente. Per le lingue che non sono sottolineate, invece, tali elementi rimarranno nella lingua principale del sito.',
433
+    'info_multilinguisme' => 'Multilinguismo',
434
+    'info_nom_non_utilisateurs_connectes' => 'Il tuo nome non appare nella lista degli utenti collegati.',
435
+    'info_nom_utilisateurs_connectes' => 'Il tuo nome è visibile nella lista degli utenti collegati.',
436
+    'info_nombre_en_ligne' => 'Attualmente on line:',
437
+    'info_non_resultat' => 'Nessun risultato per "@cherche_mot@"',
438
+    'info_non_utilisation_messagerie' => 'Il sistema di messaggistica interna di questo sito non viene utilizzato.',
439
+    'info_nouveau_message' => 'HAI UN NUOVO MESSAGGIO',
440
+    'info_nouveaux_messages' => 'HAI @total_messages@ NUOVI MESSAGGI',
441
+    'info_numero_abbreviation' => 'N. ',
442
+    'info_obligatoire' => 'Questa informazione è obbligatoria',
443
+    'info_page_actuelle' => 'Pagina corrente',
444
+    'info_pense_bete' => 'MEMO',
445
+    'info_petit_ecran' => 'Layout per monitor piccoli',
446
+    'info_petition_close' => 'Petizione chiusa',
447
+    'info_pixels' => 'pixels',
448
+    'info_plusieurs_mots_trouves' => 'Numerose parole chiave trovate per "@cherche_mot@":',
449
+    'info_portfolio_automatique' => 'Portfolio automatico:',
450
+    'info_premier_resultat' => '[@debut_limit@ primi risultati su @total@]',
451
+    'info_premier_resultat_sur' => '[@debut_limit@ primi risultati su @total@]',
452
+    'info_propose_1' => '[@nom_site_spip@] Propone: @titre@',
453
+    'info_propose_2' => 'Articolo proposto
454 454
 ---------------',
455
-	'info_propose_3' => 'L’articolo "@titre@" è proposto per la pubblicazione',
456
-	'info_propose_4' => 'Sei invitato a consultare e a dare la tua opinione ',
457
-	'info_propose_5' => 'nel forum annesso.
455
+    'info_propose_3' => 'L’articolo "@titre@" è proposto per la pubblicazione',
456
+    'info_propose_4' => 'Sei invitato a consultare e a dare la tua opinione ',
457
+    'info_propose_5' => 'nel forum annesso.
458 458
 
459 459
 È disponibile all’indirizzo:',
460
-	'info_publie_01' => 'L’articolo "@titre@" è stato convalidato da @connect_nom@.',
461
-	'info_publie_1' => '[@nom_site_spip@] PUBBLICA: @titre@',
462
-	'info_publie_2' => 'Articolo pubblicato
460
+    'info_publie_01' => 'L’articolo "@titre@" è stato convalidato da @connect_nom@.',
461
+    'info_publie_1' => '[@nom_site_spip@] PUBBLICA: @titre@',
462
+    'info_publie_2' => 'Articolo pubblicato
463 463
 --------------',
464
-	'info_rechercher' => 'Ricerca',
465
-	'info_rechercher_02' => 'Cerca:',
466
-	'info_remplacer_vignette' => 'Sostituire l’icona predefinita con una personalizzata:',
467
-	'info_rubriques_nb' => '@nb@ sezioni',
468
-	'info_rubriques_un' => '1 sezione',
469
-	'info_sans_titre_2' => 'senza titolo',
470
-	'info_selectionner_fichier' => 'Puoi selezionare un file della cartella @upload@',
471
-	'info_selectionner_fichier_2' => 'Seleziona un file:',
472
-	'info_sites_nb' => '@nb@ siti',
473
-	'info_sites_un' => '1 sito',
474
-	'info_supprimer_vignette' => 'Cancella l’immagine',
475
-	'info_symbole_bleu' => 'Il simbolo <b>blu</b> indica un <b>memo</b>: cioè un messaggio ad uso personale.',
476
-	'info_symbole_jaune' => 'Il simbolo <b>giallo</b> indica un <b>annuncio a tutti i redattori</b>: modificabile da tutti gli amministratori e visibile da tutti i redattori.',
477
-	'info_symbole_vert' => 'Il simbolo <b>verde</b> indica i <b>messaggi scambiati con altri utenti  </b> del sito.',
478
-	'info_telecharger_nouveau_logo' => 'Upload di un nuovo logo:',
479
-	'info_telecharger_ordinateur' => 'Upload dal tuo computer:',
480
-	'info_tous_resultats_enregistres' => '[tutti i risultati sono salvati]',
481
-	'info_tout_afficher' => 'Visualizza tutto',
482
-	'info_travaux_texte' => 'Questo sito non è stato ancora configurato. Torna più tardi...',
483
-	'info_travaux_titre' => 'Lavori in corso',
484
-	'info_trop_resultat' => 'Troppi risultati per "@cherche_mot@" ; restringi la ricerca.',
485
-	'info_utilisation_messagerie_interne' => 'Stai utilizzando il sistema di messaggistica interna al sito.',
486
-	'info_valider_lien' => 'convalidare questo link',
487
-	'info_verifier_image' => ', verifica che le immagini siano state trasferite correttamente.',
488
-	'info_vignette_defaut' => 'Loghi predefiniti',
489
-	'info_vignette_personnalisee' => 'Loghi personalizzati',
490
-	'info_visite' => 'visita:',
491
-	'info_vos_rendez_vous' => 'I tuoi prossimi appuntamenti',
492
-	'infos_vos_pense_bete' => 'I tuoi memo',
464
+    'info_rechercher' => 'Ricerca',
465
+    'info_rechercher_02' => 'Cerca:',
466
+    'info_remplacer_vignette' => 'Sostituire l’icona predefinita con una personalizzata:',
467
+    'info_rubriques_nb' => '@nb@ sezioni',
468
+    'info_rubriques_un' => '1 sezione',
469
+    'info_sans_titre_2' => 'senza titolo',
470
+    'info_selectionner_fichier' => 'Puoi selezionare un file della cartella @upload@',
471
+    'info_selectionner_fichier_2' => 'Seleziona un file:',
472
+    'info_sites_nb' => '@nb@ siti',
473
+    'info_sites_un' => '1 sito',
474
+    'info_supprimer_vignette' => 'Cancella l’immagine',
475
+    'info_symbole_bleu' => 'Il simbolo <b>blu</b> indica un <b>memo</b>: cioè un messaggio ad uso personale.',
476
+    'info_symbole_jaune' => 'Il simbolo <b>giallo</b> indica un <b>annuncio a tutti i redattori</b>: modificabile da tutti gli amministratori e visibile da tutti i redattori.',
477
+    'info_symbole_vert' => 'Il simbolo <b>verde</b> indica i <b>messaggi scambiati con altri utenti  </b> del sito.',
478
+    'info_telecharger_nouveau_logo' => 'Upload di un nuovo logo:',
479
+    'info_telecharger_ordinateur' => 'Upload dal tuo computer:',
480
+    'info_tous_resultats_enregistres' => '[tutti i risultati sono salvati]',
481
+    'info_tout_afficher' => 'Visualizza tutto',
482
+    'info_travaux_texte' => 'Questo sito non è stato ancora configurato. Torna più tardi...',
483
+    'info_travaux_titre' => 'Lavori in corso',
484
+    'info_trop_resultat' => 'Troppi risultati per "@cherche_mot@" ; restringi la ricerca.',
485
+    'info_utilisation_messagerie_interne' => 'Stai utilizzando il sistema di messaggistica interna al sito.',
486
+    'info_valider_lien' => 'convalidare questo link',
487
+    'info_verifier_image' => ', verifica che le immagini siano state trasferite correttamente.',
488
+    'info_vignette_defaut' => 'Loghi predefiniti',
489
+    'info_vignette_personnalisee' => 'Loghi personalizzati',
490
+    'info_visite' => 'visita:',
491
+    'info_vos_rendez_vous' => 'I tuoi prossimi appuntamenti',
492
+    'infos_vos_pense_bete' => 'I tuoi memo',
493 493
 
494
-	// L
495
-	'label_ajout_id_rapide' => 'Inserimento rapido',
496
-	'label_poids_fichier' => 'Dimensione',
497
-	'label_ponctuer' => '@label@:',
498
-	'lien_afficher_icones_seuls' => 'Mostra solo le icone',
499
-	'lien_afficher_texte_icones' => 'Mostra le icone e il testo',
500
-	'lien_afficher_texte_seul' => 'Mostra solo il testo',
501
-	'lien_aller_a_la_derniere_page' => 'Vai all’ultima pagina',
502
-	'lien_aller_a_la_page_nb' => 'Vai alla pagina @nb@',
503
-	'lien_aller_a_la_page_precedente' => 'Vai alla pagina precedente',
504
-	'lien_aller_a_la_page_suivante' => 'Vai alla pagina successiva',
505
-	'lien_aller_a_la_premiere_page' => 'Vai alla prima pagina',
506
-	'lien_liberer' => 'libera',
507
-	'lien_liberer_tous' => 'liberare questi articoli',
508
-	'lien_nouvea_pense_bete' => 'NUOVO MEMO',
509
-	'lien_nouveau_message' => 'NUOVO MESSAGGIO',
510
-	'lien_nouvelle_annonce' => 'NUOVO ANNUNCIO',
511
-	'lien_petitions' => 'PETIZIONE',
512
-	'lien_popularite' => 'popolarità: @popularite@%',
513
-	'lien_racine_site' => 'ROOT DEL SITO',
514
-	'lien_reessayer' => 'Prova di nuovo',
515
-	'lien_repondre_message' => 'Rispondi',
516
-	'lien_supprimer' => 'cancella',
517
-	'lien_tout_afficher' => 'Visualizza tutto ',
518
-	'lien_visite_site' => 'visita il sito',
519
-	'lien_visites' => '@visites@ visite',
520
-	'lien_voir_auteur' => 'Vedi questo autore',
521
-	'ligne' => 'Linea',
522
-	'login' => 'Collegamento',
523
-	'login_acces_prive' => 'accesso all’area riservata',
524
-	'login_autre_identifiant' => 'connettiti con un altro ID',
525
-	'login_cookie_accepte' => 'Imposta il tuo browser affinché li accetti (almeno per questo sito).',
526
-	'login_cookie_oblige' => 'Per identificarsi in modo sicuro su questo sito è necessario accettare i cookie.',
527
-	'login_deconnexion_ok' => 'Disconnessione effettuata.',
528
-	'login_erreur_pass' => 'Errore nella password.',
529
-	'login_espace_prive' => 'area riservata',
530
-	'login_identifiant_inconnu' => 'L’ID « @login@ » risulta inesistente.',
531
-	'login_login' => 'Login:',
532
-	'login_login2' => 'Login o indirizzo email:',
533
-	'login_login_pass_incorrect' => '(Login o password errati.)',
534
-	'login_motpasseoublie' => 'password dimenticata?',
535
-	'login_non_securise' => 'Attenzione, questo modulo non è sicuro.
494
+    // L
495
+    'label_ajout_id_rapide' => 'Inserimento rapido',
496
+    'label_poids_fichier' => 'Dimensione',
497
+    'label_ponctuer' => '@label@:',
498
+    'lien_afficher_icones_seuls' => 'Mostra solo le icone',
499
+    'lien_afficher_texte_icones' => 'Mostra le icone e il testo',
500
+    'lien_afficher_texte_seul' => 'Mostra solo il testo',
501
+    'lien_aller_a_la_derniere_page' => 'Vai all’ultima pagina',
502
+    'lien_aller_a_la_page_nb' => 'Vai alla pagina @nb@',
503
+    'lien_aller_a_la_page_precedente' => 'Vai alla pagina precedente',
504
+    'lien_aller_a_la_page_suivante' => 'Vai alla pagina successiva',
505
+    'lien_aller_a_la_premiere_page' => 'Vai alla prima pagina',
506
+    'lien_liberer' => 'libera',
507
+    'lien_liberer_tous' => 'liberare questi articoli',
508
+    'lien_nouvea_pense_bete' => 'NUOVO MEMO',
509
+    'lien_nouveau_message' => 'NUOVO MESSAGGIO',
510
+    'lien_nouvelle_annonce' => 'NUOVO ANNUNCIO',
511
+    'lien_petitions' => 'PETIZIONE',
512
+    'lien_popularite' => 'popolarità: @popularite@%',
513
+    'lien_racine_site' => 'ROOT DEL SITO',
514
+    'lien_reessayer' => 'Prova di nuovo',
515
+    'lien_repondre_message' => 'Rispondi',
516
+    'lien_supprimer' => 'cancella',
517
+    'lien_tout_afficher' => 'Visualizza tutto ',
518
+    'lien_visite_site' => 'visita il sito',
519
+    'lien_visites' => '@visites@ visite',
520
+    'lien_voir_auteur' => 'Vedi questo autore',
521
+    'ligne' => 'Linea',
522
+    'login' => 'Collegamento',
523
+    'login_acces_prive' => 'accesso all’area riservata',
524
+    'login_autre_identifiant' => 'connettiti con un altro ID',
525
+    'login_cookie_accepte' => 'Imposta il tuo browser affinché li accetti (almeno per questo sito).',
526
+    'login_cookie_oblige' => 'Per identificarsi in modo sicuro su questo sito è necessario accettare i cookie.',
527
+    'login_deconnexion_ok' => 'Disconnessione effettuata.',
528
+    'login_erreur_pass' => 'Errore nella password.',
529
+    'login_espace_prive' => 'area riservata',
530
+    'login_identifiant_inconnu' => 'L’ID « @login@ » risulta inesistente.',
531
+    'login_login' => 'Login:',
532
+    'login_login2' => 'Login o indirizzo email:',
533
+    'login_login_pass_incorrect' => '(Login o password errati.)',
534
+    'login_motpasseoublie' => 'password dimenticata?',
535
+    'login_non_securise' => 'Attenzione, questo modulo non è sicuro.
536 536
 Se non vuoi che la tua password possa essere intercettata sulla rete,
537 537
 devi attivare Javascript nel tuo browser e',
538
-	'login_nouvelle_tentative' => 'Nuovo tentativo',
539
-	'login_par_ici' => 'Sei registrato... per di qua...',
540
-	'login_pass2' => 'Password:',
541
-	'login_preferez_refuser' => '<b>Se preferisci non accettare i cookie</b> c’è un altro metodo (meno sicuro) per connettersi:',
542
-	'login_recharger' => 'aggiorna questa pagina',
543
-	'login_rester_identifie' => 'Conservare l’identificazione per alcuni giorni',
544
-	'login_retour_public' => 'Ritorna al sito pubblico',
545
-	'login_retour_site' => 'Ritorna al sito pubblico',
546
-	'login_retoursitepublic' => 'ritorna al sito pubblico',
547
-	'login_sans_cookie' => 'Identificazione senza cookie',
548
-	'login_securise' => 'Accesso protetto',
549
-	'login_sinscrire' => 'registrati',
550
-	'login_test_navigateur' => 'test browser/riconnessione',
551
-	'login_verifiez_navigateur' => '(Verifica comunque se il tuo browser ha memorizzato la password...)',
538
+    'login_nouvelle_tentative' => 'Nuovo tentativo',
539
+    'login_par_ici' => 'Sei registrato... per di qua...',
540
+    'login_pass2' => 'Password:',
541
+    'login_preferez_refuser' => '<b>Se preferisci non accettare i cookie</b> c’è un altro metodo (meno sicuro) per connettersi:',
542
+    'login_recharger' => 'aggiorna questa pagina',
543
+    'login_rester_identifie' => 'Conservare l’identificazione per alcuni giorni',
544
+    'login_retour_public' => 'Ritorna al sito pubblico',
545
+    'login_retour_site' => 'Ritorna al sito pubblico',
546
+    'login_retoursitepublic' => 'ritorna al sito pubblico',
547
+    'login_sans_cookie' => 'Identificazione senza cookie',
548
+    'login_securise' => 'Accesso protetto',
549
+    'login_sinscrire' => 'registrati',
550
+    'login_test_navigateur' => 'test browser/riconnessione',
551
+    'login_verifiez_navigateur' => '(Verifica comunque se il tuo browser ha memorizzato la password...)',
552 552
 
553
-	// M
554
-	'masquer_colonne' => 'Nascondi questa colonna',
555
-	'masquer_trad' => 'nascondere le traduzioni',
556
-	'message_nouveaux_identifiants_echec' => 'Impossibile generare nuovi identificativi',
557
-	'message_nouveaux_identifiants_echec_envoi' => 'Le nuove credenziali di accesso non possono essere inviate.',
558
-	'message_nouveaux_identifiants_ok' => 'Le nuove credenziali di accsso sono state inviate a @email@.',
559
-	'module_fichiers_langues' => 'File lingua',
553
+    // M
554
+    'masquer_colonne' => 'Nascondi questa colonna',
555
+    'masquer_trad' => 'nascondere le traduzioni',
556
+    'message_nouveaux_identifiants_echec' => 'Impossibile generare nuovi identificativi',
557
+    'message_nouveaux_identifiants_echec_envoi' => 'Le nuove credenziali di accesso non possono essere inviate.',
558
+    'message_nouveaux_identifiants_ok' => 'Le nuove credenziali di accsso sono state inviate a @email@.',
559
+    'module_fichiers_langues' => 'File lingua',
560 560
 
561
-	// N
562
-	'navigateur_pas_redirige' => 'Se la pagina non cambia automaticamente, cliccare qui per continuare.',
563
-	'numero' => 'Numero',
561
+    // N
562
+    'navigateur_pas_redirige' => 'Se la pagina non cambia automaticamente, cliccare qui per continuare.',
563
+    'numero' => 'Numero',
564 564
 
565
-	// O
566
-	'occurence' => 'Occorrenza',
567
-	'onglet_affacer_base' => 'Svuota il database',
568
-	'onglet_auteur' => 'L’autore',
569
-	'onglet_contenu_site' => 'Contenuto del sito',
570
-	'onglet_evolution_visite_mod' => 'Evoluzione',
571
-	'onglet_fonctions_avances' => 'Funzioni avanzate',
572
-	'onglet_informations_personnelles' => 'Dati personali',
573
-	'onglet_interactivite' => 'Interattività',
574
-	'onglet_messagerie' => 'Messaggi',
575
-	'onglet_repartition_rubrique' => 'Ripartizione per rubriche',
576
-	'onglet_save_restaur_base' => 'Salva/ripristina il database',
577
-	'onglet_vider_cache' => 'Svuota la cache',
565
+    // O
566
+    'occurence' => 'Occorrenza',
567
+    'onglet_affacer_base' => 'Svuota il database',
568
+    'onglet_auteur' => 'L’autore',
569
+    'onglet_contenu_site' => 'Contenuto del sito',
570
+    'onglet_evolution_visite_mod' => 'Evoluzione',
571
+    'onglet_fonctions_avances' => 'Funzioni avanzate',
572
+    'onglet_informations_personnelles' => 'Dati personali',
573
+    'onglet_interactivite' => 'Interattività',
574
+    'onglet_messagerie' => 'Messaggi',
575
+    'onglet_repartition_rubrique' => 'Ripartizione per rubriche',
576
+    'onglet_save_restaur_base' => 'Salva/ripristina il database',
577
+    'onglet_vider_cache' => 'Svuota la cache',
578 578
 
579
-	// P
580
-	'pass_choix_pass' => 'Inserisci una nuova password:',
581
-	'pass_erreur' => 'Errore',
582
-	'pass_erreur_acces_refuse' => '<b>Errore:</b> non hai più accesso a questo sito.',
583
-	'pass_erreur_code_inconnu' => '<b>Errore:</b> il codice inserito non corriponde a nessuno degli utenti che hanno accesso a questo sito.',
584
-	'pass_erreur_non_enregistre' => '<b>Errore:</b> l’indirizzo <tt>@email_oubli@</tt> non è registrato su questo sito.',
585
-	'pass_erreur_non_valide' => '<b>Errore:</b> questo indirizzo <tt>@email_oubli@</tt> non è valido!',
586
-	'pass_erreur_probleme_technique' => '<b>Errore:</b> l’email non può essere inviato a causa di un problema tecnico.',
587
-	'pass_espace_prive_bla' => 'L’area riservata di questo sito è accessibile
579
+    // P
580
+    'pass_choix_pass' => 'Inserisci una nuova password:',
581
+    'pass_erreur' => 'Errore',
582
+    'pass_erreur_acces_refuse' => '<b>Errore:</b> non hai più accesso a questo sito.',
583
+    'pass_erreur_code_inconnu' => '<b>Errore:</b> il codice inserito non corriponde a nessuno degli utenti che hanno accesso a questo sito.',
584
+    'pass_erreur_non_enregistre' => '<b>Errore:</b> l’indirizzo <tt>@email_oubli@</tt> non è registrato su questo sito.',
585
+    'pass_erreur_non_valide' => '<b>Errore:</b> questo indirizzo <tt>@email_oubli@</tt> non è valido!',
586
+    'pass_erreur_probleme_technique' => '<b>Errore:</b> l’email non può essere inviato a causa di un problema tecnico.',
587
+    'pass_espace_prive_bla' => 'L’area riservata di questo sito è accessibile
588 588
 unicamente agli utenti registrati.
589 589
 Una volta iscritto, potrai consultare gli articoli in corso di redazione,
590 590
 proporre nuovi articoli e partecipare a tutti i forum.',
591
-	'pass_forum_bla' => 'Hai chiesto di intervenire su un forum
591
+    'pass_forum_bla' => 'Hai chiesto di intervenire su un forum
592 592
 riservato agli utenti registrati.',
593
-	'pass_indiquez_cidessous' => 'Indica qui sotto l’indirizzo email con il quale ti sei registrato precedentemente.
593
+    'pass_indiquez_cidessous' => 'Indica qui sotto l’indirizzo email con il quale ti sei registrato precedentemente.
594 594
 Riceverai un email con le istruzioni per recuperare i dati di accesso al sito.',
595
-	'pass_mail_passcookie' => '(questo è un messaggio generato automaticamente)
595
+    'pass_mail_passcookie' => '(questo è un messaggio generato automaticamente)
596 596
 Per recuperare i dati di accesso al sito
597 597
 @nom_site_spip@ (@adresse_site@)
598 598
 
@@ -603,143 +603,143 @@  discard block
 block discarded – undo
603 603
 e riconnetterti all’area riservata.
604 604
 
605 605
 ',
606
-	'pass_mot_oublie' => 'Password dimenticata',
607
-	'pass_nouveau_enregistre' => 'La nuova password è stata salvata.',
608
-	'pass_nouveau_pass' => 'Nuova password',
609
-	'pass_ok' => 'OK',
610
-	'pass_oubli_mot' => 'Password dimenticata',
611
-	'pass_procedure_changer' => 'Per modificare la tua password, dobbiamo prima verificare la tua identità. Inserisci l’indirizzo email associato al tuo account.',
612
-	'pass_quitter_fenetre' => 'Chiudi la finestra',
613
-	'pass_rappel_login' => 'Ricorda: il tuo ID (login) è « @login@ ».',
614
-	'pass_recevoir_mail' => 'Riceverai un email contenente le istruzioni per recuperare i dati di accesso al sito.',
615
-	'pass_retour_public' => 'Torna al sito pubblico',
616
-	'pass_rien_a_faire_ici' => 'Vicolo cieco...',
617
-	'pass_vousinscrire' => 'Registrati al sito',
618
-	'precedent' => 'precedente',
619
-	'previsualisation' => 'Anteprima',
620
-	'previsualiser' => 'Visualizzare l’anteprima',
606
+    'pass_mot_oublie' => 'Password dimenticata',
607
+    'pass_nouveau_enregistre' => 'La nuova password è stata salvata.',
608
+    'pass_nouveau_pass' => 'Nuova password',
609
+    'pass_ok' => 'OK',
610
+    'pass_oubli_mot' => 'Password dimenticata',
611
+    'pass_procedure_changer' => 'Per modificare la tua password, dobbiamo prima verificare la tua identità. Inserisci l’indirizzo email associato al tuo account.',
612
+    'pass_quitter_fenetre' => 'Chiudi la finestra',
613
+    'pass_rappel_login' => 'Ricorda: il tuo ID (login) è « @login@ ».',
614
+    'pass_recevoir_mail' => 'Riceverai un email contenente le istruzioni per recuperare i dati di accesso al sito.',
615
+    'pass_retour_public' => 'Torna al sito pubblico',
616
+    'pass_rien_a_faire_ici' => 'Vicolo cieco...',
617
+    'pass_vousinscrire' => 'Registrati al sito',
618
+    'precedent' => 'precedente',
619
+    'previsualisation' => 'Anteprima',
620
+    'previsualiser' => 'Visualizzare l’anteprima',
621 621
 
622
-	// R
623
-	'retour' => 'Indietro',
622
+    // R
623
+    'retour' => 'Indietro',
624 624
 
625
-	// S
626
-	'spip_conforme_dtd' => 'SPIP ritiene che questo documento è conforme al proprio DOCTYPE:',
627
-	'squelette' => 'modello di layout',
628
-	'squelette_inclus_ligne' => 'modello incluso, linea',
629
-	'squelette_ligne' => 'modello, linea',
630
-	'stats_visites_et_popularite' => '@visites@ visite; popolarità: @popularite@',
631
-	'suivant' => 'successivo',
625
+    // S
626
+    'spip_conforme_dtd' => 'SPIP ritiene che questo documento è conforme al proprio DOCTYPE:',
627
+    'squelette' => 'modello di layout',
628
+    'squelette_inclus_ligne' => 'modello incluso, linea',
629
+    'squelette_ligne' => 'modello, linea',
630
+    'stats_visites_et_popularite' => '@visites@ visite; popolarità: @popularite@',
631
+    'suivant' => 'successivo',
632 632
 
633
-	// T
634
-	'taille_go' => '@taille@ Gb',
635
-	'taille_ko' => '@taille@ Kb',
636
-	'taille_mo' => '@taille@ Mb',
637
-	'taille_octets' => '@taille@ byte',
638
-	'texte_actualite_site_1' => 'Quando avrai maggiore familiarità con l’interfaccia, clicca su «',
639
-	'texte_actualite_site_2' => 'interfaccia completa',
640
-	'texte_actualite_site_3' => '» per avere accesso a nuove opzioni.',
641
-	'texte_creation_automatique_vignette' => 'La creazione automatica di thumbnail di anteprima è attivata. Se inserisci in questo campo delle immagini in formato @gd_formats@, esse saranno accompagnate da thumbnail con una dimensione massima di @taille_preview@ pixels. ',
642
-	'texte_documents_associes' => 'I seguenti documenti sono associati all’articolo,
633
+    // T
634
+    'taille_go' => '@taille@ Gb',
635
+    'taille_ko' => '@taille@ Kb',
636
+    'taille_mo' => '@taille@ Mb',
637
+    'taille_octets' => '@taille@ byte',
638
+    'texte_actualite_site_1' => 'Quando avrai maggiore familiarità con l’interfaccia, clicca su «',
639
+    'texte_actualite_site_2' => 'interfaccia completa',
640
+    'texte_actualite_site_3' => '» per avere accesso a nuove opzioni.',
641
+    'texte_creation_automatique_vignette' => 'La creazione automatica di thumbnail di anteprima è attivata. Se inserisci in questo campo delle immagini in formato @gd_formats@, esse saranno accompagnate da thumbnail con una dimensione massima di @taille_preview@ pixels. ',
642
+    'texte_documents_associes' => 'I seguenti documenti sono associati all’articolo,
643 643
 ma non vi sono stati inseriti direttamente.
644 644
 A seconda delle impostazioni di pubblicazione del sito,
645 645
 potranno essere disponibili sotto forma di documenti allegati.',
646
-	'texte_erreur_mise_niveau_base' => 'Errore nel database durante l’aggiornamento.
646
+    'texte_erreur_mise_niveau_base' => 'Errore nel database durante l’aggiornamento.
647 647
 L’immagine <b>@fichier@</b> non è passata (articolo @id_article@).
648 648
 Prendi nota di questo riferimento, ritenta l’aggiornamento,
649 649
 e verifica che le immagini si vedano ancora
650 650
 negli articoli.',
651
-	'texte_erreur_visiteur' => 'Si è tentato di entrare nell’area riservata con un login non valido.',
652
-	'texte_inc_auth_1' => 'Sei identificato con il
651
+    'texte_erreur_visiteur' => 'Si è tentato di entrare nell’area riservata con un login non valido.',
652
+    'texte_inc_auth_1' => 'Sei identificato con il
653 653
 login <b>@auth_login@</b>, ma nel database non esiste. 
654 654
 Prova a ',
655
-	'texte_inc_auth_2' => 'collegarti nuovamente',
656
-	'texte_inc_auth_3' => ', dopo aver eventualmente effettuato un logout e 
655
+    'texte_inc_auth_2' => 'collegarti nuovamente',
656
+    'texte_inc_auth_3' => ', dopo aver eventualmente effettuato un logout e 
657 657
 riavviato il tuo browser.',
658
-	'texte_inc_config' => 'Le modifiche effettuate in queste pagine influenzano notevolmente il
658
+    'texte_inc_config' => 'Le modifiche effettuate in queste pagine influenzano notevolmente il
659 659
 funzionamento del sito. Non intervenire finché non conosci bene i meccanismi del sistema SPIP. <br /><br /><b>In generale, si consiglia di lasciare sempre al webmaster la configurazione delle opzioni qui presenti.</b>',
660
-	'texte_inc_meta_1' => 'La scrittura del file <code>@fichier@</code> ha causato un errore di sistema. L’amministratore del sito, ',
661
-	'texte_inc_meta_2' => 'verifichi i diritti di scrittura',
662
-	'texte_inc_meta_3' => 'nella cartella <code>@repertoire@</code>.',
663
-	'texte_statut_en_cours_redaction' => 'in corso di redazione',
664
-	'texte_statut_poubelle' => 'nel cestino',
665
-	'texte_statut_propose_evaluation' => 'proposto per una valutazione',
666
-	'texte_statut_publie' => 'pubblicato on line',
667
-	'texte_statut_refuse' => 'rifiutato',
668
-	'titre_ajouter_mot_cle' => 'AGGIUNGI UNA PAROLA CHIAVE:',
669
-	'titre_cadre_raccourcis' => 'SCELTA RAPIDA:',
670
-	'titre_changer_couleur_interface' => 'Cambia il colore dell’interfaccia',
671
-	'titre_image_admin_article' => 'Puoi amministrare questo articolo',
672
-	'titre_image_administrateur' => 'Amministratore',
673
-	'titre_image_aide' => 'Aiuto su questo elemento',
674
-	'titre_image_auteur_supprime' => 'Autore eliminato',
675
-	'titre_image_redacteur' => 'Redattore senza accesso',
676
-	'titre_image_redacteur_02' => 'Redattore',
677
-	'titre_image_selecteur' => 'Mostra la lista',
678
-	'titre_image_visiteur' => 'Visitatore',
679
-	'titre_joindre_document' => 'ALLEGA UN DOCUMENTO',
680
-	'titre_mots_cles' => 'PAROLE CHIAVE',
681
-	'titre_probleme_technique' => 'Attenzione: un problema tecnico (server SQL) impedisce l’accesso a questa parte del sito. Grazie per la comprensione.',
682
-	'titre_publier_document' => 'ALLEGA UN DOCUMENTO A QUESTA RUBRICA',
683
-	'titre_signatures_attente' => 'Firme in corso di convalida',
684
-	'titre_signatures_confirmees' => 'Firme confermate',
685
-	'titre_statistiques' => 'Statistiche del sito',
686
-	'titre_titre_document' => 'Titolo del documento:',
687
-	'todo' => 'prossimo',
688
-	'trad_definir_reference' => 'Scegliere "@titre@" come riferimento per le traduzioni',
689
-	'trad_reference' => '(articolo di riferimento)',
660
+    'texte_inc_meta_1' => 'La scrittura del file <code>@fichier@</code> ha causato un errore di sistema. L’amministratore del sito, ',
661
+    'texte_inc_meta_2' => 'verifichi i diritti di scrittura',
662
+    'texte_inc_meta_3' => 'nella cartella <code>@repertoire@</code>.',
663
+    'texte_statut_en_cours_redaction' => 'in corso di redazione',
664
+    'texte_statut_poubelle' => 'nel cestino',
665
+    'texte_statut_propose_evaluation' => 'proposto per una valutazione',
666
+    'texte_statut_publie' => 'pubblicato on line',
667
+    'texte_statut_refuse' => 'rifiutato',
668
+    'titre_ajouter_mot_cle' => 'AGGIUNGI UNA PAROLA CHIAVE:',
669
+    'titre_cadre_raccourcis' => 'SCELTA RAPIDA:',
670
+    'titre_changer_couleur_interface' => 'Cambia il colore dell’interfaccia',
671
+    'titre_image_admin_article' => 'Puoi amministrare questo articolo',
672
+    'titre_image_administrateur' => 'Amministratore',
673
+    'titre_image_aide' => 'Aiuto su questo elemento',
674
+    'titre_image_auteur_supprime' => 'Autore eliminato',
675
+    'titre_image_redacteur' => 'Redattore senza accesso',
676
+    'titre_image_redacteur_02' => 'Redattore',
677
+    'titre_image_selecteur' => 'Mostra la lista',
678
+    'titre_image_visiteur' => 'Visitatore',
679
+    'titre_joindre_document' => 'ALLEGA UN DOCUMENTO',
680
+    'titre_mots_cles' => 'PAROLE CHIAVE',
681
+    'titre_probleme_technique' => 'Attenzione: un problema tecnico (server SQL) impedisce l’accesso a questa parte del sito. Grazie per la comprensione.',
682
+    'titre_publier_document' => 'ALLEGA UN DOCUMENTO A QUESTA RUBRICA',
683
+    'titre_signatures_attente' => 'Firme in corso di convalida',
684
+    'titre_signatures_confirmees' => 'Firme confermate',
685
+    'titre_statistiques' => 'Statistiche del sito',
686
+    'titre_titre_document' => 'Titolo del documento:',
687
+    'todo' => 'prossimo',
688
+    'trad_definir_reference' => 'Scegliere "@titre@" come riferimento per le traduzioni',
689
+    'trad_reference' => '(articolo di riferimento)',
690 690
 
691
-	// U
692
-	'upload_limit' => 'Questo file è trppo grande per il server; la dimensione massima consentita in <i>upload</i> è di @max@.',
691
+    // U
692
+    'upload_limit' => 'Questo file è trppo grande per il server; la dimensione massima consentita in <i>upload</i> è di @max@.',
693 693
 
694
-	// Z
695
-	'zbug_balise_b_aval' => ': ciclo B deve precedere ciclo BOUCLE',
696
-	'zbug_balise_inexistante' => 'errore @from@: il tag #@balise@ non esiste ',
697
-	'zbug_balise_sans_argument' => 'Argomento mancante nel tag @balise@',
698
-	'zbug_boucle' => 'ciclo',
699
-	'zbug_boucle_recursive_undef' => 'ciclo ricorsivo non definito',
700
-	'zbug_calcul' => 'calcolo',
701
-	'zbug_champ_hors_boucle' => 'Campo @champ@ fuori dal ciclo',
702
-	'zbug_champ_hors_critere' => 'Il campo @champ@ non rispetta il criterio @critere@',
703
-	'zbug_champ_hors_motif' => 'Campo @champ@ fuori da un contesto @motif@',
704
-	'zbug_code' => 'codice',
705
-	'zbug_critere_inconnu' => 'criterio sconosciuto @critere@',
706
-	'zbug_critere_sur_table_sans_cle_primaire' => '{@critere@} su una tabella senza una chiave primaria atomica',
707
-	'zbug_distant_interdit' => 'esterno non accessibile',
708
-	'zbug_doublon_table_sans_cle_primaire' => 'doppioni su una tabella senza chiave primaria atomica',
709
-	'zbug_doublon_table_sans_index' => 'doppioni su una tabella senza indice',
710
-	'zbug_erreur_boucle_double' => 'BOUCLE@id@: doppia definizione',
711
-	'zbug_erreur_boucle_fermant' => 'BOUCLE@id@: chiusura tag mancante',
712
-	'zbug_erreur_boucle_syntaxe' => 'Sintassi del ciclo errata',
713
-	'zbug_erreur_compilation' => 'Errore di compilazione',
714
-	'zbug_erreur_execution_page' => 'errore di esecuzione della pagina',
715
-	'zbug_erreur_filtre' => 'Errore : filtro <b>« @filtre@ »</b> non esistente',
716
-	'zbug_erreur_filtre_nbarg_min' => 'Filtro@filtre@: argomento(i) @nb@ mancante(i)',
717
-	'zbug_erreur_meme_parent' => 'il criterio {meme_parent} si applica unicamente ai cicli (FORUMS) o (RUBRIQUES)',
718
-	'zbug_erreur_squelette' => 'Errore/i nel modello di layout',
719
-	'zbug_hors_compilation' => 'Fuori Compilazione',
720
-	'zbug_info_erreur_squelette' => 'Errore sul sito',
721
-	'zbug_inversion_ordre_inexistant' => 'inversione di un ordine non esistente',
722
-	'zbug_pagination_sans_critere' => '#PAGINATION senza criterio {pagination} oppure usato in un ciclo ricorsivo',
723
-	'zbug_parametres_inclus_incorrects' => 'Parametri di inclusione non corretti',
724
-	'zbug_profile' => 'Tempo di elaborazione: @time@',
725
-	'zbug_resultat' => 'risultato',
726
-	'zbug_serveur_indefini' => 'server SQL non definito',
727
-	'zbug_statistiques' => 'Statistiche delle query SQL in ordine di durata',
728
-	'zbug_table_inconnue' => 'Tabella SQL « @table@ » sconosciuta',
729
-	'zxml_connus_attributs' => 'attributi conosciuti',
730
-	'zxml_de' => 'di',
731
-	'zxml_inconnu_attribut' => 'attributo sconosciuto',
732
-	'zxml_inconnu_balise' => 'segnaposto sconosciuto',
733
-	'zxml_inconnu_entite' => 'entità sconosciuta',
734
-	'zxml_inconnu_id' => 'ID sconosciuto',
735
-	'zxml_mais_de' => 'ma di',
736
-	'zxml_non_conforme' => 'non è conforme al motivo',
737
-	'zxml_non_fils' => 'non è un figlio di',
738
-	'zxml_nonvide_balise' => 'segnaposto non vuoto',
739
-	'zxml_obligatoire_attribut' => 'attributo obbligatorio ma assente in',
740
-	'zxml_succession_fils_incorrecte' => 'successione dei figli non corretta',
741
-	'zxml_survoler' => 'passarci sopra col mouse per vedere i corretti',
742
-	'zxml_valeur_attribut' => 'valore dell’attributo',
743
-	'zxml_vide_balise' => 'tag vuoto',
744
-	'zxml_vu' => 'visto in precedenza'
694
+    // Z
695
+    'zbug_balise_b_aval' => ': ciclo B deve precedere ciclo BOUCLE',
696
+    'zbug_balise_inexistante' => 'errore @from@: il tag #@balise@ non esiste ',
697
+    'zbug_balise_sans_argument' => 'Argomento mancante nel tag @balise@',
698
+    'zbug_boucle' => 'ciclo',
699
+    'zbug_boucle_recursive_undef' => 'ciclo ricorsivo non definito',
700
+    'zbug_calcul' => 'calcolo',
701
+    'zbug_champ_hors_boucle' => 'Campo @champ@ fuori dal ciclo',
702
+    'zbug_champ_hors_critere' => 'Il campo @champ@ non rispetta il criterio @critere@',
703
+    'zbug_champ_hors_motif' => 'Campo @champ@ fuori da un contesto @motif@',
704
+    'zbug_code' => 'codice',
705
+    'zbug_critere_inconnu' => 'criterio sconosciuto @critere@',
706
+    'zbug_critere_sur_table_sans_cle_primaire' => '{@critere@} su una tabella senza una chiave primaria atomica',
707
+    'zbug_distant_interdit' => 'esterno non accessibile',
708
+    'zbug_doublon_table_sans_cle_primaire' => 'doppioni su una tabella senza chiave primaria atomica',
709
+    'zbug_doublon_table_sans_index' => 'doppioni su una tabella senza indice',
710
+    'zbug_erreur_boucle_double' => 'BOUCLE@id@: doppia definizione',
711
+    'zbug_erreur_boucle_fermant' => 'BOUCLE@id@: chiusura tag mancante',
712
+    'zbug_erreur_boucle_syntaxe' => 'Sintassi del ciclo errata',
713
+    'zbug_erreur_compilation' => 'Errore di compilazione',
714
+    'zbug_erreur_execution_page' => 'errore di esecuzione della pagina',
715
+    'zbug_erreur_filtre' => 'Errore : filtro <b>« @filtre@ »</b> non esistente',
716
+    'zbug_erreur_filtre_nbarg_min' => 'Filtro@filtre@: argomento(i) @nb@ mancante(i)',
717
+    'zbug_erreur_meme_parent' => 'il criterio {meme_parent} si applica unicamente ai cicli (FORUMS) o (RUBRIQUES)',
718
+    'zbug_erreur_squelette' => 'Errore/i nel modello di layout',
719
+    'zbug_hors_compilation' => 'Fuori Compilazione',
720
+    'zbug_info_erreur_squelette' => 'Errore sul sito',
721
+    'zbug_inversion_ordre_inexistant' => 'inversione di un ordine non esistente',
722
+    'zbug_pagination_sans_critere' => '#PAGINATION senza criterio {pagination} oppure usato in un ciclo ricorsivo',
723
+    'zbug_parametres_inclus_incorrects' => 'Parametri di inclusione non corretti',
724
+    'zbug_profile' => 'Tempo di elaborazione: @time@',
725
+    'zbug_resultat' => 'risultato',
726
+    'zbug_serveur_indefini' => 'server SQL non definito',
727
+    'zbug_statistiques' => 'Statistiche delle query SQL in ordine di durata',
728
+    'zbug_table_inconnue' => 'Tabella SQL « @table@ » sconosciuta',
729
+    'zxml_connus_attributs' => 'attributi conosciuti',
730
+    'zxml_de' => 'di',
731
+    'zxml_inconnu_attribut' => 'attributo sconosciuto',
732
+    'zxml_inconnu_balise' => 'segnaposto sconosciuto',
733
+    'zxml_inconnu_entite' => 'entità sconosciuta',
734
+    'zxml_inconnu_id' => 'ID sconosciuto',
735
+    'zxml_mais_de' => 'ma di',
736
+    'zxml_non_conforme' => 'non è conforme al motivo',
737
+    'zxml_non_fils' => 'non è un figlio di',
738
+    'zxml_nonvide_balise' => 'segnaposto non vuoto',
739
+    'zxml_obligatoire_attribut' => 'attributo obbligatorio ma assente in',
740
+    'zxml_succession_fils_incorrecte' => 'successione dei figli non corretta',
741
+    'zxml_survoler' => 'passarci sopra col mouse per vedere i corretti',
742
+    'zxml_valeur_attribut' => 'valore dell’attributo',
743
+    'zxml_vide_balise' => 'tag vuoto',
744
+    'zxml_vu' => 'visto in precedenza'
745 745
 );
Please login to merge, or discard this patch.
ecrire/lang/ecrire_ar.php 1 patch
Indentation   +841 added lines, -841 removed lines patch added patch discarded remove patch
@@ -4,438 +4,438 @@  discard block
 block discarded – undo
4 4
 // ** ne pas modifier le fichier **
5 5
 
6 6
 if (!defined('_ECRIRE_INC_VERSION')) {
7
-	return;
7
+    return;
8 8
 }
9 9
 
10 10
 $GLOBALS[$GLOBALS['idx_lang']] = array(
11 11
 
12
-	// A
13
-	'activer_plugin' => 'تفعيل الملحق',
14
-	'affichage' => 'عرض',
15
-	'aide_non_disponible' => 'هذا القسم من التعليمات الفورية غير متوافر حالياً بهذه اللغة.',
16
-	'annuler_recherche' => 'إلغاء البحث',
17
-	'auteur' => 'المؤلف:',
18
-	'avis_acces_interdit' => 'الدخول محظور',
19
-	'avis_acces_interdit_prive' => 'ليس لديكم الأذونات الكافية للدخول الى الصفح <b>@exec@</b>.',
20
-	'avis_article_modifie' => 'تحذير، @nom_auteur_modif@ عمل على هذا المقال منذ @date_diff@ دقيقة',
21
-	'avis_aucun_resultat' => 'لا توجد نتائج.',
22
-	'avis_base_inaccessible' => 'لا يمكن الاتصال بقاعدة بيانات @base@.',
23
-	'avis_chemin_invalide_1' => 'لا يبدو المسار',
24
-	'avis_chemin_invalide_2' => 'الذي حددته صالحاً. الرجاء العودة الى الصفحة السابقة والتأكد من المعلومات المدخلة. والتأكد من المعلومات المدخلة.',
25
-	'avis_connexion_echec_1' => 'فشل الاتصال بقاعدة البيانات.',
26
-	'avis_connexion_echec_2' => 'عد الى الصفحة السابقة وتأكد من صحة المعلومات التي أدخلتها.',
27
-	'avis_connexion_echec_3' => '<b>ملاحظة</b> في العديد من اجهزة الخدمة، عليك <b>بطلب</b> تفعيل الدخول الى قاعدة البيانات قبل التمكن من استخدامها. اذا لم تتمكن من الاتصال بالقاعدة، تأكد من انك نفذت هذه الخطوة.',
28
-	'avis_connexion_erreur_creer_base' => 'لم يتم إنشاء قاعدة البيانات',
29
-	'avis_connexion_erreur_fichier_cle_manquant_1' => 'المشرف على الموقع هو الذي ينفذ التثبيت مع نسخة احتياطية للمفاتيح وكلمة السر الخاصة به ',
30
-	'avis_connexion_erreur_fichier_cle_manquant_2' => 'المشرف على الموقع هو الذي ينفذ التثبيت مع نسخة احتياطية للمفاتيح',
31
-	'avis_connexion_erreur_nom_base' => 'لا يجب ان يحتوي اسم القاعدة الا احرف وأرقام',
32
-	'avis_connexion_ldap_echec_1' => 'الاتصال بخادم LDAP فشل.',
33
-	'avis_connexion_ldap_echec_2' => 'عد الى الصفحة السابقة وتأكد من صحة المعلومات التي أدخلتها.',
34
-	'avis_connexion_ldap_echec_3' => 'وإلا، لا تستخدم دعم LDAP لجلب المستخدمين.',
35
-	'avis_deplacement_rubrique' => 'تحذير! يحتوي هذا القسم على @contient_breves@ خبر@scb@: إذا قمت بنقله، الرجاء تأشير هذا الخيار لتأكيد طلبك.',
36
-	'avis_erreur_connexion_mysql' => 'خطأ اتصالي SQL',
37
-	'avis_erreur_creation_compte' => 'فشل خلال تأصيل الحساب',
38
-	'avis_espace_interdit' => '<b>مجال ممنوع</b> <div>SPIP مثبت مسبقاً.</div>',
39
-	'avis_lecture_noms_bases_1' => 'لم يتمكن المثبت من قراءة أسماء قواعد البيانات المثبتة.',
40
-	'avis_lecture_noms_bases_2' => 'إما لا توجد قاعدة بيانات متوافرة أو تم ايقاف وظيفة عرض قواعد البيانات
12
+    // A
13
+    'activer_plugin' => 'تفعيل الملحق',
14
+    'affichage' => 'عرض',
15
+    'aide_non_disponible' => 'هذا القسم من التعليمات الفورية غير متوافر حالياً بهذه اللغة.',
16
+    'annuler_recherche' => 'إلغاء البحث',
17
+    'auteur' => 'المؤلف:',
18
+    'avis_acces_interdit' => 'الدخول محظور',
19
+    'avis_acces_interdit_prive' => 'ليس لديكم الأذونات الكافية للدخول الى الصفح <b>@exec@</b>.',
20
+    'avis_article_modifie' => 'تحذير، @nom_auteur_modif@ عمل على هذا المقال منذ @date_diff@ دقيقة',
21
+    'avis_aucun_resultat' => 'لا توجد نتائج.',
22
+    'avis_base_inaccessible' => 'لا يمكن الاتصال بقاعدة بيانات @base@.',
23
+    'avis_chemin_invalide_1' => 'لا يبدو المسار',
24
+    'avis_chemin_invalide_2' => 'الذي حددته صالحاً. الرجاء العودة الى الصفحة السابقة والتأكد من المعلومات المدخلة. والتأكد من المعلومات المدخلة.',
25
+    'avis_connexion_echec_1' => 'فشل الاتصال بقاعدة البيانات.',
26
+    'avis_connexion_echec_2' => 'عد الى الصفحة السابقة وتأكد من صحة المعلومات التي أدخلتها.',
27
+    'avis_connexion_echec_3' => '<b>ملاحظة</b> في العديد من اجهزة الخدمة، عليك <b>بطلب</b> تفعيل الدخول الى قاعدة البيانات قبل التمكن من استخدامها. اذا لم تتمكن من الاتصال بالقاعدة، تأكد من انك نفذت هذه الخطوة.',
28
+    'avis_connexion_erreur_creer_base' => 'لم يتم إنشاء قاعدة البيانات',
29
+    'avis_connexion_erreur_fichier_cle_manquant_1' => 'المشرف على الموقع هو الذي ينفذ التثبيت مع نسخة احتياطية للمفاتيح وكلمة السر الخاصة به ',
30
+    'avis_connexion_erreur_fichier_cle_manquant_2' => 'المشرف على الموقع هو الذي ينفذ التثبيت مع نسخة احتياطية للمفاتيح',
31
+    'avis_connexion_erreur_nom_base' => 'لا يجب ان يحتوي اسم القاعدة الا احرف وأرقام',
32
+    'avis_connexion_ldap_echec_1' => 'الاتصال بخادم LDAP فشل.',
33
+    'avis_connexion_ldap_echec_2' => 'عد الى الصفحة السابقة وتأكد من صحة المعلومات التي أدخلتها.',
34
+    'avis_connexion_ldap_echec_3' => 'وإلا، لا تستخدم دعم LDAP لجلب المستخدمين.',
35
+    'avis_deplacement_rubrique' => 'تحذير! يحتوي هذا القسم على @contient_breves@ خبر@scb@: إذا قمت بنقله، الرجاء تأشير هذا الخيار لتأكيد طلبك.',
36
+    'avis_erreur_connexion_mysql' => 'خطأ اتصالي SQL',
37
+    'avis_erreur_creation_compte' => 'فشل خلال تأصيل الحساب',
38
+    'avis_espace_interdit' => '<b>مجال ممنوع</b> <div>SPIP مثبت مسبقاً.</div>',
39
+    'avis_lecture_noms_bases_1' => 'لم يتمكن المثبت من قراءة أسماء قواعد البيانات المثبتة.',
40
+    'avis_lecture_noms_bases_2' => 'إما لا توجد قاعدة بيانات متوافرة أو تم ايقاف وظيفة عرض قواعد البيانات
41 41
 لأسباب أمنية (هكذا الحال لدى العديد من المضيفين).',
42
-	'avis_lecture_noms_bases_3' => 'إذا كانت الحال الثانية صحيحة، قد يكون هناك قاعدة بيانات تحمل إسم معرّف الدخول لديك يمكن استخدامها:',
43
-	'avis_non_acces_page' => 'لا تملك إمتياز الدخول الى هذه الصفحة.',
44
-	'avis_operation_echec' => 'العملية فشلت.',
45
-	'avis_operation_impossible' => 'عملية غير ممكنة',
46
-	'avis_suppression_base' => 'تحذير، حذف البيانات لا يمكن التراجع عنه',
42
+    'avis_lecture_noms_bases_3' => 'إذا كانت الحال الثانية صحيحة، قد يكون هناك قاعدة بيانات تحمل إسم معرّف الدخول لديك يمكن استخدامها:',
43
+    'avis_non_acces_page' => 'لا تملك إمتياز الدخول الى هذه الصفحة.',
44
+    'avis_operation_echec' => 'العملية فشلت.',
45
+    'avis_operation_impossible' => 'عملية غير ممكنة',
46
+    'avis_suppression_base' => 'تحذير، حذف البيانات لا يمكن التراجع عنه',
47 47
 
48
-	// B
49
-	'bouton_acces_ldap' => 'إضافة الوصول الى LDAP',
50
-	'bouton_ajouter' => 'إضافة',
51
-	'bouton_annuler' => 'الغاء',
52
-	'bouton_cache_activer' => 'إعادة تشغيل الذاكرة المخبأة',
53
-	'bouton_cache_desactiver' => 'إيقاف الذاكرة المخبأة مؤقتاً',
54
-	'bouton_demande_publication' => 'طلب نشر هذا المقال',
55
-	'bouton_desactive_tout' => 'تعطيل الكل',
56
-	'bouton_desinstaller' => 'إزالة التثبيت',
57
-	'bouton_effacer_tout' => 'حذف الكل',
58
-	'bouton_envoyer_message' => 'صيغة نهائية : إرسال',
59
-	'bouton_fermer' => 'إغلاق',
60
-	'bouton_mettre_a_jour_base' => 'تحديث قاعدة البيانات',
61
-	'bouton_modifier' => 'تغيير',
62
-	'bouton_radio_afficher' => 'إظهار',
63
-	'bouton_radio_apparaitre_liste_redacteurs_connectes' => 'الظهور في قائمة المحررين المتصلين',
64
-	'bouton_radio_envoi_annonces_adresse' => 'إرسال الإعلانات الى العنوان:',
65
-	'bouton_radio_envoi_liste_nouveautes' => 'إرسال قائمة بالأخبار',
66
-	'bouton_radio_non_apparaitre_liste_redacteurs_connectes' => 'عدم الظهور في قائمة المحررين',
67
-	'bouton_radio_non_envoi_annonces_editoriales' => 'عدم إرسال أي إعلان تحرير',
68
-	'bouton_redirection' => 'إعادة توجيه',
69
-	'bouton_reinitialiser_aux_valeurs_par_defaut' => 'إعادة التأصيل الى القيم القياسية',
70
-	'bouton_relancer_inscription' => 'إعادة تشغيل التسجيل',
71
-	'bouton_relancer_inscriptions' => 'إعادة تشغيل التسجيلات',
72
-	'bouton_relancer_installation' => 'إعادة إطلاق عملية التثبيت',
73
-	'bouton_reset_password' => 'إنشاء كلمة سر جديدة وإرسالها بالبريد الإلكتروني',
74
-	'bouton_suivant' => 'التالي',
75
-	'bouton_tenter_recuperation' => 'محاولة إصلاح',
76
-	'bouton_test_proxy' => 'اختبار الجهاز الوكيل',
77
-	'bouton_vider_cache' => 'تفريغ ذاكرة كاش',
48
+    // B
49
+    'bouton_acces_ldap' => 'إضافة الوصول الى LDAP',
50
+    'bouton_ajouter' => 'إضافة',
51
+    'bouton_annuler' => 'الغاء',
52
+    'bouton_cache_activer' => 'إعادة تشغيل الذاكرة المخبأة',
53
+    'bouton_cache_desactiver' => 'إيقاف الذاكرة المخبأة مؤقتاً',
54
+    'bouton_demande_publication' => 'طلب نشر هذا المقال',
55
+    'bouton_desactive_tout' => 'تعطيل الكل',
56
+    'bouton_desinstaller' => 'إزالة التثبيت',
57
+    'bouton_effacer_tout' => 'حذف الكل',
58
+    'bouton_envoyer_message' => 'صيغة نهائية : إرسال',
59
+    'bouton_fermer' => 'إغلاق',
60
+    'bouton_mettre_a_jour_base' => 'تحديث قاعدة البيانات',
61
+    'bouton_modifier' => 'تغيير',
62
+    'bouton_radio_afficher' => 'إظهار',
63
+    'bouton_radio_apparaitre_liste_redacteurs_connectes' => 'الظهور في قائمة المحررين المتصلين',
64
+    'bouton_radio_envoi_annonces_adresse' => 'إرسال الإعلانات الى العنوان:',
65
+    'bouton_radio_envoi_liste_nouveautes' => 'إرسال قائمة بالأخبار',
66
+    'bouton_radio_non_apparaitre_liste_redacteurs_connectes' => 'عدم الظهور في قائمة المحررين',
67
+    'bouton_radio_non_envoi_annonces_editoriales' => 'عدم إرسال أي إعلان تحرير',
68
+    'bouton_redirection' => 'إعادة توجيه',
69
+    'bouton_reinitialiser_aux_valeurs_par_defaut' => 'إعادة التأصيل الى القيم القياسية',
70
+    'bouton_relancer_inscription' => 'إعادة تشغيل التسجيل',
71
+    'bouton_relancer_inscriptions' => 'إعادة تشغيل التسجيلات',
72
+    'bouton_relancer_installation' => 'إعادة إطلاق عملية التثبيت',
73
+    'bouton_reset_password' => 'إنشاء كلمة سر جديدة وإرسالها بالبريد الإلكتروني',
74
+    'bouton_suivant' => 'التالي',
75
+    'bouton_tenter_recuperation' => 'محاولة إصلاح',
76
+    'bouton_test_proxy' => 'اختبار الجهاز الوكيل',
77
+    'bouton_vider_cache' => 'تفريغ ذاكرة كاش',
78 78
 
79
-	// C
80
-	'cache_modifiable_webmestre' => 'يتم تعديل هذه القيمة من قبل مسؤول الموقع.',
81
-	'calendrier_synchro' => 'اذا كنت تستخدم برنامج ادارة مواعيد يتوافق مع <b>iCal</b>، يمكنك ان تطابقه مع نشاط هذا الموقع التحريري.',
82
-	'config_activer_champs' => 'تفعيل الحقول التالية',
83
-	'config_choix_base_sup' => 'تحديد قاعدة في هذا الخادم',
84
-	'config_erreur_base_sup' => 'لا يمكن لنظام SPIP الوصول الى لائحة القواعد المتاحة',
85
-	'config_info_base_sup' => 'اذا كان لديك قواعد بيانات اخرى لاستفسارها عبر SPIP، بواسطة خادم SQL الخاص به او بواسطة خادم اخر، تتيح لك الاستمارة ادناه بالإعلان عن تلك القواعد. اذا تركت حقولاً فارغة سيتم استخدام معرّفات الاتصال بقاعدة البيانات الأساسية.',
86
-	'config_info_base_sup_disponibles' => 'قواعد اضافية يمكن استفسارها:',
87
-	'config_info_enregistree' => 'تم حفظ الإعداد الجديد',
88
-	'config_info_logos' => 'اي عنصر من الموقع يمكن ان يملك رمزاً مثل «رمز الحوم» ',
89
-	'config_info_logos_utiliser' => 'استخدام الرموز',
90
-	'config_info_logos_utiliser_non' => 'عدم استخدام الرموز',
91
-	'config_info_logos_utiliser_survol' => 'استخدام رموز الحوم',
92
-	'config_info_logos_utiliser_survol_non' => 'عدم استخدام رموز الحوم',
93
-	'config_info_redirection' => 'بتفعيل هذا الخيار، يمكنك انشاء مقالات افتراضية تشكل مرجعاً بيسطاً لمقالات منشورة في مواقع اخرى او خارج SPIP.',
94
-	'config_redirection' => 'مقالات افتراضية',
95
-	'config_titre_base_sup' => 'الاعلان عن قاعدة اضافية',
96
-	'config_titre_base_sup_choix' => 'اختيار قاعدة اضافية',
97
-	'connexion_ldap' => 'اتصال:',
98
-	'creer_et_associer_un_auteur' => 'إنشاء مؤلف وربطه',
79
+    // C
80
+    'cache_modifiable_webmestre' => 'يتم تعديل هذه القيمة من قبل مسؤول الموقع.',
81
+    'calendrier_synchro' => 'اذا كنت تستخدم برنامج ادارة مواعيد يتوافق مع <b>iCal</b>، يمكنك ان تطابقه مع نشاط هذا الموقع التحريري.',
82
+    'config_activer_champs' => 'تفعيل الحقول التالية',
83
+    'config_choix_base_sup' => 'تحديد قاعدة في هذا الخادم',
84
+    'config_erreur_base_sup' => 'لا يمكن لنظام SPIP الوصول الى لائحة القواعد المتاحة',
85
+    'config_info_base_sup' => 'اذا كان لديك قواعد بيانات اخرى لاستفسارها عبر SPIP، بواسطة خادم SQL الخاص به او بواسطة خادم اخر، تتيح لك الاستمارة ادناه بالإعلان عن تلك القواعد. اذا تركت حقولاً فارغة سيتم استخدام معرّفات الاتصال بقاعدة البيانات الأساسية.',
86
+    'config_info_base_sup_disponibles' => 'قواعد اضافية يمكن استفسارها:',
87
+    'config_info_enregistree' => 'تم حفظ الإعداد الجديد',
88
+    'config_info_logos' => 'اي عنصر من الموقع يمكن ان يملك رمزاً مثل «رمز الحوم» ',
89
+    'config_info_logos_utiliser' => 'استخدام الرموز',
90
+    'config_info_logos_utiliser_non' => 'عدم استخدام الرموز',
91
+    'config_info_logos_utiliser_survol' => 'استخدام رموز الحوم',
92
+    'config_info_logos_utiliser_survol_non' => 'عدم استخدام رموز الحوم',
93
+    'config_info_redirection' => 'بتفعيل هذا الخيار، يمكنك انشاء مقالات افتراضية تشكل مرجعاً بيسطاً لمقالات منشورة في مواقع اخرى او خارج SPIP.',
94
+    'config_redirection' => 'مقالات افتراضية',
95
+    'config_titre_base_sup' => 'الاعلان عن قاعدة اضافية',
96
+    'config_titre_base_sup_choix' => 'اختيار قاعدة اضافية',
97
+    'connexion_ldap' => 'اتصال:',
98
+    'creer_et_associer_un_auteur' => 'إنشاء مؤلف وربطه',
99 99
 
100
-	// D
101
-	'date_mot_heures' => 'ساعات',
100
+    // D
101
+    'date_mot_heures' => 'ساعات',
102 102
 
103
-	// E
104
-	'ecran_connexion_couleur_principale' => 'اللون الأساسي',
105
-	'ecran_connexion_image_fond' => 'صورة الخلفية',
106
-	'ecran_connexion_image_fond_explication' => 'استخدام صورة (تنسيق JPEG، ١٩٢٠ x ١٠٨٠ نقطة)',
107
-	'ecran_connexion_image_revenir_couleur_defaut' => 'عودة الى اللون الافتراضي',
108
-	'ecran_connexion_titre' => 'شاشة الدخول',
109
-	'ecran_securite' => '+ شاشة الأمان @version@',
110
-	'email' => 'البريد الالكتروني',
111
-	'email_2' => 'البريد الالكتروني :',
112
-	'en_savoir_plus' => 'مزيد من المعلومات',
113
-	'entree_adresse_annuaire' => 'عنوان الدليل',
114
-	'entree_adresse_email' => 'عنوانك الالكتروني',
115
-	'entree_adresse_email_2' => 'عنوان البريد الالكتروني',
116
-	'entree_base_donnee_1' => 'عنوان قاعدة البيانات',
117
-	'entree_base_donnee_2' => '(غالباً ما يتطابق هذا العنوان مع عنوان موقعك وأحياناً قد يكون عبارة «localhost» وأحياناً أخرى يترك فارغاً.)',
118
-	'entree_biographie' => 'سيرتك في بضع كلمات.',
119
-	'entree_chemin_acces' => '<b>إدخال</b> المسار:',
120
-	'entree_cle_pgp' => 'مفتاح PGP لديك',
121
-	'entree_cle_pgp_2' => 'مفتاح PGP',
122
-	'entree_contenu_rubrique' => '(محتوى القسم ببضع كلمات.)',
123
-	'entree_identifiants_connexion' => 'بيانات إتصالك...',
124
-	'entree_identifiants_connexion_2' => 'بيانات الاتصال',
125
-	'entree_informations_connexion_ldap' => 'الرجاء إدخال معلومات الاتصال بدليل LDAP في هذه الاستمارة.
103
+    // E
104
+    'ecran_connexion_couleur_principale' => 'اللون الأساسي',
105
+    'ecran_connexion_image_fond' => 'صورة الخلفية',
106
+    'ecran_connexion_image_fond_explication' => 'استخدام صورة (تنسيق JPEG، ١٩٢٠ x ١٠٨٠ نقطة)',
107
+    'ecran_connexion_image_revenir_couleur_defaut' => 'عودة الى اللون الافتراضي',
108
+    'ecran_connexion_titre' => 'شاشة الدخول',
109
+    'ecran_securite' => '+ شاشة الأمان @version@',
110
+    'email' => 'البريد الالكتروني',
111
+    'email_2' => 'البريد الالكتروني :',
112
+    'en_savoir_plus' => 'مزيد من المعلومات',
113
+    'entree_adresse_annuaire' => 'عنوان الدليل',
114
+    'entree_adresse_email' => 'عنوانك الالكتروني',
115
+    'entree_adresse_email_2' => 'عنوان البريد الالكتروني',
116
+    'entree_base_donnee_1' => 'عنوان قاعدة البيانات',
117
+    'entree_base_donnee_2' => '(غالباً ما يتطابق هذا العنوان مع عنوان موقعك وأحياناً قد يكون عبارة «localhost» وأحياناً أخرى يترك فارغاً.)',
118
+    'entree_biographie' => 'سيرتك في بضع كلمات.',
119
+    'entree_chemin_acces' => '<b>إدخال</b> المسار:',
120
+    'entree_cle_pgp' => 'مفتاح PGP لديك',
121
+    'entree_cle_pgp_2' => 'مفتاح PGP',
122
+    'entree_contenu_rubrique' => '(محتوى القسم ببضع كلمات.)',
123
+    'entree_identifiants_connexion' => 'بيانات إتصالك...',
124
+    'entree_identifiants_connexion_2' => 'بيانات الاتصال',
125
+    'entree_informations_connexion_ldap' => 'الرجاء إدخال معلومات الاتصال بدليل LDAP في هذه الاستمارة.
126 126
 من المفترض أن تكون حصلت على هذه المعلومات من المسؤول عن نظامك
127 127
 أو شبكتك.',
128
-	'entree_infos_perso' => 'عرّف بنفسك :',
129
-	'entree_infos_perso_2' => 'من هو المؤلف؟',
130
-	'entree_interieur_rubrique' => 'في القسم:	',
131
-	'entree_liens_sites' => '<b>وصلة هايبرتكست<b> (مرجع، موقع للزيارة...)',
132
-	'entree_login' => 'معرّف دخولك',
133
-	'entree_login_connexion_1' => 'معرّف الاتصال',
134
-	'entree_login_connexion_2' => '(أحياناً يتطابق مع معرّف دخول بروتوكول FTP  وأحياناً أخرى يترك فارغاً)',
135
-	'entree_mot_passe' => 'كلمة سرك',
136
-	'entree_mot_passe_1' => 'كلمة سر الاتصال',
137
-	'entree_mot_passe_2' => '(أحياناً يتطابق مع كلمة سر بروتوكول FTPوأحياناً أخرى يترك فارغاً)',
138
-	'entree_nom_fichier' => 'الرجاء إدخال اسم الملف @texte_compresse@:',
139
-	'entree_nom_pseudo' => 'الإسم او اللقب',
140
-	'entree_nom_pseudo_1' => '(الإسم او اللقب)',
141
-	'entree_nom_pseudo_2' => 'الاسم او اللقب',
142
-	'entree_nom_site' => 'إسم موقعك',
143
-	'entree_nom_site_2' => 'اسم موقع المؤلف',
144
-	'entree_nouveau_passe' => 'كلمة السر الجديدة',
145
-	'entree_passe_ldap' => 'كلمة السر',
146
-	'entree_port_annuaire' => 'رقم منفذ الدليل',
147
-	'entree_signature' => 'التوقيع',
148
-	'entree_titre_obligatoire' => '<b>العنوان</b> [إجباري]<br />',
149
-	'entree_url' => 'عنوان موقعك',
150
-	'entree_url_2' => 'عنوان الموقع',
151
-	'erreur_connect_deja_existant' => 'يوجد حالياً جهاز خدمة بهذا الاسم',
152
-	'erreur_contenu_suspect' => 'تركيبة النص غير سليمة ',
153
-	'erreur_email_deja_existant' => 'هذا العنوان الالكتروني مسجل مسبقاً',
154
-	'erreur_nom_connect_incorrect' => 'هذا الاسم لجهاز الخدمة غير مسموح به',
155
-	'erreur_plugin_attribut_balise_manquant' => 'الخاصية @attribut@ غير موجودة في علامة @balise@.',
156
-	'erreur_plugin_desinstalation_echouee' => 'فشل الغاء تثبيت الملحق. ولكن يمكنك ايقافه.',
157
-	'erreur_plugin_fichier_absent' => 'ملف غير موجود',
158
-	'erreur_plugin_fichier_def_absent' => 'ملف اعداد غير موجود',
159
-	'erreur_plugin_nom_fonction_interdit' => 'اسم دالة غير مسموح به:',
160
-	'erreur_plugin_nom_manquant' => 'اسم الملحق غير الموجود',
161
-	'erreur_plugin_prefix_manquant' => 'حقل تسمية الملحق غير محدد',
162
-	'erreur_plugin_tag_plugin_absent' => '&lt;plugin&gt; غير موجود في ملف التعريف',
163
-	'erreur_plugin_version_manquant' => 'اصدار الملحق غير موجود',
164
-	'erreur_type_fichier' => 'نوع ملفات غير صحيح',
128
+    'entree_infos_perso' => 'عرّف بنفسك :',
129
+    'entree_infos_perso_2' => 'من هو المؤلف؟',
130
+    'entree_interieur_rubrique' => 'في القسم:	',
131
+    'entree_liens_sites' => '<b>وصلة هايبرتكست<b> (مرجع، موقع للزيارة...)',
132
+    'entree_login' => 'معرّف دخولك',
133
+    'entree_login_connexion_1' => 'معرّف الاتصال',
134
+    'entree_login_connexion_2' => '(أحياناً يتطابق مع معرّف دخول بروتوكول FTP  وأحياناً أخرى يترك فارغاً)',
135
+    'entree_mot_passe' => 'كلمة سرك',
136
+    'entree_mot_passe_1' => 'كلمة سر الاتصال',
137
+    'entree_mot_passe_2' => '(أحياناً يتطابق مع كلمة سر بروتوكول FTPوأحياناً أخرى يترك فارغاً)',
138
+    'entree_nom_fichier' => 'الرجاء إدخال اسم الملف @texte_compresse@:',
139
+    'entree_nom_pseudo' => 'الإسم او اللقب',
140
+    'entree_nom_pseudo_1' => '(الإسم او اللقب)',
141
+    'entree_nom_pseudo_2' => 'الاسم او اللقب',
142
+    'entree_nom_site' => 'إسم موقعك',
143
+    'entree_nom_site_2' => 'اسم موقع المؤلف',
144
+    'entree_nouveau_passe' => 'كلمة السر الجديدة',
145
+    'entree_passe_ldap' => 'كلمة السر',
146
+    'entree_port_annuaire' => 'رقم منفذ الدليل',
147
+    'entree_signature' => 'التوقيع',
148
+    'entree_titre_obligatoire' => '<b>العنوان</b> [إجباري]<br />',
149
+    'entree_url' => 'عنوان موقعك',
150
+    'entree_url_2' => 'عنوان الموقع',
151
+    'erreur_connect_deja_existant' => 'يوجد حالياً جهاز خدمة بهذا الاسم',
152
+    'erreur_contenu_suspect' => 'تركيبة النص غير سليمة ',
153
+    'erreur_email_deja_existant' => 'هذا العنوان الالكتروني مسجل مسبقاً',
154
+    'erreur_nom_connect_incorrect' => 'هذا الاسم لجهاز الخدمة غير مسموح به',
155
+    'erreur_plugin_attribut_balise_manquant' => 'الخاصية @attribut@ غير موجودة في علامة @balise@.',
156
+    'erreur_plugin_desinstalation_echouee' => 'فشل الغاء تثبيت الملحق. ولكن يمكنك ايقافه.',
157
+    'erreur_plugin_fichier_absent' => 'ملف غير موجود',
158
+    'erreur_plugin_fichier_def_absent' => 'ملف اعداد غير موجود',
159
+    'erreur_plugin_nom_fonction_interdit' => 'اسم دالة غير مسموح به:',
160
+    'erreur_plugin_nom_manquant' => 'اسم الملحق غير الموجود',
161
+    'erreur_plugin_prefix_manquant' => 'حقل تسمية الملحق غير محدد',
162
+    'erreur_plugin_tag_plugin_absent' => '&lt;plugin&gt; غير موجود في ملف التعريف',
163
+    'erreur_plugin_version_manquant' => 'اصدار الملحق غير موجود',
164
+    'erreur_type_fichier' => 'نوع ملفات غير صحيح',
165 165
 
166
-	// H
167
-	'htaccess_a_simuler' => 'تحذير: إن إعداد خادم HTTP لديك يتجاهل ملفات @htaccess@. لتوفير أمان فعّال لموقعك، يجب تغيير الإعداد بخصوص هذه المسألة، او ان تكون قيم الثوابت @constantes@ (التي يمكن تحديدها في ملف mes_options.php) مجلدات من خارج @document_root@.',
168
-	'htaccess_inoperant' => 'htaccess غير فعّال',
166
+    // H
167
+    'htaccess_a_simuler' => 'تحذير: إن إعداد خادم HTTP لديك يتجاهل ملفات @htaccess@. لتوفير أمان فعّال لموقعك، يجب تغيير الإعداد بخصوص هذه المسألة، او ان تكون قيم الثوابت @constantes@ (التي يمكن تحديدها في ملف mes_options.php) مجلدات من خارج @document_root@.',
168
+    'htaccess_inoperant' => 'htaccess غير فعّال',
169 169
 
170
-	// I
171
-	'ical_info1' => 'تقدم هذه الصفحة وسائل عدة للاتصال بنشاط الموقع.',
172
-	'ical_info2' => 'لمزيد من المعلومات حول هذه التقنيات يمكنك زيارة <a href="@spipnet@">توثيق SPIP</a>.',
173
-	'ical_info_calendrier' => 'هناك روزتامتان تحت تصرفك. الاولى هي عبارة عن خريطة للموقع تعلن عن كل المقالات المنشورة. اما الثانية، فتحتوي على اعلانات التحرير اضافة الى احدث رسائلك الشخصية: وهي مخصصة لك يحميها مفتاح شخصي يمكنك تغييره في اي وقت يتجديد كلمة سرك.',
174
-	'ical_methode_http' => 'تحميل',
175
-	'ical_methode_webcal' => 'تزامن (webcal://)',
176
-	'ical_texte_js' => 'يتيح لك سطر جافاسكريبت واحد عرض المقالات الحديثة التي تم نشرها في اي موقع يخصك.',
177
-	'ical_texte_prive' => 'تعلمك هذه الروزنامة، المحصورة بالاستخدام الشخصي، بالنشاط التحريري الخاص في هذا الموقع (المهمات والمواعيد الشخصية والاخبار المقترحة...).',
178
-	'ical_texte_public' => 'تتيح لك هذه الروزنامة متابعة النشاط العمومي في هذا الموقع (المقالات والاخبار المنشورة).',
179
-	'ical_texte_rss' => 'يمكنك ترخيص جديد هذا الموقع من خلال اي معالج ملفات بتنسيق XML/RSS (اي RDF Site Summary). وهو ايضاً التنسيق الذي يسمح لـSPIP بقراءة احدث ما ينشر في مواقع اخرى وذلك باستخدام تنسيق تبادل متوافق (مواقع مرخصة). ',
180
-	'ical_titre_js' => 'جافاسكريبت',
181
-	'ical_titre_mailing' => 'القائمة البريدية',
182
-	'ical_titre_rss' => 'ملفات الترخيص',
183
-	'icone_accueil' => 'الأساسية',
184
-	'icone_activer_cookie' => 'وضع كعكة',
185
-	'icone_activite' => 'نشاط الموقع',
186
-	'icone_admin_plugin' => 'ادارة الملحقات',
187
-	'icone_administration' => 'صيانة',
188
-	'icone_afficher_auteurs' => 'إظهار المؤلفين',
189
-	'icone_afficher_visiteurs' => 'عرض الزوار',
190
-	'icone_arret_discussion' => 'إيقاف المشاركة في هذا النقاش',
191
-	'icone_calendrier' => 'الروزنامة',
192
-	'icone_configuration' => 'إعداد',
193
-	'icone_creer_auteur' => 'إضافة مؤلف جديد وإشراكه في هذا المقال',
194
-	'icone_creer_mot_cle' => 'إنشاء مفتاح جديد وربطه بهذا المقال',
195
-	'icone_creer_rubrique_2' => 'إنشاء قسم جديد',
196
-	'icone_developpement' => 'تطوير',
197
-	'icone_edition' => 'تحرير',
198
-	'icone_ma_langue' => 'لغتي',
199
-	'icone_mes_infos' => 'بياناتي',
200
-	'icone_mes_preferences' => 'تفضيلاتي',
201
-	'icone_modifier_article' => 'تعديل هذا المقال',
202
-	'icone_modifier_rubrique' => 'تعديل هذا القسم',
203
-	'icone_publication' => 'نشر',
204
-	'icone_relancer_signataire' => 'تذكير الموقع',
205
-	'icone_retour' => 'رجوع',
206
-	'icone_retour_article' => 'عودة إلى المقال',
207
-	'icone_squelette' => 'صفحات نموذجية',
208
-	'icone_suivi_publication' => 'متابعة النشر',
209
-	'icone_supprimer_cookie' => 'حذف الكعكة',
210
-	'icone_supprimer_rubrique' => 'حذف هذا القسم',
211
-	'icone_supprimer_signature' => 'حذف هذا التوقيع',
212
-	'icone_valider_signature' => 'التصديق على هذا التوقيع',
213
-	'image_administrer_rubrique' => 'يمكنك إدارة هذا القسم',
214
-	'impossible_modifier_login_auteur' => 'لا يمكن تغيير المعرّف.',
215
-	'impossible_modifier_pass_auteur' => 'لا يمكن تغيير كلمة السر.',
216
-	'info_1_article' => 'مقال واحد',
217
-	'info_1_auteur' => 'مؤلف واحد',
218
-	'info_1_message' => 'رسالة واحدة',
219
-	'info_1_mot_cle' => 'مفتاح واحد',
220
-	'info_1_rubrique' => 'قسم واحد',
221
-	'info_1_visiteur' => 'زائر واحد',
222
-	'info_activer_cookie' => 'يمكنك تفعيل <b>كعكة إدارية</b>، تتيح لك 
170
+    // I
171
+    'ical_info1' => 'تقدم هذه الصفحة وسائل عدة للاتصال بنشاط الموقع.',
172
+    'ical_info2' => 'لمزيد من المعلومات حول هذه التقنيات يمكنك زيارة <a href="@spipnet@">توثيق SPIP</a>.',
173
+    'ical_info_calendrier' => 'هناك روزتامتان تحت تصرفك. الاولى هي عبارة عن خريطة للموقع تعلن عن كل المقالات المنشورة. اما الثانية، فتحتوي على اعلانات التحرير اضافة الى احدث رسائلك الشخصية: وهي مخصصة لك يحميها مفتاح شخصي يمكنك تغييره في اي وقت يتجديد كلمة سرك.',
174
+    'ical_methode_http' => 'تحميل',
175
+    'ical_methode_webcal' => 'تزامن (webcal://)',
176
+    'ical_texte_js' => 'يتيح لك سطر جافاسكريبت واحد عرض المقالات الحديثة التي تم نشرها في اي موقع يخصك.',
177
+    'ical_texte_prive' => 'تعلمك هذه الروزنامة، المحصورة بالاستخدام الشخصي، بالنشاط التحريري الخاص في هذا الموقع (المهمات والمواعيد الشخصية والاخبار المقترحة...).',
178
+    'ical_texte_public' => 'تتيح لك هذه الروزنامة متابعة النشاط العمومي في هذا الموقع (المقالات والاخبار المنشورة).',
179
+    'ical_texte_rss' => 'يمكنك ترخيص جديد هذا الموقع من خلال اي معالج ملفات بتنسيق XML/RSS (اي RDF Site Summary). وهو ايضاً التنسيق الذي يسمح لـSPIP بقراءة احدث ما ينشر في مواقع اخرى وذلك باستخدام تنسيق تبادل متوافق (مواقع مرخصة). ',
180
+    'ical_titre_js' => 'جافاسكريبت',
181
+    'ical_titre_mailing' => 'القائمة البريدية',
182
+    'ical_titre_rss' => 'ملفات الترخيص',
183
+    'icone_accueil' => 'الأساسية',
184
+    'icone_activer_cookie' => 'وضع كعكة',
185
+    'icone_activite' => 'نشاط الموقع',
186
+    'icone_admin_plugin' => 'ادارة الملحقات',
187
+    'icone_administration' => 'صيانة',
188
+    'icone_afficher_auteurs' => 'إظهار المؤلفين',
189
+    'icone_afficher_visiteurs' => 'عرض الزوار',
190
+    'icone_arret_discussion' => 'إيقاف المشاركة في هذا النقاش',
191
+    'icone_calendrier' => 'الروزنامة',
192
+    'icone_configuration' => 'إعداد',
193
+    'icone_creer_auteur' => 'إضافة مؤلف جديد وإشراكه في هذا المقال',
194
+    'icone_creer_mot_cle' => 'إنشاء مفتاح جديد وربطه بهذا المقال',
195
+    'icone_creer_rubrique_2' => 'إنشاء قسم جديد',
196
+    'icone_developpement' => 'تطوير',
197
+    'icone_edition' => 'تحرير',
198
+    'icone_ma_langue' => 'لغتي',
199
+    'icone_mes_infos' => 'بياناتي',
200
+    'icone_mes_preferences' => 'تفضيلاتي',
201
+    'icone_modifier_article' => 'تعديل هذا المقال',
202
+    'icone_modifier_rubrique' => 'تعديل هذا القسم',
203
+    'icone_publication' => 'نشر',
204
+    'icone_relancer_signataire' => 'تذكير الموقع',
205
+    'icone_retour' => 'رجوع',
206
+    'icone_retour_article' => 'عودة إلى المقال',
207
+    'icone_squelette' => 'صفحات نموذجية',
208
+    'icone_suivi_publication' => 'متابعة النشر',
209
+    'icone_supprimer_cookie' => 'حذف الكعكة',
210
+    'icone_supprimer_rubrique' => 'حذف هذا القسم',
211
+    'icone_supprimer_signature' => 'حذف هذا التوقيع',
212
+    'icone_valider_signature' => 'التصديق على هذا التوقيع',
213
+    'image_administrer_rubrique' => 'يمكنك إدارة هذا القسم',
214
+    'impossible_modifier_login_auteur' => 'لا يمكن تغيير المعرّف.',
215
+    'impossible_modifier_pass_auteur' => 'لا يمكن تغيير كلمة السر.',
216
+    'info_1_article' => 'مقال واحد',
217
+    'info_1_auteur' => 'مؤلف واحد',
218
+    'info_1_message' => 'رسالة واحدة',
219
+    'info_1_mot_cle' => 'مفتاح واحد',
220
+    'info_1_rubrique' => 'قسم واحد',
221
+    'info_1_visiteur' => 'زائر واحد',
222
+    'info_activer_cookie' => 'يمكنك تفعيل <b>كعكة إدارية</b>، تتيح لك 
223 223
 التنقل بسهولة بين الموقع العمومي والمجال الخاص.',
224
-	'info_activer_menu_developpement' => 'عرض قائمة التطوير',
225
-	'info_admin_etre_webmestre' => 'إعطائي حقوق المشرف',
226
-	'info_admin_je_suis_webmestre' => 'أنا <b>مشرف</b>',
227
-	'info_admin_statuer_webmestre' => 'اعطاء حقوق مسؤول الموقع لهذا المدير',
228
-	'info_admin_webmestre' => 'هذا المدير هو <b>مسؤول الموقع</b>',
229
-	'info_administrateur' => 'مدير',
230
-	'info_administrateur_1' => 'مدير',
231
-	'info_administrateur_2' => 'الموقع (إستخدمه بحذر)',
232
-	'info_administrateur_site_01' => 'اذا كنت احد مدراء هذا الموقع، الرجاء',
233
-	'info_administrateur_site_02' => 'نقر هذه الوصلة',
234
-	'info_administrateurs' => 'مدراء',
235
-	'info_administrer_rubrique' => 'يمكنك إدارة هذا القسم',
236
-	'info_adresse' => 'الى العنوان:',
237
-	'info_adresse_desinscription' => 'عنوان حذف التسجيل :',
238
-	'info_adresse_url' => 'عنوان الموقع العمومي',
239
-	'info_afficher_par_nb' => 'عرض حسب',
240
-	'info_aide_en_ligne' => 'تعليمات SPIP الفورية',
241
-	'info_ajout_image' => 'عندما تضيف صوراً على شكل مستندات مربوطة بمقال ما،
224
+    'info_activer_menu_developpement' => 'عرض قائمة التطوير',
225
+    'info_admin_etre_webmestre' => 'إعطائي حقوق المشرف',
226
+    'info_admin_je_suis_webmestre' => 'أنا <b>مشرف</b>',
227
+    'info_admin_statuer_webmestre' => 'اعطاء حقوق مسؤول الموقع لهذا المدير',
228
+    'info_admin_webmestre' => 'هذا المدير هو <b>مسؤول الموقع</b>',
229
+    'info_administrateur' => 'مدير',
230
+    'info_administrateur_1' => 'مدير',
231
+    'info_administrateur_2' => 'الموقع (إستخدمه بحذر)',
232
+    'info_administrateur_site_01' => 'اذا كنت احد مدراء هذا الموقع، الرجاء',
233
+    'info_administrateur_site_02' => 'نقر هذه الوصلة',
234
+    'info_administrateurs' => 'مدراء',
235
+    'info_administrer_rubrique' => 'يمكنك إدارة هذا القسم',
236
+    'info_adresse' => 'الى العنوان:',
237
+    'info_adresse_desinscription' => 'عنوان حذف التسجيل :',
238
+    'info_adresse_url' => 'عنوان الموقع العمومي',
239
+    'info_afficher_par_nb' => 'عرض حسب',
240
+    'info_aide_en_ligne' => 'تعليمات SPIP الفورية',
241
+    'info_ajout_image' => 'عندما تضيف صوراً على شكل مستندات مربوطة بمقال ما،
242 242
 يمكن لـ SPIP ان ينشئ آلياً مصغرات عن
243 243
 الصور المدرجة. ويتيح ذلك مثلاً، إنشاء
244 244
 معرض صور او محفظة.',
245
-	'info_ajouter_rubrique' => 'إضافة قسم آخر الى الإدارة:',
246
-	'info_annonce_nouveautes' => 'إعلان عن آخر الأخبار',
247
-	'info_article' => 'مقال',
248
-	'info_article_2' => 'مقال',
249
-	'info_article_a_paraitre' => 'المقالات المؤجلة التي تنتظر النشر',
250
-	'info_articles_02' => 'مقال',
251
-	'info_articles_2' => 'المقالات',
252
-	'info_articles_auteur' => 'مقالات هذا المؤلف',
253
-	'info_articles_miens' => 'مقالاتي',
254
-	'info_articles_tous' => 'كل المقالات',
255
-	'info_articles_trouves' => 'المقالات التي عثر عليها',
256
-	'info_attente_validation' => 'مقالاتك المنتظرة التصديق',
257
-	'info_aucun_article' => 'لا يوجد مقالات',
258
-	'info_aucun_auteur' => 'لا يوجد مؤلفون',
259
-	'info_aucun_message' => 'لا توجد رسائل',
260
-	'info_aucun_rubrique' => 'لا توجد أقسام',
261
-	'info_aujourdhui' => 'اليوم:',
262
-	'info_auteur_gere_rubriques' => 'هذا المؤلف يدير الأقسام التالية:',
263
-	'info_auteur_gere_toutes_rubriques' => 'هذا المؤلف يدير <b>كل الأقسام</b>',
264
-	'info_auteur_gere_toutes_rubriques_2' => 'أدير <b>كل الأقسام</b>',
265
-	'info_auteurs' => 'المؤلفون',
266
-	'info_auteurs_par_tri' => 'المؤلفون@partri@',
267
-	'info_auteurs_trouves' => 'المؤلفون الذين عثر عليهم',
268
-	'info_authentification_externe' => 'التحقق الخارجي',
269
-	'info_avertissement' => 'تحذير',
270
-	'info_barre_outils' => 'مع شريط أدواته؟',
271
-	'info_base_installee' => '<b>تم تثبيت بنية قاعدة البيانات. ',
272
-	'info_bio' => 'السيرة',
273
-	'info_cache_desactive' => 'الذاكرة المخبأة متوقفة مؤقتاً.',
274
-	'info_chapeau' => 'المقدمة',
275
-	'info_chapeau_2' => 'المقدمة:',
276
-	'info_chemin_acces_1' => 'خيارات: <b>مسار الدخول في الدليل</b>',
277
-	'info_chemin_acces_2' => 'من الآن، عليك بإعداد مسار الدخول الى معلومات الدليل. هذه المعلومات أساسية لقراءة بيانات المستخدمين المحفوظة في الدليل.',
278
-	'info_chemin_acces_annuaire' => 'خيارات: <b>مسار الدخول في الدليل</b>',
279
-	'info_choix_base' => 'الخطوة الثالثة: ',
280
-	'info_classement_1' => ' من أصل @liste@ مقال',
281
-	'info_classement_2' => 'من أصل @liste@ مقال',
282
-	'info_code_acces' => 'لا تنسى بيانات الدخول الخاصة بك!',
283
-	'info_config_suivi' => 'اذا كان هذا العنوان يدل الى قائمة بريدية، يمكنك ادخال العنوان حيث يقوم المشاركون في الموفع بتسجيل انفسهم، ادناه. ويمكن لهذا العنوان ان يكون عنوان URL (مثلاً صفحة التسجيل في القائمة عبر النسيج) او عنوان بريدي يحمل موضوعاً محدداً (مثلاً: <tt>@adresse_suivi@?subject=subscribe</tt>):',
284
-	'info_config_suivi_explication' => 'يمكنك الاشتراك في القائمة البريدية في هذا الموقع. ستحصل عندها آلياً في رسالة الكترونية على اعلانات حول المقالات والاخبار المقترحة للنشر. ',
285
-	'info_confirmer_passe' => 'تأكيد كلمة السر الجديدة:',
286
-	'info_conflit_edition_avis_non_sauvegarde' => 'تنبيه، تم تعديل الحقول التالية في مكان آخر. لذلك لم يتم تسجيل نعديلاتك.',
287
-	'info_conflit_edition_differences' => 'الفروق:',
288
-	'info_conflit_edition_version_enregistree' => 'الاصدار المسجل:',
289
-	'info_conflit_edition_votre_version' => 'إصدارك:',
290
-	'info_connexion_base' => 'محاولة الاتصال بقاعدة البيانات',
291
-	'info_connexion_base_donnee' => 'الاتصال بقاعدة بياناتك',
292
-	'info_connexion_ldap_ok' => 'نجح إتصال LDAP.</b><p> يمكنك الانتقال الى الخطوة التالية.</p>',
293
-	'info_connexion_mysql' => 'الاتصال بخادم SQL',
294
-	'info_connexion_ok' => 'نجح الاتصال.',
295
-	'info_contact' => 'الاتصال',
296
-	'info_contenu_articles' => 'محتوى المقالات',
297
-	'info_contributions' => 'المساهمات',
298
-	'info_creation_paragraphe' => 'لإنشاء فقرات يكفي ترك سطور فارغة.',
299
-	'info_creation_rubrique' => 'قبل التمكن من كتابة مقالات،<br />يجب عليك إنشاء قسم واحد على الأقل.<br />',
300
-	'info_creation_tables' => 'إنشاء جداول قاعدة البيانات',
301
-	'info_creer_base' => '<b>قم بإنشاء</b>  قاعدة بيانات جديدة:',
302
-	'info_dans_rubrique' => 'في القسم:	',
303
-	'info_date_publication_anterieure' => 'تاريخ النشر السابق:',
304
-	'info_date_referencement' => 'تاريخ تبويب هذا الموقع:',
305
-	'info_derniere_etape' => 'إنتهى!',
306
-	'info_descriptif' => 'الوصف:',
307
-	'info_desinstaller_plugin' => 'يحذف البيانات ويعطل الملحقات',
308
-	'info_discussion_cours' => 'النقاشات النشطة',
309
-	'info_ecrire_article' => 'قبل التمكن من كتابة مقالات، يجب عليك إنشاء قسم واحد على الأقل.',
310
-	'info_email_envoi' => 'العنوان الالكتروني للارسال (اختياري)',
311
-	'info_email_envoi_txt' => 'ادخل هنا العنوان المطلوب استخدامه لبعث الرسائل (والا، سيتم استخدام عنوان المرسل اليه كعنوان ارسال):',
312
-	'info_email_webmestre' => 'عنوان بريد المشرف على الموقع',
313
-	'info_envoi_email_automatique' => 'إرسال البريد الآلي',
314
-	'info_envoyer_maintenant' => 'إرسال الآن',
315
-	'info_etape_suivante' => 'إنتقل الى الخطوة التالية',
316
-	'info_etape_suivante_1' => 'يمكنك الانتقال الى الخطوة التالية.',
317
-	'info_etape_suivante_2' => 'يمكنك الانتقال الى الخطوة التالية.',
318
-	'info_exceptions_proxy' => 'استثناءات للجهاز الوكيل',
319
-	'info_exportation_base' => 'نقل قاعدة البيانات الى @archive@',
320
-	'info_facilite_suivi_activite' => 'لتسهيل متابعة أنشطة تحرير
245
+    'info_ajouter_rubrique' => 'إضافة قسم آخر الى الإدارة:',
246
+    'info_annonce_nouveautes' => 'إعلان عن آخر الأخبار',
247
+    'info_article' => 'مقال',
248
+    'info_article_2' => 'مقال',
249
+    'info_article_a_paraitre' => 'المقالات المؤجلة التي تنتظر النشر',
250
+    'info_articles_02' => 'مقال',
251
+    'info_articles_2' => 'المقالات',
252
+    'info_articles_auteur' => 'مقالات هذا المؤلف',
253
+    'info_articles_miens' => 'مقالاتي',
254
+    'info_articles_tous' => 'كل المقالات',
255
+    'info_articles_trouves' => 'المقالات التي عثر عليها',
256
+    'info_attente_validation' => 'مقالاتك المنتظرة التصديق',
257
+    'info_aucun_article' => 'لا يوجد مقالات',
258
+    'info_aucun_auteur' => 'لا يوجد مؤلفون',
259
+    'info_aucun_message' => 'لا توجد رسائل',
260
+    'info_aucun_rubrique' => 'لا توجد أقسام',
261
+    'info_aujourdhui' => 'اليوم:',
262
+    'info_auteur_gere_rubriques' => 'هذا المؤلف يدير الأقسام التالية:',
263
+    'info_auteur_gere_toutes_rubriques' => 'هذا المؤلف يدير <b>كل الأقسام</b>',
264
+    'info_auteur_gere_toutes_rubriques_2' => 'أدير <b>كل الأقسام</b>',
265
+    'info_auteurs' => 'المؤلفون',
266
+    'info_auteurs_par_tri' => 'المؤلفون@partri@',
267
+    'info_auteurs_trouves' => 'المؤلفون الذين عثر عليهم',
268
+    'info_authentification_externe' => 'التحقق الخارجي',
269
+    'info_avertissement' => 'تحذير',
270
+    'info_barre_outils' => 'مع شريط أدواته؟',
271
+    'info_base_installee' => '<b>تم تثبيت بنية قاعدة البيانات. ',
272
+    'info_bio' => 'السيرة',
273
+    'info_cache_desactive' => 'الذاكرة المخبأة متوقفة مؤقتاً.',
274
+    'info_chapeau' => 'المقدمة',
275
+    'info_chapeau_2' => 'المقدمة:',
276
+    'info_chemin_acces_1' => 'خيارات: <b>مسار الدخول في الدليل</b>',
277
+    'info_chemin_acces_2' => 'من الآن، عليك بإعداد مسار الدخول الى معلومات الدليل. هذه المعلومات أساسية لقراءة بيانات المستخدمين المحفوظة في الدليل.',
278
+    'info_chemin_acces_annuaire' => 'خيارات: <b>مسار الدخول في الدليل</b>',
279
+    'info_choix_base' => 'الخطوة الثالثة: ',
280
+    'info_classement_1' => ' من أصل @liste@ مقال',
281
+    'info_classement_2' => 'من أصل @liste@ مقال',
282
+    'info_code_acces' => 'لا تنسى بيانات الدخول الخاصة بك!',
283
+    'info_config_suivi' => 'اذا كان هذا العنوان يدل الى قائمة بريدية، يمكنك ادخال العنوان حيث يقوم المشاركون في الموفع بتسجيل انفسهم، ادناه. ويمكن لهذا العنوان ان يكون عنوان URL (مثلاً صفحة التسجيل في القائمة عبر النسيج) او عنوان بريدي يحمل موضوعاً محدداً (مثلاً: <tt>@adresse_suivi@?subject=subscribe</tt>):',
284
+    'info_config_suivi_explication' => 'يمكنك الاشتراك في القائمة البريدية في هذا الموقع. ستحصل عندها آلياً في رسالة الكترونية على اعلانات حول المقالات والاخبار المقترحة للنشر. ',
285
+    'info_confirmer_passe' => 'تأكيد كلمة السر الجديدة:',
286
+    'info_conflit_edition_avis_non_sauvegarde' => 'تنبيه، تم تعديل الحقول التالية في مكان آخر. لذلك لم يتم تسجيل نعديلاتك.',
287
+    'info_conflit_edition_differences' => 'الفروق:',
288
+    'info_conflit_edition_version_enregistree' => 'الاصدار المسجل:',
289
+    'info_conflit_edition_votre_version' => 'إصدارك:',
290
+    'info_connexion_base' => 'محاولة الاتصال بقاعدة البيانات',
291
+    'info_connexion_base_donnee' => 'الاتصال بقاعدة بياناتك',
292
+    'info_connexion_ldap_ok' => 'نجح إتصال LDAP.</b><p> يمكنك الانتقال الى الخطوة التالية.</p>',
293
+    'info_connexion_mysql' => 'الاتصال بخادم SQL',
294
+    'info_connexion_ok' => 'نجح الاتصال.',
295
+    'info_contact' => 'الاتصال',
296
+    'info_contenu_articles' => 'محتوى المقالات',
297
+    'info_contributions' => 'المساهمات',
298
+    'info_creation_paragraphe' => 'لإنشاء فقرات يكفي ترك سطور فارغة.',
299
+    'info_creation_rubrique' => 'قبل التمكن من كتابة مقالات،<br />يجب عليك إنشاء قسم واحد على الأقل.<br />',
300
+    'info_creation_tables' => 'إنشاء جداول قاعدة البيانات',
301
+    'info_creer_base' => '<b>قم بإنشاء</b>  قاعدة بيانات جديدة:',
302
+    'info_dans_rubrique' => 'في القسم:	',
303
+    'info_date_publication_anterieure' => 'تاريخ النشر السابق:',
304
+    'info_date_referencement' => 'تاريخ تبويب هذا الموقع:',
305
+    'info_derniere_etape' => 'إنتهى!',
306
+    'info_descriptif' => 'الوصف:',
307
+    'info_desinstaller_plugin' => 'يحذف البيانات ويعطل الملحقات',
308
+    'info_discussion_cours' => 'النقاشات النشطة',
309
+    'info_ecrire_article' => 'قبل التمكن من كتابة مقالات، يجب عليك إنشاء قسم واحد على الأقل.',
310
+    'info_email_envoi' => 'العنوان الالكتروني للارسال (اختياري)',
311
+    'info_email_envoi_txt' => 'ادخل هنا العنوان المطلوب استخدامه لبعث الرسائل (والا، سيتم استخدام عنوان المرسل اليه كعنوان ارسال):',
312
+    'info_email_webmestre' => 'عنوان بريد المشرف على الموقع',
313
+    'info_envoi_email_automatique' => 'إرسال البريد الآلي',
314
+    'info_envoyer_maintenant' => 'إرسال الآن',
315
+    'info_etape_suivante' => 'إنتقل الى الخطوة التالية',
316
+    'info_etape_suivante_1' => 'يمكنك الانتقال الى الخطوة التالية.',
317
+    'info_etape_suivante_2' => 'يمكنك الانتقال الى الخطوة التالية.',
318
+    'info_exceptions_proxy' => 'استثناءات للجهاز الوكيل',
319
+    'info_exportation_base' => 'نقل قاعدة البيانات الى @archive@',
320
+    'info_facilite_suivi_activite' => 'لتسهيل متابعة أنشطة تحرير
321 321
 الموقع، يرسل SPIP عبر البريد الى لائحة احد المحررين البريدية مثلاً،
322 322
 الإعلان عن طلبات النشر وتصديق المقالات. يمكن ادخال عنوان او اكثر تفصل بينها فواصل.',
323
-	'info_fichiers_authent' => 'ملف التحقق «.htpasswd»',
324
-	'info_forums_abo_invites' => 'يحتوي موقعك على منتديات بالاشتراك. يشترك الزوار اذاً من الموقع العمومي.',
325
-	'info_gauche_admin_tech' => '<b>لا يحق إلا لمسؤولي الموقع الوصول الى هذه الصفحة.</b><p> إنها توفر الوصول الى وظائف
323
+    'info_fichiers_authent' => 'ملف التحقق «.htpasswd»',
324
+    'info_forums_abo_invites' => 'يحتوي موقعك على منتديات بالاشتراك. يشترك الزوار اذاً من الموقع العمومي.',
325
+    'info_gauche_admin_tech' => '<b>لا يحق إلا لمسؤولي الموقع الوصول الى هذه الصفحة.</b><p> إنها توفر الوصول الى وظائف
326 326
 متنوعة للصيانة التقنية. وتتطلب بعض هذه الوظائف عملية تحقق محددة
327 327
 تحتاج الى الدخول الى الموقع عبر بروتوكول FTP .</p>',
328
-	'info_gauche_admin_vider' => '<b>لا يحق إلا لمسؤولي الموقع الوصول الى هذه الصفحة.</b><p> إنها توفر الوصول الى وظائف
328
+    'info_gauche_admin_vider' => '<b>لا يحق إلا لمسؤولي الموقع الوصول الى هذه الصفحة.</b><p> إنها توفر الوصول الى وظائف
329 329
 متنوعة للصيانة التقنية. وتتطلب بعض هذه الوظائف عملية تحقق محددة
330 330
 تحتاج الى الدخول الى الموقع عبر بروتوكول FTP .</p>',
331
-	'info_gauche_auteurs' => 'ستجد هنا جميع مؤلفي الموقع.
331
+    'info_gauche_auteurs' => 'ستجد هنا جميع مؤلفي الموقع.
332 332
 يدل لون رمز كل مؤلف على وضعه (مدير = أخضر؛ محرر = أصفر).',
333
-	'info_gauche_auteurs_exterieurs' => 'المؤلفون الخارجيون، الذين لا يتمتعون بحق الدخول الى الموقع، معرّفون برمز أزرق؛
333
+    'info_gauche_auteurs_exterieurs' => 'المؤلفون الخارجيون، الذين لا يتمتعون بحق الدخول الى الموقع، معرّفون برمز أزرق؛
334 334
 اما المؤلفون المحذوفون فبرمز رمادي.',
335
-	'info_gauche_messagerie' => 'تتيح المراسلة تبادل الرسائل بين المحررين والحفاظ على المذكرات (لاستخدامك الشخصي) وعرض الإعلانات في الصفحة الرئيسية للمجال الخاص (إذا كنت مديراً).',
336
-	'info_gauche_statistiques_referers' => 'تعرض هذه الصفحة قائمة <i>مواقع المصدر</i>، أي المواقع التي تحتوي على وصلات تقود الى موقعك، fبين البارحة واليوم فقط: فيتم تأصيل هذه القائمة كل 24 ساعة.',
337
-	'info_gauche_visiteurs_enregistres' => 'ستجد هنا الزوار المسجلين
335
+    'info_gauche_messagerie' => 'تتيح المراسلة تبادل الرسائل بين المحررين والحفاظ على المذكرات (لاستخدامك الشخصي) وعرض الإعلانات في الصفحة الرئيسية للمجال الخاص (إذا كنت مديراً).',
336
+    'info_gauche_statistiques_referers' => 'تعرض هذه الصفحة قائمة <i>مواقع المصدر</i>، أي المواقع التي تحتوي على وصلات تقود الى موقعك، fبين البارحة واليوم فقط: فيتم تأصيل هذه القائمة كل 24 ساعة.',
337
+    'info_gauche_visiteurs_enregistres' => 'ستجد هنا الزوار المسجلين
338 338
 في مجال الموقع العام (المنتديات بالاشتراك).',
339
-	'info_generation_miniatures_images' => 'إنشاء مصغرات الصور',
340
-	'info_gerer_trad_objets' => '@objets@: إدارة روابط الترجمة',
341
-	'info_hebergeur_desactiver_envoi_email' => 'بعض خدام المواقع يوقفون إرسال البريد الآلي
339
+    'info_generation_miniatures_images' => 'إنشاء مصغرات الصور',
340
+    'info_gerer_trad_objets' => '@objets@: إدارة روابط الترجمة',
341
+    'info_hebergeur_desactiver_envoi_email' => 'بعض خدام المواقع يوقفون إرسال البريد الآلي
342 342
 في أجهزتهم. في هذه الحال، لا يمكن تفعيل
343 343
 وظائف SPIP التالية.',
344
-	'info_hier' => 'البارحة:',
345
-	'info_identification_publique' => 'هويتك العمومية...',
346
-	'info_image_process' => 'الرجاء اختيار افضل طريقة لإنشاء المصغرات بالنقر على الصورة المناسبة.',
347
-	'info_image_process2' => 'اذا لم تظهر اية صورة يكون جهاز الخدمة الذي يستضيف موقعك غير معدّ لاستخدام هذه الأدوات. اذا رغبت في استخدام هذه الوظائف، اتصل بالمسؤول التقني واطلب تثبيت أحد الملحقين «GD» او «Imagick».',
348
-	'info_images_auto' => 'يتم حساب هذه الصور آلياً',
349
-	'info_informations_personnelles' => 'المعلومات الشخصية',
350
-	'info_inscription' => 'التسجيل في',
351
-	'info_inscription_automatique' => 'تسجيل آلي للمحررين الجدد',
352
-	'info_jeu_caractere' => 'طقم حروف الموقع',
353
-	'info_jours' => 'يوم',
354
-	'info_laisser_champs_vides' => 'ترك هذه الحقول فارغة)',
355
-	'info_langues' => 'لغات الموقع',
356
-	'info_ldap_ok' => 'تم تثبيت تحقق LDAP .',
357
-	'info_lien_hypertexte' => 'وصلة هايبرتكست:',
358
-	'info_liste_nouveautes_envoyee' => 'تم إرسال لائحة جديد الموقع',
359
-	'info_liste_redacteurs_connectes' => 'قائمة المحررين المتصلين',
360
-	'info_login_existant' => 'هذا المعرّف موجود سابقاً.',
361
-	'info_login_trop_court' => 'معرّف الدخول قصيز جداً.',
362
-	'info_login_trop_court_car_pluriel' => 'يجب ان يحتوي المعرّف @nb@ أحرف على الأقل.',
363
-	'info_logos' => 'الرموز',
364
-	'info_maximum' => 'الحد الأقصى:',
365
-	'info_meme_rubrique' => 'في القسم نفسه',
366
-	'info_message_en_redaction' => 'رسالتك قيد التحرير',
367
-	'info_message_technique' => 'رسالة تقنية:',
368
-	'info_messagerie_interne' => 'المراسلة الداخلية',
369
-	'info_mise_a_niveau_base' => 'ترقية قاعدة بيانات SQL',
370
-	'info_mise_a_niveau_base_2' => '{{تحذير!}} قمت بتثبيت إصدار
344
+    'info_hier' => 'البارحة:',
345
+    'info_identification_publique' => 'هويتك العمومية...',
346
+    'info_image_process' => 'الرجاء اختيار افضل طريقة لإنشاء المصغرات بالنقر على الصورة المناسبة.',
347
+    'info_image_process2' => 'اذا لم تظهر اية صورة يكون جهاز الخدمة الذي يستضيف موقعك غير معدّ لاستخدام هذه الأدوات. اذا رغبت في استخدام هذه الوظائف، اتصل بالمسؤول التقني واطلب تثبيت أحد الملحقين «GD» او «Imagick».',
348
+    'info_images_auto' => 'يتم حساب هذه الصور آلياً',
349
+    'info_informations_personnelles' => 'المعلومات الشخصية',
350
+    'info_inscription' => 'التسجيل في',
351
+    'info_inscription_automatique' => 'تسجيل آلي للمحررين الجدد',
352
+    'info_jeu_caractere' => 'طقم حروف الموقع',
353
+    'info_jours' => 'يوم',
354
+    'info_laisser_champs_vides' => 'ترك هذه الحقول فارغة)',
355
+    'info_langues' => 'لغات الموقع',
356
+    'info_ldap_ok' => 'تم تثبيت تحقق LDAP .',
357
+    'info_lien_hypertexte' => 'وصلة هايبرتكست:',
358
+    'info_liste_nouveautes_envoyee' => 'تم إرسال لائحة جديد الموقع',
359
+    'info_liste_redacteurs_connectes' => 'قائمة المحررين المتصلين',
360
+    'info_login_existant' => 'هذا المعرّف موجود سابقاً.',
361
+    'info_login_trop_court' => 'معرّف الدخول قصيز جداً.',
362
+    'info_login_trop_court_car_pluriel' => 'يجب ان يحتوي المعرّف @nb@ أحرف على الأقل.',
363
+    'info_logos' => 'الرموز',
364
+    'info_maximum' => 'الحد الأقصى:',
365
+    'info_meme_rubrique' => 'في القسم نفسه',
366
+    'info_message_en_redaction' => 'رسالتك قيد التحرير',
367
+    'info_message_technique' => 'رسالة تقنية:',
368
+    'info_messagerie_interne' => 'المراسلة الداخلية',
369
+    'info_mise_a_niveau_base' => 'ترقية قاعدة بيانات SQL',
370
+    'info_mise_a_niveau_base_2' => '{{تحذير!}} قمت بتثبيت إصدار
371 371
 من ملفات SPIP {{أقدم}} من الإصدار الذي
372 372
 كان موجوداً في هذا الموقع: قد تواجه خطر فقدان قاعدة البيانات
373 373
 مما يحول دون عمل موقعك بشكل سليم.<br />{{إعادة تثبيت
374 374
 ملفات SPIP.}}',
375
-	'info_modification_enregistree' => 'تم تسجيل تعديلاتك',
376
-	'info_modifier_auteur' => 'تغيير المؤلف:',
377
-	'info_modifier_rubrique' => 'تعديل القسم:',
378
-	'info_modifier_titre' => 'تغيير: @titre@',
379
-	'info_mon_site_spip' => 'موقع SPIP',
380
-	'info_moyenne' => 'المتوسط:',
381
-	'info_multi_cet_article' => 'لغة هذا المقال:',
382
-	'info_multi_langues_choisies' => 'الرجاء تحديد ادناه اللغات التي ستكون متوافرة لمحرري موقعك.
375
+    'info_modification_enregistree' => 'تم تسجيل تعديلاتك',
376
+    'info_modifier_auteur' => 'تغيير المؤلف:',
377
+    'info_modifier_rubrique' => 'تعديل القسم:',
378
+    'info_modifier_titre' => 'تغيير: @titre@',
379
+    'info_mon_site_spip' => 'موقع SPIP',
380
+    'info_moyenne' => 'المتوسط:',
381
+    'info_multi_cet_article' => 'لغة هذا المقال:',
382
+    'info_multi_langues_choisies' => 'الرجاء تحديد ادناه اللغات التي ستكون متوافرة لمحرري موقعك.
383 383
   لا يمكن ايقاف اللغات المستخدمة حالياً في موقعك (والظاهرة في اول القائمة).',
384
-	'info_multi_objets' => '@objets@: تفعيل قائمة اللغات',
385
-	'info_multi_secteurs' => '... للأقسام الموجودة في اصل الموقع فقط ',
386
-	'info_nb_articles' => '@nb@ مقال',
387
-	'info_nb_auteurs' => '@nb@ مؤلف',
388
-	'info_nb_messages' => '@nb@ رسالة',
389
-	'info_nb_mots_cles' => '@nb@ مفتاح',
390
-	'info_nb_rubriques' => '@nb@ قسم',
391
-	'info_nb_visiteurs' => '@nb@ زائر',
392
-	'info_nom' => 'الإسم',
393
-	'info_nom_destinataire' => 'إسم المرسل اليه',
394
-	'info_nom_pas_conforme' => 'علامات html غير مسموح بها',
395
-	'info_nom_site' => 'إسم موقعك',
396
-	'info_nombre_articles' => '@nb_articles@ مقال،',
397
-	'info_nombre_rubriques' => '@nb_rubriques@ قسم،',
398
-	'info_nombre_sites' => '@nb_sites@ موقع،',
399
-	'info_non_deplacer' => 'عدم التحريك...',
400
-	'info_non_envoi_annonce_dernieres_nouveautes' => 'يستطيع SPIP إرسال إعلانات عن آخر الأخبار بانتظام.
384
+    'info_multi_objets' => '@objets@: تفعيل قائمة اللغات',
385
+    'info_multi_secteurs' => '... للأقسام الموجودة في اصل الموقع فقط ',
386
+    'info_nb_articles' => '@nb@ مقال',
387
+    'info_nb_auteurs' => '@nb@ مؤلف',
388
+    'info_nb_messages' => '@nb@ رسالة',
389
+    'info_nb_mots_cles' => '@nb@ مفتاح',
390
+    'info_nb_rubriques' => '@nb@ قسم',
391
+    'info_nb_visiteurs' => '@nb@ زائر',
392
+    'info_nom' => 'الإسم',
393
+    'info_nom_destinataire' => 'إسم المرسل اليه',
394
+    'info_nom_pas_conforme' => 'علامات html غير مسموح بها',
395
+    'info_nom_site' => 'إسم موقعك',
396
+    'info_nombre_articles' => '@nb_articles@ مقال،',
397
+    'info_nombre_rubriques' => '@nb_rubriques@ قسم،',
398
+    'info_nombre_sites' => '@nb_sites@ موقع،',
399
+    'info_non_deplacer' => 'عدم التحريك...',
400
+    'info_non_envoi_annonce_dernieres_nouveautes' => 'يستطيع SPIP إرسال إعلانات عن آخر الأخبار بانتظام.
401 401
 (المقالات والأخبار المنشورة حديثاً).',
402
-	'info_non_envoi_liste_nouveautes' => 'عدم إرسال قائمة بآخر الأخبار',
403
-	'info_non_modifiable' => '</i>لا يمكن تغييره<i>',
404
-	'info_non_suppression_mot_cle' => 'كلا لا أريد حذف هذا المفتاح.',
405
-	'info_notes' => 'حواشي',
406
-	'info_nouvel_article' => 'مقال جديد',
407
-	'info_nouvelle_traduction' => 'ترجمة جديدة:',
408
-	'info_numero_article' => 'المقال رقم:',
409
-	'info_obligatoire_02' => '(إجباري)',
410
-	'info_option_accepter_visiteurs' => 'قبول تسجيل الزوار من الموقع العمومي',
411
-	'info_option_ne_pas_accepter_visiteurs' => 'رفض تسجيل الزوار من الموقع العمومي',
412
-	'info_options_avancees' => 'الخيارات المتطورة',
413
-	'info_ou' => 'أو...',
414
-	'info_page_interdite' => 'صفحة محظورة',
415
-	'info_par_nom' => 'حسب الاسم',
416
-	'info_par_nombre_article' => 'حسب عدد المقالات',
417
-	'info_par_statut' => 'حسب الوضع',
418
-	'info_par_tri' => '’(حسب @tri@)’',
419
-	'info_passe_trop_court' => 'كلمة السر قصيرة جداً.',
420
-	'info_passe_trop_court_car_pluriel' => 'يجب ان تحتوي كلمة السر @nb@ أحرف على الأقل.',
421
-	'info_passes_identiques' => 'كلمتا السر ليستا متطابقتان.',
422
-	'info_plus_cinq_car' => 'أكثر من خمسة أحرف',
423
-	'info_plus_cinq_car_2' => '(أكثر من خمسة أحرف)',
424
-	'info_plus_trois_car' => '(أكثر من ثلاثة أحرف)',
425
-	'info_popularite' => 'الشعبية: @popularite@؛ الزيارات: @visites@',
426
-	'info_post_scriptum' => 'الملحق',
427
-	'info_post_scriptum_2' => 'الملحق:',
428
-	'info_pour' => 'لـ',
429
-	'info_preview_texte' => 'من الممكن تفعيل العرض المسبق للعناصر التحريرية التي تتمتع على الاقل بوضعية «مقترح»، إضافة الى العناصر «قيد التحرير» العائدة للمؤلف المتصل. هل تتاح هذه الوظيفة للمدراء فقط او لجميع المحررين او تُعطل؟',
430
-	'info_procedez_par_etape' => 'الرجاء إتباع الخطوة خطوة ',
431
-	'info_procedure_maj_version' => 'يجب تنفيذ عملية الترقية لتكييف
402
+    'info_non_envoi_liste_nouveautes' => 'عدم إرسال قائمة بآخر الأخبار',
403
+    'info_non_modifiable' => '</i>لا يمكن تغييره<i>',
404
+    'info_non_suppression_mot_cle' => 'كلا لا أريد حذف هذا المفتاح.',
405
+    'info_notes' => 'حواشي',
406
+    'info_nouvel_article' => 'مقال جديد',
407
+    'info_nouvelle_traduction' => 'ترجمة جديدة:',
408
+    'info_numero_article' => 'المقال رقم:',
409
+    'info_obligatoire_02' => '(إجباري)',
410
+    'info_option_accepter_visiteurs' => 'قبول تسجيل الزوار من الموقع العمومي',
411
+    'info_option_ne_pas_accepter_visiteurs' => 'رفض تسجيل الزوار من الموقع العمومي',
412
+    'info_options_avancees' => 'الخيارات المتطورة',
413
+    'info_ou' => 'أو...',
414
+    'info_page_interdite' => 'صفحة محظورة',
415
+    'info_par_nom' => 'حسب الاسم',
416
+    'info_par_nombre_article' => 'حسب عدد المقالات',
417
+    'info_par_statut' => 'حسب الوضع',
418
+    'info_par_tri' => '’(حسب @tri@)’',
419
+    'info_passe_trop_court' => 'كلمة السر قصيرة جداً.',
420
+    'info_passe_trop_court_car_pluriel' => 'يجب ان تحتوي كلمة السر @nb@ أحرف على الأقل.',
421
+    'info_passes_identiques' => 'كلمتا السر ليستا متطابقتان.',
422
+    'info_plus_cinq_car' => 'أكثر من خمسة أحرف',
423
+    'info_plus_cinq_car_2' => '(أكثر من خمسة أحرف)',
424
+    'info_plus_trois_car' => '(أكثر من ثلاثة أحرف)',
425
+    'info_popularite' => 'الشعبية: @popularite@؛ الزيارات: @visites@',
426
+    'info_post_scriptum' => 'الملحق',
427
+    'info_post_scriptum_2' => 'الملحق:',
428
+    'info_pour' => 'لـ',
429
+    'info_preview_texte' => 'من الممكن تفعيل العرض المسبق للعناصر التحريرية التي تتمتع على الاقل بوضعية «مقترح»، إضافة الى العناصر «قيد التحرير» العائدة للمؤلف المتصل. هل تتاح هذه الوظيفة للمدراء فقط او لجميع المحررين او تُعطل؟',
430
+    'info_procedez_par_etape' => 'الرجاء إتباع الخطوة خطوة ',
431
+    'info_procedure_maj_version' => 'يجب تنفيذ عملية الترقية لتكييف
432 432
 قاعدة البيانات مع إصدار SPIP الجديد.',
433
-	'info_proxy_ok' => 'نجح اختبار الجهاز الوكيل.',
434
-	'info_ps' => 'ملاحظة',
435
-	'info_publier' => 'نشر',
436
-	'info_publies' => 'مقالاتك المنشورة',
437
-	'info_question_accepter_visiteurs' => 'اذا كانت صفحات موقعك النموذجية تفسح المجال للزوار الذين لا يتمتعون بحق الدخول الى المجال الخاص لتسجيل انفسهم، قم بتفعيل الخيار التالي:',
438
-	'info_question_inscription_nouveaux_redacteurs' => 'هل تسمح بتسجيل محررين جدد من
433
+    'info_proxy_ok' => 'نجح اختبار الجهاز الوكيل.',
434
+    'info_ps' => 'ملاحظة',
435
+    'info_publier' => 'نشر',
436
+    'info_publies' => 'مقالاتك المنشورة',
437
+    'info_question_accepter_visiteurs' => 'اذا كانت صفحات موقعك النموذجية تفسح المجال للزوار الذين لا يتمتعون بحق الدخول الى المجال الخاص لتسجيل انفسهم، قم بتفعيل الخيار التالي:',
438
+    'info_question_inscription_nouveaux_redacteurs' => 'هل تسمح بتسجيل محررين جدد من
439 439
 الموقع العمومي؟ إذا وافقت، سيتمكن الزوار من التسجيل
440 440
 عبر إستمارة آلية والدخول الى المجال الخاص
441 441
 لعرض مقالاتهم. <div class="notice">خلال عملية التسجيل،
@@ -444,368 +444,368 @@  discard block
 block discarded – undo
444 444
  خدام المواقع يعطلون إرسال البريد الآلي في
445 445
 أجهزتهم: في هذه الحال، لا يمكن تفعيل
446 446
 التسجيل الآلي.</div>',
447
-	'info_qui_edite' => '@nom_auteur_modif@ عمل على هذا المحتوى منذ @date_diff@ دقيقة ',
448
-	'info_racine_site' => 'أصل الموقع',
449
-	'info_recharger_page' => 'الرجاء إعادة تحميل الصفحة بعد لحظات.',
450
-	'info_recherche_auteur_zero' => 'لا توجد نتائج لـ «@cherche_auteur@».',
451
-	'info_recommencer' => 'الرجاء إعادة المحاولة.',
452
-	'info_redacteur_1' => 'محرر',
453
-	'info_redacteur_2' => 'يملك حق الدخول الى المجال الخاص (ينصح به)',
454
-	'info_redacteurs' => 'محررون',
455
-	'info_redaction_en_cours' => 'قيد التحرير',
456
-	'info_redirection' => 'إعادة توجيه',
457
-	'info_redirection_activee' => 'تم تفعيل إعادة التحويل.',
458
-	'info_redirection_boucle' => 'محاولة إعادة توجيه مقال الى ذاته.',
459
-	'info_redirection_desactivee' => 'تم حذف إعادة التحويل.',
460
-	'info_refuses' => 'مقالاتك المرفوضة',
461
-	'info_reglage_ldap' => 'خيارات: <b>ضبط جلب LDAP </b>',
462
-	'info_renvoi_article' => '<b>إعادة توجيه.</b> هذا المقال يحيل الى الصفحة: ',
463
-	'info_reserve_admin' => 'المدراء وحدهم يمكنهم تغيير هذا العنوان.',
464
-	'info_restreindre_rubrique' => 'حصر الإدارة في القسم:',
465
-	'info_resultat_recherche' => 'نتائج البحث:',
466
-	'info_rubriques' => 'الأقسام',
467
-	'info_rubriques_02' => 'الأقسام',
468
-	'info_rubriques_trouvees' => 'الأقسام التي عثر عليها',
469
-	'info_sans_titre' => 'بدون عنوان',
470
-	'info_selection_chemin_acces' => '<b>حدد</b> أدناه مسار الدخول في الدليل:',
471
-	'info_signatures' => 'التوقيعات',
472
-	'info_site' => 'الموقع',
473
-	'info_site_2' => 'الموقع:',
474
-	'info_site_min' => 'الموقع',
475
-	'info_site_reference_2' => 'موقع مبوب',
476
-	'info_site_web' => 'الموقع:',
477
-	'info_sites' => ' مواقع',
478
-	'info_sites_lies_mot' => 'المواقع المبوبة المرتبطة بهذا المفتاح',
479
-	'info_sites_proxy' => 'إستخدام جهاز وكيل',
480
-	'info_sites_trouves' => 'المواقع التي عثر عليها',
481
-	'info_sous_titre' => 'العنوان الفرعي:',
482
-	'info_statut_administrateur' => 'مدير',
483
-	'info_statut_auteur' => 'وضع هذا المؤلف:',
484
-	'info_statut_auteur_2' => 'أنا',
485
-	'info_statut_auteur_a_confirmer' => 'التسجيل المطلوب التأكد منه',
486
-	'info_statut_auteur_autre' => 'وضعية اخرى:',
487
-	'info_statut_redacteur' => 'محرر',
488
-	'info_statut_utilisateurs_1' => 'الوضع الافتراضي للمستخدمين المجلوبين',
489
-	'info_statut_utilisateurs_2' => 'قم باختيار الوضع المخصص للأشخاص الموجودين في دليل LDAP عندما سيتصلون للمرة الأولى. لاحقاً، يمكنك تغيير هذه القيمة لكل مؤلف على حدى.',
490
-	'info_suivi_activite' => 'متابعة أنشطة التحرير',
491
-	'info_surtitre' => 'عنوان المدخل:',
492
-	'info_syndication_integrale_1' => 'يقدم موقعك ملفات ترخيص (انظر «<a href="@url@">@titre@</a>»).',
493
-	'info_syndication_integrale_2' => 'هل ترغب في تقديم المقالات بكاملها او الاكتفاء بنشر ملخص من بضعة مئات من الكلمات؟',
494
-	'info_table_prefix' => 'يمكنك تغيير بادئة اسماء جداول البيانات (هذا ضروري في حال تثبيت عدة مواقع لقاعدة بيانات واحدة). تكتب هذه البادئة بأحرف صغيرة بدون صوتيات ومسافات. ',
495
-	'info_taille_maximale_images' => 'سيقوم SPIP بتفقد الحد الاقصى لحجم الصور التي يمكنه معالجتها (بملايين النقاط).<br /> لن يتم تصغير الصور التي تتعدى هذا الحد.',
496
-	'info_taille_maximale_vignette' => 'الحد الأقصى لأبعاد المصغرات التي ينتجها النظام:',
497
-	'info_terminer_installation' => 'يمكنك الآن إتمام عملية التثبيت العادية',
498
-	'info_texte' => 'المادة',
499
-	'info_texte_explicatif' => 'نص توضيحي',
500
-	'info_texte_long' => '(المادة طويلة جداً: ستظهر بعدة أجزاء تتم إعادة تجميعها بعد النقر على الإدخال.)',
501
-	'info_texte_message' => 'نص مشاركتك:',
502
-	'info_texte_message_02' => 'نص الرسالة',
503
-	'info_titre' => 'الموضوع:',
504
-	'info_total' => 'المجموع:',
505
-	'info_tous_articles_en_redaction' => 'كل المقالات قيد التحرير',
506
-	'info_tous_articles_presents' => 'كل المقالات المنشورة في هذا القسم',
507
-	'info_tous_articles_refuses' => 'كل المقالات المرفوضة',
508
-	'info_tous_les' => 'كل:',
509
-	'info_tout_site' => 'الموقع بالكامل',
510
-	'info_tout_site2' => 'لم يُترجم المقال الى هذه اللغة.',
511
-	'info_tout_site3' => 'تمت ترجمة المقال الى هذه اللغة لكن طرأت تعديلات على المقال المرجع في ما بعد. يجب تحديث الترجمة.',
512
-	'info_tout_site4' => 'تمت ترجمة المقال الى هذه اللغة والترجمة حديثة.',
513
-	'info_tout_site5' => 'المقال الاصلي.',
514
-	'info_tout_site6' => '<b>تحذير:</b> المقالات الاصلية وحدها هي المعروضة.
447
+    'info_qui_edite' => '@nom_auteur_modif@ عمل على هذا المحتوى منذ @date_diff@ دقيقة ',
448
+    'info_racine_site' => 'أصل الموقع',
449
+    'info_recharger_page' => 'الرجاء إعادة تحميل الصفحة بعد لحظات.',
450
+    'info_recherche_auteur_zero' => 'لا توجد نتائج لـ «@cherche_auteur@».',
451
+    'info_recommencer' => 'الرجاء إعادة المحاولة.',
452
+    'info_redacteur_1' => 'محرر',
453
+    'info_redacteur_2' => 'يملك حق الدخول الى المجال الخاص (ينصح به)',
454
+    'info_redacteurs' => 'محررون',
455
+    'info_redaction_en_cours' => 'قيد التحرير',
456
+    'info_redirection' => 'إعادة توجيه',
457
+    'info_redirection_activee' => 'تم تفعيل إعادة التحويل.',
458
+    'info_redirection_boucle' => 'محاولة إعادة توجيه مقال الى ذاته.',
459
+    'info_redirection_desactivee' => 'تم حذف إعادة التحويل.',
460
+    'info_refuses' => 'مقالاتك المرفوضة',
461
+    'info_reglage_ldap' => 'خيارات: <b>ضبط جلب LDAP </b>',
462
+    'info_renvoi_article' => '<b>إعادة توجيه.</b> هذا المقال يحيل الى الصفحة: ',
463
+    'info_reserve_admin' => 'المدراء وحدهم يمكنهم تغيير هذا العنوان.',
464
+    'info_restreindre_rubrique' => 'حصر الإدارة في القسم:',
465
+    'info_resultat_recherche' => 'نتائج البحث:',
466
+    'info_rubriques' => 'الأقسام',
467
+    'info_rubriques_02' => 'الأقسام',
468
+    'info_rubriques_trouvees' => 'الأقسام التي عثر عليها',
469
+    'info_sans_titre' => 'بدون عنوان',
470
+    'info_selection_chemin_acces' => '<b>حدد</b> أدناه مسار الدخول في الدليل:',
471
+    'info_signatures' => 'التوقيعات',
472
+    'info_site' => 'الموقع',
473
+    'info_site_2' => 'الموقع:',
474
+    'info_site_min' => 'الموقع',
475
+    'info_site_reference_2' => 'موقع مبوب',
476
+    'info_site_web' => 'الموقع:',
477
+    'info_sites' => ' مواقع',
478
+    'info_sites_lies_mot' => 'المواقع المبوبة المرتبطة بهذا المفتاح',
479
+    'info_sites_proxy' => 'إستخدام جهاز وكيل',
480
+    'info_sites_trouves' => 'المواقع التي عثر عليها',
481
+    'info_sous_titre' => 'العنوان الفرعي:',
482
+    'info_statut_administrateur' => 'مدير',
483
+    'info_statut_auteur' => 'وضع هذا المؤلف:',
484
+    'info_statut_auteur_2' => 'أنا',
485
+    'info_statut_auteur_a_confirmer' => 'التسجيل المطلوب التأكد منه',
486
+    'info_statut_auteur_autre' => 'وضعية اخرى:',
487
+    'info_statut_redacteur' => 'محرر',
488
+    'info_statut_utilisateurs_1' => 'الوضع الافتراضي للمستخدمين المجلوبين',
489
+    'info_statut_utilisateurs_2' => 'قم باختيار الوضع المخصص للأشخاص الموجودين في دليل LDAP عندما سيتصلون للمرة الأولى. لاحقاً، يمكنك تغيير هذه القيمة لكل مؤلف على حدى.',
490
+    'info_suivi_activite' => 'متابعة أنشطة التحرير',
491
+    'info_surtitre' => 'عنوان المدخل:',
492
+    'info_syndication_integrale_1' => 'يقدم موقعك ملفات ترخيص (انظر «<a href="@url@">@titre@</a>»).',
493
+    'info_syndication_integrale_2' => 'هل ترغب في تقديم المقالات بكاملها او الاكتفاء بنشر ملخص من بضعة مئات من الكلمات؟',
494
+    'info_table_prefix' => 'يمكنك تغيير بادئة اسماء جداول البيانات (هذا ضروري في حال تثبيت عدة مواقع لقاعدة بيانات واحدة). تكتب هذه البادئة بأحرف صغيرة بدون صوتيات ومسافات. ',
495
+    'info_taille_maximale_images' => 'سيقوم SPIP بتفقد الحد الاقصى لحجم الصور التي يمكنه معالجتها (بملايين النقاط).<br /> لن يتم تصغير الصور التي تتعدى هذا الحد.',
496
+    'info_taille_maximale_vignette' => 'الحد الأقصى لأبعاد المصغرات التي ينتجها النظام:',
497
+    'info_terminer_installation' => 'يمكنك الآن إتمام عملية التثبيت العادية',
498
+    'info_texte' => 'المادة',
499
+    'info_texte_explicatif' => 'نص توضيحي',
500
+    'info_texte_long' => '(المادة طويلة جداً: ستظهر بعدة أجزاء تتم إعادة تجميعها بعد النقر على الإدخال.)',
501
+    'info_texte_message' => 'نص مشاركتك:',
502
+    'info_texte_message_02' => 'نص الرسالة',
503
+    'info_titre' => 'الموضوع:',
504
+    'info_total' => 'المجموع:',
505
+    'info_tous_articles_en_redaction' => 'كل المقالات قيد التحرير',
506
+    'info_tous_articles_presents' => 'كل المقالات المنشورة في هذا القسم',
507
+    'info_tous_articles_refuses' => 'كل المقالات المرفوضة',
508
+    'info_tous_les' => 'كل:',
509
+    'info_tout_site' => 'الموقع بالكامل',
510
+    'info_tout_site2' => 'لم يُترجم المقال الى هذه اللغة.',
511
+    'info_tout_site3' => 'تمت ترجمة المقال الى هذه اللغة لكن طرأت تعديلات على المقال المرجع في ما بعد. يجب تحديث الترجمة.',
512
+    'info_tout_site4' => 'تمت ترجمة المقال الى هذه اللغة والترجمة حديثة.',
513
+    'info_tout_site5' => 'المقال الاصلي.',
514
+    'info_tout_site6' => '<b>تحذير:</b> المقالات الاصلية وحدها هي المعروضة.
515 515
 الترجمات مرتبطة بالاصلي،
516 516
 يلون يدل على حالتها:',
517
-	'info_traductions' => 'الترجمات',
518
-	'info_travail_colaboratif' => 'تحرير المقالات المشترك',
519
-	'info_un_article' => 'مقال، ',
520
-	'info_un_site' => 'موقع،',
521
-	'info_une_rubrique' => 'قسم،',
522
-	'info_une_rubrique_02' => 'قسم واحد',
523
-	'info_url' => 'عنوان URL:',
524
-	'info_url_proxy' => 'عنوان URL للجهاز الوكيل',
525
-	'info_url_proxy_pas_conforme' => 'عنوان الجهاز الوكيل غير صالح.',
526
-	'info_url_site_pas_conforme' => 'عنوان URL غير صالح.',
527
-	'info_url_test_proxy' => 'عنوان URL للاختبار',
528
-	'info_urlref' => 'وصلة هايبرتكست:',
529
-	'info_utilisation_spip' => 'أصبح نظام النشر الآلي جاهزاً للاستخدام...',
530
-	'info_visites_par_mois' => 'عرض حسب الشهر:',
531
-	'info_visiteur_1' => 'زائر',
532
-	'info_visiteur_2' => 'للموقع العمومي',
533
-	'info_visiteurs' => 'الزوار',
534
-	'info_visiteurs_02' => 'زوار الموقع العمومي',
535
-	'info_webmestre_forces' => 'المشرفون محددون حالياً في <tt>@file_options@</tt>.',
536
-	'install_adresse_base_hebergeur' => 'عنوان قاعدة البيانات التي خصصها لك المضيف',
537
-	'install_connect_ok' => 'تم فعلاً تعريف قاعدة البيانات باسم جهاز الخدمة @connect@.',
538
-	'install_echec_annonce' => 'الارجح ان التثبيت سيفشل او يؤدي الى موقع غير سليم...',
539
-	'install_extension_mbstring' => 'لا يعمل SPIP مع:',
540
-	'install_extension_php_obligatoire' => 'يتطلب SPIP ملحق php:',
541
-	'install_login_base_hebergeur' => 'معرّف الدخول الذي خصصه لك المضيف',
542
-	'install_nom_base_hebergeur' => 'اسم قاعدة البيانات الدي خصصه لك المضيف:',
543
-	'install_pas_table' => 'قاعدة من دون جداول حالياً',
544
-	'install_pass_base_hebergeur' => 'كلمة سر الاتصال التي خصصها لك المضيف',
545
-	'install_php_extension' => 'الملحقات التالية غير موجودة: @extensions@',
546
-	'install_php_version' => 'اصدار @version@ من PHP غير كاف(الحد الادنى = @minimum@)',
547
-	'install_php_version_max' => 'PHP إصدار @version@ حديث جداً (الحد الأقصى = @maximum@)',
548
-	'install_select_langue' => 'إختر لغة ثم انقر على الزر« التالي»  للبدء بعملية التثبيت.',
549
-	'install_select_type_db' => 'تحديد نوع قاعدة البيانات:',
550
-	'install_select_type_mysql' => 'MySQL',
551
-	'install_select_type_pg' => 'PostgreSQL',
552
-	'install_select_type_sqlite2' => 'SQLite 2',
553
-	'install_select_type_sqlite3' => 'SQLite 3',
554
-	'install_serveur_hebergeur' => 'خادم قواعد البيانات الذي يوفره المضيف ',
555
-	'install_table_prefix_hebergeur' => 'بادئة اسماء الجداول التي خصصها لك المضيف:',
556
-	'install_tables_base' => 'جداول القاعدة',
557
-	'install_types_db_connus' => 'يستطيع SPIP استخدام <b>MySQL</b> (الاكثر انتشاراً) و<b>SQLite</b>.',
558
-	'install_types_db_connus_avertissement' => 'يتوافر دعم <b>PostgreSQL</b> أيضاً على سبيل الاختبار',
559
-	'instituer_erreur_statut_a_change' => 'لقد تم تعديل الوضع من قبل',
560
-	'instituer_erreur_statut_non_autorise' => 'لا يمكن اختيار هذا الوضع',
561
-	'intem_redacteur' => 'محرر',
562
-	'intitule_licence' => 'الرخصة',
563
-	'item_accepter_inscriptions' => 'السماح بالتسجيل',
564
-	'item_activer_messages_avertissement' => 'تفعيل رسائل التحذير',
565
-	'item_administrateur_2' => 'مدير',
566
-	'item_afficher_calendrier' => 'إظهار في الروزنامة',
567
-	'item_autoriser_syndication_integrale' => 'نشر كامل المقالات في ملفات الترخيص',
568
-	'item_choix_administrateurs' => 'المدراء',
569
-	'item_choix_generation_miniature' => 'إنشاء مصغرات عن الصور آلياً.',
570
-	'item_choix_non_generation_miniature' => 'عدم إنشاء مصغرات عن الصور.',
571
-	'item_choix_redacteurs' => 'المحررون',
572
-	'item_choix_visiteurs' => 'زوار الموقع العمومي',
573
-	'item_creer_fichiers_authent' => 'إنشاء ملفات .htpasswd',
574
-	'item_login' => ' المعرّف',
575
-	'item_messagerie_agenda' => 'تفعيل المراسلة والمفكرة',
576
-	'item_mots_cles_association_articles' => 'المقالات',
577
-	'item_mots_cles_association_rubriques' => 'الأقسام',
578
-	'item_mots_cles_association_sites' => 'المواقع المبوبة او المرخصة.',
579
-	'item_non' => 'كلا',
580
-	'item_non_accepter_inscriptions' => 'عدم السماح بالتسجيل',
581
-	'item_non_activer_messages_avertissement' => 'تعطيل رسائل التحذير',
582
-	'item_non_afficher_calendrier' => 'عدم إظهار في الروزنامة',
583
-	'item_non_autoriser_syndication_integrale' => 'الاكتفاء بنشر ملخص',
584
-	'item_non_creer_fichiers_authent' => 'عدم إنشاء هذه الملفات',
585
-	'item_non_messagerie_agenda' => 'تعطيل المراسلة والمفكرة',
586
-	'item_non_publier_articles' => 'عدم نشر المقالات قبل تاريخها.',
587
-	'item_nouvel_auteur' => 'مؤلف جديد',
588
-	'item_nouvelle_rubrique' => 'قسم جديد',
589
-	'item_oui' => 'نعم',
590
-	'item_publier_articles' => 'نشر المقالات مهما كان تاريخها.',
591
-	'item_reponse_article' => 'الرد على المقال',
592
-	'item_visiteur' => 'زائر',
517
+    'info_traductions' => 'الترجمات',
518
+    'info_travail_colaboratif' => 'تحرير المقالات المشترك',
519
+    'info_un_article' => 'مقال، ',
520
+    'info_un_site' => 'موقع،',
521
+    'info_une_rubrique' => 'قسم،',
522
+    'info_une_rubrique_02' => 'قسم واحد',
523
+    'info_url' => 'عنوان URL:',
524
+    'info_url_proxy' => 'عنوان URL للجهاز الوكيل',
525
+    'info_url_proxy_pas_conforme' => 'عنوان الجهاز الوكيل غير صالح.',
526
+    'info_url_site_pas_conforme' => 'عنوان URL غير صالح.',
527
+    'info_url_test_proxy' => 'عنوان URL للاختبار',
528
+    'info_urlref' => 'وصلة هايبرتكست:',
529
+    'info_utilisation_spip' => 'أصبح نظام النشر الآلي جاهزاً للاستخدام...',
530
+    'info_visites_par_mois' => 'عرض حسب الشهر:',
531
+    'info_visiteur_1' => 'زائر',
532
+    'info_visiteur_2' => 'للموقع العمومي',
533
+    'info_visiteurs' => 'الزوار',
534
+    'info_visiteurs_02' => 'زوار الموقع العمومي',
535
+    'info_webmestre_forces' => 'المشرفون محددون حالياً في <tt>@file_options@</tt>.',
536
+    'install_adresse_base_hebergeur' => 'عنوان قاعدة البيانات التي خصصها لك المضيف',
537
+    'install_connect_ok' => 'تم فعلاً تعريف قاعدة البيانات باسم جهاز الخدمة @connect@.',
538
+    'install_echec_annonce' => 'الارجح ان التثبيت سيفشل او يؤدي الى موقع غير سليم...',
539
+    'install_extension_mbstring' => 'لا يعمل SPIP مع:',
540
+    'install_extension_php_obligatoire' => 'يتطلب SPIP ملحق php:',
541
+    'install_login_base_hebergeur' => 'معرّف الدخول الذي خصصه لك المضيف',
542
+    'install_nom_base_hebergeur' => 'اسم قاعدة البيانات الدي خصصه لك المضيف:',
543
+    'install_pas_table' => 'قاعدة من دون جداول حالياً',
544
+    'install_pass_base_hebergeur' => 'كلمة سر الاتصال التي خصصها لك المضيف',
545
+    'install_php_extension' => 'الملحقات التالية غير موجودة: @extensions@',
546
+    'install_php_version' => 'اصدار @version@ من PHP غير كاف(الحد الادنى = @minimum@)',
547
+    'install_php_version_max' => 'PHP إصدار @version@ حديث جداً (الحد الأقصى = @maximum@)',
548
+    'install_select_langue' => 'إختر لغة ثم انقر على الزر« التالي»  للبدء بعملية التثبيت.',
549
+    'install_select_type_db' => 'تحديد نوع قاعدة البيانات:',
550
+    'install_select_type_mysql' => 'MySQL',
551
+    'install_select_type_pg' => 'PostgreSQL',
552
+    'install_select_type_sqlite2' => 'SQLite 2',
553
+    'install_select_type_sqlite3' => 'SQLite 3',
554
+    'install_serveur_hebergeur' => 'خادم قواعد البيانات الذي يوفره المضيف ',
555
+    'install_table_prefix_hebergeur' => 'بادئة اسماء الجداول التي خصصها لك المضيف:',
556
+    'install_tables_base' => 'جداول القاعدة',
557
+    'install_types_db_connus' => 'يستطيع SPIP استخدام <b>MySQL</b> (الاكثر انتشاراً) و<b>SQLite</b>.',
558
+    'install_types_db_connus_avertissement' => 'يتوافر دعم <b>PostgreSQL</b> أيضاً على سبيل الاختبار',
559
+    'instituer_erreur_statut_a_change' => 'لقد تم تعديل الوضع من قبل',
560
+    'instituer_erreur_statut_non_autorise' => 'لا يمكن اختيار هذا الوضع',
561
+    'intem_redacteur' => 'محرر',
562
+    'intitule_licence' => 'الرخصة',
563
+    'item_accepter_inscriptions' => 'السماح بالتسجيل',
564
+    'item_activer_messages_avertissement' => 'تفعيل رسائل التحذير',
565
+    'item_administrateur_2' => 'مدير',
566
+    'item_afficher_calendrier' => 'إظهار في الروزنامة',
567
+    'item_autoriser_syndication_integrale' => 'نشر كامل المقالات في ملفات الترخيص',
568
+    'item_choix_administrateurs' => 'المدراء',
569
+    'item_choix_generation_miniature' => 'إنشاء مصغرات عن الصور آلياً.',
570
+    'item_choix_non_generation_miniature' => 'عدم إنشاء مصغرات عن الصور.',
571
+    'item_choix_redacteurs' => 'المحررون',
572
+    'item_choix_visiteurs' => 'زوار الموقع العمومي',
573
+    'item_creer_fichiers_authent' => 'إنشاء ملفات .htpasswd',
574
+    'item_login' => ' المعرّف',
575
+    'item_messagerie_agenda' => 'تفعيل المراسلة والمفكرة',
576
+    'item_mots_cles_association_articles' => 'المقالات',
577
+    'item_mots_cles_association_rubriques' => 'الأقسام',
578
+    'item_mots_cles_association_sites' => 'المواقع المبوبة او المرخصة.',
579
+    'item_non' => 'كلا',
580
+    'item_non_accepter_inscriptions' => 'عدم السماح بالتسجيل',
581
+    'item_non_activer_messages_avertissement' => 'تعطيل رسائل التحذير',
582
+    'item_non_afficher_calendrier' => 'عدم إظهار في الروزنامة',
583
+    'item_non_autoriser_syndication_integrale' => 'الاكتفاء بنشر ملخص',
584
+    'item_non_creer_fichiers_authent' => 'عدم إنشاء هذه الملفات',
585
+    'item_non_messagerie_agenda' => 'تعطيل المراسلة والمفكرة',
586
+    'item_non_publier_articles' => 'عدم نشر المقالات قبل تاريخها.',
587
+    'item_nouvel_auteur' => 'مؤلف جديد',
588
+    'item_nouvelle_rubrique' => 'قسم جديد',
589
+    'item_oui' => 'نعم',
590
+    'item_publier_articles' => 'نشر المقالات مهما كان تاريخها.',
591
+    'item_reponse_article' => 'الرد على المقال',
592
+    'item_visiteur' => 'زائر',
593 593
 
594
-	// J
595
-	'jour_non_connu_nc' => 'غير معروف',
594
+    // J
595
+    'jour_non_connu_nc' => 'غير معروف',
596 596
 
597
-	// L
598
-	'label_bando_outils' => 'شريط الأدوات',
599
-	'label_bando_outils_afficher' => 'عرض الأدوات',
600
-	'label_bando_outils_masquer' => 'إخفاء الأدوات',
601
-	'label_choix_langue' => 'حدد لغتك',
602
-	'label_nom_fichier_connect' => 'أدخل الاسم الذي يستخدمه هذا الخادم',
603
-	'label_slogan_site' => 'شعار الموقع',
604
-	'label_taille_ecran' => 'عرض الشاشة',
605
-	'label_texte_et_icones_navigation' => 'قائمة التصفح',
606
-	'label_texte_et_icones_page' => 'عرض في الصفحة',
607
-	'ldap_correspondance' => 'استلام من الحقل @champ@',
608
-	'ldap_correspondance_1' => 'استلام حقول LDAP',
609
-	'ldap_correspondance_2' => 'لكل من حقول SPIP التالية، حدد اسم حقل LDAP المناسب. يمكن ترك حقل فارغ، استخدام المسافات او الفواصل لتجربة عدة حقول LDAP.',
610
-	'lien_ajouter_auteur' => 'إضافة هذا المؤلف',
611
-	'lien_ajouter_une_rubrique' => 'إضافة هذا القسم',
612
-	'lien_email' => 'البريد الالكتروني',
613
-	'lien_nom_site' => 'إسم الموقع:',
614
-	'lien_rapide_contenu' => 'الذهاب الى المحتوى',
615
-	'lien_rapide_navigation' => 'الذهاب اى التصفح',
616
-	'lien_rapide_recherche' => 'الذهاب الى البحث',
617
-	'lien_retirer_auteur' => 'حذف المؤلف',
618
-	'lien_retirer_rubrique' => 'سحب القسم',
619
-	'lien_retirer_tous_auteurs' => 'إزالة جميع المؤلفين',
620
-	'lien_retirer_toutes_rubriques' => 'سحب كل الأقسام',
621
-	'lien_site' => 'الموقع',
622
-	'lien_tout_decocher' => 'إزالة تحديد الكل',
623
-	'lien_tout_deplier' => 'بسط الكل',
624
-	'lien_tout_replier' => 'طي الكل',
625
-	'lien_tout_supprimer' => 'حذف الكل',
626
-	'lien_trier_nom' => 'فرز حسب الإسم  ',
627
-	'lien_trier_nombre_articles' => 'فرز حسب عدد المقالات',
628
-	'lien_trier_statut' => 'فرز حسب الوضع',
629
-	'lien_voir_en_ligne' => 'عرض مباشر:',
630
-	'logo_article' => 'رمز المقال',
631
-	'logo_auteur' => 'رمز المؤلف',
632
-	'logo_rubrique' => 'رمز القسم',
633
-	'logo_site' => 'رمز هذا الموقع',
634
-	'logo_standard_rubrique' => 'رمز الأقسام القياسي',
635
-	'logo_survol' => 'رمز الحوم',
597
+    // L
598
+    'label_bando_outils' => 'شريط الأدوات',
599
+    'label_bando_outils_afficher' => 'عرض الأدوات',
600
+    'label_bando_outils_masquer' => 'إخفاء الأدوات',
601
+    'label_choix_langue' => 'حدد لغتك',
602
+    'label_nom_fichier_connect' => 'أدخل الاسم الذي يستخدمه هذا الخادم',
603
+    'label_slogan_site' => 'شعار الموقع',
604
+    'label_taille_ecran' => 'عرض الشاشة',
605
+    'label_texte_et_icones_navigation' => 'قائمة التصفح',
606
+    'label_texte_et_icones_page' => 'عرض في الصفحة',
607
+    'ldap_correspondance' => 'استلام من الحقل @champ@',
608
+    'ldap_correspondance_1' => 'استلام حقول LDAP',
609
+    'ldap_correspondance_2' => 'لكل من حقول SPIP التالية، حدد اسم حقل LDAP المناسب. يمكن ترك حقل فارغ، استخدام المسافات او الفواصل لتجربة عدة حقول LDAP.',
610
+    'lien_ajouter_auteur' => 'إضافة هذا المؤلف',
611
+    'lien_ajouter_une_rubrique' => 'إضافة هذا القسم',
612
+    'lien_email' => 'البريد الالكتروني',
613
+    'lien_nom_site' => 'إسم الموقع:',
614
+    'lien_rapide_contenu' => 'الذهاب الى المحتوى',
615
+    'lien_rapide_navigation' => 'الذهاب اى التصفح',
616
+    'lien_rapide_recherche' => 'الذهاب الى البحث',
617
+    'lien_retirer_auteur' => 'حذف المؤلف',
618
+    'lien_retirer_rubrique' => 'سحب القسم',
619
+    'lien_retirer_tous_auteurs' => 'إزالة جميع المؤلفين',
620
+    'lien_retirer_toutes_rubriques' => 'سحب كل الأقسام',
621
+    'lien_site' => 'الموقع',
622
+    'lien_tout_decocher' => 'إزالة تحديد الكل',
623
+    'lien_tout_deplier' => 'بسط الكل',
624
+    'lien_tout_replier' => 'طي الكل',
625
+    'lien_tout_supprimer' => 'حذف الكل',
626
+    'lien_trier_nom' => 'فرز حسب الإسم  ',
627
+    'lien_trier_nombre_articles' => 'فرز حسب عدد المقالات',
628
+    'lien_trier_statut' => 'فرز حسب الوضع',
629
+    'lien_voir_en_ligne' => 'عرض مباشر:',
630
+    'logo_article' => 'رمز المقال',
631
+    'logo_auteur' => 'رمز المؤلف',
632
+    'logo_rubrique' => 'رمز القسم',
633
+    'logo_site' => 'رمز هذا الموقع',
634
+    'logo_standard_rubrique' => 'رمز الأقسام القياسي',
635
+    'logo_survol' => 'رمز الحوم',
636 636
 
637
-	// M
638
-	'menu_aide_installation_choix_base' => 'إختيار قاعدة البيانات',
639
-	'module_fichier_langue' => 'ملف اللغة',
640
-	'module_raccourci' => 'اختصار',
641
-	'module_texte_affiche' => 'النص المعروض',
642
-	'module_texte_explicatif' => 'يمكن ادراج الاختصارات التالية في صفحات الموقع النموذجية. سوف تُترجم آلياً في مختلف اللغات التي يتوافر لها ملف لغة.',
643
-	'module_texte_traduction' => 'ملف اللغة «@module@» متوافر بـ:',
644
-	'mois_non_connu' => 'غير معروف',
637
+    // M
638
+    'menu_aide_installation_choix_base' => 'إختيار قاعدة البيانات',
639
+    'module_fichier_langue' => 'ملف اللغة',
640
+    'module_raccourci' => 'اختصار',
641
+    'module_texte_affiche' => 'النص المعروض',
642
+    'module_texte_explicatif' => 'يمكن ادراج الاختصارات التالية في صفحات الموقع النموذجية. سوف تُترجم آلياً في مختلف اللغات التي يتوافر لها ملف لغة.',
643
+    'module_texte_traduction' => 'ملف اللغة «@module@» متوافر بـ:',
644
+    'mois_non_connu' => 'غير معروف',
645 645
 
646
-	// N
647
-	'nouvelle_version_spip' => 'ترقية SPIP رقم @version@ متوافرة الآن',
648
-	'nouvelle_version_spip_majeure' => 'إصدار جديد من رقم @version@ من SPIP متوافر الآن',
646
+    // N
647
+    'nouvelle_version_spip' => 'ترقية SPIP رقم @version@ متوافرة الآن',
648
+    'nouvelle_version_spip_majeure' => 'إصدار جديد من رقم @version@ من SPIP متوافر الآن',
649 649
 
650
-	// O
651
-	'onglet_contenu' => 'المحتوى',
652
-	'onglet_declarer_une_autre_base' => 'الاعلان عن قاعدة اخرى',
653
-	'onglet_discuter' => 'النقاش',
654
-	'onglet_interactivite' => 'التفاعلية',
655
-	'onglet_proprietes' => 'الخصائص',
656
-	'onglet_repartition_actuelle' => 'حالياً',
657
-	'onglet_sous_rubriques' => 'الأقسام الفرعية',
650
+    // O
651
+    'onglet_contenu' => 'المحتوى',
652
+    'onglet_declarer_une_autre_base' => 'الاعلان عن قاعدة اخرى',
653
+    'onglet_discuter' => 'النقاش',
654
+    'onglet_interactivite' => 'التفاعلية',
655
+    'onglet_proprietes' => 'الخصائص',
656
+    'onglet_repartition_actuelle' => 'حالياً',
657
+    'onglet_sous_rubriques' => 'الأقسام الفرعية',
658 658
 
659
-	// P
660
-	'page_pas_proxy' => 'لا يجب ان تمر هذه الصفحة عبر جهاز بروكسي',
661
-	'pas_de_proxy_pour' => 'لدى الضرورة، حدد الاجهزة او النطاقات التي لا يجب ان ينطبق عليها الوكيل (مثلاً: @exemple@) ',
662
-	'phpinfo' => 'إعدادات PHP',
663
-	'plugin_charge_paquet' => 'تحميل رزمة @name@',
664
-	'plugin_charger' => 'تحميل',
665
-	'plugin_erreur_charger' => 'خطأ: لا يمكن تحميل @zip@',
666
-	'plugin_erreur_droit1' => 'المجلد <code>@dest@</code> لا يسمح بالكتابة فيه.',
667
-	'plugin_erreur_droit2' => 'الرجاء التأكد من الامتيازات على هذا المجلد (وانشائه اذا اقتضى الامر)، او تثبيت الملفات عبر FTP.',
668
-	'plugin_erreur_zip' => 'فشل pclzip: خطأ @status@',
669
-	'plugin_etat_developpement' => 'قيد التطوير',
670
-	'plugin_etat_experimental' => 'اختباري',
671
-	'plugin_etat_stable' => 'ثابت',
672
-	'plugin_etat_test' => 'قيد الاختبار',
673
-	'plugin_impossible_activer' => 'لا يمكن تفعيل الملحق @plugin@',
674
-	'plugin_info_automatique1' => 'اذا اردت السماح بالتثبيت الآلي للملحقات، الرجاء:',
675
-	'plugin_info_automatique1_lib' => 'أذا رغبت في السماح بالتثبيت الآلي لهذه المكتبة، يرجى:',
676
-	'plugin_info_automatique2' => 'انشاء المجلد <code>@rep@</code>،',
677
-	'plugin_info_automatique3' => 'التأكد من ان جهاز الخدمة يمكنه الكتابة في هذا المجلد.',
678
-	'plugin_info_automatique_creer' => 'يتم انشاؤه في اصل الموقع.',
679
-	'plugin_info_automatique_exemples' => 'أمثلة:',
680
-	'plugin_info_automatique_ftp' => 'يمكنك تثبيت الملحقات بواسطة FTP في المجلد <tt>@rep@</tt>',
681
-	'plugin_info_automatique_lib' => 'بعض الملحقات تتطلب ايضاً القدرة على تحميل ملفات في مجلد <code>lib/</code> الذي يتم انشاؤه في اصل الموقع اذا لزم الامر.',
682
-	'plugin_info_automatique_liste' => 'لوائح الملحقات:',
683
-	'plugin_info_automatique_liste_officielle' => 'الملحقات الرسمية',
684
-	'plugin_info_automatique_liste_update' => 'تحديث اللوائح',
685
-	'plugin_info_automatique_ou' => 'او...',
686
-	'plugin_info_automatique_select' => 'اختر احد الملحقات ادناه: سيقوم SPIP بتحميله وتثبيته في المجلد <code>@rep@</code>. اذا كان هذا الملحق موجوداً سوف يتم تحديثه.',
687
-	'plugin_info_credit' => 'الحقوق',
688
-	'plugin_info_erreur_xml' => 'تعريف هذا الملحق غير صحيح',
689
-	'plugin_info_install_ok' => 'نجح التثبيت',
690
-	'plugin_info_necessite' => 'يتطلب:',
691
-	'plugin_info_non_compatible_spip' => 'لا يتوافق هذا الملحق مع هذا الإصدار من SPIP',
692
-	'plugin_info_plugins_dist_1' => 'تم تحميل الإضافات أدناه وتفعيلها في مجلد @plugins_dist@.',
693
-	'plugin_info_plugins_dist_2' => 'لا يمكن إيقافها.',
694
-	'plugin_info_telecharger' => 'للتحميل من @url@ والتثبيت في @rep@',
695
-	'plugin_info_upgrade_ok' => 'نجحت الترقية',
696
-	'plugin_librairies_installees' => 'المكتبات المثبتة',
697
-	'plugin_necessite_extension_php' => 'يتطلب ملحق PHP @plugin@ إصدار @version@.',
698
-	'plugin_necessite_extension_php_sans_version' => 'يتطلب ملحق  PHP @plugin@',
699
-	'plugin_necessite_lib' => 'هذا الملحق يتطلب المكتبة @lib@',
700
-	'plugin_necessite_php' => 'يتطلب @plugin@ إصدار @version@.',
701
-	'plugin_necessite_plugin' => 'يتطلب الملحق @plugin@ بالاصدار @version@.',
702
-	'plugin_necessite_plugin_sans_version' => 'يتطلب الملحق @plugin@',
703
-	'plugin_necessite_spip' => 'يتطلب SPIP باصدار @version@ على الاقل.',
704
-	'plugin_source' => 'المصدر:',
705
-	'plugin_titre_automatique' => 'تثبيت آلي',
706
-	'plugin_titre_automatique_ajouter' => 'إضافة ملحقات',
707
-	'plugin_titre_installation' => 'تثبيت الملحق @plugin@',
708
-	'plugin_titre_modifier' => 'ملحقاتي',
709
-	'plugin_utilise_extension_php' => 'إصدار ملحق  PHP @plugin@ يجب ان يكون @version@.',
710
-	'plugin_utilise_php' => 'إصدار @plugin@ يجب ان يكون @version@.',
711
-	'plugin_utilise_plugin' => 'إصدار الملحق @plugin@ يجب ان يكون @version@.',
712
-	'plugin_zip_active' => 'تابع للتفعيل',
713
-	'plugin_zip_adresse' => 'ادخل ادناه عنوان ملف zip لملحق مطلوب تحميله او عنوان لائحة ملاحق.',
714
-	'plugin_zip_adresse_champ' => 'عنوان الملحق او اللائحة ',
715
-	'plugin_zip_content' => 'يحتوي الملفات التالية (@taille@)، بانتظار تثبيتها في المجلد <code>@rep@</code>',
716
-	'plugin_zip_installe_finie' => 'تم ازالة ضغط الملف @zip@ وتثبيته.',
717
-	'plugin_zip_installe_rep_finie' => 'تم ازالة ضغط الملف @zip@ وتثبيته في المجلد @rep@',
718
-	'plugin_zip_installer' => 'بمكنك الآن تثبيته.',
719
-	'plugin_zip_telecharge' => 'تم تحميل الملف @zip@',
720
-	'plugins_actif_aucun' => 'لا يوجد ملحقات نشطة',
721
-	'plugins_actif_un' => 'ملحق واحد نشط.',
722
-	'plugins_actifs' => '@count@ ملحق ناشط.',
723
-	'plugins_actifs_liste' => 'النشطة',
724
-	'plugins_compte' => '@count@ ملحق',
725
-	'plugins_disponible_un' => 'ملحق واحد متاح.',
726
-	'plugins_disponibles' => '@count@ ملحق متوافر.',
727
-	'plugins_erreur' => 'خطأ في الملحقات: @plugins@',
728
-	'plugins_liste' => 'لائحة الملحقات',
729
-	'plugins_liste_dist' => 'الملحقات المقفلة',
730
-	'plugins_recents' => 'أحدث الملحقات.',
731
-	'plugins_tous_liste' => 'الكل',
732
-	'plugins_vue_hierarchie' => 'الهرمية',
733
-	'plugins_vue_liste' => 'لائحة',
734
-	'protocole_ldap' => 'إصدار البروتوكول:',
659
+    // P
660
+    'page_pas_proxy' => 'لا يجب ان تمر هذه الصفحة عبر جهاز بروكسي',
661
+    'pas_de_proxy_pour' => 'لدى الضرورة، حدد الاجهزة او النطاقات التي لا يجب ان ينطبق عليها الوكيل (مثلاً: @exemple@) ',
662
+    'phpinfo' => 'إعدادات PHP',
663
+    'plugin_charge_paquet' => 'تحميل رزمة @name@',
664
+    'plugin_charger' => 'تحميل',
665
+    'plugin_erreur_charger' => 'خطأ: لا يمكن تحميل @zip@',
666
+    'plugin_erreur_droit1' => 'المجلد <code>@dest@</code> لا يسمح بالكتابة فيه.',
667
+    'plugin_erreur_droit2' => 'الرجاء التأكد من الامتيازات على هذا المجلد (وانشائه اذا اقتضى الامر)، او تثبيت الملفات عبر FTP.',
668
+    'plugin_erreur_zip' => 'فشل pclzip: خطأ @status@',
669
+    'plugin_etat_developpement' => 'قيد التطوير',
670
+    'plugin_etat_experimental' => 'اختباري',
671
+    'plugin_etat_stable' => 'ثابت',
672
+    'plugin_etat_test' => 'قيد الاختبار',
673
+    'plugin_impossible_activer' => 'لا يمكن تفعيل الملحق @plugin@',
674
+    'plugin_info_automatique1' => 'اذا اردت السماح بالتثبيت الآلي للملحقات، الرجاء:',
675
+    'plugin_info_automatique1_lib' => 'أذا رغبت في السماح بالتثبيت الآلي لهذه المكتبة، يرجى:',
676
+    'plugin_info_automatique2' => 'انشاء المجلد <code>@rep@</code>،',
677
+    'plugin_info_automatique3' => 'التأكد من ان جهاز الخدمة يمكنه الكتابة في هذا المجلد.',
678
+    'plugin_info_automatique_creer' => 'يتم انشاؤه في اصل الموقع.',
679
+    'plugin_info_automatique_exemples' => 'أمثلة:',
680
+    'plugin_info_automatique_ftp' => 'يمكنك تثبيت الملحقات بواسطة FTP في المجلد <tt>@rep@</tt>',
681
+    'plugin_info_automatique_lib' => 'بعض الملحقات تتطلب ايضاً القدرة على تحميل ملفات في مجلد <code>lib/</code> الذي يتم انشاؤه في اصل الموقع اذا لزم الامر.',
682
+    'plugin_info_automatique_liste' => 'لوائح الملحقات:',
683
+    'plugin_info_automatique_liste_officielle' => 'الملحقات الرسمية',
684
+    'plugin_info_automatique_liste_update' => 'تحديث اللوائح',
685
+    'plugin_info_automatique_ou' => 'او...',
686
+    'plugin_info_automatique_select' => 'اختر احد الملحقات ادناه: سيقوم SPIP بتحميله وتثبيته في المجلد <code>@rep@</code>. اذا كان هذا الملحق موجوداً سوف يتم تحديثه.',
687
+    'plugin_info_credit' => 'الحقوق',
688
+    'plugin_info_erreur_xml' => 'تعريف هذا الملحق غير صحيح',
689
+    'plugin_info_install_ok' => 'نجح التثبيت',
690
+    'plugin_info_necessite' => 'يتطلب:',
691
+    'plugin_info_non_compatible_spip' => 'لا يتوافق هذا الملحق مع هذا الإصدار من SPIP',
692
+    'plugin_info_plugins_dist_1' => 'تم تحميل الإضافات أدناه وتفعيلها في مجلد @plugins_dist@.',
693
+    'plugin_info_plugins_dist_2' => 'لا يمكن إيقافها.',
694
+    'plugin_info_telecharger' => 'للتحميل من @url@ والتثبيت في @rep@',
695
+    'plugin_info_upgrade_ok' => 'نجحت الترقية',
696
+    'plugin_librairies_installees' => 'المكتبات المثبتة',
697
+    'plugin_necessite_extension_php' => 'يتطلب ملحق PHP @plugin@ إصدار @version@.',
698
+    'plugin_necessite_extension_php_sans_version' => 'يتطلب ملحق  PHP @plugin@',
699
+    'plugin_necessite_lib' => 'هذا الملحق يتطلب المكتبة @lib@',
700
+    'plugin_necessite_php' => 'يتطلب @plugin@ إصدار @version@.',
701
+    'plugin_necessite_plugin' => 'يتطلب الملحق @plugin@ بالاصدار @version@.',
702
+    'plugin_necessite_plugin_sans_version' => 'يتطلب الملحق @plugin@',
703
+    'plugin_necessite_spip' => 'يتطلب SPIP باصدار @version@ على الاقل.',
704
+    'plugin_source' => 'المصدر:',
705
+    'plugin_titre_automatique' => 'تثبيت آلي',
706
+    'plugin_titre_automatique_ajouter' => 'إضافة ملحقات',
707
+    'plugin_titre_installation' => 'تثبيت الملحق @plugin@',
708
+    'plugin_titre_modifier' => 'ملحقاتي',
709
+    'plugin_utilise_extension_php' => 'إصدار ملحق  PHP @plugin@ يجب ان يكون @version@.',
710
+    'plugin_utilise_php' => 'إصدار @plugin@ يجب ان يكون @version@.',
711
+    'plugin_utilise_plugin' => 'إصدار الملحق @plugin@ يجب ان يكون @version@.',
712
+    'plugin_zip_active' => 'تابع للتفعيل',
713
+    'plugin_zip_adresse' => 'ادخل ادناه عنوان ملف zip لملحق مطلوب تحميله او عنوان لائحة ملاحق.',
714
+    'plugin_zip_adresse_champ' => 'عنوان الملحق او اللائحة ',
715
+    'plugin_zip_content' => 'يحتوي الملفات التالية (@taille@)، بانتظار تثبيتها في المجلد <code>@rep@</code>',
716
+    'plugin_zip_installe_finie' => 'تم ازالة ضغط الملف @zip@ وتثبيته.',
717
+    'plugin_zip_installe_rep_finie' => 'تم ازالة ضغط الملف @zip@ وتثبيته في المجلد @rep@',
718
+    'plugin_zip_installer' => 'بمكنك الآن تثبيته.',
719
+    'plugin_zip_telecharge' => 'تم تحميل الملف @zip@',
720
+    'plugins_actif_aucun' => 'لا يوجد ملحقات نشطة',
721
+    'plugins_actif_un' => 'ملحق واحد نشط.',
722
+    'plugins_actifs' => '@count@ ملحق ناشط.',
723
+    'plugins_actifs_liste' => 'النشطة',
724
+    'plugins_compte' => '@count@ ملحق',
725
+    'plugins_disponible_un' => 'ملحق واحد متاح.',
726
+    'plugins_disponibles' => '@count@ ملحق متوافر.',
727
+    'plugins_erreur' => 'خطأ في الملحقات: @plugins@',
728
+    'plugins_liste' => 'لائحة الملحقات',
729
+    'plugins_liste_dist' => 'الملحقات المقفلة',
730
+    'plugins_recents' => 'أحدث الملحقات.',
731
+    'plugins_tous_liste' => 'الكل',
732
+    'plugins_vue_hierarchie' => 'الهرمية',
733
+    'plugins_vue_liste' => 'لائحة',
734
+    'protocole_ldap' => 'إصدار البروتوكول:',
735 735
 
736
-	// Q
737
-	'queue_executer_maintenant' => 'تنفيذ الآن',
738
-	'queue_info_purger' => 'يمكنك حذف كل الأعمال في الانتظار وتأصيل لائحة الأعمال الدورية',
739
-	'queue_nb_jobs_in_queue' => '@nb@ عمل بالانتظار',
740
-	'queue_next_job_in_nb_sec' => 'العمل القادم خلال @nb@ ثانية',
741
-	'queue_no_job_in_queue' => 'لا توجد أعمال بالانتظار',
742
-	'queue_one_job_in_queue' => 'عمل واحد بالانتظار',
743
-	'queue_priorite_tache' => 'الأفضلية',
744
-	'queue_purger_queue' => 'تأصيل لائحة الأعمال',
745
-	'queue_titre' => 'أعمال الخلفية',
736
+    // Q
737
+    'queue_executer_maintenant' => 'تنفيذ الآن',
738
+    'queue_info_purger' => 'يمكنك حذف كل الأعمال في الانتظار وتأصيل لائحة الأعمال الدورية',
739
+    'queue_nb_jobs_in_queue' => '@nb@ عمل بالانتظار',
740
+    'queue_next_job_in_nb_sec' => 'العمل القادم خلال @nb@ ثانية',
741
+    'queue_no_job_in_queue' => 'لا توجد أعمال بالانتظار',
742
+    'queue_one_job_in_queue' => 'عمل واحد بالانتظار',
743
+    'queue_priorite_tache' => 'الأفضلية',
744
+    'queue_purger_queue' => 'تأصيل لائحة الأعمال',
745
+    'queue_titre' => 'أعمال الخلفية',
746 746
 
747
-	// R
748
-	'repertoire_plugins' => 'دليل:',
749
-	'required' => '(إجباري)',
747
+    // R
748
+    'repertoire_plugins' => 'دليل:',
749
+    'required' => '(إجباري)',
750 750
 
751
-	// S
752
-	'sans_heure' => 'بدون توقيت الساعات',
753
-	'statut_admin_restreint' => 'إدارة محدودة',
754
-	'statut_webmestre' => 'المشرف على الموقع',
751
+    // S
752
+    'sans_heure' => 'بدون توقيت الساعات',
753
+    'statut_admin_restreint' => 'إدارة محدودة',
754
+    'statut_webmestre' => 'المشرف على الموقع',
755 755
 
756
-	// T
757
-	'tache_cron_asap' => 'مهمة CRON @function@ (في أسرع وقت)',
758
-	'tache_cron_secondes' => 'مهمةCRON @function@ (كل @nb@ ثانية)',
759
-	'taille_cache_image' => 'تحتل الصور التي حسبها SPIP آلياً (مصغرات مستندات، عناوين معروضة كصور، دالات رياضية بتنسيق TeX...) مساحة اجمالية تبلغ @taille@ في الدليل @dir@.',
760
-	'taille_cache_infinie' => 'لا يضع هذا الموقع اي حدود لحجم دليل الذاكرة المخبأة.',
761
-	'taille_cache_maxi' => 'يحاول SPIP الحد من حجم دليل الذاكرة المخبأة في هذا الموقع لكي لا يتعدى <b>@octets@</b> من البيانات.',
762
-	'taille_cache_moins_de' => 'حجم الذاكرة المخبأة أقل من @octets@.',
763
-	'taille_cache_octets' => 'يبلغ حجم الذاكرة المخبأة حالياً @octets@ تقريباً.',
764
-	'taille_cache_vide' => 'الذاكرة المخبأة فارغة.',
765
-	'taille_repertoire_cache' => 'حجم دليل الذاكرة المخبأة',
766
-	'text_article_propose_publication' => 'مقال معروض للنشر.',
767
-	'texte_acces_ldap_anonyme_1' => 'بعض خدام LDAP تمنع الدخول المغفل. في هذه الحال عليك بإدخال بيانات دخول أولية لتتمكن من البحث عن معلومات في الدليل لاحقاً. إلا أنه، في معظم الأحيان، يمكن ترك الحقول التالية فارغة.',
768
-	'texte_admin_effacer_01' => 'يقوم هذا الأمر بحذف  كامل محتوى قاعدة البيانات،
756
+    // T
757
+    'tache_cron_asap' => 'مهمة CRON @function@ (في أسرع وقت)',
758
+    'tache_cron_secondes' => 'مهمةCRON @function@ (كل @nb@ ثانية)',
759
+    'taille_cache_image' => 'تحتل الصور التي حسبها SPIP آلياً (مصغرات مستندات، عناوين معروضة كصور، دالات رياضية بتنسيق TeX...) مساحة اجمالية تبلغ @taille@ في الدليل @dir@.',
760
+    'taille_cache_infinie' => 'لا يضع هذا الموقع اي حدود لحجم دليل الذاكرة المخبأة.',
761
+    'taille_cache_maxi' => 'يحاول SPIP الحد من حجم دليل الذاكرة المخبأة في هذا الموقع لكي لا يتعدى <b>@octets@</b> من البيانات.',
762
+    'taille_cache_moins_de' => 'حجم الذاكرة المخبأة أقل من @octets@.',
763
+    'taille_cache_octets' => 'يبلغ حجم الذاكرة المخبأة حالياً @octets@ تقريباً.',
764
+    'taille_cache_vide' => 'الذاكرة المخبأة فارغة.',
765
+    'taille_repertoire_cache' => 'حجم دليل الذاكرة المخبأة',
766
+    'text_article_propose_publication' => 'مقال معروض للنشر.',
767
+    'texte_acces_ldap_anonyme_1' => 'بعض خدام LDAP تمنع الدخول المغفل. في هذه الحال عليك بإدخال بيانات دخول أولية لتتمكن من البحث عن معلومات في الدليل لاحقاً. إلا أنه، في معظم الأحيان، يمكن ترك الحقول التالية فارغة.',
768
+    'texte_admin_effacer_01' => 'يقوم هذا الأمر بحذف  كامل محتوى قاعدة البيانات،
769 769
 بما في ذلك كل  وسائط الوصول للمحررين والمدراء. بعد تنفيذه، يتحتم عليك
770 770
 إعادة تثبيت SPIP لإعادة إنتاج قاعدة جديدة ووسيط دخول أول مدير.',
771
-	'texte_adresse_annuaire_1' => 'إذا كان دليلك مثبت على الجهاز نفسه الذي يحتوي موقعك، فإنه على الأرجح «localhost»)).',
772
-	'texte_ajout_auteur' => 'تمت إضافة المؤلف التالي الى المقال:',
773
-	'texte_annuaire_ldap_1' => 'إذا كان لديك إمكتان وصول الى دليل LDAP، يمكنك استخدامه لجلب المستخدمين آلياً الى SPIP.',
774
-	'texte_article_statut' => 'هذا المقال:',
775
-	'texte_article_virtuel' => 'مقال إفتراضي',
776
-	'texte_article_virtuel_reference' => '<b>مقال إفتراضي: <b/>مقال مبوّب في موقع SPIP لديك، لكنه موجه الى عنوان آخر. لإلغاء التوجيه، قم بحذف العنوان أعلاه.',
777
-	'texte_aucun_resultat_auteur' => 'لا توجد نتائج لـ "@cherche_auteur@"',
778
-	'texte_auteur_messagerie' => 'يمكن لهذا الموقع رصد قائمة المحررين المتصلين بشكل دائم مما يتيح لك تبادل الرسائل في الوقت الحقيقي. يمكنك التقرير بعدم الظهور في هذه القائمة (وبالتالي تكون «مخفياً» بالنسبة للمستخدمين الآخرين).',
779
-	'texte_auteurs' => 'المؤلفون',
780
-	'texte_choix_base_1' => 'حدد قاعدة بياناتك:',
781
-	'texte_choix_base_2' => 'يحتوي خادم SQL على عدة قواعد بيانات.',
782
-	'texte_choix_base_3' => '<b>حدد</b> أدناه القاعدة التي خصصها مضيفك لك:',
783
-	'texte_choix_table_prefix' => 'بادئة الجداول:',
784
-	'texte_compte_element' => 'عنصر@count@',
785
-	'texte_compte_elements' => 'عنصر@count@',
786
-	'texte_conflit_edition_correction' => 'الرجاء التدقيق ادناه في الفوارق بين إصداري النص. يمكنك ايضاً تسخ تعديلاتك ثم البدء من جديد.',
787
-	'texte_connexion_mysql' => 'راجع المعلومات التي زودك بها مضيفك:  من المفترض ان تجد فيها خادم قاعدة البيانات وبيانات اتصالك الشخصية بالقاعدة.',
788
-	'texte_contenu_article' => '(محتوى المقال في بضع كلمات.)',
789
-	'texte_contenu_articles' => 'اعتماداً على تصميم موقعك، يمكنك اختيار
771
+    'texte_adresse_annuaire_1' => 'إذا كان دليلك مثبت على الجهاز نفسه الذي يحتوي موقعك، فإنه على الأرجح «localhost»)).',
772
+    'texte_ajout_auteur' => 'تمت إضافة المؤلف التالي الى المقال:',
773
+    'texte_annuaire_ldap_1' => 'إذا كان لديك إمكتان وصول الى دليل LDAP، يمكنك استخدامه لجلب المستخدمين آلياً الى SPIP.',
774
+    'texte_article_statut' => 'هذا المقال:',
775
+    'texte_article_virtuel' => 'مقال إفتراضي',
776
+    'texte_article_virtuel_reference' => '<b>مقال إفتراضي: <b/>مقال مبوّب في موقع SPIP لديك، لكنه موجه الى عنوان آخر. لإلغاء التوجيه، قم بحذف العنوان أعلاه.',
777
+    'texte_aucun_resultat_auteur' => 'لا توجد نتائج لـ "@cherche_auteur@"',
778
+    'texte_auteur_messagerie' => 'يمكن لهذا الموقع رصد قائمة المحررين المتصلين بشكل دائم مما يتيح لك تبادل الرسائل في الوقت الحقيقي. يمكنك التقرير بعدم الظهور في هذه القائمة (وبالتالي تكون «مخفياً» بالنسبة للمستخدمين الآخرين).',
779
+    'texte_auteurs' => 'المؤلفون',
780
+    'texte_choix_base_1' => 'حدد قاعدة بياناتك:',
781
+    'texte_choix_base_2' => 'يحتوي خادم SQL على عدة قواعد بيانات.',
782
+    'texte_choix_base_3' => '<b>حدد</b> أدناه القاعدة التي خصصها مضيفك لك:',
783
+    'texte_choix_table_prefix' => 'بادئة الجداول:',
784
+    'texte_compte_element' => 'عنصر@count@',
785
+    'texte_compte_elements' => 'عنصر@count@',
786
+    'texte_conflit_edition_correction' => 'الرجاء التدقيق ادناه في الفوارق بين إصداري النص. يمكنك ايضاً تسخ تعديلاتك ثم البدء من جديد.',
787
+    'texte_connexion_mysql' => 'راجع المعلومات التي زودك بها مضيفك:  من المفترض ان تجد فيها خادم قاعدة البيانات وبيانات اتصالك الشخصية بالقاعدة.',
788
+    'texte_contenu_article' => '(محتوى المقال في بضع كلمات.)',
789
+    'texte_contenu_articles' => 'اعتماداً على تصميم موقعك، يمكنك اختيار
790 790
 عدم استخدام بعض عناصر المقالات.
791 791
 إستخدم القائمة التالية لاختيار العناصر التي ستكون متاحة.',
792
-	'texte_crash_base' => 'إذا حصل عطل في
792
+    'texte_crash_base' => 'إذا حصل عطل في
793 793
 قاعدتك، يمكنك محاولة إصلاحها
794 794
 آلياً.',
795
-	'texte_creer_rubrique' => 'قبل التمكن من كتابة مقالات،<br />يجب عليك إنشاء قسم واحد على الأقل.',
796
-	'texte_date_creation_article' => 'تاريخ إنشاء المقال:',
797
-	'texte_date_creation_objet' => 'تاريخ الانشاء:', # on ajoute le &quot;:&quot;
798
-	'texte_date_publication_anterieure' => 'تاريخ النشر السابق:',
799
-	'texte_date_publication_anterieure_nonaffichee' => 'إخفاء تاريخ النشر السابق.',
800
-	'texte_date_publication_article' => 'تاريخ النشر:',
801
-	'texte_date_publication_objet' => 'تاريخ النشر:',
802
-	'texte_definir_comme_traduction_rubrique' => 'هذا القسم هو ترجمة للقسم رقم:',
803
-	'texte_descriptif_rapide' => 'وصف مقتضب',
804
-	'texte_effacer_base' => 'حذف قاعدة بيانات SPIP',
805
-	'texte_effacer_statistiques' => 'حذف الاحصاءات',
806
-	'texte_en_cours_validation' => 'المقالات والأخبار التالية معروضة للنشر.',
807
-	'texte_enrichir_mise_a_jour' => 'يمكنك استخدام «إختصارات الكتابة» لتحسين مظهر مادتك.',
808
-	'texte_fichier_authent' => '<b>هل يقوم SPIP بإنشاء الملفات الخاصة<tt>.htpasswd</tt>
795
+    'texte_creer_rubrique' => 'قبل التمكن من كتابة مقالات،<br />يجب عليك إنشاء قسم واحد على الأقل.',
796
+    'texte_date_creation_article' => 'تاريخ إنشاء المقال:',
797
+    'texte_date_creation_objet' => 'تاريخ الانشاء:', # on ajoute le &quot;:&quot;
798
+    'texte_date_publication_anterieure' => 'تاريخ النشر السابق:',
799
+    'texte_date_publication_anterieure_nonaffichee' => 'إخفاء تاريخ النشر السابق.',
800
+    'texte_date_publication_article' => 'تاريخ النشر:',
801
+    'texte_date_publication_objet' => 'تاريخ النشر:',
802
+    'texte_definir_comme_traduction_rubrique' => 'هذا القسم هو ترجمة للقسم رقم:',
803
+    'texte_descriptif_rapide' => 'وصف مقتضب',
804
+    'texte_effacer_base' => 'حذف قاعدة بيانات SPIP',
805
+    'texte_effacer_statistiques' => 'حذف الاحصاءات',
806
+    'texte_en_cours_validation' => 'المقالات والأخبار التالية معروضة للنشر.',
807
+    'texte_enrichir_mise_a_jour' => 'يمكنك استخدام «إختصارات الكتابة» لتحسين مظهر مادتك.',
808
+    'texte_fichier_authent' => '<b>هل يقوم SPIP بإنشاء الملفات الخاصة<tt>.htpasswd</tt>
809 809
 و<tt>.htpasswd-admin</tt> في المجلد @dossier@؟</b>
810 810
 <p>تستخدم هذه الملفات للحد من دخول المؤلفين
811 811
  والمدراء الى اجزاء اخرى من الموقع
@@ -813,42 +813,42 @@  discard block
 block discarded – undo
813 813
 إذا كنت لا تحتاج الى هذه الملفات يمكنك الإبقاء على القيمة
814 814
 الافتراضية لهذا الخيار (عدم إنشاء 
815 815
 الملفات).</p>',
816
-	'texte_informations_personnelles_1' => 'سيزودك النظام الآن بدخول شخصي الى الموقع.',
817
-	'texte_informations_personnelles_2' => '(ملاحظة: هذه إعادة تثبيت، اذا كان دخولك لا يزال يعمل، يمكنك',
818
-	'texte_introductif_article' => '(نص تقديمي للمقال)',
819
-	'texte_jeu_caractere' => 'يستحسن استخدام طقم الحروف الشامل (<tt>utf-8</tt>): يسمح هذا الطقم بعرض نصوص بجميع اللغات ولا يتسبب بمشاكل توافق مع برامج التصفح الحديثة.',
820
-	'texte_jeu_caractere_3' => 'موقعك يستخدم حالياً طقم الحروف:',
821
-	'texte_jeu_caractere_4' => 'اذا كان ذلك لا يتناسب مع واقع بياناتك (من جراء استرجاع نسخة احتياطية من القاعدة مثلاً) او اذا كنت <strong>تباشر في اطلاق هذا الموقع</strong> وترغب في استخدام طقم حروف آخر، الرجاء تحديد هذا الطقم هنا:',
822
-	'texte_login_ldap_1' => ')أتركه فارغاً للدخول المغفل أو قم بإدخال المسار الكامل، مثلاً «<tt>uid=salim, ou=users, dc=mon-domaine, dc=com</tt>»).',
823
-	'texte_login_precaution' => 'تحذير! هذا هو المعرّف الذي تتصل من خلاله الآن.
816
+    'texte_informations_personnelles_1' => 'سيزودك النظام الآن بدخول شخصي الى الموقع.',
817
+    'texte_informations_personnelles_2' => '(ملاحظة: هذه إعادة تثبيت، اذا كان دخولك لا يزال يعمل، يمكنك',
818
+    'texte_introductif_article' => '(نص تقديمي للمقال)',
819
+    'texte_jeu_caractere' => 'يستحسن استخدام طقم الحروف الشامل (<tt>utf-8</tt>): يسمح هذا الطقم بعرض نصوص بجميع اللغات ولا يتسبب بمشاكل توافق مع برامج التصفح الحديثة.',
820
+    'texte_jeu_caractere_3' => 'موقعك يستخدم حالياً طقم الحروف:',
821
+    'texte_jeu_caractere_4' => 'اذا كان ذلك لا يتناسب مع واقع بياناتك (من جراء استرجاع نسخة احتياطية من القاعدة مثلاً) او اذا كنت <strong>تباشر في اطلاق هذا الموقع</strong> وترغب في استخدام طقم حروف آخر، الرجاء تحديد هذا الطقم هنا:',
822
+    'texte_login_ldap_1' => ')أتركه فارغاً للدخول المغفل أو قم بإدخال المسار الكامل، مثلاً «<tt>uid=salim, ou=users, dc=mon-domaine, dc=com</tt>»).',
823
+    'texte_login_precaution' => 'تحذير! هذا هو المعرّف الذي تتصل من خلاله الآن.
824 824
 إستخدم هذه الاستمارة بحذر...',
825
-	'texte_messagerie_agenda' => 'يتيح نظام مراسلة لمحرري الموقع التواصل بين بعضهم مباشرة في المجال الخاص. وهو مرتبط بالمفكرة.',
826
-	'texte_mise_a_niveau_base_1' => 'لقد قمت بتحديث ملفات SPIP.
825
+    'texte_messagerie_agenda' => 'يتيح نظام مراسلة لمحرري الموقع التواصل بين بعضهم مباشرة في المجال الخاص. وهو مرتبط بالمفكرة.',
826
+    'texte_mise_a_niveau_base_1' => 'لقد قمت بتحديث ملفات SPIP.
827 827
 يجب الآن تحديث قاعدة بيانات
828 828
 الموقع.',
829
-	'texte_modifier_article' => 'تعديل المقال:',
830
-	'texte_multilinguisme' => 'اذا احتجت الى إدارة عناصر متعددة اللغات وبتصفح معقّد، يمكنك إضافة قائمة اختيار اللغة في هذه العناصر تتماشى مع تنظيم موقعك.',
831
-	'texte_multilinguisme_trad' => 'يمكنك ايضاً تفعيل نظام لإدارة الروابط بين الترجمات المختلفة لبعض العناصر.',
832
-	'texte_non_compresse' => 'غير مضغوط (خادمك لا يدعم هذه الوظيفة)',
833
-	'texte_nouvelle_version_spip_1' => 'لقد قمت بتثبيت إصدار جديد من SPIP.',
834
-	'texte_nouvelle_version_spip_2' => 'هذا الإصدار الجديد يتطلب تحديثاً أكثر عمقاً من المعتاد. إذا كنت مسؤولاً عن هذا الموقع، الرجاء حذف الملف @connect@ وإعادة تنفيذ عملية التثبيت من أجل تحديث بيانات الاتصال بالقاعدة. <p> ( ملاحظة: إذا نسيت بيانات الاتصال، أنظر في الملف @connect@ قبل حذفه...)</p>',
835
-	'texte_operation_echec' => 'عد الى الصفحة السابقة وحدد قاعدة بيانات أخرى أو قم بإنشاء قاعدة جديدة. تأكد من المعلومات التي حصلت عليها من مضيفك',
836
-	'texte_plus_trois_car' => 'أكثر من ثلاثة أحرف',
837
-	'texte_plusieurs_articles' => 'تم العثور على عدة مؤلفين لـ "@cherche_auteur@":',
838
-	'texte_port_annuaire' => '(القيمة الافتراضية مناسبة عموماً).',
839
-	'texte_presente_plugin' => 'تعرض هذه الصفحة لائحة بالملحقات المتوافرة في موقعك. يمكنك تفعيل الملحقات التي تريدها بالنقر على الخانات المناسبة لها.',
840
-	'texte_proposer_publication' => 'عندما تنتهي من مقالك،<br />يمكنك عرضه للنشر.',
841
-	'texte_proxy' => 'في بعض الحالات (انترانت، شبكات محمية...)، لا يمكن الوصول الى المواقع البعيدة (توثيق SPIP، المواقع المرخصة...) الا من خلال <b>جهاز وكيل</b>. اذا لزم الامر، حدد ادناه عنوان الجهاز على الشكل @proxy_en_cours@. بشكل عام اترك هذه الخانة فارغة.',
842
-	'texte_publication_articles_post_dates' => 'كيف يجب على SPIP  ان يتصرف بالنسبة للمقالات التي
829
+    'texte_modifier_article' => 'تعديل المقال:',
830
+    'texte_multilinguisme' => 'اذا احتجت الى إدارة عناصر متعددة اللغات وبتصفح معقّد، يمكنك إضافة قائمة اختيار اللغة في هذه العناصر تتماشى مع تنظيم موقعك.',
831
+    'texte_multilinguisme_trad' => 'يمكنك ايضاً تفعيل نظام لإدارة الروابط بين الترجمات المختلفة لبعض العناصر.',
832
+    'texte_non_compresse' => 'غير مضغوط (خادمك لا يدعم هذه الوظيفة)',
833
+    'texte_nouvelle_version_spip_1' => 'لقد قمت بتثبيت إصدار جديد من SPIP.',
834
+    'texte_nouvelle_version_spip_2' => 'هذا الإصدار الجديد يتطلب تحديثاً أكثر عمقاً من المعتاد. إذا كنت مسؤولاً عن هذا الموقع، الرجاء حذف الملف @connect@ وإعادة تنفيذ عملية التثبيت من أجل تحديث بيانات الاتصال بالقاعدة. <p> ( ملاحظة: إذا نسيت بيانات الاتصال، أنظر في الملف @connect@ قبل حذفه...)</p>',
835
+    'texte_operation_echec' => 'عد الى الصفحة السابقة وحدد قاعدة بيانات أخرى أو قم بإنشاء قاعدة جديدة. تأكد من المعلومات التي حصلت عليها من مضيفك',
836
+    'texte_plus_trois_car' => 'أكثر من ثلاثة أحرف',
837
+    'texte_plusieurs_articles' => 'تم العثور على عدة مؤلفين لـ "@cherche_auteur@":',
838
+    'texte_port_annuaire' => '(القيمة الافتراضية مناسبة عموماً).',
839
+    'texte_presente_plugin' => 'تعرض هذه الصفحة لائحة بالملحقات المتوافرة في موقعك. يمكنك تفعيل الملحقات التي تريدها بالنقر على الخانات المناسبة لها.',
840
+    'texte_proposer_publication' => 'عندما تنتهي من مقالك،<br />يمكنك عرضه للنشر.',
841
+    'texte_proxy' => 'في بعض الحالات (انترانت، شبكات محمية...)، لا يمكن الوصول الى المواقع البعيدة (توثيق SPIP، المواقع المرخصة...) الا من خلال <b>جهاز وكيل</b>. اذا لزم الامر، حدد ادناه عنوان الجهاز على الشكل @proxy_en_cours@. بشكل عام اترك هذه الخانة فارغة.',
842
+    'texte_publication_articles_post_dates' => 'كيف يجب على SPIP  ان يتصرف بالنسبة للمقالات التي
843 843
 تم تحديد تاريخها
844 844
 	في المستقبل؟',
845
-	'texte_rappel_selection_champs' => '[لا تنسى ان تحدد هذا الحقل بشكل صحيح]',
846
-	'texte_recalcul_page' => 'إذا كنت ترغب
845
+    'texte_rappel_selection_champs' => '[لا تنسى ان تحدد هذا الحقل بشكل صحيح]',
846
+    'texte_recalcul_page' => 'إذا كنت ترغب
847 847
 في تحديث صفحة واحدة، الأحرى بك تنفيذ هذه العملية من الموقع العمومي باستخدام زر «تحديث» الصفحة.
848 848
 ',
849
-	'texte_recuperer_base' => 'إصلاح قاعدة البيانات',
850
-	'texte_reference_mais_redirige' => 'مقال مبوّب في موقع SPIP لديك، لكنه موجه الى عنوان آخر.',
851
-	'texte_requetes_echouent' => '<b>عندما يفشل بعض إستفسارات SQL
849
+    'texte_recuperer_base' => 'إصلاح قاعدة البيانات',
850
+    'texte_reference_mais_redirige' => 'مقال مبوّب في موقع SPIP لديك، لكنه موجه الى عنوان آخر.',
851
+    'texte_requetes_echouent' => '<b>عندما يفشل بعض إستفسارات SQL
852 852
 بشكل منتظم ومتكرر دون أي سبب ظاهر، قد يكون
853 853
 العطل في قاعدة البيانات 
854 854
   نفسها.</b><p>
@@ -858,90 +858,90 @@  discard block
 block discarded – undo
858 858
 أدلة عن المشكلة...</p><p>
859 859
 إذا استمرت المشكلة إتصل
860 860
   بمضيف موقعك.</p>',
861
-	'texte_selection_langue_principale' => 'أدناه يمكنك تحديد «اللغة الأساسية » للموقع. لحسن الحظ لن يفرض عليك هذا الخيار تحرير مقالاتك باللغة المحددة، الا انه يحدد:
861
+    'texte_selection_langue_principale' => 'أدناه يمكنك تحديد «اللغة الأساسية » للموقع. لحسن الحظ لن يفرض عليك هذا الخيار تحرير مقالاتك باللغة المحددة، الا انه يحدد:
862 862
 <ul><li> تنسيق التواريخ الافتراضي في الموقع العام؛</li>
863 863
 <ul><li> طبيعة محرك الكتابة الذي يجب على SPIP استخدامه لتنسيق النصوص؛</li>
864 864
 <ul><li> اللغة المستخدمة في إستمارات الموقع العام؛</li>
865 865
 <ul><li> اللغة الافتراضية التي يعرضها المجال الخاص. </li></ul>',
866
-	'texte_sous_titre' => 'العنوان الفرعي',
867
-	'texte_statistiques_visites' => '(القضبان الداكنة: الأحد / المنحنيات الداكنة: التطور الوسطي)',
868
-	'texte_statut_attente_validation' => 'بانتظار التصديق',
869
-	'texte_statut_publies' => 'منشور',
870
-	'texte_statut_refuses' => 'مرفوض',
871
-	'texte_suppression_fichiers' => 'إستخدم هذا الأمر لحذف كل الملفات الموجودة
866
+    'texte_sous_titre' => 'العنوان الفرعي',
867
+    'texte_statistiques_visites' => '(القضبان الداكنة: الأحد / المنحنيات الداكنة: التطور الوسطي)',
868
+    'texte_statut_attente_validation' => 'بانتظار التصديق',
869
+    'texte_statut_publies' => 'منشور',
870
+    'texte_statut_refuses' => 'مرفوض',
871
+    'texte_suppression_fichiers' => 'إستخدم هذا الأمر لحذف كل الملفات الموجودة
872 872
 في الذاكرة المخبأة. ويتيح لك ذلك، من بين أمور أخرى، فرض تحديث كل الصفحات في حال
873 873
 قمت بإدخال تعديلات مهمة على الرسوم أو التصميم في الموقع. ',
874
-	'texte_sur_titre' => 'العنوان المدخل',
875
-	'texte_table_ok' => ': هذا الجدول صالح.',
876
-	'texte_tentative_recuperation' => 'محاولة إصلاح',
877
-	'texte_tenter_reparation' => 'محاولة إصلاح قاعدة البيانات',
878
-	'texte_test_proxy' => 'لتجربة الجهاز الوكيل، قم بإدخال عنوان موقع 
874
+    'texte_sur_titre' => 'العنوان المدخل',
875
+    'texte_table_ok' => ': هذا الجدول صالح.',
876
+    'texte_tentative_recuperation' => 'محاولة إصلاح',
877
+    'texte_tenter_reparation' => 'محاولة إصلاح قاعدة البيانات',
878
+    'texte_test_proxy' => 'لتجربة الجهاز الوكيل، قم بإدخال عنوان موقع 
879 879
 				ترغب في زيارته.',
880
-	'texte_titre_02' => 'الإسم:',
881
-	'texte_titre_obligatoire' => '<b>العنوان</b> [إجباري]',
882
-	'texte_travail_article' => '@nom_auteur_modif@ تعامل مع هذا المقال منذ @date_diff@ دقيقة',
883
-	'texte_travail_collaboratif' => 'كثيراً ما يحدث أن يتعاون
880
+    'texte_titre_02' => 'الإسم:',
881
+    'texte_titre_obligatoire' => '<b>العنوان</b> [إجباري]',
882
+    'texte_travail_article' => '@nom_auteur_modif@ تعامل مع هذا المقال منذ @date_diff@ دقيقة',
883
+    'texte_travail_collaboratif' => 'كثيراً ما يحدث أن يتعاون
884 884
 عدة محررين في تحرير المقال نفسه، فيمكن
885 885
 للنظام أن يعرض المقالات «المفتوحة» حديثاً
886 886
 بهدف تجنب إدخال تعديلات متزامنة عليها.
887 887
 هذا الخيار متوقف افتراضياً
888 888
 لتجنب عرض رسائل تحذير
889 889
 مفاجئة.',
890
-	'texte_vide' => 'فارغ',
891
-	'texte_vider_cache' => 'تفريغ الذاكرة المخبأة',
892
-	'titre_admin_tech' => 'صيانة تقنية',
893
-	'titre_admin_vider' => 'صيانة تقنية',
894
-	'titre_ajouter_un_auteur' => 'إضافة مؤلف',
895
-	'titre_ajouter_un_mot' => 'إضافة مفتاح',
896
-	'titre_cadre_afficher_article' => 'إظهار المقالات',
897
-	'titre_cadre_afficher_traductions' => 'عرض وضع الترجمات للغات التالية:',
898
-	'titre_cadre_ajouter_auteur' => 'إضافة مؤلف:',
899
-	'titre_cadre_interieur_rubrique' => 'في القسم',
900
-	'titre_cadre_numero_auteur' => 'مؤلف رقم',
901
-	'titre_cadre_numero_objet' => '@objet@ رقم:',
902
-	'titre_cadre_signature_obligatoire' => '<b>التوقيع<b> [إجباري]<br />',
903
-	'titre_config_contenu_notifications' => 'تبليغات',
904
-	'titre_config_contenu_prive' => 'في المجال الخاص',
905
-	'titre_config_contenu_public' => 'في الموقع العمومي',
906
-	'titre_config_fonctions' => 'إعداد الموقع',
907
-	'titre_config_langage' => 'إعداد اللغة',
908
-	'titre_configuration' => 'إعداد الموقع',
909
-	'titre_configurer_preferences' => 'إعداد التفضيلات',
910
-	'titre_configurer_preferences_menus' => 'إعداد تفضيلات القوائم',
911
-	'titre_conflit_edition' => 'تضارب لدى التحرير',
912
-	'titre_connexion_ldap' => 'خيارات: <b>إتصالLDAP </b>',
913
-	'titre_groupe_mots' => 'مجموعة مفاتيح:',
914
-	'titre_identite_site' => 'هوية الموقع',
915
-	'titre_langue_article' => 'لغة المقال',
916
-	'titre_langue_rubrique' => 'لغة القسم',
917
-	'titre_langue_trad_article' => 'لغة المقال وترجماته',
918
-	'titre_les_articles' => 'المقالات',
919
-	'titre_messagerie_agenda' => 'المراسلة والمفكرة',
920
-	'titre_naviguer_dans_le_site' => 'تصفح الموقع...',
921
-	'titre_nouvelle_rubrique' => 'قسم جديد',
922
-	'titre_numero_rubrique' => 'قسم رقم:',
923
-	'titre_page_articles_edit' => 'تعديل: @titre@',
924
-	'titre_page_articles_page' => 'المقالات',
925
-	'titre_page_articles_tous' => 'الموقع بالكامل',
926
-	'titre_page_calendrier' => 'روزنامة @nom_mois@ @annee@',
927
-	'titre_page_config_contenu' => 'إعداد الموقع',
928
-	'titre_page_delete_all' => 'حذف تام ونهائي',
929
-	'titre_page_recherche' => 'نتائج البحث @recherche@',
930
-	'titre_page_statistiques_referers' => 'الاحصاءات (الوصلات الآتية)',
931
-	'titre_page_upgrade' => 'ترقية SPIP',
932
-	'titre_preference_menus_favoris' => 'قائمة المفضلات',
933
-	'titre_publication_articles_post_dates' => 'نشر المقالات المؤجلة',
934
-	'titre_reparation' => 'إصلاح',
935
-	'titre_suivi_petition' => 'متابعة العرائض',
936
-	'tls_ldap' => 'أمان طبقة النقل:',
937
-	'trad_article_traduction' => 'كل اصدارات هذا المقال:',
938
-	'trad_delier' => 'ايقاف الربط هذا بهذه الترجمات',
939
-	'trad_lier' => 'هذا المقال هو ترجمة للمقال رقم:',
940
-	'trad_new' => 'كتابة ترجمة جديدة',
890
+    'texte_vide' => 'فارغ',
891
+    'texte_vider_cache' => 'تفريغ الذاكرة المخبأة',
892
+    'titre_admin_tech' => 'صيانة تقنية',
893
+    'titre_admin_vider' => 'صيانة تقنية',
894
+    'titre_ajouter_un_auteur' => 'إضافة مؤلف',
895
+    'titre_ajouter_un_mot' => 'إضافة مفتاح',
896
+    'titre_cadre_afficher_article' => 'إظهار المقالات',
897
+    'titre_cadre_afficher_traductions' => 'عرض وضع الترجمات للغات التالية:',
898
+    'titre_cadre_ajouter_auteur' => 'إضافة مؤلف:',
899
+    'titre_cadre_interieur_rubrique' => 'في القسم',
900
+    'titre_cadre_numero_auteur' => 'مؤلف رقم',
901
+    'titre_cadre_numero_objet' => '@objet@ رقم:',
902
+    'titre_cadre_signature_obligatoire' => '<b>التوقيع<b> [إجباري]<br />',
903
+    'titre_config_contenu_notifications' => 'تبليغات',
904
+    'titre_config_contenu_prive' => 'في المجال الخاص',
905
+    'titre_config_contenu_public' => 'في الموقع العمومي',
906
+    'titre_config_fonctions' => 'إعداد الموقع',
907
+    'titre_config_langage' => 'إعداد اللغة',
908
+    'titre_configuration' => 'إعداد الموقع',
909
+    'titre_configurer_preferences' => 'إعداد التفضيلات',
910
+    'titre_configurer_preferences_menus' => 'إعداد تفضيلات القوائم',
911
+    'titre_conflit_edition' => 'تضارب لدى التحرير',
912
+    'titre_connexion_ldap' => 'خيارات: <b>إتصالLDAP </b>',
913
+    'titre_groupe_mots' => 'مجموعة مفاتيح:',
914
+    'titre_identite_site' => 'هوية الموقع',
915
+    'titre_langue_article' => 'لغة المقال',
916
+    'titre_langue_rubrique' => 'لغة القسم',
917
+    'titre_langue_trad_article' => 'لغة المقال وترجماته',
918
+    'titre_les_articles' => 'المقالات',
919
+    'titre_messagerie_agenda' => 'المراسلة والمفكرة',
920
+    'titre_naviguer_dans_le_site' => 'تصفح الموقع...',
921
+    'titre_nouvelle_rubrique' => 'قسم جديد',
922
+    'titre_numero_rubrique' => 'قسم رقم:',
923
+    'titre_page_articles_edit' => 'تعديل: @titre@',
924
+    'titre_page_articles_page' => 'المقالات',
925
+    'titre_page_articles_tous' => 'الموقع بالكامل',
926
+    'titre_page_calendrier' => 'روزنامة @nom_mois@ @annee@',
927
+    'titre_page_config_contenu' => 'إعداد الموقع',
928
+    'titre_page_delete_all' => 'حذف تام ونهائي',
929
+    'titre_page_recherche' => 'نتائج البحث @recherche@',
930
+    'titre_page_statistiques_referers' => 'الاحصاءات (الوصلات الآتية)',
931
+    'titre_page_upgrade' => 'ترقية SPIP',
932
+    'titre_preference_menus_favoris' => 'قائمة المفضلات',
933
+    'titre_publication_articles_post_dates' => 'نشر المقالات المؤجلة',
934
+    'titre_reparation' => 'إصلاح',
935
+    'titre_suivi_petition' => 'متابعة العرائض',
936
+    'tls_ldap' => 'أمان طبقة النقل:',
937
+    'trad_article_traduction' => 'كل اصدارات هذا المقال:',
938
+    'trad_delier' => 'ايقاف الربط هذا بهذه الترجمات',
939
+    'trad_lier' => 'هذا المقال هو ترجمة للمقال رقم:',
940
+    'trad_new' => 'كتابة ترجمة جديدة',
941 941
 
942
-	// U
943
-	'utf8_convert_erreur_orig' => 'خطأ: طقم الحروف @charset@ غير مدعوم.',
942
+    // U
943
+    'utf8_convert_erreur_orig' => 'خطأ: طقم الحروف @charset@ غير مدعوم.',
944 944
 
945
-	// V
946
-	'version' => 'الإصدار:'
945
+    // V
946
+    'version' => 'الإصدار:'
947 947
 );
Please login to merge, or discard this patch.
ecrire/lang/ecrire_en.php 1 patch
Indentation   +841 added lines, -841 removed lines patch added patch discarded remove patch
@@ -4,432 +4,432 @@  discard block
 block discarded – undo
4 4
 // ** ne pas modifier le fichier **
5 5
 
6 6
 if (!defined('_ECRIRE_INC_VERSION')) {
7
-	return;
7
+    return;
8 8
 }
9 9
 
10 10
 $GLOBALS[$GLOBALS['idx_lang']] = array(
11 11
 
12
-	// A
13
-	'activer_plugin' => 'Enable plugin',
14
-	'affichage' => 'Display',
15
-	'aide_non_disponible' => 'This part of the online help is not yet available in this language.',
16
-	'annuler_recherche' => 'Cancel the search',
17
-	'auteur' => 'Author:',
18
-	'avis_acces_interdit' => 'Access forbidden.',
19
-	'avis_acces_interdit_prive' => 'You are not allowed to access the page <b>@exec@</b>.',
20
-	'avis_article_modifie' => 'Warning: @nom_auteur_modif@ modified this article @date_diff@ minutes ago',
21
-	'avis_aucun_resultat' => 'No results found.',
22
-	'avis_base_inaccessible' => 'Impossible to connect to the database @base@.',
23
-	'avis_chemin_invalide_1' => 'The path you selected',
24
-	'avis_chemin_invalide_2' => 'does not seem to be valid. Please go back to previous page and check the information you provided.',
25
-	'avis_connexion_echec_1' => 'Connection to the SQL server failed.',
26
-	'avis_connexion_echec_2' => 'Go back to the previous page, and check the information you provided.',
27
-	'avis_connexion_echec_3' => '<b>N.B.</b> On many servers, you must <b>request</b> activation of your access to the SQL database before you can use it. If you cannot connect to your database, check that activation has been done.',
28
-	'avis_connexion_erreur_creer_base' => 'The database could not be created.',
29
-	'avis_connexion_erreur_fichier_cle_manquant_1' => 'Installation must be performed by a webmaster with a backup of the keys and their password',
30
-	'avis_connexion_erreur_fichier_cle_manquant_2' => 'Installation must be performed by a webmaster with a backup of the keys',
31
-	'avis_connexion_erreur_nom_base' => 'The database’s name should only contain letters, digits and hyphens.',
32
-	'avis_connexion_ldap_echec_1' => 'Connection to the LDAP server failed.',
33
-	'avis_connexion_ldap_echec_2' => 'Go back to the previous page, and check the information you provided.',
34
-	'avis_connexion_ldap_echec_3' => 'Alternatively, do not use LDAP support to import users.',
35
-	'avis_deplacement_rubrique' => 'Warning! This section contains @contient_breves@ news item@scb@: if you move it, please check this box to confirm.',
36
-	'avis_erreur_connexion_mysql' => 'SQL connection error',
37
-	'avis_erreur_creation_compte' => 'Failure during account initialisation',
38
-	'avis_espace_interdit' => '<b>Forbidden area</b> <div>SPIP is already installed.</div>',
39
-	'avis_lecture_noms_bases_1' => 'The installer could not read the names of any databases already installed.',
40
-	'avis_lecture_noms_bases_2' => 'Either no database is available, or the option listing databases was disabled for security reasons (which is the case with various hosting services).',
41
-	'avis_lecture_noms_bases_3' => 'In the second case, a database named after your login might already be available:',
42
-	'avis_non_acces_page' => 'You do not have access to this page.',
43
-	'avis_operation_echec' => 'The operation failed.',
44
-	'avis_operation_impossible' => 'Operation impossible',
45
-	'avis_suppression_base' => 'WARNING: data deletion is irreversible',
12
+    // A
13
+    'activer_plugin' => 'Enable plugin',
14
+    'affichage' => 'Display',
15
+    'aide_non_disponible' => 'This part of the online help is not yet available in this language.',
16
+    'annuler_recherche' => 'Cancel the search',
17
+    'auteur' => 'Author:',
18
+    'avis_acces_interdit' => 'Access forbidden.',
19
+    'avis_acces_interdit_prive' => 'You are not allowed to access the page <b>@exec@</b>.',
20
+    'avis_article_modifie' => 'Warning: @nom_auteur_modif@ modified this article @date_diff@ minutes ago',
21
+    'avis_aucun_resultat' => 'No results found.',
22
+    'avis_base_inaccessible' => 'Impossible to connect to the database @base@.',
23
+    'avis_chemin_invalide_1' => 'The path you selected',
24
+    'avis_chemin_invalide_2' => 'does not seem to be valid. Please go back to previous page and check the information you provided.',
25
+    'avis_connexion_echec_1' => 'Connection to the SQL server failed.',
26
+    'avis_connexion_echec_2' => 'Go back to the previous page, and check the information you provided.',
27
+    'avis_connexion_echec_3' => '<b>N.B.</b> On many servers, you must <b>request</b> activation of your access to the SQL database before you can use it. If you cannot connect to your database, check that activation has been done.',
28
+    'avis_connexion_erreur_creer_base' => 'The database could not be created.',
29
+    'avis_connexion_erreur_fichier_cle_manquant_1' => 'Installation must be performed by a webmaster with a backup of the keys and their password',
30
+    'avis_connexion_erreur_fichier_cle_manquant_2' => 'Installation must be performed by a webmaster with a backup of the keys',
31
+    'avis_connexion_erreur_nom_base' => 'The database’s name should only contain letters, digits and hyphens.',
32
+    'avis_connexion_ldap_echec_1' => 'Connection to the LDAP server failed.',
33
+    'avis_connexion_ldap_echec_2' => 'Go back to the previous page, and check the information you provided.',
34
+    'avis_connexion_ldap_echec_3' => 'Alternatively, do not use LDAP support to import users.',
35
+    'avis_deplacement_rubrique' => 'Warning! This section contains @contient_breves@ news item@scb@: if you move it, please check this box to confirm.',
36
+    'avis_erreur_connexion_mysql' => 'SQL connection error',
37
+    'avis_erreur_creation_compte' => 'Failure during account initialisation',
38
+    'avis_espace_interdit' => '<b>Forbidden area</b> <div>SPIP is already installed.</div>',
39
+    'avis_lecture_noms_bases_1' => 'The installer could not read the names of any databases already installed.',
40
+    'avis_lecture_noms_bases_2' => 'Either no database is available, or the option listing databases was disabled for security reasons (which is the case with various hosting services).',
41
+    'avis_lecture_noms_bases_3' => 'In the second case, a database named after your login might already be available:',
42
+    'avis_non_acces_page' => 'You do not have access to this page.',
43
+    'avis_operation_echec' => 'The operation failed.',
44
+    'avis_operation_impossible' => 'Operation impossible',
45
+    'avis_suppression_base' => 'WARNING: data deletion is irreversible',
46 46
 
47
-	// B
48
-	'bouton_acces_ldap' => 'Add LDAP access',
49
-	'bouton_ajouter' => 'Add',
50
-	'bouton_annuler' => 'Cancel',
51
-	'bouton_cache_activer' => 'Re-activate the cache',
52
-	'bouton_cache_desactiver' => 'Disable the cache momentarily',
53
-	'bouton_demande_publication' => 'Request publication of this article',
54
-	'bouton_desactive_tout' => 'Disable all',
55
-	'bouton_desinstaller' => 'Uninstall',
56
-	'bouton_effacer_tout' => 'Delete ALL',
57
-	'bouton_envoyer_message' => 'Message complete: send',
58
-	'bouton_fermer' => 'Close',
59
-	'bouton_mettre_a_jour_base' => 'Update the database',
60
-	'bouton_modifier' => 'Modify',
61
-	'bouton_radio_afficher' => 'Show',
62
-	'bouton_radio_apparaitre_liste_redacteurs_connectes' => 'Appear in the list of editors online',
63
-	'bouton_radio_envoi_annonces_adresse' => 'Send announcements to:',
64
-	'bouton_radio_envoi_liste_nouveautes' => 'Send news update list',
65
-	'bouton_radio_non_apparaitre_liste_redacteurs_connectes' => 'Do not appear in the list of editors online',
66
-	'bouton_radio_non_envoi_annonces_editoriales' => 'Do not send any editorial announcements',
67
-	'bouton_redirection' => 'REDIRECT',
68
-	'bouton_reinitialiser_aux_valeurs_par_defaut' => 'Reset to default values',
69
-	'bouton_relancer_inscription' => 'Re-launch registration',
70
-	'bouton_relancer_inscriptions' => 'Re-launch registrations',
71
-	'bouton_relancer_installation' => 'Recommence installation',
72
-	'bouton_reset_password' => 'Create a new password and send by e-mail',
73
-	'bouton_suivant' => 'Next',
74
-	'bouton_tenter_recuperation' => 'Attempt to repair',
75
-	'bouton_test_proxy' => 'Test the proxy',
76
-	'bouton_vider_cache' => 'Empty the cache',
47
+    // B
48
+    'bouton_acces_ldap' => 'Add LDAP access',
49
+    'bouton_ajouter' => 'Add',
50
+    'bouton_annuler' => 'Cancel',
51
+    'bouton_cache_activer' => 'Re-activate the cache',
52
+    'bouton_cache_desactiver' => 'Disable the cache momentarily',
53
+    'bouton_demande_publication' => 'Request publication of this article',
54
+    'bouton_desactive_tout' => 'Disable all',
55
+    'bouton_desinstaller' => 'Uninstall',
56
+    'bouton_effacer_tout' => 'Delete ALL',
57
+    'bouton_envoyer_message' => 'Message complete: send',
58
+    'bouton_fermer' => 'Close',
59
+    'bouton_mettre_a_jour_base' => 'Update the database',
60
+    'bouton_modifier' => 'Modify',
61
+    'bouton_radio_afficher' => 'Show',
62
+    'bouton_radio_apparaitre_liste_redacteurs_connectes' => 'Appear in the list of editors online',
63
+    'bouton_radio_envoi_annonces_adresse' => 'Send announcements to:',
64
+    'bouton_radio_envoi_liste_nouveautes' => 'Send news update list',
65
+    'bouton_radio_non_apparaitre_liste_redacteurs_connectes' => 'Do not appear in the list of editors online',
66
+    'bouton_radio_non_envoi_annonces_editoriales' => 'Do not send any editorial announcements',
67
+    'bouton_redirection' => 'REDIRECT',
68
+    'bouton_reinitialiser_aux_valeurs_par_defaut' => 'Reset to default values',
69
+    'bouton_relancer_inscription' => 'Re-launch registration',
70
+    'bouton_relancer_inscriptions' => 'Re-launch registrations',
71
+    'bouton_relancer_installation' => 'Recommence installation',
72
+    'bouton_reset_password' => 'Create a new password and send by e-mail',
73
+    'bouton_suivant' => 'Next',
74
+    'bouton_tenter_recuperation' => 'Attempt to repair',
75
+    'bouton_test_proxy' => 'Test the proxy',
76
+    'bouton_vider_cache' => 'Empty the cache',
77 77
 
78
-	// C
79
-	'cache_modifiable_webmestre' => 'This parameter can be modified by the webmaster.',
80
-	'calendrier_synchro' => 'If you use a calendar application compatible with <b>iCal</b>, you can synchronise it with information from this site.',
81
-	'config_activer_champs' => 'Activate the following fields',
82
-	'config_choix_base_sup' => 'Choose a database on this server',
83
-	'config_erreur_base_sup' => 'SPIP does not have access to the list of databases available',
84
-	'config_info_base_sup' => 'If you need to query other databases using SPIP, whether on this SQL server or elsewhere, use this form to declare them. If you leave any fields empty, connection details to the main database will be used.',
85
-	'config_info_base_sup_disponibles' => 'Additional databases to which queries may be sent:',
86
-	'config_info_enregistree' => 'The new configuration has been saved',
87
-	'config_info_logos' => 'Each element of the site can have its own logo as well as a "mouseover" logo',
88
-	'config_info_logos_utiliser' => 'Use logos',
89
-	'config_info_logos_utiliser_non' => 'Do not use logos',
90
-	'config_info_logos_utiliser_survol' => 'Use "mouseover" logos',
91
-	'config_info_logos_utiliser_survol_non' => 'Do not use "mouseover" logos',
92
-	'config_info_redirection' => 'By activating this option you can create virtual articles, which are simply links to articles published on other sites, not necessarily using SPIP.',
93
-	'config_redirection' => 'Virtual articles',
94
-	'config_titre_base_sup' => 'Declaration of an additional database',
95
-	'config_titre_base_sup_choix' => 'Choose an additional database',
96
-	'connexion_ldap' => 'Connection:',
97
-	'creer_et_associer_un_auteur' => 'Create and associate an author',
78
+    // C
79
+    'cache_modifiable_webmestre' => 'This parameter can be modified by the webmaster.',
80
+    'calendrier_synchro' => 'If you use a calendar application compatible with <b>iCal</b>, you can synchronise it with information from this site.',
81
+    'config_activer_champs' => 'Activate the following fields',
82
+    'config_choix_base_sup' => 'Choose a database on this server',
83
+    'config_erreur_base_sup' => 'SPIP does not have access to the list of databases available',
84
+    'config_info_base_sup' => 'If you need to query other databases using SPIP, whether on this SQL server or elsewhere, use this form to declare them. If you leave any fields empty, connection details to the main database will be used.',
85
+    'config_info_base_sup_disponibles' => 'Additional databases to which queries may be sent:',
86
+    'config_info_enregistree' => 'The new configuration has been saved',
87
+    'config_info_logos' => 'Each element of the site can have its own logo as well as a "mouseover" logo',
88
+    'config_info_logos_utiliser' => 'Use logos',
89
+    'config_info_logos_utiliser_non' => 'Do not use logos',
90
+    'config_info_logos_utiliser_survol' => 'Use "mouseover" logos',
91
+    'config_info_logos_utiliser_survol_non' => 'Do not use "mouseover" logos',
92
+    'config_info_redirection' => 'By activating this option you can create virtual articles, which are simply links to articles published on other sites, not necessarily using SPIP.',
93
+    'config_redirection' => 'Virtual articles',
94
+    'config_titre_base_sup' => 'Declaration of an additional database',
95
+    'config_titre_base_sup_choix' => 'Choose an additional database',
96
+    'connexion_ldap' => 'Connection:',
97
+    'creer_et_associer_un_auteur' => 'Create and associate an author',
98 98
 
99
-	// D
100
-	'date_mot_heures' => 'H',
99
+    // D
100
+    'date_mot_heures' => 'H',
101 101
 
102
-	// E
103
-	'ecran_connexion_couleur_principale' => 'Main colour',
104
-	'ecran_connexion_image_fond' => 'Background image',
105
-	'ecran_connexion_image_fond_explication' => 'Use an image (JPEG format, 1920x1080 pixels)',
106
-	'ecran_connexion_image_revenir_couleur_defaut' => 'Back to the default colour',
107
-	'ecran_connexion_titre' => 'Connection screen',
108
-	'ecran_securite' => '+ safety screen @version@',
109
-	'email' => 'email',
110
-	'email_2' => 'email:',
111
-	'en_savoir_plus' => 'Learn more',
112
-	'entree_adresse_annuaire' => 'Directory address',
113
-	'entree_adresse_email' => 'Your email address',
114
-	'entree_adresse_email_2' => 'E-mail address',
115
-	'entree_base_donnee_1' => 'Database address',
116
-	'entree_base_donnee_2' => '(This address is often your site’s URL, although sometimes it will be "localhost", and sometimes it should be left blank.)',
117
-	'entree_biographie' => 'Brief biography',
118
-	'entree_chemin_acces' => '<b>Enter</b> the path:',
119
-	'entree_cle_pgp' => 'Your PGP key',
120
-	'entree_cle_pgp_2' => 'PGP key',
121
-	'entree_contenu_rubrique' => '(Brief description of the content of this section.)',
122
-	'entree_identifiants_connexion' => 'Your connection identifiers...',
123
-	'entree_identifiants_connexion_2' => 'Connection identifiers',
124
-	'entree_informations_connexion_ldap' => 'Please fill this form with the LDAP connection information provided by your system or network administrator.',
125
-	'entree_infos_perso' => 'Who are you?',
126
-	'entree_infos_perso_2' => 'Who is the author?',
127
-	'entree_interieur_rubrique' => 'In the section:',
128
-	'entree_liens_sites' => '<b>Hyperlink</b> (reference, site to visit etc.)',
129
-	'entree_login' => 'Your login',
130
-	'entree_login_connexion_1' => 'Connection login',
131
-	'entree_login_connexion_2' => '(Sometimes matches your FTP account login and sometimes left empty)',
132
-	'entree_mot_passe' => 'Your password',
133
-	'entree_mot_passe_1' => 'Password',
134
-	'entree_mot_passe_2' => '(Sometimes matches your FTP access password and sometimes left empty)',
135
-	'entree_nom_fichier' => 'Please enter the filename @texte_compresse@:',
136
-	'entree_nom_pseudo' => 'Your name or alias',
137
-	'entree_nom_pseudo_1' => '(Your name or alias)',
138
-	'entree_nom_pseudo_2' => 'Name or alias',
139
-	'entree_nom_site' => 'Website’s name',
140
-	'entree_nom_site_2' => 'Author’s website’s name',
141
-	'entree_nouveau_passe' => 'New password',
142
-	'entree_passe_ldap' => 'Password',
143
-	'entree_port_annuaire' => 'Port number of the directory',
144
-	'entree_signature' => 'Signature',
145
-	'entree_titre_obligatoire' => '<b>Title</b> [Required]<br />',
146
-	'entree_url' => 'Website’s URL',
147
-	'entree_url_2' => 'Website’s URL',
148
-	'erreur_connect_deja_existant' => 'A server by that name already exists',
149
-	'erreur_contenu_suspect' => 'Text escaped',
150
-	'erreur_email_deja_existant' => 'This email address has already been registered.',
151
-	'erreur_nom_connect_incorrect' => 'Server name not allowed',
152
-	'erreur_plugin_attribut_balise_manquant' => 'Missing attribute @attribut@ in tag @balise@',
153
-	'erreur_plugin_desinstalation_echouee' => 'Uninstallation of the plugin failed. However, you may deactivate it.',
154
-	'erreur_plugin_fichier_absent' => 'File missing',
155
-	'erreur_plugin_fichier_def_absent' => 'Definition file missing',
156
-	'erreur_plugin_nom_fonction_interdit' => 'Prohibited function name',
157
-	'erreur_plugin_nom_manquant' => 'Missing plugin name',
158
-	'erreur_plugin_prefix_manquant' => 'Namespace undefined for this plugin',
159
-	'erreur_plugin_tag_plugin_absent' => '&lt;plugin&gt; missing in the definition file',
160
-	'erreur_plugin_version_manquant' => 'Plugin version missing',
161
-	'erreur_type_fichier' => 'Wrong file type',
102
+    // E
103
+    'ecran_connexion_couleur_principale' => 'Main colour',
104
+    'ecran_connexion_image_fond' => 'Background image',
105
+    'ecran_connexion_image_fond_explication' => 'Use an image (JPEG format, 1920x1080 pixels)',
106
+    'ecran_connexion_image_revenir_couleur_defaut' => 'Back to the default colour',
107
+    'ecran_connexion_titre' => 'Connection screen',
108
+    'ecran_securite' => '+ safety screen @version@',
109
+    'email' => 'email',
110
+    'email_2' => 'email:',
111
+    'en_savoir_plus' => 'Learn more',
112
+    'entree_adresse_annuaire' => 'Directory address',
113
+    'entree_adresse_email' => 'Your email address',
114
+    'entree_adresse_email_2' => 'E-mail address',
115
+    'entree_base_donnee_1' => 'Database address',
116
+    'entree_base_donnee_2' => '(This address is often your site’s URL, although sometimes it will be "localhost", and sometimes it should be left blank.)',
117
+    'entree_biographie' => 'Brief biography',
118
+    'entree_chemin_acces' => '<b>Enter</b> the path:',
119
+    'entree_cle_pgp' => 'Your PGP key',
120
+    'entree_cle_pgp_2' => 'PGP key',
121
+    'entree_contenu_rubrique' => '(Brief description of the content of this section.)',
122
+    'entree_identifiants_connexion' => 'Your connection identifiers...',
123
+    'entree_identifiants_connexion_2' => 'Connection identifiers',
124
+    'entree_informations_connexion_ldap' => 'Please fill this form with the LDAP connection information provided by your system or network administrator.',
125
+    'entree_infos_perso' => 'Who are you?',
126
+    'entree_infos_perso_2' => 'Who is the author?',
127
+    'entree_interieur_rubrique' => 'In the section:',
128
+    'entree_liens_sites' => '<b>Hyperlink</b> (reference, site to visit etc.)',
129
+    'entree_login' => 'Your login',
130
+    'entree_login_connexion_1' => 'Connection login',
131
+    'entree_login_connexion_2' => '(Sometimes matches your FTP account login and sometimes left empty)',
132
+    'entree_mot_passe' => 'Your password',
133
+    'entree_mot_passe_1' => 'Password',
134
+    'entree_mot_passe_2' => '(Sometimes matches your FTP access password and sometimes left empty)',
135
+    'entree_nom_fichier' => 'Please enter the filename @texte_compresse@:',
136
+    'entree_nom_pseudo' => 'Your name or alias',
137
+    'entree_nom_pseudo_1' => '(Your name or alias)',
138
+    'entree_nom_pseudo_2' => 'Name or alias',
139
+    'entree_nom_site' => 'Website’s name',
140
+    'entree_nom_site_2' => 'Author’s website’s name',
141
+    'entree_nouveau_passe' => 'New password',
142
+    'entree_passe_ldap' => 'Password',
143
+    'entree_port_annuaire' => 'Port number of the directory',
144
+    'entree_signature' => 'Signature',
145
+    'entree_titre_obligatoire' => '<b>Title</b> [Required]<br />',
146
+    'entree_url' => 'Website’s URL',
147
+    'entree_url_2' => 'Website’s URL',
148
+    'erreur_connect_deja_existant' => 'A server by that name already exists',
149
+    'erreur_contenu_suspect' => 'Text escaped',
150
+    'erreur_email_deja_existant' => 'This email address has already been registered.',
151
+    'erreur_nom_connect_incorrect' => 'Server name not allowed',
152
+    'erreur_plugin_attribut_balise_manquant' => 'Missing attribute @attribut@ in tag @balise@',
153
+    'erreur_plugin_desinstalation_echouee' => 'Uninstallation of the plugin failed. However, you may deactivate it.',
154
+    'erreur_plugin_fichier_absent' => 'File missing',
155
+    'erreur_plugin_fichier_def_absent' => 'Definition file missing',
156
+    'erreur_plugin_nom_fonction_interdit' => 'Prohibited function name',
157
+    'erreur_plugin_nom_manquant' => 'Missing plugin name',
158
+    'erreur_plugin_prefix_manquant' => 'Namespace undefined for this plugin',
159
+    'erreur_plugin_tag_plugin_absent' => '&lt;plugin&gt; missing in the definition file',
160
+    'erreur_plugin_version_manquant' => 'Plugin version missing',
161
+    'erreur_type_fichier' => 'Wrong file type',
162 162
 
163
-	// H
164
-	'htaccess_a_simuler' => 'Warning: your HTTP server configuration ignores @htaccess@ files. To ensure good security, you should change the configuration for this. Alternatively, you should make sure that the constants @constantes@ (definable in the file mes_options.php) have as values directories outside @document_root@.',
165
-	'htaccess_inoperant' => 'inoperative htaccess',
163
+    // H
164
+    'htaccess_a_simuler' => 'Warning: your HTTP server configuration ignores @htaccess@ files. To ensure good security, you should change the configuration for this. Alternatively, you should make sure that the constants @constantes@ (definable in the file mes_options.php) have as values directories outside @document_root@.',
165
+    'htaccess_inoperant' => 'inoperative htaccess',
166 166
 
167
-	// I
168
-	'ical_info1' => 'This page offers several tools to be kept  up-to-date with website’s activity.',
169
-	'ical_info2' => 'For more information, do not hesitate to visit <a href="@spipnet@">SPIP’s documentation</a>.',
170
-	'ical_info_calendrier' => 'Two calendars are available. The first is a general, public calendar showing  articles as they are published. The second is personal and contains editorial announcements as well as your latest private messages: it is reserved for you via a personal key that you can modify at any time by renewing your password.',
171
-	'ical_methode_http' => 'Downloading',
172
-	'ical_methode_webcal' => 'Synchronisation (webcal://)',
173
-	'ical_texte_js' => 'A line of javascript allows you to easily display the most recent articles published on this site on any other site belonging to you.',
174
-	'ical_texte_prive' => 'This calendar, which is strictly personal, informs you of the private editorial activity of this site (tasks, personal appointments, articles and news items submitted etc.).',
175
-	'ical_texte_public' => 'This calendar allows you to follow the public activity of this site (newly-published articles and news items).',
176
-	'ical_texte_rss' => 'You can syndicate the latest news from this site in any XML/RSS (Rich Site Summary) reader. This is also the format that allows SPIP to read the latest news published by other sites using a compatible exchange format (syndicated sites).',
177
-	'ical_titre_js' => 'Javascript',
178
-	'ical_titre_mailing' => 'Mailing-list',
179
-	'ical_titre_rss' => 'Syndication files',
180
-	'icone_accueil' => 'Home',
181
-	'icone_activer_cookie' => 'Place a cookie',
182
-	'icone_activite' => 'Feedback',
183
-	'icone_admin_plugin' => 'Manage plugins',
184
-	'icone_administration' => 'Maintenance',
185
-	'icone_afficher_auteurs' => 'Show authors',
186
-	'icone_afficher_visiteurs' => 'Show visitors',
187
-	'icone_arret_discussion' => 'Stop participating in this discussion',
188
-	'icone_calendrier' => 'Calendar',
189
-	'icone_configuration' => 'Configuration',
190
-	'icone_creer_auteur' => 'Create a new author and link him/her to this article',
191
-	'icone_creer_mot_cle' => 'Create a new keyword and link it to this article',
192
-	'icone_creer_rubrique_2' => 'Create a new section',
193
-	'icone_developpement' => 'Development',
194
-	'icone_edition' => 'Edit',
195
-	'icone_ma_langue' => 'My language',
196
-	'icone_mes_infos' => 'My details',
197
-	'icone_mes_preferences' => 'Preferences',
198
-	'icone_modifier_article' => 'Edit this article',
199
-	'icone_modifier_rubrique' => 'Edit this section',
200
-	'icone_publication' => 'Publish',
201
-	'icone_relancer_signataire' => 'Contact the signatory again',
202
-	'icone_retour' => 'Back',
203
-	'icone_retour_article' => 'Back to the article',
204
-	'icone_squelette' => 'Templates',
205
-	'icone_suivi_publication' => 'Publication follow up ',
206
-	'icone_supprimer_cookie' => 'Delete cookie',
207
-	'icone_supprimer_rubrique' => 'Delete this section',
208
-	'icone_supprimer_signature' => 'Delete this signature',
209
-	'icone_valider_signature' => 'Validate this signature',
210
-	'image_administrer_rubrique' => 'You can manage this section',
211
-	'impossible_modifier_login_auteur' => 'Login cannot be changed.',
212
-	'impossible_modifier_pass_auteur' => 'Password cannot be changed.',
213
-	'info_1_article' => '1 article',
214
-	'info_1_auteur' => '1 author',
215
-	'info_1_message' => '1 message',
216
-	'info_1_mot_cle' => '1 keyword',
217
-	'info_1_rubrique' => '1 section',
218
-	'info_1_visiteur' => '1 visitor',
219
-	'info_activer_cookie' => 'You can activate an <b>administration cookie</b>, which lets you switch easily between the public website and the admin area.',
220
-	'info_activer_menu_developpement' => 'Show the Development menu',
221
-	'info_admin_etre_webmestre' => 'Give me web administrator rights',
222
-	'info_admin_je_suis_webmestre' => 'I am a <b>webmaster</b>',
223
-	'info_admin_statuer_webmestre' => 'Give webmaster rights to this administrator ',
224
-	'info_admin_webmestre' => 'This administrator is <b>webmaster</b>',
225
-	'info_administrateur' => 'Administrator',
226
-	'info_administrateur_1' => 'Administrator',
227
-	'info_administrateur_2' => 'of the site (<i>use with caution</i>)',
228
-	'info_administrateur_site_01' => 'If you are a site administrator, please',
229
-	'info_administrateur_site_02' => 'click on this link',
230
-	'info_administrateurs' => 'Administrators',
231
-	'info_administrer_rubrique' => 'You can manage this section',
232
-	'info_adresse' => 'to this address:',
233
-	'info_adresse_desinscription' => 'Unsubscription address:',
234
-	'info_adresse_url' => 'URL of the public site',
235
-	'info_afficher_par_nb' => 'Show ',
236
-	'info_aide_en_ligne' => 'SPIP Online Help',
237
-	'info_ajout_image' => 'When you add images as attached documents to an article,
167
+    // I
168
+    'ical_info1' => 'This page offers several tools to be kept  up-to-date with website’s activity.',
169
+    'ical_info2' => 'For more information, do not hesitate to visit <a href="@spipnet@">SPIP’s documentation</a>.',
170
+    'ical_info_calendrier' => 'Two calendars are available. The first is a general, public calendar showing  articles as they are published. The second is personal and contains editorial announcements as well as your latest private messages: it is reserved for you via a personal key that you can modify at any time by renewing your password.',
171
+    'ical_methode_http' => 'Downloading',
172
+    'ical_methode_webcal' => 'Synchronisation (webcal://)',
173
+    'ical_texte_js' => 'A line of javascript allows you to easily display the most recent articles published on this site on any other site belonging to you.',
174
+    'ical_texte_prive' => 'This calendar, which is strictly personal, informs you of the private editorial activity of this site (tasks, personal appointments, articles and news items submitted etc.).',
175
+    'ical_texte_public' => 'This calendar allows you to follow the public activity of this site (newly-published articles and news items).',
176
+    'ical_texte_rss' => 'You can syndicate the latest news from this site in any XML/RSS (Rich Site Summary) reader. This is also the format that allows SPIP to read the latest news published by other sites using a compatible exchange format (syndicated sites).',
177
+    'ical_titre_js' => 'Javascript',
178
+    'ical_titre_mailing' => 'Mailing-list',
179
+    'ical_titre_rss' => 'Syndication files',
180
+    'icone_accueil' => 'Home',
181
+    'icone_activer_cookie' => 'Place a cookie',
182
+    'icone_activite' => 'Feedback',
183
+    'icone_admin_plugin' => 'Manage plugins',
184
+    'icone_administration' => 'Maintenance',
185
+    'icone_afficher_auteurs' => 'Show authors',
186
+    'icone_afficher_visiteurs' => 'Show visitors',
187
+    'icone_arret_discussion' => 'Stop participating in this discussion',
188
+    'icone_calendrier' => 'Calendar',
189
+    'icone_configuration' => 'Configuration',
190
+    'icone_creer_auteur' => 'Create a new author and link him/her to this article',
191
+    'icone_creer_mot_cle' => 'Create a new keyword and link it to this article',
192
+    'icone_creer_rubrique_2' => 'Create a new section',
193
+    'icone_developpement' => 'Development',
194
+    'icone_edition' => 'Edit',
195
+    'icone_ma_langue' => 'My language',
196
+    'icone_mes_infos' => 'My details',
197
+    'icone_mes_preferences' => 'Preferences',
198
+    'icone_modifier_article' => 'Edit this article',
199
+    'icone_modifier_rubrique' => 'Edit this section',
200
+    'icone_publication' => 'Publish',
201
+    'icone_relancer_signataire' => 'Contact the signatory again',
202
+    'icone_retour' => 'Back',
203
+    'icone_retour_article' => 'Back to the article',
204
+    'icone_squelette' => 'Templates',
205
+    'icone_suivi_publication' => 'Publication follow up ',
206
+    'icone_supprimer_cookie' => 'Delete cookie',
207
+    'icone_supprimer_rubrique' => 'Delete this section',
208
+    'icone_supprimer_signature' => 'Delete this signature',
209
+    'icone_valider_signature' => 'Validate this signature',
210
+    'image_administrer_rubrique' => 'You can manage this section',
211
+    'impossible_modifier_login_auteur' => 'Login cannot be changed.',
212
+    'impossible_modifier_pass_auteur' => 'Password cannot be changed.',
213
+    'info_1_article' => '1 article',
214
+    'info_1_auteur' => '1 author',
215
+    'info_1_message' => '1 message',
216
+    'info_1_mot_cle' => '1 keyword',
217
+    'info_1_rubrique' => '1 section',
218
+    'info_1_visiteur' => '1 visitor',
219
+    'info_activer_cookie' => 'You can activate an <b>administration cookie</b>, which lets you switch easily between the public website and the admin area.',
220
+    'info_activer_menu_developpement' => 'Show the Development menu',
221
+    'info_admin_etre_webmestre' => 'Give me web administrator rights',
222
+    'info_admin_je_suis_webmestre' => 'I am a <b>webmaster</b>',
223
+    'info_admin_statuer_webmestre' => 'Give webmaster rights to this administrator ',
224
+    'info_admin_webmestre' => 'This administrator is <b>webmaster</b>',
225
+    'info_administrateur' => 'Administrator',
226
+    'info_administrateur_1' => 'Administrator',
227
+    'info_administrateur_2' => 'of the site (<i>use with caution</i>)',
228
+    'info_administrateur_site_01' => 'If you are a site administrator, please',
229
+    'info_administrateur_site_02' => 'click on this link',
230
+    'info_administrateurs' => 'Administrators',
231
+    'info_administrer_rubrique' => 'You can manage this section',
232
+    'info_adresse' => 'to this address:',
233
+    'info_adresse_desinscription' => 'Unsubscription address:',
234
+    'info_adresse_url' => 'URL of the public site',
235
+    'info_afficher_par_nb' => 'Show ',
236
+    'info_aide_en_ligne' => 'SPIP Online Help',
237
+    'info_ajout_image' => 'When you add images as attached documents to an article,
238 238
   SPIP can automatically create thumbnails from
239 239
   inserted images. This will allow, for instance, the automated
240 240
   creation of a gallery or portfolio.',
241
-	'info_ajouter_rubrique' => 'Add another section to manage:',
242
-	'info_annonce_nouveautes' => 'Latest news announcements',
243
-	'info_article' => 'article',
244
-	'info_article_2' => 'articles',
245
-	'info_article_a_paraitre' => 'Post-dated articles set for publication',
246
-	'info_articles_02' => 'articles',
247
-	'info_articles_2' => 'Articles',
248
-	'info_articles_auteur' => 'Articles by this author',
249
-	'info_articles_miens' => 'My articles',
250
-	'info_articles_tous' => 'All the articles',
251
-	'info_articles_trouves' => 'Articles found',
252
-	'info_attente_validation' => 'Your articles awaiting validation',
253
-	'info_aucun_article' => 'No articles',
254
-	'info_aucun_auteur' => 'No authors',
255
-	'info_aucun_message' => 'No messages',
256
-	'info_aucun_rubrique' => 'No sections',
257
-	'info_aujourdhui' => 'today:',
258
-	'info_auteur_gere_rubriques' => 'This author manages the following sections:',
259
-	'info_auteur_gere_toutes_rubriques' => 'This author manage <b>all the sections</b>',
260
-	'info_auteur_gere_toutes_rubriques_2' => 'I manage <b>all the sections</b>',
261
-	'info_auteurs' => 'Authors',
262
-	'info_auteurs_par_tri' => 'Authors@partri@',
263
-	'info_auteurs_trouves' => 'Authors found',
264
-	'info_authentification_externe' => 'External authentication',
265
-	'info_avertissement' => 'Warning',
266
-	'info_barre_outils' => 'with its toolbar?',
267
-	'info_base_installee' => 'Your database structure has been installed.',
268
-	'info_bio' => 'Biography',
269
-	'info_cache_desactive' => 'The cache is temporarily disabled',
270
-	'info_chapeau' => 'Introduction',
271
-	'info_chapeau_2' => 'Introduction:',
272
-	'info_chemin_acces_1' => 'Options: <b>Access path in directory</b>',
273
-	'info_chemin_acces_2' => 'You must now configure the access path to the directory information. This information is essential to read the user profiles stored in the directory.',
274
-	'info_chemin_acces_annuaire' => 'Options: <b>Access path in directory</b>',
275
-	'info_choix_base' => 'Third step:',
276
-	'info_classement_1' => ' out of @liste@',
277
-	'info_classement_2' => ' out of @liste@',
278
-	'info_code_acces' => 'Do not forget your own access codes!',
279
-	'info_config_suivi' => 'If this address corresponds to a mailing list, you can indicate the subscription address for this list. This may be a URL (e.g. a webpage enabling subscription online), or an email address with a specific subject (for instance: <tt>@adresse_suivi@?subject=subscribe</tt>):',
280
-	'info_config_suivi_explication' => 'You can subscribe to the mailing-list for this site. You will then receive email announcements concerning articles and news items submitted for publication.',
281
-	'info_confirmer_passe' => 'Confirm new password:',
282
-	'info_conflit_edition_avis_non_sauvegarde' => 'Caution: the following fields have been modified elsewhere. Your changes to these fields have therefore not been saved.',
283
-	'info_conflit_edition_differences' => 'Differences:',
284
-	'info_conflit_edition_version_enregistree' => 'Saved version:',
285
-	'info_conflit_edition_votre_version' => 'Your version:',
286
-	'info_connexion_base' => 'Trying to connect to database',
287
-	'info_connexion_base_donnee' => 'Connection to your database',
288
-	'info_connexion_ldap_ok' => '<b>LDAP connection succeeded.</b><p> You can go to the next step.</p>',
289
-	'info_connexion_mysql' => 'Your SQL connection',
290
-	'info_connexion_ok' => 'Connection succeeded.',
291
-	'info_contact' => 'Contact',
292
-	'info_contenu_articles' => 'Article content',
293
-	'info_contributions' => 'Contributions',
294
-	'info_creation_paragraphe' => 'To create paragraphs, just leave blank lines.',
295
-	'info_creation_rubrique' => 'Before writing any articles,<br /> you must create at least one section.<br />',
296
-	'info_creation_tables' => 'Creating the database tables',
297
-	'info_creer_base' => '<b>Create</b> a new database:',
298
-	'info_dans_rubrique' => 'In section:',
299
-	'info_date_publication_anterieure' => 'Previously published on:',
300
-	'info_date_referencement' => 'THIS SITE REFERENCED ON:',
301
-	'info_derniere_etape' => 'Done!',
302
-	'info_descriptif' => 'Description:',
303
-	'info_desinstaller_plugin' => ' deactivates the plugin and deletes the data',
304
-	'info_discussion_cours' => 'Current discussions',
305
-	'info_ecrire_article' => 'Before writing any articles, you must create at least one section.',
306
-	'info_email_envoi' => 'Sender’s email address (optional)',
307
-	'info_email_envoi_txt' => 'Enter the sender’s email address used for sending emails (by default, the recipient’s address is used as the sender’s address) :',
308
-	'info_email_webmestre' => 'Webmaster’s email address',
309
-	'info_envoi_email_automatique' => 'Automated mailing',
310
-	'info_envoyer_maintenant' => 'Send now',
311
-	'info_etape_suivante' => 'Go to the next step',
312
-	'info_etape_suivante_1' => 'You can move on to the next step.',
313
-	'info_etape_suivante_2' => 'You can move on to the next step.',
314
-	'info_exceptions_proxy' => 'Exceptions for the proxy',
315
-	'info_exportation_base' => 'export database to @archive@',
316
-	'info_facilite_suivi_activite' => 'To simplify monitoring of the site’s editorial;
241
+    'info_ajouter_rubrique' => 'Add another section to manage:',
242
+    'info_annonce_nouveautes' => 'Latest news announcements',
243
+    'info_article' => 'article',
244
+    'info_article_2' => 'articles',
245
+    'info_article_a_paraitre' => 'Post-dated articles set for publication',
246
+    'info_articles_02' => 'articles',
247
+    'info_articles_2' => 'Articles',
248
+    'info_articles_auteur' => 'Articles by this author',
249
+    'info_articles_miens' => 'My articles',
250
+    'info_articles_tous' => 'All the articles',
251
+    'info_articles_trouves' => 'Articles found',
252
+    'info_attente_validation' => 'Your articles awaiting validation',
253
+    'info_aucun_article' => 'No articles',
254
+    'info_aucun_auteur' => 'No authors',
255
+    'info_aucun_message' => 'No messages',
256
+    'info_aucun_rubrique' => 'No sections',
257
+    'info_aujourdhui' => 'today:',
258
+    'info_auteur_gere_rubriques' => 'This author manages the following sections:',
259
+    'info_auteur_gere_toutes_rubriques' => 'This author manage <b>all the sections</b>',
260
+    'info_auteur_gere_toutes_rubriques_2' => 'I manage <b>all the sections</b>',
261
+    'info_auteurs' => 'Authors',
262
+    'info_auteurs_par_tri' => 'Authors@partri@',
263
+    'info_auteurs_trouves' => 'Authors found',
264
+    'info_authentification_externe' => 'External authentication',
265
+    'info_avertissement' => 'Warning',
266
+    'info_barre_outils' => 'with its toolbar?',
267
+    'info_base_installee' => 'Your database structure has been installed.',
268
+    'info_bio' => 'Biography',
269
+    'info_cache_desactive' => 'The cache is temporarily disabled',
270
+    'info_chapeau' => 'Introduction',
271
+    'info_chapeau_2' => 'Introduction:',
272
+    'info_chemin_acces_1' => 'Options: <b>Access path in directory</b>',
273
+    'info_chemin_acces_2' => 'You must now configure the access path to the directory information. This information is essential to read the user profiles stored in the directory.',
274
+    'info_chemin_acces_annuaire' => 'Options: <b>Access path in directory</b>',
275
+    'info_choix_base' => 'Third step:',
276
+    'info_classement_1' => ' out of @liste@',
277
+    'info_classement_2' => ' out of @liste@',
278
+    'info_code_acces' => 'Do not forget your own access codes!',
279
+    'info_config_suivi' => 'If this address corresponds to a mailing list, you can indicate the subscription address for this list. This may be a URL (e.g. a webpage enabling subscription online), or an email address with a specific subject (for instance: <tt>@adresse_suivi@?subject=subscribe</tt>):',
280
+    'info_config_suivi_explication' => 'You can subscribe to the mailing-list for this site. You will then receive email announcements concerning articles and news items submitted for publication.',
281
+    'info_confirmer_passe' => 'Confirm new password:',
282
+    'info_conflit_edition_avis_non_sauvegarde' => 'Caution: the following fields have been modified elsewhere. Your changes to these fields have therefore not been saved.',
283
+    'info_conflit_edition_differences' => 'Differences:',
284
+    'info_conflit_edition_version_enregistree' => 'Saved version:',
285
+    'info_conflit_edition_votre_version' => 'Your version:',
286
+    'info_connexion_base' => 'Trying to connect to database',
287
+    'info_connexion_base_donnee' => 'Connection to your database',
288
+    'info_connexion_ldap_ok' => '<b>LDAP connection succeeded.</b><p> You can go to the next step.</p>',
289
+    'info_connexion_mysql' => 'Your SQL connection',
290
+    'info_connexion_ok' => 'Connection succeeded.',
291
+    'info_contact' => 'Contact',
292
+    'info_contenu_articles' => 'Article content',
293
+    'info_contributions' => 'Contributions',
294
+    'info_creation_paragraphe' => 'To create paragraphs, just leave blank lines.',
295
+    'info_creation_rubrique' => 'Before writing any articles,<br /> you must create at least one section.<br />',
296
+    'info_creation_tables' => 'Creating the database tables',
297
+    'info_creer_base' => '<b>Create</b> a new database:',
298
+    'info_dans_rubrique' => 'In section:',
299
+    'info_date_publication_anterieure' => 'Previously published on:',
300
+    'info_date_referencement' => 'THIS SITE REFERENCED ON:',
301
+    'info_derniere_etape' => 'Done!',
302
+    'info_descriptif' => 'Description:',
303
+    'info_desinstaller_plugin' => ' deactivates the plugin and deletes the data',
304
+    'info_discussion_cours' => 'Current discussions',
305
+    'info_ecrire_article' => 'Before writing any articles, you must create at least one section.',
306
+    'info_email_envoi' => 'Sender’s email address (optional)',
307
+    'info_email_envoi_txt' => 'Enter the sender’s email address used for sending emails (by default, the recipient’s address is used as the sender’s address) :',
308
+    'info_email_webmestre' => 'Webmaster’s email address',
309
+    'info_envoi_email_automatique' => 'Automated mailing',
310
+    'info_envoyer_maintenant' => 'Send now',
311
+    'info_etape_suivante' => 'Go to the next step',
312
+    'info_etape_suivante_1' => 'You can move on to the next step.',
313
+    'info_etape_suivante_2' => 'You can move on to the next step.',
314
+    'info_exceptions_proxy' => 'Exceptions for the proxy',
315
+    'info_exportation_base' => 'export database to @archive@',
316
+    'info_facilite_suivi_activite' => 'To simplify monitoring of the site’s editorial;
317 317
   activities, SPIP can send rmail notifications, e.g. to an editors’ mailing list,
318 318
   of publication requests and article validations. Enter one or more adresses separated by commas.',
319
-	'info_fichiers_authent' => 'Authentication file ".htpasswd"',
320
-	'info_forums_abo_invites' => 'Your site contains forums by subscription; visitors may register for them on the public site.',
321
-	'info_gauche_admin_tech' => '<b>Only webmasters have access to this page.</b><p> It provides access to various
319
+    'info_fichiers_authent' => 'Authentication file ".htpasswd"',
320
+    'info_forums_abo_invites' => 'Your site contains forums by subscription; visitors may register for them on the public site.',
321
+    'info_gauche_admin_tech' => '<b>Only webmasters have access to this page.</b><p> It provides access to various
322 322
 maintenance tasks. Some of them require a specific authentication process
323 323
 via FTP.</p>',
324
-	'info_gauche_admin_vider' => '<b>Only webmasters have access to this page.</b><p> It provides access to various
324
+    'info_gauche_admin_vider' => '<b>Only webmasters have access to this page.</b><p> It provides access to various
325 325
 maintenance tasks. Some of them require a specific authentication process
326 326
 via FTP.</p>',
327
-	'info_gauche_auteurs' => 'All the site authors are listed here.
327
+    'info_gauche_auteurs' => 'All the site authors are listed here.
328 328
  The status of each is indicated by the colour of their icon (administrator = green; editor = yellow).',
329
-	'info_gauche_auteurs_exterieurs' => 'Visiting authors, without any access to the site, are indicated by a blue icon; deleted authors by a grey icon.',
330
-	'info_gauche_messagerie' => 'Internal messaging lets you exchange messages between editors, keep memos (for personal use) or, display announcements on the admin area’s homepage (if you are an administrator).',
331
-	'info_gauche_statistiques_referers' => 'This page displays the list of <i>referrers</i>, i.e. websites containing links to your own site, for yesterday and today. The list is reset every 24 hours.',
332
-	'info_gauche_visiteurs_enregistres' => 'You will find here the visitors registered
329
+    'info_gauche_auteurs_exterieurs' => 'Visiting authors, without any access to the site, are indicated by a blue icon; deleted authors by a grey icon.',
330
+    'info_gauche_messagerie' => 'Internal messaging lets you exchange messages between editors, keep memos (for personal use) or, display announcements on the admin area’s homepage (if you are an administrator).',
331
+    'info_gauche_statistiques_referers' => 'This page displays the list of <i>referrers</i>, i.e. websites containing links to your own site, for yesterday and today. The list is reset every 24 hours.',
332
+    'info_gauche_visiteurs_enregistres' => 'You will find here the visitors registered
333 333
  for the public area of the site (subscription-only forums).',
334
-	'info_generation_miniatures_images' => 'Generation of thumbnail images',
335
-	'info_gerer_trad_objets' => '@objets@: manage translation links',
336
-	'info_hebergeur_desactiver_envoi_email' => 'Some hosts disable automated mail sending
334
+    'info_generation_miniatures_images' => 'Generation of thumbnail images',
335
+    'info_gerer_trad_objets' => '@objets@: manage translation links',
336
+    'info_hebergeur_desactiver_envoi_email' => 'Some hosts disable automated mail sending
337 337
 		on their servers. In this case the following features
338 338
 		of SPIP cannot be implemented.',
339
-	'info_hier' => 'yesterday:',
340
-	'info_identification_publique' => 'Your public identity...',
341
-	'info_image_process' => 'Select the best method to create thumbnails by clicking on the corresponding picture.',
342
-	'info_image_process2' => 'If you can’t see any images, then your server is not configured to use such tools. If you want to use these features, contact your provider’s technical support and ask for the «GD» or «Imagick» extensions to be installed.',
343
-	'info_images_auto' => 'Images calculated automatically',
344
-	'info_informations_personnelles' => 'Personal information',
345
-	'info_inscription' => 'Registered on',
346
-	'info_inscription_automatique' => 'Automatic registration for new editors',
347
-	'info_jeu_caractere' => 'Character set for the site',
348
-	'info_jours' => 'days',
349
-	'info_laisser_champs_vides' => 'leave these fields empty)',
350
-	'info_langues' => 'Site languages',
351
-	'info_ldap_ok' => 'LDAP authentication is installed.',
352
-	'info_lien_hypertexte' => 'Hyperlink:',
353
-	'info_liste_nouveautes_envoyee' => 'The news update list has been sent',
354
-	'info_liste_redacteurs_connectes' => 'List of editors online',
355
-	'info_login_existant' => 'This login already exists.',
356
-	'info_login_trop_court' => 'Login too short.',
357
-	'info_login_trop_court_car_pluriel' => 'Your login must contain at least @nb@ characters.',
358
-	'info_logos' => 'Logos',
359
-	'info_maximum' => 'maximum:',
360
-	'info_meme_rubrique' => 'In this section',
361
-	'info_message_en_redaction' => 'Your draft messages',
362
-	'info_message_technique' => 'Technical message:',
363
-	'info_messagerie_interne' => 'Internal messaging',
364
-	'info_mise_a_niveau_base' => 'SQL database upgrade',
365
-	'info_mise_a_niveau_base_2' => '{{Warning!}} You have installed an {older} SPIP version, prior to the one
339
+    'info_hier' => 'yesterday:',
340
+    'info_identification_publique' => 'Your public identity...',
341
+    'info_image_process' => 'Select the best method to create thumbnails by clicking on the corresponding picture.',
342
+    'info_image_process2' => 'If you can’t see any images, then your server is not configured to use such tools. If you want to use these features, contact your provider’s technical support and ask for the «GD» or «Imagick» extensions to be installed.',
343
+    'info_images_auto' => 'Images calculated automatically',
344
+    'info_informations_personnelles' => 'Personal information',
345
+    'info_inscription' => 'Registered on',
346
+    'info_inscription_automatique' => 'Automatic registration for new editors',
347
+    'info_jeu_caractere' => 'Character set for the site',
348
+    'info_jours' => 'days',
349
+    'info_laisser_champs_vides' => 'leave these fields empty)',
350
+    'info_langues' => 'Site languages',
351
+    'info_ldap_ok' => 'LDAP authentication is installed.',
352
+    'info_lien_hypertexte' => 'Hyperlink:',
353
+    'info_liste_nouveautes_envoyee' => 'The news update list has been sent',
354
+    'info_liste_redacteurs_connectes' => 'List of editors online',
355
+    'info_login_existant' => 'This login already exists.',
356
+    'info_login_trop_court' => 'Login too short.',
357
+    'info_login_trop_court_car_pluriel' => 'Your login must contain at least @nb@ characters.',
358
+    'info_logos' => 'Logos',
359
+    'info_maximum' => 'maximum:',
360
+    'info_meme_rubrique' => 'In this section',
361
+    'info_message_en_redaction' => 'Your draft messages',
362
+    'info_message_technique' => 'Technical message:',
363
+    'info_messagerie_interne' => 'Internal messaging',
364
+    'info_mise_a_niveau_base' => 'SQL database upgrade',
365
+    'info_mise_a_niveau_base_2' => '{{Warning!}} You have installed an {older} SPIP version, prior to the one
366 366
   originally installed on this website: your database is at risk of being corrupted
367 367
   and your site might not work properly anymore.<br />{{Please, re-install
368 368
   SPIP files.}}',
369
-	'info_modification_enregistree' => 'Your changes have been saved',
370
-	'info_modifier_auteur' => 'Edit author details:',
371
-	'info_modifier_rubrique' => 'Edit the section:',
372
-	'info_modifier_titre' => 'Edit: @titre@',
373
-	'info_mon_site_spip' => 'My SPIP site',
374
-	'info_moyenne' => 'average:',
375
-	'info_multi_cet_article' => 'Language for this article:',
376
-	'info_multi_langues_choisies' => 'Please select the languages to be made available to the editors of your site.
369
+    'info_modification_enregistree' => 'Your changes have been saved',
370
+    'info_modifier_auteur' => 'Edit author details:',
371
+    'info_modifier_rubrique' => 'Edit the section:',
372
+    'info_modifier_titre' => 'Edit: @titre@',
373
+    'info_mon_site_spip' => 'My SPIP site',
374
+    'info_moyenne' => 'average:',
375
+    'info_multi_cet_article' => 'Language for this article:',
376
+    'info_multi_langues_choisies' => 'Please select the languages to be made available to the editors of your site.
377 377
   Languages already used on your site (at the top of the list) cannot be disabled.',
378
-	'info_multi_objets' => '@objets@: activate the language menu',
379
-	'info_multi_secteurs' => '... only for root-level sections?',
380
-	'info_nb_articles' => '@nb@ articles',
381
-	'info_nb_auteurs' => '@nb@ authors',
382
-	'info_nb_messages' => '@nb@ messages',
383
-	'info_nb_mots_cles' => '@nb@ keywords',
384
-	'info_nb_rubriques' => '@nb@ sections',
385
-	'info_nb_visiteurs' => '@nb@ visitors',
386
-	'info_nom' => 'Name',
387
-	'info_nom_destinataire' => 'Name of recipient',
388
-	'info_nom_pas_conforme' => 'html tags are not allowed',
389
-	'info_nom_site' => 'Name of your site',
390
-	'info_nombre_articles' => '@nb_articles@ articles,',
391
-	'info_nombre_rubriques' => '@nb_rubriques@ sections,',
392
-	'info_nombre_sites' => '@nb_sites@ sites,',
393
-	'info_non_deplacer' => 'Do not move...',
394
-	'info_non_envoi_annonce_dernieres_nouveautes' => 'SPIP can send a site newsletter (list of newly-published articles and news items).
378
+    'info_multi_objets' => '@objets@: activate the language menu',
379
+    'info_multi_secteurs' => '... only for root-level sections?',
380
+    'info_nb_articles' => '@nb@ articles',
381
+    'info_nb_auteurs' => '@nb@ authors',
382
+    'info_nb_messages' => '@nb@ messages',
383
+    'info_nb_mots_cles' => '@nb@ keywords',
384
+    'info_nb_rubriques' => '@nb@ sections',
385
+    'info_nb_visiteurs' => '@nb@ visitors',
386
+    'info_nom' => 'Name',
387
+    'info_nom_destinataire' => 'Name of recipient',
388
+    'info_nom_pas_conforme' => 'html tags are not allowed',
389
+    'info_nom_site' => 'Name of your site',
390
+    'info_nombre_articles' => '@nb_articles@ articles,',
391
+    'info_nombre_rubriques' => '@nb_rubriques@ sections,',
392
+    'info_nombre_sites' => '@nb_sites@ sites,',
393
+    'info_non_deplacer' => 'Do not move...',
394
+    'info_non_envoi_annonce_dernieres_nouveautes' => 'SPIP can send a site newsletter (list of newly-published articles and news items).
395 395
   .',
396
-	'info_non_envoi_liste_nouveautes' => 'Do not send newsletter',
397
-	'info_non_modifiable' => 'cannot be modified',
398
-	'info_non_suppression_mot_cle' => 'I do not want to delete this keyword.',
399
-	'info_notes' => 'Footnotes',
400
-	'info_nouvel_article' => 'New article',
401
-	'info_nouvelle_traduction' => 'New translation:',
402
-	'info_numero_article' => 'ARTICLE NUMBER:',
403
-	'info_obligatoire_02' => '(Required)',
404
-	'info_option_accepter_visiteurs' => 'Allow visitor registration via the public site',
405
-	'info_option_ne_pas_accepter_visiteurs' => 'Disable visitor registration',
406
-	'info_options_avancees' => 'ADVANCED OPTIONS',
407
-	'info_ou' => 'or...',
408
-	'info_page_interdite' => 'Forbidden page',
409
-	'info_par_nom' => 'by name',
410
-	'info_par_nombre_article' => 'by number of articles',
411
-	'info_par_statut' => 'by status',
412
-	'info_par_tri' => '’(by @tri@)’',
413
-	'info_passe_trop_court' => 'Password too short.',
414
-	'info_passe_trop_court_car_pluriel' => 'Your password must contain at least @nb@ characters.',
415
-	'info_passes_identiques' => 'The two passwords are not identical.',
416
-	'info_plus_cinq_car' => 'more than 5 characters',
417
-	'info_plus_cinq_car_2' => '(More than 5 characters)',
418
-	'info_plus_trois_car' => '(More than 3 characters)',
419
-	'info_popularite' => 'popularity: @popularite@; visits: @visites@',
420
-	'info_post_scriptum' => 'Postscript',
421
-	'info_post_scriptum_2' => 'Postscript:',
422
-	'info_pour' => 'for',
423
-	'info_preview_texte' => 'It is possible to preview the site’s  various editorial elements with at least the "submitted" status, as well as the"editing in progress" elements of which you are the author. Should this preview mode be restricted to administrators, open to all authors, or disabled completely?',
424
-	'info_procedez_par_etape' => 'please proceed step by step',
425
-	'info_procedure_maj_version' => 'the upgrade procedure must be run to adapt
396
+    'info_non_envoi_liste_nouveautes' => 'Do not send newsletter',
397
+    'info_non_modifiable' => 'cannot be modified',
398
+    'info_non_suppression_mot_cle' => 'I do not want to delete this keyword.',
399
+    'info_notes' => 'Footnotes',
400
+    'info_nouvel_article' => 'New article',
401
+    'info_nouvelle_traduction' => 'New translation:',
402
+    'info_numero_article' => 'ARTICLE NUMBER:',
403
+    'info_obligatoire_02' => '(Required)',
404
+    'info_option_accepter_visiteurs' => 'Allow visitor registration via the public site',
405
+    'info_option_ne_pas_accepter_visiteurs' => 'Disable visitor registration',
406
+    'info_options_avancees' => 'ADVANCED OPTIONS',
407
+    'info_ou' => 'or...',
408
+    'info_page_interdite' => 'Forbidden page',
409
+    'info_par_nom' => 'by name',
410
+    'info_par_nombre_article' => 'by number of articles',
411
+    'info_par_statut' => 'by status',
412
+    'info_par_tri' => '’(by @tri@)’',
413
+    'info_passe_trop_court' => 'Password too short.',
414
+    'info_passe_trop_court_car_pluriel' => 'Your password must contain at least @nb@ characters.',
415
+    'info_passes_identiques' => 'The two passwords are not identical.',
416
+    'info_plus_cinq_car' => 'more than 5 characters',
417
+    'info_plus_cinq_car_2' => '(More than 5 characters)',
418
+    'info_plus_trois_car' => '(More than 3 characters)',
419
+    'info_popularite' => 'popularity: @popularite@; visits: @visites@',
420
+    'info_post_scriptum' => 'Postscript',
421
+    'info_post_scriptum_2' => 'Postscript:',
422
+    'info_pour' => 'for',
423
+    'info_preview_texte' => 'It is possible to preview the site’s  various editorial elements with at least the "submitted" status, as well as the"editing in progress" elements of which you are the author. Should this preview mode be restricted to administrators, open to all authors, or disabled completely?',
424
+    'info_procedez_par_etape' => 'please proceed step by step',
425
+    'info_procedure_maj_version' => 'the upgrade procedure must be run to adapt
426 426
  the database to this new version of SPIP.',
427
-	'info_proxy_ok' => 'Proxy test successful.',
428
-	'info_ps' => 'P.S.',
429
-	'info_publier' => 'publish',
430
-	'info_publies' => 'Your articles published online',
431
-	'info_question_accepter_visiteurs' => 'If your website’s templates allows visitors to register with no access to the admin area, please activate the following option:',
432
-	'info_question_inscription_nouveaux_redacteurs' => 'Do you wish to allow new editors to register
427
+    'info_proxy_ok' => 'Proxy test successful.',
428
+    'info_ps' => 'P.S.',
429
+    'info_publier' => 'publish',
430
+    'info_publies' => 'Your articles published online',
431
+    'info_question_accepter_visiteurs' => 'If your website’s templates allows visitors to register with no access to the admin area, please activate the following option:',
432
+    'info_question_inscription_nouveaux_redacteurs' => 'Do you wish to allow new editors to register
433 433
  from the public website? If you agree with this, visitors will be able to  register
434 434
   using an automatic form, and then access the admin area to
435 435
   write their own articles. <div class="notice">During the registration process, users usually receive an automatic email
@@ -437,405 +437,405 @@  discard block
 block discarded – undo
437 437
   service providers disallow sending emails from their
438 438
   servers: in that case, automated registration is not
439 439
   possible.</div>',
440
-	'info_qui_edite' => '@nom_auteur_modif@ worked on the contents @date_diff@ minutes ago',
441
-	'info_racine_site' => 'Site root',
442
-	'info_recharger_page' => 'Please wait a few moments, then reload this page.',
443
-	'info_recherche_auteur_zero' => 'No results for "@cherche_auteur@".',
444
-	'info_recommencer' => 'Please try again.',
445
-	'info_redacteur_1' => 'Editor',
446
-	'info_redacteur_2' => 'with access to the admin area (<i>recommended</i>)',
447
-	'info_redacteurs' => 'Editors',
448
-	'info_redaction_en_cours' => 'EDITING IN PROGRESS',
449
-	'info_redirection' => 'Redirection',
450
-	'info_redirection_activee' => 'Redirection is enabled.',
451
-	'info_redirection_boucle' => 'You are trying to redirect the article toward itself. ',
452
-	'info_redirection_desactivee' => 'Redirection is deleted.',
453
-	'info_refuses' => 'Your rejected articles ',
454
-	'info_reglage_ldap' => 'Options: <b>Adjusting LDAP import</b>',
455
-	'info_renvoi_article' => '<b>Redirection.</b> This article redirects to:',
456
-	'info_reserve_admin' => 'Only administrators can modify this address.',
457
-	'info_restreindre_rubrique' => 'Restrict management to section:',
458
-	'info_resultat_recherche' => 'Search results:',
459
-	'info_rubriques' => 'Sections',
460
-	'info_rubriques_02' => 'sections',
461
-	'info_rubriques_trouvees' => 'Sections found',
462
-	'info_sans_titre' => 'Untitled',
463
-	'info_selection_chemin_acces' => '<b>Select</b> the access path in the directory:',
464
-	'info_signatures' => 'signatures',
465
-	'info_site' => 'Site',
466
-	'info_site_2' => 'site:',
467
-	'info_site_min' => 'site',
468
-	'info_site_reference_2' => 'Referenced site',
469
-	'info_site_web' => 'Web site:',
470
-	'info_sites' => 'sites',
471
-	'info_sites_lies_mot' => 'Referenced sites with this keyword',
472
-	'info_sites_proxy' => 'Using a proxy',
473
-	'info_sites_trouves' => 'Sites found',
474
-	'info_sous_titre' => 'Subtitle:',
475
-	'info_statut_administrateur' => 'Administrator',
476
-	'info_statut_auteur' => 'This author’s status:',
477
-	'info_statut_auteur_2' => 'I am',
478
-	'info_statut_auteur_a_confirmer' => 'Registration to be confirmed',
479
-	'info_statut_auteur_autre' => 'Other status:',
480
-	'info_statut_redacteur' => 'Editor',
481
-	'info_statut_utilisateurs_1' => 'Default status for imported users',
482
-	'info_statut_utilisateurs_2' => 'Choose the status to be attributed to persons present in the LDAP directory when they connect for the first time. You can modify this value for each individual author later on.',
483
-	'info_suivi_activite' => 'Follow editorial activity',
484
-	'info_surtitre' => 'Top title:',
485
-	'info_syndication_integrale_1' => 'Your site provides syndication files (see "<a href="@url@">@titre@</a>").',
486
-	'info_syndication_integrale_2' => 'Do you wish to send whole articles or only a summary of a few hundred characters?',
487
-	'info_table_prefix' => 'It is possible to change the prefix of the names of the database tables. (you need to do this if you are installing several sites in the same database). The prefix must be written in unaccented, lower-case letters without any spaces.',
488
-	'info_taille_maximale_images' => 'SPIP will test for the maximum image size (in millions of pixels) which it can process.<br /> Images bigger than this will not be reduced.',
489
-	'info_taille_maximale_vignette' => 'Maximum size for vignettes generated by the system:',
490
-	'info_terminer_installation' => 'You can now finish the standard installation process.',
491
-	'info_texte' => 'Text',
492
-	'info_texte_explicatif' => 'Explanation',
493
-	'info_texte_long' => '(The text is long: it will appear in several parts which will be reassembled after validation.)',
494
-	'info_texte_message' => 'Text of your message:',
495
-	'info_texte_message_02' => 'Message text',
496
-	'info_titre' => 'Title:',
497
-	'info_total' => 'total:',
498
-	'info_tous_articles_en_redaction' => 'All articles in progress',
499
-	'info_tous_articles_presents' => 'All articles published in this section',
500
-	'info_tous_articles_refuses' => 'All refused articles',
501
-	'info_tous_les' => 'every:',
502
-	'info_tout_site' => 'The entire site',
503
-	'info_tout_site2' => 'The article has not been translated into this language.',
504
-	'info_tout_site3' => 'The article has been translated into this language, but changes have since been made to the reference article. The translation needs updating.',
505
-	'info_tout_site4' => 'The article has been translated into this language, and the translation is up-to-date.',
506
-	'info_tout_site5' => 'Original article.',
507
-	'info_tout_site6' => '<b>Warning:</b> only original articles are displayed.
440
+    'info_qui_edite' => '@nom_auteur_modif@ worked on the contents @date_diff@ minutes ago',
441
+    'info_racine_site' => 'Site root',
442
+    'info_recharger_page' => 'Please wait a few moments, then reload this page.',
443
+    'info_recherche_auteur_zero' => 'No results for "@cherche_auteur@".',
444
+    'info_recommencer' => 'Please try again.',
445
+    'info_redacteur_1' => 'Editor',
446
+    'info_redacteur_2' => 'with access to the admin area (<i>recommended</i>)',
447
+    'info_redacteurs' => 'Editors',
448
+    'info_redaction_en_cours' => 'EDITING IN PROGRESS',
449
+    'info_redirection' => 'Redirection',
450
+    'info_redirection_activee' => 'Redirection is enabled.',
451
+    'info_redirection_boucle' => 'You are trying to redirect the article toward itself. ',
452
+    'info_redirection_desactivee' => 'Redirection is deleted.',
453
+    'info_refuses' => 'Your rejected articles ',
454
+    'info_reglage_ldap' => 'Options: <b>Adjusting LDAP import</b>',
455
+    'info_renvoi_article' => '<b>Redirection.</b> This article redirects to:',
456
+    'info_reserve_admin' => 'Only administrators can modify this address.',
457
+    'info_restreindre_rubrique' => 'Restrict management to section:',
458
+    'info_resultat_recherche' => 'Search results:',
459
+    'info_rubriques' => 'Sections',
460
+    'info_rubriques_02' => 'sections',
461
+    'info_rubriques_trouvees' => 'Sections found',
462
+    'info_sans_titre' => 'Untitled',
463
+    'info_selection_chemin_acces' => '<b>Select</b> the access path in the directory:',
464
+    'info_signatures' => 'signatures',
465
+    'info_site' => 'Site',
466
+    'info_site_2' => 'site:',
467
+    'info_site_min' => 'site',
468
+    'info_site_reference_2' => 'Referenced site',
469
+    'info_site_web' => 'Web site:',
470
+    'info_sites' => 'sites',
471
+    'info_sites_lies_mot' => 'Referenced sites with this keyword',
472
+    'info_sites_proxy' => 'Using a proxy',
473
+    'info_sites_trouves' => 'Sites found',
474
+    'info_sous_titre' => 'Subtitle:',
475
+    'info_statut_administrateur' => 'Administrator',
476
+    'info_statut_auteur' => 'This author’s status:',
477
+    'info_statut_auteur_2' => 'I am',
478
+    'info_statut_auteur_a_confirmer' => 'Registration to be confirmed',
479
+    'info_statut_auteur_autre' => 'Other status:',
480
+    'info_statut_redacteur' => 'Editor',
481
+    'info_statut_utilisateurs_1' => 'Default status for imported users',
482
+    'info_statut_utilisateurs_2' => 'Choose the status to be attributed to persons present in the LDAP directory when they connect for the first time. You can modify this value for each individual author later on.',
483
+    'info_suivi_activite' => 'Follow editorial activity',
484
+    'info_surtitre' => 'Top title:',
485
+    'info_syndication_integrale_1' => 'Your site provides syndication files (see "<a href="@url@">@titre@</a>").',
486
+    'info_syndication_integrale_2' => 'Do you wish to send whole articles or only a summary of a few hundred characters?',
487
+    'info_table_prefix' => 'It is possible to change the prefix of the names of the database tables. (you need to do this if you are installing several sites in the same database). The prefix must be written in unaccented, lower-case letters without any spaces.',
488
+    'info_taille_maximale_images' => 'SPIP will test for the maximum image size (in millions of pixels) which it can process.<br /> Images bigger than this will not be reduced.',
489
+    'info_taille_maximale_vignette' => 'Maximum size for vignettes generated by the system:',
490
+    'info_terminer_installation' => 'You can now finish the standard installation process.',
491
+    'info_texte' => 'Text',
492
+    'info_texte_explicatif' => 'Explanation',
493
+    'info_texte_long' => '(The text is long: it will appear in several parts which will be reassembled after validation.)',
494
+    'info_texte_message' => 'Text of your message:',
495
+    'info_texte_message_02' => 'Message text',
496
+    'info_titre' => 'Title:',
497
+    'info_total' => 'total:',
498
+    'info_tous_articles_en_redaction' => 'All articles in progress',
499
+    'info_tous_articles_presents' => 'All articles published in this section',
500
+    'info_tous_articles_refuses' => 'All refused articles',
501
+    'info_tous_les' => 'every:',
502
+    'info_tout_site' => 'The entire site',
503
+    'info_tout_site2' => 'The article has not been translated into this language.',
504
+    'info_tout_site3' => 'The article has been translated into this language, but changes have since been made to the reference article. The translation needs updating.',
505
+    'info_tout_site4' => 'The article has been translated into this language, and the translation is up-to-date.',
506
+    'info_tout_site5' => 'Original article.',
507
+    'info_tout_site6' => '<b>Warning:</b> only original articles are displayed.
508 508
 Translations are linked to the original,
509 509
 and their status is colour-coded:',
510
-	'info_traductions' => 'Translations',
511
-	'info_travail_colaboratif' => 'Collaborative work on articles',
512
-	'info_un_article' => 'an article,',
513
-	'info_un_site' => 'a site,',
514
-	'info_une_rubrique' => 'a section,',
515
-	'info_une_rubrique_02' => '1 section',
516
-	'info_url' => 'URL:',
517
-	'info_url_proxy' => 'Proxy URL',
518
-	'info_url_proxy_pas_conforme' => 'Proxy’s URL not valid.',
519
-	'info_url_site_pas_conforme' => 'the website URL is invalid.',
520
-	'info_url_test_proxy' => 'Test URL',
521
-	'info_urlref' => 'Hyperlink:',
522
-	'info_utilisation_spip' => 'SPIP is now ready for use',
523
-	'info_visites_par_mois' => 'Monthly display:',
524
-	'info_visiteur_1' => 'Visitor',
525
-	'info_visiteur_2' => 'to the public site',
526
-	'info_visiteurs' => 'Visitors',
527
-	'info_visiteurs_02' => 'Public site visitors',
528
-	'info_webmestre_forces' => 'The web administrators are currently defined in <tt>@file_options@</tt>.',
529
-	'install_adresse_base_hebergeur' => 'Database address attributed by the hosting provider',
530
-	'install_connect_ok' => 'The new database has been declared using the server name @connect@.',
531
-	'install_echec_annonce' => 'This installation will probably fail, or damage your site.',
532
-	'install_extension_mbstring' => 'SPIP does not work with:',
533
-	'install_extension_php_obligatoire' => 'SPIP requires the php extension:',
534
-	'install_login_base_hebergeur' => 'Login attributed by the service provider',
535
-	'install_nom_base_hebergeur' => 'Database name attributed by the service provider:',
536
-	'install_pas_table' => 'The database has no tables',
537
-	'install_pass_base_hebergeur' => 'Password attributed by your hosting service ',
538
-	'install_php_extension' => 'The following extensions are missing : @extensions@',
539
-	'install_php_version' => 'This version of PHP @version@ is too old (minimum = @minimum@)',
540
-	'install_php_version_max' => 'PHP version @version@ too recent (maximum = @maximum@)',
541
-	'install_select_langue' => 'Select a language, then click on "next" to start installation.',
542
-	'install_select_type_db' => 'Indicate the type of database:',
543
-	'install_select_type_mysql' => 'MySQL',
544
-	'install_select_type_pg' => 'PostgreSQL',
545
-	'install_select_type_sqlite2' => 'SQLite 2',
546
-	'install_select_type_sqlite3' => 'SQLite 3',
547
-	'install_serveur_hebergeur' => 'Database server attributed by the hosting provider',
548
-	'install_table_prefix_hebergeur' => 'Table prefix attributed by your hosting provider:',
549
-	'install_tables_base' => 'Tables in the database',
550
-	'install_types_db_connus' => 'SPIP can use <b>MySQL</b> (the most common) and <b>SQLite</b>.',
551
-	'install_types_db_connus_avertissement' => 'The support of <b>PostgreSQL</b is actually proposed as experimental',
552
-	'instituer_erreur_statut_a_change' => 'The status has already been modified',
553
-	'instituer_erreur_statut_non_autorise' => 'You cannot select this status',
554
-	'intem_redacteur' => 'editor',
555
-	'intitule_licence' => 'Licence',
556
-	'item_accepter_inscriptions' => 'Allow registration',
557
-	'item_activer_messages_avertissement' => 'Activate warning messages',
558
-	'item_administrateur_2' => 'administrator',
559
-	'item_afficher_calendrier' => 'Display in calendar',
560
-	'item_autoriser_syndication_integrale' => 'Include entire articles in syndication feeds',
561
-	'item_choix_administrateurs' => 'administrators',
562
-	'item_choix_generation_miniature' => 'Generate thumbnails automatically.',
563
-	'item_choix_non_generation_miniature' => 'Do not generate thumbnails.',
564
-	'item_choix_redacteurs' => 'editors',
565
-	'item_choix_visiteurs' => 'visitors to the public site',
566
-	'item_creer_fichiers_authent' => 'Create .htpasswd files',
567
-	'item_login' => 'Login',
568
-	'item_messagerie_agenda' => 'Activate messaging system and calendars',
569
-	'item_mots_cles_association_articles' => 'articles',
570
-	'item_mots_cles_association_rubriques' => 'sections',
571
-	'item_mots_cles_association_sites' => 'referenced or syndicated sites.',
572
-	'item_non' => 'No',
573
-	'item_non_accepter_inscriptions' => 'Disable registration',
574
-	'item_non_activer_messages_avertissement' => 'No warning messages',
575
-	'item_non_afficher_calendrier' => 'Do not show in calendar',
576
-	'item_non_autoriser_syndication_integrale' => 'Only send a summary',
577
-	'item_non_creer_fichiers_authent' => 'Do not create these files',
578
-	'item_non_messagerie_agenda' => 'Disable the messaging system and calendars',
579
-	'item_non_publier_articles' => 'Do not publish articles before their specified publication date.',
580
-	'item_nouvel_auteur' => 'New author',
581
-	'item_nouvelle_rubrique' => 'New section',
582
-	'item_oui' => 'Yes',
583
-	'item_publier_articles' => 'Publish articles, irrespective of publication date.',
584
-	'item_reponse_article' => 'Reply to the article',
585
-	'item_visiteur' => 'visitor',
510
+    'info_traductions' => 'Translations',
511
+    'info_travail_colaboratif' => 'Collaborative work on articles',
512
+    'info_un_article' => 'an article,',
513
+    'info_un_site' => 'a site,',
514
+    'info_une_rubrique' => 'a section,',
515
+    'info_une_rubrique_02' => '1 section',
516
+    'info_url' => 'URL:',
517
+    'info_url_proxy' => 'Proxy URL',
518
+    'info_url_proxy_pas_conforme' => 'Proxy’s URL not valid.',
519
+    'info_url_site_pas_conforme' => 'the website URL is invalid.',
520
+    'info_url_test_proxy' => 'Test URL',
521
+    'info_urlref' => 'Hyperlink:',
522
+    'info_utilisation_spip' => 'SPIP is now ready for use',
523
+    'info_visites_par_mois' => 'Monthly display:',
524
+    'info_visiteur_1' => 'Visitor',
525
+    'info_visiteur_2' => 'to the public site',
526
+    'info_visiteurs' => 'Visitors',
527
+    'info_visiteurs_02' => 'Public site visitors',
528
+    'info_webmestre_forces' => 'The web administrators are currently defined in <tt>@file_options@</tt>.',
529
+    'install_adresse_base_hebergeur' => 'Database address attributed by the hosting provider',
530
+    'install_connect_ok' => 'The new database has been declared using the server name @connect@.',
531
+    'install_echec_annonce' => 'This installation will probably fail, or damage your site.',
532
+    'install_extension_mbstring' => 'SPIP does not work with:',
533
+    'install_extension_php_obligatoire' => 'SPIP requires the php extension:',
534
+    'install_login_base_hebergeur' => 'Login attributed by the service provider',
535
+    'install_nom_base_hebergeur' => 'Database name attributed by the service provider:',
536
+    'install_pas_table' => 'The database has no tables',
537
+    'install_pass_base_hebergeur' => 'Password attributed by your hosting service ',
538
+    'install_php_extension' => 'The following extensions are missing : @extensions@',
539
+    'install_php_version' => 'This version of PHP @version@ is too old (minimum = @minimum@)',
540
+    'install_php_version_max' => 'PHP version @version@ too recent (maximum = @maximum@)',
541
+    'install_select_langue' => 'Select a language, then click on "next" to start installation.',
542
+    'install_select_type_db' => 'Indicate the type of database:',
543
+    'install_select_type_mysql' => 'MySQL',
544
+    'install_select_type_pg' => 'PostgreSQL',
545
+    'install_select_type_sqlite2' => 'SQLite 2',
546
+    'install_select_type_sqlite3' => 'SQLite 3',
547
+    'install_serveur_hebergeur' => 'Database server attributed by the hosting provider',
548
+    'install_table_prefix_hebergeur' => 'Table prefix attributed by your hosting provider:',
549
+    'install_tables_base' => 'Tables in the database',
550
+    'install_types_db_connus' => 'SPIP can use <b>MySQL</b> (the most common) and <b>SQLite</b>.',
551
+    'install_types_db_connus_avertissement' => 'The support of <b>PostgreSQL</b is actually proposed as experimental',
552
+    'instituer_erreur_statut_a_change' => 'The status has already been modified',
553
+    'instituer_erreur_statut_non_autorise' => 'You cannot select this status',
554
+    'intem_redacteur' => 'editor',
555
+    'intitule_licence' => 'Licence',
556
+    'item_accepter_inscriptions' => 'Allow registration',
557
+    'item_activer_messages_avertissement' => 'Activate warning messages',
558
+    'item_administrateur_2' => 'administrator',
559
+    'item_afficher_calendrier' => 'Display in calendar',
560
+    'item_autoriser_syndication_integrale' => 'Include entire articles in syndication feeds',
561
+    'item_choix_administrateurs' => 'administrators',
562
+    'item_choix_generation_miniature' => 'Generate thumbnails automatically.',
563
+    'item_choix_non_generation_miniature' => 'Do not generate thumbnails.',
564
+    'item_choix_redacteurs' => 'editors',
565
+    'item_choix_visiteurs' => 'visitors to the public site',
566
+    'item_creer_fichiers_authent' => 'Create .htpasswd files',
567
+    'item_login' => 'Login',
568
+    'item_messagerie_agenda' => 'Activate messaging system and calendars',
569
+    'item_mots_cles_association_articles' => 'articles',
570
+    'item_mots_cles_association_rubriques' => 'sections',
571
+    'item_mots_cles_association_sites' => 'referenced or syndicated sites.',
572
+    'item_non' => 'No',
573
+    'item_non_accepter_inscriptions' => 'Disable registration',
574
+    'item_non_activer_messages_avertissement' => 'No warning messages',
575
+    'item_non_afficher_calendrier' => 'Do not show in calendar',
576
+    'item_non_autoriser_syndication_integrale' => 'Only send a summary',
577
+    'item_non_creer_fichiers_authent' => 'Do not create these files',
578
+    'item_non_messagerie_agenda' => 'Disable the messaging system and calendars',
579
+    'item_non_publier_articles' => 'Do not publish articles before their specified publication date.',
580
+    'item_nouvel_auteur' => 'New author',
581
+    'item_nouvelle_rubrique' => 'New section',
582
+    'item_oui' => 'Yes',
583
+    'item_publier_articles' => 'Publish articles, irrespective of publication date.',
584
+    'item_reponse_article' => 'Reply to the article',
585
+    'item_visiteur' => 'visitor',
586 586
 
587
-	// J
588
-	'jour_non_connu_nc' => 'unknown',
587
+    // J
588
+    'jour_non_connu_nc' => 'unknown',
589 589
 
590
-	// L
591
-	'label_bando_outils' => 'Toolbar',
592
-	'label_bando_outils_afficher' => 'Show the tools',
593
-	'label_bando_outils_masquer' => 'Hide the tools',
594
-	'label_choix_langue' => 'Choose your language',
595
-	'label_nom_fichier_connect' => 'Indicate the name for this server',
596
-	'label_slogan_site' => 'Website slogan',
597
-	'label_taille_ecran' => 'Screen width',
598
-	'label_texte_et_icones_navigation' => 'Navigation menu',
599
-	'label_texte_et_icones_page' => 'Page display',
600
-	'ldap_correspondance' => 'inherit field @champ@',
601
-	'ldap_correspondance_1' => 'Inherit LDAP fields',
602
-	'ldap_correspondance_2' => 'For each of these SPIP fields, enter the name of the corresponding LDAP field. Leave blank if you don’t want it filled, separate with spaces or commas to try several LDAP fields.',
603
-	'lien_ajouter_auteur' => 'Add this author',
604
-	'lien_ajouter_une_rubrique' => 'Add this section',
605
-	'lien_email' => 'email',
606
-	'lien_nom_site' => 'SITE NAME:',
607
-	'lien_rapide_contenu' => 'Go to the content',
608
-	'lien_rapide_navigation' => 'Go to the navigation',
609
-	'lien_rapide_recherche' => 'Go to the search',
610
-	'lien_retirer_auteur' => 'Remove author',
611
-	'lien_retirer_rubrique' => 'Remove the section',
612
-	'lien_retirer_tous_auteurs' => 'Remove all authors',
613
-	'lien_retirer_toutes_rubriques' => 'Remove all sections',
614
-	'lien_site' => 'site',
615
-	'lien_tout_decocher' => 'Uncheck all',
616
-	'lien_tout_deplier' => 'Expand all',
617
-	'lien_tout_replier' => 'Collapse all',
618
-	'lien_tout_supprimer' => 'Delete all',
619
-	'lien_trier_nom' => 'Sort by name',
620
-	'lien_trier_nombre_articles' => 'Sort by total articles',
621
-	'lien_trier_statut' => 'Sort by status',
622
-	'lien_voir_en_ligne' => 'VIEW ONLINE:',
623
-	'logo_article' => 'Article’s logo',
624
-	'logo_auteur' => 'Author’s logo',
625
-	'logo_rubrique' => 'Section’s logo',
626
-	'logo_site' => 'Website’s logo',
627
-	'logo_standard_rubrique' => 'Default sections’ logo',
628
-	'logo_survol' => 'Mouseover logo',
590
+    // L
591
+    'label_bando_outils' => 'Toolbar',
592
+    'label_bando_outils_afficher' => 'Show the tools',
593
+    'label_bando_outils_masquer' => 'Hide the tools',
594
+    'label_choix_langue' => 'Choose your language',
595
+    'label_nom_fichier_connect' => 'Indicate the name for this server',
596
+    'label_slogan_site' => 'Website slogan',
597
+    'label_taille_ecran' => 'Screen width',
598
+    'label_texte_et_icones_navigation' => 'Navigation menu',
599
+    'label_texte_et_icones_page' => 'Page display',
600
+    'ldap_correspondance' => 'inherit field @champ@',
601
+    'ldap_correspondance_1' => 'Inherit LDAP fields',
602
+    'ldap_correspondance_2' => 'For each of these SPIP fields, enter the name of the corresponding LDAP field. Leave blank if you don’t want it filled, separate with spaces or commas to try several LDAP fields.',
603
+    'lien_ajouter_auteur' => 'Add this author',
604
+    'lien_ajouter_une_rubrique' => 'Add this section',
605
+    'lien_email' => 'email',
606
+    'lien_nom_site' => 'SITE NAME:',
607
+    'lien_rapide_contenu' => 'Go to the content',
608
+    'lien_rapide_navigation' => 'Go to the navigation',
609
+    'lien_rapide_recherche' => 'Go to the search',
610
+    'lien_retirer_auteur' => 'Remove author',
611
+    'lien_retirer_rubrique' => 'Remove the section',
612
+    'lien_retirer_tous_auteurs' => 'Remove all authors',
613
+    'lien_retirer_toutes_rubriques' => 'Remove all sections',
614
+    'lien_site' => 'site',
615
+    'lien_tout_decocher' => 'Uncheck all',
616
+    'lien_tout_deplier' => 'Expand all',
617
+    'lien_tout_replier' => 'Collapse all',
618
+    'lien_tout_supprimer' => 'Delete all',
619
+    'lien_trier_nom' => 'Sort by name',
620
+    'lien_trier_nombre_articles' => 'Sort by total articles',
621
+    'lien_trier_statut' => 'Sort by status',
622
+    'lien_voir_en_ligne' => 'VIEW ONLINE:',
623
+    'logo_article' => 'Article’s logo',
624
+    'logo_auteur' => 'Author’s logo',
625
+    'logo_rubrique' => 'Section’s logo',
626
+    'logo_site' => 'Website’s logo',
627
+    'logo_standard_rubrique' => 'Default sections’ logo',
628
+    'logo_survol' => 'Mouseover logo',
629 629
 
630
-	// M
631
-	'menu_aide_installation_choix_base' => 'Choosing your database',
632
-	'module_fichier_langue' => 'Language file',
633
-	'module_raccourci' => 'Shortcut',
634
-	'module_texte_affiche' => 'Displayed text',
635
-	'module_texte_explicatif' => 'You can insert thse shortcuts in your website templates. They will be automatically translated into any languages for which a language file exists.',
636
-	'module_texte_traduction' => 'The language file « @module@ » is available in:',
637
-	'mois_non_connu' => 'unknown',
630
+    // M
631
+    'menu_aide_installation_choix_base' => 'Choosing your database',
632
+    'module_fichier_langue' => 'Language file',
633
+    'module_raccourci' => 'Shortcut',
634
+    'module_texte_affiche' => 'Displayed text',
635
+    'module_texte_explicatif' => 'You can insert thse shortcuts in your website templates. They will be automatically translated into any languages for which a language file exists.',
636
+    'module_texte_traduction' => 'The language file « @module@ » is available in:',
637
+    'mois_non_connu' => 'unknown',
638 638
 
639
-	// N
640
-	'nouvelle_version_spip' => 'SPIP upgrade @version@ is available',
641
-	'nouvelle_version_spip_majeure' => 'A new SPIP version @version@ is available',
639
+    // N
640
+    'nouvelle_version_spip' => 'SPIP upgrade @version@ is available',
641
+    'nouvelle_version_spip_majeure' => 'A new SPIP version @version@ is available',
642 642
 
643
-	// O
644
-	'onglet_contenu' => 'Contents',
645
-	'onglet_declarer_une_autre_base' => 'Declare another database',
646
-	'onglet_discuter' => 'Discuss',
647
-	'onglet_interactivite' => 'Interactivity',
648
-	'onglet_proprietes' => 'Properties',
649
-	'onglet_repartition_actuelle' => 'now',
650
-	'onglet_sous_rubriques' => 'Subsections',
643
+    // O
644
+    'onglet_contenu' => 'Contents',
645
+    'onglet_declarer_une_autre_base' => 'Declare another database',
646
+    'onglet_discuter' => 'Discuss',
647
+    'onglet_interactivite' => 'Interactivity',
648
+    'onglet_proprietes' => 'Properties',
649
+    'onglet_repartition_actuelle' => 'now',
650
+    'onglet_sous_rubriques' => 'Subsections',
651 651
 
652
-	// P
653
-	'page_pas_proxy' => 'This page must not go through the proxy',
654
-	'pas_de_proxy_pour' => 'If necessary, indicate to which machines or domains this proxy should not apply (for example: @exemple@)',
655
-	'phpinfo' => 'PHP configuration',
656
-	'plugin_charge_paquet' => 'Loading the archive file @name@',
657
-	'plugin_charger' => 'Download',
658
-	'plugin_erreur_charger' => 'error: @zip@ cannot be loaded',
659
-	'plugin_erreur_droit1' => 'Cannot write to directory <code>@dest@</code>.',
660
-	'plugin_erreur_droit2' => 'Please check write permissions for this directory (and create the directory if necessary). Alternatively, install the files by FTP.',
661
-	'plugin_erreur_zip' => 'pclzip failure: error @status@',
662
-	'plugin_etat_developpement' => 'under development',
663
-	'plugin_etat_experimental' => 'experimental',
664
-	'plugin_etat_stable' => 'stable',
665
-	'plugin_etat_test' => 'being tested',
666
-	'plugin_impossible_activer' => 'Impossible to activate the plugin @plugin@',
667
-	'plugin_info_automatique1' => 'If you wish to allow automatic plugin installation, please:',
668
-	'plugin_info_automatique1_lib' => 'If you want to let this library to be installed automatically, please:',
669
-	'plugin_info_automatique2' => 'Create a directory <code>@rep@</code> ;',
670
-	'plugin_info_automatique3' => 'Check that the server has the proper permissions to write to this directory.',
671
-	'plugin_info_automatique_creer' => 'to create at the root of the website.',
672
-	'plugin_info_automatique_exemples' => 'examples:',
673
-	'plugin_info_automatique_ftp' => 'You may install plugins by FTP in the  <tt>@rep@</tt> directory',
674
-	'plugin_info_automatique_lib' => 'Some plugins need to be able to load files into the <code>lib/</code> directory. This directory should be created at the website root.',
675
-	'plugin_info_automatique_liste' => 'Your plugin lists:',
676
-	'plugin_info_automatique_liste_officielle' => 'official plugins',
677
-	'plugin_info_automatique_liste_update' => 'Update lists',
678
-	'plugin_info_automatique_ou' => 'or...',
679
-	'plugin_info_automatique_select' => 'Select a plugin below: SPIP will load it and will install it in the <code>@rep@</code> directory. If the plugin already exists, it will be updated.',
680
-	'plugin_info_credit' => 'Credits',
681
-	'plugin_info_erreur_xml' => 'Incorrect declaration of the plugin',
682
-	'plugin_info_install_ok' => 'Installation successful',
683
-	'plugin_info_necessite' => 'Requires:',
684
-	'plugin_info_non_compatible_spip' => 'This plugin is incompatible with this version of SPIP',
685
-	'plugin_info_plugins_dist_1' => 'The following plugins are loaded and activated in the @plugins_dist@ directory.',
686
-	'plugin_info_plugins_dist_2' => 'They cannot be disabled.',
687
-	'plugin_info_telecharger' => 'load from @url@ and install to @rep@',
688
-	'plugin_info_upgrade_ok' => 'Successful update',
689
-	'plugin_librairies_installees' => 'Libraries installed',
690
-	'plugin_necessite_extension_php' => 'Requires the PHP extension @plugin@ version @version@.',
691
-	'plugin_necessite_extension_php_sans_version' => 'Requires the PHP extension @plugin@',
692
-	'plugin_necessite_lib' => 'This plugin requires the library @lib@',
693
-	'plugin_necessite_php' => 'Requires @plugin@ version @version@.',
694
-	'plugin_necessite_plugin' => 'Version @version@ of the plugin @plugin@ is required.',
695
-	'plugin_necessite_plugin_sans_version' => 'Requires the plugin @plugin@',
696
-	'plugin_necessite_spip' => 'SPIP version @version@ or newer is required.',
697
-	'plugin_source' => 'source: ',
698
-	'plugin_titre_automatique' => 'Automatic installation',
699
-	'plugin_titre_automatique_ajouter' => 'Add plugins',
700
-	'plugin_titre_installation' => '@plugin@ plugin installation',
701
-	'plugin_titre_modifier' => 'My plugins',
702
-	'plugin_utilise_extension_php' => 'The version of the PHP extension @plugin@ must be @version@.',
703
-	'plugin_utilise_php' => '@plugin@ version must be @version@.',
704
-	'plugin_utilise_plugin' => 'The version of the plugin @plugin@ must be @version@.',
705
-	'plugin_zip_active' => 'Continue in order to activate',
706
-	'plugin_zip_adresse' => 'To load a zipped plugin file, or a list of plugins, enter the path below.',
707
-	'plugin_zip_adresse_champ' => 'Path of the plugin or list ',
708
-	'plugin_zip_content' => 'It contains the following files(@taille@),<br />ready to be installed in the <code>@rep@</code> directory',
709
-	'plugin_zip_installe_finie' => 'The file @zip@ has been unpacked and installed.',
710
-	'plugin_zip_installe_rep_finie' => 'The file @zip@ has been unpacked and installed in the @rep@ directory',
711
-	'plugin_zip_installer' => 'You may now install it.',
712
-	'plugin_zip_telecharge' => 'The file @zip@ has been loaded',
713
-	'plugins_actif_aucun' => 'No plugins active.',
714
-	'plugins_actif_un' => 'One plugin active',
715
-	'plugins_actifs' => '@count@ active plugins.',
716
-	'plugins_actifs_liste' => 'Enabled',
717
-	'plugins_compte' => '@count@ plugins',
718
-	'plugins_disponible_un' => 'One plugin available',
719
-	'plugins_disponibles' => '@count@ plugins available.',
720
-	'plugins_erreur' => 'Error in the plugins: @plugins@',
721
-	'plugins_liste' => 'List of plugins',
722
-	'plugins_liste_dist' => 'Locked plugins',
723
-	'plugins_recents' => 'Recent plugins',
724
-	'plugins_tous_liste' => 'All',
725
-	'plugins_vue_hierarchie' => 'Hierarchy',
726
-	'plugins_vue_liste' => 'List',
727
-	'protocole_ldap' => 'Protocol version:',
652
+    // P
653
+    'page_pas_proxy' => 'This page must not go through the proxy',
654
+    'pas_de_proxy_pour' => 'If necessary, indicate to which machines or domains this proxy should not apply (for example: @exemple@)',
655
+    'phpinfo' => 'PHP configuration',
656
+    'plugin_charge_paquet' => 'Loading the archive file @name@',
657
+    'plugin_charger' => 'Download',
658
+    'plugin_erreur_charger' => 'error: @zip@ cannot be loaded',
659
+    'plugin_erreur_droit1' => 'Cannot write to directory <code>@dest@</code>.',
660
+    'plugin_erreur_droit2' => 'Please check write permissions for this directory (and create the directory if necessary). Alternatively, install the files by FTP.',
661
+    'plugin_erreur_zip' => 'pclzip failure: error @status@',
662
+    'plugin_etat_developpement' => 'under development',
663
+    'plugin_etat_experimental' => 'experimental',
664
+    'plugin_etat_stable' => 'stable',
665
+    'plugin_etat_test' => 'being tested',
666
+    'plugin_impossible_activer' => 'Impossible to activate the plugin @plugin@',
667
+    'plugin_info_automatique1' => 'If you wish to allow automatic plugin installation, please:',
668
+    'plugin_info_automatique1_lib' => 'If you want to let this library to be installed automatically, please:',
669
+    'plugin_info_automatique2' => 'Create a directory <code>@rep@</code> ;',
670
+    'plugin_info_automatique3' => 'Check that the server has the proper permissions to write to this directory.',
671
+    'plugin_info_automatique_creer' => 'to create at the root of the website.',
672
+    'plugin_info_automatique_exemples' => 'examples:',
673
+    'plugin_info_automatique_ftp' => 'You may install plugins by FTP in the  <tt>@rep@</tt> directory',
674
+    'plugin_info_automatique_lib' => 'Some plugins need to be able to load files into the <code>lib/</code> directory. This directory should be created at the website root.',
675
+    'plugin_info_automatique_liste' => 'Your plugin lists:',
676
+    'plugin_info_automatique_liste_officielle' => 'official plugins',
677
+    'plugin_info_automatique_liste_update' => 'Update lists',
678
+    'plugin_info_automatique_ou' => 'or...',
679
+    'plugin_info_automatique_select' => 'Select a plugin below: SPIP will load it and will install it in the <code>@rep@</code> directory. If the plugin already exists, it will be updated.',
680
+    'plugin_info_credit' => 'Credits',
681
+    'plugin_info_erreur_xml' => 'Incorrect declaration of the plugin',
682
+    'plugin_info_install_ok' => 'Installation successful',
683
+    'plugin_info_necessite' => 'Requires:',
684
+    'plugin_info_non_compatible_spip' => 'This plugin is incompatible with this version of SPIP',
685
+    'plugin_info_plugins_dist_1' => 'The following plugins are loaded and activated in the @plugins_dist@ directory.',
686
+    'plugin_info_plugins_dist_2' => 'They cannot be disabled.',
687
+    'plugin_info_telecharger' => 'load from @url@ and install to @rep@',
688
+    'plugin_info_upgrade_ok' => 'Successful update',
689
+    'plugin_librairies_installees' => 'Libraries installed',
690
+    'plugin_necessite_extension_php' => 'Requires the PHP extension @plugin@ version @version@.',
691
+    'plugin_necessite_extension_php_sans_version' => 'Requires the PHP extension @plugin@',
692
+    'plugin_necessite_lib' => 'This plugin requires the library @lib@',
693
+    'plugin_necessite_php' => 'Requires @plugin@ version @version@.',
694
+    'plugin_necessite_plugin' => 'Version @version@ of the plugin @plugin@ is required.',
695
+    'plugin_necessite_plugin_sans_version' => 'Requires the plugin @plugin@',
696
+    'plugin_necessite_spip' => 'SPIP version @version@ or newer is required.',
697
+    'plugin_source' => 'source: ',
698
+    'plugin_titre_automatique' => 'Automatic installation',
699
+    'plugin_titre_automatique_ajouter' => 'Add plugins',
700
+    'plugin_titre_installation' => '@plugin@ plugin installation',
701
+    'plugin_titre_modifier' => 'My plugins',
702
+    'plugin_utilise_extension_php' => 'The version of the PHP extension @plugin@ must be @version@.',
703
+    'plugin_utilise_php' => '@plugin@ version must be @version@.',
704
+    'plugin_utilise_plugin' => 'The version of the plugin @plugin@ must be @version@.',
705
+    'plugin_zip_active' => 'Continue in order to activate',
706
+    'plugin_zip_adresse' => 'To load a zipped plugin file, or a list of plugins, enter the path below.',
707
+    'plugin_zip_adresse_champ' => 'Path of the plugin or list ',
708
+    'plugin_zip_content' => 'It contains the following files(@taille@),<br />ready to be installed in the <code>@rep@</code> directory',
709
+    'plugin_zip_installe_finie' => 'The file @zip@ has been unpacked and installed.',
710
+    'plugin_zip_installe_rep_finie' => 'The file @zip@ has been unpacked and installed in the @rep@ directory',
711
+    'plugin_zip_installer' => 'You may now install it.',
712
+    'plugin_zip_telecharge' => 'The file @zip@ has been loaded',
713
+    'plugins_actif_aucun' => 'No plugins active.',
714
+    'plugins_actif_un' => 'One plugin active',
715
+    'plugins_actifs' => '@count@ active plugins.',
716
+    'plugins_actifs_liste' => 'Enabled',
717
+    'plugins_compte' => '@count@ plugins',
718
+    'plugins_disponible_un' => 'One plugin available',
719
+    'plugins_disponibles' => '@count@ plugins available.',
720
+    'plugins_erreur' => 'Error in the plugins: @plugins@',
721
+    'plugins_liste' => 'List of plugins',
722
+    'plugins_liste_dist' => 'Locked plugins',
723
+    'plugins_recents' => 'Recent plugins',
724
+    'plugins_tous_liste' => 'All',
725
+    'plugins_vue_hierarchie' => 'Hierarchy',
726
+    'plugins_vue_liste' => 'List',
727
+    'protocole_ldap' => 'Protocol version:',
728 728
 
729
-	// Q
730
-	'queue_executer_maintenant' => 'Run now',
731
-	'queue_info_purger' => 'You can delete all pending tasks and reset the list with periodic tasks',
732
-	'queue_nb_jobs_in_queue' => '@nb@ pending tasks',
733
-	'queue_next_job_in_nb_sec' => 'Next task in @nb@ s',
734
-	'queue_no_job_in_queue' => 'No pending tasks',
735
-	'queue_one_job_in_queue' => '1 pending task',
736
-	'queue_priorite_tache' => 'priority',
737
-	'queue_purger_queue' => 'Reset the tasks queue',
738
-	'queue_titre' => 'Background tasks',
729
+    // Q
730
+    'queue_executer_maintenant' => 'Run now',
731
+    'queue_info_purger' => 'You can delete all pending tasks and reset the list with periodic tasks',
732
+    'queue_nb_jobs_in_queue' => '@nb@ pending tasks',
733
+    'queue_next_job_in_nb_sec' => 'Next task in @nb@ s',
734
+    'queue_no_job_in_queue' => 'No pending tasks',
735
+    'queue_one_job_in_queue' => '1 pending task',
736
+    'queue_priorite_tache' => 'priority',
737
+    'queue_purger_queue' => 'Reset the tasks queue',
738
+    'queue_titre' => 'Background tasks',
739 739
 
740
-	// R
741
-	'repertoire_plugins' => 'Directory:',
742
-	'required' => '(Required)',
740
+    // R
741
+    'repertoire_plugins' => 'Directory:',
742
+    'required' => '(Required)',
743 743
 
744
-	// S
745
-	'sans_heure' => 'time not specified',
746
-	'statut_admin_restreint' => 'restricted admin',
747
-	'statut_webmestre' => 'webmaster',
744
+    // S
745
+    'sans_heure' => 'time not specified',
746
+    'statut_admin_restreint' => 'restricted admin',
747
+    'statut_webmestre' => 'webmaster',
748 748
 
749
-	// T
750
-	'tache_cron_asap' => 'CRON task @function@ (ASAP)',
751
-	'tache_cron_secondes' => 'CRON task @function@ (every @nb@ s)',
752
-	'taille_cache_image' => 'The images calculated automatically by SPIP (thumbnails, titles transformed into graphics, mathematical formulae in TeX format, etc.) take up a total of @taille@ in the @dir@ directory.',
753
-	'taille_cache_infinie' => 'This site does not have any fixed limit for the size of the cache.',
754
-	'taille_cache_maxi' => 'SPIP will try to limit the size of the cache directory to approximately <b>@octets@</b>.',
755
-	'taille_cache_moins_de' => 'The cache size is less than @octets@.',
756
-	'taille_cache_octets' => 'The size of the cache is currently around @octets@.',
757
-	'taille_cache_vide' => 'The cache is empty.',
758
-	'taille_repertoire_cache' => 'Current cache size ',
759
-	'text_article_propose_publication' => 'Article submitted for publication.',
760
-	'texte_acces_ldap_anonyme_1' => 'Some LDAP servers do not allow anonymous access. In this case you must indicate an initial access identifier for future directory searches. However, in most cases the following fields can be left empty.',
761
-	'texte_admin_effacer_01' => 'This command deletes <i>all</i> content in the database,
749
+    // T
750
+    'tache_cron_asap' => 'CRON task @function@ (ASAP)',
751
+    'tache_cron_secondes' => 'CRON task @function@ (every @nb@ s)',
752
+    'taille_cache_image' => 'The images calculated automatically by SPIP (thumbnails, titles transformed into graphics, mathematical formulae in TeX format, etc.) take up a total of @taille@ in the @dir@ directory.',
753
+    'taille_cache_infinie' => 'This site does not have any fixed limit for the size of the cache.',
754
+    'taille_cache_maxi' => 'SPIP will try to limit the size of the cache directory to approximately <b>@octets@</b>.',
755
+    'taille_cache_moins_de' => 'The cache size is less than @octets@.',
756
+    'taille_cache_octets' => 'The size of the cache is currently around @octets@.',
757
+    'taille_cache_vide' => 'The cache is empty.',
758
+    'taille_repertoire_cache' => 'Current cache size ',
759
+    'text_article_propose_publication' => 'Article submitted for publication.',
760
+    'texte_acces_ldap_anonyme_1' => 'Some LDAP servers do not allow anonymous access. In this case you must indicate an initial access identifier for future directory searches. However, in most cases the following fields can be left empty.',
761
+    'texte_admin_effacer_01' => 'This command deletes <i>all</i> content in the database,
762 762
 including <i>all</i> the access parameters for editors and administrators. After using it, you must
763 763
 reinstall SPIP, create a new database and a new administrator account.',
764
-	'texte_adresse_annuaire_1' => '(If your directory is installed on the same machine as your website, it is probably «localhost».)',
765
-	'texte_ajout_auteur' => 'The following author was added to the article:',
766
-	'texte_annuaire_ldap_1' => 'If you have access to a LDAP directory server, you can use it to import users automatically into SPIP.',
767
-	'texte_article_statut' => 'Article status:',
768
-	'texte_article_virtuel' => 'Virtual article',
769
-	'texte_article_virtuel_reference' => '<b>Virtual article:</b> an article on your SPIP website which redirects to another URL. To remove redirection, delete the URL.',
770
-	'texte_aucun_resultat_auteur' => 'No results for "@cherche_auteur@".',
771
-	'texte_auteur_messagerie' => 'This site can update the list of editors online in real time, which allows you to be contacted by other users. You can opt not to appear in this list (you are then "invisible" to other users).',
772
-	'texte_auteurs' => 'THE AUTHORS',
773
-	'texte_choix_base_1' => 'Select your database:',
774
-	'texte_choix_base_2' => 'The SQL server contains several databases.',
775
-	'texte_choix_base_3' => '<b>Select</b> below the one attributed by your hosting provider:',
776
-	'texte_choix_table_prefix' => 'Prefix for tables:',
777
-	'texte_compte_element' => '@count@ element',
778
-	'texte_compte_elements' => '@count@ elements',
779
-	'texte_conflit_edition_correction' => 'Please compare differences between the two versions. You can also copy your changes and start over.',
780
-	'texte_connexion_mysql' => 'Consult the information provided by your hosting service. It should contain the connection codes for the SQL server.',
781
-	'texte_contenu_article' => '(Brief description of the article.)',
782
-	'texte_contenu_articles' => 'Depending on the layout chosen for your site, you can decide
764
+    'texte_adresse_annuaire_1' => '(If your directory is installed on the same machine as your website, it is probably «localhost».)',
765
+    'texte_ajout_auteur' => 'The following author was added to the article:',
766
+    'texte_annuaire_ldap_1' => 'If you have access to a LDAP directory server, you can use it to import users automatically into SPIP.',
767
+    'texte_article_statut' => 'Article status:',
768
+    'texte_article_virtuel' => 'Virtual article',
769
+    'texte_article_virtuel_reference' => '<b>Virtual article:</b> an article on your SPIP website which redirects to another URL. To remove redirection, delete the URL.',
770
+    'texte_aucun_resultat_auteur' => 'No results for "@cherche_auteur@".',
771
+    'texte_auteur_messagerie' => 'This site can update the list of editors online in real time, which allows you to be contacted by other users. You can opt not to appear in this list (you are then "invisible" to other users).',
772
+    'texte_auteurs' => 'THE AUTHORS',
773
+    'texte_choix_base_1' => 'Select your database:',
774
+    'texte_choix_base_2' => 'The SQL server contains several databases.',
775
+    'texte_choix_base_3' => '<b>Select</b> below the one attributed by your hosting provider:',
776
+    'texte_choix_table_prefix' => 'Prefix for tables:',
777
+    'texte_compte_element' => '@count@ element',
778
+    'texte_compte_elements' => '@count@ elements',
779
+    'texte_conflit_edition_correction' => 'Please compare differences between the two versions. You can also copy your changes and start over.',
780
+    'texte_connexion_mysql' => 'Consult the information provided by your hosting service. It should contain the connection codes for the SQL server.',
781
+    'texte_contenu_article' => '(Brief description of the article.)',
782
+    'texte_contenu_articles' => 'Depending on the layout chosen for your site, you can decide
783 783
   that some article options are not to be used.
784 784
   Use the following list to choose which options should be available.',
785
-	'texte_crash_base' => 'If your database
785
+    'texte_crash_base' => 'If your database
786 786
    crashed, you can try to repair it
787 787
    automatically.',
788
-	'texte_creer_rubrique' => 'Before writing any articles,<br /> you must create a section.',
789
-	'texte_date_creation_article' => 'ARTICLE CREATION DATE:',
790
-	'texte_date_creation_objet' => 'Creation date:', # on ajoute le ":"
791
-	'texte_date_publication_anterieure' => 'Date first published:',
792
-	'texte_date_publication_anterieure_nonaffichee' => 'Hide previous publication date.',
793
-	'texte_date_publication_article' => 'PUBLISHED ON:',
794
-	'texte_date_publication_objet' => 'Published on:',
795
-	'texte_definir_comme_traduction_rubrique' => 'This section is a translation of section number:',
796
-	'texte_descriptif_rapide' => 'Brief description',
797
-	'texte_effacer_base' => 'Delete the SPIP database',
798
-	'texte_effacer_statistiques' => 'Delete the statistics',
799
-	'texte_en_cours_validation' => 'The following articles and news have been submitted for evaluation.',
800
-	'texte_enrichir_mise_a_jour' => 'You can enrich the layout of your text by using "typographical shortcuts".',
801
-	'texte_fichier_authent' => '<b>Should SPIP create the special files <tt>.htpasswd</tt>
788
+    'texte_creer_rubrique' => 'Before writing any articles,<br /> you must create a section.',
789
+    'texte_date_creation_article' => 'ARTICLE CREATION DATE:',
790
+    'texte_date_creation_objet' => 'Creation date:', # on ajoute le ":"
791
+    'texte_date_publication_anterieure' => 'Date first published:',
792
+    'texte_date_publication_anterieure_nonaffichee' => 'Hide previous publication date.',
793
+    'texte_date_publication_article' => 'PUBLISHED ON:',
794
+    'texte_date_publication_objet' => 'Published on:',
795
+    'texte_definir_comme_traduction_rubrique' => 'This section is a translation of section number:',
796
+    'texte_descriptif_rapide' => 'Brief description',
797
+    'texte_effacer_base' => 'Delete the SPIP database',
798
+    'texte_effacer_statistiques' => 'Delete the statistics',
799
+    'texte_en_cours_validation' => 'The following articles and news have been submitted for evaluation.',
800
+    'texte_enrichir_mise_a_jour' => 'You can enrich the layout of your text by using "typographical shortcuts".',
801
+    'texte_fichier_authent' => '<b>Should SPIP create the special files <tt>.htpasswd</tt>
802 802
   and <tt>.htpasswd-admin</tt> in the directory @dossier@?</b>
803 803
 <p>These files can be used to restrict access to authors and administrators to other parts of your site (for instance, external statistical programme).</p><p>If you have no need of such files, you can keep this option with its default value (no file creation).</p>',
804
-	'texte_informations_personnelles_1' => 'The system will now  create your personal account for this site.',
805
-	'texte_informations_personnelles_2' => '(Note: if it is a reinstallation, if your former access is still working, you can',
806
-	'texte_introductif_article' => '(Introductory text for the article.)',
807
-	'texte_jeu_caractere' => 'We advise using the universal alphabet (<tt>utf-8</tt>) on your site. This will make it possible to display text in any language. All modern browsers are fully comptabile with this character set.',
808
-	'texte_jeu_caractere_3' => 'Your site currently uses this character set:',
809
-	'texte_jeu_caractere_4' => 'If that does not correspond to your current data (this may occur after restoring your database from a backup), or if <em>you are setting up this site</em> and wish to use a different character set, please indicate the character set here:',
810
-	'texte_login_ldap_1' => '(Keep empty for anonymous access or enter complete path, for instance «<tt>uid=smith, ou=users, dc=my-domain, dc=com</tt>».)',
811
-	'texte_login_precaution' => 'Warning! This is the login which you are currently using.
804
+    'texte_informations_personnelles_1' => 'The system will now  create your personal account for this site.',
805
+    'texte_informations_personnelles_2' => '(Note: if it is a reinstallation, if your former access is still working, you can',
806
+    'texte_introductif_article' => '(Introductory text for the article.)',
807
+    'texte_jeu_caractere' => 'We advise using the universal alphabet (<tt>utf-8</tt>) on your site. This will make it possible to display text in any language. All modern browsers are fully comptabile with this character set.',
808
+    'texte_jeu_caractere_3' => 'Your site currently uses this character set:',
809
+    'texte_jeu_caractere_4' => 'If that does not correspond to your current data (this may occur after restoring your database from a backup), or if <em>you are setting up this site</em> and wish to use a different character set, please indicate the character set here:',
810
+    'texte_login_ldap_1' => '(Keep empty for anonymous access or enter complete path, for instance «<tt>uid=smith, ou=users, dc=my-domain, dc=com</tt>».)',
811
+    'texte_login_precaution' => 'Warning! This is the login which you are currently using.
812 812
  Use this form with caution...',
813
-	'texte_messagerie_agenda' => 'A messaging system lets website’s authors communicate directly into the admin area. It is linked to a calendar.',
814
-	'texte_mise_a_niveau_base_1' => 'You have just updated SPIP files.
813
+    'texte_messagerie_agenda' => 'A messaging system lets website’s authors communicate directly into the admin area. It is linked to a calendar.',
814
+    'texte_mise_a_niveau_base_1' => 'You have just updated SPIP files.
815 815
  Now you must upgrade the site
816 816
  database.',
817
-	'texte_modifier_article' => 'Edit this article:',
818
-	'texte_multilinguisme' => 'If you want to manage objects in several languages​​, with complex navigation, you can add a language selection menu to these objects, depending on the organization of your site.',
819
-	'texte_multilinguisme_trad' => 'You can also enable a system for managing links between the various translations of certain objects.',
820
-	'texte_non_compresse' => '<i>uncompressed</i> (your server does not support this feature)',
821
-	'texte_nouvelle_version_spip_1' => 'You have just installed a new version of SPIP.',
822
-	'texte_nouvelle_version_spip_2' => 'This new version requires a more thorough update than usual. If you are the webmaster of this site, please delete the file @connect@ and restart installation in order to update your database connection parameters. <p>(PS.: if you have forgotten your connection parameters, take a look at the file @connect@ before deleting it!)</p>',
823
-	'texte_operation_echec' => 'Go back to the previous page, select another database or create a new one. Verify the information provided by your hosting service.',
824
-	'texte_plus_trois_car' => 'more than 3 characters',
825
-	'texte_plusieurs_articles' => 'Several authors were found for "@cherche_auteur@":',
826
-	'texte_port_annuaire' => '(Default value is generally suitable.)',
827
-	'texte_presente_plugin' => 'This page shows the plugins available on this site. Activate the plugins you require by ticking the corresponding box.',
828
-	'texte_proposer_publication' => 'When your article is finished,<br /> you can submit it for publication.',
829
-	'texte_proxy' => 'In some cases (e.g. intranet, protected network), it is necessary to use an <i>HTTP proxy</i> to reach external sites (SPIP documentation, syndicated sites, etc.). If this is the case, enter its address in the form @proxy_en_cours@. In most cases you can leave this box empty.',
830
-	'texte_publication_articles_post_dates' => 'Which behaviour should SPIP adopt for articles whose
817
+    'texte_modifier_article' => 'Edit this article:',
818
+    'texte_multilinguisme' => 'If you want to manage objects in several languages​​, with complex navigation, you can add a language selection menu to these objects, depending on the organization of your site.',
819
+    'texte_multilinguisme_trad' => 'You can also enable a system for managing links between the various translations of certain objects.',
820
+    'texte_non_compresse' => '<i>uncompressed</i> (your server does not support this feature)',
821
+    'texte_nouvelle_version_spip_1' => 'You have just installed a new version of SPIP.',
822
+    'texte_nouvelle_version_spip_2' => 'This new version requires a more thorough update than usual. If you are the webmaster of this site, please delete the file @connect@ and restart installation in order to update your database connection parameters. <p>(PS.: if you have forgotten your connection parameters, take a look at the file @connect@ before deleting it!)</p>',
823
+    'texte_operation_echec' => 'Go back to the previous page, select another database or create a new one. Verify the information provided by your hosting service.',
824
+    'texte_plus_trois_car' => 'more than 3 characters',
825
+    'texte_plusieurs_articles' => 'Several authors were found for "@cherche_auteur@":',
826
+    'texte_port_annuaire' => '(Default value is generally suitable.)',
827
+    'texte_presente_plugin' => 'This page shows the plugins available on this site. Activate the plugins you require by ticking the corresponding box.',
828
+    'texte_proposer_publication' => 'When your article is finished,<br /> you can submit it for publication.',
829
+    'texte_proxy' => 'In some cases (e.g. intranet, protected network), it is necessary to use an <i>HTTP proxy</i> to reach external sites (SPIP documentation, syndicated sites, etc.). If this is the case, enter its address in the form @proxy_en_cours@. In most cases you can leave this box empty.',
830
+    'texte_publication_articles_post_dates' => 'Which behaviour should SPIP adopt for articles whose
831 831
   publication date has been set in
832 832
   the future?',
833
-	'texte_rappel_selection_champs' => '[Remember to select this field correctly.]',
834
-	'texte_recalcul_page' => 'If you want
833
+    'texte_rappel_selection_champs' => '[Remember to select this field correctly.]',
834
+    'texte_recalcul_page' => 'If you want
835 835
 to re-process a single page, it is easier to view that page from the public site and click "Re-process this page".',
836
-	'texte_recuperer_base' => 'Repair the database',
837
-	'texte_reference_mais_redirige' => 'article referenced in your SPIP site, but redirected to another URL.',
838
-	'texte_requetes_echouent' => '<b>When some SQL queries fail
836
+    'texte_recuperer_base' => 'Repair the database',
837
+    'texte_reference_mais_redirige' => 'article referenced in your SPIP site, but redirected to another URL.',
838
+    'texte_requetes_echouent' => '<b>When some SQL queries fail
839 839
   systematically, without apparent reason, it is possible
840 840
   that the database itself
841 841
   is the culprit.</b><p>
@@ -846,87 +846,87 @@  discard block
 block discarded – undo
846 846
   clues as to where the problem lies.</p><p>
847 847
   If the problem persists, contact your 
848 848
   service provider.</p>',
849
-	'texte_selection_langue_principale' => 'You can choose the website’s "primary language". This does not mean that you can only write articles in that language, but it will be used to determine
849
+    'texte_selection_langue_principale' => 'You can choose the website’s "primary language". This does not mean that you can only write articles in that language, but it will be used to determine
850 850
 
851 851
 <ul><li> the default date/time format on the public website,</li>
852 852
 <li> the nature of the typographical engine which will be used by SPIP for rendering text,</li>
853 853
 <li> the language in use in public website’s forms,</li>
854 854
 <li> the default language in use in the admin area.</li></ul>',
855
-	'texte_sous_titre' => 'Subtitle',
856
-	'texte_statistiques_visites' => '(dark bars = Sunday, dark curve: average visits)',
857
-	'texte_statut_attente_validation' => 'awaiting validation',
858
-	'texte_statut_publies' => 'published online',
859
-	'texte_statut_refuses' => 'rejected',
860
-	'texte_suppression_fichiers' => 'Use this command to purge all the files
855
+    'texte_sous_titre' => 'Subtitle',
856
+    'texte_statistiques_visites' => '(dark bars = Sunday, dark curve: average visits)',
857
+    'texte_statut_attente_validation' => 'awaiting validation',
858
+    'texte_statut_publies' => 'published online',
859
+    'texte_statut_refuses' => 'rejected',
860
+    'texte_suppression_fichiers' => 'Use this command to purge all the files
861 861
 in the SPIP cache. This will force recalculation of every page on the site, useful after
862 862
 significant modifications to the site’s graphics or structure.',
863
-	'texte_sur_titre' => 'Lead-in title',
864
-	'texte_table_ok' => ': this table is OK.',
865
-	'texte_tentative_recuperation' => 'Attempting to repair',
866
-	'texte_tenter_reparation' => 'Attempt to repair the database',
867
-	'texte_test_proxy' => 'To test this proxy, enter the address of a website
863
+    'texte_sur_titre' => 'Lead-in title',
864
+    'texte_table_ok' => ': this table is OK.',
865
+    'texte_tentative_recuperation' => 'Attempting to repair',
866
+    'texte_tenter_reparation' => 'Attempt to repair the database',
867
+    'texte_test_proxy' => 'To test this proxy, enter the address of a website
868 868
     for verification.',
869
-	'texte_titre_02' => 'Subject:',
870
-	'texte_titre_obligatoire' => '<b>Title</b> [Required]',
871
-	'texte_travail_article' => '@nom_auteur_modif@ edited this article @date_diff@ minutes ago',
872
-	'texte_travail_collaboratif' => 'If several editors often work on the same article, the system can mark recently "opened" articles in order to avoid multiple simultaneous editing.
869
+    'texte_titre_02' => 'Subject:',
870
+    'texte_titre_obligatoire' => '<b>Title</b> [Required]',
871
+    'texte_travail_article' => '@nom_auteur_modif@ edited this article @date_diff@ minutes ago',
872
+    'texte_travail_collaboratif' => 'If several editors often work on the same article, the system can mark recently "opened" articles in order to avoid multiple simultaneous editing.
873 873
   This option is disabled by default to avoid displaying unnecessary warning
874 874
   messages.',
875
-	'texte_vide' => 'empty',
876
-	'texte_vider_cache' => 'Empty the cache',
877
-	'titre_admin_tech' => 'Technical maintenance',
878
-	'titre_admin_vider' => 'Technical maintenance',
879
-	'titre_ajouter_un_auteur' => 'Add an author',
880
-	'titre_ajouter_un_mot' => 'Add a keyword',
881
-	'titre_cadre_afficher_article' => 'Show the articles:',
882
-	'titre_cadre_afficher_traductions' => 'Display the translation status for these languages:',
883
-	'titre_cadre_ajouter_auteur' => 'ADD AN AUTHOR:',
884
-	'titre_cadre_interieur_rubrique' => 'In section',
885
-	'titre_cadre_numero_auteur' => 'AUTHOR NUMBER',
886
-	'titre_cadre_numero_objet' => '@objet@ NUMBER:',
887
-	'titre_cadre_signature_obligatoire' => '<b>Signature</b> [Required]<br />',
888
-	'titre_config_contenu_notifications' => 'Notifications',
889
-	'titre_config_contenu_prive' => 'In the admin area',
890
-	'titre_config_contenu_public' => 'On the public site',
891
-	'titre_config_fonctions' => 'Site configuration',
892
-	'titre_config_langage' => 'Configure the language',
893
-	'titre_configuration' => 'Site configuration',
894
-	'titre_configurer_preferences' => 'Configure your preferences',
895
-	'titre_configurer_preferences_menus' => 'Settings of your menus preferences',
896
-	'titre_conflit_edition' => 'Conflict while editing',
897
-	'titre_connexion_ldap' => 'Options: <b>Your LDAP connection</b>',
898
-	'titre_groupe_mots' => 'KEYWORD GROUP:',
899
-	'titre_identite_site' => 'Site identity',
900
-	'titre_langue_article' => 'Article language',
901
-	'titre_langue_rubrique' => 'Section language',
902
-	'titre_langue_trad_article' => 'ARTICLE LANGUAGE AND TRANSLATIONS',
903
-	'titre_les_articles' => 'ARTICLES',
904
-	'titre_messagerie_agenda' => 'Messaging system and calendar',
905
-	'titre_naviguer_dans_le_site' => 'Browse the site...',
906
-	'titre_nouvelle_rubrique' => 'New section',
907
-	'titre_numero_rubrique' => 'SECTION NUMBER:',
908
-	'titre_page_articles_edit' => 'Modify: @titre@',
909
-	'titre_page_articles_page' => 'Articles',
910
-	'titre_page_articles_tous' => 'The entire site',
911
-	'titre_page_calendrier' => 'Calendar @nom_mois@ @annee@',
912
-	'titre_page_config_contenu' => 'Site configuration',
913
-	'titre_page_delete_all' => 'total and irreversible deletion',
914
-	'titre_page_recherche' => 'Search results @recherche@',
915
-	'titre_page_statistiques_referers' => 'Statistics (incoming links)',
916
-	'titre_page_upgrade' => 'SPIP upgrade',
917
-	'titre_preference_menus_favoris' => 'Favourites menu',
918
-	'titre_publication_articles_post_dates' => 'Publication of post dated articles',
919
-	'titre_reparation' => 'Repair',
920
-	'titre_suivi_petition' => 'Petitions follow-up',
921
-	'tls_ldap' => 'Transport Layer Security :',
922
-	'trad_article_traduction' => 'All the versions of this article:',
923
-	'trad_delier' => 'Stop linking to these translations',
924
-	'trad_lier' => 'This article is a translation of article number:',
925
-	'trad_new' => 'Write a new translation',
875
+    'texte_vide' => 'empty',
876
+    'texte_vider_cache' => 'Empty the cache',
877
+    'titre_admin_tech' => 'Technical maintenance',
878
+    'titre_admin_vider' => 'Technical maintenance',
879
+    'titre_ajouter_un_auteur' => 'Add an author',
880
+    'titre_ajouter_un_mot' => 'Add a keyword',
881
+    'titre_cadre_afficher_article' => 'Show the articles:',
882
+    'titre_cadre_afficher_traductions' => 'Display the translation status for these languages:',
883
+    'titre_cadre_ajouter_auteur' => 'ADD AN AUTHOR:',
884
+    'titre_cadre_interieur_rubrique' => 'In section',
885
+    'titre_cadre_numero_auteur' => 'AUTHOR NUMBER',
886
+    'titre_cadre_numero_objet' => '@objet@ NUMBER:',
887
+    'titre_cadre_signature_obligatoire' => '<b>Signature</b> [Required]<br />',
888
+    'titre_config_contenu_notifications' => 'Notifications',
889
+    'titre_config_contenu_prive' => 'In the admin area',
890
+    'titre_config_contenu_public' => 'On the public site',
891
+    'titre_config_fonctions' => 'Site configuration',
892
+    'titre_config_langage' => 'Configure the language',
893
+    'titre_configuration' => 'Site configuration',
894
+    'titre_configurer_preferences' => 'Configure your preferences',
895
+    'titre_configurer_preferences_menus' => 'Settings of your menus preferences',
896
+    'titre_conflit_edition' => 'Conflict while editing',
897
+    'titre_connexion_ldap' => 'Options: <b>Your LDAP connection</b>',
898
+    'titre_groupe_mots' => 'KEYWORD GROUP:',
899
+    'titre_identite_site' => 'Site identity',
900
+    'titre_langue_article' => 'Article language',
901
+    'titre_langue_rubrique' => 'Section language',
902
+    'titre_langue_trad_article' => 'ARTICLE LANGUAGE AND TRANSLATIONS',
903
+    'titre_les_articles' => 'ARTICLES',
904
+    'titre_messagerie_agenda' => 'Messaging system and calendar',
905
+    'titre_naviguer_dans_le_site' => 'Browse the site...',
906
+    'titre_nouvelle_rubrique' => 'New section',
907
+    'titre_numero_rubrique' => 'SECTION NUMBER:',
908
+    'titre_page_articles_edit' => 'Modify: @titre@',
909
+    'titre_page_articles_page' => 'Articles',
910
+    'titre_page_articles_tous' => 'The entire site',
911
+    'titre_page_calendrier' => 'Calendar @nom_mois@ @annee@',
912
+    'titre_page_config_contenu' => 'Site configuration',
913
+    'titre_page_delete_all' => 'total and irreversible deletion',
914
+    'titre_page_recherche' => 'Search results @recherche@',
915
+    'titre_page_statistiques_referers' => 'Statistics (incoming links)',
916
+    'titre_page_upgrade' => 'SPIP upgrade',
917
+    'titre_preference_menus_favoris' => 'Favourites menu',
918
+    'titre_publication_articles_post_dates' => 'Publication of post dated articles',
919
+    'titre_reparation' => 'Repair',
920
+    'titre_suivi_petition' => 'Petitions follow-up',
921
+    'tls_ldap' => 'Transport Layer Security :',
922
+    'trad_article_traduction' => 'All the versions of this article:',
923
+    'trad_delier' => 'Stop linking to these translations',
924
+    'trad_lier' => 'This article is a translation of article number:',
925
+    'trad_new' => 'Write a new translation',
926 926
 
927
-	// U
928
-	'utf8_convert_erreur_orig' => 'Error: the character set @charset@ is not supported.',
927
+    // U
928
+    'utf8_convert_erreur_orig' => 'Error: the character set @charset@ is not supported.',
929 929
 
930
-	// V
931
-	'version' => 'Version:'
930
+    // V
931
+    'version' => 'Version:'
932 932
 );
Please login to merge, or discard this patch.
ecrire/inc/editer.php 1 patch
Indentation   +442 added lines, -442 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('base/abstract_sql');
23 23
 
@@ -59,56 +59,56 @@  discard block
 block discarded – undo
59 59
  *     Retour des traitements.
60 60
  **/
61 61
 function formulaires_editer_objet_traiter(
62
-	$type,
63
-	$id = 'new',
64
-	$id_parent = 0,
65
-	$lier_trad = 0,
66
-	$retour = '',
67
-	$config_fonc = 'articles_edit_config',
68
-	$row = [],
69
-	$hidden = ''
62
+    $type,
63
+    $id = 'new',
64
+    $id_parent = 0,
65
+    $lier_trad = 0,
66
+    $retour = '',
67
+    $config_fonc = 'articles_edit_config',
68
+    $row = [],
69
+    $hidden = ''
70 70
 ) {
71 71
 
72
-	$res = [];
73
-	// eviter la redirection forcee par l'action...
74
-	set_request('redirect');
75
-	if ($action_editer = charger_fonction("editer_$type", 'action', true)) {
76
-		[$id, $err] = $action_editer($id);
77
-	} else {
78
-		$action_editer = charger_fonction('editer_objet', 'action');
79
-		[$id, $err] = $action_editer($id, $type);
80
-	}
81
-	$id_table_objet = id_table_objet($type);
82
-	$res[$id_table_objet] = $id;
83
-	if ($err or !$id) {
84
-		$res['message_erreur'] = ($err ?: _T('erreur'));
85
-	} else {
86
-		// Un lien de trad a prendre en compte
87
-		if ($lier_trad) {
88
-			// referencer la traduction
89
-			$referencer_traduction = charger_fonction('referencer_traduction', 'action');
90
-			$referencer_traduction($type, $id, $lier_trad);
91
-			// actions de recopie de champs / liens sur le nouvel objet créé
92
-			$completer_traduction = charger_fonction('completer_traduction', 'inc');
93
-			$err = $completer_traduction($type, $id, $lier_trad);
94
-			if ($err) {
95
-				$res['message_erreur'] = $err;
96
-				return $res;
97
-			}
98
-		}
99
-
100
-		$res['message_ok'] = _T('info_modification_enregistree');
101
-		if ($retour) {
102
-			if (strncmp($retour, 'javascript:', 11) == 0) {
103
-				$res['message_ok'] .= '<script type="text/javascript">/*<![CDATA[*/' . substr($retour, 11) . '/*]]>*/</script>';
104
-				$res['editable'] = true;
105
-			} else {
106
-				$res['redirect'] = parametre_url($retour, $id_table_objet, $id);
107
-			}
108
-		}
109
-	}
110
-
111
-	return $res;
72
+    $res = [];
73
+    // eviter la redirection forcee par l'action...
74
+    set_request('redirect');
75
+    if ($action_editer = charger_fonction("editer_$type", 'action', true)) {
76
+        [$id, $err] = $action_editer($id);
77
+    } else {
78
+        $action_editer = charger_fonction('editer_objet', 'action');
79
+        [$id, $err] = $action_editer($id, $type);
80
+    }
81
+    $id_table_objet = id_table_objet($type);
82
+    $res[$id_table_objet] = $id;
83
+    if ($err or !$id) {
84
+        $res['message_erreur'] = ($err ?: _T('erreur'));
85
+    } else {
86
+        // Un lien de trad a prendre en compte
87
+        if ($lier_trad) {
88
+            // referencer la traduction
89
+            $referencer_traduction = charger_fonction('referencer_traduction', 'action');
90
+            $referencer_traduction($type, $id, $lier_trad);
91
+            // actions de recopie de champs / liens sur le nouvel objet créé
92
+            $completer_traduction = charger_fonction('completer_traduction', 'inc');
93
+            $err = $completer_traduction($type, $id, $lier_trad);
94
+            if ($err) {
95
+                $res['message_erreur'] = $err;
96
+                return $res;
97
+            }
98
+        }
99
+
100
+        $res['message_ok'] = _T('info_modification_enregistree');
101
+        if ($retour) {
102
+            if (strncmp($retour, 'javascript:', 11) == 0) {
103
+                $res['message_ok'] .= '<script type="text/javascript">/*<![CDATA[*/' . substr($retour, 11) . '/*]]>*/</script>';
104
+                $res['editable'] = true;
105
+            } else {
106
+                $res['redirect'] = parametre_url($retour, $id_table_objet, $id);
107
+            }
108
+        }
109
+    }
110
+
111
+    return $res;
112 112
 }
113 113
 
114 114
 /**
@@ -132,29 +132,29 @@  discard block
 block discarded – undo
132 132
  *     Tableau des erreurs
133 133
  **/
134 134
 function formulaires_editer_objet_verifier($type, $id = 'new', $oblis = []) {
135
-	$erreurs = [];
136
-	if (intval($id)) {
137
-		$conflits = controler_contenu($type, $id);
138
-		if ($conflits and is_countable($conflits) ? count($conflits) : 0) {
139
-			foreach ($conflits as $champ => $conflit) {
140
-				if (!isset($erreurs[$champ])) {
141
-					$erreurs[$champ] = '';
142
-				}
143
-				$erreurs[$champ] .= _T('alerte_modif_info_concourante') . "<br /><textarea readonly='readonly' class='forml'>" . entites_html($conflit['base']) . '</textarea>';
144
-			}
145
-		}
146
-	}
147
-	foreach ($oblis as $obli) {
148
-		$value = _request($obli);
149
-		if (is_null($value) or !(is_array($value) ? count($value) : strlen($value))) {
150
-			if (!isset($erreurs[$obli])) {
151
-				$erreurs[$obli] = '';
152
-			}
153
-			$erreurs[$obli] .= _T('info_obligatoire');
154
-		}
155
-	}
156
-
157
-	return $erreurs;
135
+    $erreurs = [];
136
+    if (intval($id)) {
137
+        $conflits = controler_contenu($type, $id);
138
+        if ($conflits and is_countable($conflits) ? count($conflits) : 0) {
139
+            foreach ($conflits as $champ => $conflit) {
140
+                if (!isset($erreurs[$champ])) {
141
+                    $erreurs[$champ] = '';
142
+                }
143
+                $erreurs[$champ] .= _T('alerte_modif_info_concourante') . "<br /><textarea readonly='readonly' class='forml'>" . entites_html($conflit['base']) . '</textarea>';
144
+            }
145
+        }
146
+    }
147
+    foreach ($oblis as $obli) {
148
+        $value = _request($obli);
149
+        if (is_null($value) or !(is_array($value) ? count($value) : strlen($value))) {
150
+            if (!isset($erreurs[$obli])) {
151
+                $erreurs[$obli] = '';
152
+            }
153
+            $erreurs[$obli] .= _T('info_obligatoire');
154
+        }
155
+    }
156
+
157
+    return $erreurs;
158 158
 }
159 159
 
160 160
 /**
@@ -199,154 +199,154 @@  discard block
 block discarded – undo
199 199
  *     Environnement du formulaire.
200 200
  **/
201 201
 function formulaires_editer_objet_charger(
202
-	$type,
203
-	$id = 'new',
204
-	$id_parent = 0,
205
-	$lier_trad = 0,
206
-	$retour = '',
207
-	$config_fonc = 'articles_edit_config',
208
-	$row = [],
209
-	$hidden = ''
202
+    $type,
203
+    $id = 'new',
204
+    $id_parent = 0,
205
+    $lier_trad = 0,
206
+    $retour = '',
207
+    $config_fonc = 'articles_edit_config',
208
+    $row = [],
209
+    $hidden = ''
210 210
 ) {
211 211
 
212
-	$table_objet = table_objet($type);
213
-	$table_objet_sql = table_objet_sql($type);
214
-	$id_table_objet = id_table_objet($type);
215
-	if (!is_array($row)) {
216
-		$row = [];
217
-	}
218
-
219
-	// on accepte pas une fonction de config inconnue si elle vient d'un modele
220
-	if (
221
-		$config_fonc
222
-		and !in_array($config_fonc, ['articles_edit_config', 'rubriques_edit_config', 'auteurs_edit_config'])
223
-		and $config_fonc !== $table_objet . '_edit_config'
224
-	) {
225
-		if (
226
-			$args = test_formulaire_inclus_par_modele()
227
-			and in_array($config_fonc, $args)
228
-		) {
229
-			$config_fonc = '';
230
-		}
231
-	}
232
-
233
-	$new = !is_numeric($id);
234
-	$lang_default = '';
235
-	// Appel direct dans un squelette
236
-	if (!$row) {
237
-		if (!$new or $lier_trad) {
238
-			if ($select = charger_fonction('precharger_' . $type, 'inc', true)) {
239
-				$row = $select($id, $id_parent, $lier_trad);
240
-				// si on a une fonction precharger, elle pu faire un reglage de langue
241
-				$lang_default = (!empty($row['lang']) ? $row['lang'] : null);
242
-			} else {
243
-				$row = sql_fetsel('*', $table_objet_sql, $id_table_objet . '=' . intval($id));
244
-			}
245
-			if (!$new) {
246
-				$md5 = controles_md5($row ?: []);
247
-			}
248
-		}
249
-		if (!$row) {
250
-			$row = [];
251
-			$trouver_table = charger_fonction('trouver_table', 'base');
252
-			if ($desc = $trouver_table($table_objet)) {
253
-				foreach ($desc['field'] as $k => $v) {
254
-					$row[$k] = '';
255
-				}
256
-			}
257
-		}
258
-	}
259
-
260
-	// Gaffe: sans ceci, on ecrase systematiquement l'article d'origine
261
-	// (et donc: pas de lien de traduction)
262
-	$id = ($new or $lier_trad)
263
-		? 'oui'
264
-		: $row[$id_table_objet];
265
-	$row[$id_table_objet] = $id;
266
-
267
-	$contexte = $row;
268
-	if (is_numeric($id_parent) && strlen($id_parent) && (!isset($contexte['id_parent']) or $new)) {
269
-		if (!isset($contexte['id_parent'])) {
270
-			unset($contexte['id_rubrique']);
271
-		}
272
-		$contexte['id_parent'] = $id_parent;
273
-	} elseif (!isset($contexte['id_parent'])) {
274
-		// id_rubrique dans id_parent si possible
275
-		if (isset($contexte['id_rubrique'])) {
276
-			$contexte['id_parent'] = $contexte['id_rubrique'];
277
-			unset($contexte['id_rubrique']);
278
-		} else {
279
-			$contexte['id_parent'] = '';
280
-		}
281
-		if (
282
-			!$contexte['id_parent']
283
-			and $preselectionner_parent_nouvel_objet = charger_fonction('preselectionner_parent_nouvel_objet', 'inc', true)
284
-		) {
285
-			$contexte['id_parent'] = $preselectionner_parent_nouvel_objet($type, $row);
286
-		}
287
-	}
288
-
289
-	$config = [];
290
-	if ($config_fonc) {
291
-		$contexte['config'] = $config = $config_fonc($contexte);
292
-		if (!$lang_default) {
293
-			$lang_default = $config['langue'] ?? session_get('lang') ;
294
-		}
295
-	}
296
-	$config = $config + [
297
-		'lignes' => 0,
298
-		'langue' => '',
299
-	];
300
-
301
-	$att_text = " class='textarea' "
302
-		. " rows='"
303
-		. ($config['lignes'] + 15)
304
-		. "' cols='40'";
305
-	if (isset($contexte['texte'])) {
306
-		[$contexte['texte'], $contexte['_texte_trop_long']] = editer_texte_recolle($contexte['texte'], $att_text);
307
-	}
308
-
309
-	// on veut conserver la langue de l'interface ;
310
-	// on passe cette donnee sous un autre nom, au cas ou le squelette
311
-	// voudrait l'exploiter
312
-	if (isset($contexte['lang'])) {
313
-		$contexte['langue'] = $contexte['lang'];
314
-		unset($contexte['lang']);
315
-	}
316
-
317
-	$contexte['_hidden'] = "<input type='hidden' name='editer_$type' value='oui' />\n" .
318
-		(!$lier_trad ? '' :
319
-			("\n<input type='hidden' name='lier_trad' value='" .
320
-				$lier_trad .
321
-				"' />" .
322
-				"\n<input type='hidden' name='changer_lang' value='" .
323
-				$lang_default .
324
-				"' />"))
325
-		. $hidden
326
-		. ($md5 ?? '');
327
-
328
-	// preciser que le formulaire doit passer dans un pipeline
329
-	$contexte['_pipeline'] = ['editer_contenu_objet', ['type' => $type, 'id' => $id]];
330
-
331
-	// preciser que le formulaire doit etre securise auteur/action
332
-	// n'est plus utile lorsque l'action accepte l'id en argument direct
333
-	// on le garde pour compat
334
-	$contexte['_action'] = ["editer_$type", $id];
335
-
336
-	// et in fine placer l'autorisation
337
-	include_spip('inc/autoriser');
338
-	if (intval($id)) {
339
-		if (!autoriser('modifier', $type, intval($id))) {
340
-			$contexte['editable'] = '';
341
-		}
342
-	}
343
-	else {
344
-		if (!autoriser('creer', $type, 0, null, ['id_parent' => $id_parent])) {
345
-			$contexte['editable'] = '';
346
-		}
347
-	}
348
-
349
-	return $contexte;
212
+    $table_objet = table_objet($type);
213
+    $table_objet_sql = table_objet_sql($type);
214
+    $id_table_objet = id_table_objet($type);
215
+    if (!is_array($row)) {
216
+        $row = [];
217
+    }
218
+
219
+    // on accepte pas une fonction de config inconnue si elle vient d'un modele
220
+    if (
221
+        $config_fonc
222
+        and !in_array($config_fonc, ['articles_edit_config', 'rubriques_edit_config', 'auteurs_edit_config'])
223
+        and $config_fonc !== $table_objet . '_edit_config'
224
+    ) {
225
+        if (
226
+            $args = test_formulaire_inclus_par_modele()
227
+            and in_array($config_fonc, $args)
228
+        ) {
229
+            $config_fonc = '';
230
+        }
231
+    }
232
+
233
+    $new = !is_numeric($id);
234
+    $lang_default = '';
235
+    // Appel direct dans un squelette
236
+    if (!$row) {
237
+        if (!$new or $lier_trad) {
238
+            if ($select = charger_fonction('precharger_' . $type, 'inc', true)) {
239
+                $row = $select($id, $id_parent, $lier_trad);
240
+                // si on a une fonction precharger, elle pu faire un reglage de langue
241
+                $lang_default = (!empty($row['lang']) ? $row['lang'] : null);
242
+            } else {
243
+                $row = sql_fetsel('*', $table_objet_sql, $id_table_objet . '=' . intval($id));
244
+            }
245
+            if (!$new) {
246
+                $md5 = controles_md5($row ?: []);
247
+            }
248
+        }
249
+        if (!$row) {
250
+            $row = [];
251
+            $trouver_table = charger_fonction('trouver_table', 'base');
252
+            if ($desc = $trouver_table($table_objet)) {
253
+                foreach ($desc['field'] as $k => $v) {
254
+                    $row[$k] = '';
255
+                }
256
+            }
257
+        }
258
+    }
259
+
260
+    // Gaffe: sans ceci, on ecrase systematiquement l'article d'origine
261
+    // (et donc: pas de lien de traduction)
262
+    $id = ($new or $lier_trad)
263
+        ? 'oui'
264
+        : $row[$id_table_objet];
265
+    $row[$id_table_objet] = $id;
266
+
267
+    $contexte = $row;
268
+    if (is_numeric($id_parent) && strlen($id_parent) && (!isset($contexte['id_parent']) or $new)) {
269
+        if (!isset($contexte['id_parent'])) {
270
+            unset($contexte['id_rubrique']);
271
+        }
272
+        $contexte['id_parent'] = $id_parent;
273
+    } elseif (!isset($contexte['id_parent'])) {
274
+        // id_rubrique dans id_parent si possible
275
+        if (isset($contexte['id_rubrique'])) {
276
+            $contexte['id_parent'] = $contexte['id_rubrique'];
277
+            unset($contexte['id_rubrique']);
278
+        } else {
279
+            $contexte['id_parent'] = '';
280
+        }
281
+        if (
282
+            !$contexte['id_parent']
283
+            and $preselectionner_parent_nouvel_objet = charger_fonction('preselectionner_parent_nouvel_objet', 'inc', true)
284
+        ) {
285
+            $contexte['id_parent'] = $preselectionner_parent_nouvel_objet($type, $row);
286
+        }
287
+    }
288
+
289
+    $config = [];
290
+    if ($config_fonc) {
291
+        $contexte['config'] = $config = $config_fonc($contexte);
292
+        if (!$lang_default) {
293
+            $lang_default = $config['langue'] ?? session_get('lang') ;
294
+        }
295
+    }
296
+    $config = $config + [
297
+        'lignes' => 0,
298
+        'langue' => '',
299
+    ];
300
+
301
+    $att_text = " class='textarea' "
302
+        . " rows='"
303
+        . ($config['lignes'] + 15)
304
+        . "' cols='40'";
305
+    if (isset($contexte['texte'])) {
306
+        [$contexte['texte'], $contexte['_texte_trop_long']] = editer_texte_recolle($contexte['texte'], $att_text);
307
+    }
308
+
309
+    // on veut conserver la langue de l'interface ;
310
+    // on passe cette donnee sous un autre nom, au cas ou le squelette
311
+    // voudrait l'exploiter
312
+    if (isset($contexte['lang'])) {
313
+        $contexte['langue'] = $contexte['lang'];
314
+        unset($contexte['lang']);
315
+    }
316
+
317
+    $contexte['_hidden'] = "<input type='hidden' name='editer_$type' value='oui' />\n" .
318
+        (!$lier_trad ? '' :
319
+            ("\n<input type='hidden' name='lier_trad' value='" .
320
+                $lier_trad .
321
+                "' />" .
322
+                "\n<input type='hidden' name='changer_lang' value='" .
323
+                $lang_default .
324
+                "' />"))
325
+        . $hidden
326
+        . ($md5 ?? '');
327
+
328
+    // preciser que le formulaire doit passer dans un pipeline
329
+    $contexte['_pipeline'] = ['editer_contenu_objet', ['type' => $type, 'id' => $id]];
330
+
331
+    // preciser que le formulaire doit etre securise auteur/action
332
+    // n'est plus utile lorsque l'action accepte l'id en argument direct
333
+    // on le garde pour compat
334
+    $contexte['_action'] = ["editer_$type", $id];
335
+
336
+    // et in fine placer l'autorisation
337
+    include_spip('inc/autoriser');
338
+    if (intval($id)) {
339
+        if (!autoriser('modifier', $type, intval($id))) {
340
+            $contexte['editable'] = '';
341
+        }
342
+    }
343
+    else {
344
+        if (!autoriser('creer', $type, 0, null, ['id_parent' => $id_parent])) {
345
+            $contexte['editable'] = '';
346
+        }
347
+    }
348
+
349
+    return $contexte;
350 350
 }
351 351
 
352 352
 /**
@@ -357,29 +357,29 @@  discard block
 block discarded – undo
357 357
  * @return array
358 358
  */
359 359
 function coupe_trop_long($texte) {
360
-	$aider = charger_fonction('aider', 'inc');
361
-	if (strlen($texte) > 28 * 1024) {
362
-		$texte = str_replace("\r\n", "\n", $texte);
363
-		$pos = strpos($texte, "\n\n", 28 * 1024);  // coupe para > 28 ko
364
-		if ($pos > 0 and $pos < 32 * 1024) {
365
-			$debut = substr($texte, 0, $pos) . "\n\n<!--SPIP-->\n";
366
-			$suite = substr($texte, $pos + 2);
367
-		} else {
368
-			$pos = strpos($texte, ' ', 28 * 1024);  // sinon coupe espace
369
-			if (!($pos > 0 and $pos < 32 * 1024)) {
370
-				$pos = 28 * 1024;  // au pire (pas d'espace trouv'e)
371
-				$decalage = 0; // si y'a pas d'espace, il ne faut pas perdre le caract`ere
372
-			} else {
373
-				$decalage = 1;
374
-			}
375
-			$debut = substr($texte, 0, $pos + $decalage); // Il faut conserver l'espace s'il y en a un
376
-			$suite = substr($texte, $pos + $decalage);
377
-		}
378
-
379
-		return ([$debut, $suite]);
380
-	} else {
381
-		return ([$texte, '']);
382
-	}
360
+    $aider = charger_fonction('aider', 'inc');
361
+    if (strlen($texte) > 28 * 1024) {
362
+        $texte = str_replace("\r\n", "\n", $texte);
363
+        $pos = strpos($texte, "\n\n", 28 * 1024);  // coupe para > 28 ko
364
+        if ($pos > 0 and $pos < 32 * 1024) {
365
+            $debut = substr($texte, 0, $pos) . "\n\n<!--SPIP-->\n";
366
+            $suite = substr($texte, $pos + 2);
367
+        } else {
368
+            $pos = strpos($texte, ' ', 28 * 1024);  // sinon coupe espace
369
+            if (!($pos > 0 and $pos < 32 * 1024)) {
370
+                $pos = 28 * 1024;  // au pire (pas d'espace trouv'e)
371
+                $decalage = 0; // si y'a pas d'espace, il ne faut pas perdre le caract`ere
372
+            } else {
373
+                $decalage = 1;
374
+            }
375
+            $debut = substr($texte, 0, $pos + $decalage); // Il faut conserver l'espace s'il y en a un
376
+            $suite = substr($texte, $pos + $decalage);
377
+        }
378
+
379
+        return ([$debut, $suite]);
380
+    } else {
381
+        return ([$texte, '']);
382
+    }
383 383
 }
384 384
 
385 385
 /**
@@ -390,25 +390,25 @@  discard block
 block discarded – undo
390 390
  * @return array
391 391
  */
392 392
 function editer_texte_recolle($texte, $att_text) {
393
-	if (
394
-		(strlen($texte) < 29 * 1024)
395
-		or (include_spip('inc/layer') and ($GLOBALS['browser_name'] != 'MSIE'))
396
-	) {
397
-		return [$texte, ''];
398
-	}
399
-
400
-	include_spip('inc/barre');
401
-	$textes_supplement = "<br /><span style='color: red'>" . _T('info_texte_long') . "</span>\n";
402
-	$nombre = 0;
403
-
404
-	while (strlen($texte) > 29 * 1024) {
405
-		$nombre++;
406
-		[$texte1, $texte] = coupe_trop_long($texte);
407
-		$textes_supplement .= '<br />' .
408
-			"<textarea id='texte$nombre' name='texte_plus[$nombre]'$att_text>$texte1</textarea>\n";
409
-	}
410
-
411
-	return [$texte, $textes_supplement];
393
+    if (
394
+        (strlen($texte) < 29 * 1024)
395
+        or (include_spip('inc/layer') and ($GLOBALS['browser_name'] != 'MSIE'))
396
+    ) {
397
+        return [$texte, ''];
398
+    }
399
+
400
+    include_spip('inc/barre');
401
+    $textes_supplement = "<br /><span style='color: red'>" . _T('info_texte_long') . "</span>\n";
402
+    $nombre = 0;
403
+
404
+    while (strlen($texte) > 29 * 1024) {
405
+        $nombre++;
406
+        [$texte1, $texte] = coupe_trop_long($texte);
407
+        $textes_supplement .= '<br />' .
408
+            "<textarea id='texte$nombre' name='texte_plus[$nombre]'$att_text>$texte1</textarea>\n";
409
+    }
410
+
411
+    return [$texte, $textes_supplement];
412 412
 }
413 413
 
414 414
 /**
@@ -419,17 +419,17 @@  discard block
 block discarded – undo
419 419
  * @param int $longueur
420 420
  */
421 421
 function titre_automatique($champ_titre, $champs_contenu, $longueur = null) {
422
-	if (!_request($champ_titre)) {
423
-		$titrer_contenu = charger_fonction('titrer_contenu', 'inc');
424
-		if (!is_null($longueur)) {
425
-			$t = $titrer_contenu($champs_contenu, null, $longueur);
426
-		} else {
427
-			$t = $titrer_contenu($champs_contenu);
428
-		}
429
-		if ($t) {
430
-			set_request($champ_titre, $t);
431
-		}
432
-	}
422
+    if (!_request($champ_titre)) {
423
+        $titrer_contenu = charger_fonction('titrer_contenu', 'inc');
424
+        if (!is_null($longueur)) {
425
+            $t = $titrer_contenu($champs_contenu, null, $longueur);
426
+        } else {
427
+            $t = $titrer_contenu($champs_contenu);
428
+        }
429
+        if ($t) {
430
+            set_request($champ_titre, $t);
431
+        }
432
+    }
433 433
 }
434 434
 
435 435
 /**
@@ -449,20 +449,20 @@  discard block
 block discarded – undo
449 449
  * @return string
450 450
  */
451 451
 function inc_titrer_contenu_dist($champs_contenu, $c = null, $longueur = 50) {
452
-	// trouver un champ texte non vide
453
-	$t = '';
454
-	foreach ($champs_contenu as $champ) {
455
-		if ($t = _request($champ, $c)) {
456
-			break;
457
-		}
458
-	}
459
-
460
-	if ($t) {
461
-		include_spip('inc/texte_mini');
462
-		$t = couper($t, $longueur, '...');
463
-	}
464
-
465
-	return $t;
452
+    // trouver un champ texte non vide
453
+    $t = '';
454
+    foreach ($champs_contenu as $champ) {
455
+        if ($t = _request($champ, $c)) {
456
+            break;
457
+        }
458
+    }
459
+
460
+    if ($t) {
461
+        include_spip('inc/texte_mini');
462
+        $t = couper($t, $longueur, '...');
463
+    }
464
+
465
+    return $t;
466 466
 }
467 467
 
468 468
 /**
@@ -484,26 +484,26 @@  discard block
 block discarded – undo
484 484
  *      - array sinon couples ('$prefixe$colonne => md5)
485 485
  **/
486 486
 function controles_md5(array $data, string $prefixe = 'ctr_', string $format = 'html') {
487
-	$ctr = [];
488
-	foreach ($data as $key => $val) {
489
-		$m = md5($val ?? '');
490
-		$k = $prefixe . $key;
491
-
492
-		switch ($format) {
493
-			case 'html':
494
-				$ctr[$k] = "<input type='hidden' value='$m' name='$k' />";
495
-				break;
496
-			default:
497
-				$ctr[$k] = $m;
498
-				break;
499
-		}
500
-	}
501
-
502
-	if ($format === 'html') {
503
-		return "\n\n<!-- controles md5 -->\n" . join("\n", $ctr) . "\n\n";
504
-	} else {
505
-		return $ctr;
506
-	}
487
+    $ctr = [];
488
+    foreach ($data as $key => $val) {
489
+        $m = md5($val ?? '');
490
+        $k = $prefixe . $key;
491
+
492
+        switch ($format) {
493
+            case 'html':
494
+                $ctr[$k] = "<input type='hidden' value='$m' name='$k' />";
495
+                break;
496
+            default:
497
+                $ctr[$k] = $m;
498
+                break;
499
+        }
500
+    }
501
+
502
+    if ($format === 'html') {
503
+        return "\n\n<!-- controles md5 -->\n" . join("\n", $ctr) . "\n\n";
504
+    } else {
505
+        return $ctr;
506
+    }
507 507
 }
508 508
 
509 509
 /**
@@ -542,80 +542,80 @@  discard block
 block discarded – undo
542 542
  *     - post : le contenu posté
543 543
  **/
544 544
 function controler_contenu($type, $id, $options = [], $c = false, $serveur = '') {
545
-	include_spip('inc/filtres');
546
-
547
-	$table_objet = table_objet($type);
548
-	$spip_table_objet = table_objet_sql($type);
549
-	$trouver_table = charger_fonction('trouver_table', 'base');
550
-	$desc = $trouver_table($table_objet, $serveur);
551
-
552
-	// Appels incomplets (sans $c)
553
-	if (!is_array($c)) {
554
-		$c = [];
555
-		foreach ($desc['field'] as $champ => $ignore) {
556
-			if (_request($champ)) {
557
-				$c[$champ] = _request($champ);
558
-			}
559
-		}
560
-	}
561
-
562
-	// Securite : certaines variables ne sont jamais acceptees ici
563
-	// car elles ne relevent pas de autoriser(article, modifier) ;
564
-	// il faut passer par instituer_XX()
565
-	// TODO: faut-il passer ces variables interdites
566
-	// dans un fichier de description separe ?
567
-	unset($c['statut']);
568
-	unset($c['id_parent']);
569
-	unset($c['id_rubrique']);
570
-	unset($c['id_secteur']);
571
-
572
-	// Gerer les champs non vides
573
-	if (isset($options['nonvide']) and is_array($options['nonvide'])) {
574
-		foreach ($options['nonvide'] as $champ => $sinon) {
575
-			if ($c[$champ] === '') {
576
-				$c[$champ] = $sinon;
577
-			}
578
-		}
579
-	}
580
-
581
-	// N'accepter que les champs qui existent
582
-	// [TODO] ici aussi on peut valider les contenus en fonction du type
583
-	$champs = [];
584
-	foreach ($desc['field'] as $champ => $ignore) {
585
-		if (isset($c[$champ])) {
586
-			$champs[$champ] = $c[$champ];
587
-		}
588
-	}
589
-
590
-	// Nettoyer les valeurs
591
-	$champs = array_map('corriger_caracteres', $champs);
592
-
593
-	// Envoyer aux plugins
594
-	$champs = pipeline(
595
-		'pre_edition',
596
-		[
597
-			'args' => [
598
-				'table' => $spip_table_objet, // compatibilite
599
-				'table_objet' => $table_objet,
600
-				'spip_table_objet' => $spip_table_objet,
601
-				'type' => $type,
602
-				'id_objet' => $id,
603
-				'champs' => $options['champs'] ?? [], // [doc] c'est quoi ?
604
-				'action' => 'controler',
605
-				'serveur' => $serveur,
606
-			],
607
-			'data' => $champs
608
-		]
609
-	);
610
-
611
-	if (!$champs) {
612
-		return false;
613
-	}
614
-
615
-	// Verifier si les mises a jour sont pertinentes, datees, en conflit etc
616
-	$conflits = controler_md5($champs, $_POST, $type, $id, $serveur, $options['prefix'] ?? 'ctr_');
617
-
618
-	return $conflits;
545
+    include_spip('inc/filtres');
546
+
547
+    $table_objet = table_objet($type);
548
+    $spip_table_objet = table_objet_sql($type);
549
+    $trouver_table = charger_fonction('trouver_table', 'base');
550
+    $desc = $trouver_table($table_objet, $serveur);
551
+
552
+    // Appels incomplets (sans $c)
553
+    if (!is_array($c)) {
554
+        $c = [];
555
+        foreach ($desc['field'] as $champ => $ignore) {
556
+            if (_request($champ)) {
557
+                $c[$champ] = _request($champ);
558
+            }
559
+        }
560
+    }
561
+
562
+    // Securite : certaines variables ne sont jamais acceptees ici
563
+    // car elles ne relevent pas de autoriser(article, modifier) ;
564
+    // il faut passer par instituer_XX()
565
+    // TODO: faut-il passer ces variables interdites
566
+    // dans un fichier de description separe ?
567
+    unset($c['statut']);
568
+    unset($c['id_parent']);
569
+    unset($c['id_rubrique']);
570
+    unset($c['id_secteur']);
571
+
572
+    // Gerer les champs non vides
573
+    if (isset($options['nonvide']) and is_array($options['nonvide'])) {
574
+        foreach ($options['nonvide'] as $champ => $sinon) {
575
+            if ($c[$champ] === '') {
576
+                $c[$champ] = $sinon;
577
+            }
578
+        }
579
+    }
580
+
581
+    // N'accepter que les champs qui existent
582
+    // [TODO] ici aussi on peut valider les contenus en fonction du type
583
+    $champs = [];
584
+    foreach ($desc['field'] as $champ => $ignore) {
585
+        if (isset($c[$champ])) {
586
+            $champs[$champ] = $c[$champ];
587
+        }
588
+    }
589
+
590
+    // Nettoyer les valeurs
591
+    $champs = array_map('corriger_caracteres', $champs);
592
+
593
+    // Envoyer aux plugins
594
+    $champs = pipeline(
595
+        'pre_edition',
596
+        [
597
+            'args' => [
598
+                'table' => $spip_table_objet, // compatibilite
599
+                'table_objet' => $table_objet,
600
+                'spip_table_objet' => $spip_table_objet,
601
+                'type' => $type,
602
+                'id_objet' => $id,
603
+                'champs' => $options['champs'] ?? [], // [doc] c'est quoi ?
604
+                'action' => 'controler',
605
+                'serveur' => $serveur,
606
+            ],
607
+            'data' => $champs
608
+        ]
609
+    );
610
+
611
+    if (!$champs) {
612
+        return false;
613
+    }
614
+
615
+    // Verifier si les mises a jour sont pertinentes, datees, en conflit etc
616
+    $conflits = controler_md5($champs, $_POST, $type, $id, $serveur, $options['prefix'] ?? 'ctr_');
617
+
618
+    return $conflits;
619 619
 }
620 620
 
621 621
 
@@ -645,64 +645,64 @@  discard block
 block discarded – undo
645 645
  *     - post : le contenu posté
646 646
  **/
647 647
 function controler_md5(&$champs, $ctr, $type, $id, $serveur, $prefix = 'ctr_') {
648
-	$spip_table_objet = table_objet_sql($type);
649
-	$id_table_objet = id_table_objet($type);
650
-
651
-	// Controle des MD5 envoyes
652
-	// On elimine les donnees non modifiees par le formulaire (mais
653
-	// potentiellement modifiees entre temps par un autre utilisateur)
654
-	foreach ($champs as $key => $val) {
655
-		if (isset($ctr[$prefix . $key]) and $m = $ctr[$prefix . $key]) {
656
-			if (is_scalar($val) and $m == md5($val)) {
657
-				unset($champs[$key]);
658
-			}
659
-		}
660
-	}
661
-	if (!$champs) {
662
-		return;
663
-	}
664
-
665
-	// On veut savoir si notre modif va avoir un impact
666
-	// par rapport aux donnees contenues dans la base
667
-	// (qui peuvent etre differentes de celles ayant servi a calculer le ctr)
668
-	$s = sql_fetsel(array_keys($champs), $spip_table_objet, "$id_table_objet=$id", $serveur);
669
-	$intact = true;
670
-	foreach ($champs as $ch => $val) {
671
-		$intact &= ($s[$ch] == $val);
672
-	}
673
-	if ($intact) {
674
-		return;
675
-	}
676
-
677
-	// Detection de conflits :
678
-	// On verifie si notre modif ne provient pas d'un formulaire
679
-	// genere a partir de donnees modifiees dans l'intervalle ; ici
680
-	// on compare a ce qui est dans la base, et on bloque en cas
681
-	// de conflit.
682
-	$ctrh = $ctrq = $conflits = [];
683
-	foreach (array_keys($champs) as $key) {
684
-		if (isset($ctr[$prefix . $key]) and $m = $ctr[$prefix . $key]) {
685
-			$ctrh[$key] = $m;
686
-			$ctrq[] = $key;
687
-		}
688
-	}
689
-	if ($ctrq) {
690
-		$ctrq = sql_fetsel($ctrq, $spip_table_objet, "$id_table_objet=$id", $serveur);
691
-		foreach ($ctrh as $key => $m) {
692
-			if (
693
-				$m != md5($ctrq[$key])
694
-				and $champs[$key] !== $ctrq[$key]
695
-			) {
696
-				$conflits[$key] = [
697
-					'base' => $ctrq[$key],
698
-					'post' => $champs[$key]
699
-				];
700
-				unset($champs[$key]); # stocker quand meme les modifs ?
701
-			}
702
-		}
703
-	}
704
-
705
-	return $conflits;
648
+    $spip_table_objet = table_objet_sql($type);
649
+    $id_table_objet = id_table_objet($type);
650
+
651
+    // Controle des MD5 envoyes
652
+    // On elimine les donnees non modifiees par le formulaire (mais
653
+    // potentiellement modifiees entre temps par un autre utilisateur)
654
+    foreach ($champs as $key => $val) {
655
+        if (isset($ctr[$prefix . $key]) and $m = $ctr[$prefix . $key]) {
656
+            if (is_scalar($val) and $m == md5($val)) {
657
+                unset($champs[$key]);
658
+            }
659
+        }
660
+    }
661
+    if (!$champs) {
662
+        return;
663
+    }
664
+
665
+    // On veut savoir si notre modif va avoir un impact
666
+    // par rapport aux donnees contenues dans la base
667
+    // (qui peuvent etre differentes de celles ayant servi a calculer le ctr)
668
+    $s = sql_fetsel(array_keys($champs), $spip_table_objet, "$id_table_objet=$id", $serveur);
669
+    $intact = true;
670
+    foreach ($champs as $ch => $val) {
671
+        $intact &= ($s[$ch] == $val);
672
+    }
673
+    if ($intact) {
674
+        return;
675
+    }
676
+
677
+    // Detection de conflits :
678
+    // On verifie si notre modif ne provient pas d'un formulaire
679
+    // genere a partir de donnees modifiees dans l'intervalle ; ici
680
+    // on compare a ce qui est dans la base, et on bloque en cas
681
+    // de conflit.
682
+    $ctrh = $ctrq = $conflits = [];
683
+    foreach (array_keys($champs) as $key) {
684
+        if (isset($ctr[$prefix . $key]) and $m = $ctr[$prefix . $key]) {
685
+            $ctrh[$key] = $m;
686
+            $ctrq[] = $key;
687
+        }
688
+    }
689
+    if ($ctrq) {
690
+        $ctrq = sql_fetsel($ctrq, $spip_table_objet, "$id_table_objet=$id", $serveur);
691
+        foreach ($ctrh as $key => $m) {
692
+            if (
693
+                $m != md5($ctrq[$key])
694
+                and $champs[$key] !== $ctrq[$key]
695
+            ) {
696
+                $conflits[$key] = [
697
+                    'base' => $ctrq[$key],
698
+                    'post' => $champs[$key]
699
+                ];
700
+                unset($champs[$key]); # stocker quand meme les modifs ?
701
+            }
702
+        }
703
+    }
704
+
705
+    return $conflits;
706 706
 }
707 707
 
708 708
 /**
@@ -714,9 +714,9 @@  discard block
 block discarded – undo
714 714
  * @return string
715 715
  */
716 716
 function display_conflit_champ($x) {
717
-	if (strstr($x, "\n") or strlen($x) > 80) {
718
-		return "<textarea style='width:99%; height:10em;'>" . entites_html($x) . "</textarea>\n";
719
-	} else {
720
-		return "<input type='text' size='40' style='width:99%' value=\"" . entites_html($x) . "\" />\n";
721
-	}
717
+    if (strstr($x, "\n") or strlen($x) > 80) {
718
+        return "<textarea style='width:99%; height:10em;'>" . entites_html($x) . "</textarea>\n";
719
+    } else {
720
+        return "<input type='text' size='40' style='width:99%' value=\"" . entites_html($x) . "\" />\n";
721
+    }
722 722
 }
Please login to merge, or discard this patch.
ecrire/req/mysql.php 1 patch
Indentation   +878 added lines, -878 removed lines patch added patch discarded remove patch
@@ -20,15 +20,15 @@  discard block
 block discarded – undo
20 20
  */
21 21
 
22 22
 if (!defined('_ECRIRE_INC_VERSION')) {
23
-	return;
23
+    return;
24 24
 }
25 25
 
26 26
 if (!defined('_MYSQL_NOPLANES')) {
27
-	define('_MYSQL_NOPLANES', true);
27
+    define('_MYSQL_NOPLANES', true);
28 28
 }
29 29
 
30 30
 if (!defined('_MYSQL_ENGINE')) {
31
-	define('_MYSQL_ENGINE', 'MyISAM');
31
+    define('_MYSQL_ENGINE', 'MyISAM');
32 32
 }
33 33
 
34 34
 /**
@@ -45,112 +45,112 @@  discard block
 block discarded – undo
45 45
  *     - tableau décrivant la connexion sinon
46 46
  */
47 47
 function req_mysql_dist($host, $port, $login, $pass, $db = '', $prefixe = '') {
48
-	if (!extension_loaded(\mysqli::class)) {
49
-		return false;
50
-	}
51
-
52
-	// si port est fourni mais pas host, c'est un socket -> compat avec vieille syntaxe de mysql_connect() et anciens fichiers connect.php
53
-	try {
54
-		if (
55
-			$port and !is_numeric($socket = $port)
56
-			and (!$host or $host === 'localhost')
57
-		) {
58
-			$link = @mysqli_connect($host, $login, $pass, '', null, $socket);
59
-		} elseif ($port) {
60
-			$link = @mysqli_connect($host, $login, $pass, '', $port);
61
-		} else {
62
-			$link = @mysqli_connect($host, $login, $pass);
63
-		}
64
-	} catch (\mysqli_sql_exception $e) {
65
-		spip_log('mysqli_sql_exception: ' . $e->getMessage(), 'mysql.' . _LOG_DEBUG);
66
-		$link = false;
67
-	}
68
-
69
-	if (!$link) {
70
-		spip_log('Echec mysqli_connect. Erreur : ' . mysqli_connect_error(), 'mysql.' . _LOG_HS);
71
-
72
-		return false;
73
-	}
74
-	$last = '';
75
-	if (!$db) {
76
-		$ok = $link;
77
-		$db = 'spip';
78
-	} else {
79
-		$ok = mysqli_select_db($link, $db);
80
-		if (
81
-			defined('_MYSQL_SET_SQL_MODE')
82
-			or defined('_MYSQL_SQL_MODE_TEXT_NOT_NULL') // compatibilite
83
-		) {
84
-			mysqli_query($link, $last = "set sql_mode=''");
85
-		}
86
-	}
87
-
88
-	spip_log(
89
-		"Connexion MySQLi vers $host, base $db, prefixe $prefixe " . ($ok ? 'operationnelle' : 'impossible'),
90
-		_LOG_DEBUG
91
-	);
92
-
93
-	return !$ok ? false : [
94
-		'db' => $db,
95
-		'last' => $last,
96
-		'prefixe' => $prefixe ?: $db,
97
-		'link' => $link,
98
-		'total_requetes' => 0,
99
-	];
48
+    if (!extension_loaded(\mysqli::class)) {
49
+        return false;
50
+    }
51
+
52
+    // si port est fourni mais pas host, c'est un socket -> compat avec vieille syntaxe de mysql_connect() et anciens fichiers connect.php
53
+    try {
54
+        if (
55
+            $port and !is_numeric($socket = $port)
56
+            and (!$host or $host === 'localhost')
57
+        ) {
58
+            $link = @mysqli_connect($host, $login, $pass, '', null, $socket);
59
+        } elseif ($port) {
60
+            $link = @mysqli_connect($host, $login, $pass, '', $port);
61
+        } else {
62
+            $link = @mysqli_connect($host, $login, $pass);
63
+        }
64
+    } catch (\mysqli_sql_exception $e) {
65
+        spip_log('mysqli_sql_exception: ' . $e->getMessage(), 'mysql.' . _LOG_DEBUG);
66
+        $link = false;
67
+    }
68
+
69
+    if (!$link) {
70
+        spip_log('Echec mysqli_connect. Erreur : ' . mysqli_connect_error(), 'mysql.' . _LOG_HS);
71
+
72
+        return false;
73
+    }
74
+    $last = '';
75
+    if (!$db) {
76
+        $ok = $link;
77
+        $db = 'spip';
78
+    } else {
79
+        $ok = mysqli_select_db($link, $db);
80
+        if (
81
+            defined('_MYSQL_SET_SQL_MODE')
82
+            or defined('_MYSQL_SQL_MODE_TEXT_NOT_NULL') // compatibilite
83
+        ) {
84
+            mysqli_query($link, $last = "set sql_mode=''");
85
+        }
86
+    }
87
+
88
+    spip_log(
89
+        "Connexion MySQLi vers $host, base $db, prefixe $prefixe " . ($ok ? 'operationnelle' : 'impossible'),
90
+        _LOG_DEBUG
91
+    );
92
+
93
+    return !$ok ? false : [
94
+        'db' => $db,
95
+        'last' => $last,
96
+        'prefixe' => $prefixe ?: $db,
97
+        'link' => $link,
98
+        'total_requetes' => 0,
99
+    ];
100 100
 }
101 101
 
102 102
 
103 103
 $GLOBALS['spip_mysql_functions_1'] = [
104
-	'alter' => 'spip_mysql_alter',
105
-	'count' => 'spip_mysql_count',
106
-	'countsel' => 'spip_mysql_countsel',
107
-	'create' => 'spip_mysql_create',
108
-	'create_base' => 'spip_mysql_create_base',
109
-	'create_view' => 'spip_mysql_create_view',
110
-	'date_proche' => 'spip_mysql_date_proche',
111
-	'delete' => 'spip_mysql_delete',
112
-	'drop_table' => 'spip_mysql_drop_table',
113
-	'drop_view' => 'spip_mysql_drop_view',
114
-	'errno' => 'spip_mysql_errno',
115
-	'error' => 'spip_mysql_error',
116
-	'explain' => 'spip_mysql_explain',
117
-	'fetch' => 'spip_mysql_fetch',
118
-	'seek' => 'spip_mysql_seek',
119
-	'free' => 'spip_mysql_free',
120
-	'hex' => 'spip_mysql_hex',
121
-	'in' => 'spip_mysql_in',
122
-	'insert' => 'spip_mysql_insert',
123
-	'insertq' => 'spip_mysql_insertq',
124
-	'insertq_multi' => 'spip_mysql_insertq_multi',
125
-	'listdbs' => 'spip_mysql_listdbs',
126
-	'multi' => 'spip_mysql_multi',
127
-	'optimize' => 'spip_mysql_optimize',
128
-	'query' => 'spip_mysql_query',
129
-	'quote' => 'spip_mysql_quote',
130
-	'replace' => 'spip_mysql_replace',
131
-	'replace_multi' => 'spip_mysql_replace_multi',
132
-	'repair' => 'spip_mysql_repair',
133
-	'select' => 'spip_mysql_select',
134
-	'selectdb' => 'spip_mysql_selectdb',
135
-	'set_charset' => 'spip_mysql_set_charset',
136
-	'get_charset' => 'spip_mysql_get_charset',
137
-	'showbase' => 'spip_mysql_showbase',
138
-	'showtable' => 'spip_mysql_showtable',
139
-	'table_exists' => 'spip_mysql_table_exists',
140
-	'update' => 'spip_mysql_update',
141
-	'updateq' => 'spip_mysql_updateq',
142
-
143
-	// association de chaque nom http d'un charset aux couples MySQL
144
-	'charsets' => [
145
-		'cp1250' => ['charset' => 'cp1250', 'collation' => 'cp1250_general_ci'],
146
-		'cp1251' => ['charset' => 'cp1251', 'collation' => 'cp1251_general_ci'],
147
-		'cp1256' => ['charset' => 'cp1256', 'collation' => 'cp1256_general_ci'],
148
-		'iso-8859-1' => ['charset' => 'latin1', 'collation' => 'latin1_swedish_ci'],
104
+    'alter' => 'spip_mysql_alter',
105
+    'count' => 'spip_mysql_count',
106
+    'countsel' => 'spip_mysql_countsel',
107
+    'create' => 'spip_mysql_create',
108
+    'create_base' => 'spip_mysql_create_base',
109
+    'create_view' => 'spip_mysql_create_view',
110
+    'date_proche' => 'spip_mysql_date_proche',
111
+    'delete' => 'spip_mysql_delete',
112
+    'drop_table' => 'spip_mysql_drop_table',
113
+    'drop_view' => 'spip_mysql_drop_view',
114
+    'errno' => 'spip_mysql_errno',
115
+    'error' => 'spip_mysql_error',
116
+    'explain' => 'spip_mysql_explain',
117
+    'fetch' => 'spip_mysql_fetch',
118
+    'seek' => 'spip_mysql_seek',
119
+    'free' => 'spip_mysql_free',
120
+    'hex' => 'spip_mysql_hex',
121
+    'in' => 'spip_mysql_in',
122
+    'insert' => 'spip_mysql_insert',
123
+    'insertq' => 'spip_mysql_insertq',
124
+    'insertq_multi' => 'spip_mysql_insertq_multi',
125
+    'listdbs' => 'spip_mysql_listdbs',
126
+    'multi' => 'spip_mysql_multi',
127
+    'optimize' => 'spip_mysql_optimize',
128
+    'query' => 'spip_mysql_query',
129
+    'quote' => 'spip_mysql_quote',
130
+    'replace' => 'spip_mysql_replace',
131
+    'replace_multi' => 'spip_mysql_replace_multi',
132
+    'repair' => 'spip_mysql_repair',
133
+    'select' => 'spip_mysql_select',
134
+    'selectdb' => 'spip_mysql_selectdb',
135
+    'set_charset' => 'spip_mysql_set_charset',
136
+    'get_charset' => 'spip_mysql_get_charset',
137
+    'showbase' => 'spip_mysql_showbase',
138
+    'showtable' => 'spip_mysql_showtable',
139
+    'table_exists' => 'spip_mysql_table_exists',
140
+    'update' => 'spip_mysql_update',
141
+    'updateq' => 'spip_mysql_updateq',
142
+
143
+    // association de chaque nom http d'un charset aux couples MySQL
144
+    'charsets' => [
145
+        'cp1250' => ['charset' => 'cp1250', 'collation' => 'cp1250_general_ci'],
146
+        'cp1251' => ['charset' => 'cp1251', 'collation' => 'cp1251_general_ci'],
147
+        'cp1256' => ['charset' => 'cp1256', 'collation' => 'cp1256_general_ci'],
148
+        'iso-8859-1' => ['charset' => 'latin1', 'collation' => 'latin1_swedish_ci'],
149 149
 //'iso-8859-6'=>array('charset'=>'latin1','collation'=>'latin1_swedish_ci'),
150
-		'iso-8859-9' => ['charset' => 'latin5', 'collation' => 'latin5_turkish_ci'],
150
+        'iso-8859-9' => ['charset' => 'latin5', 'collation' => 'latin5_turkish_ci'],
151 151
 //'iso-8859-15'=>array('charset'=>'latin1','collation'=>'latin1_swedish_ci'),
152
-		'utf-8' => ['charset' => 'utf8', 'collation' => 'utf8_general_ci']
153
-	]
152
+        'utf-8' => ['charset' => 'utf8', 'collation' => 'utf8_general_ci']
153
+    ]
154 154
 ];
155 155
 
156 156
 
@@ -161,9 +161,9 @@  discard block
 block discarded – undo
161 161
  * @return Object Information de connexion pour mysqli
162 162
  */
163 163
 function _mysql_link($serveur = '') {
164
-	$link = &$GLOBALS['connexions'][$serveur ?: 0]['link'];
164
+    $link = &$GLOBALS['connexions'][$serveur ?: 0]['link'];
165 165
 
166
-	return $link;
166
+    return $link;
167 167
 }
168 168
 
169 169
 
@@ -176,10 +176,10 @@  discard block
 block discarded – undo
176 176
  * @return mysqli_result|bool Jeu de résultats pour fetch()
177 177
  */
178 178
 function spip_mysql_set_charset($charset, $serveur = '', $requeter = true) {
179
-	$connexion = &$GLOBALS['connexions'][$serveur ? strtolower($serveur) : 0];
180
-	spip_log('changement de charset sql : ' . 'SET NAMES ' . _q($charset), _LOG_DEBUG);
179
+    $connexion = &$GLOBALS['connexions'][$serveur ? strtolower($serveur) : 0];
180
+    spip_log('changement de charset sql : ' . 'SET NAMES ' . _q($charset), _LOG_DEBUG);
181 181
 
182
-	return mysqli_query($connexion['link'], $connexion['last'] = 'SET NAMES ' . _q($charset));
182
+    return mysqli_query($connexion['link'], $connexion['last'] = 'SET NAMES ' . _q($charset));
183 183
 }
184 184
 
185 185
 
@@ -192,11 +192,11 @@  discard block
 block discarded – undo
192 192
  * @return array Description du charset (son nom est dans 'charset')
193 193
  */
194 194
 function spip_mysql_get_charset($charset = [], $serveur = '', $requeter = true) {
195
-	$connexion = &$GLOBALS['connexions'][$serveur ? strtolower($serveur) : 0];
196
-	$connexion['last'] = $c = 'SHOW CHARACTER SET'
197
-		. (!$charset ? '' : (' LIKE ' . _q($charset['charset'])));
195
+    $connexion = &$GLOBALS['connexions'][$serveur ? strtolower($serveur) : 0];
196
+    $connexion['last'] = $c = 'SHOW CHARACTER SET'
197
+        . (!$charset ? '' : (' LIKE ' . _q($charset['charset'])));
198 198
 
199
-	return spip_mysql_fetch(mysqli_query($connexion['link'], $c), null, $serveur);
199
+    return spip_mysql_fetch(mysqli_query($connexion['link'], $c), null, $serveur);
200 200
 }
201 201
 
202 202
 /**
@@ -212,80 +212,80 @@  discard block
 block discarded – undo
212 212
  */
213 213
 function spip_mysql_query($query, $serveur = '', $requeter = true) {
214 214
 
215
-	$connexion = &$GLOBALS['connexions'][$serveur ? strtolower($serveur) : 0];
216
-	$prefixe = $connexion['prefixe'];
217
-	$link = $connexion['link'];
218
-	$db = $connexion['db'];
219
-
220
-	$query = _mysql_traite_query($query, $db, $prefixe);
221
-
222
-	// renvoyer la requete inerte si demandee
223
-	if (!$requeter) {
224
-		return $query;
225
-	}
226
-
227
-	if (isset($_GET['var_profile']) or (defined('_DEBUG_TRACE_QUERIES') and _DEBUG_TRACE_QUERIES)) {
228
-		include_spip('public/tracer');
229
-		$t = trace_query_start();
230
-	} else {
231
-		$t = 0;
232
-	}
233
-
234
-	$connexion['last'] = $query;
235
-	$connexion['total_requetes']++;
236
-
237
-	// ajouter un debug utile dans log/mysql-slow.log ?
238
-	$debug = '';
239
-	if (defined('_DEBUG_SLOW_QUERIES') and _DEBUG_SLOW_QUERIES) {
240
-		if (isset($GLOBALS['debug']['aucasou'])) {
241
-			[, $id, , $infos] = $GLOBALS['debug']['aucasou'];
242
-			$debug .= "BOUCLE$id @ " . ($infos[0] ?? '') . ' | ';
243
-		}
244
-		if (isset($_SERVER['REQUEST_URI'])) {
245
-			$debug .= $_SERVER['REQUEST_URI'];
246
-		}
247
-		if (!empty($GLOBALS['ip'])) {
248
-			$debug .= ' + ' . $GLOBALS['ip'];
249
-		}
250
-		$debug = ' /* ' . mysqli_real_escape_string($link, str_replace('*/', '@/', $debug)) . ' */';
251
-	}
252
-	try {
253
-		$r = mysqli_query($link, $query . $debug);
254
-	} catch (\mysqli_sql_exception $e) {
255
-		spip_log('mysqli_sql_exception: ' . $e->getMessage(), 'mysql.' . _LOG_DEBUG);
256
-		$r = false;
257
-		// TODO: utiliser l’exception ensuite plutôt que les appels à spip_mysql_errno()
258
-		// mais il faut pour php < 8.1 forcer les exeptions via mysqli_report().
259
-	}
260
-
261
-	//Eviter de propager le GoneAway sur les autres requetes d'un même processus PHP
262
-	if ($e = spip_mysql_errno($serveur)) {  // Log d'un Gone Away
263
-		if ($e == 2006) { //Si Gone Away on relance une connexion vierge
264
-			//Fermer la connexion defaillante
265
-			mysqli_close($connexion['link']);
266
-			unset($GLOBALS['connexions'][$serveur ? strtolower($serveur) : 0]);
267
-			//Relancer une connexion vierge
268
-			spip_connect($serveur);
269
-			$connexion = &$GLOBALS['connexions'][$serveur ? strtolower($serveur) : 0];
270
-			$link = $connexion['link'];
271
-			//On retente au cas où
272
-			try {
273
-				$r = mysqli_query($link, $query . $debug);
274
-			} catch (\mysqli_sql_exception $e) {
275
-				spip_log('mysqli_sql_exception: ' . $e->getMessage(), 'mysql.' . _LOG_DEBUG);
276
-				$r = false;
277
-				// TODO: utiliser l’exception ensuite plutôt que les appels à spip_mysql_errno()
278
-				// mais il faut pour php < 8.1 forcer les exeptions via mysqli_report().
279
-			}
280
-		}
281
-	}
282
-
283
-	// Log de l'erreur eventuelle
284
-	if ($e = spip_mysql_errno($serveur)) {
285
-		// et du fautif
286
-		$e .= spip_mysql_error($query, $serveur);
287
-	}
288
-	return $t ? trace_query_end($query, $t, $r, $e, $serveur) : $r;
215
+    $connexion = &$GLOBALS['connexions'][$serveur ? strtolower($serveur) : 0];
216
+    $prefixe = $connexion['prefixe'];
217
+    $link = $connexion['link'];
218
+    $db = $connexion['db'];
219
+
220
+    $query = _mysql_traite_query($query, $db, $prefixe);
221
+
222
+    // renvoyer la requete inerte si demandee
223
+    if (!$requeter) {
224
+        return $query;
225
+    }
226
+
227
+    if (isset($_GET['var_profile']) or (defined('_DEBUG_TRACE_QUERIES') and _DEBUG_TRACE_QUERIES)) {
228
+        include_spip('public/tracer');
229
+        $t = trace_query_start();
230
+    } else {
231
+        $t = 0;
232
+    }
233
+
234
+    $connexion['last'] = $query;
235
+    $connexion['total_requetes']++;
236
+
237
+    // ajouter un debug utile dans log/mysql-slow.log ?
238
+    $debug = '';
239
+    if (defined('_DEBUG_SLOW_QUERIES') and _DEBUG_SLOW_QUERIES) {
240
+        if (isset($GLOBALS['debug']['aucasou'])) {
241
+            [, $id, , $infos] = $GLOBALS['debug']['aucasou'];
242
+            $debug .= "BOUCLE$id @ " . ($infos[0] ?? '') . ' | ';
243
+        }
244
+        if (isset($_SERVER['REQUEST_URI'])) {
245
+            $debug .= $_SERVER['REQUEST_URI'];
246
+        }
247
+        if (!empty($GLOBALS['ip'])) {
248
+            $debug .= ' + ' . $GLOBALS['ip'];
249
+        }
250
+        $debug = ' /* ' . mysqli_real_escape_string($link, str_replace('*/', '@/', $debug)) . ' */';
251
+    }
252
+    try {
253
+        $r = mysqli_query($link, $query . $debug);
254
+    } catch (\mysqli_sql_exception $e) {
255
+        spip_log('mysqli_sql_exception: ' . $e->getMessage(), 'mysql.' . _LOG_DEBUG);
256
+        $r = false;
257
+        // TODO: utiliser l’exception ensuite plutôt que les appels à spip_mysql_errno()
258
+        // mais il faut pour php < 8.1 forcer les exeptions via mysqli_report().
259
+    }
260
+
261
+    //Eviter de propager le GoneAway sur les autres requetes d'un même processus PHP
262
+    if ($e = spip_mysql_errno($serveur)) {  // Log d'un Gone Away
263
+        if ($e == 2006) { //Si Gone Away on relance une connexion vierge
264
+            //Fermer la connexion defaillante
265
+            mysqli_close($connexion['link']);
266
+            unset($GLOBALS['connexions'][$serveur ? strtolower($serveur) : 0]);
267
+            //Relancer une connexion vierge
268
+            spip_connect($serveur);
269
+            $connexion = &$GLOBALS['connexions'][$serveur ? strtolower($serveur) : 0];
270
+            $link = $connexion['link'];
271
+            //On retente au cas où
272
+            try {
273
+                $r = mysqli_query($link, $query . $debug);
274
+            } catch (\mysqli_sql_exception $e) {
275
+                spip_log('mysqli_sql_exception: ' . $e->getMessage(), 'mysql.' . _LOG_DEBUG);
276
+                $r = false;
277
+                // TODO: utiliser l’exception ensuite plutôt que les appels à spip_mysql_errno()
278
+                // mais il faut pour php < 8.1 forcer les exeptions via mysqli_report().
279
+            }
280
+        }
281
+    }
282
+
283
+    // Log de l'erreur eventuelle
284
+    if ($e = spip_mysql_errno($serveur)) {
285
+        // et du fautif
286
+        $e .= spip_mysql_error($query, $serveur);
287
+    }
288
+    return $t ? trace_query_end($query, $t, $r, $e, $serveur) : $r;
289 289
 }
290 290
 
291 291
 /**
@@ -300,12 +300,12 @@  discard block
 block discarded – undo
300 300
  *     - array  : Tableau décrivant requête et temps d'exécution si var_profile actif pour tracer.
301 301
  */
302 302
 function spip_mysql_alter($query, $serveur = '', $requeter = true) {
303
-	// ici on supprime les ` entourant le nom de table pour permettre
304
-	// la transposition du prefixe, compte tenu que les plugins ont la mauvaise habitude
305
-	// d'utiliser ceux-ci, copie-colle de phpmyadmin
306
-	$query = preg_replace(',^TABLE\s*`([^`]*)`,i', "TABLE \\1", $query);
303
+    // ici on supprime les ` entourant le nom de table pour permettre
304
+    // la transposition du prefixe, compte tenu que les plugins ont la mauvaise habitude
305
+    // d'utiliser ceux-ci, copie-colle de phpmyadmin
306
+    $query = preg_replace(',^TABLE\s*`([^`]*)`,i', "TABLE \\1", $query);
307 307
 
308
-	return spip_mysql_query('ALTER ' . $query, $serveur, $requeter); # i.e. que PG se debrouille
308
+    return spip_mysql_query('ALTER ' . $query, $serveur, $requeter); # i.e. que PG se debrouille
309 309
 }
310 310
 
311 311
 
@@ -318,9 +318,9 @@  discard block
 block discarded – undo
318 318
  * @return bool            Toujours true
319 319
  */
320 320
 function spip_mysql_optimize($table, $serveur = '', $requeter = true) {
321
-	spip_mysql_query('OPTIMIZE TABLE ' . $table);
321
+    spip_mysql_query('OPTIMIZE TABLE ' . $table);
322 322
 
323
-	return true;
323
+    return true;
324 324
 }
325 325
 
326 326
 
@@ -333,18 +333,18 @@  discard block
 block discarded – undo
333 333
  * @return array           Tableau de l'explication
334 334
  */
335 335
 function spip_mysql_explain($query, $serveur = '', $requeter = true) {
336
-	if (strpos(ltrim($query), 'SELECT') !== 0) {
337
-		return [];
338
-	}
339
-	$connexion = &$GLOBALS['connexions'][$serveur ? strtolower($serveur) : 0];
340
-	$prefixe = $connexion['prefixe'];
341
-	$link = $connexion['link'];
342
-	$db = $connexion['db'];
343
-
344
-	$query = 'EXPLAIN ' . _mysql_traite_query($query, $db, $prefixe);
345
-	$r = mysqli_query($link, $query);
346
-
347
-	return spip_mysql_fetch($r, null, $serveur);
336
+    if (strpos(ltrim($query), 'SELECT') !== 0) {
337
+        return [];
338
+    }
339
+    $connexion = &$GLOBALS['connexions'][$serveur ? strtolower($serveur) : 0];
340
+    $prefixe = $connexion['prefixe'];
341
+    $link = $connexion['link'];
342
+    $db = $connexion['db'];
343
+
344
+    $query = 'EXPLAIN ' . _mysql_traite_query($query, $db, $prefixe);
345
+    $r = mysqli_query($link, $query);
346
+
347
+    return spip_mysql_fetch($r, null, $serveur);
348 348
 }
349 349
 
350 350
 
@@ -373,35 +373,35 @@  discard block
 block discarded – undo
373 373
  *     - array  : Tableau décrivant requête et temps d'exécution si var_profile actif pour tracer.
374 374
  */
375 375
 function spip_mysql_select(
376
-	$select,
377
-	$from,
378
-	$where = '',
379
-	$groupby = '',
380
-	$orderby = '',
381
-	$limit = '',
382
-	$having = '',
383
-	$serveur = '',
384
-	$requeter = true
376
+    $select,
377
+    $from,
378
+    $where = '',
379
+    $groupby = '',
380
+    $orderby = '',
381
+    $limit = '',
382
+    $having = '',
383
+    $serveur = '',
384
+    $requeter = true
385 385
 ) {
386 386
 
387 387
 
388
-	$from = (!is_array($from) ? $from : spip_mysql_select_as($from));
389
-	$query =
390
-		calculer_mysql_expression('SELECT', $select, ', ')
391
-		. calculer_mysql_expression('FROM', $from, ', ')
392
-		. calculer_mysql_expression('WHERE', $where)
393
-		. calculer_mysql_expression('GROUP BY', $groupby, ',')
394
-		. calculer_mysql_expression('HAVING', $having)
395
-		. ($orderby ? ("\nORDER BY " . spip_mysql_order($orderby)) : '')
396
-		. ($limit ? "\nLIMIT $limit" : '');
388
+    $from = (!is_array($from) ? $from : spip_mysql_select_as($from));
389
+    $query =
390
+        calculer_mysql_expression('SELECT', $select, ', ')
391
+        . calculer_mysql_expression('FROM', $from, ', ')
392
+        . calculer_mysql_expression('WHERE', $where)
393
+        . calculer_mysql_expression('GROUP BY', $groupby, ',')
394
+        . calculer_mysql_expression('HAVING', $having)
395
+        . ($orderby ? ("\nORDER BY " . spip_mysql_order($orderby)) : '')
396
+        . ($limit ? "\nLIMIT $limit" : '');
397 397
 
398
-	// renvoyer la requete inerte si demandee
399
-	if ($requeter === false) {
400
-		return $query;
401
-	}
402
-	$r = spip_mysql_query($query, $serveur, $requeter);
398
+    // renvoyer la requete inerte si demandee
399
+    if ($requeter === false) {
400
+        return $query;
401
+    }
402
+    $r = spip_mysql_query($query, $serveur, $requeter);
403 403
 
404
-	return $r ?: $query;
404
+    return $r ?: $query;
405 405
 }
406 406
 
407 407
 
@@ -418,7 +418,7 @@  discard block
 block discarded – undo
418 418
  * @return string Texte du orderby préparé
419 419
  */
420 420
 function spip_mysql_order($orderby) {
421
-	return (is_array($orderby)) ? join(', ', $orderby) : $orderby;
421
+    return (is_array($orderby)) ? join(', ', $orderby) : $orderby;
422 422
 }
423 423
 
424 424
 
@@ -441,26 +441,26 @@  discard block
 block discarded – undo
441 441
  *     Contrainte pour clause WHERE
442 442
  */
443 443
 function calculer_mysql_where($v) {
444
-	if (!is_array($v)) {
445
-		return $v;
446
-	}
447
-
448
-	$op = array_shift($v);
449
-	if (!($n = count($v))) {
450
-		return $op;
451
-	} else {
452
-		$arg = calculer_mysql_where(array_shift($v));
453
-		if ($n == 1) {
454
-			return "$op($arg)";
455
-		} else {
456
-			$arg2 = calculer_mysql_where(array_shift($v));
457
-			if ($n == 2) {
458
-				return "($arg $op $arg2)";
459
-			} else {
460
-				return "($arg $op ($arg2) : $v[0])";
461
-			}
462
-		}
463
-	}
444
+    if (!is_array($v)) {
445
+        return $v;
446
+    }
447
+
448
+    $op = array_shift($v);
449
+    if (!($n = count($v))) {
450
+        return $op;
451
+    } else {
452
+        $arg = calculer_mysql_where(array_shift($v));
453
+        if ($n == 1) {
454
+            return "$op($arg)";
455
+        } else {
456
+            $arg2 = calculer_mysql_where(array_shift($v));
457
+            if ($n == 2) {
458
+                return "($arg $op $arg2)";
459
+            } else {
460
+                return "($arg $op ($arg2) : $v[0])";
461
+            }
462
+        }
463
+    }
464 464
 }
465 465
 
466 466
 /**
@@ -475,21 +475,21 @@  discard block
 block discarded – undo
475 475
  * @return string            Texte de l'expression, une partie donc, du texte la requête.
476 476
  */
477 477
 function calculer_mysql_expression($expression, $v, $join = 'AND') {
478
-	if (empty($v)) {
479
-		return '';
480
-	}
481
-
482
-	$exp = "\n$expression ";
483
-
484
-	if (!is_array($v)) {
485
-		return $exp . $v;
486
-	} else {
487
-		if (strtoupper($join) === 'AND') {
488
-			return $exp . join("\n\t$join ", array_map('calculer_mysql_where', $v));
489
-		} else {
490
-			return $exp . join($join, $v);
491
-		}
492
-	}
478
+    if (empty($v)) {
479
+        return '';
480
+    }
481
+
482
+    $exp = "\n$expression ";
483
+
484
+    if (!is_array($v)) {
485
+        return $exp . $v;
486
+    } else {
487
+        if (strtoupper($join) === 'AND') {
488
+            return $exp . join("\n\t$join ", array_map('calculer_mysql_where', $v));
489
+        } else {
490
+            return $exp . join($join, $v);
491
+        }
492
+    }
493 493
 }
494 494
 
495 495
 
@@ -500,26 +500,26 @@  discard block
 block discarded – undo
500 500
  * @return string Sélection de colonnes pour une clause SELECT
501 501
  */
502 502
 function spip_mysql_select_as($args) {
503
-	$res = '';
504
-	foreach ($args as $k => $v) {
505
-		if (substr($k, -1) == '@') {
506
-			// c'est une jointure qui se refere au from precedent
507
-			// pas de virgule
508
-			$res .= '  ' . $v;
509
-		} else {
510
-			if (!is_numeric($k)) {
511
-				$p = strpos($v, ' ');
512
-				if ($p) {
513
-					$v = substr($v, 0, $p) . " AS `$k`" . substr($v, $p);
514
-				} else {
515
-					$v .= " AS `$k`";
516
-				}
517
-			}
518
-			$res .= ', ' . $v;
519
-		}
520
-	}
521
-
522
-	return substr($res, 2);
503
+    $res = '';
504
+    foreach ($args as $k => $v) {
505
+        if (substr($k, -1) == '@') {
506
+            // c'est une jointure qui se refere au from precedent
507
+            // pas de virgule
508
+            $res .= '  ' . $v;
509
+        } else {
510
+            if (!is_numeric($k)) {
511
+                $p = strpos($v, ' ');
512
+                if ($p) {
513
+                    $v = substr($v, 0, $p) . " AS `$k`" . substr($v, $p);
514
+                } else {
515
+                    $v .= " AS `$k`";
516
+                }
517
+            }
518
+            $res .= ', ' . $v;
519
+        }
520
+    }
521
+
522
+    return substr($res, 2);
523 523
 }
524 524
 
525 525
 
@@ -544,58 +544,58 @@  discard block
 block discarded – undo
544 544
  */
545 545
 function _mysql_traite_query($query, $db = '', $prefixe = '', $echappe_textes = true) {
546 546
 
547
-	if ($GLOBALS['mysql_rappel_nom_base'] and $db) {
548
-		$pref = '`' . $db . '`.';
549
-	} else {
550
-		$pref = '';
551
-	}
552
-
553
-	if ($prefixe) {
554
-		$pref .= $prefixe . '_';
555
-	}
556
-
557
-	if (!preg_match('/\s(SET|VALUES|WHERE|DATABASE)\s/i', $query, $regs)) {
558
-		$suite = '';
559
-	} else {
560
-		$suite = strstr($query, (string) $regs[0]);
561
-		$query = substr($query, 0, -strlen($suite));
562
-		// propager le prefixe en cas de requete imbriquee
563
-		// il faut alors echapper les chaine avant de le faire, pour ne pas risquer de
564
-		// modifier une requete qui est en fait juste du texte dans un champ
565
-		if (stripos($suite, 'SELECT') !== false) {
566
-			if ($echappe_textes) {
567
-				[$suite_echap, $textes] = query_echappe_textes($suite);
568
-			}
569
-			else {
570
-				$suite_echap = $suite;
571
-			}
572
-			if (preg_match('/^(.*?)([(]\s*SELECT\b.*)$/si', $suite_echap, $r)) {
573
-				$suite_echap = $r[1] . _mysql_traite_query($r[2], $db, $prefixe, false);
574
-				if ($echappe_textes) {
575
-					$suite = query_reinjecte_textes($suite_echap, $textes);
576
-				}
577
-				else {
578
-					$suite = $suite_echap;
579
-				}
580
-			}
581
-		}
582
-	}
583
-	$r = preg_replace(_SQL_PREFIXE_TABLE_MYSQL, '\1' . $pref, $query) . $suite;
584
-
585
-	// en option, remplacer les emoji (que mysql ne sait pas gérer) en &#128169;
586
-	// remplacer les emoji (que mysql ne sait pas gérer) en &#128169;
587
-	if (
588
-		defined('_MYSQL_NOPLANES')
589
-		and _MYSQL_NOPLANES
590
-		and !empty($GLOBALS['meta']['charset_sql_connexion'])
591
-		and $GLOBALS['meta']['charset_sql_connexion'] == 'utf8'
592
-	) {
593
-		include_spip('inc/charsets');
594
-		$r = utf8_noplanes($r);
595
-	}
596
-
597
-	#spip_log("_mysql_traite_query: " . substr($r,0, 50) . ".... $db, $prefixe", _LOG_DEBUG);
598
-	return $r;
547
+    if ($GLOBALS['mysql_rappel_nom_base'] and $db) {
548
+        $pref = '`' . $db . '`.';
549
+    } else {
550
+        $pref = '';
551
+    }
552
+
553
+    if ($prefixe) {
554
+        $pref .= $prefixe . '_';
555
+    }
556
+
557
+    if (!preg_match('/\s(SET|VALUES|WHERE|DATABASE)\s/i', $query, $regs)) {
558
+        $suite = '';
559
+    } else {
560
+        $suite = strstr($query, (string) $regs[0]);
561
+        $query = substr($query, 0, -strlen($suite));
562
+        // propager le prefixe en cas de requete imbriquee
563
+        // il faut alors echapper les chaine avant de le faire, pour ne pas risquer de
564
+        // modifier une requete qui est en fait juste du texte dans un champ
565
+        if (stripos($suite, 'SELECT') !== false) {
566
+            if ($echappe_textes) {
567
+                [$suite_echap, $textes] = query_echappe_textes($suite);
568
+            }
569
+            else {
570
+                $suite_echap = $suite;
571
+            }
572
+            if (preg_match('/^(.*?)([(]\s*SELECT\b.*)$/si', $suite_echap, $r)) {
573
+                $suite_echap = $r[1] . _mysql_traite_query($r[2], $db, $prefixe, false);
574
+                if ($echappe_textes) {
575
+                    $suite = query_reinjecte_textes($suite_echap, $textes);
576
+                }
577
+                else {
578
+                    $suite = $suite_echap;
579
+                }
580
+            }
581
+        }
582
+    }
583
+    $r = preg_replace(_SQL_PREFIXE_TABLE_MYSQL, '\1' . $pref, $query) . $suite;
584
+
585
+    // en option, remplacer les emoji (que mysql ne sait pas gérer) en &#128169;
586
+    // remplacer les emoji (que mysql ne sait pas gérer) en &#128169;
587
+    if (
588
+        defined('_MYSQL_NOPLANES')
589
+        and _MYSQL_NOPLANES
590
+        and !empty($GLOBALS['meta']['charset_sql_connexion'])
591
+        and $GLOBALS['meta']['charset_sql_connexion'] == 'utf8'
592
+    ) {
593
+        include_spip('inc/charsets');
594
+        $r = utf8_noplanes($r);
595
+    }
596
+
597
+    #spip_log("_mysql_traite_query: " . substr($r,0, 50) . ".... $db, $prefixe", _LOG_DEBUG);
598
+    return $r;
599 599
 }
600 600
 
601 601
 /**
@@ -613,17 +613,17 @@  discard block
 block discarded – undo
613 613
  *     - False en cas d'erreur.
614 614
  **/
615 615
 function spip_mysql_selectdb($db, $serveur = '', $requeter = true) {
616
-	$link = _mysql_link($serveur);
617
-	try {
618
-		$ok = mysqli_select_db($link, $db);
619
-	} catch (\mysqli_sql_exception $e) {
620
-		$ok = false;
621
-	}
622
-	if (!$ok) {
623
-		spip_log('Echec mysqli_selectdb. Erreur : ' . mysqli_error($link), 'mysql.' . _LOG_CRITIQUE);
624
-	}
625
-
626
-	return $ok;
616
+    $link = _mysql_link($serveur);
617
+    try {
618
+        $ok = mysqli_select_db($link, $db);
619
+    } catch (\mysqli_sql_exception $e) {
620
+        $ok = false;
621
+    }
622
+    if (!$ok) {
623
+        spip_log('Echec mysqli_selectdb. Erreur : ' . mysqli_error($link), 'mysql.' . _LOG_CRITIQUE);
624
+    }
625
+
626
+    return $ok;
627 627
 }
628 628
 
629 629
 
@@ -644,14 +644,14 @@  discard block
 block discarded – undo
644 644
  *     Liste de noms de bases de données
645 645
  **/
646 646
 function spip_mysql_listdbs($serveur = '', $requeter = true) {
647
-	$dbs = [];
648
-	if ($res = spip_mysql_query('SHOW DATABASES', $serveur)) {
649
-		while ($row = mysqli_fetch_assoc($res)) {
650
-			$dbs[] = $row['Database'];
651
-		}
652
-	}
653
-
654
-	return $dbs;
647
+    $dbs = [];
648
+    if ($res = spip_mysql_query('SHOW DATABASES', $serveur)) {
649
+        while ($row = mysqli_fetch_assoc($res)) {
650
+            $dbs[] = $row['Database'];
651
+        }
652
+    }
653
+
654
+    return $dbs;
655 655
 }
656 656
 
657 657
 
@@ -674,73 +674,73 @@  discard block
 block discarded – undo
674 674
  *     - true si la requête réussie, false sinon.
675 675
  */
676 676
 function spip_mysql_create(
677
-	$nom,
678
-	$champs,
679
-	$cles,
680
-	$autoinc = false,
681
-	$temporary = false,
682
-	$serveur = '',
683
-	$requeter = true
677
+    $nom,
678
+    $champs,
679
+    $cles,
680
+    $autoinc = false,
681
+    $temporary = false,
682
+    $serveur = '',
683
+    $requeter = true
684 684
 ) {
685 685
 
686
-	$query = '';
687
-	$keys = '';
688
-	$s = '';
689
-	$p = '';
690
-
691
-	// certains plugins declarent les tables  (permet leur inclusion dans le dump)
692
-	// sans les renseigner (laisse le compilo recuperer la description)
693
-	if (!is_array($champs) || !is_array($cles)) {
694
-		return;
695
-	}
696
-
697
-	$res = spip_mysql_query('SELECT version() as v', $serveur);
698
-	if (($row = mysqli_fetch_array($res)) && (version_compare($row['v'], '5.0', '>='))) {
699
-		spip_mysql_query("SET sql_mode=''", $serveur);
700
-	}
701
-
702
-	foreach ($cles as $k => $v) {
703
-		$keys .= "$s\n\t\t$k ($v)";
704
-		if ($k == 'PRIMARY KEY') {
705
-			$p = $v;
706
-		}
707
-		$s = ',';
708
-	}
709
-	$s = '';
710
-
711
-	$character_set = '';
712
-	if (@$GLOBALS['meta']['charset_sql_base']) {
713
-		$character_set .= ' CHARACTER SET ' . $GLOBALS['meta']['charset_sql_base'];
714
-	}
715
-	if (@$GLOBALS['meta']['charset_collation_sql_base']) {
716
-		$character_set .= ' COLLATE ' . $GLOBALS['meta']['charset_collation_sql_base'];
717
-	}
718
-
719
-	foreach ($champs as $k => $v) {
720
-		$v = _mysql_remplacements_definitions_table($v);
721
-		if (preg_match(',([a-z]*\s*(\(\s*[0-9]*\s*\))?(\s*binary)?),i', $v, $defs)) {
722
-			if (
723
-				preg_match(',(char|text),i', $defs[1])
724
-				and !preg_match(',(binary|CHARACTER|COLLATE),i', $v)
725
-			) {
726
-				$v = $defs[1] . $character_set . ' ' . substr($v, strlen($defs[1]));
727
-			}
728
-		}
729
-
730
-		$query .= "$s\n\t\t$k $v"
731
-			. (($autoinc && ($p == $k) && preg_match(',\b(big|small|medium)?int\b,i', $v))
732
-				? ' auto_increment'
733
-				: ''
734
-			);
735
-		$s = ',';
736
-	}
737
-	$temporary = $temporary ? 'TEMPORARY' : '';
738
-	$q = "CREATE $temporary TABLE IF NOT EXISTS $nom ($query" . ($keys ? ",$keys" : '') . ')'
739
-		. ' ENGINE=' . _MYSQL_ENGINE
740
-		. ($character_set ? " DEFAULT $character_set" : '')
741
-		. "\n";
742
-
743
-	return spip_mysql_query($q, $serveur);
686
+    $query = '';
687
+    $keys = '';
688
+    $s = '';
689
+    $p = '';
690
+
691
+    // certains plugins declarent les tables  (permet leur inclusion dans le dump)
692
+    // sans les renseigner (laisse le compilo recuperer la description)
693
+    if (!is_array($champs) || !is_array($cles)) {
694
+        return;
695
+    }
696
+
697
+    $res = spip_mysql_query('SELECT version() as v', $serveur);
698
+    if (($row = mysqli_fetch_array($res)) && (version_compare($row['v'], '5.0', '>='))) {
699
+        spip_mysql_query("SET sql_mode=''", $serveur);
700
+    }
701
+
702
+    foreach ($cles as $k => $v) {
703
+        $keys .= "$s\n\t\t$k ($v)";
704
+        if ($k == 'PRIMARY KEY') {
705
+            $p = $v;
706
+        }
707
+        $s = ',';
708
+    }
709
+    $s = '';
710
+
711
+    $character_set = '';
712
+    if (@$GLOBALS['meta']['charset_sql_base']) {
713
+        $character_set .= ' CHARACTER SET ' . $GLOBALS['meta']['charset_sql_base'];
714
+    }
715
+    if (@$GLOBALS['meta']['charset_collation_sql_base']) {
716
+        $character_set .= ' COLLATE ' . $GLOBALS['meta']['charset_collation_sql_base'];
717
+    }
718
+
719
+    foreach ($champs as $k => $v) {
720
+        $v = _mysql_remplacements_definitions_table($v);
721
+        if (preg_match(',([a-z]*\s*(\(\s*[0-9]*\s*\))?(\s*binary)?),i', $v, $defs)) {
722
+            if (
723
+                preg_match(',(char|text),i', $defs[1])
724
+                and !preg_match(',(binary|CHARACTER|COLLATE),i', $v)
725
+            ) {
726
+                $v = $defs[1] . $character_set . ' ' . substr($v, strlen($defs[1]));
727
+            }
728
+        }
729
+
730
+        $query .= "$s\n\t\t$k $v"
731
+            . (($autoinc && ($p == $k) && preg_match(',\b(big|small|medium)?int\b,i', $v))
732
+                ? ' auto_increment'
733
+                : ''
734
+            );
735
+        $s = ',';
736
+    }
737
+    $temporary = $temporary ? 'TEMPORARY' : '';
738
+    $q = "CREATE $temporary TABLE IF NOT EXISTS $nom ($query" . ($keys ? ",$keys" : '') . ')'
739
+        . ' ENGINE=' . _MYSQL_ENGINE
740
+        . ($character_set ? " DEFAULT $character_set" : '')
741
+        . "\n";
742
+
743
+    return spip_mysql_query($q, $serveur);
744 744
 }
745 745
 
746 746
 
@@ -753,25 +753,25 @@  discard block
 block discarded – undo
753 753
  *     Définition SQL adaptée pour MySQL d'un champ de table
754 754
  */
755 755
 function _mysql_remplacements_definitions_table($query) {
756
-	// quelques remplacements
757
-	$num = '(\s*\([0-9]*\))?';
758
-	$enum = '(\s*\([^\)]*\))?';
759
-
760
-	$remplace = [
761
-		'/VARCHAR(\s*[^\s\(])/is' => 'VARCHAR(255)\\1',
762
-		'/^TIMESTAMP($| NULL DEFAULT NULL)/is' => 'TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP',
763
-	];
764
-
765
-	if (is_string($query)) {
766
-		$query = preg_replace(array_keys($remplace), $remplace, $query);
767
-	} elseif (is_array($query)) {
768
-		$keys = array_keys($remplace);
769
-		foreach ($query as $k => $q) {
770
-			$query[$k] = preg_replace($keys, $remplace, $q);
771
-		}
772
-	}
773
-
774
-	return $query;
756
+    // quelques remplacements
757
+    $num = '(\s*\([0-9]*\))?';
758
+    $enum = '(\s*\([^\)]*\))?';
759
+
760
+    $remplace = [
761
+        '/VARCHAR(\s*[^\s\(])/is' => 'VARCHAR(255)\\1',
762
+        '/^TIMESTAMP($| NULL DEFAULT NULL)/is' => 'TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP',
763
+    ];
764
+
765
+    if (is_string($query)) {
766
+        $query = preg_replace(array_keys($remplace), $remplace, $query);
767
+    } elseif (is_array($query)) {
768
+        $keys = array_keys($remplace);
769
+        foreach ($query as $k => $q) {
770
+            $query[$k] = preg_replace($keys, $remplace, $q);
771
+        }
772
+    }
773
+
774
+    return $query;
775 775
 }
776 776
 
777 777
 
@@ -784,7 +784,7 @@  discard block
 block discarded – undo
784 784
  * @return bool true si la base est créee.
785 785
  **/
786 786
 function spip_mysql_create_base($nom, $serveur = '', $requeter = true) {
787
-	return spip_mysql_query("CREATE DATABASE `$nom`", $serveur, $requeter);
787
+    return spip_mysql_query("CREATE DATABASE `$nom`", $serveur, $requeter);
788 788
 }
789 789
 
790 790
 
@@ -805,19 +805,19 @@  discard block
 block discarded – undo
805 805
  *     - string texte de la requête si $requeter vaut false
806 806
  */
807 807
 function spip_mysql_create_view($nom, $query_select, $serveur = '', $requeter = true) {
808
-	if (!$query_select) {
809
-		return false;
810
-	}
811
-	// vue deja presente
812
-	if (sql_showtable($nom, false, $serveur)) {
813
-		spip_log("Echec creation d'une vue sql ($nom) car celle-ci existe deja (serveur:$serveur)", _LOG_ERREUR);
808
+    if (!$query_select) {
809
+        return false;
810
+    }
811
+    // vue deja presente
812
+    if (sql_showtable($nom, false, $serveur)) {
813
+        spip_log("Echec creation d'une vue sql ($nom) car celle-ci existe deja (serveur:$serveur)", _LOG_ERREUR);
814 814
 
815
-		return false;
816
-	}
815
+        return false;
816
+    }
817 817
 
818
-	$query = "CREATE VIEW $nom AS " . $query_select;
818
+    $query = "CREATE VIEW $nom AS " . $query_select;
819 819
 
820
-	return spip_mysql_query($query, $serveur, $requeter);
820
+    return spip_mysql_query($query, $serveur, $requeter);
821 821
 }
822 822
 
823 823
 
@@ -833,11 +833,11 @@  discard block
 block discarded – undo
833 833
  *     - true si la requête a réussie, false sinon
834 834
  */
835 835
 function spip_mysql_drop_table($table, $exist = '', $serveur = '', $requeter = true) {
836
-	if ($exist) {
837
-		$exist = ' IF EXISTS';
838
-	}
836
+    if ($exist) {
837
+        $exist = ' IF EXISTS';
838
+    }
839 839
 
840
-	return spip_mysql_query("DROP TABLE$exist $table", $serveur, $requeter);
840
+    return spip_mysql_query("DROP TABLE$exist $table", $serveur, $requeter);
841 841
 }
842 842
 
843 843
 /**
@@ -852,11 +852,11 @@  discard block
 block discarded – undo
852 852
  *     - true si la requête a réussie, false sinon
853 853
  */
854 854
 function spip_mysql_drop_view($view, $exist = '', $serveur = '', $requeter = true) {
855
-	if ($exist) {
856
-		$exist = ' IF EXISTS';
857
-	}
855
+    if ($exist) {
856
+        $exist = ' IF EXISTS';
857
+    }
858 858
 
859
-	return spip_mysql_query("DROP VIEW$exist $view", $serveur, $requeter);
859
+    return spip_mysql_query("DROP VIEW$exist $view", $serveur, $requeter);
860 860
 }
861 861
 
862 862
 /**
@@ -873,7 +873,7 @@  discard block
 block discarded – undo
873 873
  *     Ressource à utiliser avec sql_fetch()
874 874
  **/
875 875
 function spip_mysql_showbase($match, $serveur = '', $requeter = true) {
876
-	return spip_mysql_query('SHOW TABLES LIKE ' . _q($match), $serveur, $requeter);
876
+    return spip_mysql_query('SHOW TABLES LIKE ' . _q($match), $serveur, $requeter);
877 877
 }
878 878
 
879 879
 /**
@@ -889,17 +889,17 @@  discard block
 block discarded – undo
889 889
  *     - true si la requête a réussie, false sinon
890 890
  */
891 891
 function spip_mysql_repair($table, $serveur = '', $requeter = true) {
892
-	$table_status = spip_mysql_fetch(spip_mysql_query('SHOW TABLE STATUS WHERE Name = ' . _q($table), $serveur, true));
893
-	$engine = $table_status['Engine'];
894
-	if ($engine == 'InnoDB') {
895
-		if (spip_mysql_alter("TABLE $table ENGINE = InnoDB", $serveur, $requeter)) {
896
-			return [' OK '];
897
-		}
898
-	} elseif ($engine == 'MyISAM') {
899
-		return spip_mysql_query("REPAIR TABLE `$table`", $serveur, $requeter);
900
-	} else {
901
-		spip_log("spip_mysql_repair impossible pour la table $table engine $engine", 'mysql.' . _LOG_DEBUG);
902
-	}
892
+    $table_status = spip_mysql_fetch(spip_mysql_query('SHOW TABLE STATUS WHERE Name = ' . _q($table), $serveur, true));
893
+    $engine = $table_status['Engine'];
894
+    if ($engine == 'InnoDB') {
895
+        if (spip_mysql_alter("TABLE $table ENGINE = InnoDB", $serveur, $requeter)) {
896
+            return [' OK '];
897
+        }
898
+    } elseif ($engine == 'MyISAM') {
899
+        return spip_mysql_query("REPAIR TABLE `$table`", $serveur, $requeter);
900
+    } else {
901
+        spip_log("spip_mysql_repair impossible pour la table $table engine $engine", 'mysql.' . _LOG_DEBUG);
902
+    }
903 903
 }
904 904
 
905 905
 /**
@@ -917,12 +917,12 @@  discard block
 block discarded – undo
917 917
  *     - string : requete sql, si $requeter = true
918 918
  **/
919 919
 function spip_mysql_table_exists(string $table, $serveur = '', $requeter = true) {
920
-	$r = spip_mysql_query('SHOW TABLES LIKE ' . _q($table), $serveur, $requeter);
921
-	if (!$requeter) {
922
-		return $r;
923
-	}
924
-	$res = spip_mysql_fetch($r);
925
-	return (bool) $res;
920
+    $r = spip_mysql_query('SHOW TABLES LIKE ' . _q($table), $serveur, $requeter);
921
+    if (!$requeter) {
922
+        return $r;
923
+    }
924
+    $res = spip_mysql_fetch($r);
925
+    return (bool) $res;
926 926
 }
927 927
 
928 928
 define('_MYSQL_RE_SHOW_TABLE', '/^[^(),]*\(((?:[^()]*\((?:[^()]*\([^()]*\))?[^()]*\)[^()]*)*[^()]*)\)[^()]*$/');
@@ -945,86 +945,86 @@  discard block
 block discarded – undo
945 945
  *     - array description de la table sinon
946 946
  */
947 947
 function spip_mysql_showtable($nom_table, $serveur = '', $requeter = true) {
948
-	$s = spip_mysql_query("SHOW CREATE TABLE `$nom_table`", $serveur, $requeter);
949
-	if (!$s) {
950
-		return '';
951
-	}
952
-	if (!$requeter) {
953
-		return $s;
954
-	}
955
-
956
-	[, $a] = mysqli_fetch_array($s, MYSQLI_NUM);
957
-	if (preg_match(_MYSQL_RE_SHOW_TABLE, $a, $r)) {
958
-		$desc = $r[1];
959
-		// extraction d'une KEY éventuelle en prenant garde de ne pas
960
-		// relever un champ dont le nom contient KEY (ex. ID_WHISKEY)
961
-		if (preg_match('/^(.*?),([^,]*\sKEY[ (].*)$/s', $desc, $r)) {
962
-			$namedkeys = $r[2];
963
-			$desc = $r[1];
964
-		} else {
965
-			$namedkeys = '';
966
-		}
967
-
968
-		$fields = [];
969
-		foreach (preg_split('/,\s*`/', $desc) as $v) {
970
-			preg_match('/^\s*`?([^`]*)`\s*(.*)/', $v, $r);
971
-			$fields[strtolower($r[1])] = $r[2];
972
-		}
973
-		$keys = [];
974
-
975
-		foreach (preg_split('/\)\s*(,|$)/', $namedkeys) as $v) {
976
-			if (preg_match('/^\s*([^(]*)\(([^(]*(\(\d+\))?)$/', $v, $r)) {
977
-				$k = str_replace('`', '', trim($r[1]));
978
-				$t = strtolower(str_replace('`', '', $r[2]));
979
-				if ($k && !isset($keys[$k])) {
980
-					$keys[$k] = $t;
981
-				} else {
982
-					$keys[] = $t;
983
-				}
984
-			}
985
-		}
986
-		spip_mysql_free($s);
987
-
988
-		return ['field' => $fields, 'key' => $keys];
989
-	}
990
-
991
-	$res = spip_mysql_query("SHOW COLUMNS FROM `$nom_table`", $serveur);
992
-	if ($res) {
993
-		$nfields = [];
994
-		$nkeys = [];
995
-		while ($val = spip_mysql_fetch($res)) {
996
-			$nfields[$val['Field']] = $val['Type'];
997
-			if ($val['Null'] == 'NO') {
998
-				$nfields[$val['Field']] .= ' NOT NULL';
999
-			}
1000
-			if ($val['Default'] === '0' || $val['Default']) {
1001
-				if (preg_match('/[A-Z_]/', $val['Default'])) {
1002
-					$nfields[$val['Field']] .= ' DEFAULT ' . $val['Default'];
1003
-				} else {
1004
-					$nfields[$val['Field']] .= " DEFAULT '" . $val['Default'] . "'";
1005
-				}
1006
-			}
1007
-			if ($val['Extra']) {
1008
-				$nfields[$val['Field']] .= ' ' . $val['Extra'];
1009
-			}
1010
-			if ($val['Key'] == 'PRI') {
1011
-				$nkeys['PRIMARY KEY'] = $val['Field'];
1012
-			} else {
1013
-				if ($val['Key'] == 'MUL') {
1014
-					$nkeys['KEY ' . $val['Field']] = $val['Field'];
1015
-				} else {
1016
-					if ($val['Key'] == 'UNI') {
1017
-						$nkeys['UNIQUE KEY ' . $val['Field']] = $val['Field'];
1018
-					}
1019
-				}
1020
-			}
1021
-		}
1022
-		spip_mysql_free($res);
1023
-
1024
-		return ['field' => $nfields, 'key' => $nkeys];
1025
-	}
1026
-
1027
-	return '';
948
+    $s = spip_mysql_query("SHOW CREATE TABLE `$nom_table`", $serveur, $requeter);
949
+    if (!$s) {
950
+        return '';
951
+    }
952
+    if (!$requeter) {
953
+        return $s;
954
+    }
955
+
956
+    [, $a] = mysqli_fetch_array($s, MYSQLI_NUM);
957
+    if (preg_match(_MYSQL_RE_SHOW_TABLE, $a, $r)) {
958
+        $desc = $r[1];
959
+        // extraction d'une KEY éventuelle en prenant garde de ne pas
960
+        // relever un champ dont le nom contient KEY (ex. ID_WHISKEY)
961
+        if (preg_match('/^(.*?),([^,]*\sKEY[ (].*)$/s', $desc, $r)) {
962
+            $namedkeys = $r[2];
963
+            $desc = $r[1];
964
+        } else {
965
+            $namedkeys = '';
966
+        }
967
+
968
+        $fields = [];
969
+        foreach (preg_split('/,\s*`/', $desc) as $v) {
970
+            preg_match('/^\s*`?([^`]*)`\s*(.*)/', $v, $r);
971
+            $fields[strtolower($r[1])] = $r[2];
972
+        }
973
+        $keys = [];
974
+
975
+        foreach (preg_split('/\)\s*(,|$)/', $namedkeys) as $v) {
976
+            if (preg_match('/^\s*([^(]*)\(([^(]*(\(\d+\))?)$/', $v, $r)) {
977
+                $k = str_replace('`', '', trim($r[1]));
978
+                $t = strtolower(str_replace('`', '', $r[2]));
979
+                if ($k && !isset($keys[$k])) {
980
+                    $keys[$k] = $t;
981
+                } else {
982
+                    $keys[] = $t;
983
+                }
984
+            }
985
+        }
986
+        spip_mysql_free($s);
987
+
988
+        return ['field' => $fields, 'key' => $keys];
989
+    }
990
+
991
+    $res = spip_mysql_query("SHOW COLUMNS FROM `$nom_table`", $serveur);
992
+    if ($res) {
993
+        $nfields = [];
994
+        $nkeys = [];
995
+        while ($val = spip_mysql_fetch($res)) {
996
+            $nfields[$val['Field']] = $val['Type'];
997
+            if ($val['Null'] == 'NO') {
998
+                $nfields[$val['Field']] .= ' NOT NULL';
999
+            }
1000
+            if ($val['Default'] === '0' || $val['Default']) {
1001
+                if (preg_match('/[A-Z_]/', $val['Default'])) {
1002
+                    $nfields[$val['Field']] .= ' DEFAULT ' . $val['Default'];
1003
+                } else {
1004
+                    $nfields[$val['Field']] .= " DEFAULT '" . $val['Default'] . "'";
1005
+                }
1006
+            }
1007
+            if ($val['Extra']) {
1008
+                $nfields[$val['Field']] .= ' ' . $val['Extra'];
1009
+            }
1010
+            if ($val['Key'] == 'PRI') {
1011
+                $nkeys['PRIMARY KEY'] = $val['Field'];
1012
+            } else {
1013
+                if ($val['Key'] == 'MUL') {
1014
+                    $nkeys['KEY ' . $val['Field']] = $val['Field'];
1015
+                } else {
1016
+                    if ($val['Key'] == 'UNI') {
1017
+                        $nkeys['UNIQUE KEY ' . $val['Field']] = $val['Field'];
1018
+                    }
1019
+                }
1020
+            }
1021
+        }
1022
+        spip_mysql_free($res);
1023
+
1024
+        return ['field' => $nfields, 'key' => $nkeys];
1025
+    }
1026
+
1027
+    return '';
1028 1028
 }
1029 1029
 
1030 1030
 
@@ -1043,13 +1043,13 @@  discard block
 block discarded – undo
1043 1043
  *     - false Erreur
1044 1044
  */
1045 1045
 function spip_mysql_fetch($r, $t = '', $serveur = '', $requeter = true) {
1046
-	if (!$t) {
1047
-		$t = \MYSQLI_ASSOC;
1048
-	}
1049
-	if ($r) {
1050
-		return mysqli_fetch_array($r, $t);
1051
-	}
1052
-	return false;
1046
+    if (!$t) {
1047
+        $t = \MYSQLI_ASSOC;
1048
+    }
1049
+    if ($r) {
1050
+        return mysqli_fetch_array($r, $t);
1051
+    }
1052
+    return false;
1053 1053
 }
1054 1054
 
1055 1055
 /**
@@ -1062,9 +1062,9 @@  discard block
 block discarded – undo
1062 1062
  * @return bool True si déplacement réussi, false sinon.
1063 1063
  **/
1064 1064
 function spip_mysql_seek($r, $row_number, $serveur = '', $requeter = true) {
1065
-	if ($r and mysqli_num_rows($r)) {
1066
-		return mysqli_data_seek($r, $row_number);
1067
-	}
1065
+    if ($r and mysqli_num_rows($r)) {
1066
+        return mysqli_data_seek($r, $row_number);
1067
+    }
1068 1068
 }
1069 1069
 
1070 1070
 
@@ -1082,26 +1082,26 @@  discard block
 block discarded – undo
1082 1082
  *     - int Nombre de lignes (0 si la requête n'a pas réussie)
1083 1083
  **/
1084 1084
 function spip_mysql_countsel(
1085
-	$from = [],
1086
-	$where = [],
1087
-	$groupby = '',
1088
-	$having = [],
1089
-	$serveur = '',
1090
-	$requeter = true
1085
+    $from = [],
1086
+    $where = [],
1087
+    $groupby = '',
1088
+    $having = [],
1089
+    $serveur = '',
1090
+    $requeter = true
1091 1091
 ) {
1092
-	$c = !$groupby ? '*' : ('DISTINCT ' . (is_string($groupby) ? $groupby : join(',', $groupby)));
1093
-
1094
-	$r = spip_mysql_select("COUNT($c)", $from, $where, '', '', '', $having, $serveur, $requeter);
1095
-	if (!$requeter) {
1096
-		return $r;
1097
-	}
1098
-	if (!$r instanceof mysqli_result) {
1099
-		return 0;
1100
-	}
1101
-	[$c] = mysqli_fetch_array($r, MYSQLI_NUM);
1102
-	mysqli_free_result($r);
1103
-
1104
-	return $c;
1092
+    $c = !$groupby ? '*' : ('DISTINCT ' . (is_string($groupby) ? $groupby : join(',', $groupby)));
1093
+
1094
+    $r = spip_mysql_select("COUNT($c)", $from, $where, '', '', '', $having, $serveur, $requeter);
1095
+    if (!$requeter) {
1096
+        return $r;
1097
+    }
1098
+    if (!$r instanceof mysqli_result) {
1099
+        return 0;
1100
+    }
1101
+    [$c] = mysqli_fetch_array($r, MYSQLI_NUM);
1102
+    mysqli_free_result($r);
1103
+
1104
+    return $c;
1105 1105
 }
1106 1106
 
1107 1107
 
@@ -1124,16 +1124,16 @@  discard block
 block discarded – undo
1124 1124
  *     Erreur eventuelle
1125 1125
  **/
1126 1126
 function spip_mysql_error($query = '', $serveur = '', $requeter = true) {
1127
-	$link = $GLOBALS['connexions'][$serveur ? strtolower($serveur) : 0]['link'];
1128
-	$s = mysqli_error($link);
1129
-	if ($s) {
1130
-		$trace = debug_backtrace();
1131
-		if ($trace[0]['function'] != 'spip_mysql_error') {
1132
-			spip_log("$s - $query - " . sql_error_backtrace(), 'mysql.' . _LOG_ERREUR);
1133
-		}
1134
-	}
1135
-
1136
-	return $s;
1127
+    $link = $GLOBALS['connexions'][$serveur ? strtolower($serveur) : 0]['link'];
1128
+    $s = mysqli_error($link);
1129
+    if ($s) {
1130
+        $trace = debug_backtrace();
1131
+        if ($trace[0]['function'] != 'spip_mysql_error') {
1132
+            spip_log("$s - $query - " . sql_error_backtrace(), 'mysql.' . _LOG_ERREUR);
1133
+        }
1134
+    }
1135
+
1136
+    return $s;
1137 1137
 }
1138 1138
 
1139 1139
 
@@ -1148,18 +1148,18 @@  discard block
 block discarded – undo
1148 1148
  *     0, pas d'erreur. Autre, numéro de l'erreur.
1149 1149
  **/
1150 1150
 function spip_mysql_errno($serveur = '', $requeter = true) {
1151
-	$link = $GLOBALS['connexions'][$serveur ?: 0]['link'];
1152
-	$s = mysqli_errno($link);
1153
-	// 2006 MySQL server has gone away
1154
-	// 2013 Lost connection to MySQL server during query
1155
-	if (in_array($s, [2006, 2013])) {
1156
-		define('spip_interdire_cache', true);
1157
-	}
1158
-	if ($s) {
1159
-		spip_log("Erreur mysql $s", _LOG_ERREUR);
1160
-	}
1161
-
1162
-	return $s;
1151
+    $link = $GLOBALS['connexions'][$serveur ?: 0]['link'];
1152
+    $s = mysqli_errno($link);
1153
+    // 2006 MySQL server has gone away
1154
+    // 2013 Lost connection to MySQL server during query
1155
+    if (in_array($s, [2006, 2013])) {
1156
+        define('spip_interdire_cache', true);
1157
+    }
1158
+    if ($s) {
1159
+        spip_log("Erreur mysql $s", _LOG_ERREUR);
1160
+    }
1161
+
1162
+    return $s;
1163 1163
 }
1164 1164
 
1165 1165
 
@@ -1173,9 +1173,9 @@  discard block
 block discarded – undo
1173 1173
  * @return int               Nombre de lignes
1174 1174
  */
1175 1175
 function spip_mysql_count($r, $serveur = '', $requeter = true) {
1176
-	if ($r) {
1177
-		return mysqli_num_rows($r);
1178
-	}
1176
+    if ($r) {
1177
+        return mysqli_num_rows($r);
1178
+    }
1179 1179
 }
1180 1180
 
1181 1181
 
@@ -1191,7 +1191,7 @@  discard block
 block discarded – undo
1191 1191
  * @return bool              True si réussi
1192 1192
  */
1193 1193
 function spip_mysql_free($r, $serveur = '', $requeter = true) {
1194
-	return (($r instanceof mysqli_result) ? mysqli_free_result($r) : false);
1194
+    return (($r instanceof mysqli_result) ? mysqli_free_result($r) : false);
1195 1195
 }
1196 1196
 
1197 1197
 
@@ -1219,59 +1219,59 @@  discard block
 block discarded – undo
1219 1219
  **/
1220 1220
 function spip_mysql_insert($table, $champs, $valeurs, $desc = [], $serveur = '', $requeter = true) {
1221 1221
 
1222
-	$e = null;
1223
-	$connexion = &$GLOBALS['connexions'][$serveur ? strtolower($serveur) : 0];
1224
-	$link = $connexion['link'];
1225
-	$table = prefixer_table_spip($table, $connexion['prefixe']);
1226
-
1227
-	// remplacer les emoji (que mysql ne sait pas gérer) en &#128169;
1228
-	if (
1229
-		defined('_MYSQL_NOPLANES')
1230
-		and _MYSQL_NOPLANES
1231
-		and !empty($GLOBALS['meta']['charset_sql_connexion'])
1232
-		and $GLOBALS['meta']['charset_sql_connexion'] == 'utf8'
1233
-	) {
1234
-		include_spip('inc/charsets');
1235
-		$valeurs = utf8_noplanes($valeurs);
1236
-	}
1237
-
1238
-	$query = "INSERT INTO $table $champs VALUES $valeurs";
1239
-	if (!$requeter) {
1240
-		return $query;
1241
-	}
1242
-
1243
-	if (isset($_GET['var_profile'])) {
1244
-		include_spip('public/tracer');
1245
-		$t = trace_query_start();
1246
-		$e = '';
1247
-	} else {
1248
-		$t = 0;
1249
-	}
1250
-
1251
-	$connexion['last'] = $query;
1252
-	#spip_log($query, 'mysql.'._LOG_DEBUG);
1253
-	$r = false;
1254
-	$insert = false;
1255
-	try {
1256
-		$insert = mysqli_query($link, $query);
1257
-	} catch (\mysqli_sql_exception $e) {
1258
-		spip_log('mysqli_sql_exception: ' . $e->getMessage(), 'mysql.' . _LOG_DEBUG);
1259
-		// TODO: utiliser l’exception ensuite plutôt que les appels à spip_mysql_errno()
1260
-		// mais il faut pour php < 8.1 forcer les exeptions via mysqli_report().
1261
-	}
1262
-	if ($insert) {
1263
-		$r = mysqli_insert_id($link);
1264
-	} else {
1265
-		// Log de l'erreur eventuelle
1266
-		if ($e = spip_mysql_errno($serveur)) {
1267
-			// et du fautif
1268
-			$e .= spip_mysql_error($query, $serveur);
1269
-		}
1270
-	}
1271
-
1272
-	return $t ? trace_query_end($query, $t, $r, $e, $serveur) : $r;
1273
-
1274
-	// return $r ? $r : (($r===0) ? -1 : 0); pb avec le multi-base.
1222
+    $e = null;
1223
+    $connexion = &$GLOBALS['connexions'][$serveur ? strtolower($serveur) : 0];
1224
+    $link = $connexion['link'];
1225
+    $table = prefixer_table_spip($table, $connexion['prefixe']);
1226
+
1227
+    // remplacer les emoji (que mysql ne sait pas gérer) en &#128169;
1228
+    if (
1229
+        defined('_MYSQL_NOPLANES')
1230
+        and _MYSQL_NOPLANES
1231
+        and !empty($GLOBALS['meta']['charset_sql_connexion'])
1232
+        and $GLOBALS['meta']['charset_sql_connexion'] == 'utf8'
1233
+    ) {
1234
+        include_spip('inc/charsets');
1235
+        $valeurs = utf8_noplanes($valeurs);
1236
+    }
1237
+
1238
+    $query = "INSERT INTO $table $champs VALUES $valeurs";
1239
+    if (!$requeter) {
1240
+        return $query;
1241
+    }
1242
+
1243
+    if (isset($_GET['var_profile'])) {
1244
+        include_spip('public/tracer');
1245
+        $t = trace_query_start();
1246
+        $e = '';
1247
+    } else {
1248
+        $t = 0;
1249
+    }
1250
+
1251
+    $connexion['last'] = $query;
1252
+    #spip_log($query, 'mysql.'._LOG_DEBUG);
1253
+    $r = false;
1254
+    $insert = false;
1255
+    try {
1256
+        $insert = mysqli_query($link, $query);
1257
+    } catch (\mysqli_sql_exception $e) {
1258
+        spip_log('mysqli_sql_exception: ' . $e->getMessage(), 'mysql.' . _LOG_DEBUG);
1259
+        // TODO: utiliser l’exception ensuite plutôt que les appels à spip_mysql_errno()
1260
+        // mais il faut pour php < 8.1 forcer les exeptions via mysqli_report().
1261
+    }
1262
+    if ($insert) {
1263
+        $r = mysqli_insert_id($link);
1264
+    } else {
1265
+        // Log de l'erreur eventuelle
1266
+        if ($e = spip_mysql_errno($serveur)) {
1267
+            // et du fautif
1268
+            $e .= spip_mysql_error($query, $serveur);
1269
+        }
1270
+    }
1271
+
1272
+    return $t ? trace_query_end($query, $t, $r, $e, $serveur) : $r;
1273
+
1274
+    // return $r ? $r : (($r===0) ? -1 : 0); pb avec le multi-base.
1275 1275
 }
1276 1276
 
1277 1277
 /**
@@ -1296,26 +1296,26 @@  discard block
 block discarded – undo
1296 1296
  **/
1297 1297
 function spip_mysql_insertq($table, $couples = [], $desc = [], $serveur = '', $requeter = true) {
1298 1298
 
1299
-	if (!$desc) {
1300
-		$desc = description_table($table, $serveur);
1301
-	}
1302
-	if (!$desc) {
1303
-		$couples = [];
1304
-	}
1305
-	$fields = $desc['field'] ?? [];
1306
-
1307
-	foreach ($couples as $champ => $val) {
1308
-		$couples[$champ] = spip_mysql_cite($val, $fields[$champ]);
1309
-	}
1310
-
1311
-	return spip_mysql_insert(
1312
-		$table,
1313
-		'(' . join(',', array_keys($couples)) . ')',
1314
-		'(' . join(',', $couples) . ')',
1315
-		$desc,
1316
-		$serveur,
1317
-		$requeter
1318
-	);
1299
+    if (!$desc) {
1300
+        $desc = description_table($table, $serveur);
1301
+    }
1302
+    if (!$desc) {
1303
+        $couples = [];
1304
+    }
1305
+    $fields = $desc['field'] ?? [];
1306
+
1307
+    foreach ($couples as $champ => $val) {
1308
+        $couples[$champ] = spip_mysql_cite($val, $fields[$champ]);
1309
+    }
1310
+
1311
+    return spip_mysql_insert(
1312
+        $table,
1313
+        '(' . join(',', array_keys($couples)) . ')',
1314
+        '(' . join(',', $couples) . ')',
1315
+        $desc,
1316
+        $serveur,
1317
+        $requeter
1318
+    );
1319 1319
 }
1320 1320
 
1321 1321
 
@@ -1340,34 +1340,34 @@  discard block
 block discarded – undo
1340 1340
  **/
1341 1341
 function spip_mysql_insertq_multi($table, $tab_couples = [], $desc = [], $serveur = '', $requeter = true) {
1342 1342
 
1343
-	if (!$desc) {
1344
-		$desc = description_table($table, $serveur);
1345
-	}
1346
-	if (!$desc) {
1347
-		$tab_couples = [];
1348
-	}
1349
-	$fields = $desc['field'] ?? [];
1350
-
1351
-	$cles = '(' . join(',', array_keys(reset($tab_couples))) . ')';
1352
-	$valeurs = [];
1353
-	$r = false;
1354
-
1355
-	// Quoter et Inserer par groupes de 100 max pour eviter un debordement de pile
1356
-	foreach ($tab_couples as $couples) {
1357
-		foreach ($couples as $champ => $val) {
1358
-			$couples[$champ] = spip_mysql_cite($val, $fields[$champ]);
1359
-		}
1360
-		$valeurs[] = '(' . join(',', $couples) . ')';
1361
-		if (count($valeurs) >= 100) {
1362
-			$r = spip_mysql_insert($table, $cles, join(', ', $valeurs), $desc, $serveur, $requeter);
1363
-			$valeurs = [];
1364
-		}
1365
-	}
1366
-	if (count($valeurs)) {
1367
-		$r = spip_mysql_insert($table, $cles, join(', ', $valeurs), $desc, $serveur, $requeter);
1368
-	}
1369
-
1370
-	return $r; // dans le cas d'une table auto_increment, le dernier insert_id
1343
+    if (!$desc) {
1344
+        $desc = description_table($table, $serveur);
1345
+    }
1346
+    if (!$desc) {
1347
+        $tab_couples = [];
1348
+    }
1349
+    $fields = $desc['field'] ?? [];
1350
+
1351
+    $cles = '(' . join(',', array_keys(reset($tab_couples))) . ')';
1352
+    $valeurs = [];
1353
+    $r = false;
1354
+
1355
+    // Quoter et Inserer par groupes de 100 max pour eviter un debordement de pile
1356
+    foreach ($tab_couples as $couples) {
1357
+        foreach ($couples as $champ => $val) {
1358
+            $couples[$champ] = spip_mysql_cite($val, $fields[$champ]);
1359
+        }
1360
+        $valeurs[] = '(' . join(',', $couples) . ')';
1361
+        if (count($valeurs) >= 100) {
1362
+            $r = spip_mysql_insert($table, $cles, join(', ', $valeurs), $desc, $serveur, $requeter);
1363
+            $valeurs = [];
1364
+        }
1365
+    }
1366
+    if (count($valeurs)) {
1367
+        $r = spip_mysql_insert($table, $cles, join(', ', $valeurs), $desc, $serveur, $requeter);
1368
+    }
1369
+
1370
+    return $r; // dans le cas d'une table auto_increment, le dernier insert_id
1371 1371
 }
1372 1372
 
1373 1373
 /**
@@ -1392,19 +1392,19 @@  discard block
 block discarded – undo
1392 1392
  *     - array Tableau décrivant la requête et son temps d'exécution si var_profile est actif
1393 1393
  */
1394 1394
 function spip_mysql_update($table, $champs, $where = '', $desc = [], $serveur = '', $requeter = true) {
1395
-	$set = [];
1396
-	foreach ($champs as $champ => $val) {
1397
-		$set[] = $champ . "=$val";
1398
-	}
1399
-	if (!empty($set)) {
1400
-		return spip_mysql_query(
1401
-			calculer_mysql_expression('UPDATE', $table, ',')
1402
-			. calculer_mysql_expression('SET', $set, ',')
1403
-			. calculer_mysql_expression('WHERE', $where),
1404
-			$serveur,
1405
-			$requeter
1406
-		);
1407
-	}
1395
+    $set = [];
1396
+    foreach ($champs as $champ => $val) {
1397
+        $set[] = $champ . "=$val";
1398
+    }
1399
+    if (!empty($set)) {
1400
+        return spip_mysql_query(
1401
+            calculer_mysql_expression('UPDATE', $table, ',')
1402
+            . calculer_mysql_expression('SET', $set, ',')
1403
+            . calculer_mysql_expression('WHERE', $where),
1404
+            $serveur,
1405
+            $requeter
1406
+        );
1407
+    }
1408 1408
 }
1409 1409
 
1410 1410
 /**
@@ -1437,29 +1437,29 @@  discard block
 block discarded – undo
1437 1437
  */
1438 1438
 function spip_mysql_updateq($table, $champs, $where = '', $desc = [], $serveur = '', $requeter = true) {
1439 1439
 
1440
-	if (!$champs) {
1441
-		return;
1442
-	}
1443
-	if (!$desc) {
1444
-		$desc = description_table($table, $serveur);
1445
-	}
1446
-	if (!$desc) {
1447
-		$champs = [];
1448
-	} else {
1449
-		$fields = $desc['field'];
1450
-	}
1451
-	$set = [];
1452
-	foreach ($champs as $champ => $val) {
1453
-		$set[] = $champ . '=' . spip_mysql_cite($val, @$fields[$champ]);
1454
-	}
1455
-
1456
-	return spip_mysql_query(
1457
-		calculer_mysql_expression('UPDATE', $table, ',')
1458
-		. calculer_mysql_expression('SET', $set, ',')
1459
-		. calculer_mysql_expression('WHERE', $where),
1460
-		$serveur,
1461
-		$requeter
1462
-	);
1440
+    if (!$champs) {
1441
+        return;
1442
+    }
1443
+    if (!$desc) {
1444
+        $desc = description_table($table, $serveur);
1445
+    }
1446
+    if (!$desc) {
1447
+        $champs = [];
1448
+    } else {
1449
+        $fields = $desc['field'];
1450
+    }
1451
+    $set = [];
1452
+    foreach ($champs as $champ => $val) {
1453
+        $set[] = $champ . '=' . spip_mysql_cite($val, @$fields[$champ]);
1454
+    }
1455
+
1456
+    return spip_mysql_query(
1457
+        calculer_mysql_expression('UPDATE', $table, ',')
1458
+        . calculer_mysql_expression('SET', $set, ',')
1459
+        . calculer_mysql_expression('WHERE', $where),
1460
+        $serveur,
1461
+        $requeter
1462
+    );
1463 1463
 }
1464 1464
 
1465 1465
 /**
@@ -1475,22 +1475,22 @@  discard block
 block discarded – undo
1475 1475
  *     - False en cas d'erreur.
1476 1476
  **/
1477 1477
 function spip_mysql_delete($table, $where = '', $serveur = '', $requeter = true) {
1478
-	$res = spip_mysql_query(
1479
-		calculer_mysql_expression('DELETE FROM', $table, ',')
1480
-		. calculer_mysql_expression('WHERE', $where),
1481
-		$serveur,
1482
-		$requeter
1483
-	);
1484
-	if (!$requeter) {
1485
-		return $res;
1486
-	}
1487
-	if ($res) {
1488
-		$link = _mysql_link($serveur);
1489
-
1490
-		return mysqli_affected_rows($link);
1491
-	} else {
1492
-		return false;
1493
-	}
1478
+    $res = spip_mysql_query(
1479
+        calculer_mysql_expression('DELETE FROM', $table, ',')
1480
+        . calculer_mysql_expression('WHERE', $where),
1481
+        $serveur,
1482
+        $requeter
1483
+    );
1484
+    if (!$requeter) {
1485
+        return $res;
1486
+    }
1487
+    if ($res) {
1488
+        $link = _mysql_link($serveur);
1489
+
1490
+        return mysqli_affected_rows($link);
1491
+    } else {
1492
+        return false;
1493
+    }
1494 1494
 }
1495 1495
 
1496 1496
 
@@ -1519,10 +1519,10 @@  discard block
 block discarded – undo
1519 1519
  *     - False en cas d'erreur.
1520 1520
  **/
1521 1521
 function spip_mysql_replace($table, $couples, $desc = [], $serveur = '', $requeter = true) {
1522
-	return spip_mysql_query("REPLACE $table (" . join(',', array_keys($couples)) . ') VALUES (' . join(
1523
-		',',
1524
-		array_map('_q', $couples)
1525
-	) . ')', $serveur, $requeter);
1522
+    return spip_mysql_query("REPLACE $table (" . join(',', array_keys($couples)) . ') VALUES (' . join(
1523
+        ',',
1524
+        array_map('_q', $couples)
1525
+    ) . ')', $serveur, $requeter);
1526 1526
 }
1527 1527
 
1528 1528
 
@@ -1551,14 +1551,14 @@  discard block
 block discarded – undo
1551 1551
  *     - False en cas d'erreur.
1552 1552
  **/
1553 1553
 function spip_mysql_replace_multi($table, $tab_couples, $desc = [], $serveur = '', $requeter = true) {
1554
-	$cles = '(' . join(',', array_keys($tab_couples[0])) . ')';
1555
-	$valeurs = [];
1556
-	foreach ($tab_couples as $couples) {
1557
-		$valeurs[] = '(' . join(',', array_map('_q', $couples)) . ')';
1558
-	}
1559
-	$valeurs = implode(', ', $valeurs);
1560
-
1561
-	return spip_mysql_query("REPLACE $table $cles VALUES $valeurs", $serveur, $requeter);
1554
+    $cles = '(' . join(',', array_keys($tab_couples[0])) . ')';
1555
+    $valeurs = [];
1556
+    foreach ($tab_couples as $couples) {
1557
+        $valeurs[] = '(' . join(',', array_map('_q', $couples)) . ')';
1558
+    }
1559
+    $valeurs = implode(', ', $valeurs);
1560
+
1561
+    return spip_mysql_query("REPLACE $table $cles VALUES $valeurs", $serveur, $requeter);
1562 1562
 }
1563 1563
 
1564 1564
 
@@ -1573,32 +1573,32 @@  discard block
 block discarded – undo
1573 1573
  * @return string       Texte de sélection pour la requête
1574 1574
  */
1575 1575
 function spip_mysql_multi($objet, $lang) {
1576
-	$lengthlang = strlen("[$lang]");
1577
-	$posmulti = 'INSTR(' . $objet . ", '<multi>')";
1578
-	$posfinmulti = 'INSTR(' . $objet . ", '</multi>')";
1579
-	$debutchaine = 'LEFT(' . $objet . ", $posmulti-1)";
1580
-	$finchaine = 'RIGHT(' . $objet . ', CHAR_LENGTH(' . $objet . ") -(7+$posfinmulti))";
1581
-	$chainemulti = 'TRIM(SUBSTRING(' . $objet . ", $posmulti+7, $posfinmulti -(7+$posmulti)))";
1582
-	$poslang = "INSTR($chainemulti,'[" . $lang . "]')";
1583
-	$poslang = "IF($poslang=0,INSTR($chainemulti,']')+1,$poslang+$lengthlang)";
1584
-	$chainelang = 'TRIM(SUBSTRING(' . $objet . ", $posmulti+7+$poslang-1,$posfinmulti -($posmulti+7+$poslang-1) ))";
1585
-	$posfinlang = 'INSTR(' . $chainelang . ", '[')";
1586
-	$chainelang = "IF($posfinlang>0,LEFT($chainelang,$posfinlang-1),$chainelang)";
1587
-	//$chainelang = "LEFT($chainelang,$posfinlang-1)";
1588
-	$retour = "(TRIM(IF($posmulti = 0 , " .
1589
-		'     TRIM(' . $objet . '), ' .
1590
-		'     CONCAT( ' .
1591
-		"          $debutchaine, " .
1592
-		'          IF( ' .
1593
-		"               $poslang = 0, " .
1594
-		"                     $chainemulti, " .
1595
-		"               $chainelang" .
1596
-		'          ), ' .
1597
-		"          $finchaine" .
1598
-		'     ) ' .
1599
-		'))) AS multi';
1600
-
1601
-	return $retour;
1576
+    $lengthlang = strlen("[$lang]");
1577
+    $posmulti = 'INSTR(' . $objet . ", '<multi>')";
1578
+    $posfinmulti = 'INSTR(' . $objet . ", '</multi>')";
1579
+    $debutchaine = 'LEFT(' . $objet . ", $posmulti-1)";
1580
+    $finchaine = 'RIGHT(' . $objet . ', CHAR_LENGTH(' . $objet . ") -(7+$posfinmulti))";
1581
+    $chainemulti = 'TRIM(SUBSTRING(' . $objet . ", $posmulti+7, $posfinmulti -(7+$posmulti)))";
1582
+    $poslang = "INSTR($chainemulti,'[" . $lang . "]')";
1583
+    $poslang = "IF($poslang=0,INSTR($chainemulti,']')+1,$poslang+$lengthlang)";
1584
+    $chainelang = 'TRIM(SUBSTRING(' . $objet . ", $posmulti+7+$poslang-1,$posfinmulti -($posmulti+7+$poslang-1) ))";
1585
+    $posfinlang = 'INSTR(' . $chainelang . ", '[')";
1586
+    $chainelang = "IF($posfinlang>0,LEFT($chainelang,$posfinlang-1),$chainelang)";
1587
+    //$chainelang = "LEFT($chainelang,$posfinlang-1)";
1588
+    $retour = "(TRIM(IF($posmulti = 0 , " .
1589
+        '     TRIM(' . $objet . '), ' .
1590
+        '     CONCAT( ' .
1591
+        "          $debutchaine, " .
1592
+        '          IF( ' .
1593
+        "               $poslang = 0, " .
1594
+        "                     $chainemulti, " .
1595
+        "               $chainelang" .
1596
+        '          ), ' .
1597
+        "          $finchaine" .
1598
+        '     ) ' .
1599
+        '))) AS multi';
1600
+
1601
+    return $retour;
1602 1602
 }
1603 1603
 
1604 1604
 /**
@@ -1612,7 +1612,7 @@  discard block
 block discarded – undo
1612 1612
  *     Valeur hexadécimale pour MySQL
1613 1613
  **/
1614 1614
 function spip_mysql_hex($v) {
1615
-	return '0x' . $v;
1615
+    return '0x' . $v;
1616 1616
 }
1617 1617
 
1618 1618
 /**
@@ -1628,15 +1628,15 @@  discard block
 block discarded – undo
1628 1628
  *    Donnée prête à être utilisée par le gestionnaire SQL
1629 1629
  */
1630 1630
 function spip_mysql_quote($v, $type = '') {
1631
-	if (!is_array($v)) {
1632
-		return spip_mysql_cite($v, $type);
1633
-	}
1634
-
1635
-	// si c'est un tableau, le parcourir en propageant le type
1636
-	foreach ($v as $k => $r) {
1637
-		$v[$k] = spip_mysql_quote($r, $type);
1638
-	}
1639
-	return implode(',', $v);
1631
+    if (!is_array($v)) {
1632
+        return spip_mysql_cite($v, $type);
1633
+    }
1634
+
1635
+    // si c'est un tableau, le parcourir en propageant le type
1636
+    foreach ($v as $k => $r) {
1637
+        $v[$k] = spip_mysql_quote($r, $type);
1638
+    }
1639
+    return implode(',', $v);
1640 1640
 }
1641 1641
 
1642 1642
 /**
@@ -1652,18 +1652,18 @@  discard block
 block discarded – undo
1652 1652
  *     Expression SQL
1653 1653
  **/
1654 1654
 function spip_mysql_date_proche($champ, $interval, $unite) {
1655
-	$use_now = ( ($champ === 'maj' or strpos($champ, '.maj')) ? true : false );
1656
-	return '('
1657
-	. $champ
1658
-	. (($interval <= 0) ? '>' : '<')
1659
-	. (($interval <= 0) ? 'DATE_SUB' : 'DATE_ADD')
1660
-	. '('
1661
-	. ($use_now ? 'NOW()' : sql_quote(date('Y-m-d H:i:s')))
1662
-	. ', INTERVAL '
1663
-	. (($interval > 0) ? $interval : (0 - $interval))
1664
-	. ' '
1665
-	. $unite
1666
-	. '))';
1655
+    $use_now = ( ($champ === 'maj' or strpos($champ, '.maj')) ? true : false );
1656
+    return '('
1657
+    . $champ
1658
+    . (($interval <= 0) ? '>' : '<')
1659
+    . (($interval <= 0) ? 'DATE_SUB' : 'DATE_ADD')
1660
+    . '('
1661
+    . ($use_now ? 'NOW()' : sql_quote(date('Y-m-d H:i:s')))
1662
+    . ', INTERVAL '
1663
+    . (($interval > 0) ? $interval : (0 - $interval))
1664
+    . ' '
1665
+    . $unite
1666
+    . '))';
1667 1667
 }
1668 1668
 
1669 1669
 
@@ -1687,7 +1687,7 @@  discard block
 block discarded – undo
1687 1687
  *     Expression de requête SQL
1688 1688
  **/
1689 1689
 function spip_mysql_in($val, $valeurs, $not = '', $serveur = '', $requeter = true) {
1690
-	return "($val $not IN ($valeurs))";
1690
+    return "($val $not IN ($valeurs))";
1691 1691
 }
1692 1692
 
1693 1693
 
@@ -1699,39 +1699,39 @@  discard block
 block discarded – undo
1699 1699
  * @return string|number     Texte ou nombre échappé
1700 1700
  */
1701 1701
 function spip_mysql_cite($v, $type) {
1702
-	if (!$type) {
1703
-		if (is_bool($v)) {
1704
-			return strval(intval($v));
1705
-		} elseif (is_numeric($v)) {
1706
-			return strval($v);
1707
-		} elseif ($v === null) {
1708
-			return "''";
1709
-		}
1710
-		return "'" . addslashes($v) . "'";
1711
-	}
1712
-
1713
-	if ($v === null) {
1714
-		if (stripos($type, 'NOT NULL') === false) {
1715
-			// null php se traduit en NULL SQL
1716
-			return 'NULL';
1717
-		} else {
1718
-			return "''";
1719
-		}
1720
-	} elseif (sql_test_date($type) and preg_match('/^\w+\(/', $v)) {
1721
-		return $v;
1722
-	} elseif (sql_test_int($type)) {
1723
-		if (
1724
-			is_numeric($v)
1725
-			or ($v and ctype_xdigit(substr($v, 2)) and $v[0] === '0' and $v[1] === 'x')
1726
-		) {
1727
-			return $v;
1728
-		} else {
1729
-			// si pas numerique, forcer le intval
1730
-			return intval($v);
1731
-		}
1732
-	}
1733
-
1734
-	return ("'" . addslashes($v) . "'");
1702
+    if (!$type) {
1703
+        if (is_bool($v)) {
1704
+            return strval(intval($v));
1705
+        } elseif (is_numeric($v)) {
1706
+            return strval($v);
1707
+        } elseif ($v === null) {
1708
+            return "''";
1709
+        }
1710
+        return "'" . addslashes($v) . "'";
1711
+    }
1712
+
1713
+    if ($v === null) {
1714
+        if (stripos($type, 'NOT NULL') === false) {
1715
+            // null php se traduit en NULL SQL
1716
+            return 'NULL';
1717
+        } else {
1718
+            return "''";
1719
+        }
1720
+    } elseif (sql_test_date($type) and preg_match('/^\w+\(/', $v)) {
1721
+        return $v;
1722
+    } elseif (sql_test_int($type)) {
1723
+        if (
1724
+            is_numeric($v)
1725
+            or ($v and ctype_xdigit(substr($v, 2)) and $v[0] === '0' and $v[1] === 'x')
1726
+        ) {
1727
+            return $v;
1728
+        } else {
1729
+            // si pas numerique, forcer le intval
1730
+            return intval($v);
1731
+        }
1732
+    }
1733
+
1734
+    return ("'" . addslashes($v) . "'");
1735 1735
 }
1736 1736
 
1737 1737
 /**
@@ -1741,7 +1741,7 @@  discard block
 block discarded – undo
1741 1741
  *     True si on a les fonctions, false sinon
1742 1742
  */
1743 1743
 function spip_versions_mysql() {
1744
-	return function_exists('mysqli_query');
1744
+    return function_exists('mysqli_query');
1745 1745
 }
1746 1746
 
1747 1747
 
@@ -1754,20 +1754,20 @@  discard block
 block discarded – undo
1754 1754
  *     - chaîne : code compilé pour le faire désactiver par SPIP sinon
1755 1755
  */
1756 1756
 function test_rappel_nom_base_mysql($server_db) {
1757
-	$GLOBALS['mysql_rappel_nom_base'] = true;
1758
-	sql_delete('spip_meta', "nom='mysql_rappel_nom_base'", $server_db);
1759
-	$ok = spip_query("INSERT INTO spip_meta (nom,valeur) VALUES ('mysql_rappel_nom_base', 'test')", $server_db);
1757
+    $GLOBALS['mysql_rappel_nom_base'] = true;
1758
+    sql_delete('spip_meta', "nom='mysql_rappel_nom_base'", $server_db);
1759
+    $ok = spip_query("INSERT INTO spip_meta (nom,valeur) VALUES ('mysql_rappel_nom_base', 'test')", $server_db);
1760 1760
 
1761
-	if ($ok) {
1762
-		sql_delete('spip_meta', "nom='mysql_rappel_nom_base'", $server_db);
1761
+    if ($ok) {
1762
+        sql_delete('spip_meta', "nom='mysql_rappel_nom_base'", $server_db);
1763 1763
 
1764
-		return '';
1765
-	} else {
1766
-		$GLOBALS['mysql_rappel_nom_base'] = false;
1764
+        return '';
1765
+    } else {
1766
+        $GLOBALS['mysql_rappel_nom_base'] = false;
1767 1767
 
1768
-		return "\$GLOBALS['mysql_rappel_nom_base'] = false; " .
1769
-		"/* echec de test_rappel_nom_base_mysql a l'installation. */\n";
1770
-	}
1768
+        return "\$GLOBALS['mysql_rappel_nom_base'] = false; " .
1769
+        "/* echec de test_rappel_nom_base_mysql a l'installation. */\n";
1770
+    }
1771 1771
 }
1772 1772
 
1773 1773
 /**
@@ -1781,13 +1781,13 @@  discard block
 block discarded – undo
1781 1781
  *     - chaîne : code compilé pour l'indiquer le résultat du test à SPIP
1782 1782
  */
1783 1783
 function test_sql_mode_mysql($server_db) {
1784
-	$res = sql_select('version() as v', '', '', '', '', '', '', $server_db);
1785
-	$row = sql_fetch($res, $server_db);
1786
-	if (version_compare($row['v'], '5.0.0', '>=')) {
1787
-		defined('_MYSQL_SET_SQL_MODE') || define('_MYSQL_SET_SQL_MODE', true);
1784
+    $res = sql_select('version() as v', '', '', '', '', '', '', $server_db);
1785
+    $row = sql_fetch($res, $server_db);
1786
+    if (version_compare($row['v'], '5.0.0', '>=')) {
1787
+        defined('_MYSQL_SET_SQL_MODE') || define('_MYSQL_SET_SQL_MODE', true);
1788 1788
 
1789
-		return "defined('_MYSQL_SET_SQL_MODE') || define('_MYSQL_SET_SQL_MODE',true);\n";
1790
-	}
1789
+        return "defined('_MYSQL_SET_SQL_MODE') || define('_MYSQL_SET_SQL_MODE',true);\n";
1790
+    }
1791 1791
 
1792
-	return '';
1792
+    return '';
1793 1793
 }
Please login to merge, or discard this patch.
ecrire/public/fonctions.php 1 patch
Indentation   +364 added lines, -364 removed lines patch added patch discarded remove patch
@@ -23,7 +23,7 @@  discard block
 block discarded – undo
23 23
  **/
24 24
 
25 25
 if (!defined('_ECRIRE_INC_VERSION')) {
26
-	return;
26
+    return;
27 27
 }
28 28
 
29 29
 // public/interfaces definit des traitements sur les champs qui utilisent des fonctions de inc/texte
@@ -55,75 +55,75 @@  discard block
 block discarded – undo
55 55
  *     Introduction calculée
56 56
  **/
57 57
 function filtre_introduction_dist($descriptif, $texte, $longueur, $connect, $suite = null) {
58
-	// Si un descriptif est envoye, on l'utilise directement
59
-	if (strlen($descriptif)) {
60
-		return appliquer_traitement_champ($descriptif, 'introduction', '', [], $connect);
61
-	}
62
-
63
-	// De preference ce qui est marque <intro>...</intro>
64
-	$intro = '';
65
-	$texte = preg_replace(',(</?)intro>,i', "\\1intro>", $texte); // minuscules
66
-	while ($fin = strpos($texte, '</intro>')) {
67
-		$zone = substr($texte, 0, $fin);
68
-		$texte = substr($texte, $fin + strlen('</intro>'));
69
-		if ($deb = strpos($zone, '<intro>') or substr($zone, 0, 7) == '<intro>') {
70
-			$zone = substr($zone, $deb + 7);
71
-		}
72
-		$intro .= $zone;
73
-	}
74
-
75
-	// [12025] On ne *PEUT* pas couper simplement ici car c'est du texte brut,
76
-	// qui inclus raccourcis et modeles
77
-	// un simple <articlexx> peut etre ensuite transforme en 1000 lignes ...
78
-	// par ailleurs le nettoyage des raccourcis ne tient pas compte
79
-	// des surcharges et enrichissement de propre
80
-	// couper doit se faire apres propre
81
-	//$texte = nettoyer_raccourcis_typo($intro ? $intro : $texte, $connect);
82
-
83
-	// Cependant pour des questions de perfs on coupe quand meme, en prenant
84
-	// large et en se mefiant des tableaux #1323
85
-
86
-	if (strlen($intro)) {
87
-		$texte = $intro;
88
-	} else {
89
-		if (
90
-			strpos("\n" . $texte, "\n|") === false
91
-			and strlen($texte) > 2.5 * $longueur
92
-		) {
93
-			if (strpos($texte, '<multi') !== false) {
94
-				$texte = extraire_multi($texte);
95
-			}
96
-			$texte = couper($texte, 2 * $longueur);
97
-		}
98
-	}
99
-
100
-	// ne pas tenir compte des notes
101
-	if ($notes = charger_fonction('notes', 'inc', true)) {
102
-		$notes('', 'empiler');
103
-	}
104
-	// Supprimer les modèles avant le propre afin d'éviter qu'ils n'ajoutent du texte indésirable
105
-	// dans l'introduction.
106
-	$texte = supprime_img($texte, '');
107
-	$texte = appliquer_traitement_champ($texte, 'introduction', '', [], $connect);
108
-
109
-	if ($notes) {
110
-		$notes('', 'depiler');
111
-	}
112
-
113
-	if (is_null($suite) and defined('_INTRODUCTION_SUITE')) {
114
-		$suite = _INTRODUCTION_SUITE;
115
-	}
116
-	$texte = couper($texte, $longueur, $suite);
117
-	// comme on a coupe il faut repasser la typo (on a perdu les insecables)
118
-	$texte = typo($texte, true, $connect, []);
119
-
120
-	// et reparagrapher si necessaire (coherence avec le cas descriptif)
121
-	// une introduction a tojours un <p>
122
-	if ($GLOBALS['toujours_paragrapher']) { // Fermer les paragraphes
123
-	$texte = paragrapher($texte, $GLOBALS['toujours_paragrapher']);
124
-	}
125
-
126
-	return $texte;
58
+    // Si un descriptif est envoye, on l'utilise directement
59
+    if (strlen($descriptif)) {
60
+        return appliquer_traitement_champ($descriptif, 'introduction', '', [], $connect);
61
+    }
62
+
63
+    // De preference ce qui est marque <intro>...</intro>
64
+    $intro = '';
65
+    $texte = preg_replace(',(</?)intro>,i', "\\1intro>", $texte); // minuscules
66
+    while ($fin = strpos($texte, '</intro>')) {
67
+        $zone = substr($texte, 0, $fin);
68
+        $texte = substr($texte, $fin + strlen('</intro>'));
69
+        if ($deb = strpos($zone, '<intro>') or substr($zone, 0, 7) == '<intro>') {
70
+            $zone = substr($zone, $deb + 7);
71
+        }
72
+        $intro .= $zone;
73
+    }
74
+
75
+    // [12025] On ne *PEUT* pas couper simplement ici car c'est du texte brut,
76
+    // qui inclus raccourcis et modeles
77
+    // un simple <articlexx> peut etre ensuite transforme en 1000 lignes ...
78
+    // par ailleurs le nettoyage des raccourcis ne tient pas compte
79
+    // des surcharges et enrichissement de propre
80
+    // couper doit se faire apres propre
81
+    //$texte = nettoyer_raccourcis_typo($intro ? $intro : $texte, $connect);
82
+
83
+    // Cependant pour des questions de perfs on coupe quand meme, en prenant
84
+    // large et en se mefiant des tableaux #1323
85
+
86
+    if (strlen($intro)) {
87
+        $texte = $intro;
88
+    } else {
89
+        if (
90
+            strpos("\n" . $texte, "\n|") === false
91
+            and strlen($texte) > 2.5 * $longueur
92
+        ) {
93
+            if (strpos($texte, '<multi') !== false) {
94
+                $texte = extraire_multi($texte);
95
+            }
96
+            $texte = couper($texte, 2 * $longueur);
97
+        }
98
+    }
99
+
100
+    // ne pas tenir compte des notes
101
+    if ($notes = charger_fonction('notes', 'inc', true)) {
102
+        $notes('', 'empiler');
103
+    }
104
+    // Supprimer les modèles avant le propre afin d'éviter qu'ils n'ajoutent du texte indésirable
105
+    // dans l'introduction.
106
+    $texte = supprime_img($texte, '');
107
+    $texte = appliquer_traitement_champ($texte, 'introduction', '', [], $connect);
108
+
109
+    if ($notes) {
110
+        $notes('', 'depiler');
111
+    }
112
+
113
+    if (is_null($suite) and defined('_INTRODUCTION_SUITE')) {
114
+        $suite = _INTRODUCTION_SUITE;
115
+    }
116
+    $texte = couper($texte, $longueur, $suite);
117
+    // comme on a coupe il faut repasser la typo (on a perdu les insecables)
118
+    $texte = typo($texte, true, $connect, []);
119
+
120
+    // et reparagrapher si necessaire (coherence avec le cas descriptif)
121
+    // une introduction a tojours un <p>
122
+    if ($GLOBALS['toujours_paragrapher']) { // Fermer les paragraphes
123
+    $texte = paragrapher($texte, $GLOBALS['toujours_paragrapher']);
124
+    }
125
+
126
+    return $texte;
127 127
 }
128 128
 
129 129
 
@@ -158,73 +158,73 @@  discard block
 block discarded – undo
158 158
  *     Code HTML de la pagination
159 159
  **/
160 160
 function filtre_pagination_dist(
161
-	$total,
162
-	$nom,
163
-	$position,
164
-	$pas,
165
-	$liste = true,
166
-	$modele = '',
167
-	string $connect = '',
168
-	$env = []
161
+    $total,
162
+    $nom,
163
+    $position,
164
+    $pas,
165
+    $liste = true,
166
+    $modele = '',
167
+    string $connect = '',
168
+    $env = []
169 169
 ) {
170
-	static $ancres = [];
171
-	if ($pas < 1) {
172
-		return '';
173
-	}
174
-	$ancre = 'pagination' . $nom; // #pagination_articles
175
-	$debut = 'debut' . $nom; // 'debut_articles'
176
-
177
-	// n'afficher l'ancre qu'une fois
178
-	if (!isset($ancres[$ancre])) {
179
-		$bloc_ancre = $ancres[$ancre] = "<a id='" . $ancre . "' class='pagination_ancre'></a>";
180
-	} else {
181
-		$bloc_ancre = '';
182
-	}
183
-	// liste = false : on ne veut que l'ancre
184
-	if (!$liste) {
185
-		return $ancres[$ancre];
186
-	}
187
-
188
-	$self = (empty($env['self']) ? self() : $env['self']);
189
-	$pagination = [
190
-		'debut' => $debut,
191
-		'url' => parametre_url($self, 'fragment', ''), // nettoyer l'id ahah eventuel
192
-		'total' => $total,
193
-		'position' => intval($position),
194
-		'pas' => $pas,
195
-		'nombre_pages' => floor(($total - 1) / $pas) + 1,
196
-		'page_courante' => floor(intval($position) / $pas) + 1,
197
-		'ancre' => $ancre,
198
-		'bloc_ancre' => $bloc_ancre
199
-	];
200
-	if (is_array($env)) {
201
-		$pagination = array_merge($env, $pagination);
202
-	}
203
-
204
-	// Pas de pagination
205
-	if ($pagination['nombre_pages'] <= 1) {
206
-		return '';
207
-	}
208
-
209
-	if ($modele) {
210
-		$pagination['type_pagination'] = $modele;
211
-		if (trouver_fond('pagination_' . $modele, 'modeles')) {
212
-			$modele = '_' . $modele;
213
-		}
214
-		else {
215
-			$modele = '';
216
-		}
217
-	}
218
-
219
-	if (!defined('_PAGINATION_NOMBRE_LIENS_MAX')) {
220
-		define('_PAGINATION_NOMBRE_LIENS_MAX', 10);
221
-	}
222
-	if (!defined('_PAGINATION_NOMBRE_LIENS_MAX_ECRIRE')) {
223
-		define('_PAGINATION_NOMBRE_LIENS_MAX_ECRIRE', 5);
224
-	}
225
-
226
-
227
-	return recuperer_fond("modeles/pagination$modele", $pagination, ['trim' => true], $connect);
170
+    static $ancres = [];
171
+    if ($pas < 1) {
172
+        return '';
173
+    }
174
+    $ancre = 'pagination' . $nom; // #pagination_articles
175
+    $debut = 'debut' . $nom; // 'debut_articles'
176
+
177
+    // n'afficher l'ancre qu'une fois
178
+    if (!isset($ancres[$ancre])) {
179
+        $bloc_ancre = $ancres[$ancre] = "<a id='" . $ancre . "' class='pagination_ancre'></a>";
180
+    } else {
181
+        $bloc_ancre = '';
182
+    }
183
+    // liste = false : on ne veut que l'ancre
184
+    if (!$liste) {
185
+        return $ancres[$ancre];
186
+    }
187
+
188
+    $self = (empty($env['self']) ? self() : $env['self']);
189
+    $pagination = [
190
+        'debut' => $debut,
191
+        'url' => parametre_url($self, 'fragment', ''), // nettoyer l'id ahah eventuel
192
+        'total' => $total,
193
+        'position' => intval($position),
194
+        'pas' => $pas,
195
+        'nombre_pages' => floor(($total - 1) / $pas) + 1,
196
+        'page_courante' => floor(intval($position) / $pas) + 1,
197
+        'ancre' => $ancre,
198
+        'bloc_ancre' => $bloc_ancre
199
+    ];
200
+    if (is_array($env)) {
201
+        $pagination = array_merge($env, $pagination);
202
+    }
203
+
204
+    // Pas de pagination
205
+    if ($pagination['nombre_pages'] <= 1) {
206
+        return '';
207
+    }
208
+
209
+    if ($modele) {
210
+        $pagination['type_pagination'] = $modele;
211
+        if (trouver_fond('pagination_' . $modele, 'modeles')) {
212
+            $modele = '_' . $modele;
213
+        }
214
+        else {
215
+            $modele = '';
216
+        }
217
+    }
218
+
219
+    if (!defined('_PAGINATION_NOMBRE_LIENS_MAX')) {
220
+        define('_PAGINATION_NOMBRE_LIENS_MAX', 10);
221
+    }
222
+    if (!defined('_PAGINATION_NOMBRE_LIENS_MAX_ECRIRE')) {
223
+        define('_PAGINATION_NOMBRE_LIENS_MAX_ECRIRE', 5);
224
+    }
225
+
226
+
227
+    return recuperer_fond("modeles/pagination$modele", $pagination, ['trim' => true], $connect);
228 228
 }
229 229
 
230 230
 
@@ -243,44 +243,44 @@  discard block
 block discarded – undo
243 243
  *     Liste (première page, dernière page).
244 244
  **/
245 245
 function filtre_bornes_pagination_dist($courante, $nombre, $max = 10) {
246
-	if ($max <= 0 or $max >= $nombre) {
247
-		return [1, $nombre];
248
-	}
249
-	if ($max <= 1) {
250
-		return [$courante, $courante];
251
-	}
252
-
253
-	$premiere = max(1, $courante - floor(($max - 1) / 2));
254
-	$derniere = min($nombre, $premiere + $max - 2);
255
-	$premiere = $derniere == $nombre ? $derniere - $max + 1 : $premiere;
256
-
257
-	return [$premiere, $derniere];
246
+    if ($max <= 0 or $max >= $nombre) {
247
+        return [1, $nombre];
248
+    }
249
+    if ($max <= 1) {
250
+        return [$courante, $courante];
251
+    }
252
+
253
+    $premiere = max(1, $courante - floor(($max - 1) / 2));
254
+    $derniere = min($nombre, $premiere + $max - 2);
255
+    $premiere = $derniere == $nombre ? $derniere - $max + 1 : $premiere;
256
+
257
+    return [$premiere, $derniere];
258 258
 }
259 259
 
260 260
 function filtre_pagination_affiche_texte_lien_page_dist($type_pagination, $numero_page, $rang_item) {
261
-	if ($numero_page === 'tous') {
262
-		return '&#8734;';
263
-	}
264
-	if ($numero_page === 'prev') {
265
-		return '&lt;';
266
-	}
267
-	if ($numero_page === 'next') {
268
-		return '&gt;';
269
-	}
270
-
271
-	switch ($type_pagination) {
272
-		case 'resultats':
273
-			return $rang_item + 1; // 1 11 21 31...
274
-		case 'naturel':
275
-			return $rang_item ?: 1; // 1 10 20 30...
276
-		case 'rang':
277
-			return $rang_item; // 0 10 20 30...
278
-
279
-		case 'page':
280
-		case 'prive':
281
-		default:
282
-			return $numero_page; // 1 2 3 4 5...
283
-	}
261
+    if ($numero_page === 'tous') {
262
+        return '&#8734;';
263
+    }
264
+    if ($numero_page === 'prev') {
265
+        return '&lt;';
266
+    }
267
+    if ($numero_page === 'next') {
268
+        return '&gt;';
269
+    }
270
+
271
+    switch ($type_pagination) {
272
+        case 'resultats':
273
+            return $rang_item + 1; // 1 11 21 31...
274
+        case 'naturel':
275
+            return $rang_item ?: 1; // 1 10 20 30...
276
+        case 'rang':
277
+            return $rang_item; // 0 10 20 30...
278
+
279
+        case 'page':
280
+        case 'prive':
281
+        default:
282
+            return $numero_page; // 1 2 3 4 5...
283
+    }
284 284
 }
285 285
 
286 286
 /**
@@ -293,15 +293,15 @@  discard block
 block discarded – undo
293 293
  **/
294 294
 function lister_objets_avec_logos($type) {
295 295
 
296
-	$objet = objet_type($type);
297
-	$ids = sql_allfetsel('L.id_objet', 'spip_documents AS D JOIN spip_documents_liens AS L ON L.id_document=D.id_document', 'D.mode=' . sql_quote('logoon') . ' AND L.objet=' . sql_quote($objet));
298
-	if ($ids) {
299
-		$ids = array_column($ids, 'id_objet');
300
-		return implode(',', $ids);
301
-	}
302
-	else {
303
-		return '0';
304
-	}
296
+    $objet = objet_type($type);
297
+    $ids = sql_allfetsel('L.id_objet', 'spip_documents AS D JOIN spip_documents_liens AS L ON L.id_document=D.id_document', 'D.mode=' . sql_quote('logoon') . ' AND L.objet=' . sql_quote($objet));
298
+    if ($ids) {
299
+        $ids = array_column($ids, 'id_objet');
300
+        return implode(',', $ids);
301
+    }
302
+    else {
303
+        return '0';
304
+    }
305 305
 }
306 306
 
307 307
 
@@ -317,14 +317,14 @@  discard block
 block discarded – undo
317 317
  *     Code HTML des notes
318 318
  **/
319 319
 function calculer_notes() {
320
-	$r = '';
321
-	if ($notes = charger_fonction('notes', 'inc', true)) {
322
-		$r = $notes([]);
323
-		$notes('', 'depiler');
324
-		$notes('', 'empiler');
325
-	}
326
-
327
-	return $r;
320
+    $r = '';
321
+    if ($notes = charger_fonction('notes', 'inc', true)) {
322
+        $r = $notes([]);
323
+        $notes('', 'depiler');
324
+        $notes('', 'empiler');
325
+    }
326
+
327
+    return $r;
328 328
 }
329 329
 
330 330
 
@@ -341,10 +341,10 @@  discard block
 block discarded – undo
341 341
  * @return string
342 342
  */
343 343
 function retrouver_rang_lien($objet_source, $ids, $objet_lie, $idl, $objet_lien) {
344
-	$res = lister_objets_liens($objet_source, $objet_lie, $idl, $objet_lien);
345
-	$res = array_column($res, 'rang_lien', $objet_source);
344
+    $res = lister_objets_liens($objet_source, $objet_lie, $idl, $objet_lien);
345
+    $res = array_column($res, 'rang_lien', $objet_source);
346 346
 
347
-	return ($res[$ids] ?? '');
347
+    return ($res[$ids] ?? '');
348 348
 }
349 349
 
350 350
 
@@ -361,19 +361,19 @@  discard block
 block discarded – undo
361 361
  * @private
362 362
  */
363 363
 function lister_objets_liens($objet_source, $objet, $id_objet, $objet_lien) {
364
-	static $liens = [];
365
-	if (!isset($liens["$objet_source-$objet-$id_objet-$objet_lien"])) {
366
-		include_spip('action/editer_liens');
367
-		// quand $objet == $objet_lien == $objet_source on reste sur le cas par defaut de $objet_lien == $objet_source
368
-		if ($objet_lien == $objet and $objet_lien !== $objet_source) {
369
-			$res = objet_trouver_liens([$objet => $id_objet], [$objet_source => '*']);
370
-		} else {
371
-			$res = objet_trouver_liens([$objet_source => '*'], [$objet => $id_objet]);
372
-		}
373
-
374
-		$liens["$objet_source-$objet-$id_objet-$objet_lien"] = $res;
375
-	}
376
-	return $liens["$objet_source-$objet-$id_objet-$objet_lien"];
364
+    static $liens = [];
365
+    if (!isset($liens["$objet_source-$objet-$id_objet-$objet_lien"])) {
366
+        include_spip('action/editer_liens');
367
+        // quand $objet == $objet_lien == $objet_source on reste sur le cas par defaut de $objet_lien == $objet_source
368
+        if ($objet_lien == $objet and $objet_lien !== $objet_source) {
369
+            $res = objet_trouver_liens([$objet => $id_objet], [$objet_source => '*']);
370
+        } else {
371
+            $res = objet_trouver_liens([$objet_source => '*'], [$objet => $id_objet]);
372
+        }
373
+
374
+        $liens["$objet_source-$objet-$id_objet-$objet_lien"] = $res;
375
+    }
376
+    return $liens["$objet_source-$objet-$id_objet-$objet_lien"];
377 377
 }
378 378
 
379 379
 /**
@@ -387,24 +387,24 @@  discard block
 block discarded – undo
387 387
  * @return int|string
388 388
  */
389 389
 function calculer_rang_smart($titre, $objet_source, $id, $env) {
390
-	// Cas du #RANG utilisé dans #FORMULAIRE_EDITER_LIENS -> attraper le rang du lien
391
-	// permet de voir le rang du lien si il y en a un en base, meme avant un squelette xxxx-lies.html ne gerant pas les liens
392
-	if (
393
-		isset($env['form']) and $env['form']
394
-		and isset($env['_objet_lien']) and $env['_objet_lien']
395
-		and (function_exists('lien_triables') or include_spip('action/editer_liens'))
396
-		and $r = objet_associable($env['_objet_lien'])
397
-		and [$p, $table_lien] = $r
398
-		and lien_triables($table_lien)
399
-		and isset($env['objet']) and $env['objet']
400
-		and isset($env['id_objet']) and $env['id_objet']
401
-		and $objet_source
402
-		and $id = intval($id)
403
-	) {
404
-		$rang = retrouver_rang_lien($objet_source, $id, $env['objet'], $env['id_objet'], $env['_objet_lien']);
405
-		return ($rang ?: '');
406
-	}
407
-	return recuperer_numero($titre);
390
+    // Cas du #RANG utilisé dans #FORMULAIRE_EDITER_LIENS -> attraper le rang du lien
391
+    // permet de voir le rang du lien si il y en a un en base, meme avant un squelette xxxx-lies.html ne gerant pas les liens
392
+    if (
393
+        isset($env['form']) and $env['form']
394
+        and isset($env['_objet_lien']) and $env['_objet_lien']
395
+        and (function_exists('lien_triables') or include_spip('action/editer_liens'))
396
+        and $r = objet_associable($env['_objet_lien'])
397
+        and [$p, $table_lien] = $r
398
+        and lien_triables($table_lien)
399
+        and isset($env['objet']) and $env['objet']
400
+        and isset($env['id_objet']) and $env['id_objet']
401
+        and $objet_source
402
+        and $id = intval($id)
403
+    ) {
404
+        $rang = retrouver_rang_lien($objet_source, $id, $env['objet'], $env['id_objet'], $env['_objet_lien']);
405
+        return ($rang ?: '');
406
+    }
407
+    return recuperer_numero($titre);
408 408
 }
409 409
 
410 410
 /**
@@ -431,72 +431,72 @@  discard block
 block discarded – undo
431 431
  */
432 432
 function calculer_balise_tri(string $champ_ou_sens, string $libelle, string $classe, string $tri_nom, string $tri_champ, string $tri_sens, $liste_tri_sens_defaut): string {
433 433
 
434
-	$url = self('&');
435
-	$tri_sens = (int) $tri_sens;
436
-	$alias_sens = [
437
-		'<' => -1,
438
-		'>' => 1,
439
-		'inverse' => -1,
440
-	];
441
-
442
-	// Normaliser la liste des sens de tri par défaut
443
-	// On ajoute un jocker pour les champs non présents dans la liste
444
-	// avec la valeur du 1er item de la liste, idem critère {tri}
445
-	if (is_array($liste_tri_sens_defaut)) {
446
-		$liste_tri_sens_defaut['*'] = array_values($liste_tri_sens_defaut)[0];
447
-	} else {
448
-		$liste_tri_sens_defaut = [
449
-			'*' => (int) ($alias_sens[$liste_tri_sens_defaut] ?? $liste_tri_sens_defaut),
450
-		];
451
-	}
452
-
453
-	// Les sens de tri actuel et nouveau :
454
-	// Soit c'est un sens fixe donné en paramètre (< ou >)
455
-	$is_sens_fixe = array_key_exists($champ_ou_sens, $alias_sens);
456
-	if ($is_sens_fixe) {
457
-		$tri_sens_actuel = $tri_sens;
458
-		$tri_sens_nouveau = $alias_sens[$champ_ou_sens];
459
-	// Soit c'est le champ utilisé actuellement pour le tri → on inverse le sens
460
-	} elseif ($champ_ou_sens === $tri_champ) {
461
-		$tri_sens_actuel = $tri_sens;
462
-		$tri_sens_nouveau = $tri_sens * -1;
463
-	// Sinon c'est un nouveau champ, et on prend son tri par défaut
464
-	} else {
465
-		$tri_sens_actuel = $tri_sens_nouveau = (int) ($liste_tri_sens_defaut[$champ_ou_sens] ?? $liste_tri_sens_defaut['*']);
466
-	}
467
-
468
-	// URL : ajouter le champ sur lequel porte le tri
469
-	if (!$is_sens_fixe) {
470
-		$param_tri = "tri$tri_nom";
471
-		$url = parametre_url($url, $param_tri, $champ_ou_sens);
472
-	}
473
-
474
-	// URL : n'ajouter le sens de tri que si nécessaire,
475
-	// c.à.d différent du sens par défaut pour le champ
476
-	$param_sens = "sens$tri_nom";
477
-	$tri_sens_defaut_champ = (int) ($liste_tri_sens_defaut[$champ_ou_sens] ?? $liste_tri_sens_defaut['*']);
478
-	if ($tri_sens_nouveau !== $tri_sens_defaut_champ) {
479
-		$url = parametre_url($url, $param_sens, $tri_sens_nouveau);
480
-	} else {
481
-		$url = parametre_url($url, $param_sens, '');
482
-	}
483
-
484
-	// Drapeau pour garder en session ?
485
-	$param_memo = (!$is_sens_fixe ? $param_tri : $param_sens);
486
-	$url = parametre_url($url, 'var_memotri', strncmp($tri_nom, 'session', 7) == 0 ? $param_memo : '');
487
-
488
-	// Classes : on indique le sens de tri et l'item exposé
489
-	if (!$is_sens_fixe) {
490
-		$classe .= ' item-tri item-tri_' . ($tri_sens_actuel === 1 ? 'asc' : 'desc');
491
-	}
492
-	if ($champ_ou_sens === $tri_champ) {
493
-		$classe .= ' item-tri_actif';
494
-	}
495
-
496
-	// Lien
497
-	$balise = lien_ou_expose($url, $libelle, false, $classe);
498
-
499
-	return $balise;
434
+    $url = self('&');
435
+    $tri_sens = (int) $tri_sens;
436
+    $alias_sens = [
437
+        '<' => -1,
438
+        '>' => 1,
439
+        'inverse' => -1,
440
+    ];
441
+
442
+    // Normaliser la liste des sens de tri par défaut
443
+    // On ajoute un jocker pour les champs non présents dans la liste
444
+    // avec la valeur du 1er item de la liste, idem critère {tri}
445
+    if (is_array($liste_tri_sens_defaut)) {
446
+        $liste_tri_sens_defaut['*'] = array_values($liste_tri_sens_defaut)[0];
447
+    } else {
448
+        $liste_tri_sens_defaut = [
449
+            '*' => (int) ($alias_sens[$liste_tri_sens_defaut] ?? $liste_tri_sens_defaut),
450
+        ];
451
+    }
452
+
453
+    // Les sens de tri actuel et nouveau :
454
+    // Soit c'est un sens fixe donné en paramètre (< ou >)
455
+    $is_sens_fixe = array_key_exists($champ_ou_sens, $alias_sens);
456
+    if ($is_sens_fixe) {
457
+        $tri_sens_actuel = $tri_sens;
458
+        $tri_sens_nouveau = $alias_sens[$champ_ou_sens];
459
+    // Soit c'est le champ utilisé actuellement pour le tri → on inverse le sens
460
+    } elseif ($champ_ou_sens === $tri_champ) {
461
+        $tri_sens_actuel = $tri_sens;
462
+        $tri_sens_nouveau = $tri_sens * -1;
463
+    // Sinon c'est un nouveau champ, et on prend son tri par défaut
464
+    } else {
465
+        $tri_sens_actuel = $tri_sens_nouveau = (int) ($liste_tri_sens_defaut[$champ_ou_sens] ?? $liste_tri_sens_defaut['*']);
466
+    }
467
+
468
+    // URL : ajouter le champ sur lequel porte le tri
469
+    if (!$is_sens_fixe) {
470
+        $param_tri = "tri$tri_nom";
471
+        $url = parametre_url($url, $param_tri, $champ_ou_sens);
472
+    }
473
+
474
+    // URL : n'ajouter le sens de tri que si nécessaire,
475
+    // c.à.d différent du sens par défaut pour le champ
476
+    $param_sens = "sens$tri_nom";
477
+    $tri_sens_defaut_champ = (int) ($liste_tri_sens_defaut[$champ_ou_sens] ?? $liste_tri_sens_defaut['*']);
478
+    if ($tri_sens_nouveau !== $tri_sens_defaut_champ) {
479
+        $url = parametre_url($url, $param_sens, $tri_sens_nouveau);
480
+    } else {
481
+        $url = parametre_url($url, $param_sens, '');
482
+    }
483
+
484
+    // Drapeau pour garder en session ?
485
+    $param_memo = (!$is_sens_fixe ? $param_tri : $param_sens);
486
+    $url = parametre_url($url, 'var_memotri', strncmp($tri_nom, 'session', 7) == 0 ? $param_memo : '');
487
+
488
+    // Classes : on indique le sens de tri et l'item exposé
489
+    if (!$is_sens_fixe) {
490
+        $classe .= ' item-tri item-tri_' . ($tri_sens_actuel === 1 ? 'asc' : 'desc');
491
+    }
492
+    if ($champ_ou_sens === $tri_champ) {
493
+        $classe .= ' item-tri_actif';
494
+    }
495
+
496
+    // Lien
497
+    $balise = lien_ou_expose($url, $libelle, false, $classe);
498
+
499
+    return $balise;
500 500
 }
501 501
 
502 502
 
@@ -512,7 +512,7 @@  discard block
 block discarded – undo
512 512
  * @return string
513 513
  */
514 514
 function tri_protege_champ($t) {
515
-	return preg_replace(',[^\s\w.+\[\]],', '', $t);
515
+    return preg_replace(',[^\s\w.+\[\]],', '', $t);
516 516
 }
517 517
 
518 518
 /**
@@ -525,43 +525,43 @@  discard block
 block discarded – undo
525 525
  * @return string
526 526
  */
527 527
 function tri_champ_order($t, $from = null, $senstri = '') {
528
-	if (strncmp($t, 'multi ', 6) == 0) {
529
-		return 'multi' . $senstri;
530
-	}
531
-
532
-	$champ = $t;
533
-
534
-	$prefixe = '';
535
-	foreach (['num ', 'sinum '] as $p) {
536
-		if (strpos($t, $p) === 0) {
537
-			$champ = substr($t, strlen($p));
538
-			$prefixe = $p;
539
-		}
540
-	}
541
-
542
-	// enlever les autres espaces non evacues par tri_protege_champ
543
-	$champ = preg_replace(',\s,', '', $champ);
544
-
545
-	if (is_array($from)) {
546
-		$trouver_table = charger_fonction('trouver_table', 'base');
547
-		foreach ($from as $idt => $table_sql) {
548
-			if (
549
-				$desc = $trouver_table($table_sql)
550
-				and isset($desc['field'][$champ])
551
-			) {
552
-				$champ = "$idt.$champ";
553
-				break;
554
-			}
555
-		}
556
-	}
557
-	switch ($prefixe) {
558
-		case 'num ':
559
-			return "CASE( 0+$champ ) WHEN 0 THEN 1 ELSE 0 END{$senstri}, 0+$champ{$senstri}";
560
-		case 'sinum ':
561
-			return "CASE( 0+$champ ) WHEN 0 THEN 1 ELSE 0 END{$senstri}";
562
-		default:
563
-			return $champ . $senstri;
564
-	}
528
+    if (strncmp($t, 'multi ', 6) == 0) {
529
+        return 'multi' . $senstri;
530
+    }
531
+
532
+    $champ = $t;
533
+
534
+    $prefixe = '';
535
+    foreach (['num ', 'sinum '] as $p) {
536
+        if (strpos($t, $p) === 0) {
537
+            $champ = substr($t, strlen($p));
538
+            $prefixe = $p;
539
+        }
540
+    }
541
+
542
+    // enlever les autres espaces non evacues par tri_protege_champ
543
+    $champ = preg_replace(',\s,', '', $champ);
544
+
545
+    if (is_array($from)) {
546
+        $trouver_table = charger_fonction('trouver_table', 'base');
547
+        foreach ($from as $idt => $table_sql) {
548
+            if (
549
+                $desc = $trouver_table($table_sql)
550
+                and isset($desc['field'][$champ])
551
+            ) {
552
+                $champ = "$idt.$champ";
553
+                break;
554
+            }
555
+        }
556
+    }
557
+    switch ($prefixe) {
558
+        case 'num ':
559
+            return "CASE( 0+$champ ) WHEN 0 THEN 1 ELSE 0 END{$senstri}, 0+$champ{$senstri}";
560
+        case 'sinum ':
561
+            return "CASE( 0+$champ ) WHEN 0 THEN 1 ELSE 0 END{$senstri}";
562
+        default:
563
+            return $champ . $senstri;
564
+    }
565 565
 }
566 566
 
567 567
 /**
@@ -575,18 +575,18 @@  discard block
 block discarded – undo
575 575
  * @return string
576 576
  */
577 577
 function tri_champ_select($t) {
578
-	if (strncmp($t, 'multi ', 6) == 0) {
579
-		$t = substr($t, 6);
580
-		$t = preg_replace(',\s,', '', $t);
581
-		$t = sql_multi($t, $GLOBALS['spip_lang']);
582
-
583
-		return $t;
584
-	}
585
-	if (trim($t) == 'hasard') {
586
-		return 'rand() AS hasard';
587
-	}
588
-
589
-	return "''";
578
+    if (strncmp($t, 'multi ', 6) == 0) {
579
+        $t = substr($t, 6);
580
+        $t = preg_replace(',\s,', '', $t);
581
+        $t = sql_multi($t, $GLOBALS['spip_lang']);
582
+
583
+        return $t;
584
+    }
585
+    if (trim($t) == 'hasard') {
586
+        return 'rand() AS hasard';
587
+    }
588
+
589
+    return "''";
590 590
 }
591 591
 
592 592
 /**
@@ -598,16 +598,16 @@  discard block
 block discarded – undo
598 598
  * @return string
599 599
  */
600 600
 function formate_liste_critere_par_ordre_liste($valeurs, $serveur = '') {
601
-	if (!is_array($valeurs)) {
602
-		return '';
603
-	}
604
-	$f = sql_serveur('quote', $serveur, true);
605
-	if (!is_string($f) or !$f) {
606
-		return '';
607
-	}
608
-	$valeurs = implode(',', array_map($f, array_unique($valeurs)));
609
-
610
-	return $valeurs;
601
+    if (!is_array($valeurs)) {
602
+        return '';
603
+    }
604
+    $f = sql_serveur('quote', $serveur, true);
605
+    if (!is_string($f) or !$f) {
606
+        return '';
607
+    }
608
+    $valeurs = implode(',', array_map($f, array_unique($valeurs)));
609
+
610
+    return $valeurs;
611 611
 }
612 612
 
613 613
 /**
@@ -630,20 +630,20 @@  discard block
 block discarded – undo
630 630
  *     Valeur $defaut sinon.
631 631
  **/
632 632
 function appliquer_filtre_sinon($arg, $filtre, $args, $defaut = '') {
633
-	// Si c'est un filtre d'image, on utilise image_filtrer()
634
-	// Attention : les 2 premiers arguments sont inversés dans ce cas
635
-	if (trouver_filtre_matrice($filtre) and substr($filtre, 0, 6) == 'image_') {
636
-		include_spip('inc/filtres_images_lib_mini');
637
-		$args[1] = $args[0];
638
-		$args[0] = $filtre;
639
-		return image_graver(image_filtrer($args));
640
-	}
641
-
642
-	$f = chercher_filtre($filtre);
643
-	if (!$f) {
644
-		return $defaut;
645
-	}
646
-	array_shift($args); // enlever $arg
647
-	array_shift($args); // enlever $filtre
648
-	return $f($arg, ...$args);
633
+    // Si c'est un filtre d'image, on utilise image_filtrer()
634
+    // Attention : les 2 premiers arguments sont inversés dans ce cas
635
+    if (trouver_filtre_matrice($filtre) and substr($filtre, 0, 6) == 'image_') {
636
+        include_spip('inc/filtres_images_lib_mini');
637
+        $args[1] = $args[0];
638
+        $args[0] = $filtre;
639
+        return image_graver(image_filtrer($args));
640
+    }
641
+
642
+    $f = chercher_filtre($filtre);
643
+    if (!$f) {
644
+        return $defaut;
645
+    }
646
+    array_shift($args); // enlever $arg
647
+    array_shift($args); // enlever $filtre
648
+    return $f($arg, ...$args);
649 649
 }
Please login to merge, or discard this patch.
ecrire/inc/filtres.php 1 patch
Indentation   +2476 added lines, -2476 removed lines patch added patch discarded remove patch
@@ -16,7 +16,7 @@  discard block
 block discarded – undo
16 16
  * @package SPIP\Core\Filtres
17 17
  **/
18 18
 if (!defined('_ECRIRE_INC_VERSION')) {
19
-	return;
19
+    return;
20 20
 }
21 21
 
22 22
 include_spip('inc/charsets');
@@ -42,8 +42,8 @@  discard block
 block discarded – undo
42 42
  * @return string Fonction PHP correspondante du filtre
43 43
  */
44 44
 function charger_filtre($fonc, $default = 'filtre_identite_dist') {
45
-	include_fichiers_fonctions(); // inclure les fichiers fonctions
46
-	return chercher_filtre($fonc, $default);
45
+    include_fichiers_fonctions(); // inclure les fichiers fonctions
46
+    return chercher_filtre($fonc, $default);
47 47
 }
48 48
 
49 49
 /**
@@ -53,7 +53,7 @@  discard block
 block discarded – undo
53 53
  * @return string Texte
54 54
  **/
55 55
 function filtre_identite_dist($texte) {
56
- return $texte;
56
+    return $texte;
57 57
 }
58 58
 
59 59
 /**
@@ -77,33 +77,33 @@  discard block
 block discarded – undo
77 77
  *     Fonction PHP correspondante du filtre demandé
78 78
  */
79 79
 function chercher_filtre($fonc, $default = null) {
80
-	if (!$fonc) {
81
-		return $default;
82
-	}
83
-	// Cas des types mime, sans confondre avec les appels de fonction de classe
84
-	// Foo::Bar
85
-	// qui peuvent etre avec un namespace : space\Foo::Bar
86
-	if (preg_match(',^[\w]+/,', $fonc)) {
87
-		$nom = preg_replace(',\W,', '_', $fonc);
88
-		$f = chercher_filtre($nom);
89
-		// cas du sous-type MIME sans filtre associe, passer au type:
90
-		// si filtre_text_plain pas defini, passe a filtre_text
91
-		if (!$f and $nom !== $fonc) {
92
-			$f = chercher_filtre(preg_replace(',\W.*$,', '', $fonc));
93
-		}
94
-
95
-		return $f;
96
-	}
97
-
98
-	include_fichiers_fonctions();
99
-	foreach (['filtre_' . $fonc, 'filtre_' . $fonc . '_dist', $fonc] as $f) {
100
-		trouver_filtre_matrice($f); // charge des fichiers spécifiques éventuels
101
-		if (is_callable($f)) {
102
-			return $f;
103
-		}
104
-	}
105
-
106
-	return $default;
80
+    if (!$fonc) {
81
+        return $default;
82
+    }
83
+    // Cas des types mime, sans confondre avec les appels de fonction de classe
84
+    // Foo::Bar
85
+    // qui peuvent etre avec un namespace : space\Foo::Bar
86
+    if (preg_match(',^[\w]+/,', $fonc)) {
87
+        $nom = preg_replace(',\W,', '_', $fonc);
88
+        $f = chercher_filtre($nom);
89
+        // cas du sous-type MIME sans filtre associe, passer au type:
90
+        // si filtre_text_plain pas defini, passe a filtre_text
91
+        if (!$f and $nom !== $fonc) {
92
+            $f = chercher_filtre(preg_replace(',\W.*$,', '', $fonc));
93
+        }
94
+
95
+        return $f;
96
+    }
97
+
98
+    include_fichiers_fonctions();
99
+    foreach (['filtre_' . $fonc, 'filtre_' . $fonc . '_dist', $fonc] as $f) {
100
+        trouver_filtre_matrice($f); // charge des fichiers spécifiques éventuels
101
+        if (is_callable($f)) {
102
+            return $f;
103
+        }
104
+    }
105
+
106
+    return $default;
107 107
 }
108 108
 
109 109
 /**
@@ -147,8 +147,8 @@  discard block
 block discarded – undo
147 147
  *     Chaîne vide sinon.
148 148
  **/
149 149
 function appliquer_filtre($arg, $filtre) {
150
-	$args = func_get_args();
151
-	return appliquer_filtre_sinon($arg, $filtre, $args, '');
150
+    $args = func_get_args();
151
+    return appliquer_filtre_sinon($arg, $filtre, $args, '');
152 152
 }
153 153
 
154 154
 /**
@@ -173,8 +173,8 @@  discard block
 block discarded – undo
173 173
  *     Texte d'origine sinon
174 174
  **/
175 175
 function appliquer_si_filtre($arg, $filtre) {
176
-	$args = func_get_args();
177
-	return appliquer_filtre_sinon($arg, $filtre, $args, $arg);
176
+    $args = func_get_args();
177
+    return appliquer_filtre_sinon($arg, $filtre, $args, $arg);
178 178
 }
179 179
 
180 180
 /**
@@ -190,12 +190,12 @@  discard block
 block discarded – undo
190 190
  *     Version de SPIP
191 191
  **/
192 192
 function spip_version() {
193
-	$version = $GLOBALS['spip_version_affichee'];
194
-	if ($vcs_version = version_vcs_courante(_DIR_RACINE)) {
195
-		$version .= " $vcs_version";
196
-	}
193
+    $version = $GLOBALS['spip_version_affichee'];
194
+    if ($vcs_version = version_vcs_courante(_DIR_RACINE)) {
195
+        $version .= " $vcs_version";
196
+    }
197 197
 
198
-	return $version;
198
+    return $version;
199 199
 }
200 200
 
201 201
 /**
@@ -207,11 +207,11 @@  discard block
 block discarded – undo
207 207
  * @return string
208 208
  */
209 209
 function header_silencieux($version): string {
210
-	if (isset($GLOBALS['spip_header_silencieux']) && (bool) $GLOBALS['spip_header_silencieux']) {
211
-		$version = '';
212
-	}
210
+    if (isset($GLOBALS['spip_header_silencieux']) && (bool) $GLOBALS['spip_header_silencieux']) {
211
+        $version = '';
212
+    }
213 213
 
214
-	return (string) $version;
214
+    return (string) $version;
215 215
 }
216 216
 
217 217
 /**
@@ -224,19 +224,19 @@  discard block
 block discarded – undo
224 224
  *    - string|null si $raw = false
225 225
  */
226 226
 function version_vcs_courante($dir, $raw = false) {
227
-	$desc = decrire_version_git($dir);
228
-	if ($desc === null) {
229
-		$desc = decrire_version_svn($dir);
230
-	}
231
-	if ($desc === null or $raw) {
232
-		return $desc;
233
-	}
234
-	// affichage "GIT [master: abcdef]"
235
-	$commit = $desc['commit_short'] ?? $desc['commit'];
236
-	if ($desc['branch']) {
237
-		$commit = $desc['branch'] . ': ' . $commit;
238
-	}
239
-	return "{$desc['vcs']} [$commit]";
227
+    $desc = decrire_version_git($dir);
228
+    if ($desc === null) {
229
+        $desc = decrire_version_svn($dir);
230
+    }
231
+    if ($desc === null or $raw) {
232
+        return $desc;
233
+    }
234
+    // affichage "GIT [master: abcdef]"
235
+    $commit = $desc['commit_short'] ?? $desc['commit'];
236
+    if ($desc['branch']) {
237
+        $commit = $desc['branch'] . ': ' . $commit;
238
+    }
239
+    return "{$desc['vcs']} [$commit]";
240 240
 }
241 241
 
242 242
 /**
@@ -248,24 +248,24 @@  discard block
 block discarded – undo
248 248
  *      array ['branch' => xx, 'commit' => yy] sinon.
249 249
  **/
250 250
 function decrire_version_git($dir) {
251
-	if (!$dir) {
252
-		$dir = '.';
253
-	}
251
+    if (!$dir) {
252
+        $dir = '.';
253
+    }
254 254
 
255
-	// version installee par GIT
256
-	if (lire_fichier($dir . '/.git/HEAD', $c)) {
257
-		$currentHead = trim(substr($c, 4));
258
-		if (lire_fichier($dir . '/.git/' . $currentHead, $hash)) {
259
-			return [
260
-				'vcs' => 'GIT',
261
-				'branch' => basename($currentHead),
262
-				'commit' => trim($hash),
263
-				'commit_short' => substr(trim($hash), 0, 8),
264
-			];
265
-		}
266
-	}
255
+    // version installee par GIT
256
+    if (lire_fichier($dir . '/.git/HEAD', $c)) {
257
+        $currentHead = trim(substr($c, 4));
258
+        if (lire_fichier($dir . '/.git/' . $currentHead, $hash)) {
259
+            return [
260
+                'vcs' => 'GIT',
261
+                'branch' => basename($currentHead),
262
+                'commit' => trim($hash),
263
+                'commit_short' => substr(trim($hash), 0, 8),
264
+            ];
265
+        }
266
+    }
267 267
 
268
-	return null;
268
+    return null;
269 269
 }
270 270
 
271 271
 
@@ -278,25 +278,25 @@  discard block
 block discarded – undo
278 278
  *      array ['commit' => yy, 'date' => xx, 'author' => xx] sinon.
279 279
  **/
280 280
 function decrire_version_svn($dir) {
281
-	if (!$dir) {
282
-		$dir = '.';
283
-	}
284
-	// version installee par SVN
285
-	if (file_exists($dir . '/.svn/wc.db') && class_exists(\SQLite3::class)) {
286
-		$db = new SQLite3($dir . '/.svn/wc.db');
287
-		$result = $db->query('SELECT changed_revision FROM nodes WHERE local_relpath = "" LIMIT 1');
288
-		if ($result) {
289
-			$row = $result->fetchArray();
290
-			if ($row['changed_revision'] != '') {
291
-				return [
292
-					'vcs' => 'SVN',
293
-					'branch' => '',
294
-					'commit' => $row['changed_revision'],
295
-				];
296
-			}
297
-		}
298
-	}
299
-	return null;
281
+    if (!$dir) {
282
+        $dir = '.';
283
+    }
284
+    // version installee par SVN
285
+    if (file_exists($dir . '/.svn/wc.db') && class_exists(\SQLite3::class)) {
286
+        $db = new SQLite3($dir . '/.svn/wc.db');
287
+        $result = $db->query('SELECT changed_revision FROM nodes WHERE local_relpath = "" LIMIT 1');
288
+        if ($result) {
289
+            $row = $result->fetchArray();
290
+            if ($row['changed_revision'] != '') {
291
+                return [
292
+                    'vcs' => 'SVN',
293
+                    'branch' => '',
294
+                    'commit' => $row['changed_revision'],
295
+                ];
296
+            }
297
+        }
298
+    }
299
+    return null;
300 300
 }
301 301
 
302 302
 // La matrice est necessaire pour ne filtrer _que_ des fonctions definies dans filtres_images
@@ -343,18 +343,18 @@  discard block
 block discarded – undo
343 343
  *     Code HTML retourné par le filtre
344 344
  **/
345 345
 function filtrer($filtre) {
346
-	$tous = func_get_args();
347
-	if (trouver_filtre_matrice($filtre) and substr($filtre, 0, 6) == 'image_') {
348
-		return image_filtrer($tous);
349
-	} elseif ($f = chercher_filtre($filtre)) {
350
-		array_shift($tous);
351
-		return $f(...$tous);
352
-	} else {
353
-		// le filtre n'existe pas, on provoque une erreur
354
-		$msg = ['zbug_erreur_filtre', ['filtre' => texte_script($filtre)]];
355
-		erreur_squelette($msg);
356
-		return '';
357
-	}
346
+    $tous = func_get_args();
347
+    if (trouver_filtre_matrice($filtre) and substr($filtre, 0, 6) == 'image_') {
348
+        return image_filtrer($tous);
349
+    } elseif ($f = chercher_filtre($filtre)) {
350
+        array_shift($tous);
351
+        return $f(...$tous);
352
+    } else {
353
+        // le filtre n'existe pas, on provoque une erreur
354
+        $msg = ['zbug_erreur_filtre', ['filtre' => texte_script($filtre)]];
355
+        erreur_squelette($msg);
356
+        return '';
357
+    }
358 358
 }
359 359
 
360 360
 /**
@@ -371,11 +371,11 @@  discard block
 block discarded – undo
371 371
  * @return bool true si on trouve le filtre dans la matrice, false sinon.
372 372
  */
373 373
 function trouver_filtre_matrice($filtre) {
374
-	if (isset($GLOBALS['spip_matrice'][$filtre]) and is_string($f = $GLOBALS['spip_matrice'][$filtre])) {
375
-		find_in_path($f, '', true);
376
-		$GLOBALS['spip_matrice'][$filtre] = true;
377
-	}
378
-	return !empty($GLOBALS['spip_matrice'][$filtre]);
374
+    if (isset($GLOBALS['spip_matrice'][$filtre]) and is_string($f = $GLOBALS['spip_matrice'][$filtre])) {
375
+        find_in_path($f, '', true);
376
+        $GLOBALS['spip_matrice'][$filtre] = true;
377
+    }
378
+    return !empty($GLOBALS['spip_matrice'][$filtre]);
379 379
 }
380 380
 
381 381
 
@@ -403,8 +403,8 @@  discard block
 block discarded – undo
403 403
  * @return mixed
404 404
  */
405 405
 function filtre_set(&$Pile, $val, $key, $continue = null) {
406
-	$Pile['vars'][$key] = $val;
407
-	return $continue ? $val : '';
406
+    $Pile['vars'][$key] = $val;
407
+    return $continue ? $val : '';
408 408
 }
409 409
 
410 410
 /**
@@ -430,8 +430,8 @@  discard block
 block discarded – undo
430 430
  * @return string|mixed Retourne `$val` si `$continue` présent, sinon ''.
431 431
  */
432 432
 function filtre_setenv(&$Pile, $val, $key, $continue = null) {
433
-	$Pile[0][$key] = $val;
434
-	return $continue ? $val : '';
433
+    $Pile[0][$key] = $val;
434
+    return $continue ? $val : '';
435 435
 }
436 436
 
437 437
 /**
@@ -440,8 +440,8 @@  discard block
 block discarded – undo
440 440
  * @return string
441 441
  */
442 442
 function filtre_sanitize_env(&$Pile, $keys) {
443
-	$Pile[0] = spip_sanitize_from_request($Pile[0], $keys);
444
-	return '';
443
+    $Pile[0] = spip_sanitize_from_request($Pile[0], $keys);
444
+    return '';
445 445
 }
446 446
 
447 447
 
@@ -464,18 +464,18 @@  discard block
 block discarded – undo
464 464
  * @return mixed Retourne la valeur (sans la modifier).
465 465
  */
466 466
 function filtre_debug($val, $key = null) {
467
-	$debug = (
468
-		is_null($key) ? '' : (var_export($key, true) . ' = ')
469
-		) . var_export($val, true);
467
+    $debug = (
468
+        is_null($key) ? '' : (var_export($key, true) . ' = ')
469
+        ) . var_export($val, true);
470 470
 
471
-	include_spip('inc/autoriser');
472
-	if (autoriser('webmestre')) {
473
-		echo "<div class='spip_debug'>\n", $debug, "</div>\n";
474
-	}
471
+    include_spip('inc/autoriser');
472
+    if (autoriser('webmestre')) {
473
+        echo "<div class='spip_debug'>\n", $debug, "</div>\n";
474
+    }
475 475
 
476
-	spip_log($debug, 'debug');
476
+    spip_log($debug, 'debug');
477 477
 
478
-	return $val;
478
+    return $val;
479 479
 }
480 480
 
481 481
 
@@ -505,84 +505,84 @@  discard block
 block discarded – undo
505 505
  *     Texte qui a reçu les filtres
506 506
  **/
507 507
 function image_filtrer($args) {
508
-	$filtre = array_shift($args); # enlever $filtre
509
-	$texte = array_shift($args);
510
-	if ($texte === null || !strlen($texte)) {
511
-		return '';
512
-	}
513
-	find_in_path('filtres_images_mini.php', 'inc/', true);
514
-	statut_effacer_images_temporaires(true); // activer la suppression des images temporaires car le compilo finit la chaine par un image_graver
515
-	// Cas du nom de fichier local
516
-	$is_file = trim($texte);
517
-	if (
518
-		strpos(substr($is_file, strlen(_DIR_RACINE)), '..') !== false
519
-		  or strpbrk($is_file, "<>\n\r\t") !== false
520
-		  or strpos($is_file, '/') === 0
521
-	) {
522
-		$is_file = false;
523
-	}
524
-	if ($is_file) {
525
-		$is_local_file = function ($path) {
526
-			if (strpos($path, '?') !== false) {
527
-				$path = supprimer_timestamp($path);
528
-				// remove ?24px added by find_in_theme on .svg files
529
-				$path = preg_replace(',\?[[:digit:]]+(px)$,', '', $path);
530
-			}
531
-			return file_exists($path);
532
-		};
533
-		if ($is_local_file($is_file) or tester_url_absolue($is_file)) {
534
-			$res = $filtre("<img src='$is_file' />", ...$args);
535
-			statut_effacer_images_temporaires(false); // desactiver pour les appels hors compilo
536
-			return $res;
537
-		}
538
-	}
539
-
540
-	// Cas general : trier toutes les images, avec eventuellement leur <span>
541
-	if (
542
-		preg_match_all(
543
-			',(<([a-z]+) [^<>]*spip_documents[^<>]*>)?\s*(<img\s.*>),UimsS',
544
-			$texte,
545
-			$tags,
546
-			PREG_SET_ORDER
547
-		)
548
-	) {
549
-		foreach ($tags as $tag) {
550
-			$class = extraire_attribut($tag[3], 'class');
551
-			if (
552
-				!$class or
553
-				(strpos($class, 'filtre_inactif') === false
554
-					// compat historique a virer en 3.2
555
-					and strpos($class, 'no_image_filtrer') === false)
556
-			) {
557
-				if ($reduit = $filtre($tag[3], ...$args)) {
558
-					// En cas de span spip_documents, modifier le style=...width:
559
-					if ($tag[1]) {
560
-						$w = extraire_attribut($reduit, 'width');
561
-						if (!$w and preg_match(',width:\s*(\d+)px,S', extraire_attribut($reduit, 'style'), $regs)) {
562
-							$w = $regs[1];
563
-						}
564
-						if ($w and ($style = extraire_attribut($tag[1], 'style'))) {
565
-							$style = preg_replace(',width:\s*\d+px,S', "width:${w}px", $style);
566
-							$replace = inserer_attribut($tag[1], 'style', $style);
567
-							$texte = str_replace($tag[1], $replace, $texte);
568
-						}
569
-					}
570
-					// traiter aussi un eventuel mouseover
571
-					if ($mouseover = extraire_attribut($reduit, 'onmouseover')) {
572
-						if (preg_match(",this[.]src=['\"]([^'\"]+)['\"],ims", $mouseover, $match)) {
573
-							$srcover = $match[1];
574
-							$srcover_filter = $filtre("<img src='" . $match[1] . "' />", ...$args);
575
-							$srcover_filter = extraire_attribut($srcover_filter, 'src');
576
-							$reduit = str_replace($srcover, $srcover_filter, $reduit);
577
-						}
578
-					}
579
-					$texte = str_replace($tag[3], $reduit, $texte);
580
-				}
581
-			}
582
-		}
583
-	}
584
-	statut_effacer_images_temporaires(false); // desactiver pour les appels hors compilo
585
-	return $texte;
508
+    $filtre = array_shift($args); # enlever $filtre
509
+    $texte = array_shift($args);
510
+    if ($texte === null || !strlen($texte)) {
511
+        return '';
512
+    }
513
+    find_in_path('filtres_images_mini.php', 'inc/', true);
514
+    statut_effacer_images_temporaires(true); // activer la suppression des images temporaires car le compilo finit la chaine par un image_graver
515
+    // Cas du nom de fichier local
516
+    $is_file = trim($texte);
517
+    if (
518
+        strpos(substr($is_file, strlen(_DIR_RACINE)), '..') !== false
519
+          or strpbrk($is_file, "<>\n\r\t") !== false
520
+          or strpos($is_file, '/') === 0
521
+    ) {
522
+        $is_file = false;
523
+    }
524
+    if ($is_file) {
525
+        $is_local_file = function ($path) {
526
+            if (strpos($path, '?') !== false) {
527
+                $path = supprimer_timestamp($path);
528
+                // remove ?24px added by find_in_theme on .svg files
529
+                $path = preg_replace(',\?[[:digit:]]+(px)$,', '', $path);
530
+            }
531
+            return file_exists($path);
532
+        };
533
+        if ($is_local_file($is_file) or tester_url_absolue($is_file)) {
534
+            $res = $filtre("<img src='$is_file' />", ...$args);
535
+            statut_effacer_images_temporaires(false); // desactiver pour les appels hors compilo
536
+            return $res;
537
+        }
538
+    }
539
+
540
+    // Cas general : trier toutes les images, avec eventuellement leur <span>
541
+    if (
542
+        preg_match_all(
543
+            ',(<([a-z]+) [^<>]*spip_documents[^<>]*>)?\s*(<img\s.*>),UimsS',
544
+            $texte,
545
+            $tags,
546
+            PREG_SET_ORDER
547
+        )
548
+    ) {
549
+        foreach ($tags as $tag) {
550
+            $class = extraire_attribut($tag[3], 'class');
551
+            if (
552
+                !$class or
553
+                (strpos($class, 'filtre_inactif') === false
554
+                    // compat historique a virer en 3.2
555
+                    and strpos($class, 'no_image_filtrer') === false)
556
+            ) {
557
+                if ($reduit = $filtre($tag[3], ...$args)) {
558
+                    // En cas de span spip_documents, modifier le style=...width:
559
+                    if ($tag[1]) {
560
+                        $w = extraire_attribut($reduit, 'width');
561
+                        if (!$w and preg_match(',width:\s*(\d+)px,S', extraire_attribut($reduit, 'style'), $regs)) {
562
+                            $w = $regs[1];
563
+                        }
564
+                        if ($w and ($style = extraire_attribut($tag[1], 'style'))) {
565
+                            $style = preg_replace(',width:\s*\d+px,S', "width:${w}px", $style);
566
+                            $replace = inserer_attribut($tag[1], 'style', $style);
567
+                            $texte = str_replace($tag[1], $replace, $texte);
568
+                        }
569
+                    }
570
+                    // traiter aussi un eventuel mouseover
571
+                    if ($mouseover = extraire_attribut($reduit, 'onmouseover')) {
572
+                        if (preg_match(",this[.]src=['\"]([^'\"]+)['\"],ims", $mouseover, $match)) {
573
+                            $srcover = $match[1];
574
+                            $srcover_filter = $filtre("<img src='" . $match[1] . "' />", ...$args);
575
+                            $srcover_filter = extraire_attribut($srcover_filter, 'src');
576
+                            $reduit = str_replace($srcover, $srcover_filter, $reduit);
577
+                        }
578
+                    }
579
+                    $texte = str_replace($tag[3], $reduit, $texte);
580
+                }
581
+            }
582
+        }
583
+    }
584
+    statut_effacer_images_temporaires(false); // desactiver pour les appels hors compilo
585
+    return $texte;
586 586
 }
587 587
 
588 588
 /**
@@ -599,91 +599,91 @@  discard block
 block discarded – undo
599 599
  **/
600 600
 function infos_image($img, $force_refresh = false) {
601 601
 
602
-	static $largeur_img = [], $hauteur_img = [], $poids_img = [];
603
-	$srcWidth = 0;
604
-	$srcHeight = 0;
605
-	$srcSize = null;
606
-
607
-	$src = extraire_attribut($img, 'src');
608
-
609
-	if (!$src) {
610
-		$src = $img;
611
-	} else {
612
-		$srcWidth = extraire_attribut($img, 'width');
613
-		$srcHeight = extraire_attribut($img, 'height');
614
-	}
615
-
616
-	// ne jamais operer directement sur une image distante pour des raisons de perfo
617
-	// la copie locale a toutes les chances d'etre la ou de resservir
618
-	if (tester_url_absolue($src)) {
619
-		include_spip('inc/distant');
620
-		$fichier = copie_locale($src);
621
-		$src = $fichier ? _DIR_RACINE . $fichier : $src;
622
-	}
623
-	if (($p = strpos($src, '?')) !== false) {
624
-		$src = substr($src, 0, $p);
625
-	}
626
-
627
-	$imagesize = false;
628
-	if (isset($largeur_img[$src]) and !$force_refresh) {
629
-		$srcWidth = $largeur_img[$src];
630
-	}
631
-	if (isset($hauteur_img[$src]) and !$force_refresh) {
632
-		$srcHeight = $hauteur_img[$src];
633
-	}
634
-	if (isset($poids_img[$src]) and !$force_refresh) {
635
-		$srcSize = $poids_img[$src];
636
-	}
637
-	if (!$srcWidth or !$srcHeight or is_null($srcSize)) {
638
-		if (
639
-			file_exists($src)
640
-			and $imagesize = spip_getimagesize($src)
641
-		) {
642
-			if (!$srcWidth) {
643
-				$largeur_img[$src] = $srcWidth = $imagesize[0];
644
-			}
645
-			if (!$srcHeight) {
646
-				$hauteur_img[$src] = $srcHeight = $imagesize[1];
647
-			}
648
-			if (!$srcSize) {
649
-				$poids_img[$src] = filesize($src);
650
-			}
651
-		}
652
-		elseif (strpos($src, '<svg') !== false) {
653
-			include_spip('inc/svg');
654
-			if ($attrs = svg_lire_attributs($src)) {
655
-				[$width, $height, $viewbox] = svg_getimagesize_from_attr($attrs);
656
-				if (!$srcWidth) {
657
-					$largeur_img[$src] = $srcWidth = $width;
658
-				}
659
-				if (!$srcHeight) {
660
-					$hauteur_img[$src] = $srcHeight = $height;
661
-				}
662
-				if (!$srcSize) {
663
-					$poids_img[$src] = $srcSize = strlen($src);
664
-				}
665
-			}
666
-		}
667
-		// $src peut etre une reference a une image temporaire dont a n'a que le log .src
668
-		// on s'y refere, l'image sera reconstruite en temps utile si necessaire
669
-		elseif (
670
-			@file_exists($f = "$src.src")
671
-			and lire_fichier($f, $valeurs)
672
-			and $valeurs = unserialize($valeurs)
673
-		) {
674
-			if (!$srcWidth) {
675
-				$largeur_img[$src] = $srcWidth = $valeurs['largeur_dest'];
676
-			}
677
-			if (!$srcHeight) {
678
-				$hauteur_img[$src] = $srcHeight = $valeurs['hauteur_dest'];
679
-			}
680
-			if (!$srcSize) {
681
-				$poids_img[$src] = $srcSize = 0;
682
-			}
683
-		}
684
-	}
685
-
686
-	return ['hauteur' => $srcHeight, 'largeur' => $srcWidth, 'poids' => $srcSize];
602
+    static $largeur_img = [], $hauteur_img = [], $poids_img = [];
603
+    $srcWidth = 0;
604
+    $srcHeight = 0;
605
+    $srcSize = null;
606
+
607
+    $src = extraire_attribut($img, 'src');
608
+
609
+    if (!$src) {
610
+        $src = $img;
611
+    } else {
612
+        $srcWidth = extraire_attribut($img, 'width');
613
+        $srcHeight = extraire_attribut($img, 'height');
614
+    }
615
+
616
+    // ne jamais operer directement sur une image distante pour des raisons de perfo
617
+    // la copie locale a toutes les chances d'etre la ou de resservir
618
+    if (tester_url_absolue($src)) {
619
+        include_spip('inc/distant');
620
+        $fichier = copie_locale($src);
621
+        $src = $fichier ? _DIR_RACINE . $fichier : $src;
622
+    }
623
+    if (($p = strpos($src, '?')) !== false) {
624
+        $src = substr($src, 0, $p);
625
+    }
626
+
627
+    $imagesize = false;
628
+    if (isset($largeur_img[$src]) and !$force_refresh) {
629
+        $srcWidth = $largeur_img[$src];
630
+    }
631
+    if (isset($hauteur_img[$src]) and !$force_refresh) {
632
+        $srcHeight = $hauteur_img[$src];
633
+    }
634
+    if (isset($poids_img[$src]) and !$force_refresh) {
635
+        $srcSize = $poids_img[$src];
636
+    }
637
+    if (!$srcWidth or !$srcHeight or is_null($srcSize)) {
638
+        if (
639
+            file_exists($src)
640
+            and $imagesize = spip_getimagesize($src)
641
+        ) {
642
+            if (!$srcWidth) {
643
+                $largeur_img[$src] = $srcWidth = $imagesize[0];
644
+            }
645
+            if (!$srcHeight) {
646
+                $hauteur_img[$src] = $srcHeight = $imagesize[1];
647
+            }
648
+            if (!$srcSize) {
649
+                $poids_img[$src] = filesize($src);
650
+            }
651
+        }
652
+        elseif (strpos($src, '<svg') !== false) {
653
+            include_spip('inc/svg');
654
+            if ($attrs = svg_lire_attributs($src)) {
655
+                [$width, $height, $viewbox] = svg_getimagesize_from_attr($attrs);
656
+                if (!$srcWidth) {
657
+                    $largeur_img[$src] = $srcWidth = $width;
658
+                }
659
+                if (!$srcHeight) {
660
+                    $hauteur_img[$src] = $srcHeight = $height;
661
+                }
662
+                if (!$srcSize) {
663
+                    $poids_img[$src] = $srcSize = strlen($src);
664
+                }
665
+            }
666
+        }
667
+        // $src peut etre une reference a une image temporaire dont a n'a que le log .src
668
+        // on s'y refere, l'image sera reconstruite en temps utile si necessaire
669
+        elseif (
670
+            @file_exists($f = "$src.src")
671
+            and lire_fichier($f, $valeurs)
672
+            and $valeurs = unserialize($valeurs)
673
+        ) {
674
+            if (!$srcWidth) {
675
+                $largeur_img[$src] = $srcWidth = $valeurs['largeur_dest'];
676
+            }
677
+            if (!$srcHeight) {
678
+                $hauteur_img[$src] = $srcHeight = $valeurs['hauteur_dest'];
679
+            }
680
+            if (!$srcSize) {
681
+                $poids_img[$src] = $srcSize = 0;
682
+            }
683
+        }
684
+    }
685
+
686
+    return ['hauteur' => $srcHeight, 'largeur' => $srcWidth, 'poids' => $srcSize];
687 687
 }
688 688
 
689 689
 /**
@@ -699,13 +699,13 @@  discard block
 block discarded – undo
699 699
  *     poids
700 700
  **/
701 701
 function poids_image($img, $force_refresh = false) {
702
-	$infos = infos_image($img, $force_refresh);
703
-	return $infos['poids'];
702
+    $infos = infos_image($img, $force_refresh);
703
+    return $infos['poids'];
704 704
 }
705 705
 
706 706
 function taille_image($img, $force_refresh = false) {
707
-	$infos = infos_image($img, $force_refresh);
708
-	return [$infos['hauteur'], $infos['largeur']];
707
+    $infos = infos_image($img, $force_refresh);
708
+    return [$infos['hauteur'], $infos['largeur']];
709 709
 }
710 710
 
711 711
 /**
@@ -722,12 +722,12 @@  discard block
 block discarded – undo
722 722
  *     Largeur en pixels, NULL ou 0 si aucune image.
723 723
  **/
724 724
 function largeur($img) {
725
-	if (!$img) {
726
-		return;
727
-	}
728
-	[$h, $l] = taille_image($img);
725
+    if (!$img) {
726
+        return;
727
+    }
728
+    [$h, $l] = taille_image($img);
729 729
 
730
-	return $l;
730
+    return $l;
731 731
 }
732 732
 
733 733
 /**
@@ -744,12 +744,12 @@  discard block
 block discarded – undo
744 744
  *     Hauteur en pixels, NULL ou 0 si aucune image.
745 745
  **/
746 746
 function hauteur($img) {
747
-	if (!$img) {
748
-		return;
749
-	}
750
-	[$h, $l] = taille_image($img);
747
+    if (!$img) {
748
+        return;
749
+    }
750
+    [$h, $l] = taille_image($img);
751 751
 
752
-	return $h;
752
+    return $h;
753 753
 }
754 754
 
755 755
 
@@ -769,11 +769,11 @@  discard block
 block discarded – undo
769 769
  * @return string
770 770
  **/
771 771
 function corriger_entites_html($texte) {
772
-	if (strpos($texte, '&amp;') === false) {
773
-		return $texte;
774
-	}
772
+    if (strpos($texte, '&amp;') === false) {
773
+        return $texte;
774
+    }
775 775
 
776
-	return preg_replace(',&amp;(#[0-9][0-9][0-9]+;|amp;),iS', '&\1', $texte);
776
+    return preg_replace(',&amp;(#[0-9][0-9][0-9]+;|amp;),iS', '&\1', $texte);
777 777
 }
778 778
 
779 779
 /**
@@ -788,11 +788,11 @@  discard block
 block discarded – undo
788 788
  * @return string
789 789
  **/
790 790
 function corriger_toutes_entites_html($texte) {
791
-	if (strpos($texte, '&amp;') === false) {
792
-		return $texte;
793
-	}
791
+    if (strpos($texte, '&amp;') === false) {
792
+        return $texte;
793
+    }
794 794
 
795
-	return preg_replace(',&amp;(#?[a-z0-9]+;),iS', '&\1', $texte);
795
+    return preg_replace(',&amp;(#?[a-z0-9]+;),iS', '&\1', $texte);
796 796
 }
797 797
 
798 798
 /**
@@ -802,7 +802,7 @@  discard block
 block discarded – undo
802 802
  * @return string
803 803
  **/
804 804
 function proteger_amp($texte) {
805
-	return str_replace('&', '&amp;', $texte);
805
+    return str_replace('&', '&amp;', $texte);
806 806
 }
807 807
 
808 808
 
@@ -833,21 +833,21 @@  discard block
 block discarded – undo
833 833
  * @return mixed|string
834 834
  */
835 835
 function entites_html($texte, $tout = false, $quote = true) {
836
-	if (
837
-		!is_string($texte) or !$texte
838
-		or strpbrk($texte, "&\"'<>") == false
839
-	) {
840
-		return $texte;
841
-	}
842
-	include_spip('inc/texte');
843
-	$flags = ($quote ? ENT_QUOTES : ENT_NOQUOTES);
844
-	$flags |= ENT_HTML401;
845
-	$texte = spip_htmlspecialchars(echappe_retour(echappe_html($texte, '', true), '', 'proteger_amp'), $flags);
846
-	if ($tout) {
847
-		return corriger_toutes_entites_html($texte);
848
-	} else {
849
-		return corriger_entites_html($texte);
850
-	}
836
+    if (
837
+        !is_string($texte) or !$texte
838
+        or strpbrk($texte, "&\"'<>") == false
839
+    ) {
840
+        return $texte;
841
+    }
842
+    include_spip('inc/texte');
843
+    $flags = ($quote ? ENT_QUOTES : ENT_NOQUOTES);
844
+    $flags |= ENT_HTML401;
845
+    $texte = spip_htmlspecialchars(echappe_retour(echappe_html($texte, '', true), '', 'proteger_amp'), $flags);
846
+    if ($tout) {
847
+        return corriger_toutes_entites_html($texte);
848
+    } else {
849
+        return corriger_entites_html($texte);
850
+    }
851 851
 }
852 852
 
853 853
 /**
@@ -866,37 +866,37 @@  discard block
 block discarded – undo
866 866
  *     Texte converti
867 867
  **/
868 868
 function filtrer_entites($texte) {
869
-	if (strpos($texte, '&') === false) {
870
-		return $texte;
871
-	}
872
-	// filtrer
873
-	$texte = html2unicode($texte);
874
-	// remettre le tout dans le charset cible
875
-	$texte = unicode2charset($texte);
876
-	// cas particulier des " et ' qu'il faut filtrer aussi
877
-	// (on le faisait deja avec un &quot;)
878
-	if (strpos($texte, '&#') !== false) {
879
-		$texte = str_replace(['&#039;', '&#39;', '&#034;', '&#34;'], ["'", "'", '"', '"'], $texte);
880
-	}
869
+    if (strpos($texte, '&') === false) {
870
+        return $texte;
871
+    }
872
+    // filtrer
873
+    $texte = html2unicode($texte);
874
+    // remettre le tout dans le charset cible
875
+    $texte = unicode2charset($texte);
876
+    // cas particulier des " et ' qu'il faut filtrer aussi
877
+    // (on le faisait deja avec un &quot;)
878
+    if (strpos($texte, '&#') !== false) {
879
+        $texte = str_replace(['&#039;', '&#39;', '&#034;', '&#34;'], ["'", "'", '"', '"'], $texte);
880
+    }
881 881
 
882
-	return $texte;
882
+    return $texte;
883 883
 }
884 884
 
885 885
 
886 886
 if (!function_exists('filtre_filtrer_entites_dist')) {
887
-	/**
888
-	 * Version sécurisée de filtrer_entites
889
-	 *
890
-	 * @uses interdire_scripts()
891
-	 * @uses filtrer_entites()
892
-	 *
893
-	 * @param string $t
894
-	 * @return string
895
-	 */
896
-	function filtre_filtrer_entites_dist($t) {
897
-		include_spip('inc/texte');
898
-		return interdire_scripts(filtrer_entites($t));
899
-	}
887
+    /**
888
+     * Version sécurisée de filtrer_entites
889
+     *
890
+     * @uses interdire_scripts()
891
+     * @uses filtrer_entites()
892
+     *
893
+     * @param string $t
894
+     * @return string
895
+     */
896
+    function filtre_filtrer_entites_dist($t) {
897
+        include_spip('inc/texte');
898
+        return interdire_scripts(filtrer_entites($t));
899
+    }
900 900
 }
901 901
 
902 902
 
@@ -911,18 +911,18 @@  discard block
 block discarded – undo
911 911
  * @return string|array
912 912
  **/
913 913
 function supprimer_caracteres_illegaux($texte) {
914
-	static $from = "\x0\x1\x2\x3\x4\x5\x6\x7\x8\xB\xC\xE\xF\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1A\x1B\x1C\x1D\x1E\x1F";
915
-	static $to = null;
914
+    static $from = "\x0\x1\x2\x3\x4\x5\x6\x7\x8\xB\xC\xE\xF\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1A\x1B\x1C\x1D\x1E\x1F";
915
+    static $to = null;
916 916
 
917
-	if (is_array($texte)) {
918
-		return array_map('supprimer_caracteres_illegaux', $texte);
919
-	}
917
+    if (is_array($texte)) {
918
+        return array_map('supprimer_caracteres_illegaux', $texte);
919
+    }
920 920
 
921
-	if (!$to) {
922
-		$to = str_repeat('-', strlen($from));
923
-	}
921
+    if (!$to) {
922
+        $to = str_repeat('-', strlen($from));
923
+    }
924 924
 
925
-	return strtr($texte, $from, $to);
925
+    return strtr($texte, $from, $to);
926 926
 }
927 927
 
928 928
 /**
@@ -934,10 +934,10 @@  discard block
 block discarded – undo
934 934
  * @return string|array
935 935
  **/
936 936
 function corriger_caracteres($texte) {
937
-	$texte = corriger_caracteres_windows($texte);
938
-	$texte = supprimer_caracteres_illegaux($texte);
937
+    $texte = corriger_caracteres_windows($texte);
938
+    $texte = supprimer_caracteres_illegaux($texte);
939 939
 
940
-	return $texte;
940
+    return $texte;
941 941
 }
942 942
 
943 943
 /**
@@ -954,44 +954,44 @@  discard block
 block discarded – undo
954 954
  *     Texte encodé pour XML
955 955
  */
956 956
 function texte_backend(string $texte): string {
957
-	if ($texte === '') {
958
-		return '';
959
-	}
957
+    if ($texte === '') {
958
+        return '';
959
+    }
960 960
 
961
-	static $apostrophe = ['&#8217;', "'"]; # n'allouer qu'une fois
961
+    static $apostrophe = ['&#8217;', "'"]; # n'allouer qu'une fois
962 962
 
963
-	// si on a des liens ou des images, les passer en absolu
964
-	$texte = liens_absolus($texte);
963
+    // si on a des liens ou des images, les passer en absolu
964
+    $texte = liens_absolus($texte);
965 965
 
966
-	// echapper les tags &gt; &lt;
967
-	$texte = preg_replace(',&(gt|lt);,S', '&amp;\1;', $texte);
966
+    // echapper les tags &gt; &lt;
967
+    $texte = preg_replace(',&(gt|lt);,S', '&amp;\1;', $texte);
968 968
 
969
-	// importer les &eacute;
970
-	$texte = filtrer_entites($texte);
969
+    // importer les &eacute;
970
+    $texte = filtrer_entites($texte);
971 971
 
972
-	// " -> &quot; et tout ce genre de choses
973
-	$u = $GLOBALS['meta']['pcre_u'];
974
-	$texte = str_replace('&nbsp;', ' ', $texte);
975
-	$texte = preg_replace('/\s{2,}/S' . $u, ' ', $texte);
976
-	// ne pas echapper les sinqle quotes car certains outils de syndication gerent mal
977
-	$texte = entites_html($texte, false, false);
978
-	// mais bien echapper les double quotes !
979
-	$texte = str_replace('"', '&#034;', $texte);
972
+    // " -> &quot; et tout ce genre de choses
973
+    $u = $GLOBALS['meta']['pcre_u'];
974
+    $texte = str_replace('&nbsp;', ' ', $texte);
975
+    $texte = preg_replace('/\s{2,}/S' . $u, ' ', $texte);
976
+    // ne pas echapper les sinqle quotes car certains outils de syndication gerent mal
977
+    $texte = entites_html($texte, false, false);
978
+    // mais bien echapper les double quotes !
979
+    $texte = str_replace('"', '&#034;', $texte);
980 980
 
981
-	// verifier le charset
982
-	$texte = charset2unicode($texte);
981
+    // verifier le charset
982
+    $texte = charset2unicode($texte);
983 983
 
984
-	// Caracteres problematiques en iso-latin 1
985
-	if (isset($GLOBALS['meta']['charset']) and $GLOBALS['meta']['charset'] == 'iso-8859-1') {
986
-		$texte = str_replace(chr(156), '&#156;', $texte);
987
-		$texte = str_replace(chr(140), '&#140;', $texte);
988
-		$texte = str_replace(chr(159), '&#159;', $texte);
989
-	}
984
+    // Caracteres problematiques en iso-latin 1
985
+    if (isset($GLOBALS['meta']['charset']) and $GLOBALS['meta']['charset'] == 'iso-8859-1') {
986
+        $texte = str_replace(chr(156), '&#156;', $texte);
987
+        $texte = str_replace(chr(140), '&#140;', $texte);
988
+        $texte = str_replace(chr(159), '&#159;', $texte);
989
+    }
990 990
 
991
-	// l'apostrophe curly pose probleme a certains lecteure de RSS
992
-	// et le caractere apostrophe alourdit les squelettes avec PHP
993
-	// ==> on les remplace par l'entite HTML
994
-	return str_replace($apostrophe, "'", $texte);
991
+    // l'apostrophe curly pose probleme a certains lecteure de RSS
992
+    // et le caractere apostrophe alourdit les squelettes avec PHP
993
+    // ==> on les remplace par l'entite HTML
994
+    return str_replace($apostrophe, "'", $texte);
995 995
 }
996 996
 
997 997
 /**
@@ -1008,7 +1008,7 @@  discard block
 block discarded – undo
1008 1008
  *     Texte encodé et quote pour XML
1009 1009
  */
1010 1010
 function texte_backendq(string $texte): string {
1011
-	return addslashes(texte_backend($texte));
1011
+    return addslashes(texte_backend($texte));
1012 1012
 }
1013 1013
 
1014 1014
 
@@ -1031,11 +1031,11 @@  discard block
 block discarded – undo
1031 1031
  *     Numéro de titre, sinon chaîne vide
1032 1032
  **/
1033 1033
 function supprimer_numero($texte) {
1034
-	return preg_replace(
1035
-		',^[[:space:]]*([0-9]+)([.)]|' . chr(194) . '?' . chr(176) . ')[[:space:]]+,S',
1036
-		'',
1037
-		$texte
1038
-	);
1034
+    return preg_replace(
1035
+        ',^[[:space:]]*([0-9]+)([.)]|' . chr(194) . '?' . chr(176) . ')[[:space:]]+,S',
1036
+        '',
1037
+        $texte
1038
+    );
1039 1039
 }
1040 1040
 
1041 1041
 /**
@@ -1058,17 +1058,17 @@  discard block
 block discarded – undo
1058 1058
  *     Numéro de titre, sinon chaîne vide
1059 1059
  **/
1060 1060
 function recuperer_numero($texte) {
1061
-	if (
1062
-		preg_match(
1063
-			',^[[:space:]]*([0-9]+)([.)]|' . chr(194) . '?' . chr(176) . ')[[:space:]]+,S',
1064
-			$texte,
1065
-			$regs
1066
-		)
1067
-	) {
1068
-		return strval($regs[1]);
1069
-	} else {
1070
-		return '';
1071
-	}
1061
+    if (
1062
+        preg_match(
1063
+            ',^[[:space:]]*([0-9]+)([.)]|' . chr(194) . '?' . chr(176) . ')[[:space:]]+,S',
1064
+            $texte,
1065
+            $regs
1066
+        )
1067
+    ) {
1068
+        return strval($regs[1]);
1069
+    } else {
1070
+        return '';
1071
+    }
1072 1072
 }
1073 1073
 
1074 1074
 /**
@@ -1095,16 +1095,16 @@  discard block
 block discarded – undo
1095 1095
  *     Texte ou tableau de textes converti
1096 1096
  **/
1097 1097
 function supprimer_tags($texte, $rempl = '') {
1098
-	if ($texte === null) {
1099
-		return '';
1100
-	}
1101
-	$texte = preg_replace(',<(!--|\w|/|!\[endif|!\[if)[^>]*>,US', $rempl, $texte);
1102
-	// ne pas oublier un < final non ferme car coupe
1103
-	$texte = preg_replace(',<(!--|\w|/).*$,US', $rempl, $texte);
1104
-	// mais qui peut aussi etre un simple signe plus petit que
1105
-	$texte = str_replace('<', '&lt;', $texte);
1098
+    if ($texte === null) {
1099
+        return '';
1100
+    }
1101
+    $texte = preg_replace(',<(!--|\w|/|!\[endif|!\[if)[^>]*>,US', $rempl, $texte);
1102
+    // ne pas oublier un < final non ferme car coupe
1103
+    $texte = preg_replace(',<(!--|\w|/).*$,US', $rempl, $texte);
1104
+    // mais qui peut aussi etre un simple signe plus petit que
1105
+    $texte = str_replace('<', '&lt;', $texte);
1106 1106
 
1107
-	return $texte;
1107
+    return $texte;
1108 1108
 }
1109 1109
 
1110 1110
 /**
@@ -1127,9 +1127,9 @@  discard block
 block discarded – undo
1127 1127
  *     Texte converti
1128 1128
  **/
1129 1129
 function echapper_tags($texte, $rempl = '') {
1130
-	$texte = preg_replace('/<([^>]*)>/', "&lt;\\1&gt;", $texte);
1130
+    $texte = preg_replace('/<([^>]*)>/', "&lt;\\1&gt;", $texte);
1131 1131
 
1132
-	return $texte;
1132
+    return $texte;
1133 1133
 }
1134 1134
 
1135 1135
 /**
@@ -1150,18 +1150,18 @@  discard block
 block discarded – undo
1150 1150
  *     Texte converti
1151 1151
  **/
1152 1152
 function textebrut($texte) {
1153
-	$u = $GLOBALS['meta']['pcre_u'];
1154
-	$texte = preg_replace('/\s+/S' . $u, ' ', $texte);
1155
-	$texte = preg_replace('/<(p|br)( [^>]*)?' . '>/iS', "\n\n", $texte);
1156
-	$texte = preg_replace("/^\n+/", '', $texte);
1157
-	$texte = preg_replace("/\n+$/", '', $texte);
1158
-	$texte = preg_replace("/\n +/", "\n", $texte);
1159
-	$texte = supprimer_tags($texte);
1160
-	$texte = preg_replace('/(&nbsp;| )+/S', ' ', $texte);
1161
-	// nettoyer l'apostrophe curly qui pose probleme a certains rss-readers, lecteurs de mail...
1162
-	$texte = str_replace('&#8217;', "'", $texte);
1153
+    $u = $GLOBALS['meta']['pcre_u'];
1154
+    $texte = preg_replace('/\s+/S' . $u, ' ', $texte);
1155
+    $texte = preg_replace('/<(p|br)( [^>]*)?' . '>/iS', "\n\n", $texte);
1156
+    $texte = preg_replace("/^\n+/", '', $texte);
1157
+    $texte = preg_replace("/\n+$/", '', $texte);
1158
+    $texte = preg_replace("/\n +/", "\n", $texte);
1159
+    $texte = supprimer_tags($texte);
1160
+    $texte = preg_replace('/(&nbsp;| )+/S', ' ', $texte);
1161
+    // nettoyer l'apostrophe curly qui pose probleme a certains rss-readers, lecteurs de mail...
1162
+    $texte = str_replace('&#8217;', "'", $texte);
1163 1163
 
1164
-	return $texte;
1164
+    return $texte;
1165 1165
 }
1166 1166
 
1167 1167
 
@@ -1177,23 +1177,23 @@  discard block
 block discarded – undo
1177 1177
  *     Texte avec liens ouvrants
1178 1178
  **/
1179 1179
 function liens_ouvrants($texte) {
1180
-	if (
1181
-		preg_match_all(
1182
-			",(<a\s+[^>]*https?://[^>]*class=[\"']spip_(out|url)\b[^>]+>),imsS",
1183
-			$texte,
1184
-			$liens,
1185
-			PREG_PATTERN_ORDER
1186
-		)
1187
-	) {
1188
-		foreach ($liens[0] as $a) {
1189
-			$rel = 'noopener noreferrer ' . extraire_attribut($a, 'rel');
1190
-			$ablank = inserer_attribut($a, 'rel', $rel);
1191
-			$ablank = inserer_attribut($ablank, 'target', '_blank');
1192
-			$texte = str_replace($a, $ablank, $texte);
1193
-		}
1194
-	}
1195
-
1196
-	return $texte;
1180
+    if (
1181
+        preg_match_all(
1182
+            ",(<a\s+[^>]*https?://[^>]*class=[\"']spip_(out|url)\b[^>]+>),imsS",
1183
+            $texte,
1184
+            $liens,
1185
+            PREG_PATTERN_ORDER
1186
+        )
1187
+    ) {
1188
+        foreach ($liens[0] as $a) {
1189
+            $rel = 'noopener noreferrer ' . extraire_attribut($a, 'rel');
1190
+            $ablank = inserer_attribut($a, 'rel', $rel);
1191
+            $ablank = inserer_attribut($ablank, 'target', '_blank');
1192
+            $texte = str_replace($a, $ablank, $texte);
1193
+        }
1194
+    }
1195
+
1196
+    return $texte;
1197 1197
 }
1198 1198
 
1199 1199
 /**
@@ -1203,22 +1203,22 @@  discard block
 block discarded – undo
1203 1203
  * @return string
1204 1204
  */
1205 1205
 function liens_nofollow($texte) {
1206
-	if (stripos($texte, '<a') === false) {
1207
-		return $texte;
1208
-	}
1206
+    if (stripos($texte, '<a') === false) {
1207
+        return $texte;
1208
+    }
1209 1209
 
1210
-	if (preg_match_all(",<a\b[^>]*>,UimsS", $texte, $regs, PREG_PATTERN_ORDER)) {
1211
-		foreach ($regs[0] as $a) {
1212
-			$rel = extraire_attribut($a, 'rel') ?? '';
1213
-			if (strpos($rel, 'nofollow') === false) {
1214
-				$rel = 'nofollow' . ($rel ? " $rel" : '');
1215
-				$anofollow = inserer_attribut($a, 'rel', $rel);
1216
-				$texte = str_replace($a, $anofollow, $texte);
1217
-			}
1218
-		}
1219
-	}
1210
+    if (preg_match_all(",<a\b[^>]*>,UimsS", $texte, $regs, PREG_PATTERN_ORDER)) {
1211
+        foreach ($regs[0] as $a) {
1212
+            $rel = extraire_attribut($a, 'rel') ?? '';
1213
+            if (strpos($rel, 'nofollow') === false) {
1214
+                $rel = 'nofollow' . ($rel ? " $rel" : '');
1215
+                $anofollow = inserer_attribut($a, 'rel', $rel);
1216
+                $texte = str_replace($a, $anofollow, $texte);
1217
+            }
1218
+        }
1219
+    }
1220 1220
 
1221
-	return $texte;
1221
+    return $texte;
1222 1222
 }
1223 1223
 
1224 1224
 /**
@@ -1237,12 +1237,12 @@  discard block
 block discarded – undo
1237 1237
  *     Texte sans paraghaphes
1238 1238
  **/
1239 1239
 function PtoBR($texte) {
1240
-	$u = $GLOBALS['meta']['pcre_u'];
1241
-	$texte = preg_replace('@</p>@iS', "\n", $texte);
1242
-	$texte = preg_replace("@<p\b.*>@UiS", '<br />', $texte);
1243
-	$texte = preg_replace('@^\s*<br />@S' . $u, '', $texte);
1240
+    $u = $GLOBALS['meta']['pcre_u'];
1241
+    $texte = preg_replace('@</p>@iS', "\n", $texte);
1242
+    $texte = preg_replace("@<p\b.*>@UiS", '<br />', $texte);
1243
+    $texte = preg_replace('@^\s*<br />@S' . $u, '', $texte);
1244 1244
 
1245
-	return $texte;
1245
+    return $texte;
1246 1246
 }
1247 1247
 
1248 1248
 
@@ -1267,14 +1267,14 @@  discard block
 block discarded – undo
1267 1267
  * @return string Texte encadré du style CSS
1268 1268
  */
1269 1269
 function lignes_longues($texte) {
1270
-	if (!strlen(trim($texte))) {
1271
-		return $texte;
1272
-	}
1273
-	include_spip('inc/texte');
1274
-	$tag = preg_match(',</?(' . _BALISES_BLOCS . ')[>[:space:]],iS', $texte) ?
1275
-		'div' : 'span';
1270
+    if (!strlen(trim($texte))) {
1271
+        return $texte;
1272
+    }
1273
+    include_spip('inc/texte');
1274
+    $tag = preg_match(',</?(' . _BALISES_BLOCS . ')[>[:space:]],iS', $texte) ?
1275
+        'div' : 'span';
1276 1276
 
1277
-	return "<$tag style='word-wrap:break-word;'>$texte</$tag>";
1277
+    return "<$tag style='word-wrap:break-word;'>$texte</$tag>";
1278 1278
 }
1279 1279
 
1280 1280
 /**
@@ -1293,30 +1293,30 @@  discard block
 block discarded – undo
1293 1293
  * @return string Texte en majuscule
1294 1294
  */
1295 1295
 function majuscules($texte) {
1296
-	if (!strlen($texte)) {
1297
-		return '';
1298
-	}
1296
+    if (!strlen($texte)) {
1297
+        return '';
1298
+    }
1299 1299
 
1300
-	// Cas du turc
1301
-	if ($GLOBALS['spip_lang'] == 'tr') {
1302
-		# remplacer hors des tags et des entites
1303
-		if (preg_match_all(',<[^<>]+>|&[^;]+;,S', $texte, $regs, PREG_SET_ORDER)) {
1304
-			foreach ($regs as $n => $match) {
1305
-				$texte = str_replace($match[0], "@@SPIP_TURC$n@@", $texte);
1306
-			}
1307
-		}
1300
+    // Cas du turc
1301
+    if ($GLOBALS['spip_lang'] == 'tr') {
1302
+        # remplacer hors des tags et des entites
1303
+        if (preg_match_all(',<[^<>]+>|&[^;]+;,S', $texte, $regs, PREG_SET_ORDER)) {
1304
+            foreach ($regs as $n => $match) {
1305
+                $texte = str_replace($match[0], "@@SPIP_TURC$n@@", $texte);
1306
+            }
1307
+        }
1308 1308
 
1309
-		$texte = str_replace('i', '&#304;', $texte);
1309
+        $texte = str_replace('i', '&#304;', $texte);
1310 1310
 
1311
-		if ($regs) {
1312
-			foreach ($regs as $n => $match) {
1313
-				$texte = str_replace("@@SPIP_TURC$n@@", $match[0], $texte);
1314
-			}
1315
-		}
1316
-	}
1311
+        if ($regs) {
1312
+            foreach ($regs as $n => $match) {
1313
+                $texte = str_replace("@@SPIP_TURC$n@@", $match[0], $texte);
1314
+            }
1315
+        }
1316
+    }
1317 1317
 
1318
-	// Cas general
1319
-	return "<span style='text-transform: uppercase;'>$texte</span>";
1318
+    // Cas general
1319
+    return "<span style='text-transform: uppercase;'>$texte</span>";
1320 1320
 }
1321 1321
 
1322 1322
 /**
@@ -1334,29 +1334,29 @@  discard block
 block discarded – undo
1334 1334
  * @return string
1335 1335
  **/
1336 1336
 function taille_en_octets($taille) {
1337
-	if (!defined('_KILOBYTE')) {
1338
-		/**
1339
-		 * Définit le nombre d'octets dans un Kilobyte
1340
-		 *
1341
-		 * @var int
1342
-		 **/
1343
-		define('_KILOBYTE', 1024);
1344
-	}
1337
+    if (!defined('_KILOBYTE')) {
1338
+        /**
1339
+         * Définit le nombre d'octets dans un Kilobyte
1340
+         *
1341
+         * @var int
1342
+         **/
1343
+        define('_KILOBYTE', 1024);
1344
+    }
1345 1345
 
1346
-	if ($taille < 1) {
1347
-		return '';
1348
-	}
1349
-	if ($taille < _KILOBYTE) {
1350
-		$taille = _T('taille_octets', ['taille' => $taille]);
1351
-	} elseif ($taille < _KILOBYTE * _KILOBYTE) {
1352
-		$taille = _T('taille_ko', ['taille' => round($taille / _KILOBYTE, 1)]);
1353
-	} elseif ($taille < _KILOBYTE * _KILOBYTE * _KILOBYTE) {
1354
-		$taille = _T('taille_mo', ['taille' => round($taille / _KILOBYTE / _KILOBYTE, 1)]);
1355
-	} else {
1356
-		$taille = _T('taille_go', ['taille' => round($taille / _KILOBYTE / _KILOBYTE / _KILOBYTE, 2)]);
1357
-	}
1346
+    if ($taille < 1) {
1347
+        return '';
1348
+    }
1349
+    if ($taille < _KILOBYTE) {
1350
+        $taille = _T('taille_octets', ['taille' => $taille]);
1351
+    } elseif ($taille < _KILOBYTE * _KILOBYTE) {
1352
+        $taille = _T('taille_ko', ['taille' => round($taille / _KILOBYTE, 1)]);
1353
+    } elseif ($taille < _KILOBYTE * _KILOBYTE * _KILOBYTE) {
1354
+        $taille = _T('taille_mo', ['taille' => round($taille / _KILOBYTE / _KILOBYTE, 1)]);
1355
+    } else {
1356
+        $taille = _T('taille_go', ['taille' => round($taille / _KILOBYTE / _KILOBYTE / _KILOBYTE, 2)]);
1357
+    }
1358 1358
 
1359
-	return $taille;
1359
+    return $taille;
1360 1360
 }
1361 1361
 
1362 1362
 
@@ -1378,21 +1378,21 @@  discard block
 block discarded – undo
1378 1378
  *     Texte prêt pour être utilisé en attribut HTML
1379 1379
  **/
1380 1380
 function attribut_html(?string $texte, $textebrut = true): string {
1381
-	if ($texte === null) {
1382
-		return '';
1383
-	}
1384
-	$u = $GLOBALS['meta']['pcre_u'];
1385
-	if ($textebrut) {
1386
-		$texte = preg_replace([",\n,", ',\s(?=\s),msS' . $u], [' ', ''], textebrut($texte));
1387
-	}
1388
-	$texte = texte_backend($texte);
1389
-	$texte = str_replace(["'", '"'], ['&#039;', '&#034;'], $texte);
1381
+    if ($texte === null) {
1382
+        return '';
1383
+    }
1384
+    $u = $GLOBALS['meta']['pcre_u'];
1385
+    if ($textebrut) {
1386
+        $texte = preg_replace([",\n,", ',\s(?=\s),msS' . $u], [' ', ''], textebrut($texte));
1387
+    }
1388
+    $texte = texte_backend($texte);
1389
+    $texte = str_replace(["'", '"'], ['&#039;', '&#034;'], $texte);
1390 1390
 
1391
-	return preg_replace(
1392
-		['/&(amp;|#38;)/', '/&(?![A-Za-z]{0,4}\w{2,3};|#[0-9]{2,5};)/'],
1393
-		['&', '&#38;'],
1394
-		$texte
1395
-	);
1391
+    return preg_replace(
1392
+        ['/&(amp;|#38;)/', '/&(?![A-Za-z]{0,4}\w{2,3};|#[0-9]{2,5};)/'],
1393
+        ['&', '&#38;'],
1394
+        $texte
1395
+    );
1396 1396
 }
1397 1397
 
1398 1398
 
@@ -1412,15 +1412,15 @@  discard block
 block discarded – undo
1412 1412
  *     URL ou chaîne vide
1413 1413
  **/
1414 1414
 function vider_url(?string $url, $entites = true): string {
1415
-	if ($url === null) {
1416
-		return '';
1417
-	}
1418
-	# un message pour abs_url
1419
-	$GLOBALS['mode_abs_url'] = 'url';
1420
-	$url = trim($url);
1421
-	$r = ',^(?:' . _PROTOCOLES_STD . '):?/?/?$,iS';
1415
+    if ($url === null) {
1416
+        return '';
1417
+    }
1418
+    # un message pour abs_url
1419
+    $GLOBALS['mode_abs_url'] = 'url';
1420
+    $url = trim($url);
1421
+    $r = ',^(?:' . _PROTOCOLES_STD . '):?/?/?$,iS';
1422 1422
 
1423
-	return preg_match($r, $url) ? '' : ($entites ? entites_html($url) : $url);
1423
+    return preg_match($r, $url) ? '' : ($entites ? entites_html($url) : $url);
1424 1424
 }
1425 1425
 
1426 1426
 
@@ -1435,10 +1435,10 @@  discard block
 block discarded – undo
1435 1435
  * @return string Adresse email maquillée
1436 1436
  **/
1437 1437
 function antispam($texte) {
1438
-	include_spip('inc/acces');
1439
-	$masque = creer_pass_aleatoire(3);
1438
+    include_spip('inc/acces');
1439
+    $masque = creer_pass_aleatoire(3);
1440 1440
 
1441
-	return preg_replace('/@/', " $masque ", $texte);
1441
+    return preg_replace('/@/', " $masque ", $texte);
1442 1442
 }
1443 1443
 
1444 1444
 /**
@@ -1470,8 +1470,8 @@  discard block
 block discarded – undo
1470 1470
  *     True si on a le droit d'accès, false sinon.
1471 1471
  **/
1472 1472
 function filtre_securiser_acces_dist($id_auteur, $cle, $dir, $op = '', $args = '') {
1473
-	include_spip('inc/acces');
1474
-	return securiser_acces_low_sec($id_auteur, $cle, $op ? "$dir $op $args" : $dir);
1473
+    include_spip('inc/acces');
1474
+    return securiser_acces_low_sec($id_auteur, $cle, $op ? "$dir $op $args" : $dir);
1475 1475
 }
1476 1476
 
1477 1477
 /**
@@ -1496,13 +1496,13 @@  discard block
 block discarded – undo
1496 1496
  *     Retourne $texte, sinon $sinon.
1497 1497
  **/
1498 1498
 function sinon($texte, $sinon = '') {
1499
-	if ($texte) {
1500
-		return $texte;
1501
-	} elseif (is_scalar($texte) and strlen($texte)) {
1502
-		return $texte;
1503
-	} else {
1504
-		return $sinon;
1505
-	}
1499
+    if ($texte) {
1500
+        return $texte;
1501
+    } elseif (is_scalar($texte) and strlen($texte)) {
1502
+        return $texte;
1503
+    } else {
1504
+        return $sinon;
1505
+    }
1506 1506
 }
1507 1507
 
1508 1508
 /**
@@ -1526,7 +1526,7 @@  discard block
 block discarded – undo
1526 1526
  * @return mixed
1527 1527
  **/
1528 1528
 function choixsivide($a, $vide, $pasvide) {
1529
-	return $a ? $pasvide : $vide;
1529
+    return $a ? $pasvide : $vide;
1530 1530
 }
1531 1531
 
1532 1532
 /**
@@ -1550,7 +1550,7 @@  discard block
 block discarded – undo
1550 1550
  * @return mixed
1551 1551
  **/
1552 1552
 function choixsiegal($a1, $a2, $v, $f) {
1553
-	return ($a1 == $a2) ? $v : $f;
1553
+    return ($a1 == $a2) ? $v : $f;
1554 1554
 }
1555 1555
 
1556 1556
 //
@@ -1569,13 +1569,13 @@  discard block
 block discarded – undo
1569 1569
  * @return string
1570 1570
  **/
1571 1571
 function filtrer_ical($texte) {
1572
-	#include_spip('inc/charsets');
1573
-	$texte = html2unicode($texte);
1574
-	$texte = unicode2charset(charset2unicode($texte, $GLOBALS['meta']['charset']), 'utf-8');
1575
-	$texte = preg_replace("/\n/", ' ', $texte);
1576
-	$texte = preg_replace('/,/', '\,', $texte);
1572
+    #include_spip('inc/charsets');
1573
+    $texte = html2unicode($texte);
1574
+    $texte = unicode2charset(charset2unicode($texte, $GLOBALS['meta']['charset']), 'utf-8');
1575
+    $texte = preg_replace("/\n/", ' ', $texte);
1576
+    $texte = preg_replace('/,/', '\,', $texte);
1577 1577
 
1578
-	return $texte;
1578
+    return $texte;
1579 1579
 }
1580 1580
 
1581 1581
 
@@ -1600,54 +1600,54 @@  discard block
 block discarded – undo
1600 1600
  * @return string
1601 1601
  **/
1602 1602
 function post_autobr($texte, $delim = "\n_ ") {
1603
-	if (!function_exists('echappe_html')) {
1604
-		include_spip('inc/texte_mini');
1605
-	}
1606
-	$texte = str_replace("\r\n", "\r", $texte);
1607
-	$texte = str_replace("\r", "\n", $texte);
1608
-
1609
-	if (preg_match(",\n+$,", $texte, $fin)) {
1610
-		$texte = substr($texte, 0, -strlen($fin = $fin[0]));
1611
-	} else {
1612
-		$fin = '';
1613
-	}
1614
-
1615
-	$texte = echappe_html($texte, '', true);
1616
-
1617
-	// echapper les modeles
1618
-	if (strpos($texte, '<') !== false) {
1619
-		include_spip('inc/lien');
1620
-		if (defined('_PREG_MODELE')) {
1621
-			$preg_modeles = '@' . _PREG_MODELE . '@imsS';
1622
-			$texte = echappe_html($texte, '', true, $preg_modeles);
1623
-		}
1624
-	}
1625
-
1626
-	$debut = '';
1627
-	$suite = $texte;
1628
-	while ($t = strpos('-' . $suite, "\n", 1)) {
1629
-		$debut .= substr($suite, 0, $t - 1);
1630
-		$suite = substr($suite, $t);
1631
-		$car = substr($suite, 0, 1);
1632
-		if (
1633
-			($car <> '-') and ($car <> '_') and ($car <> "\n") and ($car <> '|') and ($car <> '}')
1634
-			and !preg_match(',^\s*(\n|</?(quote|div|dl|dt|dd)|$),S', ($suite))
1635
-			and !preg_match(',</?(quote|div|dl|dt|dd)> *$,iS', $debut)
1636
-		) {
1637
-			$debut .= $delim;
1638
-		} else {
1639
-			$debut .= "\n";
1640
-		}
1641
-		if (preg_match(",^\n+,", $suite, $regs)) {
1642
-			$debut .= $regs[0];
1643
-			$suite = substr($suite, strlen($regs[0]));
1644
-		}
1645
-	}
1646
-	$texte = $debut . $suite;
1647
-
1648
-	$texte = echappe_retour($texte);
1649
-
1650
-	return $texte . $fin;
1603
+    if (!function_exists('echappe_html')) {
1604
+        include_spip('inc/texte_mini');
1605
+    }
1606
+    $texte = str_replace("\r\n", "\r", $texte);
1607
+    $texte = str_replace("\r", "\n", $texte);
1608
+
1609
+    if (preg_match(",\n+$,", $texte, $fin)) {
1610
+        $texte = substr($texte, 0, -strlen($fin = $fin[0]));
1611
+    } else {
1612
+        $fin = '';
1613
+    }
1614
+
1615
+    $texte = echappe_html($texte, '', true);
1616
+
1617
+    // echapper les modeles
1618
+    if (strpos($texte, '<') !== false) {
1619
+        include_spip('inc/lien');
1620
+        if (defined('_PREG_MODELE')) {
1621
+            $preg_modeles = '@' . _PREG_MODELE . '@imsS';
1622
+            $texte = echappe_html($texte, '', true, $preg_modeles);
1623
+        }
1624
+    }
1625
+
1626
+    $debut = '';
1627
+    $suite = $texte;
1628
+    while ($t = strpos('-' . $suite, "\n", 1)) {
1629
+        $debut .= substr($suite, 0, $t - 1);
1630
+        $suite = substr($suite, $t);
1631
+        $car = substr($suite, 0, 1);
1632
+        if (
1633
+            ($car <> '-') and ($car <> '_') and ($car <> "\n") and ($car <> '|') and ($car <> '}')
1634
+            and !preg_match(',^\s*(\n|</?(quote|div|dl|dt|dd)|$),S', ($suite))
1635
+            and !preg_match(',</?(quote|div|dl|dt|dd)> *$,iS', $debut)
1636
+        ) {
1637
+            $debut .= $delim;
1638
+        } else {
1639
+            $debut .= "\n";
1640
+        }
1641
+        if (preg_match(",^\n+,", $suite, $regs)) {
1642
+            $debut .= $regs[0];
1643
+            $suite = substr($suite, strlen($regs[0]));
1644
+        }
1645
+    }
1646
+    $texte = $debut . $suite;
1647
+
1648
+    $texte = echappe_retour($texte);
1649
+
1650
+    return $texte . $fin;
1651 1651
 }
1652 1652
 
1653 1653
 
@@ -1688,47 +1688,47 @@  discard block
 block discarded – undo
1688 1688
  * @return string
1689 1689
  **/
1690 1690
 function extraire_idiome($letexte, $lang = null, $options = []) {
1691
-	static $traduire = false;
1692
-	if (
1693
-		$letexte
1694
-		and preg_match_all(_EXTRAIRE_IDIOME, $letexte, $regs, PREG_SET_ORDER)
1695
-	) {
1696
-		if (!$traduire) {
1697
-			$traduire = charger_fonction('traduire', 'inc');
1698
-			include_spip('inc/lang');
1699
-		}
1700
-		if (!$lang) {
1701
-			$lang = $GLOBALS['spip_lang'];
1702
-		}
1703
-		// Compatibilité avec le prototype de fonction précédente qui utilisait un boolean
1704
-		if (is_bool($options)) {
1705
-			$options = ['echappe_span' => $options];
1706
-		}
1707
-		if (!isset($options['echappe_span'])) {
1708
-			$options = array_merge($options, ['echappe_span' => false]);
1709
-		}
1710
-
1711
-		foreach ($regs as $reg) {
1712
-			$cle = ($reg[1] ? $reg[1] . ':' : '') . $reg[2];
1713
-			$desc = $traduire($cle, $lang, true);
1714
-			$l = $desc->langue;
1715
-			// si pas de traduction, on laissera l'écriture de l'idiome entier dans le texte.
1716
-			if (strlen($desc->texte ?? '')) {
1717
-				$trad = code_echappement($desc->texte, 'idiome', false);
1718
-				if ($l !== $lang) {
1719
-					$trad = str_replace("'", '"', inserer_attribut($trad, 'lang', $l));
1720
-				}
1721
-				if (lang_dir($l) !== lang_dir($lang)) {
1722
-					$trad = str_replace("'", '"', inserer_attribut($trad, 'dir', lang_dir($l)));
1723
-				}
1724
-				if (!$options['echappe_span']) {
1725
-					$trad = echappe_retour($trad, 'idiome');
1726
-				}
1727
-				$letexte = str_replace($reg[0], $trad, $letexte);
1728
-			}
1729
-		}
1730
-	}
1731
-	return $letexte;
1691
+    static $traduire = false;
1692
+    if (
1693
+        $letexte
1694
+        and preg_match_all(_EXTRAIRE_IDIOME, $letexte, $regs, PREG_SET_ORDER)
1695
+    ) {
1696
+        if (!$traduire) {
1697
+            $traduire = charger_fonction('traduire', 'inc');
1698
+            include_spip('inc/lang');
1699
+        }
1700
+        if (!$lang) {
1701
+            $lang = $GLOBALS['spip_lang'];
1702
+        }
1703
+        // Compatibilité avec le prototype de fonction précédente qui utilisait un boolean
1704
+        if (is_bool($options)) {
1705
+            $options = ['echappe_span' => $options];
1706
+        }
1707
+        if (!isset($options['echappe_span'])) {
1708
+            $options = array_merge($options, ['echappe_span' => false]);
1709
+        }
1710
+
1711
+        foreach ($regs as $reg) {
1712
+            $cle = ($reg[1] ? $reg[1] . ':' : '') . $reg[2];
1713
+            $desc = $traduire($cle, $lang, true);
1714
+            $l = $desc->langue;
1715
+            // si pas de traduction, on laissera l'écriture de l'idiome entier dans le texte.
1716
+            if (strlen($desc->texte ?? '')) {
1717
+                $trad = code_echappement($desc->texte, 'idiome', false);
1718
+                if ($l !== $lang) {
1719
+                    $trad = str_replace("'", '"', inserer_attribut($trad, 'lang', $l));
1720
+                }
1721
+                if (lang_dir($l) !== lang_dir($lang)) {
1722
+                    $trad = str_replace("'", '"', inserer_attribut($trad, 'dir', lang_dir($l)));
1723
+                }
1724
+                if (!$options['echappe_span']) {
1725
+                    $trad = echappe_retour($trad, 'idiome');
1726
+                }
1727
+                $letexte = str_replace($reg[0], $trad, $letexte);
1728
+            }
1729
+        }
1730
+    }
1731
+    return $letexte;
1732 1732
 }
1733 1733
 
1734 1734
 /**
@@ -1780,68 +1780,68 @@  discard block
 block discarded – undo
1780 1780
  **/
1781 1781
 function extraire_multi($letexte, $lang = null, $options = []) {
1782 1782
 
1783
-	if (
1784
-		$letexte
1785
-		and preg_match_all(_EXTRAIRE_MULTI, $letexte, $regs, PREG_SET_ORDER)
1786
-	) {
1787
-		if (!$lang) {
1788
-			$lang = $GLOBALS['spip_lang'];
1789
-		}
1790
-
1791
-		// Compatibilité avec le prototype de fonction précédente qui utilisait un boolean
1792
-		if (is_bool($options)) {
1793
-			$options = ['echappe_span' => $options, 'lang_defaut' => _LANGUE_PAR_DEFAUT];
1794
-		}
1795
-		if (!isset($options['echappe_span'])) {
1796
-			$options = array_merge($options, ['echappe_span' => false]);
1797
-		}
1798
-		if (!isset($options['lang_defaut'])) {
1799
-			$options = array_merge($options, ['lang_defaut' => _LANGUE_PAR_DEFAUT]);
1800
-		}
1801
-
1802
-		include_spip('inc/lang');
1803
-		foreach ($regs as $reg) {
1804
-			// chercher la version de la langue courante
1805
-			$trads = extraire_trads($reg[1]);
1806
-			if ($l = approcher_langue($trads, $lang)) {
1807
-				$trad = $trads[$l];
1808
-			} else {
1809
-				if ($options['lang_defaut'] == 'aucune') {
1810
-					$trad = '';
1811
-				} else {
1812
-					// langue absente, prendre le fr ou une langue précisée (meme comportement que inc/traduire.php)
1813
-					// ou la premiere dispo
1814
-					// mais typographier le texte selon les regles de celle-ci
1815
-					// Attention aux blocs multi sur plusieurs lignes
1816
-					if (!$l = approcher_langue($trads, $options['lang_defaut'])) {
1817
-						$l = key($trads);
1818
-					}
1819
-					$trad = $trads[$l];
1820
-					$typographie = charger_fonction(lang_typo($l), 'typographie');
1821
-					$trad = $typographie($trad);
1822
-					// Tester si on echappe en span ou en div
1823
-					// il ne faut pas echapper en div si propre produit un seul paragraphe
1824
-					include_spip('inc/texte');
1825
-					$trad_propre = preg_replace(',(^<p[^>]*>|</p>$),Uims', '', propre($trad));
1826
-					$mode = preg_match(',</?(' . _BALISES_BLOCS . ')[>[:space:]],iS', $trad_propre) ? 'div' : 'span';
1827
-					if ($mode === 'div') {
1828
-						$trad = rtrim($trad) . "\n\n";
1829
-					}
1830
-					$trad = code_echappement($trad, 'multi', false, $mode);
1831
-					$trad = str_replace("'", '"', inserer_attribut($trad, 'lang', $l));
1832
-					if (lang_dir($l) !== lang_dir($lang)) {
1833
-						$trad = str_replace("'", '"', inserer_attribut($trad, 'dir', lang_dir($l)));
1834
-					}
1835
-					if (!$options['echappe_span']) {
1836
-						$trad = echappe_retour($trad, 'multi');
1837
-					}
1838
-				}
1839
-			}
1840
-			$letexte = str_replace($reg[0], $trad, $letexte);
1841
-		}
1842
-	}
1843
-
1844
-	return $letexte;
1783
+    if (
1784
+        $letexte
1785
+        and preg_match_all(_EXTRAIRE_MULTI, $letexte, $regs, PREG_SET_ORDER)
1786
+    ) {
1787
+        if (!$lang) {
1788
+            $lang = $GLOBALS['spip_lang'];
1789
+        }
1790
+
1791
+        // Compatibilité avec le prototype de fonction précédente qui utilisait un boolean
1792
+        if (is_bool($options)) {
1793
+            $options = ['echappe_span' => $options, 'lang_defaut' => _LANGUE_PAR_DEFAUT];
1794
+        }
1795
+        if (!isset($options['echappe_span'])) {
1796
+            $options = array_merge($options, ['echappe_span' => false]);
1797
+        }
1798
+        if (!isset($options['lang_defaut'])) {
1799
+            $options = array_merge($options, ['lang_defaut' => _LANGUE_PAR_DEFAUT]);
1800
+        }
1801
+
1802
+        include_spip('inc/lang');
1803
+        foreach ($regs as $reg) {
1804
+            // chercher la version de la langue courante
1805
+            $trads = extraire_trads($reg[1]);
1806
+            if ($l = approcher_langue($trads, $lang)) {
1807
+                $trad = $trads[$l];
1808
+            } else {
1809
+                if ($options['lang_defaut'] == 'aucune') {
1810
+                    $trad = '';
1811
+                } else {
1812
+                    // langue absente, prendre le fr ou une langue précisée (meme comportement que inc/traduire.php)
1813
+                    // ou la premiere dispo
1814
+                    // mais typographier le texte selon les regles de celle-ci
1815
+                    // Attention aux blocs multi sur plusieurs lignes
1816
+                    if (!$l = approcher_langue($trads, $options['lang_defaut'])) {
1817
+                        $l = key($trads);
1818
+                    }
1819
+                    $trad = $trads[$l];
1820
+                    $typographie = charger_fonction(lang_typo($l), 'typographie');
1821
+                    $trad = $typographie($trad);
1822
+                    // Tester si on echappe en span ou en div
1823
+                    // il ne faut pas echapper en div si propre produit un seul paragraphe
1824
+                    include_spip('inc/texte');
1825
+                    $trad_propre = preg_replace(',(^<p[^>]*>|</p>$),Uims', '', propre($trad));
1826
+                    $mode = preg_match(',</?(' . _BALISES_BLOCS . ')[>[:space:]],iS', $trad_propre) ? 'div' : 'span';
1827
+                    if ($mode === 'div') {
1828
+                        $trad = rtrim($trad) . "\n\n";
1829
+                    }
1830
+                    $trad = code_echappement($trad, 'multi', false, $mode);
1831
+                    $trad = str_replace("'", '"', inserer_attribut($trad, 'lang', $l));
1832
+                    if (lang_dir($l) !== lang_dir($lang)) {
1833
+                        $trad = str_replace("'", '"', inserer_attribut($trad, 'dir', lang_dir($l)));
1834
+                    }
1835
+                    if (!$options['echappe_span']) {
1836
+                        $trad = echappe_retour($trad, 'multi');
1837
+                    }
1838
+                }
1839
+            }
1840
+            $letexte = str_replace($reg[0], $trad, $letexte);
1841
+        }
1842
+    }
1843
+
1844
+    return $letexte;
1845 1845
 }
1846 1846
 
1847 1847
 /**
@@ -1857,21 +1857,21 @@  discard block
 block discarded – undo
1857 1857
  *     Peut retourner un code de langue vide, lorsqu'un texte par défaut est indiqué.
1858 1858
  **/
1859 1859
 function extraire_trads($bloc) {
1860
-	$trads = [];
1861
-	$lang = '';
1860
+    $trads = [];
1861
+    $lang = '';
1862 1862
 // ce reg fait planter l'analyse multi s'il y a de l'{italique} dans le champ
1863 1863
 //	while (preg_match("/^(.*?)[{\[]([a-z_]+)[}\]]/siS", $bloc, $regs)) {
1864
-	while (preg_match('/^(.*?)[\[]([a-z_]+)[\]]/siS', $bloc, $regs)) {
1865
-		$texte = trim($regs[1]);
1866
-		if ($texte or $lang) {
1867
-			$trads[$lang] = $texte;
1868
-		}
1869
-		$bloc = substr($bloc, strlen($regs[0]));
1870
-		$lang = $regs[2];
1871
-	}
1872
-	$trads[$lang] = $bloc;
1864
+    while (preg_match('/^(.*?)[\[]([a-z_]+)[\]]/siS', $bloc, $regs)) {
1865
+        $texte = trim($regs[1]);
1866
+        if ($texte or $lang) {
1867
+            $trads[$lang] = $texte;
1868
+        }
1869
+        $bloc = substr($bloc, strlen($regs[0]));
1870
+        $lang = $regs[2];
1871
+    }
1872
+    $trads[$lang] = $bloc;
1873 1873
 
1874
-	return $trads;
1874
+    return $trads;
1875 1875
 }
1876 1876
 
1877 1877
 
@@ -1882,7 +1882,7 @@  discard block
 block discarded – undo
1882 1882
  * @return string L'initiale en majuscule
1883 1883
  */
1884 1884
 function filtre_initiale($nom) {
1885
-	return spip_substr(trim(strtoupper(extraire_multi($nom))), 0, 1);
1885
+    return spip_substr(trim(strtoupper(extraire_multi($nom))), 0, 1);
1886 1886
 }
1887 1887
 
1888 1888
 
@@ -1927,33 +1927,33 @@  discard block
 block discarded – undo
1927 1927
  *      - null (interne) : si on empile
1928 1928
  **/
1929 1929
 function unique($donnee, $famille = '', $cpt = false) {
1930
-	static $mem = [];
1931
-	// permettre de vider la pile et de la restaurer
1932
-	// pour le calcul de introduction...
1933
-	if ($famille == '_spip_raz_') {
1934
-		$tmp = $mem;
1935
-		$mem = [];
1936
-
1937
-		return $tmp;
1938
-	} elseif ($famille == '_spip_set_') {
1939
-		$mem = $donnee;
1940
-
1941
-		return;
1942
-	}
1943
-	// eviter une notice
1944
-	if (!isset($mem[$famille])) {
1945
-		$mem[$famille] = [];
1946
-	}
1947
-	if ($cpt) {
1948
-		return is_countable($mem[$famille]) ? count($mem[$famille]) : 0;
1949
-	}
1950
-	// eviter une notice
1951
-	if (!isset($mem[$famille][$donnee])) {
1952
-		$mem[$famille][$donnee] = 0;
1953
-	}
1954
-	if (!($mem[$famille][$donnee]++)) {
1955
-		return $donnee;
1956
-	}
1930
+    static $mem = [];
1931
+    // permettre de vider la pile et de la restaurer
1932
+    // pour le calcul de introduction...
1933
+    if ($famille == '_spip_raz_') {
1934
+        $tmp = $mem;
1935
+        $mem = [];
1936
+
1937
+        return $tmp;
1938
+    } elseif ($famille == '_spip_set_') {
1939
+        $mem = $donnee;
1940
+
1941
+        return;
1942
+    }
1943
+    // eviter une notice
1944
+    if (!isset($mem[$famille])) {
1945
+        $mem[$famille] = [];
1946
+    }
1947
+    if ($cpt) {
1948
+        return is_countable($mem[$famille]) ? count($mem[$famille]) : 0;
1949
+    }
1950
+    // eviter une notice
1951
+    if (!isset($mem[$famille][$donnee])) {
1952
+        $mem[$famille][$donnee] = 0;
1953
+    }
1954
+    if (!($mem[$famille][$donnee]++)) {
1955
+        return $donnee;
1956
+    }
1957 1957
 }
1958 1958
 
1959 1959
 
@@ -1983,20 +1983,20 @@  discard block
 block discarded – undo
1983 1983
  *     Une des valeurs en fonction du compteur.
1984 1984
  **/
1985 1985
 function alterner($i, ...$args) {
1986
-	// recuperer les arguments (attention fonctions un peu space)
1987
-	$num = count($args);
1986
+    // recuperer les arguments (attention fonctions un peu space)
1987
+    $num = count($args);
1988 1988
 
1989
-	if ($num === 1 && is_array($args[0])) {
1990
-		// un tableau de valeur dont les cles sont numerotees de 0 a num
1991
-		$args = array_values($args[0]);
1992
-		$num = count($args);
1993
-	}
1989
+    if ($num === 1 && is_array($args[0])) {
1990
+        // un tableau de valeur dont les cles sont numerotees de 0 a num
1991
+        $args = array_values($args[0]);
1992
+        $num = count($args);
1993
+    }
1994 1994
 
1995
-	// un index compris entre 0 et num exclus
1996
-	$i = ((intval($i) - 1) % $num); // dans ]-$num;$num[
1997
-	$i = ($i + $num) % $num; // dans [0;$num[
1998
-	// renvoyer le i-ieme argument, modulo le nombre d'arguments
1999
-	return $args[$i];
1995
+    // un index compris entre 0 et num exclus
1996
+    $i = ((intval($i) - 1) % $num); // dans ]-$num;$num[
1997
+    $i = ($i + $num) % $num; // dans [0;$num[
1998
+    // renvoyer le i-ieme argument, modulo le nombre d'arguments
1999
+    return $args[$i];
2000 2000
 }
2001 2001
 
2002 2002
 
@@ -2022,51 +2022,51 @@  discard block
 block discarded – undo
2022 2022
  *     - null lorsque l’attribut n’existe pas.
2023 2023
  **/
2024 2024
 function extraire_attribut($balise, $attribut, $complet = false) {
2025
-	if (is_array($balise)) {
2026
-		array_walk(
2027
-			$balise,
2028
-			function (&$a, $key, $t) {
2029
-				$a = extraire_attribut($a, $t);
2030
-			},
2031
-			$attribut
2032
-		);
2033
-
2034
-		return $balise;
2035
-	}
2036
-	if (
2037
-		$balise
2038
-		&& preg_match(
2039
-			',(^.*?<(?:(?>\s*)(?>[\w:.-]+)(?>(?:=(?:"[^"]*"|\'[^\']*\'|[^\'"]\S*))?))*?)(\s+'
2040
-			. $attribut
2041
-			. '(?:=\s*("[^"]*"|\'[^\']*\'|[^\'"]\S*))?)()((?:[\s/][^>]*)?>.*),isS',
2042
-			$balise,
2043
-			$r
2044
-		)
2045
-	) {
2046
-		if (isset($r[3][0]) and ($r[3][0] == '"' || $r[3][0] == "'")) {
2047
-			$r[4] = substr($r[3], 1, -1);
2048
-			$r[3] = $r[3][0];
2049
-		} elseif ($r[3] !== '') {
2050
-			$r[4] = $r[3];
2051
-			$r[3] = '';
2052
-		} else {
2053
-			$r[4] = trim($r[2]);
2054
-		}
2055
-		$att = $r[4];
2056
-		if (strpos($att, '&#') !== false) {
2057
-			$att = str_replace(['&#039;', '&#39;', '&#034;', '&#34;'], ["'", "'", '"', '"'], $att);
2058
-		}
2059
-		$att = filtrer_entites($att);
2060
-	} else {
2061
-		$att = null;
2062
-		$r = [];
2063
-	}
2064
-
2065
-	if ($complet) {
2066
-		return [$att, $r];
2067
-	} else {
2068
-		return $att;
2069
-	}
2025
+    if (is_array($balise)) {
2026
+        array_walk(
2027
+            $balise,
2028
+            function (&$a, $key, $t) {
2029
+                $a = extraire_attribut($a, $t);
2030
+            },
2031
+            $attribut
2032
+        );
2033
+
2034
+        return $balise;
2035
+    }
2036
+    if (
2037
+        $balise
2038
+        && preg_match(
2039
+            ',(^.*?<(?:(?>\s*)(?>[\w:.-]+)(?>(?:=(?:"[^"]*"|\'[^\']*\'|[^\'"]\S*))?))*?)(\s+'
2040
+            . $attribut
2041
+            . '(?:=\s*("[^"]*"|\'[^\']*\'|[^\'"]\S*))?)()((?:[\s/][^>]*)?>.*),isS',
2042
+            $balise,
2043
+            $r
2044
+        )
2045
+    ) {
2046
+        if (isset($r[3][0]) and ($r[3][0] == '"' || $r[3][0] == "'")) {
2047
+            $r[4] = substr($r[3], 1, -1);
2048
+            $r[3] = $r[3][0];
2049
+        } elseif ($r[3] !== '') {
2050
+            $r[4] = $r[3];
2051
+            $r[3] = '';
2052
+        } else {
2053
+            $r[4] = trim($r[2]);
2054
+        }
2055
+        $att = $r[4];
2056
+        if (strpos($att, '&#') !== false) {
2057
+            $att = str_replace(['&#039;', '&#39;', '&#034;', '&#34;'], ["'", "'", '"', '"'], $att);
2058
+        }
2059
+        $att = filtrer_entites($att);
2060
+    } else {
2061
+        $att = null;
2062
+        $r = [];
2063
+    }
2064
+
2065
+    if ($complet) {
2066
+        return [$att, $r];
2067
+    } else {
2068
+        return $att;
2069
+    }
2070 2070
 }
2071 2071
 
2072 2072
 /**
@@ -2099,41 +2099,41 @@  discard block
 block discarded – undo
2099 2099
  **/
2100 2100
 function inserer_attribut(?string $balise, string $attribut, string $val, bool $proteger = true, bool $vider = false): string {
2101 2101
 
2102
-	if ($balise === null or $balise === '') {
2103
-		return '';
2104
-	}
2102
+    if ($balise === null or $balise === '') {
2103
+        return '';
2104
+    }
2105 2105
 
2106
-	// preparer l'attribut
2107
-	// supprimer les &nbsp; etc mais pas les balises html
2108
-	// qui ont un sens dans un attribut value d'un input
2109
-	if ($proteger) {
2110
-		$val = attribut_html($val, false);
2111
-	}
2106
+    // preparer l'attribut
2107
+    // supprimer les &nbsp; etc mais pas les balises html
2108
+    // qui ont un sens dans un attribut value d'un input
2109
+    if ($proteger) {
2110
+        $val = attribut_html($val, false);
2111
+    }
2112 2112
 
2113
-	// echapper les ' pour eviter tout bug
2114
-	$val = str_replace("'", '&#039;', $val);
2115
-	if ($vider and strlen($val) === 0) {
2116
-		$insert = '';
2117
-	} else {
2118
-		$insert = " $attribut='$val'";
2119
-	}
2113
+    // echapper les ' pour eviter tout bug
2114
+    $val = str_replace("'", '&#039;', $val);
2115
+    if ($vider and strlen($val) === 0) {
2116
+        $insert = '';
2117
+    } else {
2118
+        $insert = " $attribut='$val'";
2119
+    }
2120 2120
 
2121
-	[$old, $r] = extraire_attribut($balise, $attribut, true);
2121
+    [$old, $r] = extraire_attribut($balise, $attribut, true);
2122 2122
 
2123
-	if ($old !== null) {
2124
-		// Remplacer l'ancien attribut du meme nom
2125
-		$balise = $r[1] . $insert . $r[5];
2126
-	} else {
2127
-		// preferer une balise " />" (comme <img />)
2128
-		if (preg_match(',/>,', $balise)) {
2129
-			$balise = preg_replace(',\s?/>,S', $insert . ' />', $balise, 1);
2130
-		} // sinon une balise <a ...> ... </a>
2131
-		else {
2132
-			$balise = preg_replace(',\s?>,S', $insert . '>', $balise, 1);
2133
-		}
2134
-	}
2123
+    if ($old !== null) {
2124
+        // Remplacer l'ancien attribut du meme nom
2125
+        $balise = $r[1] . $insert . $r[5];
2126
+    } else {
2127
+        // preferer une balise " />" (comme <img />)
2128
+        if (preg_match(',/>,', $balise)) {
2129
+            $balise = preg_replace(',\s?/>,S', $insert . ' />', $balise, 1);
2130
+        } // sinon une balise <a ...> ... </a>
2131
+        else {
2132
+            $balise = preg_replace(',\s?>,S', $insert . '>', $balise, 1);
2133
+        }
2134
+    }
2135 2135
 
2136
-	return $balise;
2136
+    return $balise;
2137 2137
 }
2138 2138
 
2139 2139
 /**
@@ -2151,7 +2151,7 @@  discard block
 block discarded – undo
2151 2151
  * @return string Code HTML sans l'attribut
2152 2152
  **/
2153 2153
 function vider_attribut(?string $balise, string $attribut): string {
2154
-	return inserer_attribut($balise, $attribut, '', false, true);
2154
+    return inserer_attribut($balise, $attribut, '', false, true);
2155 2155
 }
2156 2156
 
2157 2157
 /**
@@ -2163,53 +2163,53 @@  discard block
 block discarded – undo
2163 2163
  * @return string
2164 2164
  */
2165 2165
 function modifier_class($balise, $class, $operation = 'ajouter') {
2166
-	if (is_string($class)) {
2167
-		$class = explode(' ', trim($class));
2168
-	}
2169
-	$class = array_filter($class);
2170
-	$class = array_unique($class);
2171
-	if (!$class) {
2172
-		return $balise;
2173
-	}
2174
-
2175
-	// si la ou les classes ont des caracteres invalides on ne fait rien
2176
-	if (preg_match(',[^\w-],', implode('', $class))) {
2177
-		return $balise;
2178
-	}
2179
-
2180
-	$class_courante = extraire_attribut($balise, 'class');
2181
-	$class_new = $class_courante;
2182
-	foreach ($class as $c) {
2183
-		$is_class_presente = false;
2184
-		if (
2185
-			$class_courante
2186
-			and strpos($class_courante, (string) $c) !== false
2187
-			and preg_match('/(^|\s)' . preg_quote($c) . '($|\s)/', $class_courante)
2188
-		) {
2189
-			$is_class_presente = true;
2190
-		}
2191
-		if (
2192
-			in_array($operation, ['ajouter', 'commuter'])
2193
-			and !$is_class_presente
2194
-		) {
2195
-			$class_new = ltrim(rtrim($class_new ?? '') . ' ' . $c);
2196
-		} elseif (
2197
-			in_array($operation, ['supprimer', 'commuter'])
2198
-			and $is_class_presente
2199
-		) {
2200
-			$class_new = trim(preg_replace('/(^|\s)' . preg_quote($c) . '($|\s)/', "\\1", $class_new));
2201
-		}
2202
-	}
2203
-
2204
-	if ($class_new !== $class_courante) {
2205
-		if (strlen($class_new)) {
2206
-			$balise = inserer_attribut($balise, 'class', $class_new);
2207
-		} elseif ($class_courante) {
2208
-			$balise = vider_attribut($balise, 'class');
2209
-		}
2210
-	}
2211
-
2212
-	return $balise;
2166
+    if (is_string($class)) {
2167
+        $class = explode(' ', trim($class));
2168
+    }
2169
+    $class = array_filter($class);
2170
+    $class = array_unique($class);
2171
+    if (!$class) {
2172
+        return $balise;
2173
+    }
2174
+
2175
+    // si la ou les classes ont des caracteres invalides on ne fait rien
2176
+    if (preg_match(',[^\w-],', implode('', $class))) {
2177
+        return $balise;
2178
+    }
2179
+
2180
+    $class_courante = extraire_attribut($balise, 'class');
2181
+    $class_new = $class_courante;
2182
+    foreach ($class as $c) {
2183
+        $is_class_presente = false;
2184
+        if (
2185
+            $class_courante
2186
+            and strpos($class_courante, (string) $c) !== false
2187
+            and preg_match('/(^|\s)' . preg_quote($c) . '($|\s)/', $class_courante)
2188
+        ) {
2189
+            $is_class_presente = true;
2190
+        }
2191
+        if (
2192
+            in_array($operation, ['ajouter', 'commuter'])
2193
+            and !$is_class_presente
2194
+        ) {
2195
+            $class_new = ltrim(rtrim($class_new ?? '') . ' ' . $c);
2196
+        } elseif (
2197
+            in_array($operation, ['supprimer', 'commuter'])
2198
+            and $is_class_presente
2199
+        ) {
2200
+            $class_new = trim(preg_replace('/(^|\s)' . preg_quote($c) . '($|\s)/', "\\1", $class_new));
2201
+        }
2202
+    }
2203
+
2204
+    if ($class_new !== $class_courante) {
2205
+        if (strlen($class_new)) {
2206
+            $balise = inserer_attribut($balise, 'class', $class_new);
2207
+        } elseif ($class_courante) {
2208
+            $balise = vider_attribut($balise, 'class');
2209
+        }
2210
+    }
2211
+
2212
+    return $balise;
2213 2213
 }
2214 2214
 
2215 2215
 /**
@@ -2219,7 +2219,7 @@  discard block
 block discarded – undo
2219 2219
  * @return string
2220 2220
  */
2221 2221
 function ajouter_class($balise, $class) {
2222
-	return modifier_class($balise, $class, 'ajouter');
2222
+    return modifier_class($balise, $class, 'ajouter');
2223 2223
 }
2224 2224
 
2225 2225
 /**
@@ -2229,7 +2229,7 @@  discard block
 block discarded – undo
2229 2229
  * @return string
2230 2230
  */
2231 2231
 function supprimer_class($balise, $class) {
2232
-	return modifier_class($balise, $class, 'supprimer');
2232
+    return modifier_class($balise, $class, 'supprimer');
2233 2233
 }
2234 2234
 
2235 2235
 /**
@@ -2240,7 +2240,7 @@  discard block
 block discarded – undo
2240 2240
  * @return string
2241 2241
  */
2242 2242
 function commuter_class($balise, $class) {
2243
-	return modifier_class($balise, $class, 'commuter');
2243
+    return modifier_class($balise, $class, 'commuter');
2244 2244
 }
2245 2245
 
2246 2246
 /**
@@ -2251,19 +2251,19 @@  discard block
 block discarded – undo
2251 2251
  * @return string
2252 2252
  */
2253 2253
 function tester_config($id, $mode = '') {
2254
-	include_spip('action/inscrire_auteur');
2254
+    include_spip('action/inscrire_auteur');
2255 2255
 
2256
-	return tester_statut_inscription($mode, $id);
2256
+    return tester_statut_inscription($mode, $id);
2257 2257
 }
2258 2258
 
2259 2259
 //
2260 2260
 // Quelques fonctions de calcul arithmetique
2261 2261
 //
2262 2262
 function floatstr($a) {
2263
- return str_replace(',', '.', (string)floatval($a));
2263
+    return str_replace(',', '.', (string)floatval($a));
2264 2264
 }
2265 2265
 function strize($f, $a, $b) {
2266
- return floatstr($f(floatstr($a), floatstr($b)));
2266
+    return floatstr($f(floatstr($a), floatstr($b)));
2267 2267
 }
2268 2268
 
2269 2269
 /**
@@ -2282,7 +2282,7 @@  discard block
 block discarded – undo
2282 2282
  * @return int $a+$b
2283 2283
  **/
2284 2284
 function plus($a, $b) {
2285
-	return $a + $b;
2285
+    return $a + $b;
2286 2286
 }
2287 2287
 function strplus($a, $b) {
2288 2288
 return strize('plus', $a, $b);
@@ -2303,7 +2303,7 @@  discard block
 block discarded – undo
2303 2303
  * @return int $a-$b
2304 2304
  **/
2305 2305
 function moins($a, $b) {
2306
-	return $a - $b;
2306
+    return $a - $b;
2307 2307
 }
2308 2308
 function strmoins($a, $b) {
2309 2309
 return strize('moins', $a, $b);
@@ -2326,7 +2326,7 @@  discard block
 block discarded – undo
2326 2326
  * @return int $a*$b
2327 2327
  **/
2328 2328
 function mult($a, $b) {
2329
-	return $a * $b;
2329
+    return $a * $b;
2330 2330
 }
2331 2331
 function strmult($a, $b) {
2332 2332
 return strize('mult', $a, $b);
@@ -2349,7 +2349,7 @@  discard block
 block discarded – undo
2349 2349
  * @return int $a/$b (ou 0 si $b est nul)
2350 2350
  **/
2351 2351
 function div($a, $b) {
2352
-	return $b ? $a / $b : 0;
2352
+    return $b ? $a / $b : 0;
2353 2353
 }
2354 2354
 function strdiv($a, $b) {
2355 2355
 return strize('div', $a, $b);
@@ -2373,7 +2373,7 @@  discard block
 block discarded – undo
2373 2373
  * @return int ($nb % $mod) + $add
2374 2374
  **/
2375 2375
 function modulo($nb, $mod, $add = 0) {
2376
-	return ($mod ? $nb % $mod : 0) + $add;
2376
+    return ($mod ? $nb % $mod : 0) + $add;
2377 2377
 }
2378 2378
 
2379 2379
 
@@ -2388,26 +2388,26 @@  discard block
 block discarded – undo
2388 2388
  *      - true sinon
2389 2389
  **/
2390 2390
 function nom_acceptable($nom) {
2391
-	$remp2 = [];
2392
-	$remp1 = [];
2393
-	if (!is_string($nom)) {
2394
-		return false;
2395
-	}
2396
-	if (!defined('_TAGS_NOM_AUTEUR')) {
2397
-		define('_TAGS_NOM_AUTEUR', '');
2398
-	}
2399
-	$tags_acceptes = array_unique(explode(',', 'multi,' . _TAGS_NOM_AUTEUR));
2400
-	foreach ($tags_acceptes as $tag) {
2401
-		if (strlen($tag)) {
2402
-			$remp1[] = '<' . trim($tag) . '>';
2403
-			$remp1[] = '</' . trim($tag) . '>';
2404
-			$remp2[] = '\x60' . trim($tag) . '\x61';
2405
-			$remp2[] = '\x60/' . trim($tag) . '\x61';
2406
-		}
2407
-	}
2408
-	$v_nom = str_replace($remp2, $remp1, supprimer_tags(str_replace($remp1, $remp2, $nom)));
2409
-
2410
-	return str_replace('&lt;', '<', $v_nom) == $nom;
2391
+    $remp2 = [];
2392
+    $remp1 = [];
2393
+    if (!is_string($nom)) {
2394
+        return false;
2395
+    }
2396
+    if (!defined('_TAGS_NOM_AUTEUR')) {
2397
+        define('_TAGS_NOM_AUTEUR', '');
2398
+    }
2399
+    $tags_acceptes = array_unique(explode(',', 'multi,' . _TAGS_NOM_AUTEUR));
2400
+    foreach ($tags_acceptes as $tag) {
2401
+        if (strlen($tag)) {
2402
+            $remp1[] = '<' . trim($tag) . '>';
2403
+            $remp1[] = '</' . trim($tag) . '>';
2404
+            $remp2[] = '\x60' . trim($tag) . '\x61';
2405
+            $remp2[] = '\x60/' . trim($tag) . '\x61';
2406
+        }
2407
+    }
2408
+    $v_nom = str_replace($remp2, $remp1, supprimer_tags(str_replace($remp1, $remp2, $nom)));
2409
+
2410
+    return str_replace('&lt;', '<', $v_nom) == $nom;
2411 2411
 }
2412 2412
 
2413 2413
 
@@ -2423,14 +2423,14 @@  discard block
 block discarded – undo
2423 2423
  *      - renvoie un tableau si l'entree est un tableau
2424 2424
  **/
2425 2425
 function email_valide($adresses) {
2426
-	if (is_array($adresses)) {
2427
-		$adresses = array_map('email_valide', $adresses);
2428
-		$adresses = array_filter($adresses);
2429
-		return $adresses;
2430
-	}
2426
+    if (is_array($adresses)) {
2427
+        $adresses = array_map('email_valide', $adresses);
2428
+        $adresses = array_filter($adresses);
2429
+        return $adresses;
2430
+    }
2431 2431
 
2432
-	$email_valide = charger_fonction('email_valide', 'inc');
2433
-	return $email_valide($adresses);
2432
+    $email_valide = charger_fonction('email_valide', 'inc');
2433
+    return $email_valide($adresses);
2434 2434
 }
2435 2435
 
2436 2436
 /**
@@ -2444,29 +2444,29 @@  discard block
 block discarded – undo
2444 2444
  * @return string Texte
2445 2445
  **/
2446 2446
 function afficher_enclosures($tags) {
2447
-	$s = [];
2448
-	foreach (extraire_balises($tags, 'a') as $tag) {
2449
-		if (
2450
-			extraire_attribut($tag, 'rel') == 'enclosure'
2451
-			and $t = extraire_attribut($tag, 'href')
2452
-		) {
2453
-			$s[] = preg_replace(
2454
-				',>[^<]+</a>,S',
2455
-				'>'
2456
-				. http_img_pack(
2457
-					'attachment-16.png',
2458
-					$t,
2459
-					'',
2460
-					$t,
2461
-					['utiliser_suffixe_size' => true]
2462
-				)
2463
-				. '</a>',
2464
-				$tag
2465
-			);
2466
-		}
2467
-	}
2468
-
2469
-	return join('&nbsp;', $s);
2447
+    $s = [];
2448
+    foreach (extraire_balises($tags, 'a') as $tag) {
2449
+        if (
2450
+            extraire_attribut($tag, 'rel') == 'enclosure'
2451
+            and $t = extraire_attribut($tag, 'href')
2452
+        ) {
2453
+            $s[] = preg_replace(
2454
+                ',>[^<]+</a>,S',
2455
+                '>'
2456
+                . http_img_pack(
2457
+                    'attachment-16.png',
2458
+                    $t,
2459
+                    '',
2460
+                    $t,
2461
+                    ['utiliser_suffixe_size' => true]
2462
+                )
2463
+                . '</a>',
2464
+                $tag
2465
+            );
2466
+        }
2467
+    }
2468
+
2469
+    return join('&nbsp;', $s);
2470 2470
 }
2471 2471
 
2472 2472
 /**
@@ -2481,15 +2481,15 @@  discard block
 block discarded – undo
2481 2481
  * @return string Liens trouvés
2482 2482
  **/
2483 2483
 function afficher_tags($tags, $rels = 'tag,directory') {
2484
-	$s = [];
2485
-	foreach (extraire_balises($tags, 'a') as $tag) {
2486
-		$rel = extraire_attribut($tag, 'rel');
2487
-		if (strstr(",$rels,", (string) ",$rel,")) {
2488
-			$s[] = $tag;
2489
-		}
2490
-	}
2484
+    $s = [];
2485
+    foreach (extraire_balises($tags, 'a') as $tag) {
2486
+        $rel = extraire_attribut($tag, 'rel');
2487
+        if (strstr(",$rels,", (string) ",$rel,")) {
2488
+            $s[] = $tag;
2489
+        }
2490
+    }
2491 2491
 
2492
-	return join(', ', $s);
2492
+    return join(', ', $s);
2493 2493
 }
2494 2494
 
2495 2495
 
@@ -2511,21 +2511,21 @@  discard block
 block discarded – undo
2511 2511
  * @return string Tag HTML `<a>` avec microformat.
2512 2512
  **/
2513 2513
 function enclosure2microformat($e) {
2514
-	if (!$url = filtrer_entites(extraire_attribut($e, 'url'))) {
2515
-		$url = filtrer_entites(extraire_attribut($e, 'href'));
2516
-	}
2517
-	$type = extraire_attribut($e, 'type');
2518
-	if (!$length = extraire_attribut($e, 'length')) {
2519
-		# <media:content : longeur dans fileSize. On tente.
2520
-		$length = extraire_attribut($e, 'fileSize');
2521
-	}
2522
-	$fichier = basename($url);
2514
+    if (!$url = filtrer_entites(extraire_attribut($e, 'url'))) {
2515
+        $url = filtrer_entites(extraire_attribut($e, 'href'));
2516
+    }
2517
+    $type = extraire_attribut($e, 'type');
2518
+    if (!$length = extraire_attribut($e, 'length')) {
2519
+        # <media:content : longeur dans fileSize. On tente.
2520
+        $length = extraire_attribut($e, 'fileSize');
2521
+    }
2522
+    $fichier = basename($url);
2523 2523
 
2524
-	return '<a rel="enclosure"'
2525
-	. ($url ? ' href="' . spip_htmlspecialchars($url) . '"' : '')
2526
-	. ($type ? ' type="' . spip_htmlspecialchars($type) . '"' : '')
2527
-	. ($length ? ' title="' . spip_htmlspecialchars($length) . '"' : '')
2528
-	. '>' . $fichier . '</a>';
2524
+    return '<a rel="enclosure"'
2525
+    . ($url ? ' href="' . spip_htmlspecialchars($url) . '"' : '')
2526
+    . ($type ? ' type="' . spip_htmlspecialchars($type) . '"' : '')
2527
+    . ($length ? ' title="' . spip_htmlspecialchars($length) . '"' : '')
2528
+    . '>' . $fichier . '</a>';
2529 2529
 }
2530 2530
 
2531 2531
 /**
@@ -2543,24 +2543,24 @@  discard block
 block discarded – undo
2543 2543
  * @return string Tags RSS `<enclosure>`.
2544 2544
  **/
2545 2545
 function microformat2enclosure($tags) {
2546
-	$enclosures = [];
2547
-	foreach (extraire_balises($tags, 'a') as $e) {
2548
-		if (extraire_attribut($e, 'rel') == 'enclosure') {
2549
-			$url = filtrer_entites(extraire_attribut($e, 'href'));
2550
-			$type = extraire_attribut($e, 'type');
2551
-			if (!$length = intval(extraire_attribut($e, 'title'))) {
2552
-				$length = intval(extraire_attribut($e, 'length'));
2553
-			} # vieux data
2554
-			$fichier = basename($url);
2555
-			$enclosures[] = '<enclosure'
2556
-				. ($url ? ' url="' . spip_htmlspecialchars($url) . '"' : '')
2557
-				. ($type ? ' type="' . spip_htmlspecialchars($type) . '"' : '')
2558
-				. ($length ? ' length="' . $length . '"' : '')
2559
-				. ' />';
2560
-		}
2561
-	}
2546
+    $enclosures = [];
2547
+    foreach (extraire_balises($tags, 'a') as $e) {
2548
+        if (extraire_attribut($e, 'rel') == 'enclosure') {
2549
+            $url = filtrer_entites(extraire_attribut($e, 'href'));
2550
+            $type = extraire_attribut($e, 'type');
2551
+            if (!$length = intval(extraire_attribut($e, 'title'))) {
2552
+                $length = intval(extraire_attribut($e, 'length'));
2553
+            } # vieux data
2554
+            $fichier = basename($url);
2555
+            $enclosures[] = '<enclosure'
2556
+                . ($url ? ' url="' . spip_htmlspecialchars($url) . '"' : '')
2557
+                . ($type ? ' type="' . spip_htmlspecialchars($type) . '"' : '')
2558
+                . ($length ? ' length="' . $length . '"' : '')
2559
+                . ' />';
2560
+        }
2561
+    }
2562 2562
 
2563
-	return join("\n", $enclosures);
2563
+    return join("\n", $enclosures);
2564 2564
 }
2565 2565
 
2566 2566
 
@@ -2576,16 +2576,16 @@  discard block
 block discarded – undo
2576 2576
  * @return string Tags RSS Atom `<dc:subject>`.
2577 2577
  **/
2578 2578
 function tags2dcsubject($tags) {
2579
-	$subjects = '';
2580
-	foreach (extraire_balises($tags, 'a') as $e) {
2581
-		if (extraire_attribut($e, 'rel') == 'tag') {
2582
-			$subjects .= '<dc:subject>'
2583
-				. texte_backend(textebrut($e))
2584
-				. '</dc:subject>' . "\n";
2585
-		}
2586
-	}
2579
+    $subjects = '';
2580
+    foreach (extraire_balises($tags, 'a') as $e) {
2581
+        if (extraire_attribut($e, 'rel') == 'tag') {
2582
+            $subjects .= '<dc:subject>'
2583
+                . texte_backend(textebrut($e))
2584
+                . '</dc:subject>' . "\n";
2585
+        }
2586
+    }
2587 2587
 
2588
-	return $subjects;
2588
+    return $subjects;
2589 2589
 }
2590 2590
 
2591 2591
 /**
@@ -2614,27 +2614,27 @@  discard block
 block discarded – undo
2614 2614
  *     - Tableau de résultats, si tableau en entrée.
2615 2615
  **/
2616 2616
 function extraire_balise($texte, $tag = 'a') {
2617
-	if (is_array($texte)) {
2618
-		array_walk(
2619
-			$texte,
2620
-			function (&$a, $key, $t) {
2621
-				$a = extraire_balise($a, $t);
2622
-			},
2623
-			$tag
2624
-		);
2625
-
2626
-		return $texte;
2627
-	}
2628
-
2629
-	if (
2630
-		preg_match(
2631
-			",<$tag\b[^>]*(/>|>.*</$tag\b[^>]*>|>),UimsS",
2632
-			$texte,
2633
-			$regs
2634
-		)
2635
-	) {
2636
-		return $regs[0];
2637
-	}
2617
+    if (is_array($texte)) {
2618
+        array_walk(
2619
+            $texte,
2620
+            function (&$a, $key, $t) {
2621
+                $a = extraire_balise($a, $t);
2622
+            },
2623
+            $tag
2624
+        );
2625
+
2626
+        return $texte;
2627
+    }
2628
+
2629
+    if (
2630
+        preg_match(
2631
+            ",<$tag\b[^>]*(/>|>.*</$tag\b[^>]*>|>),UimsS",
2632
+            $texte,
2633
+            $regs
2634
+        )
2635
+    ) {
2636
+        return $regs[0];
2637
+    }
2638 2638
 }
2639 2639
 
2640 2640
 /**
@@ -2662,30 +2662,30 @@  discard block
 block discarded – undo
2662 2662
  *     - Tableau de résultats, si tableau en entrée.
2663 2663
  **/
2664 2664
 function extraire_balises($texte, $tag = 'a') {
2665
-	if (is_array($texte)) {
2666
-		array_walk(
2667
-			$texte,
2668
-			function (&$a, $key, $t) {
2669
-				$a = extraire_balises($a, $t);
2670
-			},
2671
-			$tag
2672
-		);
2673
-
2674
-		return $texte;
2675
-	}
2676
-
2677
-	if (
2678
-		preg_match_all(
2679
-			",<${tag}\b[^>]*(/>|>.*</${tag}\b[^>]*>|>),UimsS",
2680
-			$texte,
2681
-			$regs,
2682
-			PREG_PATTERN_ORDER
2683
-		)
2684
-	) {
2685
-		return $regs[0];
2686
-	} else {
2687
-		return [];
2688
-	}
2665
+    if (is_array($texte)) {
2666
+        array_walk(
2667
+            $texte,
2668
+            function (&$a, $key, $t) {
2669
+                $a = extraire_balises($a, $t);
2670
+            },
2671
+            $tag
2672
+        );
2673
+
2674
+        return $texte;
2675
+    }
2676
+
2677
+    if (
2678
+        preg_match_all(
2679
+            ",<${tag}\b[^>]*(/>|>.*</${tag}\b[^>]*>|>),UimsS",
2680
+            $texte,
2681
+            $regs,
2682
+            PREG_PATTERN_ORDER
2683
+        )
2684
+    ) {
2685
+        return $regs[0];
2686
+    } else {
2687
+        return [];
2688
+    }
2689 2689
 }
2690 2690
 
2691 2691
 /**
@@ -2714,11 +2714,11 @@  discard block
 block discarded – undo
2714 2714
  *     - `$def` si on n'a pas transmis de tableau
2715 2715
  **/
2716 2716
 function in_any($val, $vals, $def = '') {
2717
-	if (!is_array($vals) and $vals and $v = unserialize($vals)) {
2718
-		$vals = $v;
2719
-	}
2717
+    if (!is_array($vals) and $vals and $v = unserialize($vals)) {
2718
+        $vals = $v;
2719
+    }
2720 2720
 
2721
-	return (!is_array($vals) ? $def : (in_array($val, $vals) ? ' ' : ''));
2721
+    return (!is_array($vals) ? $def : (in_array($val, $vals) ? ' ' : ''));
2722 2722
 }
2723 2723
 
2724 2724
 
@@ -2739,12 +2739,12 @@  discard block
 block discarded – undo
2739 2739
  *     Résultat du calcul
2740 2740
  **/
2741 2741
 function valeur_numerique($expr) {
2742
-	$a = 0;
2743
-	if (preg_match(',^[0-9]+(\s*[+*-]\s*[0-9]+)*$,S', trim($expr))) {
2744
-		eval("\$a = $expr;");
2745
-	}
2742
+    $a = 0;
2743
+    if (preg_match(',^[0-9]+(\s*[+*-]\s*[0-9]+)*$,S', trim($expr))) {
2744
+        eval("\$a = $expr;");
2745
+    }
2746 2746
 
2747
-	return intval($a);
2747
+    return intval($a);
2748 2748
 }
2749 2749
 
2750 2750
 /**
@@ -2763,7 +2763,7 @@  discard block
 block discarded – undo
2763 2763
  *      Retourne `$a*$b/$c`
2764 2764
  **/
2765 2765
 function regledetrois($a, $b, $c) {
2766
-	return round($a * $b / $c);
2766
+    return round($a * $b / $c);
2767 2767
 }
2768 2768
 
2769 2769
 
@@ -2786,79 +2786,79 @@  discard block
 block discarded – undo
2786 2786
  * @return string Suite de champs input hidden
2787 2787
  **/
2788 2788
 function form_hidden(?string $action = ''): string {
2789
-	$action ??= '';
2790
-
2791
-	$contexte = [];
2792
-	include_spip('inc/urls');
2793
-	if (
2794
-		$p = urls_decoder_url($action, '')
2795
-		and reset($p)
2796
-	) {
2797
-		$fond = array_shift($p);
2798
-		if ($fond != '404') {
2799
-			$contexte = array_shift($p);
2800
-			$contexte['page'] = $fond;
2801
-			$action = preg_replace('/([?]' . preg_quote($fond) . '[^&=]*[0-9]+)(&|$)/', '?&', $action);
2802
-		}
2803
-	}
2804
-	// defaire ce qu'a injecte urls_decoder_url : a revoir en modifiant la signature de urls_decoder_url
2805
-	if (defined('_DEFINIR_CONTEXTE_TYPE') and _DEFINIR_CONTEXTE_TYPE) {
2806
-		unset($contexte['type']);
2807
-	}
2808
-	if (!defined('_DEFINIR_CONTEXTE_TYPE_PAGE') or _DEFINIR_CONTEXTE_TYPE_PAGE) {
2809
-		unset($contexte['type-page']);
2810
-	}
2811
-
2812
-	// on va remplir un tableau de valeurs en prenant bien soin de ne pas
2813
-	// ecraser les elements de la forme mots[]=1&mots[]=2
2814
-	$values = [];
2815
-
2816
-	// d'abord avec celles de l'url
2817
-	if (false !== ($p = strpos($action, '?'))) {
2818
-		foreach (preg_split('/&(amp;)?/S', substr($action, $p + 1)) as $c) {
2819
-			$c = explode('=', $c, 2);
2820
-			$var = array_shift($c);
2821
-			$val = array_shift($c) ?? '';
2822
-			if ($var) {
2823
-				$val = rawurldecode($val);
2824
-				$var = rawurldecode($var); // decoder les [] eventuels
2825
-				if (preg_match(',\[\]$,S', $var)) {
2826
-					$values[] = [$var, $val];
2827
-				} else {
2828
-					if (!isset($values[$var])) {
2829
-						$values[$var] = [$var, $val];
2830
-					}
2831
-				}
2832
-			}
2833
-		}
2834
-	}
2835
-
2836
-	// ensuite avec celles du contexte, sans doublonner !
2837
-	foreach ($contexte as $var => $val) {
2838
-		if (preg_match(',\[\]$,S', $var)) {
2839
-			$values[] = [$var, $val];
2840
-		} else {
2841
-			if (!isset($values[$var])) {
2842
-				$values[$var] = [$var, $val];
2843
-			}
2844
-		}
2845
-	}
2846
-
2847
-	// puis on rassemble le tout
2848
-	$hidden = [];
2849
-	foreach ($values as $value) {
2850
-		[$var, $val] = $value;
2851
-		$hidden[] = '<input name="'
2852
-			. entites_html($var)
2853
-			. '"'
2854
-			. (is_null($val)
2855
-				? ''
2856
-				: ' value="' . entites_html($val) . '"'
2857
-			)
2858
-			. ' type="hidden"' . "\n/>";
2859
-	}
2860
-
2861
-	return join('', $hidden);
2789
+    $action ??= '';
2790
+
2791
+    $contexte = [];
2792
+    include_spip('inc/urls');
2793
+    if (
2794
+        $p = urls_decoder_url($action, '')
2795
+        and reset($p)
2796
+    ) {
2797
+        $fond = array_shift($p);
2798
+        if ($fond != '404') {
2799
+            $contexte = array_shift($p);
2800
+            $contexte['page'] = $fond;
2801
+            $action = preg_replace('/([?]' . preg_quote($fond) . '[^&=]*[0-9]+)(&|$)/', '?&', $action);
2802
+        }
2803
+    }
2804
+    // defaire ce qu'a injecte urls_decoder_url : a revoir en modifiant la signature de urls_decoder_url
2805
+    if (defined('_DEFINIR_CONTEXTE_TYPE') and _DEFINIR_CONTEXTE_TYPE) {
2806
+        unset($contexte['type']);
2807
+    }
2808
+    if (!defined('_DEFINIR_CONTEXTE_TYPE_PAGE') or _DEFINIR_CONTEXTE_TYPE_PAGE) {
2809
+        unset($contexte['type-page']);
2810
+    }
2811
+
2812
+    // on va remplir un tableau de valeurs en prenant bien soin de ne pas
2813
+    // ecraser les elements de la forme mots[]=1&mots[]=2
2814
+    $values = [];
2815
+
2816
+    // d'abord avec celles de l'url
2817
+    if (false !== ($p = strpos($action, '?'))) {
2818
+        foreach (preg_split('/&(amp;)?/S', substr($action, $p + 1)) as $c) {
2819
+            $c = explode('=', $c, 2);
2820
+            $var = array_shift($c);
2821
+            $val = array_shift($c) ?? '';
2822
+            if ($var) {
2823
+                $val = rawurldecode($val);
2824
+                $var = rawurldecode($var); // decoder les [] eventuels
2825
+                if (preg_match(',\[\]$,S', $var)) {
2826
+                    $values[] = [$var, $val];
2827
+                } else {
2828
+                    if (!isset($values[$var])) {
2829
+                        $values[$var] = [$var, $val];
2830
+                    }
2831
+                }
2832
+            }
2833
+        }
2834
+    }
2835
+
2836
+    // ensuite avec celles du contexte, sans doublonner !
2837
+    foreach ($contexte as $var => $val) {
2838
+        if (preg_match(',\[\]$,S', $var)) {
2839
+            $values[] = [$var, $val];
2840
+        } else {
2841
+            if (!isset($values[$var])) {
2842
+                $values[$var] = [$var, $val];
2843
+            }
2844
+        }
2845
+    }
2846
+
2847
+    // puis on rassemble le tout
2848
+    $hidden = [];
2849
+    foreach ($values as $value) {
2850
+        [$var, $val] = $value;
2851
+        $hidden[] = '<input name="'
2852
+            . entites_html($var)
2853
+            . '"'
2854
+            . (is_null($val)
2855
+                ? ''
2856
+                : ' value="' . entites_html($val) . '"'
2857
+            )
2858
+            . ' type="hidden"' . "\n/>";
2859
+    }
2860
+
2861
+    return join('', $hidden);
2862 2862
 }
2863 2863
 
2864 2864
 
@@ -2880,7 +2880,7 @@  discard block
 block discarded – undo
2880 2880
  *    - la première valeur du tableau sinon.
2881 2881
  **/
2882 2882
 function filtre_reset($array) {
2883
-	return !is_array($array) ? null : reset($array);
2883
+    return !is_array($array) ? null : reset($array);
2884 2884
 }
2885 2885
 
2886 2886
 /**
@@ -2901,7 +2901,7 @@  discard block
 block discarded – undo
2901 2901
  *    - la dernière valeur du tableau sinon.
2902 2902
  **/
2903 2903
 function filtre_end($array) {
2904
-	return !is_array($array) ? null : end($array);
2904
+    return !is_array($array) ? null : end($array);
2905 2905
 }
2906 2906
 
2907 2907
 /**
@@ -2921,11 +2921,11 @@  discard block
 block discarded – undo
2921 2921
  *
2922 2922
  **/
2923 2923
 function filtre_push($array, $val) {
2924
-	if (!is_array($array) or !array_push($array, $val)) {
2925
-		return '';
2926
-	}
2924
+    if (!is_array($array) or !array_push($array, $val)) {
2925
+        return '';
2926
+    }
2927 2927
 
2928
-	return $array;
2928
+    return $array;
2929 2929
 }
2930 2930
 
2931 2931
 /**
@@ -2944,7 +2944,7 @@  discard block
 block discarded – undo
2944 2944
  *     - `true` si la valeur existe dans le tableau, `false` sinon.
2945 2945
  **/
2946 2946
 function filtre_find($array, $val) {
2947
-	return (is_array($array) and in_array($val, $array));
2947
+    return (is_array($array) and in_array($val, $array));
2948 2948
 }
2949 2949
 
2950 2950
 
@@ -2961,13 +2961,13 @@  discard block
 block discarded – undo
2961 2961
  *     Contenu avec urls en absolus
2962 2962
  **/
2963 2963
 function urls_absolues_css($contenu, $source) {
2964
-	$path = suivre_lien(url_absolue($source), './');
2964
+    $path = suivre_lien(url_absolue($source), './');
2965 2965
 
2966
-	return preg_replace_callback(
2967
-		",url\s*\(\s*['\"]?([^'\"/#\s][^:]*)['\"]?\s*\),Uims",
2968
-		fn($x) => "url('" . suivre_lien($path, $x[1]) . "')",
2969
-		$contenu
2970
-	);
2966
+    return preg_replace_callback(
2967
+        ",url\s*\(\s*['\"]?([^'\"/#\s][^:]*)['\"]?\s*\),Uims",
2968
+        fn($x) => "url('" . suivre_lien($path, $x[1]) . "')",
2969
+        $contenu
2970
+    );
2971 2971
 }
2972 2972
 
2973 2973
 
@@ -2996,119 +2996,119 @@  discard block
 block discarded – undo
2996 2996
  *     Chemin du fichier CSS inversé
2997 2997
  **/
2998 2998
 function direction_css($css, $voulue = '') {
2999
-	if (!preg_match(',(_rtl)?\.css$,i', $css, $r)) {
3000
-		return $css;
3001
-	}
3002
-	include_spip('inc/lang');
3003
-	// si on a precise le sens voulu en argument, le prendre en compte
3004
-	if ($voulue = strtolower($voulue)) {
3005
-		if ($voulue != 'rtl' and $voulue != 'ltr') {
3006
-			$voulue = lang_dir($voulue);
3007
-		}
3008
-	} else {
3009
-		$voulue = lang_dir();
3010
-	}
3011
-
3012
-	$r = count($r) > 1;
3013
-	$right = $r ? 'left' : 'right'; // 'right' de la css lue en entree
3014
-	$dir = $r ? 'rtl' : 'ltr';
3015
-	$ndir = $r ? 'ltr' : 'rtl';
3016
-
3017
-	if ($voulue == $dir) {
3018
-		return $css;
3019
-	}
3020
-
3021
-	if (
3022
-		// url absolue
3023
-		preg_match(',^https?:,i', $css)
3024
-		// ou qui contient un ?
3025
-		or (($p = strpos($css, '?')) !== false)
3026
-	) {
3027
-		$distant = true;
3028
-		$cssf = parse_url($css);
3029
-		$cssf = $cssf['path'] . ($cssf['query'] ? '?' . $cssf['query'] : '');
3030
-		$cssf = preg_replace(',[?:&=],', '_', $cssf);
3031
-	} else {
3032
-		$distant = false;
3033
-		$cssf = $css;
3034
-		// 1. regarder d'abord si un fichier avec la bonne direction n'est pas aussi
3035
-		//propose (rien a faire dans ce cas)
3036
-		$f = preg_replace(',(_rtl)?\.css$,i', '_' . $ndir . '.css', $css);
3037
-		if (@file_exists($f)) {
3038
-			return $f;
3039
-		}
3040
-	}
3041
-
3042
-	// 2.
3043
-	$dir_var = sous_repertoire(_DIR_VAR, 'cache-css');
3044
-	$f = $dir_var
3045
-		. preg_replace(',.*/(.*?)(_rtl)?\.css,', '\1', $cssf)
3046
-		. '.' . substr(md5($cssf), 0, 4) . '_' . $ndir . '.css';
3047
-
3048
-	// la css peut etre distante (url absolue !)
3049
-	if ($distant) {
3050
-		include_spip('inc/distant');
3051
-		$res = recuperer_url($css);
3052
-		if (!$res or !$contenu = $res['page']) {
3053
-			return $css;
3054
-		}
3055
-	} else {
3056
-		if (
3057
-			(@filemtime($f) > @filemtime($css))
3058
-			and (_VAR_MODE != 'recalcul')
3059
-		) {
3060
-			return $f;
3061
-		}
3062
-		if (!lire_fichier($css, $contenu)) {
3063
-			return $css;
3064
-		}
3065
-	}
3066
-
3067
-
3068
-	// Inverser la direction gauche-droite en utilisant CSSTidy qui gere aussi les shorthands
3069
-	include_spip('lib/csstidy/class.csstidy');
3070
-	$parser = new csstidy();
3071
-	$parser->set_cfg('optimise_shorthands', 0);
3072
-	$parser->set_cfg('reverse_left_and_right', true);
3073
-	$parser->parse($contenu);
3074
-
3075
-	$contenu = $parser->print->plain();
3076
-
3077
-
3078
-	// reperer les @import auxquels il faut propager le direction_css
3079
-	preg_match_all(",\@import\s*url\s*\(\s*['\"]?([^'\"/][^:]*)['\"]?\s*\),Uims", $contenu, $regs);
3080
-	$src = [];
3081
-	$src_direction_css = [];
3082
-	$src_faux_abs = [];
3083
-	$d = dirname($css);
3084
-	foreach ($regs[1] as $k => $import_css) {
3085
-		$css_direction = direction_css("$d/$import_css", $voulue);
3086
-		// si la css_direction est dans le meme path que la css d'origine, on tronque le path, elle sera passee en absolue
3087
-		if (substr($css_direction, 0, strlen($d) + 1) == "$d/") {
3088
-			$css_direction = substr($css_direction, strlen($d) + 1);
3089
-		} // si la css_direction commence par $dir_var on la fait passer pour une absolue
3090
-		elseif (substr($css_direction, 0, strlen($dir_var)) == $dir_var) {
3091
-			$css_direction = substr($css_direction, strlen($dir_var));
3092
-			$src_faux_abs['/@@@@@@/' . $css_direction] = $css_direction;
3093
-			$css_direction = '/@@@@@@/' . $css_direction;
3094
-		}
3095
-		$src[] = $regs[0][$k];
3096
-		$src_direction_css[] = str_replace($import_css, $css_direction, $regs[0][$k]);
3097
-	}
3098
-	$contenu = str_replace($src, $src_direction_css, $contenu);
3099
-
3100
-	$contenu = urls_absolues_css($contenu, $css);
3101
-
3102
-	// virer les fausses url absolues que l'on a mis dans les import
3103
-	if (count($src_faux_abs)) {
3104
-		$contenu = str_replace(array_keys($src_faux_abs), $src_faux_abs, $contenu);
3105
-	}
3106
-
3107
-	if (!ecrire_fichier($f, $contenu)) {
3108
-		return $css;
3109
-	}
3110
-
3111
-	return $f;
2999
+    if (!preg_match(',(_rtl)?\.css$,i', $css, $r)) {
3000
+        return $css;
3001
+    }
3002
+    include_spip('inc/lang');
3003
+    // si on a precise le sens voulu en argument, le prendre en compte
3004
+    if ($voulue = strtolower($voulue)) {
3005
+        if ($voulue != 'rtl' and $voulue != 'ltr') {
3006
+            $voulue = lang_dir($voulue);
3007
+        }
3008
+    } else {
3009
+        $voulue = lang_dir();
3010
+    }
3011
+
3012
+    $r = count($r) > 1;
3013
+    $right = $r ? 'left' : 'right'; // 'right' de la css lue en entree
3014
+    $dir = $r ? 'rtl' : 'ltr';
3015
+    $ndir = $r ? 'ltr' : 'rtl';
3016
+
3017
+    if ($voulue == $dir) {
3018
+        return $css;
3019
+    }
3020
+
3021
+    if (
3022
+        // url absolue
3023
+        preg_match(',^https?:,i', $css)
3024
+        // ou qui contient un ?
3025
+        or (($p = strpos($css, '?')) !== false)
3026
+    ) {
3027
+        $distant = true;
3028
+        $cssf = parse_url($css);
3029
+        $cssf = $cssf['path'] . ($cssf['query'] ? '?' . $cssf['query'] : '');
3030
+        $cssf = preg_replace(',[?:&=],', '_', $cssf);
3031
+    } else {
3032
+        $distant = false;
3033
+        $cssf = $css;
3034
+        // 1. regarder d'abord si un fichier avec la bonne direction n'est pas aussi
3035
+        //propose (rien a faire dans ce cas)
3036
+        $f = preg_replace(',(_rtl)?\.css$,i', '_' . $ndir . '.css', $css);
3037
+        if (@file_exists($f)) {
3038
+            return $f;
3039
+        }
3040
+    }
3041
+
3042
+    // 2.
3043
+    $dir_var = sous_repertoire(_DIR_VAR, 'cache-css');
3044
+    $f = $dir_var
3045
+        . preg_replace(',.*/(.*?)(_rtl)?\.css,', '\1', $cssf)
3046
+        . '.' . substr(md5($cssf), 0, 4) . '_' . $ndir . '.css';
3047
+
3048
+    // la css peut etre distante (url absolue !)
3049
+    if ($distant) {
3050
+        include_spip('inc/distant');
3051
+        $res = recuperer_url($css);
3052
+        if (!$res or !$contenu = $res['page']) {
3053
+            return $css;
3054
+        }
3055
+    } else {
3056
+        if (
3057
+            (@filemtime($f) > @filemtime($css))
3058
+            and (_VAR_MODE != 'recalcul')
3059
+        ) {
3060
+            return $f;
3061
+        }
3062
+        if (!lire_fichier($css, $contenu)) {
3063
+            return $css;
3064
+        }
3065
+    }
3066
+
3067
+
3068
+    // Inverser la direction gauche-droite en utilisant CSSTidy qui gere aussi les shorthands
3069
+    include_spip('lib/csstidy/class.csstidy');
3070
+    $parser = new csstidy();
3071
+    $parser->set_cfg('optimise_shorthands', 0);
3072
+    $parser->set_cfg('reverse_left_and_right', true);
3073
+    $parser->parse($contenu);
3074
+
3075
+    $contenu = $parser->print->plain();
3076
+
3077
+
3078
+    // reperer les @import auxquels il faut propager le direction_css
3079
+    preg_match_all(",\@import\s*url\s*\(\s*['\"]?([^'\"/][^:]*)['\"]?\s*\),Uims", $contenu, $regs);
3080
+    $src = [];
3081
+    $src_direction_css = [];
3082
+    $src_faux_abs = [];
3083
+    $d = dirname($css);
3084
+    foreach ($regs[1] as $k => $import_css) {
3085
+        $css_direction = direction_css("$d/$import_css", $voulue);
3086
+        // si la css_direction est dans le meme path que la css d'origine, on tronque le path, elle sera passee en absolue
3087
+        if (substr($css_direction, 0, strlen($d) + 1) == "$d/") {
3088
+            $css_direction = substr($css_direction, strlen($d) + 1);
3089
+        } // si la css_direction commence par $dir_var on la fait passer pour une absolue
3090
+        elseif (substr($css_direction, 0, strlen($dir_var)) == $dir_var) {
3091
+            $css_direction = substr($css_direction, strlen($dir_var));
3092
+            $src_faux_abs['/@@@@@@/' . $css_direction] = $css_direction;
3093
+            $css_direction = '/@@@@@@/' . $css_direction;
3094
+        }
3095
+        $src[] = $regs[0][$k];
3096
+        $src_direction_css[] = str_replace($import_css, $css_direction, $regs[0][$k]);
3097
+    }
3098
+    $contenu = str_replace($src, $src_direction_css, $contenu);
3099
+
3100
+    $contenu = urls_absolues_css($contenu, $css);
3101
+
3102
+    // virer les fausses url absolues que l'on a mis dans les import
3103
+    if (count($src_faux_abs)) {
3104
+        $contenu = str_replace(array_keys($src_faux_abs), $src_faux_abs, $contenu);
3105
+    }
3106
+
3107
+    if (!ecrire_fichier($f, $contenu)) {
3108
+        return $css;
3109
+    }
3110
+
3111
+    return $f;
3112 3112
 }
3113 3113
 
3114 3114
 
@@ -3131,46 +3131,46 @@  discard block
 block discarded – undo
3131 3131
  *     - Chemin ou URL du fichier CSS source sinon.
3132 3132
  **/
3133 3133
 function url_absolue_css($css) {
3134
-	if (!preg_match(',\.css$,i', $css, $r)) {
3135
-		return $css;
3136
-	}
3134
+    if (!preg_match(',\.css$,i', $css, $r)) {
3135
+        return $css;
3136
+    }
3137 3137
 
3138
-	$url_absolue_css = url_absolue($css);
3138
+    $url_absolue_css = url_absolue($css);
3139 3139
 
3140
-	$f = basename($css, '.css');
3141
-	$f = sous_repertoire(_DIR_VAR, 'cache-css')
3142
-		. preg_replace(',(.*?)(_rtl|_ltr)?$,', "\\1-urlabs-" . substr(md5("$css-urlabs"), 0, 4) . "\\2", $f)
3143
-		. '.css';
3140
+    $f = basename($css, '.css');
3141
+    $f = sous_repertoire(_DIR_VAR, 'cache-css')
3142
+        . preg_replace(',(.*?)(_rtl|_ltr)?$,', "\\1-urlabs-" . substr(md5("$css-urlabs"), 0, 4) . "\\2", $f)
3143
+        . '.css';
3144 3144
 
3145
-	if ((@filemtime($f) > @filemtime($css)) and (_VAR_MODE != 'recalcul')) {
3146
-		return $f;
3147
-	}
3145
+    if ((@filemtime($f) > @filemtime($css)) and (_VAR_MODE != 'recalcul')) {
3146
+        return $f;
3147
+    }
3148 3148
 
3149
-	if ($url_absolue_css == $css) {
3150
-		if (
3151
-			strncmp($GLOBALS['meta']['adresse_site'], $css, $l = strlen($GLOBALS['meta']['adresse_site'])) != 0
3152
-			or !lire_fichier(_DIR_RACINE . substr($css, $l), $contenu)
3153
-		) {
3154
-			include_spip('inc/distant');
3155
-			$contenu = recuperer_url($css);
3156
-			$contenu = $contenu['page'] ?? '';
3157
-			if (!$contenu) {
3158
-				return $css;
3159
-			}
3160
-		}
3161
-	} elseif (!lire_fichier($css, $contenu)) {
3162
-		return $css;
3163
-	}
3149
+    if ($url_absolue_css == $css) {
3150
+        if (
3151
+            strncmp($GLOBALS['meta']['adresse_site'], $css, $l = strlen($GLOBALS['meta']['adresse_site'])) != 0
3152
+            or !lire_fichier(_DIR_RACINE . substr($css, $l), $contenu)
3153
+        ) {
3154
+            include_spip('inc/distant');
3155
+            $contenu = recuperer_url($css);
3156
+            $contenu = $contenu['page'] ?? '';
3157
+            if (!$contenu) {
3158
+                return $css;
3159
+            }
3160
+        }
3161
+    } elseif (!lire_fichier($css, $contenu)) {
3162
+        return $css;
3163
+    }
3164 3164
 
3165
-	// passer les url relatives a la css d'origine en url absolues
3166
-	$contenu = urls_absolues_css($contenu, $css);
3165
+    // passer les url relatives a la css d'origine en url absolues
3166
+    $contenu = urls_absolues_css($contenu, $css);
3167 3167
 
3168
-	// ecrire la css
3169
-	if (!ecrire_fichier($f, $contenu)) {
3170
-		return $css;
3171
-	}
3168
+    // ecrire la css
3169
+    if (!ecrire_fichier($f, $contenu)) {
3170
+        return $css;
3171
+    }
3172 3172
 
3173
-	return $f;
3173
+    return $f;
3174 3174
 }
3175 3175
 
3176 3176
 
@@ -3204,24 +3204,24 @@  discard block
 block discarded – undo
3204 3204
  *     Valeur trouvée ou valeur par défaut.
3205 3205
  **/
3206 3206
 function table_valeur($table, $cle, $defaut = '', $conserver_null = false) {
3207
-	foreach (explode('/', $cle) as $k) {
3208
-		$table = (is_string($table) ? @unserialize($table) : $table);
3207
+    foreach (explode('/', $cle) as $k) {
3208
+        $table = (is_string($table) ? @unserialize($table) : $table);
3209 3209
 
3210
-		if (is_object($table)) {
3211
-			$table = (($k !== '') and isset($table->$k)) ? $table->$k : $defaut;
3212
-		} elseif (is_array($table)) {
3213
-			if ($conserver_null) {
3214
-				$table = array_key_exists($k, $table) ? $table[$k] : $defaut;
3215
-			} else {
3216
-				$table = ($table[$k] ?? $defaut);
3217
-			}
3218
-		} else {
3219
-			$table = $defaut;
3220
-			break;
3221
-		}
3222
-	}
3210
+        if (is_object($table)) {
3211
+            $table = (($k !== '') and isset($table->$k)) ? $table->$k : $defaut;
3212
+        } elseif (is_array($table)) {
3213
+            if ($conserver_null) {
3214
+                $table = array_key_exists($k, $table) ? $table[$k] : $defaut;
3215
+            } else {
3216
+                $table = ($table[$k] ?? $defaut);
3217
+            }
3218
+        } else {
3219
+            $table = $defaut;
3220
+            break;
3221
+        }
3222
+    }
3223 3223
 
3224
-	return $table;
3224
+    return $table;
3225 3225
 }
3226 3226
 
3227 3227
 /**
@@ -3254,22 +3254,22 @@  discard block
 block discarded – undo
3254 3254
  *     - string : expression trouvée.
3255 3255
  **/
3256 3256
 function filtre_match_dist(?string $texte, $expression, $modif = 'UimsS', $capte = 0) {
3257
-	if (intval($modif) and $capte == 0) {
3258
-		$capte = $modif;
3259
-		$modif = 'UimsS';
3260
-	}
3261
-	$expression = str_replace('\/', '/', $expression);
3262
-	$expression = str_replace('/', '\/', $expression);
3257
+    if (intval($modif) and $capte == 0) {
3258
+        $capte = $modif;
3259
+        $modif = 'UimsS';
3260
+    }
3261
+    $expression = str_replace('\/', '/', $expression);
3262
+    $expression = str_replace('/', '\/', $expression);
3263 3263
 
3264
-	if (preg_match('/' . $expression . '/' . $modif, $texte ?? '', $r)) {
3265
-		if (isset($r[$capte])) {
3266
-			return $r[$capte];
3267
-		} else {
3268
-			return true;
3269
-		}
3270
-	}
3264
+    if (preg_match('/' . $expression . '/' . $modif, $texte ?? '', $r)) {
3265
+        if (isset($r[$capte])) {
3266
+            return $r[$capte];
3267
+        } else {
3268
+            return true;
3269
+        }
3270
+    }
3271 3271
 
3272
-	return false;
3272
+    return false;
3273 3273
 }
3274 3274
 
3275 3275
 
@@ -3296,10 +3296,10 @@  discard block
 block discarded – undo
3296 3296
  *     Texte
3297 3297
  **/
3298 3298
 function replace($texte, $expression, $replace = '', $modif = 'UimsS') {
3299
-	$expression = str_replace('\/', '/', $expression);
3300
-	$expression = str_replace('/', '\/', $expression);
3299
+    $expression = str_replace('\/', '/', $expression);
3300
+    $expression = str_replace('/', '\/', $expression);
3301 3301
 
3302
-	return preg_replace('/' . $expression . '/' . $modif, $replace, $texte);
3302
+    return preg_replace('/' . $expression . '/' . $modif, $replace, $texte);
3303 3303
 }
3304 3304
 
3305 3305
 
@@ -3317,25 +3317,25 @@  discard block
 block discarded – undo
3317 3317
  **/
3318 3318
 function traiter_doublons_documents(&$doublons, $letexte) {
3319 3319
 
3320
-	// Verifier dans le texte & les notes (pas beau, helas)
3321
-	$t = $letexte . $GLOBALS['les_notes'];
3320
+    // Verifier dans le texte & les notes (pas beau, helas)
3321
+    $t = $letexte . $GLOBALS['les_notes'];
3322 3322
 
3323
-	if (
3324
-		strstr($t, 'spip_document_') // evite le preg_match_all si inutile
3325
-		and preg_match_all(
3326
-			',<[^>]+\sclass=["\']spip_document_([0-9]+)[\s"\'],imsS',
3327
-			$t,
3328
-			$matches,
3329
-			PREG_PATTERN_ORDER
3330
-		)
3331
-	) {
3332
-		if (!isset($doublons['documents'])) {
3333
-			$doublons['documents'] = '';
3334
-		}
3335
-		$doublons['documents'] .= ',' . join(',', $matches[1]);
3336
-	}
3323
+    if (
3324
+        strstr($t, 'spip_document_') // evite le preg_match_all si inutile
3325
+        and preg_match_all(
3326
+            ',<[^>]+\sclass=["\']spip_document_([0-9]+)[\s"\'],imsS',
3327
+            $t,
3328
+            $matches,
3329
+            PREG_PATTERN_ORDER
3330
+        )
3331
+    ) {
3332
+        if (!isset($doublons['documents'])) {
3333
+            $doublons['documents'] = '';
3334
+        }
3335
+        $doublons['documents'] .= ',' . join(',', $matches[1]);
3336
+    }
3337 3337
 
3338
-	return $letexte;
3338
+    return $letexte;
3339 3339
 }
3340 3340
 
3341 3341
 /**
@@ -3349,7 +3349,7 @@  discard block
 block discarded – undo
3349 3349
  * @return string Chaîne vide
3350 3350
  **/
3351 3351
 function vide($texte) {
3352
-	return '';
3352
+    return '';
3353 3353
 }
3354 3354
 
3355 3355
 //
@@ -3378,23 +3378,23 @@  discard block
 block discarded – undo
3378 3378
  *      Code HTML résultant
3379 3379
  **/
3380 3380
 function env_to_params($env, $ignore_params = []) {
3381
-	$ignore_params = array_merge(
3382
-		['id', 'lang', 'id_document', 'date', 'date_redac', 'align', 'fond', '', 'recurs', 'emb', 'dir_racine'],
3383
-		$ignore_params
3384
-	);
3385
-	if (!is_array($env)) {
3386
-		$env = unserialize($env);
3387
-	}
3388
-	$texte = '';
3389
-	if ($env) {
3390
-		foreach ($env as $i => $j) {
3391
-			if (is_string($j) and !in_array($i, $ignore_params)) {
3392
-				$texte .= "<param name='" . attribut_html($i) . "'\n\tvalue='" . attribut_html($j) . "' />";
3393
-			}
3394
-		}
3395
-	}
3396
-
3397
-	return $texte;
3381
+    $ignore_params = array_merge(
3382
+        ['id', 'lang', 'id_document', 'date', 'date_redac', 'align', 'fond', '', 'recurs', 'emb', 'dir_racine'],
3383
+        $ignore_params
3384
+    );
3385
+    if (!is_array($env)) {
3386
+        $env = unserialize($env);
3387
+    }
3388
+    $texte = '';
3389
+    if ($env) {
3390
+        foreach ($env as $i => $j) {
3391
+            if (is_string($j) and !in_array($i, $ignore_params)) {
3392
+                $texte .= "<param name='" . attribut_html($i) . "'\n\tvalue='" . attribut_html($j) . "' />";
3393
+            }
3394
+        }
3395
+    }
3396
+
3397
+    return $texte;
3398 3398
 }
3399 3399
 
3400 3400
 /**
@@ -3417,23 +3417,23 @@  discard block
 block discarded – undo
3417 3417
  *      Code HTML résultant
3418 3418
  **/
3419 3419
 function env_to_attributs($env, $ignore_params = []) {
3420
-	$ignore_params = array_merge(
3421
-		['id', 'lang', 'id_document', 'date', 'date_redac', 'align', 'fond', '', 'recurs', 'emb', 'dir_racine'],
3422
-		$ignore_params
3423
-	);
3424
-	if (!is_array($env)) {
3425
-		$env = unserialize($env);
3426
-	}
3427
-	$texte = '';
3428
-	if ($env) {
3429
-		foreach ($env as $i => $j) {
3430
-			if (is_string($j) and !in_array($i, $ignore_params)) {
3431
-				$texte .= attribut_html($i) . "='" . attribut_html($j) . "' ";
3432
-			}
3433
-		}
3434
-	}
3420
+    $ignore_params = array_merge(
3421
+        ['id', 'lang', 'id_document', 'date', 'date_redac', 'align', 'fond', '', 'recurs', 'emb', 'dir_racine'],
3422
+        $ignore_params
3423
+    );
3424
+    if (!is_array($env)) {
3425
+        $env = unserialize($env);
3426
+    }
3427
+    $texte = '';
3428
+    if ($env) {
3429
+        foreach ($env as $i => $j) {
3430
+            if (is_string($j) and !in_array($i, $ignore_params)) {
3431
+                $texte .= attribut_html($i) . "='" . attribut_html($j) . "' ";
3432
+            }
3433
+        }
3434
+    }
3435 3435
 
3436
-	return $texte;
3436
+    return $texte;
3437 3437
 }
3438 3438
 
3439 3439
 
@@ -3451,7 +3451,7 @@  discard block
 block discarded – undo
3451 3451
  * @return string Chaînes concaténés
3452 3452
  **/
3453 3453
 function concat(...$args): string {
3454
-	return join('', $args);
3454
+    return join('', $args);
3455 3455
 }
3456 3456
 
3457 3457
 
@@ -3471,23 +3471,23 @@  discard block
 block discarded – undo
3471 3471
  *     Contenu du ou des fichiers, concaténé
3472 3472
  **/
3473 3473
 function charge_scripts($files, $script = true) {
3474
-	$flux = '';
3475
-	foreach (is_array($files) ? $files : explode('|', $files) as $file) {
3476
-		if (!is_string($file)) {
3477
-			continue;
3478
-		}
3479
-		if ($script) {
3480
-			$file = preg_match(',^\w+$,', $file) ? "javascript/$file.js" : '';
3481
-		}
3482
-		if ($file) {
3483
-			$path = find_in_path($file);
3484
-			if ($path) {
3485
-				$flux .= spip_file_get_contents($path);
3486
-			}
3487
-		}
3488
-	}
3489
-
3490
-	return $flux;
3474
+    $flux = '';
3475
+    foreach (is_array($files) ? $files : explode('|', $files) as $file) {
3476
+        if (!is_string($file)) {
3477
+            continue;
3478
+        }
3479
+        if ($script) {
3480
+            $file = preg_match(',^\w+$,', $file) ? "javascript/$file.js" : '';
3481
+        }
3482
+        if ($file) {
3483
+            $path = find_in_path($file);
3484
+            if ($path) {
3485
+                $flux .= spip_file_get_contents($path);
3486
+            }
3487
+        }
3488
+    }
3489
+
3490
+    return $flux;
3491 3491
 }
3492 3492
 
3493 3493
 /**
@@ -3498,22 +3498,22 @@  discard block
 block discarded – undo
3498 3498
  * @return string
3499 3499
  */
3500 3500
 function http_img_variante_svg_si_possible($img_file) {
3501
-	// on peut fournir une icone generique -xx.svg qui fera le job dans toutes les tailles, et qui est prioritaire sur le png
3502
-	// si il y a un .svg a la bonne taille (-16.svg) a cote, on l'utilise en remplacement du -16.png
3503
-	if (
3504
-		preg_match(',-(\d+)[.](png|gif|svg)$,', $img_file, $m)
3505
-		and $variante_svg_generique = substr($img_file, 0, -strlen($m[0])) . '-xx.svg'
3506
-		and file_exists($variante_svg_generique)
3507
-	) {
3508
-		if ($variante_svg_size = substr($variante_svg_generique, 0, -6) . $m[1] . '.svg' and file_exists($variante_svg_size)) {
3509
-			$img_file = $variante_svg_size;
3510
-		}
3511
-		else {
3512
-			$img_file = $variante_svg_generique;
3513
-		}
3514
-	}
3501
+    // on peut fournir une icone generique -xx.svg qui fera le job dans toutes les tailles, et qui est prioritaire sur le png
3502
+    // si il y a un .svg a la bonne taille (-16.svg) a cote, on l'utilise en remplacement du -16.png
3503
+    if (
3504
+        preg_match(',-(\d+)[.](png|gif|svg)$,', $img_file, $m)
3505
+        and $variante_svg_generique = substr($img_file, 0, -strlen($m[0])) . '-xx.svg'
3506
+        and file_exists($variante_svg_generique)
3507
+    ) {
3508
+        if ($variante_svg_size = substr($variante_svg_generique, 0, -6) . $m[1] . '.svg' and file_exists($variante_svg_size)) {
3509
+            $img_file = $variante_svg_size;
3510
+        }
3511
+        else {
3512
+            $img_file = $variante_svg_generique;
3513
+        }
3514
+    }
3515 3515
 
3516
-	return $img_file;
3516
+    return $img_file;
3517 3517
 }
3518 3518
 
3519 3519
 /**
@@ -3534,54 +3534,54 @@  discard block
 block discarded – undo
3534 3534
  */
3535 3535
 function http_img_pack($img, $alt, $atts = '', $title = '', $options = []) {
3536 3536
 
3537
-	$img_file = $img;
3538
-	if ($p = strpos($img_file, '?')) {
3539
-		$img_file = substr($img_file, 0, $p);
3540
-	}
3541
-	if (!isset($options['chemin_image']) or $options['chemin_image'] == true) {
3542
-		$img_file = chemin_image($img);
3543
-	}
3544
-	else {
3545
-		if (!isset($options['variante_svg_si_possible']) or $options['variante_svg_si_possible'] == true) {
3546
-			$img_file = http_img_variante_svg_si_possible($img_file);
3547
-		}
3548
-	}
3549
-	if (stripos($atts, 'width') === false) {
3550
-		// utiliser directement l'info de taille presente dans le nom
3551
-		if (
3552
-			(!isset($options['utiliser_suffixe_size'])
3553
-				or $options['utiliser_suffixe_size'] == true
3554
-			  or strpos($img_file, '-xx.svg') !== false)
3555
-			and (preg_match(',-([0-9]+)[.](png|gif|svg)$,', $img, $regs)
3556
-					 or preg_match(',\?([0-9]+)px$,', $img, $regs))
3557
-		) {
3558
-			$largeur = $hauteur = intval($regs[1]);
3559
-		} else {
3560
-			$taille = taille_image($img_file);
3561
-			[$hauteur, $largeur] = $taille;
3562
-			if (!$hauteur or !$largeur) {
3563
-				return '';
3564
-			}
3565
-		}
3566
-		$atts .= " width='" . $largeur . "' height='" . $hauteur . "'";
3567
-	}
3568
-
3569
-	if (file_exists($img_file)) {
3570
-		$img_file = timestamp($img_file);
3571
-	}
3572
-	if ($alt === false) {
3573
-		$alt = '';
3574
-	}
3575
-	elseif ($alt or $alt === '') {
3576
-		$alt = " alt='" . attribut_html($alt) . "'";
3577
-	}
3578
-	else {
3579
-		$alt = " alt='" . attribut_html($title) . "'";
3580
-	}
3581
-	return "<img src='$img_file'$alt"
3582
-	. ($title ? ' title="' . attribut_html($title) . '"' : '')
3583
-	. ' ' . ltrim($atts)
3584
-	. ' />';
3537
+    $img_file = $img;
3538
+    if ($p = strpos($img_file, '?')) {
3539
+        $img_file = substr($img_file, 0, $p);
3540
+    }
3541
+    if (!isset($options['chemin_image']) or $options['chemin_image'] == true) {
3542
+        $img_file = chemin_image($img);
3543
+    }
3544
+    else {
3545
+        if (!isset($options['variante_svg_si_possible']) or $options['variante_svg_si_possible'] == true) {
3546
+            $img_file = http_img_variante_svg_si_possible($img_file);
3547
+        }
3548
+    }
3549
+    if (stripos($atts, 'width') === false) {
3550
+        // utiliser directement l'info de taille presente dans le nom
3551
+        if (
3552
+            (!isset($options['utiliser_suffixe_size'])
3553
+                or $options['utiliser_suffixe_size'] == true
3554
+              or strpos($img_file, '-xx.svg') !== false)
3555
+            and (preg_match(',-([0-9]+)[.](png|gif|svg)$,', $img, $regs)
3556
+                     or preg_match(',\?([0-9]+)px$,', $img, $regs))
3557
+        ) {
3558
+            $largeur = $hauteur = intval($regs[1]);
3559
+        } else {
3560
+            $taille = taille_image($img_file);
3561
+            [$hauteur, $largeur] = $taille;
3562
+            if (!$hauteur or !$largeur) {
3563
+                return '';
3564
+            }
3565
+        }
3566
+        $atts .= " width='" . $largeur . "' height='" . $hauteur . "'";
3567
+    }
3568
+
3569
+    if (file_exists($img_file)) {
3570
+        $img_file = timestamp($img_file);
3571
+    }
3572
+    if ($alt === false) {
3573
+        $alt = '';
3574
+    }
3575
+    elseif ($alt or $alt === '') {
3576
+        $alt = " alt='" . attribut_html($alt) . "'";
3577
+    }
3578
+    else {
3579
+        $alt = " alt='" . attribut_html($title) . "'";
3580
+    }
3581
+    return "<img src='$img_file'$alt"
3582
+    . ($title ? ' title="' . attribut_html($title) . '"' : '')
3583
+    . ' ' . ltrim($atts)
3584
+    . ' />';
3585 3585
 }
3586 3586
 
3587 3587
 /**
@@ -3593,70 +3593,70 @@  discard block
 block discarded – undo
3593 3593
  * @return string
3594 3594
  */
3595 3595
 function http_style_background($img, $att = '', $size = null) {
3596
-	if ($size and is_numeric($size)) {
3597
-		$size = trim($size) . 'px';
3598
-	}
3599
-	return " style='background" .
3600
-		($att ? '' : '-image') . ': url("' . chemin_image($img) . '")' . ($att ? (' ' . $att) : '') . ';'
3601
-		. ($size ? "background-size:{$size};" : '')
3602
-		. "'";
3596
+    if ($size and is_numeric($size)) {
3597
+        $size = trim($size) . 'px';
3598
+    }
3599
+    return " style='background" .
3600
+        ($att ? '' : '-image') . ': url("' . chemin_image($img) . '")' . ($att ? (' ' . $att) : '') . ';'
3601
+        . ($size ? "background-size:{$size};" : '')
3602
+        . "'";
3603 3603
 }
3604 3604
 
3605 3605
 
3606 3606
 function helper_filtre_balise_img_svg_arguments($alt_or_size, $class_or_size, $size) {
3607
-	$args = [$alt_or_size, $class_or_size, $size];
3608
-	while (is_null(end($args)) and count($args)) {
3609
-		array_pop($args);
3610
-	}
3611
-	if (!count($args)) {
3612
-		return [null, null, null];
3613
-	}
3614
-	if (count($args) < 3) {
3615
-		$maybe_size = array_pop($args);
3616
-		// @2x
3617
-		// @1.5x
3618
-		// 512
3619
-		// 512x*
3620
-		// 512x300
3621
-		if (
3622
-			!strlen($maybe_size)
3623
-			or !preg_match(',^(@\d+(\.\d+)?x|\d+(x\*)?|\d+x\d+)$,', trim($maybe_size))
3624
-		) {
3625
-			$args[] = $maybe_size;
3626
-			$maybe_size = null;
3627
-		}
3628
-		while (count($args) < 2) {
3629
-			$args[] = null; // default alt or class
3630
-		}
3631
-		$args[] = $maybe_size;
3632
-	}
3633
-	return $args;
3607
+    $args = [$alt_or_size, $class_or_size, $size];
3608
+    while (is_null(end($args)) and count($args)) {
3609
+        array_pop($args);
3610
+    }
3611
+    if (!count($args)) {
3612
+        return [null, null, null];
3613
+    }
3614
+    if (count($args) < 3) {
3615
+        $maybe_size = array_pop($args);
3616
+        // @2x
3617
+        // @1.5x
3618
+        // 512
3619
+        // 512x*
3620
+        // 512x300
3621
+        if (
3622
+            !strlen($maybe_size)
3623
+            or !preg_match(',^(@\d+(\.\d+)?x|\d+(x\*)?|\d+x\d+)$,', trim($maybe_size))
3624
+        ) {
3625
+            $args[] = $maybe_size;
3626
+            $maybe_size = null;
3627
+        }
3628
+        while (count($args) < 2) {
3629
+            $args[] = null; // default alt or class
3630
+        }
3631
+        $args[] = $maybe_size;
3632
+    }
3633
+    return $args;
3634 3634
 }
3635 3635
 
3636 3636
 function helper_filtre_balise_img_svg_size($img, $size) {
3637
-	// si size est de la forme '@2x' c'est un coeff multiplicateur sur la densite
3638
-	if (strpos($size, '@') === 0 and substr($size, -1) === 'x') {
3639
-		$coef = floatval(substr($size, 1, -1));
3640
-		[$h, $w] = taille_image($img);
3641
-		$height = intval(round($h / $coef));
3642
-		$width = intval(round($w / $coef));
3643
-	}
3644
-	// sinon c'est une valeur seule si image caree ou largeurxhauteur
3645
-	else {
3646
-		$size = explode('x', $size, 2);
3647
-		$size = array_map('trim', $size);
3648
-		$height = $width = intval(array_shift($size));
3649
-
3650
-		if (count($size) and reset($size)) {
3651
-			$height = array_shift($size);
3652
-			if ($height === '*') {
3653
-				[$h, $w] = taille_image($img);
3654
-				$height = intval(round($h * $width / $w));
3655
-			}
3656
-		}
3657
-	}
3658
-
3659
-	return [$width, $height];
3637
+    // si size est de la forme '@2x' c'est un coeff multiplicateur sur la densite
3638
+    if (strpos($size, '@') === 0 and substr($size, -1) === 'x') {
3639
+        $coef = floatval(substr($size, 1, -1));
3640
+        [$h, $w] = taille_image($img);
3641
+        $height = intval(round($h / $coef));
3642
+        $width = intval(round($w / $coef));
3643
+    }
3644
+    // sinon c'est une valeur seule si image caree ou largeurxhauteur
3645
+    else {
3646
+        $size = explode('x', $size, 2);
3647
+        $size = array_map('trim', $size);
3648
+        $height = $width = intval(array_shift($size));
3649
+
3650
+        if (count($size) and reset($size)) {
3651
+            $height = array_shift($size);
3652
+            if ($height === '*') {
3653
+                [$h, $w] = taille_image($img);
3654
+                $height = intval(round($h * $width / $w));
3655
+            }
3656
+        }
3657
+    }
3658
+
3659
+    return [$width, $height];
3660 3660
 }
3661 3661
 
3662 3662
 /**
@@ -3692,43 +3692,43 @@  discard block
 block discarded – undo
3692 3692
  */
3693 3693
 function filtre_balise_img_dist($img, $alt = '', $class = null, $size = null) {
3694 3694
 
3695
-	[$alt, $class, $size] = helper_filtre_balise_img_svg_arguments($alt, $class, $size);
3696
-
3697
-	$img = trim((string) $img);
3698
-	if (strpos($img, '<img') === 0) {
3699
-		if (!is_null($alt)) {
3700
-			$img = inserer_attribut($img, 'alt', $alt);
3701
-		}
3702
-		if (!is_null($class)) {
3703
-			if (strlen($class)) {
3704
-				$img = inserer_attribut($img, 'class', $class);
3705
-			}
3706
-			else {
3707
-				$img = vider_attribut($img, 'class');
3708
-			}
3709
-		}
3710
-	}
3711
-	else {
3712
-		$img = http_img_pack(
3713
-			$img,
3714
-			$alt,
3715
-			$class ? " class='" . attribut_html($class) . "'" : '',
3716
-			'',
3717
-			['chemin_image' => false, 'utiliser_suffixe_size' => false]
3718
-		);
3719
-		if (is_null($alt)) {
3720
-			$img = vider_attribut($img, 'alt');
3721
-		}
3722
-	}
3723
-
3724
-	if ($img and !is_null($size) and strlen($size = trim($size))) {
3725
-		[$width, $height] = helper_filtre_balise_img_svg_size($img, $size);
3726
-
3727
-		$img = inserer_attribut($img, 'width', $width);
3728
-		$img = inserer_attribut($img, 'height', $height);
3729
-	}
3730
-
3731
-	return $img;
3695
+    [$alt, $class, $size] = helper_filtre_balise_img_svg_arguments($alt, $class, $size);
3696
+
3697
+    $img = trim((string) $img);
3698
+    if (strpos($img, '<img') === 0) {
3699
+        if (!is_null($alt)) {
3700
+            $img = inserer_attribut($img, 'alt', $alt);
3701
+        }
3702
+        if (!is_null($class)) {
3703
+            if (strlen($class)) {
3704
+                $img = inserer_attribut($img, 'class', $class);
3705
+            }
3706
+            else {
3707
+                $img = vider_attribut($img, 'class');
3708
+            }
3709
+        }
3710
+    }
3711
+    else {
3712
+        $img = http_img_pack(
3713
+            $img,
3714
+            $alt,
3715
+            $class ? " class='" . attribut_html($class) . "'" : '',
3716
+            '',
3717
+            ['chemin_image' => false, 'utiliser_suffixe_size' => false]
3718
+        );
3719
+        if (is_null($alt)) {
3720
+            $img = vider_attribut($img, 'alt');
3721
+        }
3722
+    }
3723
+
3724
+    if ($img and !is_null($size) and strlen($size = trim($size))) {
3725
+        [$width, $height] = helper_filtre_balise_img_svg_size($img, $size);
3726
+
3727
+        $img = inserer_attribut($img, 'width', $width);
3728
+        $img = inserer_attribut($img, 'height', $height);
3729
+    }
3730
+
3731
+    return $img;
3732 3732
 }
3733 3733
 
3734 3734
 
@@ -3762,80 +3762,80 @@  discard block
 block discarded – undo
3762 3762
  */
3763 3763
 function filtre_balise_svg_dist($img, $alt = '', $class = null, $size = null) {
3764 3764
 
3765
-	$svg = null;
3766
-	$img = trim($img);
3767
-	$img_file = $img;
3768
-	if (strpos($img, '<svg') === false) {
3769
-		if ($p = strpos($img_file, '?')) {
3770
-			$img_file = substr($img_file, 0, $p);
3771
-		}
3772
-
3773
-		// ne jamais operer directement sur une image distante pour des raisons de perfo
3774
-		// la copie locale a toutes les chances d'etre la ou de resservir
3775
-		if (tester_url_absolue($img_file)) {
3776
-			include_spip('inc/distant');
3777
-			$fichier = copie_locale($img_file);
3778
-			$img_file = ($fichier ? _DIR_RACINE . $fichier : $img_file);
3779
-		}
3780
-
3781
-		if (
3782
-			!$img_file
3783
-			or !file_exists($img_file)
3784
-			or !$svg = file_get_contents($img_file)
3785
-		) {
3786
-			return '';
3787
-		}
3788
-	}
3789
-
3790
-	if (!preg_match(",<svg\b[^>]*>,UimsS", $svg, $match)) {
3791
-		return '';
3792
-	}
3793
-
3794
-	[$alt, $class, $size] = helper_filtre_balise_img_svg_arguments($alt, $class, $size);
3795
-
3796
-	$balise_svg = $match[0];
3797
-	$balise_svg_source = $balise_svg;
3798
-
3799
-	// entete XML à supprimer
3800
-	$svg = preg_replace(',^\s*<\?xml[^>]*\?' . '>,', '', $svg);
3801
-
3802
-	// IE est toujours mon ami
3803
-	$balise_svg = inserer_attribut($balise_svg, 'focusable', 'false');
3804
-
3805
-	// regler la classe
3806
-	if (!is_null($class)) {
3807
-		if (strlen($class)) {
3808
-			$balise_svg = inserer_attribut($balise_svg, 'class', $class);
3809
-		}
3810
-		else {
3811
-			$balise_svg = vider_attribut($balise_svg, 'class');
3812
-		}
3813
-	}
3814
-
3815
-	// regler le alt
3816
-	if ($alt) {
3817
-		$balise_svg = inserer_attribut($balise_svg, 'role', 'img');
3818
-		$id = 'img-svg-title-' . substr(md5("$img_file:$svg:$alt"), 0, 4);
3819
-		$balise_svg = inserer_attribut($balise_svg, 'aria-labelledby', $id);
3820
-		$title = "<title id=\"$id\">" . entites_html($alt) . "</title>\n";
3821
-		$balise_svg .= $title;
3822
-	}
3823
-	else {
3824
-		$balise_svg = inserer_attribut($balise_svg, 'aria-hidden', 'true');
3825
-	}
3826
-
3827
-	$svg = str_replace($balise_svg_source, $balise_svg, $svg);
3828
-
3829
-	if (!is_null($size) and strlen($size = trim($size))) {
3830
-		[$width, $height] = helper_filtre_balise_img_svg_size($svg, $size);
3831
-
3832
-		if (!function_exists('svg_redimensionner')) {
3833
-			include_spip('inc/svg');
3834
-		}
3835
-		$svg = svg_redimensionner($svg, $width, $height);
3836
-	}
3837
-
3838
-	return $svg;
3765
+    $svg = null;
3766
+    $img = trim($img);
3767
+    $img_file = $img;
3768
+    if (strpos($img, '<svg') === false) {
3769
+        if ($p = strpos($img_file, '?')) {
3770
+            $img_file = substr($img_file, 0, $p);
3771
+        }
3772
+
3773
+        // ne jamais operer directement sur une image distante pour des raisons de perfo
3774
+        // la copie locale a toutes les chances d'etre la ou de resservir
3775
+        if (tester_url_absolue($img_file)) {
3776
+            include_spip('inc/distant');
3777
+            $fichier = copie_locale($img_file);
3778
+            $img_file = ($fichier ? _DIR_RACINE . $fichier : $img_file);
3779
+        }
3780
+
3781
+        if (
3782
+            !$img_file
3783
+            or !file_exists($img_file)
3784
+            or !$svg = file_get_contents($img_file)
3785
+        ) {
3786
+            return '';
3787
+        }
3788
+    }
3789
+
3790
+    if (!preg_match(",<svg\b[^>]*>,UimsS", $svg, $match)) {
3791
+        return '';
3792
+    }
3793
+
3794
+    [$alt, $class, $size] = helper_filtre_balise_img_svg_arguments($alt, $class, $size);
3795
+
3796
+    $balise_svg = $match[0];
3797
+    $balise_svg_source = $balise_svg;
3798
+
3799
+    // entete XML à supprimer
3800
+    $svg = preg_replace(',^\s*<\?xml[^>]*\?' . '>,', '', $svg);
3801
+
3802
+    // IE est toujours mon ami
3803
+    $balise_svg = inserer_attribut($balise_svg, 'focusable', 'false');
3804
+
3805
+    // regler la classe
3806
+    if (!is_null($class)) {
3807
+        if (strlen($class)) {
3808
+            $balise_svg = inserer_attribut($balise_svg, 'class', $class);
3809
+        }
3810
+        else {
3811
+            $balise_svg = vider_attribut($balise_svg, 'class');
3812
+        }
3813
+    }
3814
+
3815
+    // regler le alt
3816
+    if ($alt) {
3817
+        $balise_svg = inserer_attribut($balise_svg, 'role', 'img');
3818
+        $id = 'img-svg-title-' . substr(md5("$img_file:$svg:$alt"), 0, 4);
3819
+        $balise_svg = inserer_attribut($balise_svg, 'aria-labelledby', $id);
3820
+        $title = "<title id=\"$id\">" . entites_html($alt) . "</title>\n";
3821
+        $balise_svg .= $title;
3822
+    }
3823
+    else {
3824
+        $balise_svg = inserer_attribut($balise_svg, 'aria-hidden', 'true');
3825
+    }
3826
+
3827
+    $svg = str_replace($balise_svg_source, $balise_svg, $svg);
3828
+
3829
+    if (!is_null($size) and strlen($size = trim($size))) {
3830
+        [$width, $height] = helper_filtre_balise_img_svg_size($svg, $size);
3831
+
3832
+        if (!function_exists('svg_redimensionner')) {
3833
+            include_spip('inc/svg');
3834
+        }
3835
+        $svg = svg_redimensionner($svg, $width, $height);
3836
+    }
3837
+
3838
+    return $svg;
3839 3839
 }
3840 3840
 
3841 3841
 
@@ -3861,18 +3861,18 @@  discard block
 block discarded – undo
3861 3861
  *     Code HTML résultant
3862 3862
  **/
3863 3863
 function filtre_foreach_dist($tableau, $modele = 'foreach') {
3864
-	$texte = '';
3865
-	if (is_array($tableau)) {
3866
-		foreach ($tableau as $k => $v) {
3867
-			$res = recuperer_fond(
3868
-				'modeles/' . $modele,
3869
-				array_merge(['cle' => $k], (is_array($v) ? $v : ['valeur' => $v]))
3870
-			);
3871
-			$texte .= $res;
3872
-		}
3873
-	}
3864
+    $texte = '';
3865
+    if (is_array($tableau)) {
3866
+        foreach ($tableau as $k => $v) {
3867
+            $res = recuperer_fond(
3868
+                'modeles/' . $modele,
3869
+                array_merge(['cle' => $k], (is_array($v) ? $v : ['valeur' => $v]))
3870
+            );
3871
+            $texte .= $res;
3872
+        }
3873
+    }
3874 3874
 
3875
-	return $texte;
3875
+    return $texte;
3876 3876
 }
3877 3877
 
3878 3878
 
@@ -3897,37 +3897,37 @@  discard block
 block discarded – undo
3897 3897
  *         - tout : retourne toutes les informations du plugin actif
3898 3898
  **/
3899 3899
 function filtre_info_plugin_dist($plugin, $type_info, $reload = false) {
3900
-	include_spip('inc/plugin');
3901
-	$plugin = strtoupper($plugin);
3902
-	$plugins_actifs = liste_plugin_actifs();
3903
-
3904
-	if (!$plugin) {
3905
-		return serialize(array_keys($plugins_actifs));
3906
-	} elseif (empty($plugins_actifs[$plugin]) and !$reload) {
3907
-		return '';
3908
-	} elseif (($type_info == 'est_actif') and !$reload) {
3909
-		return $plugins_actifs[$plugin] ? 1 : 0;
3910
-	} elseif (isset($plugins_actifs[$plugin][$type_info]) and !$reload) {
3911
-		return $plugins_actifs[$plugin][$type_info];
3912
-	} else {
3913
-		$get_infos = charger_fonction('get_infos', 'plugins');
3914
-		// On prend en compte les extensions
3915
-		if (!is_dir($plugins_actifs[$plugin]['dir_type'])) {
3916
-			$dir_plugins = constant($plugins_actifs[$plugin]['dir_type']);
3917
-		} else {
3918
-			$dir_plugins = $plugins_actifs[$plugin]['dir_type'];
3919
-		}
3920
-		if (!$infos = $get_infos($plugins_actifs[$plugin]['dir'], $reload, $dir_plugins)) {
3921
-			return '';
3922
-		}
3923
-		if ($type_info == 'tout') {
3924
-			return $infos;
3925
-		} elseif ($type_info == 'est_actif') {
3926
-			return $infos ? 1 : 0;
3927
-		} else {
3928
-			return strval($infos[$type_info]);
3929
-		}
3930
-	}
3900
+    include_spip('inc/plugin');
3901
+    $plugin = strtoupper($plugin);
3902
+    $plugins_actifs = liste_plugin_actifs();
3903
+
3904
+    if (!$plugin) {
3905
+        return serialize(array_keys($plugins_actifs));
3906
+    } elseif (empty($plugins_actifs[$plugin]) and !$reload) {
3907
+        return '';
3908
+    } elseif (($type_info == 'est_actif') and !$reload) {
3909
+        return $plugins_actifs[$plugin] ? 1 : 0;
3910
+    } elseif (isset($plugins_actifs[$plugin][$type_info]) and !$reload) {
3911
+        return $plugins_actifs[$plugin][$type_info];
3912
+    } else {
3913
+        $get_infos = charger_fonction('get_infos', 'plugins');
3914
+        // On prend en compte les extensions
3915
+        if (!is_dir($plugins_actifs[$plugin]['dir_type'])) {
3916
+            $dir_plugins = constant($plugins_actifs[$plugin]['dir_type']);
3917
+        } else {
3918
+            $dir_plugins = $plugins_actifs[$plugin]['dir_type'];
3919
+        }
3920
+        if (!$infos = $get_infos($plugins_actifs[$plugin]['dir'], $reload, $dir_plugins)) {
3921
+            return '';
3922
+        }
3923
+        if ($type_info == 'tout') {
3924
+            return $infos;
3925
+        } elseif ($type_info == 'est_actif') {
3926
+            return $infos ? 1 : 0;
3927
+        } else {
3928
+            return strval($infos[$type_info]);
3929
+        }
3930
+    }
3931 3931
 }
3932 3932
 
3933 3933
 
@@ -3954,9 +3954,9 @@  discard block
 block discarded – undo
3954 3954
  *     Code HTML de l'image de puce de statut à insérer (et du menu de changement si présent)
3955 3955
  */
3956 3956
 function puce_changement_statut($id_objet, $statut, $id_rubrique, $type, $ajax = false) {
3957
-	$puce_statut = charger_fonction('puce_statut', 'inc');
3957
+    $puce_statut = charger_fonction('puce_statut', 'inc');
3958 3958
 
3959
-	return $puce_statut($id_objet, $statut, $id_rubrique, $type, $ajax);
3959
+    return $puce_statut($id_objet, $statut, $id_rubrique, $type, $ajax);
3960 3960
 }
3961 3961
 
3962 3962
 
@@ -3986,19 +3986,19 @@  discard block
 block discarded – undo
3986 3986
  *     Code HTML de l'image de puce de statut à insérer (et du menu de changement si présent)
3987 3987
  */
3988 3988
 function filtre_puce_statut_dist($statut, $objet, $id_objet = 0, $id_parent = 0) {
3989
-	static $puce_statut = null;
3990
-	if (!$puce_statut) {
3991
-		$puce_statut = charger_fonction('puce_statut', 'inc');
3992
-	}
3989
+    static $puce_statut = null;
3990
+    if (!$puce_statut) {
3991
+        $puce_statut = charger_fonction('puce_statut', 'inc');
3992
+    }
3993 3993
 
3994
-	return $puce_statut(
3995
-		$id_objet,
3996
-		$statut,
3997
-		$id_parent,
3998
-		$objet,
3999
-		false,
4000
-		objet_info($objet, 'editable') ? _ACTIVER_PUCE_RAPIDE : false
4001
-	);
3994
+    return $puce_statut(
3995
+        $id_objet,
3996
+        $statut,
3997
+        $id_parent,
3998
+        $objet,
3999
+        false,
4000
+        objet_info($objet, 'editable') ? _ACTIVER_PUCE_RAPIDE : false
4001
+    );
4002 4002
 }
4003 4003
 
4004 4004
 
@@ -4025,98 +4025,98 @@  discard block
 block discarded – undo
4025 4025
  *   hash du contexte
4026 4026
  */
4027 4027
 function encoder_contexte_ajax($c, $form = '', $emboite = null, $ajaxid = '') {
4028
-	$env = null;
4029
-	if (
4030
-		is_string($c)
4031
-		and @unserialize($c) !== false
4032
-	) {
4033
-		$c = unserialize($c);
4034
-	}
4035
-
4036
-	// supprimer les parametres debut_x
4037
-	// pour que la pagination ajax ne soit pas plantee
4038
-	// si on charge la page &debut_x=1 : car alors en cliquant sur l'item 0,
4039
-	// le debut_x=0 n'existe pas, et on resterait sur 1
4040
-	if (is_array($c)) {
4041
-		foreach ($c as $k => $v) {
4042
-			if (strpos($k, 'debut_') === 0) {
4043
-				unset($c[$k]);
4044
-			}
4045
-		}
4046
-	}
4047
-
4048
-	if (!function_exists('calculer_cle_action')) {
4049
-		include_spip('inc/securiser_action');
4050
-	}
4051
-
4052
-	$c = serialize($c);
4053
-	$cle = calculer_cle_action($form . $c);
4054
-	$c = "$cle:$c";
4055
-
4056
-	// on ne stocke pas les contextes dans des fichiers en cache
4057
-	// par defaut, sauf si cette configuration a été forcée
4058
-	// OU que la longueur de l’argument géneré est plus long
4059
-	// que ce qui est toléré.
4060
-	$cache_contextes_ajax = (defined('_CACHE_CONTEXTES_AJAX') and _CACHE_CONTEXTES_AJAX);
4061
-	if (!$cache_contextes_ajax) {
4062
-		$env = $c;
4063
-		if (function_exists('gzdeflate') && function_exists('gzinflate')) {
4064
-			$env = gzdeflate($env);
4065
-		}
4066
-		$env = _xor($env);
4067
-		$env = base64_encode($env);
4068
-		$len = strlen($env);
4069
-		// Si l’url est trop longue pour le navigateur
4070
-		$max_len = _CACHE_CONTEXTES_AJAX_SUR_LONGUEUR;
4071
-		if ($len > $max_len) {
4072
-			$cache_contextes_ajax = true;
4073
-			spip_log(
4074
-				'Contextes AJAX forces en fichiers !'
4075
-				. ' Cela arrive lorsque la valeur du contexte'
4076
-				. " depasse la longueur maximale autorisee ($max_len). Ici : $len.",
4077
-				_LOG_AVERTISSEMENT
4078
-			);
4079
-		}
4080
-		// Sinon si Suhosin est actif et a une la valeur maximale des variables en GET...
4081
-		elseif (
4082
-			$max_len = @ini_get('suhosin.get.max_value_length')
4083
-			and $max_len < $len
4084
-		) {
4085
-			$cache_contextes_ajax = true;
4086
-			spip_log('Contextes AJAX forces en fichiers !'
4087
-				. ' Cela arrive lorsque la valeur du contexte'
4088
-				. ' depasse la longueur maximale autorisee par Suhosin'
4089
-				. " ($max_len) dans 'suhosin.get.max_value_length'. Ici : $len."
4090
-				. ' Vous devriez modifier les parametres de Suhosin'
4091
-				. ' pour accepter au moins 1024 caracteres.', _LOG_AVERTISSEMENT);
4092
-		}
4093
-	}
4094
-
4095
-	if ($cache_contextes_ajax) {
4096
-		$dir = sous_repertoire(_DIR_CACHE, 'contextes');
4097
-		// stocker les contextes sur disque et ne passer qu'un hash dans l'url
4098
-		$md5 = md5($c);
4099
-		ecrire_fichier("$dir/c$md5", $c);
4100
-		$env = $md5;
4101
-	}
4102
-
4103
-	if ($emboite === null) {
4104
-		return $env;
4105
-	}
4106
-	if (!trim($emboite)) {
4107
-		return '';
4108
-	}
4109
-	// toujours encoder l'url source dans le bloc ajax
4110
-	$r = self();
4111
-	$r = ' data-origin="' . $r . '"';
4112
-	$class = 'ajaxbloc';
4113
-	if ($ajaxid and is_string($ajaxid)) {
4114
-		// ajaxid est normalement conforme a un nom de classe css
4115
-		// on ne verifie pas la conformite, mais on passe entites_html par dessus par precaution
4116
-		$class .= ' ajax-id-' . entites_html($ajaxid);
4117
-	}
4118
-
4119
-	return "<div class='$class' " . "data-ajax-env='$env'$r>\n$emboite</div><!--ajaxbloc-->\n";
4028
+    $env = null;
4029
+    if (
4030
+        is_string($c)
4031
+        and @unserialize($c) !== false
4032
+    ) {
4033
+        $c = unserialize($c);
4034
+    }
4035
+
4036
+    // supprimer les parametres debut_x
4037
+    // pour que la pagination ajax ne soit pas plantee
4038
+    // si on charge la page &debut_x=1 : car alors en cliquant sur l'item 0,
4039
+    // le debut_x=0 n'existe pas, et on resterait sur 1
4040
+    if (is_array($c)) {
4041
+        foreach ($c as $k => $v) {
4042
+            if (strpos($k, 'debut_') === 0) {
4043
+                unset($c[$k]);
4044
+            }
4045
+        }
4046
+    }
4047
+
4048
+    if (!function_exists('calculer_cle_action')) {
4049
+        include_spip('inc/securiser_action');
4050
+    }
4051
+
4052
+    $c = serialize($c);
4053
+    $cle = calculer_cle_action($form . $c);
4054
+    $c = "$cle:$c";
4055
+
4056
+    // on ne stocke pas les contextes dans des fichiers en cache
4057
+    // par defaut, sauf si cette configuration a été forcée
4058
+    // OU que la longueur de l’argument géneré est plus long
4059
+    // que ce qui est toléré.
4060
+    $cache_contextes_ajax = (defined('_CACHE_CONTEXTES_AJAX') and _CACHE_CONTEXTES_AJAX);
4061
+    if (!$cache_contextes_ajax) {
4062
+        $env = $c;
4063
+        if (function_exists('gzdeflate') && function_exists('gzinflate')) {
4064
+            $env = gzdeflate($env);
4065
+        }
4066
+        $env = _xor($env);
4067
+        $env = base64_encode($env);
4068
+        $len = strlen($env);
4069
+        // Si l’url est trop longue pour le navigateur
4070
+        $max_len = _CACHE_CONTEXTES_AJAX_SUR_LONGUEUR;
4071
+        if ($len > $max_len) {
4072
+            $cache_contextes_ajax = true;
4073
+            spip_log(
4074
+                'Contextes AJAX forces en fichiers !'
4075
+                . ' Cela arrive lorsque la valeur du contexte'
4076
+                . " depasse la longueur maximale autorisee ($max_len). Ici : $len.",
4077
+                _LOG_AVERTISSEMENT
4078
+            );
4079
+        }
4080
+        // Sinon si Suhosin est actif et a une la valeur maximale des variables en GET...
4081
+        elseif (
4082
+            $max_len = @ini_get('suhosin.get.max_value_length')
4083
+            and $max_len < $len
4084
+        ) {
4085
+            $cache_contextes_ajax = true;
4086
+            spip_log('Contextes AJAX forces en fichiers !'
4087
+                . ' Cela arrive lorsque la valeur du contexte'
4088
+                . ' depasse la longueur maximale autorisee par Suhosin'
4089
+                . " ($max_len) dans 'suhosin.get.max_value_length'. Ici : $len."
4090
+                . ' Vous devriez modifier les parametres de Suhosin'
4091
+                . ' pour accepter au moins 1024 caracteres.', _LOG_AVERTISSEMENT);
4092
+        }
4093
+    }
4094
+
4095
+    if ($cache_contextes_ajax) {
4096
+        $dir = sous_repertoire(_DIR_CACHE, 'contextes');
4097
+        // stocker les contextes sur disque et ne passer qu'un hash dans l'url
4098
+        $md5 = md5($c);
4099
+        ecrire_fichier("$dir/c$md5", $c);
4100
+        $env = $md5;
4101
+    }
4102
+
4103
+    if ($emboite === null) {
4104
+        return $env;
4105
+    }
4106
+    if (!trim($emboite)) {
4107
+        return '';
4108
+    }
4109
+    // toujours encoder l'url source dans le bloc ajax
4110
+    $r = self();
4111
+    $r = ' data-origin="' . $r . '"';
4112
+    $class = 'ajaxbloc';
4113
+    if ($ajaxid and is_string($ajaxid)) {
4114
+        // ajaxid est normalement conforme a un nom de classe css
4115
+        // on ne verifie pas la conformite, mais on passe entites_html par dessus par precaution
4116
+        $class .= ' ajax-id-' . entites_html($ajaxid);
4117
+    }
4118
+
4119
+    return "<div class='$class' " . "data-ajax-env='$env'$r>\n$emboite</div><!--ajaxbloc-->\n";
4120 4120
 }
4121 4121
 
4122 4122
 /**
@@ -4136,37 +4136,37 @@  discard block
 block discarded – undo
4136 4136
  *   - false : erreur de décodage
4137 4137
  */
4138 4138
 function decoder_contexte_ajax($c, $form = '') {
4139
-	if (!function_exists('calculer_cle_action')) {
4140
-		include_spip('inc/securiser_action');
4141
-	}
4142
-	if (
4143
-		((defined('_CACHE_CONTEXTES_AJAX') and _CACHE_CONTEXTES_AJAX) or strlen($c) == 32)
4144
-		and $dir = sous_repertoire(_DIR_CACHE, 'contextes')
4145
-		and lire_fichier("$dir/c$c", $contexte)
4146
-	) {
4147
-		$c = $contexte;
4148
-	} else {
4149
-		$c = @base64_decode($c);
4150
-		$c = _xor($c);
4151
-		if (function_exists('gzdeflate') && function_exists('gzinflate')) {
4152
-			$c = @gzinflate($c);
4153
-		}
4154
-	}
4155
-
4156
-	// extraire la signature en debut de contexte
4157
-	// et la verifier avant de deserializer
4158
-	// format : signature:donneesserializees
4159
-	if ($p = strpos($c, ':')) {
4160
-		$cle = substr($c, 0, $p);
4161
-		$c = substr($c, $p + 1);
4162
-
4163
-		if ($cle == calculer_cle_action($form . $c)) {
4164
-			$env = @unserialize($c);
4165
-			return $env;
4166
-		}
4167
-	}
4168
-
4169
-	return false;
4139
+    if (!function_exists('calculer_cle_action')) {
4140
+        include_spip('inc/securiser_action');
4141
+    }
4142
+    if (
4143
+        ((defined('_CACHE_CONTEXTES_AJAX') and _CACHE_CONTEXTES_AJAX) or strlen($c) == 32)
4144
+        and $dir = sous_repertoire(_DIR_CACHE, 'contextes')
4145
+        and lire_fichier("$dir/c$c", $contexte)
4146
+    ) {
4147
+        $c = $contexte;
4148
+    } else {
4149
+        $c = @base64_decode($c);
4150
+        $c = _xor($c);
4151
+        if (function_exists('gzdeflate') && function_exists('gzinflate')) {
4152
+            $c = @gzinflate($c);
4153
+        }
4154
+    }
4155
+
4156
+    // extraire la signature en debut de contexte
4157
+    // et la verifier avant de deserializer
4158
+    // format : signature:donneesserializees
4159
+    if ($p = strpos($c, ':')) {
4160
+        $cle = substr($c, 0, $p);
4161
+        $c = substr($c, $p + 1);
4162
+
4163
+        if ($cle == calculer_cle_action($form . $c)) {
4164
+            $env = @unserialize($c);
4165
+            return $env;
4166
+        }
4167
+    }
4168
+
4169
+    return false;
4170 4170
 }
4171 4171
 
4172 4172
 
@@ -4184,20 +4184,20 @@  discard block
 block discarded – undo
4184 4184
  *    Message décrypté ou encrypté
4185 4185
  **/
4186 4186
 function _xor($message, $key = null) {
4187
-	if (is_null($key)) {
4188
-		if (!function_exists('calculer_cle_action')) {
4189
-			include_spip('inc/securiser_action');
4190
-		}
4191
-		$key = pack('H*', calculer_cle_action('_xor'));
4192
-	}
4187
+    if (is_null($key)) {
4188
+        if (!function_exists('calculer_cle_action')) {
4189
+            include_spip('inc/securiser_action');
4190
+        }
4191
+        $key = pack('H*', calculer_cle_action('_xor'));
4192
+    }
4193 4193
 
4194
-	$keylen = strlen($key);
4195
-	$messagelen = strlen($message);
4196
-	for ($i = 0; $i < $messagelen; $i++) {
4197
-		$message[$i] = ~($message[$i] ^ $key[$i % $keylen]);
4198
-	}
4194
+    $keylen = strlen($key);
4195
+    $messagelen = strlen($message);
4196
+    for ($i = 0; $i < $messagelen; $i++) {
4197
+        $message[$i] = ~($message[$i] ^ $key[$i % $keylen]);
4198
+    }
4199 4199
 
4200
-	return $message;
4200
+    return $message;
4201 4201
 }
4202 4202
 
4203 4203
 /**
@@ -4211,7 +4211,7 @@  discard block
 block discarded – undo
4211 4211
  * @return string
4212 4212
  */
4213 4213
 function url_reponse_forum($texte) {
4214
- return $texte;
4214
+    return $texte;
4215 4215
 }
4216 4216
 
4217 4217
 /**
@@ -4225,7 +4225,7 @@  discard block
 block discarded – undo
4225 4225
  * @return string
4226 4226
  */
4227 4227
 function url_rss_forum($texte) {
4228
- return $texte;
4228
+    return $texte;
4229 4229
 }
4230 4230
 
4231 4231
 
@@ -4264,37 +4264,37 @@  discard block
 block discarded – undo
4264 4264
  *   Code HTML
4265 4265
  */
4266 4266
 function lien_ou_expose($url, $libelle = null, $on = false, $class = '', $title = '', $rel = '', $evt = '') {
4267
-	if ($on) {
4268
-		$bal = 'strong';
4269
-		$class = '';
4270
-		$att = '';
4271
-		// si $on passe la balise et optionnelement une ou ++classe
4272
-		// a.active span.selected.active etc....
4273
-		if (is_string($on) and (strncmp($on, 'a', 1) == 0 or strncmp($on, 'span', 4) == 0 or strncmp($on, 'strong', 6) == 0)) {
4274
-			$on = explode('.', $on);
4275
-			// on verifie que c'est exactement une des 3 balises a, span ou strong
4276
-			if (in_array(reset($on), ['a', 'span', 'strong'])) {
4277
-				$bal = array_shift($on);
4278
-				$class = implode(' ', $on);
4279
-				if ($bal == 'a') {
4280
-					$att = 'href="#" ';
4281
-				}
4282
-			}
4283
-		}
4284
-		$att .= 'class="' . ($class ? attribut_html($class) . ' ' : '') . (defined('_LIEN_OU_EXPOSE_CLASS_ON') ? _LIEN_OU_EXPOSE_CLASS_ON : 'on') . '"';
4285
-	} else {
4286
-		$bal = 'a';
4287
-		$att = "href='$url'"
4288
-			. ($title ? " title='" . attribut_html($title) . "'" : '')
4289
-			. ($class ? " class='" . attribut_html($class) . "'" : '')
4290
-			. ($rel ? " rel='" . attribut_html($rel) . "'" : '')
4291
-			. $evt;
4292
-	}
4293
-	if ($libelle === null) {
4294
-		$libelle = $url;
4295
-	}
4296
-
4297
-	return "<$bal $att>$libelle</$bal>";
4267
+    if ($on) {
4268
+        $bal = 'strong';
4269
+        $class = '';
4270
+        $att = '';
4271
+        // si $on passe la balise et optionnelement une ou ++classe
4272
+        // a.active span.selected.active etc....
4273
+        if (is_string($on) and (strncmp($on, 'a', 1) == 0 or strncmp($on, 'span', 4) == 0 or strncmp($on, 'strong', 6) == 0)) {
4274
+            $on = explode('.', $on);
4275
+            // on verifie que c'est exactement une des 3 balises a, span ou strong
4276
+            if (in_array(reset($on), ['a', 'span', 'strong'])) {
4277
+                $bal = array_shift($on);
4278
+                $class = implode(' ', $on);
4279
+                if ($bal == 'a') {
4280
+                    $att = 'href="#" ';
4281
+                }
4282
+            }
4283
+        }
4284
+        $att .= 'class="' . ($class ? attribut_html($class) . ' ' : '') . (defined('_LIEN_OU_EXPOSE_CLASS_ON') ? _LIEN_OU_EXPOSE_CLASS_ON : 'on') . '"';
4285
+    } else {
4286
+        $bal = 'a';
4287
+        $att = "href='$url'"
4288
+            . ($title ? " title='" . attribut_html($title) . "'" : '')
4289
+            . ($class ? " class='" . attribut_html($class) . "'" : '')
4290
+            . ($rel ? " rel='" . attribut_html($rel) . "'" : '')
4291
+            . $evt;
4292
+    }
4293
+    if ($libelle === null) {
4294
+        $libelle = $url;
4295
+    }
4296
+
4297
+    return "<$bal $att>$libelle</$bal>";
4298 4298
 }
4299 4299
 
4300 4300
 
@@ -4311,39 +4311,39 @@  discard block
 block discarded – undo
4311 4311
  * @return string : la chaine de langue finale en utilisant la fonction _T()
4312 4312
  */
4313 4313
 function singulier_ou_pluriel($nb, $chaine_un, $chaine_plusieurs, $var = 'nb', $vars = []) {
4314
-	static $local_singulier_ou_pluriel = [];
4315
-
4316
-	// si nb=0 ou pas de $vars valide on retourne une chaine vide, a traiter par un |sinon
4317
-	if (!is_numeric($nb) or $nb == 0) {
4318
-		return '';
4319
-	}
4320
-	if (!is_array($vars)) {
4321
-		return '';
4322
-	}
4323
-
4324
-	$langue = $GLOBALS['spip_lang'];
4325
-	if (!isset($local_singulier_ou_pluriel[$langue])) {
4326
-		$local_singulier_ou_pluriel[$langue] = false;
4327
-		if (
4328
-			$f = charger_fonction("singulier_ou_pluriel_${langue}", 'inc', true)
4329
-			or $f = charger_fonction('singulier_ou_pluriel', 'inc', true)
4330
-		) {
4331
-			$local_singulier_ou_pluriel[$langue] = $f;
4332
-		}
4333
-	}
4334
-
4335
-	// si on a une surcharge on l'utilise
4336
-	if ($local_singulier_ou_pluriel[$langue]) {
4337
-		return ($local_singulier_ou_pluriel[$langue])($nb, $chaine_un, $chaine_plusieurs, $var, $vars);
4338
-	}
4339
-
4340
-	// sinon traitement par defaut
4341
-	$vars[$var] = $nb;
4342
-	if ($nb >= 2) {
4343
-		return _T($chaine_plusieurs, $vars);
4344
-	} else {
4345
-		return _T($chaine_un, $vars);
4346
-	}
4314
+    static $local_singulier_ou_pluriel = [];
4315
+
4316
+    // si nb=0 ou pas de $vars valide on retourne une chaine vide, a traiter par un |sinon
4317
+    if (!is_numeric($nb) or $nb == 0) {
4318
+        return '';
4319
+    }
4320
+    if (!is_array($vars)) {
4321
+        return '';
4322
+    }
4323
+
4324
+    $langue = $GLOBALS['spip_lang'];
4325
+    if (!isset($local_singulier_ou_pluriel[$langue])) {
4326
+        $local_singulier_ou_pluriel[$langue] = false;
4327
+        if (
4328
+            $f = charger_fonction("singulier_ou_pluriel_${langue}", 'inc', true)
4329
+            or $f = charger_fonction('singulier_ou_pluriel', 'inc', true)
4330
+        ) {
4331
+            $local_singulier_ou_pluriel[$langue] = $f;
4332
+        }
4333
+    }
4334
+
4335
+    // si on a une surcharge on l'utilise
4336
+    if ($local_singulier_ou_pluriel[$langue]) {
4337
+        return ($local_singulier_ou_pluriel[$langue])($nb, $chaine_un, $chaine_plusieurs, $var, $vars);
4338
+    }
4339
+
4340
+    // sinon traitement par defaut
4341
+    $vars[$var] = $nb;
4342
+    if ($nb >= 2) {
4343
+        return _T($chaine_plusieurs, $vars);
4344
+    } else {
4345
+        return _T($chaine_un, $vars);
4346
+    }
4347 4347
 }
4348 4348
 
4349 4349
 
@@ -4371,73 +4371,73 @@  discard block
 block discarded – undo
4371 4371
  */
4372 4372
 function prepare_icone_base($type, $lien, $texte, $fond, $fonction = '', $class = '', $javascript = '') {
4373 4373
 
4374
-	$class_lien = $class_bouton = $class;
4375
-
4376
-	// Normaliser la fonction et compléter la classe en fonction
4377
-	if (in_array($fonction, ['del', 'supprimer.gif'])) {
4378
-		$class_lien .= ' danger';
4379
-		$class_bouton .= ' btn_danger';
4380
-	} elseif ($fonction == 'rien.gif') {
4381
-		$fonction = '';
4382
-	} elseif ($fonction == 'delsafe') {
4383
-		$fonction = 'del';
4384
-	}
4385
-
4386
-	$fond_origine = $fond;
4387
-	// Remappage des icone : article-24.png+new => article-new-24.png
4388
-	if ($icone_renommer = charger_fonction('icone_renommer', 'inc', true)) {
4389
-		[$fond, $fonction] = $icone_renommer($fond, $fonction);
4390
-	}
4391
-
4392
-	// Ajouter le type d'objet dans la classe
4393
-	$objet_type = substr(basename($fond), 0, -4);
4394
-	$class_lien .= " $objet_type";
4395
-	$class_bouton .= " $objet_type";
4396
-
4397
-	// Texte
4398
-	$alt = attribut_html($texte);
4399
-	$title = " title=\"$alt\""; // est-ce pertinent de doubler le alt par un title ?
4400
-
4401
-	// Liens : préparer les classes ajax
4402
-	$ajax = '';
4403
-	if ($type === 'lien') {
4404
-		if (strpos($class_lien, 'ajax') !== false) {
4405
-			$ajax = 'ajax';
4406
-			if (strpos($class_lien, 'preload') !== false) {
4407
-				$ajax .= ' preload';
4408
-			}
4409
-			if (strpos($class_lien, 'nocache') !== false) {
4410
-				$ajax .= ' nocache';
4411
-			}
4412
-			$ajax = " class='$ajax'";
4413
-		}
4414
-	}
4415
-
4416
-	// Repérer la taille et l'ajouter dans la classe
4417
-	$size = 24;
4418
-	if (
4419
-		preg_match('/-([0-9]{1,3})[.](gif|png|svg)$/i', $fond, $match)
4420
-		or preg_match('/-([0-9]{1,3})([.](gif|png|svg))?$/i', $fond_origine, $match)
4421
-	) {
4422
-		$size = $match[1];
4423
-	}
4424
-	$class_lien .= " s$size";
4425
-	$class_bouton .= " s$size";
4426
-
4427
-	// Icône
4428
-	$icone = http_img_pack($fond, $alt, "width='$size' height='$size'");
4429
-	$icone = '<span class="icone-image' . ($fonction ? " icone-fonction icone-fonction-$fonction" : '') . "\">$icone</span>";
4430
-
4431
-	// Markup final
4432
-	if ($type == 'lien') {
4433
-		return "<span class='icone $class_lien'>"
4434
-		. "<a href='$lien'$title$ajax$javascript>"
4435
-		. $icone
4436
-		. "<b>$texte</b>"
4437
-		. "</a></span>\n";
4438
-	} else {
4439
-		return bouton_action("$icone $texte", $lien, $class_bouton, $javascript, $alt);
4440
-	}
4374
+    $class_lien = $class_bouton = $class;
4375
+
4376
+    // Normaliser la fonction et compléter la classe en fonction
4377
+    if (in_array($fonction, ['del', 'supprimer.gif'])) {
4378
+        $class_lien .= ' danger';
4379
+        $class_bouton .= ' btn_danger';
4380
+    } elseif ($fonction == 'rien.gif') {
4381
+        $fonction = '';
4382
+    } elseif ($fonction == 'delsafe') {
4383
+        $fonction = 'del';
4384
+    }
4385
+
4386
+    $fond_origine = $fond;
4387
+    // Remappage des icone : article-24.png+new => article-new-24.png
4388
+    if ($icone_renommer = charger_fonction('icone_renommer', 'inc', true)) {
4389
+        [$fond, $fonction] = $icone_renommer($fond, $fonction);
4390
+    }
4391
+
4392
+    // Ajouter le type d'objet dans la classe
4393
+    $objet_type = substr(basename($fond), 0, -4);
4394
+    $class_lien .= " $objet_type";
4395
+    $class_bouton .= " $objet_type";
4396
+
4397
+    // Texte
4398
+    $alt = attribut_html($texte);
4399
+    $title = " title=\"$alt\""; // est-ce pertinent de doubler le alt par un title ?
4400
+
4401
+    // Liens : préparer les classes ajax
4402
+    $ajax = '';
4403
+    if ($type === 'lien') {
4404
+        if (strpos($class_lien, 'ajax') !== false) {
4405
+            $ajax = 'ajax';
4406
+            if (strpos($class_lien, 'preload') !== false) {
4407
+                $ajax .= ' preload';
4408
+            }
4409
+            if (strpos($class_lien, 'nocache') !== false) {
4410
+                $ajax .= ' nocache';
4411
+            }
4412
+            $ajax = " class='$ajax'";
4413
+        }
4414
+    }
4415
+
4416
+    // Repérer la taille et l'ajouter dans la classe
4417
+    $size = 24;
4418
+    if (
4419
+        preg_match('/-([0-9]{1,3})[.](gif|png|svg)$/i', $fond, $match)
4420
+        or preg_match('/-([0-9]{1,3})([.](gif|png|svg))?$/i', $fond_origine, $match)
4421
+    ) {
4422
+        $size = $match[1];
4423
+    }
4424
+    $class_lien .= " s$size";
4425
+    $class_bouton .= " s$size";
4426
+
4427
+    // Icône
4428
+    $icone = http_img_pack($fond, $alt, "width='$size' height='$size'");
4429
+    $icone = '<span class="icone-image' . ($fonction ? " icone-fonction icone-fonction-$fonction" : '') . "\">$icone</span>";
4430
+
4431
+    // Markup final
4432
+    if ($type == 'lien') {
4433
+        return "<span class='icone $class_lien'>"
4434
+        . "<a href='$lien'$title$ajax$javascript>"
4435
+        . $icone
4436
+        . "<b>$texte</b>"
4437
+        . "</a></span>\n";
4438
+    } else {
4439
+        return bouton_action("$icone $texte", $lien, $class_bouton, $javascript, $alt);
4440
+    }
4441 4441
 }
4442 4442
 
4443 4443
 /**
@@ -4461,7 +4461,7 @@  discard block
 block discarded – undo
4461 4461
  *     Code HTML du lien
4462 4462
  **/
4463 4463
 function icone_base($lien, $texte, $fond, $fonction = '', $class = '', $javascript = '') {
4464
-	return prepare_icone_base('lien', $lien, $texte, $fond, $fonction, $class, $javascript);
4464
+    return prepare_icone_base('lien', $lien, $texte, $fond, $fonction, $class, $javascript);
4465 4465
 }
4466 4466
 
4467 4467
 /**
@@ -4496,7 +4496,7 @@  discard block
 block discarded – undo
4496 4496
  *     Code HTML du lien
4497 4497
  **/
4498 4498
 function filtre_icone_verticale_dist($lien, $texte, $fond, $fonction = '', $class = '', $javascript = '') {
4499
-	return icone_base($lien, $texte, $fond, $fonction, "verticale $class", $javascript);
4499
+    return icone_base($lien, $texte, $fond, $fonction, "verticale $class", $javascript);
4500 4500
 }
4501 4501
 
4502 4502
 /**
@@ -4541,7 +4541,7 @@  discard block
 block discarded – undo
4541 4541
  *     Code HTML du lien
4542 4542
  **/
4543 4543
 function filtre_icone_horizontale_dist($lien, $texte, $fond, $fonction = '', $class = '', $javascript = '') {
4544
-	return icone_base($lien, $texte, $fond, $fonction, "horizontale $class", $javascript);
4544
+    return icone_base($lien, $texte, $fond, $fonction, "horizontale $class", $javascript);
4545 4545
 }
4546 4546
 
4547 4547
 /**
@@ -4572,7 +4572,7 @@  discard block
 block discarded – undo
4572 4572
  *     Code HTML du lien
4573 4573
  **/
4574 4574
 function filtre_bouton_action_horizontal_dist($lien, $texte, $fond, $fonction = '', $class = '', $confirm = '') {
4575
-	return prepare_icone_base('bouton', $lien, $texte, $fond, $fonction, $class, $confirm);
4575
+    return prepare_icone_base('bouton', $lien, $texte, $fond, $fonction, $class, $confirm);
4576 4576
 }
4577 4577
 
4578 4578
 /**
@@ -4603,7 +4603,7 @@  discard block
 block discarded – undo
4603 4603
  *     Code HTML du lien
4604 4604
  */
4605 4605
 function filtre_icone_dist($lien, $texte, $fond, $align = '', $fonction = '', $class = '', $javascript = '') {
4606
-	return icone_base($lien, $texte, $fond, $fonction, "verticale $align $class", $javascript);
4606
+    return icone_base($lien, $texte, $fond, $fonction, "verticale $align $class", $javascript);
4607 4607
 }
4608 4608
 
4609 4609
 
@@ -4625,7 +4625,7 @@  discard block
 block discarded – undo
4625 4625
  * @return array Liste des éléments
4626 4626
  */
4627 4627
 function filtre_explode_dist($a, $b) {
4628
-	return explode($b, (string) $a);
4628
+    return explode($b, (string) $a);
4629 4629
 }
4630 4630
 
4631 4631
 /**
@@ -4646,7 +4646,7 @@  discard block
 block discarded – undo
4646 4646
  * @return string Texte
4647 4647
  */
4648 4648
 function filtre_implode_dist($a, $b) {
4649
-	return is_array($a) ? implode($b, $a) : $a;
4649
+    return is_array($a) ? implode($b, $a) : $a;
4650 4650
 }
4651 4651
 
4652 4652
 /**
@@ -4655,22 +4655,22 @@  discard block
 block discarded – undo
4655 4655
  * @return string Code CSS
4656 4656
  */
4657 4657
 function bando_images_background() {
4658
-	include_spip('inc/bandeau');
4659
-	// recuperer tous les boutons et leurs images
4660
-	$boutons = definir_barre_boutons(definir_barre_contexte(), true, false);
4658
+    include_spip('inc/bandeau');
4659
+    // recuperer tous les boutons et leurs images
4660
+    $boutons = definir_barre_boutons(definir_barre_contexte(), true, false);
4661 4661
 
4662
-	$res = '';
4663
-	foreach ($boutons as $page => $detail) {
4664
-		$selecteur = (in_array($page, ['outils_rapides', 'outils_collaboratifs']) ? '' : '.navigation_avec_icones ');
4665
-		foreach ($detail->sousmenu as $souspage => $sousdetail) {
4666
-			if ($sousdetail->icone and strlen(trim($sousdetail->icone))) {
4667
-				$img = http_img_variante_svg_si_possible($sousdetail->icone);
4668
-				$res .= "\n$selecteur.bando2_$souspage {background-image:url($img);}";
4669
-			}
4670
-		}
4671
-	}
4662
+    $res = '';
4663
+    foreach ($boutons as $page => $detail) {
4664
+        $selecteur = (in_array($page, ['outils_rapides', 'outils_collaboratifs']) ? '' : '.navigation_avec_icones ');
4665
+        foreach ($detail->sousmenu as $souspage => $sousdetail) {
4666
+            if ($sousdetail->icone and strlen(trim($sousdetail->icone))) {
4667
+                $img = http_img_variante_svg_si_possible($sousdetail->icone);
4668
+                $res .= "\n$selecteur.bando2_$souspage {background-image:url($img);}";
4669
+            }
4670
+        }
4671
+    }
4672 4672
 
4673
-	return $res;
4673
+    return $res;
4674 4674
 }
4675 4675
 
4676 4676
 /**
@@ -4695,27 +4695,27 @@  discard block
 block discarded – undo
4695 4695
  */
4696 4696
 function bouton_action($libelle, $url, $class = '', $confirm = '', $title = '', $callback = '') {
4697 4697
 
4698
-	// Classes : dispatcher `ajax` sur le formulaire
4699
-	$class_form = '';
4700
-	if (strpos($class, 'ajax') !== false) {
4701
-		$class_form = 'ajax';
4702
-		$class = str_replace('ajax', '', $class);
4703
-	}
4704
-	$class_btn = 'submit ' . trim($class);
4698
+    // Classes : dispatcher `ajax` sur le formulaire
4699
+    $class_form = '';
4700
+    if (strpos($class, 'ajax') !== false) {
4701
+        $class_form = 'ajax';
4702
+        $class = str_replace('ajax', '', $class);
4703
+    }
4704
+    $class_btn = 'submit ' . trim($class);
4705 4705
 
4706
-	if ($confirm) {
4707
-		$confirm = 'confirm("' . attribut_html($confirm) . '")';
4708
-		if ($callback) {
4709
-			$callback = "$confirm?($callback):false";
4710
-		} else {
4711
-			$callback = $confirm;
4712
-		}
4713
-	}
4714
-	$onclick = $callback ? " onclick='return " . addcslashes($callback, "'") . "'" : '';
4715
-	$title = $title ? " title='$title'" : '';
4706
+    if ($confirm) {
4707
+        $confirm = 'confirm("' . attribut_html($confirm) . '")';
4708
+        if ($callback) {
4709
+            $callback = "$confirm?($callback):false";
4710
+        } else {
4711
+            $callback = $confirm;
4712
+        }
4713
+    }
4714
+    $onclick = $callback ? " onclick='return " . addcslashes($callback, "'") . "'" : '';
4715
+    $title = $title ? " title='$title'" : '';
4716 4716
 
4717
-	return "<form class='bouton_action_post $class_form' method='post' action='$url'><div>" . form_hidden($url)
4718
-	. "<button type='submit' class='$class_btn'$title$onclick>$libelle</button></div></form>";
4717
+    return "<form class='bouton_action_post $class_form' method='post' action='$url'><div>" . form_hidden($url)
4718
+    . "<button type='submit' class='$class_btn'$title$onclick>$libelle</button></div></form>";
4719 4719
 }
4720 4720
 
4721 4721
 /**
@@ -4738,101 +4738,101 @@  discard block
 block discarded – undo
4738 4738
  * @return string
4739 4739
  */
4740 4740
 function generer_objet_info($id_objet, string $type_objet, string $info, string $etoile = '', array $params = []): string {
4741
-	static $trouver_table = null;
4742
-	static $objets;
4743
-
4744
-	// On verifie qu'on a tout ce qu'il faut
4745
-	$id_objet = intval($id_objet);
4746
-	if (!($id_objet and $type_objet and $info)) {
4747
-		return '';
4748
-	}
4749
-
4750
-	// si on a deja note que l'objet n'existe pas, ne pas aller plus loin
4751
-	if (isset($objets[$type_objet]) and $objets[$type_objet] === false) {
4752
-		return '';
4753
-	}
4754
-
4755
-	// Si on demande l'url, on retourne direct la fonction
4756
-	if ($info == 'url') {
4757
-		return generer_objet_url($id_objet, $type_objet, ...$params);
4758
-	}
4759
-
4760
-	// Sinon on va tout chercher dans la table et on garde en memoire
4761
-	$demande_titre = ($info === 'titre');
4762
-	$demande_introduction = ($info === 'introduction');
4763
-
4764
-	// On ne fait la requete que si on a pas deja l'objet ou si on demande le titre mais qu'on ne l'a pas encore
4765
-	if (
4766
-		!isset($objets[$type_objet][$id_objet])
4767
-		or
4768
-		($demande_titre and !isset($objets[$type_objet][$id_objet]['titre']))
4769
-	) {
4770
-		if (!$trouver_table) {
4771
-			$trouver_table = charger_fonction('trouver_table', 'base');
4772
-		}
4773
-		$desc = $trouver_table(table_objet_sql($type_objet));
4774
-		if (!$desc) {
4775
-			return $objets[$type_objet] = false;
4776
-		}
4777
-
4778
-		// Si on demande le titre, on le gere en interne
4779
-		$champ_titre = '';
4780
-		if ($demande_titre) {
4781
-			// si pas de titre declare mais champ titre, il sera peuple par le select *
4782
-			$champ_titre = (!empty($desc['titre'])) ? ', ' . $desc['titre'] : '';
4783
-		}
4784
-		include_spip('base/abstract_sql');
4785
-		include_spip('base/connect_sql');
4786
-		$objets[$type_objet][$id_objet] = sql_fetsel(
4787
-			'*' . $champ_titre,
4788
-			$desc['table_sql'],
4789
-			id_table_objet($type_objet) . ' = ' . intval($id_objet)
4790
-		);
4791
-
4792
-		// Toujours noter la longueur d'introduction, même si pas demandé cette fois-ci
4793
-		$objets[$type_objet]['introduction_longueur'] = $desc['introduction_longueur'] ?? null;
4794
-	}
4795
-
4796
-	// Pour les fonction generer_xxx, si on demande l'introduction,
4797
-	// ajouter la longueur au début des params supplémentaires
4798
-	if ($demande_introduction) {
4799
-		$introduction_longueur = $objets[$type_objet]['introduction_longueur'];
4800
-		array_unshift($params, $introduction_longueur);
4801
-	}
4802
-
4803
-	// Si la fonction generer_TYPE_TRUC existe, on l'utilise pour formater $info_generee
4804
-	if (
4805
-		$generer = charger_fonction("generer_${type_objet}_${info}", '', true)
4806
-		// @deprecated 4.1 generer_TRUC_TYPE
4807
-		or $generer = charger_fonction("generer_${info}_${type_objet}", '', true)
4808
-	) {
4809
-		$info_generee = $generer($id_objet, $objets[$type_objet][$id_objet], ...$params);
4810
-	}
4811
-	// Si la fonction generer_objet_TRUC existe, on l'utilise pour formater $info_generee
4812
-	elseif (
4813
-		$generer = charger_fonction("generer_objet_${info}", '', true)
4814
-		// @deprecated 4.1 generer_TRUC_entite
4815
-		or $generer = charger_fonction("generer_${info}_entite", '', true)
4816
-	) {
4817
-		$info_generee = $generer($id_objet, $type_objet, $objets[$type_objet][$id_objet], ...$params);
4818
-	} // Sinon on prend directement le champ SQL tel quel
4819
-	else {
4820
-		$info_generee = ($objets[$type_objet][$id_objet][$info] ?? '');
4821
-	}
4822
-
4823
-	// On va ensuite appliquer les traitements automatiques si besoin
4824
-	if (!$etoile) {
4825
-		// FIXME: on fournit un ENV minimum avec id et type et connect=''
4826
-		// mais ce fonctionnement est a ameliorer !
4827
-		$info_generee = appliquer_traitement_champ(
4828
-			$info_generee,
4829
-			$info,
4830
-			table_objet($type_objet),
4831
-			['id_objet' => $id_objet, 'objet' => $type_objet, '']
4832
-		);
4833
-	}
4834
-
4835
-	return $info_generee;
4741
+    static $trouver_table = null;
4742
+    static $objets;
4743
+
4744
+    // On verifie qu'on a tout ce qu'il faut
4745
+    $id_objet = intval($id_objet);
4746
+    if (!($id_objet and $type_objet and $info)) {
4747
+        return '';
4748
+    }
4749
+
4750
+    // si on a deja note que l'objet n'existe pas, ne pas aller plus loin
4751
+    if (isset($objets[$type_objet]) and $objets[$type_objet] === false) {
4752
+        return '';
4753
+    }
4754
+
4755
+    // Si on demande l'url, on retourne direct la fonction
4756
+    if ($info == 'url') {
4757
+        return generer_objet_url($id_objet, $type_objet, ...$params);
4758
+    }
4759
+
4760
+    // Sinon on va tout chercher dans la table et on garde en memoire
4761
+    $demande_titre = ($info === 'titre');
4762
+    $demande_introduction = ($info === 'introduction');
4763
+
4764
+    // On ne fait la requete que si on a pas deja l'objet ou si on demande le titre mais qu'on ne l'a pas encore
4765
+    if (
4766
+        !isset($objets[$type_objet][$id_objet])
4767
+        or
4768
+        ($demande_titre and !isset($objets[$type_objet][$id_objet]['titre']))
4769
+    ) {
4770
+        if (!$trouver_table) {
4771
+            $trouver_table = charger_fonction('trouver_table', 'base');
4772
+        }
4773
+        $desc = $trouver_table(table_objet_sql($type_objet));
4774
+        if (!$desc) {
4775
+            return $objets[$type_objet] = false;
4776
+        }
4777
+
4778
+        // Si on demande le titre, on le gere en interne
4779
+        $champ_titre = '';
4780
+        if ($demande_titre) {
4781
+            // si pas de titre declare mais champ titre, il sera peuple par le select *
4782
+            $champ_titre = (!empty($desc['titre'])) ? ', ' . $desc['titre'] : '';
4783
+        }
4784
+        include_spip('base/abstract_sql');
4785
+        include_spip('base/connect_sql');
4786
+        $objets[$type_objet][$id_objet] = sql_fetsel(
4787
+            '*' . $champ_titre,
4788
+            $desc['table_sql'],
4789
+            id_table_objet($type_objet) . ' = ' . intval($id_objet)
4790
+        );
4791
+
4792
+        // Toujours noter la longueur d'introduction, même si pas demandé cette fois-ci
4793
+        $objets[$type_objet]['introduction_longueur'] = $desc['introduction_longueur'] ?? null;
4794
+    }
4795
+
4796
+    // Pour les fonction generer_xxx, si on demande l'introduction,
4797
+    // ajouter la longueur au début des params supplémentaires
4798
+    if ($demande_introduction) {
4799
+        $introduction_longueur = $objets[$type_objet]['introduction_longueur'];
4800
+        array_unshift($params, $introduction_longueur);
4801
+    }
4802
+
4803
+    // Si la fonction generer_TYPE_TRUC existe, on l'utilise pour formater $info_generee
4804
+    if (
4805
+        $generer = charger_fonction("generer_${type_objet}_${info}", '', true)
4806
+        // @deprecated 4.1 generer_TRUC_TYPE
4807
+        or $generer = charger_fonction("generer_${info}_${type_objet}", '', true)
4808
+    ) {
4809
+        $info_generee = $generer($id_objet, $objets[$type_objet][$id_objet], ...$params);
4810
+    }
4811
+    // Si la fonction generer_objet_TRUC existe, on l'utilise pour formater $info_generee
4812
+    elseif (
4813
+        $generer = charger_fonction("generer_objet_${info}", '', true)
4814
+        // @deprecated 4.1 generer_TRUC_entite
4815
+        or $generer = charger_fonction("generer_${info}_entite", '', true)
4816
+    ) {
4817
+        $info_generee = $generer($id_objet, $type_objet, $objets[$type_objet][$id_objet], ...$params);
4818
+    } // Sinon on prend directement le champ SQL tel quel
4819
+    else {
4820
+        $info_generee = ($objets[$type_objet][$id_objet][$info] ?? '');
4821
+    }
4822
+
4823
+    // On va ensuite appliquer les traitements automatiques si besoin
4824
+    if (!$etoile) {
4825
+        // FIXME: on fournit un ENV minimum avec id et type et connect=''
4826
+        // mais ce fonctionnement est a ameliorer !
4827
+        $info_generee = appliquer_traitement_champ(
4828
+            $info_generee,
4829
+            $info,
4830
+            table_objet($type_objet),
4831
+            ['id_objet' => $id_objet, 'objet' => $type_objet, '']
4832
+        );
4833
+    }
4834
+
4835
+    return $info_generee;
4836 4836
 }
4837 4837
 
4838 4838
 /**
@@ -4840,7 +4840,7 @@  discard block
 block discarded – undo
4840 4840
  * @see generer_objet_info
4841 4841
  */
4842 4842
 function generer_info_entite($id_objet, $type_objet, $info, $etoile = '', $params = []) {
4843
-	return generer_objet_info(intval($id_objet), $type_objet, $info, $etoile, $params);
4843
+    return generer_objet_info(intval($id_objet), $type_objet, $info, $etoile, $params);
4844 4844
 }
4845 4845
 
4846 4846
 /**
@@ -4873,36 +4873,36 @@  discard block
 block discarded – undo
4873 4873
  */
4874 4874
 function generer_objet_introduction(int $id_objet, string $type_objet, array $ligne_sql, ?int $introduction_longueur = null, $longueur_ou_suite = null, ?string $suite = null, string $connect = ''): string {
4875 4875
 
4876
-	$descriptif = $ligne_sql['descriptif'] ?? '';
4877
-	$texte = $ligne_sql['texte'] ?? '';
4878
-	// En absence de descriptif, on se rabat sur chapo + texte
4879
-	if (isset($ligne_sql['chapo'])) {
4880
-		$chapo = $ligne_sql['chapo'];
4881
-		$texte = strlen($descriptif) ?
4882
-			'' :
4883
-			"$chapo \n\n $texte";
4884
-	}
4876
+    $descriptif = $ligne_sql['descriptif'] ?? '';
4877
+    $texte = $ligne_sql['texte'] ?? '';
4878
+    // En absence de descriptif, on se rabat sur chapo + texte
4879
+    if (isset($ligne_sql['chapo'])) {
4880
+        $chapo = $ligne_sql['chapo'];
4881
+        $texte = strlen($descriptif) ?
4882
+            '' :
4883
+            "$chapo \n\n $texte";
4884
+    }
4885 4885
 
4886
-	// Longueur en paramètre, sinon celle renseignée dans la description de l'objet, sinon valeur en dur
4887
-	if (!intval($longueur_ou_suite)) {
4888
-		$longueur = intval($introduction_longueur ?: 600);
4889
-	} else {
4890
-		$longueur = intval($longueur_ou_suite);
4891
-	}
4886
+    // Longueur en paramètre, sinon celle renseignée dans la description de l'objet, sinon valeur en dur
4887
+    if (!intval($longueur_ou_suite)) {
4888
+        $longueur = intval($introduction_longueur ?: 600);
4889
+    } else {
4890
+        $longueur = intval($longueur_ou_suite);
4891
+    }
4892 4892
 
4893
-	// On peut optionnellement passer la suite en 1er paramètre de la balise
4894
-	// Ex : #INTRODUCTION{...}
4895
-	if (
4896
-		is_null($suite)
4897
-		and !intval($longueur_ou_suite)
4898
-	) {
4899
-		$suite = $longueur_ou_suite;
4900
-	}
4893
+    // On peut optionnellement passer la suite en 1er paramètre de la balise
4894
+    // Ex : #INTRODUCTION{...}
4895
+    if (
4896
+        is_null($suite)
4897
+        and !intval($longueur_ou_suite)
4898
+    ) {
4899
+        $suite = $longueur_ou_suite;
4900
+    }
4901 4901
 
4902
-	$f = chercher_filtre('introduction');
4903
-	$introduction = $f($descriptif, $texte, $longueur, $connect, $suite);
4902
+    $f = chercher_filtre('introduction');
4903
+    $introduction = $f($descriptif, $texte, $longueur, $connect, $suite);
4904 4904
 
4905
-	return $introduction;
4905
+    return $introduction;
4906 4906
 }
4907 4907
 
4908 4908
 /**
@@ -4910,7 +4910,7 @@  discard block
 block discarded – undo
4910 4910
  * @see generer_objet_introduction
4911 4911
  */
4912 4912
 function generer_introduction_entite($id_objet, $type_objet, $ligne_sql, $introduction_longueur = null, $longueur_ou_suite = null, $suite = null, string $connect = '') {
4913
-	return generer_objet_introduction(intval($id_objet), $type_objet, $ligne_sql, $introduction_longueur, $longueur_ou_suite, $suite, $connect);
4913
+    return generer_objet_introduction(intval($id_objet), $type_objet, $ligne_sql, $introduction_longueur, $longueur_ou_suite, $suite, $connect);
4914 4914
 }
4915 4915
 
4916 4916
 /**
@@ -4924,49 +4924,49 @@  discard block
 block discarded – undo
4924 4924
  * @return string
4925 4925
  */
4926 4926
 function appliquer_traitement_champ($texte, $champ, $table_objet = '', $env = [], string $connect = '') {
4927
-	if (!$champ) {
4928
-		return $texte;
4929
-	}
4927
+    if (!$champ) {
4928
+        return $texte;
4929
+    }
4930 4930
 
4931
-	// On charge les définitions des traitements (inc/texte et fichiers de fonctions)
4932
-	// car il ne faut pas partir du principe que c'est déjà chargé (form ajax, etc)
4933
-	include_fichiers_fonctions();
4931
+    // On charge les définitions des traitements (inc/texte et fichiers de fonctions)
4932
+    // car il ne faut pas partir du principe que c'est déjà chargé (form ajax, etc)
4933
+    include_fichiers_fonctions();
4934 4934
 
4935
-	$champ = strtoupper($champ);
4936
-	$traitements = $GLOBALS['table_des_traitements'][$champ] ?? false;
4937
-	if (!$traitements or !is_array($traitements)) {
4938
-		return $texte;
4939
-	}
4935
+    $champ = strtoupper($champ);
4936
+    $traitements = $GLOBALS['table_des_traitements'][$champ] ?? false;
4937
+    if (!$traitements or !is_array($traitements)) {
4938
+        return $texte;
4939
+    }
4940 4940
 
4941
-	$traitement = '';
4942
-	if ($table_objet and (!isset($traitements[0]) or count($traitements) > 1)) {
4943
-		// necessaire pour prendre en charge les vieux appels avec un table_objet_sql en 3e arg
4944
-		$table_objet = table_objet($table_objet);
4945
-		if (isset($traitements[$table_objet])) {
4946
-			$traitement = $traitements[$table_objet];
4947
-		}
4948
-	}
4949
-	if (!$traitement and isset($traitements[0])) {
4950
-		$traitement = $traitements[0];
4951
-	}
4952
-	// (sinon prendre le premier de la liste par defaut ?)
4941
+    $traitement = '';
4942
+    if ($table_objet and (!isset($traitements[0]) or count($traitements) > 1)) {
4943
+        // necessaire pour prendre en charge les vieux appels avec un table_objet_sql en 3e arg
4944
+        $table_objet = table_objet($table_objet);
4945
+        if (isset($traitements[$table_objet])) {
4946
+            $traitement = $traitements[$table_objet];
4947
+        }
4948
+    }
4949
+    if (!$traitement and isset($traitements[0])) {
4950
+        $traitement = $traitements[0];
4951
+    }
4952
+    // (sinon prendre le premier de la liste par defaut ?)
4953 4953
 
4954
-	if (!$traitement) {
4955
-		return $texte;
4956
-	}
4954
+    if (!$traitement) {
4955
+        return $texte;
4956
+    }
4957 4957
 
4958
-	$traitement = str_replace('%s', "'" . texte_script($texte) . "'", $traitement);
4958
+    $traitement = str_replace('%s', "'" . texte_script($texte) . "'", $traitement);
4959 4959
 
4960
-	// signaler qu'on est dans l'espace prive pour les filtres qui se servent de ce flag
4961
-	if (test_espace_prive()) {
4962
-		$env['espace_prive'] = 1;
4963
-	}
4960
+    // signaler qu'on est dans l'espace prive pour les filtres qui se servent de ce flag
4961
+    if (test_espace_prive()) {
4962
+        $env['espace_prive'] = 1;
4963
+    }
4964 4964
 
4965
-	// Fournir $connect et $Pile[0] au traitement si besoin
4966
-	$Pile = [0 => $env];
4967
-	eval("\$texte = $traitement;");
4965
+    // Fournir $connect et $Pile[0] au traitement si besoin
4966
+    $Pile = [0 => $env];
4967
+    eval("\$texte = $traitement;");
4968 4968
 
4969
-	return $texte;
4969
+    return $texte;
4970 4970
 }
4971 4971
 
4972 4972
 
@@ -4980,21 +4980,21 @@  discard block
 block discarded – undo
4980 4980
  * @return string
4981 4981
  */
4982 4982
 function generer_objet_lien(int $id_objet, string $objet, int $longueur = 80, string $connect = ''): string {
4983
-	include_spip('inc/liens');
4984
-	$titre = traiter_raccourci_titre($id_objet, $objet, $connect);
4985
-	// lorsque l'objet n'est plus declare (plugin desactive par exemple)
4986
-	// le raccourcis n'est plus valide
4987
-	$titre = typo($titre['titre'] ?? '');
4988
-	// on essaye avec generer_info_entite ?
4989
-	if (!strlen($titre) and !$connect) {
4990
-		$titre = generer_objet_info($id_objet, $objet, 'titre');
4991
-	}
4992
-	if (!strlen($titre)) {
4993
-		$titre = _T('info_sans_titre');
4994
-	}
4995
-	$url = generer_objet_url($id_objet, $objet, '', '', null, '', $connect);
4983
+    include_spip('inc/liens');
4984
+    $titre = traiter_raccourci_titre($id_objet, $objet, $connect);
4985
+    // lorsque l'objet n'est plus declare (plugin desactive par exemple)
4986
+    // le raccourcis n'est plus valide
4987
+    $titre = typo($titre['titre'] ?? '');
4988
+    // on essaye avec generer_info_entite ?
4989
+    if (!strlen($titre) and !$connect) {
4990
+        $titre = generer_objet_info($id_objet, $objet, 'titre');
4991
+    }
4992
+    if (!strlen($titre)) {
4993
+        $titre = _T('info_sans_titre');
4994
+    }
4995
+    $url = generer_objet_url($id_objet, $objet, '', '', null, '', $connect);
4996 4996
 
4997
-	return "<a href='$url' class='$objet'>" . couper($titre, $longueur) . '</a>';
4997
+    return "<a href='$url' class='$objet'>" . couper($titre, $longueur) . '</a>';
4998 4998
 }
4999 4999
 
5000 5000
 /**
@@ -5002,7 +5002,7 @@  discard block
 block discarded – undo
5002 5002
  * @see generer_objet_lien
5003 5003
  */
5004 5004
 function generer_lien_entite($id_objet, $objet, $longueur = 80, $connect = null) {
5005
-	return generer_objet_lien(intval($id_objet), $objet, $longueur, $connect ?? '');
5005
+    return generer_objet_lien(intval($id_objet), $objet, $longueur, $connect ?? '');
5006 5006
 }
5007 5007
 
5008 5008
 /**
@@ -5018,15 +5018,15 @@  discard block
 block discarded – undo
5018 5018
  * @return string
5019 5019
  */
5020 5020
 function wrap($texte, $wrap) {
5021
-	$balises = extraire_balises($wrap);
5022
-	if (preg_match_all(",<([a-z]\w*)\b[^>]*>,UimsS", $wrap, $regs, PREG_PATTERN_ORDER)) {
5023
-		$texte = $wrap . $texte;
5024
-		$regs = array_reverse($regs[1]);
5025
-		$wrap = '</' . implode('></', $regs) . '>';
5026
-		$texte = $texte . $wrap;
5027
-	}
5021
+    $balises = extraire_balises($wrap);
5022
+    if (preg_match_all(",<([a-z]\w*)\b[^>]*>,UimsS", $wrap, $regs, PREG_PATTERN_ORDER)) {
5023
+        $texte = $wrap . $texte;
5024
+        $regs = array_reverse($regs[1]);
5025
+        $wrap = '</' . implode('></', $regs) . '>';
5026
+        $texte = $texte . $wrap;
5027
+    }
5028 5028
 
5029
-	return $texte;
5029
+    return $texte;
5030 5030
 }
5031 5031
 
5032 5032
 
@@ -5046,44 +5046,44 @@  discard block
 block discarded – undo
5046 5046
  * @return array|mixed|string
5047 5047
  */
5048 5048
 function filtre_print_dist($u, $join = '<br />', $indent = 0) {
5049
-	if (is_string($u)) {
5050
-		$u = typo($u);
5049
+    if (is_string($u)) {
5050
+        $u = typo($u);
5051 5051
 
5052
-		return $u;
5053
-	}
5052
+        return $u;
5053
+    }
5054 5054
 
5055
-	// caster $u en array si besoin
5056
-	if (is_object($u)) {
5057
-		$u = (array)$u;
5058
-	}
5055
+    // caster $u en array si besoin
5056
+    if (is_object($u)) {
5057
+        $u = (array)$u;
5058
+    }
5059 5059
 
5060
-	if (is_array($u)) {
5061
-		$out = '';
5062
-		// toutes les cles sont numeriques ?
5063
-		// et aucun enfant n'est un tableau
5064
-		// liste simple separee par des virgules
5065
-		$numeric_keys = array_map('is_numeric', array_keys($u));
5066
-		$array_values = array_map('is_array', $u);
5067
-		$object_values = array_map('is_object', $u);
5068
-		if (
5069
-			array_sum($numeric_keys) == count($numeric_keys)
5070
-			and !array_sum($array_values)
5071
-			and !array_sum($object_values)
5072
-		) {
5073
-			return join(', ', array_map('filtre_print_dist', $u));
5074
-		}
5060
+    if (is_array($u)) {
5061
+        $out = '';
5062
+        // toutes les cles sont numeriques ?
5063
+        // et aucun enfant n'est un tableau
5064
+        // liste simple separee par des virgules
5065
+        $numeric_keys = array_map('is_numeric', array_keys($u));
5066
+        $array_values = array_map('is_array', $u);
5067
+        $object_values = array_map('is_object', $u);
5068
+        if (
5069
+            array_sum($numeric_keys) == count($numeric_keys)
5070
+            and !array_sum($array_values)
5071
+            and !array_sum($object_values)
5072
+        ) {
5073
+            return join(', ', array_map('filtre_print_dist', $u));
5074
+        }
5075 5075
 
5076
-		// sinon on passe a la ligne et on indente
5077
-		$i_str = str_pad('', $indent, ' ');
5078
-		foreach ($u as $k => $v) {
5079
-			$out .= $join . $i_str . "$k: " . filtre_print_dist($v, $join, $indent + 2);
5080
-		}
5076
+        // sinon on passe a la ligne et on indente
5077
+        $i_str = str_pad('', $indent, ' ');
5078
+        foreach ($u as $k => $v) {
5079
+            $out .= $join . $i_str . "$k: " . filtre_print_dist($v, $join, $indent + 2);
5080
+        }
5081 5081
 
5082
-		return $out;
5083
-	}
5082
+        return $out;
5083
+    }
5084 5084
 
5085
-	// on sait pas quoi faire...
5086
-	return $u;
5085
+    // on sait pas quoi faire...
5086
+    return $u;
5087 5087
 }
5088 5088
 
5089 5089
 
@@ -5096,10 +5096,10 @@  discard block
 block discarded – undo
5096 5096
  * @return string|array
5097 5097
  */
5098 5098
 function objet_info($objet, $info) {
5099
-	$table = table_objet_sql($objet);
5100
-	$infos = lister_tables_objets_sql($table);
5099
+    $table = table_objet_sql($objet);
5100
+    $infos = lister_tables_objets_sql($table);
5101 5101
 
5102
-	return ($infos[$info] ?? '');
5102
+    return ($infos[$info] ?? '');
5103 5103
 }
5104 5104
 
5105 5105
 /**
@@ -5114,11 +5114,11 @@  discard block
 block discarded – undo
5114 5114
  *     Texte traduit du comptage, tel que '3 articles'
5115 5115
  */
5116 5116
 function objet_afficher_nb($nb, $objet) {
5117
-	if (!$nb) {
5118
-		return _T(objet_info($objet, 'info_aucun_objet'));
5119
-	} else {
5120
-		return _T(objet_info($objet, $nb == 1 ? 'info_1_objet' : 'info_nb_objets'), ['nb' => $nb]);
5121
-	}
5117
+    if (!$nb) {
5118
+        return _T(objet_info($objet, 'info_aucun_objet'));
5119
+    } else {
5120
+        return _T(objet_info($objet, $nb == 1 ? 'info_1_objet' : 'info_nb_objets'), ['nb' => $nb]);
5121
+    }
5122 5122
 }
5123 5123
 
5124 5124
 /**
@@ -5130,11 +5130,11 @@  discard block
 block discarded – undo
5130 5130
  * @return string
5131 5131
  */
5132 5132
 function objet_icone($objet, $taille = 24, $class = '') {
5133
-	$icone = objet_info($objet, 'icone_objet') . '-' . $taille . '.png';
5134
-	$icone = chemin_image($icone);
5135
-	$balise_img = charger_filtre('balise_img');
5133
+    $icone = objet_info($objet, 'icone_objet') . '-' . $taille . '.png';
5134
+    $icone = chemin_image($icone);
5135
+    $balise_img = charger_filtre('balise_img');
5136 5136
 
5137
-	return $icone ? $balise_img($icone, _T(objet_info($objet, 'texte_objet')), $class, $taille) : '';
5137
+    return $icone ? $balise_img($icone, _T(objet_info($objet, 'texte_objet')), $class, $taille) : '';
5138 5138
 }
5139 5139
 
5140 5140
 /**
@@ -5155,12 +5155,12 @@  discard block
 block discarded – undo
5155 5155
  * @return string
5156 5156
  */
5157 5157
 function objet_T($objet, $chaine, $args = [], $options = []) {
5158
-	$chaine = explode(':', $chaine);
5159
-	if ($t = _T($objet . ':' . end($chaine), $args, array_merge($options, ['force' => false]))) {
5160
-		return $t;
5161
-	}
5162
-	$chaine = implode(':', $chaine);
5163
-	return _T($chaine, $args, $options);
5158
+    $chaine = explode(':', $chaine);
5159
+    if ($t = _T($objet . ':' . end($chaine), $args, array_merge($options, ['force' => false]))) {
5160
+        return $t;
5161
+    }
5162
+    $chaine = implode(':', $chaine);
5163
+    return _T($chaine, $args, $options);
5164 5164
 }
5165 5165
 
5166 5166
 /**
@@ -5174,18 +5174,18 @@  discard block
 block discarded – undo
5174 5174
  * @return string      Code HTML
5175 5175
  */
5176 5176
 function insert_head_css_conditionnel($flux) {
5177
-	if (
5178
-		strpos($flux, '<!-- insert_head_css -->') === false
5179
-		and $p = strpos($flux, '<!-- insert_head -->')
5180
-	) {
5181
-		// plutot avant le premier js externe (jquery) pour etre non bloquant
5182
-		if ($p1 = stripos($flux, '<script src=') and $p1 < $p) {
5183
-			$p = $p1;
5184
-		}
5185
-		$flux = substr_replace($flux, pipeline('insert_head_css', '<!-- insert_head_css -->'), $p, 0);
5186
-	}
5177
+    if (
5178
+        strpos($flux, '<!-- insert_head_css -->') === false
5179
+        and $p = strpos($flux, '<!-- insert_head -->')
5180
+    ) {
5181
+        // plutot avant le premier js externe (jquery) pour etre non bloquant
5182
+        if ($p1 = stripos($flux, '<script src=') and $p1 < $p) {
5183
+            $p = $p1;
5184
+        }
5185
+        $flux = substr_replace($flux, pipeline('insert_head_css', '<!-- insert_head_css -->'), $p, 0);
5186
+    }
5187 5187
 
5188
-	return $flux;
5188
+    return $flux;
5189 5189
 }
5190 5190
 
5191 5191
 /**
@@ -5208,75 +5208,75 @@  discard block
 block discarded – undo
5208 5208
  * @return string
5209 5209
  */
5210 5210
 function produire_fond_statique($fond, $contexte = [], $options = [], string $connect = '') {
5211
-	if (isset($contexte['format'])) {
5212
-		$extension = $contexte['format'];
5213
-		unset($contexte['format']);
5214
-	} else {
5215
-		$extension = 'html';
5216
-		if (preg_match(',[.](css|js|json|xml|svg)$,', $fond, $m)) {
5217
-			$extension = $m[1];
5218
-		}
5219
-	}
5220
-	// recuperer le contenu produit par le squelette
5221
-	$options['raw'] = true;
5222
-	$cache = recuperer_fond($fond, $contexte, $options, $connect);
5223
-
5224
-	// calculer le nom de la css
5225
-	$dir_var = sous_repertoire(_DIR_VAR, 'cache-' . $extension);
5226
-	$nom_safe = preg_replace(',\W,', '_', str_replace('.', '_', $fond));
5227
-	$contexte_implicite = calculer_contexte_implicite();
5228
-
5229
-	// par defaut on hash selon les contextes qui sont a priori moins variables
5230
-	// mais on peut hasher selon le contenu a la demande, si plusieurs contextes produisent un meme contenu
5231
-	// reduit la variabilite du nom et donc le nombre de css concatenees possibles in fine
5232
-	if (isset($options['hash_on_content']) and $options['hash_on_content']) {
5233
-		$hash = md5($contexte_implicite['host'] . '::' . $cache);
5234
-	}
5235
-	else {
5236
-		unset($contexte_implicite['notes']); // pas pertinent pour signaler un changeemnt de contenu pour des css/js
5237
-		ksort($contexte);
5238
-		$hash = md5($fond . json_encode($contexte_implicite, JSON_THROW_ON_ERROR) . json_encode($contexte, JSON_THROW_ON_ERROR) . $connect);
5239
-	}
5240
-	$filename = $dir_var . $extension . "dyn-$nom_safe-" . substr($hash, 0, 8) . ".$extension";
5241
-
5242
-	// mettre a jour le fichier si il n'existe pas
5243
-	// ou trop ancien
5244
-	// le dernier fichier produit est toujours suffixe par .last
5245
-	// et recopie sur le fichier cible uniquement si il change
5246
-	if (
5247
-		!file_exists($filename)
5248
-		or !file_exists($filename . '.last')
5249
-		or (isset($cache['lastmodified']) and $cache['lastmodified'] and filemtime($filename . '.last') < $cache['lastmodified'])
5250
-		or (defined('_VAR_MODE') and _VAR_MODE == 'recalcul')
5251
-	) {
5252
-		$contenu = $cache['texte'];
5253
-		// passer les urls en absolu si c'est une css
5254
-		if ($extension == 'css') {
5255
-			$contenu = urls_absolues_css(
5256
-				$contenu,
5257
-				test_espace_prive() ? generer_url_ecrire('accueil') : generer_url_public($fond)
5258
-			);
5259
-		}
5260
-
5261
-		$comment = '';
5262
-		// ne pas insérer de commentaire sur certains formats
5263
-		if (!in_array($extension, ['json', 'xml', 'svg'])) {
5264
-			$comment = "/* #PRODUIRE{fond=$fond";
5265
-			foreach ($contexte as $k => $v) {
5266
-				if (is_array($v)) {
5267
-					$v = var_export($v, true);
5268
-				}
5269
-				$comment .= ",$k=$v";
5270
-			}
5271
-			// pas de date dans le commentaire car sinon ca invalide le md5 et force la maj
5272
-			// mais on peut mettre un md5 du contenu, ce qui donne un aperu rapide si la feuille a change ou non
5273
-			$comment .= "}\n   md5:" . md5($contenu) . " */\n";
5274
-		}
5275
-		// et ecrire le fichier si il change
5276
-		ecrire_fichier_calcule_si_modifie($filename, $comment . $contenu, false, true);
5277
-	}
5278
-
5279
-	return timestamp($filename);
5211
+    if (isset($contexte['format'])) {
5212
+        $extension = $contexte['format'];
5213
+        unset($contexte['format']);
5214
+    } else {
5215
+        $extension = 'html';
5216
+        if (preg_match(',[.](css|js|json|xml|svg)$,', $fond, $m)) {
5217
+            $extension = $m[1];
5218
+        }
5219
+    }
5220
+    // recuperer le contenu produit par le squelette
5221
+    $options['raw'] = true;
5222
+    $cache = recuperer_fond($fond, $contexte, $options, $connect);
5223
+
5224
+    // calculer le nom de la css
5225
+    $dir_var = sous_repertoire(_DIR_VAR, 'cache-' . $extension);
5226
+    $nom_safe = preg_replace(',\W,', '_', str_replace('.', '_', $fond));
5227
+    $contexte_implicite = calculer_contexte_implicite();
5228
+
5229
+    // par defaut on hash selon les contextes qui sont a priori moins variables
5230
+    // mais on peut hasher selon le contenu a la demande, si plusieurs contextes produisent un meme contenu
5231
+    // reduit la variabilite du nom et donc le nombre de css concatenees possibles in fine
5232
+    if (isset($options['hash_on_content']) and $options['hash_on_content']) {
5233
+        $hash = md5($contexte_implicite['host'] . '::' . $cache);
5234
+    }
5235
+    else {
5236
+        unset($contexte_implicite['notes']); // pas pertinent pour signaler un changeemnt de contenu pour des css/js
5237
+        ksort($contexte);
5238
+        $hash = md5($fond . json_encode($contexte_implicite, JSON_THROW_ON_ERROR) . json_encode($contexte, JSON_THROW_ON_ERROR) . $connect);
5239
+    }
5240
+    $filename = $dir_var . $extension . "dyn-$nom_safe-" . substr($hash, 0, 8) . ".$extension";
5241
+
5242
+    // mettre a jour le fichier si il n'existe pas
5243
+    // ou trop ancien
5244
+    // le dernier fichier produit est toujours suffixe par .last
5245
+    // et recopie sur le fichier cible uniquement si il change
5246
+    if (
5247
+        !file_exists($filename)
5248
+        or !file_exists($filename . '.last')
5249
+        or (isset($cache['lastmodified']) and $cache['lastmodified'] and filemtime($filename . '.last') < $cache['lastmodified'])
5250
+        or (defined('_VAR_MODE') and _VAR_MODE == 'recalcul')
5251
+    ) {
5252
+        $contenu = $cache['texte'];
5253
+        // passer les urls en absolu si c'est une css
5254
+        if ($extension == 'css') {
5255
+            $contenu = urls_absolues_css(
5256
+                $contenu,
5257
+                test_espace_prive() ? generer_url_ecrire('accueil') : generer_url_public($fond)
5258
+            );
5259
+        }
5260
+
5261
+        $comment = '';
5262
+        // ne pas insérer de commentaire sur certains formats
5263
+        if (!in_array($extension, ['json', 'xml', 'svg'])) {
5264
+            $comment = "/* #PRODUIRE{fond=$fond";
5265
+            foreach ($contexte as $k => $v) {
5266
+                if (is_array($v)) {
5267
+                    $v = var_export($v, true);
5268
+                }
5269
+                $comment .= ",$k=$v";
5270
+            }
5271
+            // pas de date dans le commentaire car sinon ca invalide le md5 et force la maj
5272
+            // mais on peut mettre un md5 du contenu, ce qui donne un aperu rapide si la feuille a change ou non
5273
+            $comment .= "}\n   md5:" . md5($contenu) . " */\n";
5274
+        }
5275
+        // et ecrire le fichier si il change
5276
+        ecrire_fichier_calcule_si_modifie($filename, $comment . $contenu, false, true);
5277
+    }
5278
+
5279
+    return timestamp($filename);
5280 5280
 }
5281 5281
 
5282 5282
 /**
@@ -5289,15 +5289,15 @@  discard block
 block discarded – undo
5289 5289
  *    $fichier auquel on a ajouté le timestamp
5290 5290
  */
5291 5291
 function timestamp($fichier) {
5292
-	if (
5293
-		!$fichier
5294
-		or !file_exists($fichier)
5295
-		or !$m = filemtime($fichier)
5296
-	) {
5297
-		return $fichier;
5298
-	}
5292
+    if (
5293
+        !$fichier
5294
+        or !file_exists($fichier)
5295
+        or !$m = filemtime($fichier)
5296
+    ) {
5297
+        return $fichier;
5298
+    }
5299 5299
 
5300
-	return "$fichier?$m";
5300
+    return "$fichier?$m";
5301 5301
 }
5302 5302
 
5303 5303
 /**
@@ -5307,11 +5307,11 @@  discard block
 block discarded – undo
5307 5307
  * @return string
5308 5308
  */
5309 5309
 function supprimer_timestamp($url) {
5310
-	if (strpos($url, '?') === false) {
5311
-		return $url;
5312
-	}
5310
+    if (strpos($url, '?') === false) {
5311
+        return $url;
5312
+    }
5313 5313
 
5314
-	return preg_replace(',\?[[:digit:]]+$,', '', $url);
5314
+    return preg_replace(',\?[[:digit:]]+$,', '', $url);
5315 5315
 }
5316 5316
 
5317 5317
 /**
@@ -5326,15 +5326,15 @@  discard block
 block discarded – undo
5326 5326
  * @return string
5327 5327
  */
5328 5328
 function filtre_nettoyer_titre_email_dist($titre) {
5329
-	include_spip('inc/envoyer_mail');
5329
+    include_spip('inc/envoyer_mail');
5330 5330
 
5331
-	$titre = nettoyer_titre_email($titre);
5332
-	// on est dans un squelette : securiser le retour
5333
-	if (strpos($titre, '<') !== false) {
5334
-		$titre = interdire_scripts($titre);
5335
-	}
5331
+    $titre = nettoyer_titre_email($titre);
5332
+    // on est dans un squelette : securiser le retour
5333
+    if (strpos($titre, '<') !== false) {
5334
+        $titre = interdire_scripts($titre);
5335
+    }
5336 5336
 
5337
-	return $titre;
5337
+    return $titre;
5338 5338
 }
5339 5339
 
5340 5340
 /**
@@ -5356,27 +5356,27 @@  discard block
 block discarded – undo
5356 5356
  * @return string
5357 5357
  */
5358 5358
 function filtre_chercher_rubrique_dist(
5359
-	$titre,
5360
-	$id_objet,
5361
-	$id_parent,
5362
-	$objet,
5363
-	$id_secteur,
5364
-	$restreint,
5365
-	$actionable = false,
5366
-	$retour_sans_cadre = false
5359
+    $titre,
5360
+    $id_objet,
5361
+    $id_parent,
5362
+    $objet,
5363
+    $id_secteur,
5364
+    $restreint,
5365
+    $actionable = false,
5366
+    $retour_sans_cadre = false
5367 5367
 ) {
5368
-	include_spip('inc/filtres_ecrire');
5368
+    include_spip('inc/filtres_ecrire');
5369 5369
 
5370
-	return chercher_rubrique(
5371
-		$titre,
5372
-		$id_objet,
5373
-		$id_parent,
5374
-		$objet,
5375
-		$id_secteur,
5376
-		$restreint,
5377
-		$actionable,
5378
-		$retour_sans_cadre
5379
-	);
5370
+    return chercher_rubrique(
5371
+        $titre,
5372
+        $id_objet,
5373
+        $id_parent,
5374
+        $objet,
5375
+        $id_secteur,
5376
+        $restreint,
5377
+        $actionable,
5378
+        $retour_sans_cadre
5379
+    );
5380 5380
 }
5381 5381
 
5382 5382
 /**
@@ -5405,56 +5405,56 @@  discard block
 block discarded – undo
5405 5405
  *     Chaîne vide si l'accès est autorisé
5406 5406
  */
5407 5407
 function sinon_interdire_acces($ok = false, $url = '', $statut = 0, $message = null) {
5408
-	if ($ok) {
5409
-		return '';
5410
-	}
5411
-
5412
-	// Vider tous les tampons
5413
-	$level = @ob_get_level();
5414
-	while ($level--) {
5415
-		@ob_end_clean();
5416
-	}
5417
-
5418
-	include_spip('inc/headers');
5419
-
5420
-	// S'il y a une URL, on redirige (si pas de statut, la fonction mettra 302 par défaut)
5421
-	if ($url) {
5422
-		redirige_par_entete($url, '', $statut);
5423
-	}
5424
-
5425
-	// ecriture simplifiee avec message en 3eme argument (= statut 403)
5426
-	if (!is_numeric($statut) and is_null($message)) {
5427
-		$message = $statut;
5428
-		$statut = 0;
5429
-	}
5430
-	if (!$message) {
5431
-		$message = '';
5432
-	}
5433
-	$statut = intval($statut);
5434
-
5435
-	// Si on est dans l'espace privé, on génère du 403 Forbidden par defaut ou du 404
5436
-	if (test_espace_prive()) {
5437
-		if (!$statut or !in_array($statut, [404, 403])) {
5438
-			$statut = 403;
5439
-		}
5440
-		http_response_code(403);
5441
-		$echec = charger_fonction('403', 'exec');
5442
-		$echec($message);
5443
-	} else {
5444
-		// Sinon dans l'espace public on redirige vers une 404 par défaut, car elle toujours présente normalement
5445
-		if (!$statut) {
5446
-			$statut = 404;
5447
-		}
5448
-		// Dans tous les cas on modifie l'entité avec ce qui est demandé
5449
-		http_response_code($statut);
5450
-		// Si le statut est une erreur et qu'il n'y a pas de redirection on va chercher le squelette du même nom
5451
-		if ($statut >= 400) {
5452
-			echo recuperer_fond("$statut", ['erreur' => $message]);
5453
-		}
5454
-	}
5455
-
5456
-
5457
-	exit;
5408
+    if ($ok) {
5409
+        return '';
5410
+    }
5411
+
5412
+    // Vider tous les tampons
5413
+    $level = @ob_get_level();
5414
+    while ($level--) {
5415
+        @ob_end_clean();
5416
+    }
5417
+
5418
+    include_spip('inc/headers');
5419
+
5420
+    // S'il y a une URL, on redirige (si pas de statut, la fonction mettra 302 par défaut)
5421
+    if ($url) {
5422
+        redirige_par_entete($url, '', $statut);
5423
+    }
5424
+
5425
+    // ecriture simplifiee avec message en 3eme argument (= statut 403)
5426
+    if (!is_numeric($statut) and is_null($message)) {
5427
+        $message = $statut;
5428
+        $statut = 0;
5429
+    }
5430
+    if (!$message) {
5431
+        $message = '';
5432
+    }
5433
+    $statut = intval($statut);
5434
+
5435
+    // Si on est dans l'espace privé, on génère du 403 Forbidden par defaut ou du 404
5436
+    if (test_espace_prive()) {
5437
+        if (!$statut or !in_array($statut, [404, 403])) {
5438
+            $statut = 403;
5439
+        }
5440
+        http_response_code(403);
5441
+        $echec = charger_fonction('403', 'exec');
5442
+        $echec($message);
5443
+    } else {
5444
+        // Sinon dans l'espace public on redirige vers une 404 par défaut, car elle toujours présente normalement
5445
+        if (!$statut) {
5446
+            $statut = 404;
5447
+        }
5448
+        // Dans tous les cas on modifie l'entité avec ce qui est demandé
5449
+        http_response_code($statut);
5450
+        // Si le statut est une erreur et qu'il n'y a pas de redirection on va chercher le squelette du même nom
5451
+        if ($statut >= 400) {
5452
+            echo recuperer_fond("$statut", ['erreur' => $message]);
5453
+        }
5454
+    }
5455
+
5456
+
5457
+    exit;
5458 5458
 }
5459 5459
 
5460 5460
 /**
@@ -5465,11 +5465,11 @@  discard block
 block discarded – undo
5465 5465
  * @return string
5466 5466
  */
5467 5467
 function filtre_compacte_dist($source, $format = null) {
5468
-	if (function_exists('minifier')) {
5469
-		return minifier($source, $format);
5470
-	}
5468
+    if (function_exists('minifier')) {
5469
+        return minifier($source, $format);
5470
+    }
5471 5471
 
5472
-	return $source;
5472
+    return $source;
5473 5473
 }
5474 5474
 
5475 5475
 
@@ -5481,32 +5481,32 @@  discard block
 block discarded – undo
5481 5481
  * @return string
5482 5482
  */
5483 5483
 function spip_affiche_mot_de_passe_masque(?string $passe, bool $afficher_partiellement = false, ?int $portion_pourcent = null): string {
5484
-	$passe ??= '';
5485
-	$l = strlen($passe);
5486
-
5487
-	if ($l <= 8 or !$afficher_partiellement) {
5488
-		if (!$l) {
5489
-			return ''; // montrer qu'il y a pas de mot de passe si il y en a pas
5490
-		}
5491
-		return str_pad('', $afficher_partiellement ? $l : 16, '*');
5492
-	}
5493
-
5494
-	if (is_null($portion_pourcent)) {
5495
-		if (!defined('_SPIP_AFFICHE_MOT_DE_PASSE_MASQUE_PERCENT')) {
5496
-			define('_SPIP_AFFICHE_MOT_DE_PASSE_MASQUE_PERCENT', 20); // 20%
5497
-		}
5498
-		$portion_pourcent = _SPIP_AFFICHE_MOT_DE_PASSE_MASQUE_PERCENT;
5499
-	}
5500
-	if ($portion_pourcent >= 100) {
5501
-		return $passe;
5502
-	}
5503
-	$e = intval(ceil($l * $portion_pourcent / 100 / 2));
5504
-	$e = max($e, 0);
5505
-	$mid = str_pad('', $l - 2 * $e, '*');
5506
-	if ($e > 0 and strlen($mid) > 8) {
5507
-		$mid = '***...***';
5508
-	}
5509
-	return substr($passe, 0, $e) . $mid . ($e > 0 ? substr($passe, -$e) : '');
5484
+    $passe ??= '';
5485
+    $l = strlen($passe);
5486
+
5487
+    if ($l <= 8 or !$afficher_partiellement) {
5488
+        if (!$l) {
5489
+            return ''; // montrer qu'il y a pas de mot de passe si il y en a pas
5490
+        }
5491
+        return str_pad('', $afficher_partiellement ? $l : 16, '*');
5492
+    }
5493
+
5494
+    if (is_null($portion_pourcent)) {
5495
+        if (!defined('_SPIP_AFFICHE_MOT_DE_PASSE_MASQUE_PERCENT')) {
5496
+            define('_SPIP_AFFICHE_MOT_DE_PASSE_MASQUE_PERCENT', 20); // 20%
5497
+        }
5498
+        $portion_pourcent = _SPIP_AFFICHE_MOT_DE_PASSE_MASQUE_PERCENT;
5499
+    }
5500
+    if ($portion_pourcent >= 100) {
5501
+        return $passe;
5502
+    }
5503
+    $e = intval(ceil($l * $portion_pourcent / 100 / 2));
5504
+    $e = max($e, 0);
5505
+    $mid = str_pad('', $l - 2 * $e, '*');
5506
+    if ($e > 0 and strlen($mid) > 8) {
5507
+        $mid = '***...***';
5508
+    }
5509
+    return substr($passe, 0, $e) . $mid . ($e > 0 ? substr($passe, -$e) : '');
5510 5510
 }
5511 5511
 
5512 5512
 
@@ -5527,64 +5527,64 @@  discard block
 block discarded – undo
5527 5527
  */
5528 5528
 function identifiant_slug($texte, $type = '', $options = []) {
5529 5529
 
5530
-	$original = $texte;
5531
-	$separateur = ($options['separateur'] ?? '_');
5532
-	$longueur_maxi = ($options['longueur_maxi'] ?? 60);
5533
-	$longueur_mini = ($options['longueur_mini'] ?? 0);
5530
+    $original = $texte;
5531
+    $separateur = ($options['separateur'] ?? '_');
5532
+    $longueur_maxi = ($options['longueur_maxi'] ?? 60);
5533
+    $longueur_mini = ($options['longueur_mini'] ?? 0);
5534 5534
 
5535
-	if (!function_exists('translitteration')) {
5536
-		include_spip('inc/charsets');
5537
-	}
5535
+    if (!function_exists('translitteration')) {
5536
+        include_spip('inc/charsets');
5537
+    }
5538 5538
 
5539
-	// pas de balise html
5540
-	if (strpos($texte, '<') !== false) {
5541
-		$texte = strip_tags($texte);
5542
-	}
5543
-	if (strpos($texte, '&') !== false) {
5544
-		$texte = unicode2charset($texte);
5545
-	}
5546
-	// On enlève les espaces indésirables
5547
-	$texte = trim($texte);
5539
+    // pas de balise html
5540
+    if (strpos($texte, '<') !== false) {
5541
+        $texte = strip_tags($texte);
5542
+    }
5543
+    if (strpos($texte, '&') !== false) {
5544
+        $texte = unicode2charset($texte);
5545
+    }
5546
+    // On enlève les espaces indésirables
5547
+    $texte = trim($texte);
5548 5548
 
5549
-	// On enlève les accents et cie
5550
-	$texte = translitteration($texte);
5549
+    // On enlève les accents et cie
5550
+    $texte = translitteration($texte);
5551 5551
 
5552
-	// On remplace tout ce qui n'est pas un mot par un séparateur
5553
-	$texte = preg_replace(',[\W_]+,ms', $separateur, $texte);
5552
+    // On remplace tout ce qui n'est pas un mot par un séparateur
5553
+    $texte = preg_replace(',[\W_]+,ms', $separateur, $texte);
5554 5554
 
5555
-	// nettoyer les doubles occurences du separateur si besoin
5556
-	while (strpos($texte, (string) "$separateur$separateur") !== false) {
5557
-		$texte = str_replace("$separateur$separateur", $separateur, $texte);
5558
-	}
5555
+    // nettoyer les doubles occurences du separateur si besoin
5556
+    while (strpos($texte, (string) "$separateur$separateur") !== false) {
5557
+        $texte = str_replace("$separateur$separateur", $separateur, $texte);
5558
+    }
5559 5559
 
5560
-	// pas de separateur au debut ni a la fin
5561
-	$texte = trim($texte, $separateur);
5560
+    // pas de separateur au debut ni a la fin
5561
+    $texte = trim($texte, $separateur);
5562 5562
 
5563
-	// en minuscules
5564
-	$texte = strtolower($texte);
5563
+    // en minuscules
5564
+    $texte = strtolower($texte);
5565 5565
 
5566
-	switch ($type) {
5567
-		case 'class':
5568
-		case 'id':
5569
-		case 'anchor':
5570
-			if (preg_match(',^\d,', $texte)) {
5571
-				$texte = substr($type, 0, 1) . $texte;
5572
-			}
5573
-	}
5566
+    switch ($type) {
5567
+        case 'class':
5568
+        case 'id':
5569
+        case 'anchor':
5570
+            if (preg_match(',^\d,', $texte)) {
5571
+                $texte = substr($type, 0, 1) . $texte;
5572
+            }
5573
+    }
5574 5574
 
5575
-	if (strlen($texte) > $longueur_maxi) {
5576
-		$texte = substr($texte, 0, $longueur_maxi);
5577
-	}
5575
+    if (strlen($texte) > $longueur_maxi) {
5576
+        $texte = substr($texte, 0, $longueur_maxi);
5577
+    }
5578 5578
 
5579
-	if (strlen($texte) < $longueur_mini and $longueur_mini < $longueur_maxi) {
5580
-		if (preg_match(',^\d,', $texte)) {
5581
-			$texte = ($type ? substr($type, 0, 1) : 's') . $texte;
5582
-		}
5583
-		$texte .= $separateur . md5($original);
5584
-		$texte = substr($texte, 0, $longueur_mini);
5585
-	}
5579
+    if (strlen($texte) < $longueur_mini and $longueur_mini < $longueur_maxi) {
5580
+        if (preg_match(',^\d,', $texte)) {
5581
+            $texte = ($type ? substr($type, 0, 1) : 's') . $texte;
5582
+        }
5583
+        $texte .= $separateur . md5($original);
5584
+        $texte = substr($texte, 0, $longueur_mini);
5585
+    }
5586 5586
 
5587
-	return $texte;
5587
+    return $texte;
5588 5588
 }
5589 5589
 
5590 5590
 
@@ -5605,11 +5605,11 @@  discard block
 block discarded – undo
5605 5605
  * @exemple `<:info_maximum|label_nettoyer:>`
5606 5606
  */
5607 5607
 function label_nettoyer(string $text, bool $ucfirst = true): string {
5608
-	$label = preg_replace('#([\s:]|\&nbsp;)+$#u', '', $text);
5609
-	if ($ucfirst) {
5610
-		$label = spip_ucfirst($label);
5611
-	}
5612
-	return $label;
5608
+    $label = preg_replace('#([\s:]|\&nbsp;)+$#u', '', $text);
5609
+    if ($ucfirst) {
5610
+        $label = spip_ucfirst($label);
5611
+    }
5612
+    return $label;
5613 5613
 }
5614 5614
 
5615 5615
 /**
@@ -5622,8 +5622,8 @@  discard block
 block discarded – undo
5622 5622
  * @exemple `<:info_maximum|label_ponctuer:>`
5623 5623
  */
5624 5624
 function label_ponctuer(string $text, bool $ucfirst = true): string {
5625
-	$label = label_nettoyer($text, $ucfirst);
5626
-	return _T('label_ponctuer', ['label' => $label]);
5625
+    $label = label_nettoyer($text, $ucfirst);
5626
+    return _T('label_ponctuer', ['label' => $label]);
5627 5627
 }
5628 5628
 
5629 5629
 
@@ -5636,19 +5636,19 @@  discard block
 block discarded – undo
5636 5636
  * @return array
5637 5637
  */
5638 5638
 function helper_filtre_objet_lister_enfants_ou_parents($objet, $id_objet, $fonction) {
5639
-	if (!in_array($fonction, ['objet_lister_parents', 'objet_lister_enfants', 'objet_lister_parents_par_type', 'objet_lister_enfants_par_type'])) {
5640
-		return [];
5641
-	}
5639
+    if (!in_array($fonction, ['objet_lister_parents', 'objet_lister_enfants', 'objet_lister_parents_par_type', 'objet_lister_enfants_par_type'])) {
5640
+        return [];
5641
+    }
5642 5642
 
5643
-	// compatibilite signature inversee
5644
-	if (is_numeric($objet) and !is_numeric($id_objet)) {
5645
-		[$objet, $id_objet] = [$id_objet, $objet];
5646
-	}
5643
+    // compatibilite signature inversee
5644
+    if (is_numeric($objet) and !is_numeric($id_objet)) {
5645
+        [$objet, $id_objet] = [$id_objet, $objet];
5646
+    }
5647 5647
 
5648
-	if (!function_exists($fonction)) {
5649
-		include_spip('base/objets');
5650
-	}
5651
-	return $fonction($objet, $id_objet);
5648
+    if (!function_exists($fonction)) {
5649
+        include_spip('base/objets');
5650
+    }
5651
+    return $fonction($objet, $id_objet);
5652 5652
 }
5653 5653
 
5654 5654
 
@@ -5663,7 +5663,7 @@  discard block
 block discarded – undo
5663 5663
  * @return array
5664 5664
  */
5665 5665
 function filtre_objet_lister_parents_dist($objet, $id_objet) {
5666
-	return helper_filtre_objet_lister_enfants_ou_parents($objet, $id_objet, 'objet_lister_parents');
5666
+    return helper_filtre_objet_lister_enfants_ou_parents($objet, $id_objet, 'objet_lister_parents');
5667 5667
 }
5668 5668
 
5669 5669
 /**
@@ -5677,7 +5677,7 @@  discard block
 block discarded – undo
5677 5677
  * @return array
5678 5678
  */
5679 5679
 function filtre_objet_lister_parents_par_type_dist($objet, $id_objet) {
5680
-	return helper_filtre_objet_lister_enfants_ou_parents($objet, $id_objet, 'objet_lister_parents_par_type');
5680
+    return helper_filtre_objet_lister_enfants_ou_parents($objet, $id_objet, 'objet_lister_parents_par_type');
5681 5681
 }
5682 5682
 
5683 5683
 /**
@@ -5691,7 +5691,7 @@  discard block
 block discarded – undo
5691 5691
  * @return array
5692 5692
  */
5693 5693
 function filtre_objet_lister_enfants_dist($objet, $id_objet) {
5694
-	return helper_filtre_objet_lister_enfants_ou_parents($objet, $id_objet, 'objet_lister_enfants');
5694
+    return helper_filtre_objet_lister_enfants_ou_parents($objet, $id_objet, 'objet_lister_enfants');
5695 5695
 }
5696 5696
 
5697 5697
 /**
@@ -5705,5 +5705,5 @@  discard block
 block discarded – undo
5705 5705
  * @return array
5706 5706
  */
5707 5707
 function filtre_objet_lister_enfants_par_type_dist($objet, $id_objet) {
5708
-	return helper_filtre_objet_lister_enfants_ou_parents($objet, $id_objet, 'objet_lister_enfants_par_type');
5708
+    return helper_filtre_objet_lister_enfants_ou_parents($objet, $id_objet, 'objet_lister_enfants_par_type');
5709 5709
 }
Please login to merge, or discard this patch.
ecrire/req/sqlite_generique.php 1 patch
Indentation   +2005 added lines, -2005 removed lines patch added patch discarded remove patch
@@ -18,7 +18,7 @@  discard block
 block discarded – undo
18 18
  */
19 19
 
20 20
 if (!defined('_ECRIRE_INC_VERSION')) {
21
-	return;
21
+    return;
22 22
 }
23 23
 
24 24
 // TODO: get/set_caracteres ?
@@ -42,91 +42,91 @@  discard block
 block discarded – undo
42 42
  * @return array|bool
43 43
  */
44 44
 function req_sqlite_dist($addr, $port, $login, $pass, $db = '', $prefixe = '', $sqlite_version = '') {
45
-	static $last_connect = [];
46
-
47
-	// si provient de selectdb
48
-	// un code pour etre sur que l'on vient de select_db()
49
-	if (strpos($db, $code = '@selectdb@') !== false) {
50
-		foreach (['addr', 'port', 'login', 'pass', 'prefixe'] as $a) {
51
-			$$a = $last_connect[$a];
52
-		}
53
-		$db = str_replace($code, '', $db);
54
-	}
55
-
56
-	/*
45
+    static $last_connect = [];
46
+
47
+    // si provient de selectdb
48
+    // un code pour etre sur que l'on vient de select_db()
49
+    if (strpos($db, $code = '@selectdb@') !== false) {
50
+        foreach (['addr', 'port', 'login', 'pass', 'prefixe'] as $a) {
51
+            $$a = $last_connect[$a];
52
+        }
53
+        $db = str_replace($code, '', $db);
54
+    }
55
+
56
+    /*
57 57
 	 * En sqlite, seule l'adresse du fichier est importante.
58 58
 	 * Ce sera $db le nom,
59 59
 	 * le path est $addr
60 60
 	 * (_DIR_DB si $addr est vide)
61 61
 	 */
62
-	_sqlite_init();
63
-
64
-	// determiner le dossier de la base : $addr ou _DIR_DB
65
-	$f = _DIR_DB;
66
-	if ($addr and strpos($addr, '/') !== false) {
67
-		$f = rtrim($addr, '/') . '/';
68
-	}
69
-
70
-	// un nom de base demande et impossible d'obtenir la base, on s'en va :
71
-	// il faut que la base existe ou que le repertoire parent soit writable
72
-	if ($db and !is_file($f .= $db . '.sqlite') and !is_writable(dirname($f))) {
73
-		spip_log("base $f non trouvee ou droits en ecriture manquants", 'sqlite.' . _LOG_HS);
74
-
75
-		return false;
76
-	}
77
-
78
-	// charger les modules sqlite au besoin
79
-	if (!_sqlite_charger_version($sqlite_version)) {
80
-		spip_log("Impossible de trouver/charger le module SQLite ($sqlite_version)!", 'sqlite.' . _LOG_HS);
81
-
82
-		return false;
83
-	}
84
-
85
-	// chargement des constantes
86
-	// il ne faut pas definir les constantes avant d'avoir charge les modules sqlite
87
-	$define = 'spip_sqlite' . $sqlite_version . '_constantes';
88
-	$define();
89
-
90
-	$ok = false;
91
-	if (!$db) {
92
-		// si pas de db ->
93
-		// base temporaire tant qu'on ne connait pas son vrai nom
94
-		// pour tester la connexion
95
-		$db = '_sqlite' . $sqlite_version . '_install';
96
-		$tmp = _DIR_DB . $db . '.sqlite';
97
-		$ok = $link = new \PDO("sqlite:$tmp");
98
-	} else {
99
-		// Ouvrir (eventuellement creer la base)
100
-		$ok = $link = new \PDO("sqlite:$f");
101
-	}
102
-
103
-	if (!$ok) {
104
-		$e = _sqlite_last_error_from_link($link);
105
-		spip_log("Impossible d'ouvrir la base SQLite($sqlite_version) $f : $e", 'sqlite.' . _LOG_HS);
106
-
107
-		return false;
108
-	}
109
-
110
-	if ($link) {
111
-		$last_connect = [
112
-			'addr' => $addr,
113
-			'port' => $port,
114
-			'login' => $login,
115
-			'pass' => $pass,
116
-			'db' => $db,
117
-			'prefixe' => $prefixe,
118
-		];
119
-		// etre sur qu'on definit bien les fonctions a chaque nouvelle connexion
120
-		include_spip('req/sqlite_fonctions');
121
-		_sqlite_init_functions($link);
122
-	}
123
-
124
-	return [
125
-		'db' => $db,
126
-		'prefixe' => $prefixe ? $prefixe : $db,
127
-		'link' => $link,
128
-		'total_requetes' => 0,
129
-	];
62
+    _sqlite_init();
63
+
64
+    // determiner le dossier de la base : $addr ou _DIR_DB
65
+    $f = _DIR_DB;
66
+    if ($addr and strpos($addr, '/') !== false) {
67
+        $f = rtrim($addr, '/') . '/';
68
+    }
69
+
70
+    // un nom de base demande et impossible d'obtenir la base, on s'en va :
71
+    // il faut que la base existe ou que le repertoire parent soit writable
72
+    if ($db and !is_file($f .= $db . '.sqlite') and !is_writable(dirname($f))) {
73
+        spip_log("base $f non trouvee ou droits en ecriture manquants", 'sqlite.' . _LOG_HS);
74
+
75
+        return false;
76
+    }
77
+
78
+    // charger les modules sqlite au besoin
79
+    if (!_sqlite_charger_version($sqlite_version)) {
80
+        spip_log("Impossible de trouver/charger le module SQLite ($sqlite_version)!", 'sqlite.' . _LOG_HS);
81
+
82
+        return false;
83
+    }
84
+
85
+    // chargement des constantes
86
+    // il ne faut pas definir les constantes avant d'avoir charge les modules sqlite
87
+    $define = 'spip_sqlite' . $sqlite_version . '_constantes';
88
+    $define();
89
+
90
+    $ok = false;
91
+    if (!$db) {
92
+        // si pas de db ->
93
+        // base temporaire tant qu'on ne connait pas son vrai nom
94
+        // pour tester la connexion
95
+        $db = '_sqlite' . $sqlite_version . '_install';
96
+        $tmp = _DIR_DB . $db . '.sqlite';
97
+        $ok = $link = new \PDO("sqlite:$tmp");
98
+    } else {
99
+        // Ouvrir (eventuellement creer la base)
100
+        $ok = $link = new \PDO("sqlite:$f");
101
+    }
102
+
103
+    if (!$ok) {
104
+        $e = _sqlite_last_error_from_link($link);
105
+        spip_log("Impossible d'ouvrir la base SQLite($sqlite_version) $f : $e", 'sqlite.' . _LOG_HS);
106
+
107
+        return false;
108
+    }
109
+
110
+    if ($link) {
111
+        $last_connect = [
112
+            'addr' => $addr,
113
+            'port' => $port,
114
+            'login' => $login,
115
+            'pass' => $pass,
116
+            'db' => $db,
117
+            'prefixe' => $prefixe,
118
+        ];
119
+        // etre sur qu'on definit bien les fonctions a chaque nouvelle connexion
120
+        include_spip('req/sqlite_fonctions');
121
+        _sqlite_init_functions($link);
122
+    }
123
+
124
+    return [
125
+        'db' => $db,
126
+        'prefixe' => $prefixe ? $prefixe : $db,
127
+        'link' => $link,
128
+        'total_requetes' => 0,
129
+    ];
130 130
 }
131 131
 
132 132
 
@@ -145,14 +145,14 @@  discard block
 block discarded – undo
145 145
  *    Resultat de la requete
146 146
  */
147 147
 function spip_sqlite_query($query, $serveur = '', $requeter = true) {
148
-	#spip_log("spip_sqlite_query() > $query",'sqlite.'._LOG_DEBUG);
149
-	#_sqlite_init(); // fait la premiere fois dans spip_sqlite
150
-	$query = spip_sqlite::traduire_requete($query, $serveur);
151
-	if (!$requeter) {
152
-		return $query;
153
-	}
148
+    #spip_log("spip_sqlite_query() > $query",'sqlite.'._LOG_DEBUG);
149
+    #_sqlite_init(); // fait la premiere fois dans spip_sqlite
150
+    $query = spip_sqlite::traduire_requete($query, $serveur);
151
+    if (!$requeter) {
152
+        return $query;
153
+    }
154 154
 
155
-	return spip_sqlite::executer_requete($query, $serveur);
155
+    return spip_sqlite::executer_requete($query, $serveur);
156 156
 }
157 157
 
158 158
 
@@ -169,11 +169,11 @@  discard block
 block discarded – undo
169 169
  */
170 170
 function spip_sqlite_alter($query, $serveur = '', $requeter = true) {
171 171
 
172
-	$query = spip_sqlite_query("ALTER $query", $serveur, false);
173
-	// traduire la requete pour recuperer les bons noms de table
174
-	$query = spip_sqlite::traduire_requete($query, $serveur);
172
+    $query = spip_sqlite_query("ALTER $query", $serveur, false);
173
+    // traduire la requete pour recuperer les bons noms de table
174
+    $query = spip_sqlite::traduire_requete($query, $serveur);
175 175
 
176
-	/*
176
+    /*
177 177
 		 * la il faut faire les transformations
178 178
 		 * si ALTER TABLE x (DROP|CHANGE) y
179 179
 		 *
@@ -182,251 +182,251 @@  discard block
 block discarded – undo
182 182
 		 * 3) faire chaque requete independemment
183 183
 		 */
184 184
 
185
-	// 1
186
-	if (preg_match('/\s*(ALTER(\s*IGNORE)?\s*TABLE\s*([^\s]*))\s*(.*)?/is', $query, $regs)) {
187
-		$debut = $regs[1];
188
-		$table = $regs[3];
189
-		$suite = $regs[4];
190
-	} else {
191
-		spip_log("SQLite : Probleme de ALTER TABLE mal forme dans $query", 'sqlite.' . _LOG_ERREUR);
192
-
193
-		return false;
194
-	}
195
-
196
-	// 2
197
-	// il faudrait une regexp pour eviter de spliter ADD PRIMARY KEY (colA, colB)
198
-	// tout en cassant "ADD PRIMARY KEY (colA, colB), ADD INDEX (chose)"... en deux
199
-	// ou revoir l'api de sql_alter en creant un
200
-	// sql_alter_table($table,array($actions));
201
-	$todo = explode(',', $suite);
202
-
203
-	// on remet les morceaux dechires ensembles... que c'est laid !
204
-	$todo2 = [];
205
-	$i = 0;
206
-	$ouverte = false;
207
-	while ($do = array_shift($todo)) {
208
-		$todo2[$i] = isset($todo2[$i]) ? $todo2[$i] . ',' . $do : $do;
209
-		$o = (false !== strpos($do, '('));
210
-		$f = (false !== strpos($do, ')'));
211
-		if ($o and !$f) {
212
-			$ouverte = true;
213
-		} elseif ($f) {
214
-			$ouverte = false;
215
-		}
216
-		if (!$ouverte) {
217
-			$i++;
218
-		}
219
-	}
220
-
221
-	// 3
222
-	$resultats = [];
223
-	foreach ($todo2 as $do) {
224
-		$do = trim($do);
225
-		if (
226
-			!preg_match('/(DROP PRIMARY KEY|DROP KEY|DROP INDEX|DROP COLUMN|DROP'
227
-			. '|CHANGE COLUMN|CHANGE|MODIFY|RENAME TO|RENAME'
228
-			. '|ADD PRIMARY KEY|ADD KEY|ADD INDEX|ADD UNIQUE KEY|ADD UNIQUE'
229
-			. '|ADD COLUMN|ADD'
230
-			. ')\s*([^\s]*)\s*(.*)?/i', $do, $matches)
231
-		) {
232
-			spip_log(
233
-				"SQLite : Probleme de ALTER TABLE, utilisation non reconnue dans : $do \n(requete d'origine : $query)",
234
-				'sqlite.' . _LOG_ERREUR
235
-			);
236
-
237
-			return false;
238
-		}
239
-
240
-		$cle = strtoupper($matches[1]);
241
-		$colonne_origine = $matches[2];
242
-		$colonne_destination = '';
243
-
244
-		$def = $matches[3];
245
-
246
-		// eluder une eventuelle clause before|after|first inutilisable
247
-		$defr = rtrim(preg_replace('/(BEFORE|AFTER|FIRST)(.*)$/is', '', $def));
248
-		$defo = $defr; // garder la def d'origine pour certains cas
249
-		// remplacer les definitions venant de mysql
250
-		$defr = _sqlite_remplacements_definitions_table($defr);
251
-
252
-		// reinjecter dans le do
253
-		$do = str_replace($def, $defr, $do);
254
-		$def = $defr;
255
-
256
-		switch ($cle) {
257
-			// suppression d'un index
258
-			case 'DROP KEY':
259
-			case 'DROP INDEX':
260
-				$nom_index = $colonne_origine;
261
-				spip_sqlite_drop_index($nom_index, $table, $serveur);
262
-				break;
263
-
264
-			// suppression d'une pk
265
-			case 'DROP PRIMARY KEY':
266
-				if (
267
-					!_sqlite_modifier_table(
268
-						$table,
269
-						$colonne_origine,
270
-						['key' => ['PRIMARY KEY' => '']],
271
-						$serveur
272
-					)
273
-				) {
274
-					return false;
275
-				}
276
-				break;
277
-			// suppression d'une colonne
278
-			case 'DROP COLUMN':
279
-			case 'DROP':
280
-				if (
281
-					!_sqlite_modifier_table(
282
-						$table,
283
-						[$colonne_origine => ''],
284
-						[],
285
-						$serveur
286
-					)
287
-				) {
288
-					return false;
289
-				}
290
-				break;
291
-
292
-			case 'CHANGE COLUMN':
293
-			case 'CHANGE':
294
-				// recuperer le nom de la future colonne
295
-				// on reprend la def d'origine car _sqlite_modifier_table va refaire la translation
296
-				// en tenant compte de la cle primaire (ce qui est mieux)
297
-				$def = trim($defo);
298
-				$colonne_destination = substr($def, 0, strpos($def, ' '));
299
-				$def = substr($def, strlen($colonne_destination) + 1);
300
-
301
-				if (
302
-					!_sqlite_modifier_table(
303
-						$table,
304
-						[$colonne_origine => $colonne_destination],
305
-						['field' => [$colonne_destination => $def]],
306
-						$serveur
307
-					)
308
-				) {
309
-					return false;
310
-				}
311
-				break;
312
-
313
-			case 'MODIFY':
314
-				// on reprend la def d'origine car _sqlite_modifier_table va refaire la translation
315
-				// en tenant compte de la cle primaire (ce qui est mieux)
316
-				if (
317
-					!_sqlite_modifier_table(
318
-						$table,
319
-						$colonne_origine,
320
-						['field' => [$colonne_origine => $defo]],
321
-						$serveur
322
-					)
323
-				) {
324
-					return false;
325
-				}
326
-				break;
327
-
328
-			// pas geres en sqlite2
329
-			case 'RENAME':
330
-				$do = 'RENAME TO' . substr($do, 6);
331
-			case 'RENAME TO':
332
-				if (!spip_sqlite::executer_requete("$debut $do", $serveur)) {
333
-					spip_log("SQLite : Erreur ALTER TABLE / RENAME : $query", 'sqlite.' . _LOG_ERREUR);
334
-
335
-					return false;
336
-				}
337
-				break;
338
-
339
-			// ajout d'une pk
340
-			case 'ADD PRIMARY KEY':
341
-				$pk = trim(substr($do, 16));
342
-				$pk = ($pk[0] == '(') ? substr($pk, 1, -1) : $pk;
343
-				if (
344
-					!_sqlite_modifier_table(
345
-						$table,
346
-						$colonne_origine,
347
-						['key' => ['PRIMARY KEY' => $pk]],
348
-						$serveur
349
-					)
350
-				) {
351
-					return false;
352
-				}
353
-				break;
354
-			// ajout d'un index
355
-			case 'ADD UNIQUE KEY':
356
-			case 'ADD UNIQUE':
357
-				$unique = true;
358
-			case 'ADD INDEX':
359
-			case 'ADD KEY':
360
-				if (!isset($unique)) {
361
-					$unique = false;
362
-				}
363
-				// peut etre "(colonne)" ou "nom_index (colonnes)"
364
-				// bug potentiel si qqn met "(colonne, colonne)"
365
-				//
366
-				// nom_index (colonnes)
367
-				if ($def) {
368
-					$colonnes = substr($def, 1, -1);
369
-					$nom_index = $colonne_origine;
370
-				} else {
371
-					// (colonne)
372
-					if ($colonne_origine[0] == '(') {
373
-						$colonnes = substr($colonne_origine, 1, -1);
374
-						if (false !== strpos(',', $colonnes)) {
375
-							spip_log('SQLite : Erreur, impossible de creer un index sur plusieurs colonnes'
376
-								. " sans qu'il ait de nom ($table, ($colonnes))", 'sqlite.' . _LOG_ERREUR);
377
-							break;
378
-						} else {
379
-							$nom_index = $colonnes;
380
-						}
381
-					} // nom_index
382
-					else {
383
-						$nom_index = $colonnes = $colonne_origine;
384
-					}
385
-				}
386
-				spip_sqlite_create_index($nom_index, $table, $colonnes, $unique, $serveur);
387
-				break;
388
-
389
-			// pas geres en sqlite2
390
-			case 'ADD COLUMN':
391
-				$do = 'ADD' . substr($do, 10);
392
-			case 'ADD':
393
-			default:
394
-				if (!preg_match(',primary\s+key,i', $do)) {
395
-					if (!spip_sqlite::executer_requete("$debut $do", $serveur)) {
396
-						spip_log("SQLite : Erreur ALTER TABLE / ADD : $query", 'sqlite.' . _LOG_ERREUR);
397
-
398
-						return false;
399
-					}
400
-					break;
401
-				}
402
-				// ou si la colonne est aussi primary key
403
-				// cas du add id_truc int primary key
404
-				// ajout d'une colonne qui passe en primary key directe
405
-				else {
406
-					$def = trim(substr($do, 3));
407
-					$colonne_ajoutee = substr($def, 0, strpos($def, ' '));
408
-					$def = substr($def, strlen($colonne_ajoutee) + 1);
409
-					$opts = [];
410
-					if (preg_match(',primary\s+key,i', $def)) {
411
-						$opts['key'] = ['PRIMARY KEY' => $colonne_ajoutee];
412
-						$def = preg_replace(',primary\s+key,i', '', $def);
413
-					}
414
-					$opts['field'] = [$colonne_ajoutee => $def];
415
-					if (!_sqlite_modifier_table($table, [$colonne_ajoutee], $opts, $serveur)) {
416
-						spip_log("SQLite : Erreur ALTER TABLE / ADD : $query", 'sqlite.' . _LOG_ERREUR);
417
-
418
-						return false;
419
-					}
420
-				}
421
-				break;
422
-		}
423
-		// tout est bon, ouf !
424
-		spip_log("SQLite ($serveur) : Changements OK : $debut $do", 'sqlite.' . _LOG_INFO);
425
-	}
426
-
427
-	spip_log("SQLite ($serveur) : fin ALTER TABLE OK !", 'sqlite.' . _LOG_INFO);
428
-
429
-	return true;
185
+    // 1
186
+    if (preg_match('/\s*(ALTER(\s*IGNORE)?\s*TABLE\s*([^\s]*))\s*(.*)?/is', $query, $regs)) {
187
+        $debut = $regs[1];
188
+        $table = $regs[3];
189
+        $suite = $regs[4];
190
+    } else {
191
+        spip_log("SQLite : Probleme de ALTER TABLE mal forme dans $query", 'sqlite.' . _LOG_ERREUR);
192
+
193
+        return false;
194
+    }
195
+
196
+    // 2
197
+    // il faudrait une regexp pour eviter de spliter ADD PRIMARY KEY (colA, colB)
198
+    // tout en cassant "ADD PRIMARY KEY (colA, colB), ADD INDEX (chose)"... en deux
199
+    // ou revoir l'api de sql_alter en creant un
200
+    // sql_alter_table($table,array($actions));
201
+    $todo = explode(',', $suite);
202
+
203
+    // on remet les morceaux dechires ensembles... que c'est laid !
204
+    $todo2 = [];
205
+    $i = 0;
206
+    $ouverte = false;
207
+    while ($do = array_shift($todo)) {
208
+        $todo2[$i] = isset($todo2[$i]) ? $todo2[$i] . ',' . $do : $do;
209
+        $o = (false !== strpos($do, '('));
210
+        $f = (false !== strpos($do, ')'));
211
+        if ($o and !$f) {
212
+            $ouverte = true;
213
+        } elseif ($f) {
214
+            $ouverte = false;
215
+        }
216
+        if (!$ouverte) {
217
+            $i++;
218
+        }
219
+    }
220
+
221
+    // 3
222
+    $resultats = [];
223
+    foreach ($todo2 as $do) {
224
+        $do = trim($do);
225
+        if (
226
+            !preg_match('/(DROP PRIMARY KEY|DROP KEY|DROP INDEX|DROP COLUMN|DROP'
227
+            . '|CHANGE COLUMN|CHANGE|MODIFY|RENAME TO|RENAME'
228
+            . '|ADD PRIMARY KEY|ADD KEY|ADD INDEX|ADD UNIQUE KEY|ADD UNIQUE'
229
+            . '|ADD COLUMN|ADD'
230
+            . ')\s*([^\s]*)\s*(.*)?/i', $do, $matches)
231
+        ) {
232
+            spip_log(
233
+                "SQLite : Probleme de ALTER TABLE, utilisation non reconnue dans : $do \n(requete d'origine : $query)",
234
+                'sqlite.' . _LOG_ERREUR
235
+            );
236
+
237
+            return false;
238
+        }
239
+
240
+        $cle = strtoupper($matches[1]);
241
+        $colonne_origine = $matches[2];
242
+        $colonne_destination = '';
243
+
244
+        $def = $matches[3];
245
+
246
+        // eluder une eventuelle clause before|after|first inutilisable
247
+        $defr = rtrim(preg_replace('/(BEFORE|AFTER|FIRST)(.*)$/is', '', $def));
248
+        $defo = $defr; // garder la def d'origine pour certains cas
249
+        // remplacer les definitions venant de mysql
250
+        $defr = _sqlite_remplacements_definitions_table($defr);
251
+
252
+        // reinjecter dans le do
253
+        $do = str_replace($def, $defr, $do);
254
+        $def = $defr;
255
+
256
+        switch ($cle) {
257
+            // suppression d'un index
258
+            case 'DROP KEY':
259
+            case 'DROP INDEX':
260
+                $nom_index = $colonne_origine;
261
+                spip_sqlite_drop_index($nom_index, $table, $serveur);
262
+                break;
263
+
264
+            // suppression d'une pk
265
+            case 'DROP PRIMARY KEY':
266
+                if (
267
+                    !_sqlite_modifier_table(
268
+                        $table,
269
+                        $colonne_origine,
270
+                        ['key' => ['PRIMARY KEY' => '']],
271
+                        $serveur
272
+                    )
273
+                ) {
274
+                    return false;
275
+                }
276
+                break;
277
+            // suppression d'une colonne
278
+            case 'DROP COLUMN':
279
+            case 'DROP':
280
+                if (
281
+                    !_sqlite_modifier_table(
282
+                        $table,
283
+                        [$colonne_origine => ''],
284
+                        [],
285
+                        $serveur
286
+                    )
287
+                ) {
288
+                    return false;
289
+                }
290
+                break;
291
+
292
+            case 'CHANGE COLUMN':
293
+            case 'CHANGE':
294
+                // recuperer le nom de la future colonne
295
+                // on reprend la def d'origine car _sqlite_modifier_table va refaire la translation
296
+                // en tenant compte de la cle primaire (ce qui est mieux)
297
+                $def = trim($defo);
298
+                $colonne_destination = substr($def, 0, strpos($def, ' '));
299
+                $def = substr($def, strlen($colonne_destination) + 1);
300
+
301
+                if (
302
+                    !_sqlite_modifier_table(
303
+                        $table,
304
+                        [$colonne_origine => $colonne_destination],
305
+                        ['field' => [$colonne_destination => $def]],
306
+                        $serveur
307
+                    )
308
+                ) {
309
+                    return false;
310
+                }
311
+                break;
312
+
313
+            case 'MODIFY':
314
+                // on reprend la def d'origine car _sqlite_modifier_table va refaire la translation
315
+                // en tenant compte de la cle primaire (ce qui est mieux)
316
+                if (
317
+                    !_sqlite_modifier_table(
318
+                        $table,
319
+                        $colonne_origine,
320
+                        ['field' => [$colonne_origine => $defo]],
321
+                        $serveur
322
+                    )
323
+                ) {
324
+                    return false;
325
+                }
326
+                break;
327
+
328
+            // pas geres en sqlite2
329
+            case 'RENAME':
330
+                $do = 'RENAME TO' . substr($do, 6);
331
+            case 'RENAME TO':
332
+                if (!spip_sqlite::executer_requete("$debut $do", $serveur)) {
333
+                    spip_log("SQLite : Erreur ALTER TABLE / RENAME : $query", 'sqlite.' . _LOG_ERREUR);
334
+
335
+                    return false;
336
+                }
337
+                break;
338
+
339
+            // ajout d'une pk
340
+            case 'ADD PRIMARY KEY':
341
+                $pk = trim(substr($do, 16));
342
+                $pk = ($pk[0] == '(') ? substr($pk, 1, -1) : $pk;
343
+                if (
344
+                    !_sqlite_modifier_table(
345
+                        $table,
346
+                        $colonne_origine,
347
+                        ['key' => ['PRIMARY KEY' => $pk]],
348
+                        $serveur
349
+                    )
350
+                ) {
351
+                    return false;
352
+                }
353
+                break;
354
+            // ajout d'un index
355
+            case 'ADD UNIQUE KEY':
356
+            case 'ADD UNIQUE':
357
+                $unique = true;
358
+            case 'ADD INDEX':
359
+            case 'ADD KEY':
360
+                if (!isset($unique)) {
361
+                    $unique = false;
362
+                }
363
+                // peut etre "(colonne)" ou "nom_index (colonnes)"
364
+                // bug potentiel si qqn met "(colonne, colonne)"
365
+                //
366
+                // nom_index (colonnes)
367
+                if ($def) {
368
+                    $colonnes = substr($def, 1, -1);
369
+                    $nom_index = $colonne_origine;
370
+                } else {
371
+                    // (colonne)
372
+                    if ($colonne_origine[0] == '(') {
373
+                        $colonnes = substr($colonne_origine, 1, -1);
374
+                        if (false !== strpos(',', $colonnes)) {
375
+                            spip_log('SQLite : Erreur, impossible de creer un index sur plusieurs colonnes'
376
+                                . " sans qu'il ait de nom ($table, ($colonnes))", 'sqlite.' . _LOG_ERREUR);
377
+                            break;
378
+                        } else {
379
+                            $nom_index = $colonnes;
380
+                        }
381
+                    } // nom_index
382
+                    else {
383
+                        $nom_index = $colonnes = $colonne_origine;
384
+                    }
385
+                }
386
+                spip_sqlite_create_index($nom_index, $table, $colonnes, $unique, $serveur);
387
+                break;
388
+
389
+            // pas geres en sqlite2
390
+            case 'ADD COLUMN':
391
+                $do = 'ADD' . substr($do, 10);
392
+            case 'ADD':
393
+            default:
394
+                if (!preg_match(',primary\s+key,i', $do)) {
395
+                    if (!spip_sqlite::executer_requete("$debut $do", $serveur)) {
396
+                        spip_log("SQLite : Erreur ALTER TABLE / ADD : $query", 'sqlite.' . _LOG_ERREUR);
397
+
398
+                        return false;
399
+                    }
400
+                    break;
401
+                }
402
+                // ou si la colonne est aussi primary key
403
+                // cas du add id_truc int primary key
404
+                // ajout d'une colonne qui passe en primary key directe
405
+                else {
406
+                    $def = trim(substr($do, 3));
407
+                    $colonne_ajoutee = substr($def, 0, strpos($def, ' '));
408
+                    $def = substr($def, strlen($colonne_ajoutee) + 1);
409
+                    $opts = [];
410
+                    if (preg_match(',primary\s+key,i', $def)) {
411
+                        $opts['key'] = ['PRIMARY KEY' => $colonne_ajoutee];
412
+                        $def = preg_replace(',primary\s+key,i', '', $def);
413
+                    }
414
+                    $opts['field'] = [$colonne_ajoutee => $def];
415
+                    if (!_sqlite_modifier_table($table, [$colonne_ajoutee], $opts, $serveur)) {
416
+                        spip_log("SQLite : Erreur ALTER TABLE / ADD : $query", 'sqlite.' . _LOG_ERREUR);
417
+
418
+                        return false;
419
+                    }
420
+                }
421
+                break;
422
+        }
423
+        // tout est bon, ouf !
424
+        spip_log("SQLite ($serveur) : Changements OK : $debut $do", 'sqlite.' . _LOG_INFO);
425
+    }
426
+
427
+    spip_log("SQLite ($serveur) : fin ALTER TABLE OK !", 'sqlite.' . _LOG_INFO);
428
+
429
+    return true;
430 430
 }
431 431
 
432 432
 
@@ -449,38 +449,38 @@  discard block
 block discarded – undo
449 449
  *     - true si la requête réussie, false sinon.
450 450
  */
451 451
 function spip_sqlite_create(
452
-	$nom,
453
-	$champs,
454
-	$cles,
455
-	$autoinc = false,
456
-	$temporary = false,
457
-	$serveur = '',
458
-	$requeter = true
452
+    $nom,
453
+    $champs,
454
+    $cles,
455
+    $autoinc = false,
456
+    $temporary = false,
457
+    $serveur = '',
458
+    $requeter = true
459 459
 ) {
460
-	$query = _sqlite_requete_create($nom, $champs, $cles, $autoinc, $temporary, $ifnotexists = true, $serveur, $requeter);
461
-	if (!$query) {
462
-		return false;
463
-	}
464
-	$res = spip_sqlite_query($query, $serveur, $requeter);
465
-
466
-	// SQLite ne cree pas les KEY sur les requetes CREATE TABLE
467
-	// il faut donc les faire creer ensuite
468
-	if (!$requeter) {
469
-		return $res;
470
-	}
471
-
472
-	$ok = $res ? true : false;
473
-	if ($ok) {
474
-		foreach ($cles as $k => $v) {
475
-			if (preg_match(',^(UNIQUE KEY|KEY|UNIQUE)\s,i', $k, $m)) {
476
-				$index = trim(substr($k, strlen($m[1])));
477
-				$unique = (strlen($m[1]) > 3);
478
-				$ok &= spip_sqlite_create_index($index, $nom, $v, $unique, $serveur);
479
-			}
480
-		}
481
-	}
482
-
483
-	return $ok ? true : false;
460
+    $query = _sqlite_requete_create($nom, $champs, $cles, $autoinc, $temporary, $ifnotexists = true, $serveur, $requeter);
461
+    if (!$query) {
462
+        return false;
463
+    }
464
+    $res = spip_sqlite_query($query, $serveur, $requeter);
465
+
466
+    // SQLite ne cree pas les KEY sur les requetes CREATE TABLE
467
+    // il faut donc les faire creer ensuite
468
+    if (!$requeter) {
469
+        return $res;
470
+    }
471
+
472
+    $ok = $res ? true : false;
473
+    if ($ok) {
474
+        foreach ($cles as $k => $v) {
475
+            if (preg_match(',^(UNIQUE KEY|KEY|UNIQUE)\s,i', $k, $m)) {
476
+                $index = trim(substr($k, strlen($m[1])));
477
+                $unique = (strlen($m[1]) > 3);
478
+                $ok &= spip_sqlite_create_index($index, $nom, $v, $unique, $serveur);
479
+            }
480
+        }
481
+    }
482
+
483
+    return $ok ? true : false;
484 484
 }
485 485
 
486 486
 /**
@@ -493,21 +493,21 @@  discard block
 block discarded – undo
493 493
  * @return bool true si la base est créee.
494 494
  **/
495 495
 function spip_sqlite_create_base($nom, $serveur = '', $option = true) {
496
-	$f = $nom . '.sqlite';
497
-	if (strpos($nom, '/') === false) {
498
-		$f = _DIR_DB . $f;
499
-	}
496
+    $f = $nom . '.sqlite';
497
+    if (strpos($nom, '/') === false) {
498
+        $f = _DIR_DB . $f;
499
+    }
500 500
 
501
-	$ok = new \PDO("sqlite:$f");
501
+    $ok = new \PDO("sqlite:$f");
502 502
 
503
-	if ($ok) {
504
-		unset($ok);
503
+    if ($ok) {
504
+        unset($ok);
505 505
 
506
-		return true;
507
-	}
508
-	unset($ok);
506
+        return true;
507
+    }
508
+    unset($ok);
509 509
 
510
-	return false;
510
+    return false;
511 511
 }
512 512
 
513 513
 
@@ -528,22 +528,22 @@  discard block
 block discarded – undo
528 528
  *     - string texte de la requête si $requeter vaut false
529 529
  */
530 530
 function spip_sqlite_create_view($nom, $query_select, $serveur = '', $requeter = true) {
531
-	if (!$query_select) {
532
-		return false;
533
-	}
534
-	// vue deja presente
535
-	if (sql_showtable($nom, false, $serveur)) {
536
-		spip_log(
537
-			"Echec creation d'une vue sql ($nom) car celle-ci existe deja (serveur:$serveur)",
538
-			'sqlite.' . _LOG_ERREUR
539
-		);
531
+    if (!$query_select) {
532
+        return false;
533
+    }
534
+    // vue deja presente
535
+    if (sql_showtable($nom, false, $serveur)) {
536
+        spip_log(
537
+            "Echec creation d'une vue sql ($nom) car celle-ci existe deja (serveur:$serveur)",
538
+            'sqlite.' . _LOG_ERREUR
539
+        );
540 540
 
541
-		return false;
542
-	}
541
+        return false;
542
+    }
543 543
 
544
-	$query = "CREATE VIEW $nom AS " . $query_select;
544
+    $query = "CREATE VIEW $nom AS " . $query_select;
545 545
 
546
-	return spip_sqlite_query($query, $serveur, $requeter);
546
+    return spip_sqlite_query($query, $serveur, $requeter);
547 547
 }
548 548
 
549 549
 /**
@@ -565,54 +565,54 @@  discard block
 block discarded – undo
565 565
  *    string : requête, false si erreur, true sinon.
566 566
  */
567 567
 function spip_sqlite_create_index($nom, $table, $champs, $unique = '', $serveur = '', $requeter = true) {
568
-	if (!($nom or $table or $champs)) {
569
-		spip_log(
570
-			"Champ manquant pour creer un index sqlite ($nom, $table, (" . join(',', $champs) . '))',
571
-			'sqlite.' . _LOG_ERREUR
572
-		);
573
-
574
-		return false;
575
-	}
576
-
577
-	// SQLite ne differentie pas noms des index en fonction des tables
578
-	// il faut donc creer des noms uniques d'index pour une base sqlite
579
-	$nom = $table . '_' . $nom;
580
-	// enlever d'eventuelles parentheses deja presentes sur champs
581
-	if (!is_array($champs)) {
582
-		if ($champs[0] == '(') {
583
-			$champs = substr($champs, 1, -1);
584
-		}
585
-		$champs = [$champs];
586
-		// supprimer l'info de longueur d'index mysql en fin de champ
587
-		$champs = preg_replace(',\(\d+\)$,', '', $champs);
588
-	}
589
-
590
-	$ifnotexists = '';
591
-	$version = spip_sqlite_fetch(spip_sqlite_query('select sqlite_version() AS sqlite_version', $serveur), '', $serveur);
592
-	if (!function_exists('spip_version_compare')) {
593
-		include_spip('plugins/installer');
594
-	}
595
-
596
-	if ($version and spip_version_compare($version['sqlite_version'], '3.3.0', '>=')) {
597
-		$ifnotexists = ' IF NOT EXISTS';
598
-	} else {
599
-		/* simuler le IF EXISTS - version 2 et sqlite < 3.3a */
600
-		$a = spip_sqlite_showtable($table, $serveur);
601
-		if (isset($a['key']['KEY ' . $nom])) {
602
-			return true;
603
-		}
604
-	}
605
-
606
-	$query = 'CREATE ' . ($unique ? 'UNIQUE ' : '') . "INDEX$ifnotexists $nom ON $table (" . join(',', $champs) . ')';
607
-	$res = spip_sqlite_query($query, $serveur, $requeter);
608
-	if (!$requeter) {
609
-		return $res;
610
-	}
611
-	if ($res) {
612
-		return true;
613
-	} else {
614
-		return false;
615
-	}
568
+    if (!($nom or $table or $champs)) {
569
+        spip_log(
570
+            "Champ manquant pour creer un index sqlite ($nom, $table, (" . join(',', $champs) . '))',
571
+            'sqlite.' . _LOG_ERREUR
572
+        );
573
+
574
+        return false;
575
+    }
576
+
577
+    // SQLite ne differentie pas noms des index en fonction des tables
578
+    // il faut donc creer des noms uniques d'index pour une base sqlite
579
+    $nom = $table . '_' . $nom;
580
+    // enlever d'eventuelles parentheses deja presentes sur champs
581
+    if (!is_array($champs)) {
582
+        if ($champs[0] == '(') {
583
+            $champs = substr($champs, 1, -1);
584
+        }
585
+        $champs = [$champs];
586
+        // supprimer l'info de longueur d'index mysql en fin de champ
587
+        $champs = preg_replace(',\(\d+\)$,', '', $champs);
588
+    }
589
+
590
+    $ifnotexists = '';
591
+    $version = spip_sqlite_fetch(spip_sqlite_query('select sqlite_version() AS sqlite_version', $serveur), '', $serveur);
592
+    if (!function_exists('spip_version_compare')) {
593
+        include_spip('plugins/installer');
594
+    }
595
+
596
+    if ($version and spip_version_compare($version['sqlite_version'], '3.3.0', '>=')) {
597
+        $ifnotexists = ' IF NOT EXISTS';
598
+    } else {
599
+        /* simuler le IF EXISTS - version 2 et sqlite < 3.3a */
600
+        $a = spip_sqlite_showtable($table, $serveur);
601
+        if (isset($a['key']['KEY ' . $nom])) {
602
+            return true;
603
+        }
604
+    }
605
+
606
+    $query = 'CREATE ' . ($unique ? 'UNIQUE ' : '') . "INDEX$ifnotexists $nom ON $table (" . join(',', $champs) . ')';
607
+    $res = spip_sqlite_query($query, $serveur, $requeter);
608
+    if (!$requeter) {
609
+        return $res;
610
+    }
611
+    if ($res) {
612
+        return true;
613
+    } else {
614
+        return false;
615
+    }
616 616
 }
617 617
 
618 618
 /**
@@ -629,31 +629,31 @@  discard block
 block discarded – undo
629 629
  * @return int                 Nombre de lignes
630 630
  */
631 631
 function spip_sqlite_count($r, $serveur = '', $requeter = true) {
632
-	if (!$r) {
633
-		return 0;
634
-	}
635
-
636
-	// select ou autre (insert, update,...) ?
637
-	// (link,requete) a compter
638
-	if (is_array($r->spipSqliteRowCount)) {
639
-		list($link, $query) = $r->spipSqliteRowCount;
640
-		// amelioration possible a tester intensivement : pas de order by pour compter !
641
-		// $query = preg_replace(",ORDER BY .+(LIMIT\s|HAVING\s|GROUP BY\s|$),Uims","\\1",$query);
642
-		$query = "SELECT count(*) as zzzzsqlitecount FROM ($query)";
643
-		$l = $link->query($query);
644
-		$i = 0;
645
-		if ($l and $z = $l->fetch()) {
646
-			$i = $z['zzzzsqlitecount'];
647
-		}
648
-		$r->spipSqliteRowCount = $i;
649
-	}
650
-	if (isset($r->spipSqliteRowCount)) {
651
-		// Ce compte est faux s'il y a des limit dans la requete :(
652
-		// il retourne le nombre d'enregistrements sans le limit
653
-		return $r->spipSqliteRowCount;
654
-	} else {
655
-		return $r->rowCount();
656
-	}
632
+    if (!$r) {
633
+        return 0;
634
+    }
635
+
636
+    // select ou autre (insert, update,...) ?
637
+    // (link,requete) a compter
638
+    if (is_array($r->spipSqliteRowCount)) {
639
+        list($link, $query) = $r->spipSqliteRowCount;
640
+        // amelioration possible a tester intensivement : pas de order by pour compter !
641
+        // $query = preg_replace(",ORDER BY .+(LIMIT\s|HAVING\s|GROUP BY\s|$),Uims","\\1",$query);
642
+        $query = "SELECT count(*) as zzzzsqlitecount FROM ($query)";
643
+        $l = $link->query($query);
644
+        $i = 0;
645
+        if ($l and $z = $l->fetch()) {
646
+            $i = $z['zzzzsqlitecount'];
647
+        }
648
+        $r->spipSqliteRowCount = $i;
649
+    }
650
+    if (isset($r->spipSqliteRowCount)) {
651
+        // Ce compte est faux s'il y a des limit dans la requete :(
652
+        // il retourne le nombre d'enregistrements sans le limit
653
+        return $r->spipSqliteRowCount;
654
+    } else {
655
+        return $r->rowCount();
656
+    }
657 657
 }
658 658
 
659 659
 
@@ -672,30 +672,30 @@  discard block
 block discarded – undo
672 672
  *     - false si la requête a échouée
673 673
  **/
674 674
 function spip_sqlite_countsel(
675
-	$from = [],
676
-	$where = [],
677
-	$groupby = '',
678
-	$having = [],
679
-	$serveur = '',
680
-	$requeter = true
675
+    $from = [],
676
+    $where = [],
677
+    $groupby = '',
678
+    $having = [],
679
+    $serveur = '',
680
+    $requeter = true
681 681
 ) {
682
-	$c = !$groupby ? '*' : ('DISTINCT ' . (is_string($groupby) ? $groupby : join(',', $groupby)));
683
-	$r = spip_sqlite_select(
684
-		"COUNT($c)",
685
-		$from,
686
-		$where,
687
-		'',
688
-		'',
689
-		'',
690
-		$having,
691
-		$serveur,
692
-		$requeter
693
-	);
694
-	if ((is_resource($r) or is_object($r)) && $requeter) { // ressource : sqlite2, object : sqlite3
695
-		list($r) = spip_sqlite_fetch($r, SPIP_SQLITE3_NUM, $serveur);
696
-	}
697
-
698
-	return $r;
682
+    $c = !$groupby ? '*' : ('DISTINCT ' . (is_string($groupby) ? $groupby : join(',', $groupby)));
683
+    $r = spip_sqlite_select(
684
+        "COUNT($c)",
685
+        $from,
686
+        $where,
687
+        '',
688
+        '',
689
+        '',
690
+        $having,
691
+        $serveur,
692
+        $requeter
693
+    );
694
+    if ((is_resource($r) or is_object($r)) && $requeter) { // ressource : sqlite2, object : sqlite3
695
+        list($r) = spip_sqlite_fetch($r, SPIP_SQLITE3_NUM, $serveur);
696
+    }
697
+
698
+    return $r;
699 699
 }
700 700
 
701 701
 
@@ -712,24 +712,24 @@  discard block
 block discarded – undo
712 712
  *     - False en cas d'erreur.
713 713
  **/
714 714
 function spip_sqlite_delete($table, $where = '', $serveur = '', $requeter = true) {
715
-	$res = spip_sqlite_query(
716
-		_sqlite_calculer_expression('DELETE FROM', $table, ',')
717
-		. _sqlite_calculer_expression('WHERE', $where),
718
-		$serveur,
719
-		$requeter
720
-	);
715
+    $res = spip_sqlite_query(
716
+        _sqlite_calculer_expression('DELETE FROM', $table, ',')
717
+        . _sqlite_calculer_expression('WHERE', $where),
718
+        $serveur,
719
+        $requeter
720
+    );
721 721
 
722
-	// renvoyer la requete inerte si demandee
723
-	if (!$requeter) {
724
-		return $res;
725
-	}
722
+    // renvoyer la requete inerte si demandee
723
+    if (!$requeter) {
724
+        return $res;
725
+    }
726 726
 
727
-	if ($res) {
728
-		$link = _sqlite_link($serveur);
729
-		return $res->rowCount();
730
-	} else {
731
-		return false;
732
-	}
727
+    if ($res) {
728
+        $link = _sqlite_link($serveur);
729
+        return $res->rowCount();
730
+    } else {
731
+        return false;
732
+    }
733 733
 }
734 734
 
735 735
 
@@ -745,15 +745,15 @@  discard block
 block discarded – undo
745 745
  *     - true si la requête a réussie, false sinon
746 746
  */
747 747
 function spip_sqlite_drop_table($table, $exist = '', $serveur = '', $requeter = true) {
748
-	if ($exist) {
749
-		$exist = ' IF EXISTS';
750
-	}
748
+    if ($exist) {
749
+        $exist = ' IF EXISTS';
750
+    }
751 751
 
752
-	if (spip_sqlite_query("DROP TABLE$exist $table", $serveur, $requeter)) {
753
-		return true;
754
-	} else {
755
-		return false;
756
-	}
752
+    if (spip_sqlite_query("DROP TABLE$exist $table", $serveur, $requeter)) {
753
+        return true;
754
+    } else {
755
+        return false;
756
+    }
757 757
 }
758 758
 
759 759
 
@@ -769,11 +769,11 @@  discard block
 block discarded – undo
769 769
  *     - true si la requête a réussie, false sinon
770 770
  */
771 771
 function spip_sqlite_drop_view($view, $exist = '', $serveur = '', $requeter = true) {
772
-	if ($exist) {
773
-		$exist = ' IF EXISTS';
774
-	}
772
+    if ($exist) {
773
+        $exist = ' IF EXISTS';
774
+    }
775 775
 
776
-	return spip_sqlite_query("DROP VIEW$exist $view", $serveur, $requeter);
776
+    return spip_sqlite_query("DROP VIEW$exist $view", $serveur, $requeter);
777 777
 }
778 778
 
779 779
 /**
@@ -787,20 +787,20 @@  discard block
 block discarded – undo
787 787
  * @return bool ou requete
788 788
  */
789 789
 function spip_sqlite_drop_index($nom, $table, $serveur = '', $requeter = true) {
790
-	if (!($nom or $table)) {
791
-		spip_log("Champ manquant pour supprimer un index sqlite ($nom, $table)", 'sqlite.' . _LOG_ERREUR);
790
+    if (!($nom or $table)) {
791
+        spip_log("Champ manquant pour supprimer un index sqlite ($nom, $table)", 'sqlite.' . _LOG_ERREUR);
792 792
 
793
-		return false;
794
-	}
793
+        return false;
794
+    }
795 795
 
796
-	// SQLite ne differentie pas noms des index en fonction des tables
797
-	// il faut donc creer des noms uniques d'index pour une base sqlite
798
-	$index = $table . '_' . $nom;
799
-	$exist = ' IF EXISTS';
796
+    // SQLite ne differentie pas noms des index en fonction des tables
797
+    // il faut donc creer des noms uniques d'index pour une base sqlite
798
+    $index = $table . '_' . $nom;
799
+    $exist = ' IF EXISTS';
800 800
 
801
-	$query = "DROP INDEX$exist $index";
801
+    $query = "DROP INDEX$exist $index";
802 802
 
803
-	return spip_sqlite_query($query, $serveur, $requeter);
803
+    return spip_sqlite_query($query, $serveur, $requeter);
804 804
 }
805 805
 
806 806
 /**
@@ -816,28 +816,28 @@  discard block
 block discarded – undo
816 816
  *     Erreur eventuelle
817 817
  **/
818 818
 function spip_sqlite_error($query = '', $serveur = '') {
819
-	$link = _sqlite_link($serveur);
819
+    $link = _sqlite_link($serveur);
820 820
 
821
-	if ($link) {
822
-		$errs = $link->errorInfo();
823
-		$s = _sqlite_last_error_from_link($link);
824
-	} else {
825
-		$s = ': aucune ressource sqlite (link)';
826
-	}
827
-	if ($s) {
828
-		$trace = debug_backtrace();
829
-		if ($trace[0]['function'] != 'spip_sqlite_error') {
830
-			spip_log("$s - $query - " . sql_error_backtrace(), 'sqlite.' . _LOG_ERREUR);
831
-		}
832
-	}
821
+    if ($link) {
822
+        $errs = $link->errorInfo();
823
+        $s = _sqlite_last_error_from_link($link);
824
+    } else {
825
+        $s = ': aucune ressource sqlite (link)';
826
+    }
827
+    if ($s) {
828
+        $trace = debug_backtrace();
829
+        if ($trace[0]['function'] != 'spip_sqlite_error') {
830
+            spip_log("$s - $query - " . sql_error_backtrace(), 'sqlite.' . _LOG_ERREUR);
831
+        }
832
+    }
833 833
 
834
-	return $s;
834
+    return $s;
835 835
 }
836 836
 
837 837
 function _sqlite_last_error_from_link($link) {
838
-	if ($link) {
839
-		$errs = $link->errorInfo();
840
-		/*
838
+    if ($link) {
839
+        $errs = $link->errorInfo();
840
+        /*
841 841
 			$errs[0]
842 842
 				numero SQLState ('HY000' souvent lors d'une erreur)
843 843
 				http://www.easysoft.com/developer/interfaces/odbc/sqlstate_status_return_codes.html
@@ -847,11 +847,11 @@  discard block
 block discarded – undo
847 847
 			$errs[2]
848 848
 				Le texte du message d'erreur
849 849
 		*/
850
-		if (ltrim($errs[0], '0')) { // 00000 si pas d'erreur
851
-			return "$errs[2]";
852
-		}
853
-	}
854
-	return '';
850
+        if (ltrim($errs[0], '0')) { // 00000 si pas d'erreur
851
+            return "$errs[2]";
852
+        }
853
+    }
854
+    return '';
855 855
 }
856 856
 
857 857
 /**
@@ -868,23 +868,23 @@  discard block
 block discarded – undo
868 868
  *    'HY000/1' : numéro de l'erreur SQLState / numéro d'erreur interne SQLite (en sqlite 3)
869 869
  **/
870 870
 function spip_sqlite_errno($serveur = '') {
871
-	$link = _sqlite_link($serveur);
871
+    $link = _sqlite_link($serveur);
872 872
 
873
-	if ($link) {
874
-		$t = $link->errorInfo();
875
-		$s = ltrim($t[0], '0'); // 00000 si pas d'erreur
876
-		if ($s) {
877
-			$s .= ' / ' . $t[1];
878
-		} // ajoute l'erreur du moteur SQLite
879
-	} else {
880
-		$s = ': aucune ressource sqlite (link)';
881
-	}
873
+    if ($link) {
874
+        $t = $link->errorInfo();
875
+        $s = ltrim($t[0], '0'); // 00000 si pas d'erreur
876
+        if ($s) {
877
+            $s .= ' / ' . $t[1];
878
+        } // ajoute l'erreur du moteur SQLite
879
+    } else {
880
+        $s = ': aucune ressource sqlite (link)';
881
+    }
882 882
 
883
-	if ($s) {
884
-		spip_log("Erreur sqlite $s", 'sqlite.' . _LOG_ERREUR);
885
-	}
883
+    if ($s) {
884
+        spip_log("Erreur sqlite $s", 'sqlite.' . _LOG_ERREUR);
885
+    }
886 886
 
887
-	return $s ? $s : 0;
887
+    return $s ? $s : 0;
888 888
 }
889 889
 
890 890
 
@@ -900,19 +900,19 @@  discard block
 block discarded – undo
900 900
  *     - false si on a pas pu avoir d'explication
901 901
  */
902 902
 function spip_sqlite_explain($query, $serveur = '', $requeter = true) {
903
-	if (strpos(ltrim($query), 'SELECT') !== 0) {
904
-		return [];
905
-	}
903
+    if (strpos(ltrim($query), 'SELECT') !== 0) {
904
+        return [];
905
+    }
906 906
 
907
-	$query = spip_sqlite::traduire_requete($query, $serveur);
908
-	$query = 'EXPLAIN ' . $query;
909
-	if (!$requeter) {
910
-		return $query;
911
-	}
912
-	// on ne trace pas ces requetes, sinon on obtient un tracage sans fin...
913
-	$r = spip_sqlite::executer_requete($query, $serveur, false);
907
+    $query = spip_sqlite::traduire_requete($query, $serveur);
908
+    $query = 'EXPLAIN ' . $query;
909
+    if (!$requeter) {
910
+        return $query;
911
+    }
912
+    // on ne trace pas ces requetes, sinon on obtient un tracage sans fin...
913
+    $r = spip_sqlite::executer_requete($query, $serveur, false);
914 914
 
915
-	return $r ? spip_sqlite_fetch($r, null, $serveur) : false; // hum ? etrange ca... a verifier
915
+    return $r ? spip_sqlite_fetch($r, null, $serveur) : false; // hum ? etrange ca... a verifier
916 916
 }
917 917
 
918 918
 
@@ -932,35 +932,35 @@  discard block
 block discarded – undo
932 932
  */
933 933
 function spip_sqlite_fetch($r, $t = '', $serveur = '', $requeter = true) {
934 934
 
935
-	$link = _sqlite_link($serveur);
936
-	$t = $t ? $t : SPIP_SQLITE3_ASSOC;
935
+    $link = _sqlite_link($serveur);
936
+    $t = $t ? $t : SPIP_SQLITE3_ASSOC;
937 937
 
938
-	if (!$r) {
939
-		return false;
940
-	}
938
+    if (!$r) {
939
+        return false;
940
+    }
941 941
 
942
-	$retour = $r->fetch($t);
942
+    $retour = $r->fetch($t);
943 943
 
944
-	if (!$retour) {
945
-		if ($r->errorCode() === '00000') {
946
-			return null;
947
-		}
948
-		return false;
949
-	}
944
+    if (!$retour) {
945
+        if ($r->errorCode() === '00000') {
946
+            return null;
947
+        }
948
+        return false;
949
+    }
950 950
 
951
-	// Renvoie des 'table.titre' au lieu de 'titre' tout court ! pff !
952
-	// suppression de 'table.' pour toutes les cles (c'est un peu violent !)
953
-	// c'est couteux : on ne verifie que la premiere ligne pour voir si on le fait ou non
954
-	if (strpos(implode('', array_keys($retour)), '.') !== false) {
955
-		foreach ($retour as $cle => $val) {
956
-			if (($pos = strpos($cle, '.')) !== false) {
957
-				$retour[substr($cle, $pos + 1)] = &$retour[$cle];
958
-				unset($retour[$cle]);
959
-			}
960
-		}
961
-	}
951
+    // Renvoie des 'table.titre' au lieu de 'titre' tout court ! pff !
952
+    // suppression de 'table.' pour toutes les cles (c'est un peu violent !)
953
+    // c'est couteux : on ne verifie que la premiere ligne pour voir si on le fait ou non
954
+    if (strpos(implode('', array_keys($retour)), '.') !== false) {
955
+        foreach ($retour as $cle => $val) {
956
+            if (($pos = strpos($cle, '.')) !== false) {
957
+                $retour[substr($cle, $pos + 1)] = &$retour[$cle];
958
+                unset($retour[$cle]);
959
+            }
960
+        }
961
+    }
962 962
 
963
-	return $retour;
963
+    return $retour;
964 964
 }
965 965
 
966 966
 /**
@@ -973,8 +973,8 @@  discard block
 block discarded – undo
973 973
  * @return bool True si déplacement réussi, false sinon.
974 974
  **/
975 975
 function spip_sqlite_seek($r, $row_number, $serveur = '', $requeter = true) {
976
-	// encore un truc de bien fichu : PDO ne PEUT PAS faire de seek ou de rewind...
977
-	return false;
976
+    // encore un truc de bien fichu : PDO ne PEUT PAS faire de seek ou de rewind...
977
+    return false;
978 978
 }
979 979
 
980 980
 
@@ -990,10 +990,10 @@  discard block
 block discarded – undo
990 990
  * @return bool                True si réussi
991 991
  */
992 992
 function spip_sqlite_free(&$r, $serveur = '', $requeter = true) {
993
-	unset($r);
993
+    unset($r);
994 994
 
995
-	return true;
996
-	//return sqlite_free_result($r);
995
+    return true;
996
+    //return sqlite_free_result($r);
997 997
 }
998 998
 
999 999
 
@@ -1008,8 +1008,8 @@  discard block
 block discarded – undo
1008 1008
  * @return void
1009 1009
  */
1010 1010
 function spip_sqlite_get_charset($charset = [], $serveur = '', $requeter = true) {
1011
-	//$c = !$charset ? '' : (" LIKE "._q($charset['charset']));
1012
-	//return spip_sqlite_fetch(sqlite_query(_sqlite_link($serveur), "SHOW CHARACTER SET$c"), NULL, $serveur);
1011
+    //$c = !$charset ? '' : (" LIKE "._q($charset['charset']));
1012
+    //return spip_sqlite_fetch(sqlite_query(_sqlite_link($serveur), "SHOW CHARACTER SET$c"), NULL, $serveur);
1013 1013
 }
1014 1014
 
1015 1015
 
@@ -1024,7 +1024,7 @@  discard block
 block discarded – undo
1024 1024
  *     Valeur hexadécimale pour SQLite
1025 1025
  **/
1026 1026
 function spip_sqlite_hex($v) {
1027
-	return hexdec($v);
1027
+    return hexdec($v);
1028 1028
 }
1029 1029
 
1030 1030
 
@@ -1046,7 +1046,7 @@  discard block
 block discarded – undo
1046 1046
  *     Expression de requête SQL
1047 1047
  **/
1048 1048
 function spip_sqlite_in($val, $valeurs, $not = '', $serveur = '', $requeter = true) {
1049
-	return "($val $not IN ($valeurs))";
1049
+    return "($val $not IN ($valeurs))";
1050 1050
 }
1051 1051
 
1052 1052
 
@@ -1074,20 +1074,20 @@  discard block
 block discarded – undo
1074 1074
  **/
1075 1075
 function spip_sqlite_insert($table, $champs, $valeurs, $desc = [], $serveur = '', $requeter = true) {
1076 1076
 
1077
-	$query = "INSERT INTO $table " . ($champs ? "$champs VALUES $valeurs" : 'DEFAULT VALUES');
1078
-	if ($r = spip_sqlite_query($query, $serveur, $requeter)) {
1079
-		if (!$requeter) {
1080
-			return $r;
1081
-		}
1082
-		$nb = spip_sqlite::last_insert_id($serveur);
1083
-	} else {
1084
-		$nb = false;
1085
-	}
1077
+    $query = "INSERT INTO $table " . ($champs ? "$champs VALUES $valeurs" : 'DEFAULT VALUES');
1078
+    if ($r = spip_sqlite_query($query, $serveur, $requeter)) {
1079
+        if (!$requeter) {
1080
+            return $r;
1081
+        }
1082
+        $nb = spip_sqlite::last_insert_id($serveur);
1083
+    } else {
1084
+        $nb = false;
1085
+    }
1086 1086
 
1087
-	$err = spip_sqlite_error($query, $serveur);
1087
+    $err = spip_sqlite_error($query, $serveur);
1088 1088
 
1089
-	// cas particulier : ne pas substituer la reponse spip_sqlite_query si on est en profilage
1090
-	return isset($_GET['var_profile']) ? $r : $nb;
1089
+    // cas particulier : ne pas substituer la reponse spip_sqlite_query si on est en profilage
1090
+    return isset($_GET['var_profile']) ? $r : $nb;
1091 1091
 }
1092 1092
 
1093 1093
 
@@ -1112,28 +1112,28 @@  discard block
 block discarded – undo
1112 1112
  *     - Tableau de description de la requête et du temps d'exécution, si var_profile activé
1113 1113
  **/
1114 1114
 function spip_sqlite_insertq($table, $couples = [], $desc = [], $serveur = '', $requeter = true) {
1115
-	if (!$desc) {
1116
-		$desc = description_table($table, $serveur);
1117
-	}
1118
-	if (!$desc) {
1119
-		die("$table insertion sans description");
1120
-	}
1121
-	$fields = isset($desc['field']) ? $desc['field'] : [];
1115
+    if (!$desc) {
1116
+        $desc = description_table($table, $serveur);
1117
+    }
1118
+    if (!$desc) {
1119
+        die("$table insertion sans description");
1120
+    }
1121
+    $fields = isset($desc['field']) ? $desc['field'] : [];
1122 1122
 
1123
-	foreach ($couples as $champ => $val) {
1124
-		$couples[$champ] = _sqlite_calculer_cite($val, $fields[$champ]);
1125
-	}
1123
+    foreach ($couples as $champ => $val) {
1124
+        $couples[$champ] = _sqlite_calculer_cite($val, $fields[$champ]);
1125
+    }
1126 1126
 
1127
-	// recherche de champs 'timestamp' pour mise a jour auto de ceux-ci
1128
-	$couples = _sqlite_ajouter_champs_timestamp($table, $couples, $desc, $serveur);
1127
+    // recherche de champs 'timestamp' pour mise a jour auto de ceux-ci
1128
+    $couples = _sqlite_ajouter_champs_timestamp($table, $couples, $desc, $serveur);
1129 1129
 
1130
-	$cles = $valeurs = '';
1131
-	if (count($couples)) {
1132
-		$cles = '(' . join(',', array_keys($couples)) . ')';
1133
-		$valeurs = '(' . join(',', $couples) . ')';
1134
-	}
1130
+    $cles = $valeurs = '';
1131
+    if (count($couples)) {
1132
+        $cles = '(' . join(',', array_keys($couples)) . ')';
1133
+        $valeurs = '(' . join(',', $couples) . ')';
1134
+    }
1135 1135
 
1136
-	return spip_sqlite_insert($table, $cles, $valeurs, $desc, $serveur, $requeter);
1136
+    return spip_sqlite_insert($table, $cles, $valeurs, $desc, $serveur, $requeter);
1137 1137
 }
1138 1138
 
1139 1139
 
@@ -1157,70 +1157,70 @@  discard block
 block discarded – undo
1157 1157
  *     - False en cas d'erreur.
1158 1158
  **/
1159 1159
 function spip_sqlite_insertq_multi($table, $tab_couples = [], $desc = [], $serveur = '', $requeter = true) {
1160
-	if (!$desc) {
1161
-		$desc = description_table($table, $serveur);
1162
-	}
1163
-	if (!$desc) {
1164
-		die("$table insertion sans description");
1165
-	}
1166
-	if (!isset($desc['field'])) {
1167
-		$desc['field'] = [];
1168
-	}
1169
-
1170
-	// recuperer les champs 'timestamp' pour mise a jour auto de ceux-ci
1171
-	$maj = _sqlite_ajouter_champs_timestamp($table, [], $desc, $serveur);
1172
-
1173
-	// seul le nom de la table est a traduire ici :
1174
-	// le faire une seule fois au debut
1175
-	$query_start = "INSERT INTO $table ";
1176
-	$query_start = spip_sqlite::traduire_requete($query_start, $serveur);
1177
-
1178
-	// ouvrir une transaction
1179
-	if ($requeter) {
1180
-		spip_sqlite::demarrer_transaction($serveur);
1181
-	}
1182
-
1183
-	while ($couples = array_shift($tab_couples)) {
1184
-		foreach ($couples as $champ => $val) {
1185
-			$couples[$champ] = _sqlite_calculer_cite($val, $desc['field'][$champ]);
1186
-		}
1187
-
1188
-		// inserer les champs timestamp par defaut
1189
-		$couples = array_merge($maj, $couples);
1190
-
1191
-		$champs = $valeurs = '';
1192
-		if (count($couples)) {
1193
-			$champs = '(' . join(',', array_keys($couples)) . ')';
1194
-			$valeurs = '(' . join(',', $couples) . ')';
1195
-			$query = $query_start . "$champs VALUES $valeurs";
1196
-		} else {
1197
-			$query = $query_start . 'DEFAULT VALUES';
1198
-		}
1199
-
1200
-		if ($requeter) {
1201
-			$retour = spip_sqlite::executer_requete($query, $serveur);
1202
-		}
1203
-
1204
-		// sur le dernier couple uniquement
1205
-		if (!count($tab_couples)) {
1206
-			$nb = 0;
1207
-			if ($requeter) {
1208
-				$nb = spip_sqlite::last_insert_id($serveur);
1209
-			} else {
1210
-				return $query;
1211
-			}
1212
-		}
1213
-
1214
-		$err = spip_sqlite_error($query, $serveur);
1215
-	}
1216
-
1217
-	if ($requeter) {
1218
-		spip_sqlite::finir_transaction($serveur);
1219
-	}
1220
-
1221
-	// renvoie le dernier id d'autoincrement ajoute
1222
-	// cas particulier : ne pas substituer la reponse spip_sqlite_query si on est en profilage
1223
-	return isset($_GET['var_profile']) ? $retour : $nb;
1160
+    if (!$desc) {
1161
+        $desc = description_table($table, $serveur);
1162
+    }
1163
+    if (!$desc) {
1164
+        die("$table insertion sans description");
1165
+    }
1166
+    if (!isset($desc['field'])) {
1167
+        $desc['field'] = [];
1168
+    }
1169
+
1170
+    // recuperer les champs 'timestamp' pour mise a jour auto de ceux-ci
1171
+    $maj = _sqlite_ajouter_champs_timestamp($table, [], $desc, $serveur);
1172
+
1173
+    // seul le nom de la table est a traduire ici :
1174
+    // le faire une seule fois au debut
1175
+    $query_start = "INSERT INTO $table ";
1176
+    $query_start = spip_sqlite::traduire_requete($query_start, $serveur);
1177
+
1178
+    // ouvrir une transaction
1179
+    if ($requeter) {
1180
+        spip_sqlite::demarrer_transaction($serveur);
1181
+    }
1182
+
1183
+    while ($couples = array_shift($tab_couples)) {
1184
+        foreach ($couples as $champ => $val) {
1185
+            $couples[$champ] = _sqlite_calculer_cite($val, $desc['field'][$champ]);
1186
+        }
1187
+
1188
+        // inserer les champs timestamp par defaut
1189
+        $couples = array_merge($maj, $couples);
1190
+
1191
+        $champs = $valeurs = '';
1192
+        if (count($couples)) {
1193
+            $champs = '(' . join(',', array_keys($couples)) . ')';
1194
+            $valeurs = '(' . join(',', $couples) . ')';
1195
+            $query = $query_start . "$champs VALUES $valeurs";
1196
+        } else {
1197
+            $query = $query_start . 'DEFAULT VALUES';
1198
+        }
1199
+
1200
+        if ($requeter) {
1201
+            $retour = spip_sqlite::executer_requete($query, $serveur);
1202
+        }
1203
+
1204
+        // sur le dernier couple uniquement
1205
+        if (!count($tab_couples)) {
1206
+            $nb = 0;
1207
+            if ($requeter) {
1208
+                $nb = spip_sqlite::last_insert_id($serveur);
1209
+            } else {
1210
+                return $query;
1211
+            }
1212
+        }
1213
+
1214
+        $err = spip_sqlite_error($query, $serveur);
1215
+    }
1216
+
1217
+    if ($requeter) {
1218
+        spip_sqlite::finir_transaction($serveur);
1219
+    }
1220
+
1221
+    // renvoie le dernier id d'autoincrement ajoute
1222
+    // cas particulier : ne pas substituer la reponse spip_sqlite_query si on est en profilage
1223
+    return isset($_GET['var_profile']) ? $retour : $nb;
1224 1224
 }
1225 1225
 
1226 1226
 
@@ -1235,7 +1235,7 @@  discard block
 block discarded – undo
1235 1235
  *     Toujours true.
1236 1236
  **/
1237 1237
 function spip_sqlite_preferer_transaction($serveur = '', $requeter = true) {
1238
-	return true;
1238
+    return true;
1239 1239
 }
1240 1240
 
1241 1241
 /**
@@ -1252,12 +1252,12 @@  discard block
 block discarded – undo
1252 1252
  *     string si texte de la requête demandé, true sinon
1253 1253
  **/
1254 1254
 function spip_sqlite_demarrer_transaction($serveur = '', $requeter = true) {
1255
-	if (!$requeter) {
1256
-		return 'BEGIN TRANSACTION';
1257
-	}
1258
-	spip_sqlite::demarrer_transaction($serveur);
1255
+    if (!$requeter) {
1256
+        return 'BEGIN TRANSACTION';
1257
+    }
1258
+    spip_sqlite::demarrer_transaction($serveur);
1259 1259
 
1260
-	return true;
1260
+    return true;
1261 1261
 }
1262 1262
 
1263 1263
 /**
@@ -1271,12 +1271,12 @@  discard block
 block discarded – undo
1271 1271
  *     string si texte de la requête demandé, true sinon
1272 1272
  **/
1273 1273
 function spip_sqlite_terminer_transaction($serveur = '', $requeter = true) {
1274
-	if (!$requeter) {
1275
-		return 'COMMIT';
1276
-	}
1277
-	spip_sqlite::finir_transaction($serveur);
1274
+    if (!$requeter) {
1275
+        return 'COMMIT';
1276
+    }
1277
+    spip_sqlite::finir_transaction($serveur);
1278 1278
 
1279
-	return true;
1279
+    return true;
1280 1280
 }
1281 1281
 
1282 1282
 
@@ -1291,27 +1291,27 @@  discard block
 block discarded – undo
1291 1291
  *     Liste des noms de bases
1292 1292
  **/
1293 1293
 function spip_sqlite_listdbs($serveur = '', $requeter = true) {
1294
-	_sqlite_init();
1294
+    _sqlite_init();
1295 1295
 
1296
-	if (!is_dir($d = substr(_DIR_DB, 0, -1))) {
1297
-		return [];
1298
-	}
1296
+    if (!is_dir($d = substr(_DIR_DB, 0, -1))) {
1297
+        return [];
1298
+    }
1299 1299
 
1300
-	include_spip('inc/flock');
1301
-	$bases = preg_files($d, $pattern = '(.*)\.sqlite$');
1302
-	$bds = [];
1300
+    include_spip('inc/flock');
1301
+    $bases = preg_files($d, $pattern = '(.*)\.sqlite$');
1302
+    $bds = [];
1303 1303
 
1304
-	foreach ($bases as $b) {
1305
-		// pas de bases commencant pas sqlite
1306
-		// (on s'en sert pour l'installation pour simuler la presence d'un serveur)
1307
-		// les bases sont de la forme _sqliteX_tmp_spip_install.sqlite
1308
-		if (strpos($b, '_sqlite')) {
1309
-			continue;
1310
-		}
1311
-		$bds[] = preg_replace(";.*/$pattern;iS", '$1', $b);
1312
-	}
1304
+    foreach ($bases as $b) {
1305
+        // pas de bases commencant pas sqlite
1306
+        // (on s'en sert pour l'installation pour simuler la presence d'un serveur)
1307
+        // les bases sont de la forme _sqliteX_tmp_spip_install.sqlite
1308
+        if (strpos($b, '_sqlite')) {
1309
+            continue;
1310
+        }
1311
+        $bds[] = preg_replace(";.*/$pattern;iS", '$1', $b);
1312
+    }
1313 1313
 
1314
-	return $bds;
1314
+    return $bds;
1315 1315
 }
1316 1316
 
1317 1317
 
@@ -1326,9 +1326,9 @@  discard block
 block discarded – undo
1326 1326
  * @return string       Texte de sélection pour la requête
1327 1327
  */
1328 1328
 function spip_sqlite_multi($objet, $lang) {
1329
-	$r = 'EXTRAIRE_MULTI(' . $objet . ", '" . $lang . "') AS multi";
1329
+    $r = 'EXTRAIRE_MULTI(' . $objet . ", '" . $lang . "') AS multi";
1330 1330
 
1331
-	return $r;
1331
+    return $r;
1332 1332
 }
1333 1333
 
1334 1334
 
@@ -1345,15 +1345,15 @@  discard block
 block discarded – undo
1345 1345
  * @return bool|string true / false / requete
1346 1346
  **/
1347 1347
 function spip_sqlite_optimize($table, $serveur = '', $requeter = true) {
1348
-	static $do = false;
1349
-	if ($requeter and $do) {
1350
-		return true;
1351
-	}
1352
-	if ($requeter) {
1353
-		$do = true;
1354
-	}
1348
+    static $do = false;
1349
+    if ($requeter and $do) {
1350
+        return true;
1351
+    }
1352
+    if ($requeter) {
1353
+        $do = true;
1354
+    }
1355 1355
 
1356
-	return spip_sqlite_query('VACUUM', $serveur, $requeter);
1356
+    return spip_sqlite_query('VACUUM', $serveur, $requeter);
1357 1357
 }
1358 1358
 
1359 1359
 
@@ -1370,15 +1370,15 @@  discard block
 block discarded – undo
1370 1370
  *    Donnée prête à être utilisée par le gestionnaire SQL
1371 1371
  */
1372 1372
 function spip_sqlite_quote($v, $type = '') {
1373
-	if (!is_array($v)) {
1374
-		return _sqlite_calculer_cite($v, $type);
1375
-	}
1376
-	// si c'est un tableau, le parcourir en propageant le type
1377
-	foreach ($v as $k => $r) {
1378
-		$v[$k] = spip_sqlite_quote($r, $type);
1379
-	}
1373
+    if (!is_array($v)) {
1374
+        return _sqlite_calculer_cite($v, $type);
1375
+    }
1376
+    // si c'est un tableau, le parcourir en propageant le type
1377
+    foreach ($v as $k => $r) {
1378
+        $v[$k] = spip_sqlite_quote($r, $type);
1379
+    }
1380 1380
 
1381
-	return join(',', $v);
1381
+    return join(',', $v);
1382 1382
 }
1383 1383
 
1384 1384
 
@@ -1395,9 +1395,9 @@  discard block
 block discarded – undo
1395 1395
  *     Expression SQL
1396 1396
  **/
1397 1397
 function spip_sqlite_date_proche($champ, $interval, $unite) {
1398
-	$op = (($interval <= 0) ? '>' : '<');
1398
+    $op = (($interval <= 0) ? '>' : '<');
1399 1399
 
1400
-	return "($champ $op datetime('" . date('Y-m-d H:i:s') . "', '$interval $unite'))";
1400
+    return "($champ $op datetime('" . date('Y-m-d H:i:s') . "', '$interval $unite'))";
1401 1401
 }
1402 1402
 
1403 1403
 
@@ -1415,48 +1415,48 @@  discard block
 block discarded – undo
1415 1415
  *     l'état de la table après la réparation
1416 1416
  */
1417 1417
 function spip_sqlite_repair($table, $serveur = '', $requeter = true) {
1418
-	if (
1419
-		$desc = spip_sqlite_showtable($table, $serveur)
1420
-		and isset($desc['field'])
1421
-		and is_array($desc['field'])
1422
-	) {
1423
-		foreach ($desc['field'] as $c => $d) {
1424
-			if (
1425
-				preg_match(',^(tinytext|mediumtext|text|longtext|varchar|char),i', $d)
1426
-				and stripos($d, 'NOT NULL') !== false
1427
-				and stripos($d, 'DEFAULT') === false
1428
-				/* pas touche aux cles primaires */
1429
-				and (!isset($desc['key']['PRIMARY KEY']) or $desc['key']['PRIMARY KEY'] !== $c)
1430
-			) {
1431
-				spip_sqlite_alter($q = "TABLE $table CHANGE $c $c $d DEFAULT ''", $serveur);
1432
-				spip_log("ALTER $q", 'repair' . _LOG_INFO_IMPORTANTE);
1433
-			}
1434
-			if (
1435
-				preg_match(',^(INTEGER),i', $d)
1436
-				and stripos($d, 'NOT NULL') !== false
1437
-				and stripos($d, 'DEFAULT') === false
1438
-				/* pas touche aux cles primaires */
1439
-				and (!isset($desc['key']['PRIMARY KEY']) or $desc['key']['PRIMARY KEY'] !== $c)
1440
-			) {
1441
-				spip_sqlite_alter($q = "TABLE $table CHANGE $c $c $d DEFAULT '0'", $serveur);
1442
-				spip_log("ALTER $q", 'repair' . _LOG_INFO_IMPORTANTE);
1443
-			}
1444
-			if (
1445
-				preg_match(',^(datetime),i', $d)
1446
-				and stripos($d, 'NOT NULL') !== false
1447
-				and stripos($d, 'DEFAULT') === false
1448
-				/* pas touche aux cles primaires */
1449
-				and (!isset($desc['key']['PRIMARY KEY']) or $desc['key']['PRIMARY KEY'] !== $c)
1450
-			) {
1451
-				spip_sqlite_alter($q = "TABLE $table CHANGE $c $c $d DEFAULT '0000-00-00 00:00:00'", $serveur);
1452
-				spip_log("ALTER $q", 'repair' . _LOG_INFO_IMPORTANTE);
1453
-			}
1454
-		}
1455
-
1456
-		return [' OK '];
1457
-	}
1458
-
1459
-	return [' ERROR '];
1418
+    if (
1419
+        $desc = spip_sqlite_showtable($table, $serveur)
1420
+        and isset($desc['field'])
1421
+        and is_array($desc['field'])
1422
+    ) {
1423
+        foreach ($desc['field'] as $c => $d) {
1424
+            if (
1425
+                preg_match(',^(tinytext|mediumtext|text|longtext|varchar|char),i', $d)
1426
+                and stripos($d, 'NOT NULL') !== false
1427
+                and stripos($d, 'DEFAULT') === false
1428
+                /* pas touche aux cles primaires */
1429
+                and (!isset($desc['key']['PRIMARY KEY']) or $desc['key']['PRIMARY KEY'] !== $c)
1430
+            ) {
1431
+                spip_sqlite_alter($q = "TABLE $table CHANGE $c $c $d DEFAULT ''", $serveur);
1432
+                spip_log("ALTER $q", 'repair' . _LOG_INFO_IMPORTANTE);
1433
+            }
1434
+            if (
1435
+                preg_match(',^(INTEGER),i', $d)
1436
+                and stripos($d, 'NOT NULL') !== false
1437
+                and stripos($d, 'DEFAULT') === false
1438
+                /* pas touche aux cles primaires */
1439
+                and (!isset($desc['key']['PRIMARY KEY']) or $desc['key']['PRIMARY KEY'] !== $c)
1440
+            ) {
1441
+                spip_sqlite_alter($q = "TABLE $table CHANGE $c $c $d DEFAULT '0'", $serveur);
1442
+                spip_log("ALTER $q", 'repair' . _LOG_INFO_IMPORTANTE);
1443
+            }
1444
+            if (
1445
+                preg_match(',^(datetime),i', $d)
1446
+                and stripos($d, 'NOT NULL') !== false
1447
+                and stripos($d, 'DEFAULT') === false
1448
+                /* pas touche aux cles primaires */
1449
+                and (!isset($desc['key']['PRIMARY KEY']) or $desc['key']['PRIMARY KEY'] !== $c)
1450
+            ) {
1451
+                spip_sqlite_alter($q = "TABLE $table CHANGE $c $c $d DEFAULT '0000-00-00 00:00:00'", $serveur);
1452
+                spip_log("ALTER $q", 'repair' . _LOG_INFO_IMPORTANTE);
1453
+            }
1454
+        }
1455
+
1456
+        return [' OK '];
1457
+    }
1458
+
1459
+    return [' ERROR '];
1460 1460
 }
1461 1461
 
1462 1462
 
@@ -1485,25 +1485,25 @@  discard block
 block discarded – undo
1485 1485
  *     - False en cas d'erreur.
1486 1486
  **/
1487 1487
 function spip_sqlite_replace($table, $couples, $desc = [], $serveur = '', $requeter = true) {
1488
-	if (!$desc) {
1489
-		$desc = description_table($table, $serveur);
1490
-	}
1491
-	if (!$desc) {
1492
-		die("$table insertion sans description");
1493
-	}
1494
-	$fields = isset($desc['field']) ? $desc['field'] : [];
1488
+    if (!$desc) {
1489
+        $desc = description_table($table, $serveur);
1490
+    }
1491
+    if (!$desc) {
1492
+        die("$table insertion sans description");
1493
+    }
1494
+    $fields = isset($desc['field']) ? $desc['field'] : [];
1495 1495
 
1496
-	foreach ($couples as $champ => $val) {
1497
-		$couples[$champ] = _sqlite_calculer_cite($val, $fields[$champ]);
1498
-	}
1496
+    foreach ($couples as $champ => $val) {
1497
+        $couples[$champ] = _sqlite_calculer_cite($val, $fields[$champ]);
1498
+    }
1499 1499
 
1500
-	// recherche de champs 'timestamp' pour mise a jour auto de ceux-ci
1501
-	$couples = _sqlite_ajouter_champs_timestamp($table, $couples, $desc, $serveur);
1500
+    // recherche de champs 'timestamp' pour mise a jour auto de ceux-ci
1501
+    $couples = _sqlite_ajouter_champs_timestamp($table, $couples, $desc, $serveur);
1502 1502
 
1503
-	return spip_sqlite_query("REPLACE INTO $table (" . join(',', array_keys($couples)) . ') VALUES (' . join(
1504
-		',',
1505
-		$couples
1506
-	) . ')', $serveur);
1503
+    return spip_sqlite_query("REPLACE INTO $table (" . join(',', array_keys($couples)) . ') VALUES (' . join(
1504
+        ',',
1505
+        $couples
1506
+    ) . ')', $serveur);
1507 1507
 }
1508 1508
 
1509 1509
 
@@ -1533,13 +1533,13 @@  discard block
 block discarded – undo
1533 1533
  **/
1534 1534
 function spip_sqlite_replace_multi($table, $tab_couples, $desc = [], $serveur = '', $requeter = true) {
1535 1535
 
1536
-	// boucler pour trainter chaque requete independemment
1537
-	foreach ($tab_couples as $couples) {
1538
-		$retour = spip_sqlite_replace($table, $couples, $desc, $serveur, $requeter);
1539
-	}
1536
+    // boucler pour trainter chaque requete independemment
1537
+    foreach ($tab_couples as $couples) {
1538
+        $retour = spip_sqlite_replace($table, $couples, $desc, $serveur, $requeter);
1539
+    }
1540 1540
 
1541
-	// renvoie le dernier id
1542
-	return $retour;
1541
+    // renvoie le dernier id
1542
+    return $retour;
1543 1543
 }
1544 1544
 
1545 1545
 
@@ -1566,44 +1566,44 @@  discard block
 block discarded – undo
1566 1566
  *     - array  : Tableau décrivant requête et temps d'exécution si var_profile actif pour tracer.
1567 1567
  */
1568 1568
 function spip_sqlite_select(
1569
-	$select,
1570
-	$from,
1571
-	$where = '',
1572
-	$groupby = '',
1573
-	$orderby = '',
1574
-	$limit = '',
1575
-	$having = '',
1576
-	$serveur = '',
1577
-	$requeter = true
1569
+    $select,
1570
+    $from,
1571
+    $where = '',
1572
+    $groupby = '',
1573
+    $orderby = '',
1574
+    $limit = '',
1575
+    $having = '',
1576
+    $serveur = '',
1577
+    $requeter = true
1578 1578
 ) {
1579 1579
 
1580
-	// version() n'est pas connu de sqlite
1581
-	$select = str_replace('version()', 'sqlite_version()', $select);
1580
+    // version() n'est pas connu de sqlite
1581
+    $select = str_replace('version()', 'sqlite_version()', $select);
1582 1582
 
1583
-	// recomposer from
1584
-	$from = (!is_array($from) ? $from : _sqlite_calculer_select_as($from));
1583
+    // recomposer from
1584
+    $from = (!is_array($from) ? $from : _sqlite_calculer_select_as($from));
1585 1585
 
1586
-	$query =
1587
-		_sqlite_calculer_expression('SELECT', $select, ', ')
1588
-		. _sqlite_calculer_expression('FROM', $from, ', ')
1589
-		. _sqlite_calculer_expression('WHERE', $where)
1590
-		. _sqlite_calculer_expression('GROUP BY', $groupby, ',')
1591
-		. _sqlite_calculer_expression('HAVING', $having)
1592
-		. ($orderby ? ("\nORDER BY " . _sqlite_calculer_order($orderby)) : '')
1593
-		. ($limit ? "\nLIMIT $limit" : '');
1586
+    $query =
1587
+        _sqlite_calculer_expression('SELECT', $select, ', ')
1588
+        . _sqlite_calculer_expression('FROM', $from, ', ')
1589
+        . _sqlite_calculer_expression('WHERE', $where)
1590
+        . _sqlite_calculer_expression('GROUP BY', $groupby, ',')
1591
+        . _sqlite_calculer_expression('HAVING', $having)
1592
+        . ($orderby ? ("\nORDER BY " . _sqlite_calculer_order($orderby)) : '')
1593
+        . ($limit ? "\nLIMIT $limit" : '');
1594 1594
 
1595
-	// dans un select, on doit renvoyer la requête en cas d'erreur
1596
-	$res = spip_sqlite_query($query, $serveur, $requeter);
1597
-	// texte de la requete demande ?
1598
-	if (!$requeter) {
1599
-		return $res;
1600
-	}
1601
-	// erreur survenue ?
1602
-	if ($res === false) {
1603
-		return spip_sqlite::traduire_requete($query, $serveur);
1604
-	}
1595
+    // dans un select, on doit renvoyer la requête en cas d'erreur
1596
+    $res = spip_sqlite_query($query, $serveur, $requeter);
1597
+    // texte de la requete demande ?
1598
+    if (!$requeter) {
1599
+        return $res;
1600
+    }
1601
+    // erreur survenue ?
1602
+    if ($res === false) {
1603
+        return spip_sqlite::traduire_requete($query, $serveur);
1604
+    }
1605 1605
 
1606
-	return $res;
1606
+    return $res;
1607 1607
 }
1608 1608
 
1609 1609
 
@@ -1622,32 +1622,32 @@  discard block
 block discarded – undo
1622 1622
  *     - False en cas d'erreur.
1623 1623
  **/
1624 1624
 function spip_sqlite_selectdb($db, $serveur = '', $requeter = true) {
1625
-	_sqlite_init();
1625
+    _sqlite_init();
1626 1626
 
1627
-	// interdire la creation d'une nouvelle base,
1628
-	// sauf si on est dans l'installation
1629
-	if (
1630
-		!is_file($f = _DIR_DB . $db . '.sqlite')
1631
-		&& (!defined('_ECRIRE_INSTALL') || !_ECRIRE_INSTALL)
1632
-	) {
1633
-		spip_log("Il est interdit de creer la base $db", 'sqlite.' . _LOG_HS);
1627
+    // interdire la creation d'une nouvelle base,
1628
+    // sauf si on est dans l'installation
1629
+    if (
1630
+        !is_file($f = _DIR_DB . $db . '.sqlite')
1631
+        && (!defined('_ECRIRE_INSTALL') || !_ECRIRE_INSTALL)
1632
+    ) {
1633
+        spip_log("Il est interdit de creer la base $db", 'sqlite.' . _LOG_HS);
1634 1634
 
1635
-		return false;
1636
-	}
1635
+        return false;
1636
+    }
1637 1637
 
1638
-	// se connecter a la base indiquee
1639
-	// avec les identifiants connus
1640
-	$index = $serveur ? $serveur : 0;
1638
+    // se connecter a la base indiquee
1639
+    // avec les identifiants connus
1640
+    $index = $serveur ? $serveur : 0;
1641 1641
 
1642
-	if ($link = spip_connect_db('', '', '', '', '@selectdb@' . $db, $serveur, '', '')) {
1643
-		if (($db == $link['db']) && $GLOBALS['connexions'][$index] = $link) {
1644
-			return $db;
1645
-		}
1646
-	} else {
1647
-		spip_log("Impossible de selectionner la base $db", 'sqlite.' . _LOG_HS);
1642
+    if ($link = spip_connect_db('', '', '', '', '@selectdb@' . $db, $serveur, '', '')) {
1643
+        if (($db == $link['db']) && $GLOBALS['connexions'][$index] = $link) {
1644
+            return $db;
1645
+        }
1646
+    } else {
1647
+        spip_log("Impossible de selectionner la base $db", 'sqlite.' . _LOG_HS);
1648 1648
 
1649
-		return false;
1650
-	}
1649
+        return false;
1650
+    }
1651 1651
 }
1652 1652
 
1653 1653
 
@@ -1662,8 +1662,8 @@  discard block
 block discarded – undo
1662 1662
  * @return void
1663 1663
  */
1664 1664
 function spip_sqlite_set_charset($charset, $serveur = '', $requeter = true) {
1665
-	# spip_log("Gestion charset sql a ecrire : "."SET NAMES "._q($charset), 'sqlite.'._LOG_ERREUR);
1666
-	# return spip_sqlite_query("SET NAMES ". spip_sqlite_quote($charset), $serveur); //<-- Passe pas !
1665
+    # spip_log("Gestion charset sql a ecrire : "."SET NAMES "._q($charset), 'sqlite.'._LOG_ERREUR);
1666
+    # return spip_sqlite_query("SET NAMES ". spip_sqlite_quote($charset), $serveur); //<-- Passe pas !
1667 1667
 }
1668 1668
 
1669 1669
 
@@ -1681,24 +1681,24 @@  discard block
 block discarded – undo
1681 1681
  *     Ressource à utiliser avec sql_fetch()
1682 1682
  **/
1683 1683
 function spip_sqlite_showbase($match, $serveur = '', $requeter = true) {
1684
-	// type est le type d'entrée : table / index / view
1685
-	// on ne retourne que les tables (?) et non les vues...
1686
-	# ESCAPE non supporte par les versions sqlite <3
1687
-	#	return spip_sqlite_query("SELECT name FROM sqlite_master WHERE type='table' AND tbl_name LIKE "._q($match)." ESCAPE '\'", $serveur, $requeter);
1688
-	$match = preg_quote($match);
1689
-	$match = str_replace('\\\_', '[[TIRETBAS]]', $match);
1690
-	$match = str_replace('\\\%', '[[POURCENT]]', $match);
1691
-	$match = str_replace('_', '.', $match);
1692
-	$match = str_replace('%', '.*', $match);
1693
-	$match = str_replace('[[TIRETBAS]]', '_', $match);
1694
-	$match = str_replace('[[POURCENT]]', '%', $match);
1695
-	$match = "^$match$";
1696
-
1697
-	return spip_sqlite_query(
1698
-		"SELECT name FROM sqlite_master WHERE type='table' AND tbl_name REGEXP " . _q($match),
1699
-		$serveur,
1700
-		$requeter
1701
-	);
1684
+    // type est le type d'entrée : table / index / view
1685
+    // on ne retourne que les tables (?) et non les vues...
1686
+    # ESCAPE non supporte par les versions sqlite <3
1687
+    #	return spip_sqlite_query("SELECT name FROM sqlite_master WHERE type='table' AND tbl_name LIKE "._q($match)." ESCAPE '\'", $serveur, $requeter);
1688
+    $match = preg_quote($match);
1689
+    $match = str_replace('\\\_', '[[TIRETBAS]]', $match);
1690
+    $match = str_replace('\\\%', '[[POURCENT]]', $match);
1691
+    $match = str_replace('_', '.', $match);
1692
+    $match = str_replace('%', '.*', $match);
1693
+    $match = str_replace('[[TIRETBAS]]', '_', $match);
1694
+    $match = str_replace('[[POURCENT]]', '%', $match);
1695
+    $match = "^$match$";
1696
+
1697
+    return spip_sqlite_query(
1698
+        "SELECT name FROM sqlite_master WHERE type='table' AND tbl_name REGEXP " . _q($match),
1699
+        $serveur,
1700
+        $requeter
1701
+    );
1702 1702
 }
1703 1703
 
1704 1704
 /**
@@ -1716,19 +1716,19 @@  discard block
 block discarded – undo
1716 1716
  *     - string : requete sql, si $requeter = true
1717 1717
  **/
1718 1718
 function spip_sqlite_table_exists(string $table, $serveur = '', $requeter = true) {
1719
-	$r = spip_sqlite_query(
1720
-		'SELECT name FROM sqlite_master WHERE'
1721
-		. ' type=\'table\''
1722
-		. ' AND name=' . spip_sqlite_quote($table, 'string')
1723
-		. ' AND name NOT LIKE \'sqlite_%\'',
1724
-		$serveur,
1725
-		$requeter
1726
-	);
1727
-	if (!$requeter) {
1728
-		return $r;
1729
-	}
1730
-	$res = spip_sqlite_fetch($r);
1731
-	return (bool) $res;
1719
+    $r = spip_sqlite_query(
1720
+        'SELECT name FROM sqlite_master WHERE'
1721
+        . ' type=\'table\''
1722
+        . ' AND name=' . spip_sqlite_quote($table, 'string')
1723
+        . ' AND name NOT LIKE \'sqlite_%\'',
1724
+        $serveur,
1725
+        $requeter
1726
+    );
1727
+    if (!$requeter) {
1728
+        return $r;
1729
+    }
1730
+    $res = spip_sqlite_fetch($r);
1731
+    return (bool) $res;
1732 1732
 }
1733 1733
 
1734 1734
 define('_SQLITE_RE_SHOW_TABLE', '/^[^(),]*\(((?:[^()]*\((?:[^()]*\([^()]*\))?[^()]*\)[^()]*)*[^()]*)\)[^()]*$/');
@@ -1751,129 +1751,129 @@  discard block
 block discarded – undo
1751 1751
  *     - array description de la table sinon
1752 1752
  */
1753 1753
 function spip_sqlite_showtable($nom_table, $serveur = '', $requeter = true) {
1754
-	$query =
1755
-		'SELECT sql, type FROM'
1756
-		. ' (SELECT * FROM sqlite_master UNION ALL'
1757
-		. ' SELECT * FROM sqlite_temp_master)'
1758
-		. " WHERE tbl_name LIKE '$nom_table'"
1759
-		. " AND type!='meta' AND sql NOT NULL AND name NOT LIKE 'sqlite_%'"
1760
-		. ' ORDER BY substr(type,2,1), name';
1761
-
1762
-	$a = spip_sqlite_query($query, $serveur, $requeter);
1763
-	if (!$a) {
1764
-		return '';
1765
-	}
1766
-	if (!$requeter) {
1767
-		return $a;
1768
-	}
1769
-	if (!($a = spip_sqlite_fetch($a, null, $serveur))) {
1770
-		return '';
1771
-	}
1772
-	$vue = ($a['type'] == 'view'); // table | vue
1773
-
1774
-	// c'est une table
1775
-	// il faut parser le create
1776
-	if (!$vue) {
1777
-		if (!preg_match(_SQLITE_RE_SHOW_TABLE, array_shift($a), $r)) {
1778
-			return '';
1779
-		} else {
1780
-			$desc = $r[1];
1781
-			// extraction d'une KEY éventuelle en prenant garde de ne pas
1782
-			// relever un champ dont le nom contient KEY (ex. ID_WHISKEY)
1783
-			if (preg_match('/^(.*?),([^,]*\sKEY[ (].*)$/s', $desc, $r)) {
1784
-				$namedkeys = $r[2];
1785
-				$desc = $r[1];
1786
-			} else {
1787
-				$namedkeys = '';
1788
-			}
1789
-
1790
-			$fields = [];
1791
-			$keys = [];
1792
-
1793
-			// enlever les contenus des valeurs DEFAULT 'xxx' qui pourraient perturber
1794
-			// par exemple s'il contiennent une virgule.
1795
-			// /!\ cela peut aussi echapper le nom des champs si la table a eu des operations avec SQLite Manager !
1796
-			list($desc, $echaps) = query_echappe_textes($desc);
1797
-
1798
-			// separer toutes les descriptions de champs, separes par des virgules
1799
-			# /!\ explode peut exploser aussi DECIMAL(10,2) !
1800
-			$k_precedent = null;
1801
-			foreach (explode(',', $desc) as $v) {
1802
-				preg_match('/^\s*([^\s]+)\s+(.*)/', $v, $r);
1803
-				// Les cles de champs peuvent etre entourees
1804
-				// de guillements doubles " , simples ', graves ` ou de crochets [ ],  ou rien.
1805
-				// http://www.sqlite.org/lang_keywords.html
1806
-				$k = strtolower(query_reinjecte_textes($r[1], $echaps)); // champ, "champ", [champ]...
1807
-				if ($char = strpbrk($k[0], '\'"[`')) {
1808
-					$k = trim($k, $char);
1809
-					if ($char == '[') {
1810
-						$k = rtrim($k, ']');
1811
-					}
1812
-				}
1813
-				$def = query_reinjecte_textes($r[2], $echaps); // valeur du champ
1814
-
1815
-				// rustine pour DECIMAL(10,2)
1816
-				// s'il y a une parenthèse fermante dans la clé
1817
-				// ou dans la définition sans qu'il n'y ait une ouverture avant
1818
-				if (false !== strpos($k, ')') or preg_match('/^[^\(]*\)/', $def)) {
1819
-					$fields[$k_precedent] .= ',' . $k . ' ' . $def;
1820
-					continue;
1821
-				}
1822
-
1823
-				// la primary key peut etre dans une des descriptions de champs
1824
-				// et non en fin de table, cas encore decouvert avec Sqlite Manager
1825
-				if (stripos($r[2], 'PRIMARY KEY') !== false) {
1826
-					$keys['PRIMARY KEY'] = $k;
1827
-				}
1828
-
1829
-				$fields[$k] = $def;
1830
-				$k_precedent = $k;
1831
-			}
1832
-			// key inclues dans la requete
1833
-			foreach (preg_split('/\)\s*(,|$)/', $namedkeys) as $v) {
1834
-				if (preg_match('/^\s*([^(]*)\(([^(]*(\(\d+\))?)$/', $v, $r)) {
1835
-					$k = str_replace('`', '', trim($r[1]));
1836
-					$t = trim(strtolower(str_replace('`', '', $r[2])), '"');
1837
-					if ($k && !isset($keys[$k])) {
1838
-						$keys[$k] = $t;
1839
-					} else {
1840
-						$keys[] = $t;
1841
-					}
1842
-				}
1843
-			}
1844
-			// sinon ajouter les key index
1845
-			$query =
1846
-				'SELECT name,sql FROM'
1847
-				. ' (SELECT * FROM sqlite_master UNION ALL'
1848
-				. ' SELECT * FROM sqlite_temp_master)'
1849
-				. " WHERE tbl_name LIKE '$nom_table'"
1850
-				. " AND type='index' AND name NOT LIKE 'sqlite_%'"
1851
-				. 'ORDER BY substr(type,2,1), name';
1852
-			$a = spip_sqlite_query($query, $serveur, $requeter);
1853
-			while ($r = spip_sqlite_fetch($a, null, $serveur)) {
1854
-				$key = str_replace($nom_table . '_', '', $r['name']); // enlever le nom de la table ajoute a l'index
1855
-				$keytype = 'KEY';
1856
-				if (strpos($r['sql'], 'UNIQUE INDEX') !== false) {
1857
-					$keytype = 'UNIQUE KEY';
1858
-				}
1859
-				$colonnes = preg_replace(',.*\((.*)\).*,', '$1', $r['sql']);
1860
-				$keys[$keytype . ' ' . $key] = $colonnes;
1861
-			}
1862
-		}
1863
-	} // c'est une vue, on liste les champs disponibles simplement
1864
-	else {
1865
-		if ($res = sql_fetsel('*', $nom_table, '', '', '', '1', '', $serveur)) { // limit 1
1866
-			$fields = [];
1867
-			foreach ($res as $c => $v) {
1868
-				$fields[$c] = '';
1869
-			}
1870
-			$keys = [];
1871
-		} else {
1872
-			return '';
1873
-		}
1874
-	}
1875
-
1876
-	return ['field' => $fields, 'key' => $keys];
1754
+    $query =
1755
+        'SELECT sql, type FROM'
1756
+        . ' (SELECT * FROM sqlite_master UNION ALL'
1757
+        . ' SELECT * FROM sqlite_temp_master)'
1758
+        . " WHERE tbl_name LIKE '$nom_table'"
1759
+        . " AND type!='meta' AND sql NOT NULL AND name NOT LIKE 'sqlite_%'"
1760
+        . ' ORDER BY substr(type,2,1), name';
1761
+
1762
+    $a = spip_sqlite_query($query, $serveur, $requeter);
1763
+    if (!$a) {
1764
+        return '';
1765
+    }
1766
+    if (!$requeter) {
1767
+        return $a;
1768
+    }
1769
+    if (!($a = spip_sqlite_fetch($a, null, $serveur))) {
1770
+        return '';
1771
+    }
1772
+    $vue = ($a['type'] == 'view'); // table | vue
1773
+
1774
+    // c'est une table
1775
+    // il faut parser le create
1776
+    if (!$vue) {
1777
+        if (!preg_match(_SQLITE_RE_SHOW_TABLE, array_shift($a), $r)) {
1778
+            return '';
1779
+        } else {
1780
+            $desc = $r[1];
1781
+            // extraction d'une KEY éventuelle en prenant garde de ne pas
1782
+            // relever un champ dont le nom contient KEY (ex. ID_WHISKEY)
1783
+            if (preg_match('/^(.*?),([^,]*\sKEY[ (].*)$/s', $desc, $r)) {
1784
+                $namedkeys = $r[2];
1785
+                $desc = $r[1];
1786
+            } else {
1787
+                $namedkeys = '';
1788
+            }
1789
+
1790
+            $fields = [];
1791
+            $keys = [];
1792
+
1793
+            // enlever les contenus des valeurs DEFAULT 'xxx' qui pourraient perturber
1794
+            // par exemple s'il contiennent une virgule.
1795
+            // /!\ cela peut aussi echapper le nom des champs si la table a eu des operations avec SQLite Manager !
1796
+            list($desc, $echaps) = query_echappe_textes($desc);
1797
+
1798
+            // separer toutes les descriptions de champs, separes par des virgules
1799
+            # /!\ explode peut exploser aussi DECIMAL(10,2) !
1800
+            $k_precedent = null;
1801
+            foreach (explode(',', $desc) as $v) {
1802
+                preg_match('/^\s*([^\s]+)\s+(.*)/', $v, $r);
1803
+                // Les cles de champs peuvent etre entourees
1804
+                // de guillements doubles " , simples ', graves ` ou de crochets [ ],  ou rien.
1805
+                // http://www.sqlite.org/lang_keywords.html
1806
+                $k = strtolower(query_reinjecte_textes($r[1], $echaps)); // champ, "champ", [champ]...
1807
+                if ($char = strpbrk($k[0], '\'"[`')) {
1808
+                    $k = trim($k, $char);
1809
+                    if ($char == '[') {
1810
+                        $k = rtrim($k, ']');
1811
+                    }
1812
+                }
1813
+                $def = query_reinjecte_textes($r[2], $echaps); // valeur du champ
1814
+
1815
+                // rustine pour DECIMAL(10,2)
1816
+                // s'il y a une parenthèse fermante dans la clé
1817
+                // ou dans la définition sans qu'il n'y ait une ouverture avant
1818
+                if (false !== strpos($k, ')') or preg_match('/^[^\(]*\)/', $def)) {
1819
+                    $fields[$k_precedent] .= ',' . $k . ' ' . $def;
1820
+                    continue;
1821
+                }
1822
+
1823
+                // la primary key peut etre dans une des descriptions de champs
1824
+                // et non en fin de table, cas encore decouvert avec Sqlite Manager
1825
+                if (stripos($r[2], 'PRIMARY KEY') !== false) {
1826
+                    $keys['PRIMARY KEY'] = $k;
1827
+                }
1828
+
1829
+                $fields[$k] = $def;
1830
+                $k_precedent = $k;
1831
+            }
1832
+            // key inclues dans la requete
1833
+            foreach (preg_split('/\)\s*(,|$)/', $namedkeys) as $v) {
1834
+                if (preg_match('/^\s*([^(]*)\(([^(]*(\(\d+\))?)$/', $v, $r)) {
1835
+                    $k = str_replace('`', '', trim($r[1]));
1836
+                    $t = trim(strtolower(str_replace('`', '', $r[2])), '"');
1837
+                    if ($k && !isset($keys[$k])) {
1838
+                        $keys[$k] = $t;
1839
+                    } else {
1840
+                        $keys[] = $t;
1841
+                    }
1842
+                }
1843
+            }
1844
+            // sinon ajouter les key index
1845
+            $query =
1846
+                'SELECT name,sql FROM'
1847
+                . ' (SELECT * FROM sqlite_master UNION ALL'
1848
+                . ' SELECT * FROM sqlite_temp_master)'
1849
+                . " WHERE tbl_name LIKE '$nom_table'"
1850
+                . " AND type='index' AND name NOT LIKE 'sqlite_%'"
1851
+                . 'ORDER BY substr(type,2,1), name';
1852
+            $a = spip_sqlite_query($query, $serveur, $requeter);
1853
+            while ($r = spip_sqlite_fetch($a, null, $serveur)) {
1854
+                $key = str_replace($nom_table . '_', '', $r['name']); // enlever le nom de la table ajoute a l'index
1855
+                $keytype = 'KEY';
1856
+                if (strpos($r['sql'], 'UNIQUE INDEX') !== false) {
1857
+                    $keytype = 'UNIQUE KEY';
1858
+                }
1859
+                $colonnes = preg_replace(',.*\((.*)\).*,', '$1', $r['sql']);
1860
+                $keys[$keytype . ' ' . $key] = $colonnes;
1861
+            }
1862
+        }
1863
+    } // c'est une vue, on liste les champs disponibles simplement
1864
+    else {
1865
+        if ($res = sql_fetsel('*', $nom_table, '', '', '', '1', '', $serveur)) { // limit 1
1866
+            $fields = [];
1867
+            foreach ($res as $c => $v) {
1868
+                $fields[$c] = '';
1869
+            }
1870
+            $keys = [];
1871
+        } else {
1872
+            return '';
1873
+        }
1874
+    }
1875
+
1876
+    return ['field' => $fields, 'key' => $keys];
1877 1877
 }
1878 1878
 
1879 1879
 
@@ -1899,22 +1899,22 @@  discard block
 block discarded – undo
1899 1899
  *     - array Tableau décrivant la requête et son temps d'exécution si var_profile est actif
1900 1900
  */
1901 1901
 function spip_sqlite_update($table, $champs, $where = '', $desc = '', $serveur = '', $requeter = true) {
1902
-	// recherche de champs 'timestamp' pour mise a jour auto de ceux-ci
1903
-	$champs = _sqlite_ajouter_champs_timestamp($table, $champs, $desc, $serveur);
1902
+    // recherche de champs 'timestamp' pour mise a jour auto de ceux-ci
1903
+    $champs = _sqlite_ajouter_champs_timestamp($table, $champs, $desc, $serveur);
1904 1904
 
1905
-	$set = [];
1906
-	foreach ($champs as $champ => $val) {
1907
-		$set[] = $champ . "=$val";
1908
-	}
1909
-	if (!empty($set)) {
1910
-		return spip_sqlite_query(
1911
-			_sqlite_calculer_expression('UPDATE', $table, ',')
1912
-			. _sqlite_calculer_expression('SET', $set, ',')
1913
-			. _sqlite_calculer_expression('WHERE', $where),
1914
-			$serveur,
1915
-			$requeter
1916
-		);
1917
-	}
1905
+    $set = [];
1906
+    foreach ($champs as $champ => $val) {
1907
+        $set[] = $champ . "=$val";
1908
+    }
1909
+    if (!empty($set)) {
1910
+        return spip_sqlite_query(
1911
+            _sqlite_calculer_expression('UPDATE', $table, ',')
1912
+            . _sqlite_calculer_expression('SET', $set, ',')
1913
+            . _sqlite_calculer_expression('WHERE', $where),
1914
+            $serveur,
1915
+            $requeter
1916
+        );
1917
+    }
1918 1918
 }
1919 1919
 
1920 1920
 
@@ -1944,38 +1944,38 @@  discard block
 block discarded – undo
1944 1944
  */
1945 1945
 function spip_sqlite_updateq($table, $champs, $where = '', $desc = [], $serveur = '', $requeter = true) {
1946 1946
 
1947
-	if (!$champs) {
1948
-		return;
1949
-	}
1950
-	if (!$desc) {
1951
-		$desc = description_table($table, $serveur);
1952
-	}
1953
-	if (!$desc) {
1954
-		die("$table insertion sans description");
1955
-	}
1956
-	$fields = $desc['field'];
1957
-
1958
-	$set = [];
1959
-	foreach ($champs as $champ => $val) {
1960
-		$set[$champ] = $champ . '=' . _sqlite_calculer_cite($val, isset($fields[$champ]) ? $fields[$champ] : '');
1961
-	}
1962
-
1963
-	// recherche de champs 'timestamp' pour mise a jour auto de ceux-ci
1964
-	// attention ils sont deja quotes
1965
-	$maj = _sqlite_ajouter_champs_timestamp($table, [], $desc, $serveur);
1966
-	foreach ($maj as $champ => $val) {
1967
-		if (!isset($set[$champ])) {
1968
-			$set[$champ] = $champ . '=' . $val;
1969
-		}
1970
-	}
1971
-
1972
-	return spip_sqlite_query(
1973
-		_sqlite_calculer_expression('UPDATE', $table, ',')
1974
-		. _sqlite_calculer_expression('SET', $set, ',')
1975
-		. _sqlite_calculer_expression('WHERE', $where),
1976
-		$serveur,
1977
-		$requeter
1978
-	);
1947
+    if (!$champs) {
1948
+        return;
1949
+    }
1950
+    if (!$desc) {
1951
+        $desc = description_table($table, $serveur);
1952
+    }
1953
+    if (!$desc) {
1954
+        die("$table insertion sans description");
1955
+    }
1956
+    $fields = $desc['field'];
1957
+
1958
+    $set = [];
1959
+    foreach ($champs as $champ => $val) {
1960
+        $set[$champ] = $champ . '=' . _sqlite_calculer_cite($val, isset($fields[$champ]) ? $fields[$champ] : '');
1961
+    }
1962
+
1963
+    // recherche de champs 'timestamp' pour mise a jour auto de ceux-ci
1964
+    // attention ils sont deja quotes
1965
+    $maj = _sqlite_ajouter_champs_timestamp($table, [], $desc, $serveur);
1966
+    foreach ($maj as $champ => $val) {
1967
+        if (!isset($set[$champ])) {
1968
+            $set[$champ] = $champ . '=' . $val;
1969
+        }
1970
+    }
1971
+
1972
+    return spip_sqlite_query(
1973
+        _sqlite_calculer_expression('UPDATE', $table, ',')
1974
+        . _sqlite_calculer_expression('SET', $set, ',')
1975
+        . _sqlite_calculer_expression('WHERE', $where),
1976
+        $serveur,
1977
+        $requeter
1978
+    );
1979 1979
 }
1980 1980
 
1981 1981
 
@@ -1993,17 +1993,17 @@  discard block
 block discarded – undo
1993 1993
  * @return void
1994 1994
  */
1995 1995
 function _sqlite_init() {
1996
-	if (!defined('_DIR_DB')) {
1997
-		define('_DIR_DB', _DIR_ETC . 'bases/');
1998
-	}
1999
-	if (!defined('_SQLITE_CHMOD')) {
2000
-		define('_SQLITE_CHMOD', _SPIP_CHMOD);
2001
-	}
1996
+    if (!defined('_DIR_DB')) {
1997
+        define('_DIR_DB', _DIR_ETC . 'bases/');
1998
+    }
1999
+    if (!defined('_SQLITE_CHMOD')) {
2000
+        define('_SQLITE_CHMOD', _SPIP_CHMOD);
2001
+    }
2002 2002
 
2003
-	if (!is_dir($d = _DIR_DB)) {
2004
-		include_spip('inc/flock');
2005
-		sous_repertoire($d);
2006
-	}
2003
+    if (!is_dir($d = _DIR_DB)) {
2004
+        include_spip('inc/flock');
2005
+        sous_repertoire($d);
2006
+    }
2007 2007
 }
2008 2008
 
2009 2009
 
@@ -2017,20 +2017,20 @@  discard block
 block discarded – undo
2017 2017
  * @return bool|int
2018 2018
  */
2019 2019
 function _sqlite_is_version($version = '', $link = '', $serveur = '', $requeter = true) {
2020
-	if ($link === '') {
2021
-		$link = _sqlite_link($serveur);
2022
-	}
2023
-	if (!$link) {
2024
-		return false;
2025
-	}
2020
+    if ($link === '') {
2021
+        $link = _sqlite_link($serveur);
2022
+    }
2023
+    if (!$link) {
2024
+        return false;
2025
+    }
2026 2026
 
2027
-	$v = 3;
2027
+    $v = 3;
2028 2028
 
2029
-	if (!$version) {
2030
-		return $v;
2031
-	}
2029
+    if (!$version) {
2030
+        return $v;
2031
+    }
2032 2032
 
2033
-	return ($version == $v);
2033
+    return ($version == $v);
2034 2034
 }
2035 2035
 
2036 2036
 
@@ -2041,9 +2041,9 @@  discard block
 block discarded – undo
2041 2041
  * @return PDO Information de connexion pour SQLite
2042 2042
  */
2043 2043
 function _sqlite_link($serveur = '') {
2044
-	$link = &$GLOBALS['connexions'][$serveur ? $serveur : 0]['link'];
2044
+    $link = &$GLOBALS['connexions'][$serveur ? $serveur : 0]['link'];
2045 2045
 
2046
-	return $link;
2046
+    return $link;
2047 2047
 }
2048 2048
 
2049 2049
 
@@ -2058,55 +2058,55 @@  discard block
 block discarded – undo
2058 2058
  * @return string|number     Texte ou nombre échappé
2059 2059
  */
2060 2060
 function _sqlite_calculer_cite($v, $type) {
2061
-	if ($type) {
2062
-		if (
2063
-			is_null($v)
2064
-			and stripos($type, 'NOT NULL') === false
2065
-		) {
2066
-			// null php se traduit en NULL SQL
2067
-			return 'NULL';
2068
-		}
2069
-
2070
-		if (sql_test_date($type) and preg_match('/^\w+\(/', $v)) {
2071
-			return $v;
2072
-		}
2073
-		if (sql_test_int($type)) {
2074
-			if (is_numeric($v)) {
2075
-				return $v;
2076
-			} elseif ($v === null) {
2077
-				return 0;
2078
-			} elseif (ctype_xdigit(substr($v, 2)) and strncmp($v, '0x', 2) === 0) {
2079
-				return hexdec(substr($v, 2));
2080
-			} else {
2081
-				return intval($v);
2082
-			}
2083
-		}
2084
-	} else {
2085
-		// si on ne connait pas le type on le deduit de $v autant que possible
2086
-		if (is_bool($v)) {
2087
-			return strval(intval($v));
2088
-		}
2089
-		elseif (is_numeric($v)) {
2090
-			return strval($v);
2091
-		}
2092
-	}
2093
-
2094
-	// trouver un link sqlite pour faire l'echappement
2095
-	foreach ($GLOBALS['connexions'] as $s) {
2096
-		if (
2097
-			$l = $s['link']
2098
-			and is_object($l)
2099
-			and $l instanceof \PDO
2100
-			and $l->getAttribute(\PDO::ATTR_DRIVER_NAME) === 'sqlite'
2101
-		) {
2102
-			return $l->quote($v);
2103
-		}
2104
-	}
2105
-
2106
-	// echapper les ' en ''
2107
-	spip_log('Pas de methode ->quote pour echapper', 'sqlite.' . _LOG_INFO_IMPORTANTE);
2108
-
2109
-	return ("'" . str_replace("'", "''", $v) . "'");
2061
+    if ($type) {
2062
+        if (
2063
+            is_null($v)
2064
+            and stripos($type, 'NOT NULL') === false
2065
+        ) {
2066
+            // null php se traduit en NULL SQL
2067
+            return 'NULL';
2068
+        }
2069
+
2070
+        if (sql_test_date($type) and preg_match('/^\w+\(/', $v)) {
2071
+            return $v;
2072
+        }
2073
+        if (sql_test_int($type)) {
2074
+            if (is_numeric($v)) {
2075
+                return $v;
2076
+            } elseif ($v === null) {
2077
+                return 0;
2078
+            } elseif (ctype_xdigit(substr($v, 2)) and strncmp($v, '0x', 2) === 0) {
2079
+                return hexdec(substr($v, 2));
2080
+            } else {
2081
+                return intval($v);
2082
+            }
2083
+        }
2084
+    } else {
2085
+        // si on ne connait pas le type on le deduit de $v autant que possible
2086
+        if (is_bool($v)) {
2087
+            return strval(intval($v));
2088
+        }
2089
+        elseif (is_numeric($v)) {
2090
+            return strval($v);
2091
+        }
2092
+    }
2093
+
2094
+    // trouver un link sqlite pour faire l'echappement
2095
+    foreach ($GLOBALS['connexions'] as $s) {
2096
+        if (
2097
+            $l = $s['link']
2098
+            and is_object($l)
2099
+            and $l instanceof \PDO
2100
+            and $l->getAttribute(\PDO::ATTR_DRIVER_NAME) === 'sqlite'
2101
+        ) {
2102
+            return $l->quote($v);
2103
+        }
2104
+    }
2105
+
2106
+    // echapper les ' en ''
2107
+    spip_log('Pas de methode ->quote pour echapper', 'sqlite.' . _LOG_INFO_IMPORTANTE);
2108
+
2109
+    return ("'" . str_replace("'", "''", $v) . "'");
2110 2110
 }
2111 2111
 
2112 2112
 
@@ -2122,21 +2122,21 @@  discard block
 block discarded – undo
2122 2122
  * @return string            Texte de l'expression, une partie donc, du texte la requête.
2123 2123
  */
2124 2124
 function _sqlite_calculer_expression($expression, $v, $join = 'AND') {
2125
-	if (empty($v)) {
2126
-		return '';
2127
-	}
2125
+    if (empty($v)) {
2126
+        return '';
2127
+    }
2128 2128
 
2129
-	$exp = "\n$expression ";
2129
+    $exp = "\n$expression ";
2130 2130
 
2131
-	if (!is_array($v)) {
2132
-		return $exp . $v;
2133
-	} else {
2134
-		if (strtoupper($join) === 'AND') {
2135
-			return $exp . join("\n\t$join ", array_map('_sqlite_calculer_where', $v));
2136
-		} else {
2137
-			return $exp . join($join, $v);
2138
-		}
2139
-	}
2131
+    if (!is_array($v)) {
2132
+        return $exp . $v;
2133
+    } else {
2134
+        if (strtoupper($join) === 'AND') {
2135
+            return $exp . join("\n\t$join ", array_map('_sqlite_calculer_where', $v));
2136
+        } else {
2137
+            return $exp . join($join, $v);
2138
+        }
2139
+    }
2140 2140
 }
2141 2141
 
2142 2142
 
@@ -2152,7 +2152,7 @@  discard block
 block discarded – undo
2152 2152
  * @return string Texte du orderby préparé
2153 2153
  */
2154 2154
 function _sqlite_calculer_order($orderby) {
2155
-	return (is_array($orderby)) ? join(', ', $orderby) : $orderby;
2155
+    return (is_array($orderby)) ? join(', ', $orderby) : $orderby;
2156 2156
 }
2157 2157
 
2158 2158
 
@@ -2163,26 +2163,26 @@  discard block
 block discarded – undo
2163 2163
  * @return string Sélection de colonnes pour une clause SELECT
2164 2164
  */
2165 2165
 function _sqlite_calculer_select_as($args) {
2166
-	$res = '';
2167
-	foreach ($args as $k => $v) {
2168
-		if (substr($k, -1) == '@') {
2169
-			// c'est une jointure qui se refere au from precedent
2170
-			// pas de virgule
2171
-			$res .= '  ' . $v;
2172
-		} else {
2173
-			if (!is_numeric($k)) {
2174
-				$p = strpos($v, ' ');
2175
-				if ($p) {
2176
-					$v = substr($v, 0, $p) . " AS '$k'" . substr($v, $p);
2177
-				} else {
2178
-					$v .= " AS '$k'";
2179
-				}
2180
-			}
2181
-			$res .= ', ' . $v;
2182
-		}
2183
-	}
2184
-
2185
-	return substr($res, 2);
2166
+    $res = '';
2167
+    foreach ($args as $k => $v) {
2168
+        if (substr($k, -1) == '@') {
2169
+            // c'est une jointure qui se refere au from precedent
2170
+            // pas de virgule
2171
+            $res .= '  ' . $v;
2172
+        } else {
2173
+            if (!is_numeric($k)) {
2174
+                $p = strpos($v, ' ');
2175
+                if ($p) {
2176
+                    $v = substr($v, 0, $p) . " AS '$k'" . substr($v, $p);
2177
+                } else {
2178
+                    $v .= " AS '$k'";
2179
+                }
2180
+            }
2181
+            $res .= ', ' . $v;
2182
+        }
2183
+    }
2184
+
2185
+    return substr($res, 2);
2186 2186
 }
2187 2187
 
2188 2188
 
@@ -2205,26 +2205,26 @@  discard block
 block discarded – undo
2205 2205
  *     Contrainte pour clause WHERE
2206 2206
  */
2207 2207
 function _sqlite_calculer_where($v) {
2208
-	if (!is_array($v)) {
2209
-		return $v;
2210
-	}
2211
-
2212
-	$op = array_shift($v);
2213
-	if (!($n = count($v))) {
2214
-		return $op;
2215
-	} else {
2216
-		$arg = _sqlite_calculer_where(array_shift($v));
2217
-		if ($n == 1) {
2218
-			return "$op($arg)";
2219
-		} else {
2220
-			$arg2 = _sqlite_calculer_where(array_shift($v));
2221
-			if ($n == 2) {
2222
-				return "($arg $op $arg2)";
2223
-			} else {
2224
-				return "($arg $op ($arg2) : $v[0])";
2225
-			}
2226
-		}
2227
-	}
2208
+    if (!is_array($v)) {
2209
+        return $v;
2210
+    }
2211
+
2212
+    $op = array_shift($v);
2213
+    if (!($n = count($v))) {
2214
+        return $op;
2215
+    } else {
2216
+        $arg = _sqlite_calculer_where(array_shift($v));
2217
+        if ($n == 1) {
2218
+            return "$op($arg)";
2219
+        } else {
2220
+            $arg2 = _sqlite_calculer_where(array_shift($v));
2221
+            if ($n == 2) {
2222
+                return "($arg $op $arg2)";
2223
+            } else {
2224
+                return "($arg $op ($arg2) : $v[0])";
2225
+            }
2226
+        }
2227
+    }
2228 2228
 }
2229 2229
 
2230 2230
 
@@ -2239,19 +2239,19 @@  discard block
 block discarded – undo
2239 2239
  * @return array|bool
2240 2240
  */
2241 2241
 function _sqlite_charger_version($version = '') {
2242
-	$versions = [];
2242
+    $versions = [];
2243 2243
 
2244
-	// version 3
2245
-	if (!$version || $version == 3) {
2246
-		if (extension_loaded('pdo') && extension_loaded('pdo_sqlite')) {
2247
-			$versions[] = 3;
2248
-		}
2249
-	}
2250
-	if ($version) {
2251
-		return in_array($version, $versions);
2252
-	}
2244
+    // version 3
2245
+    if (!$version || $version == 3) {
2246
+        if (extension_loaded('pdo') && extension_loaded('pdo_sqlite')) {
2247
+            $versions[] = 3;
2248
+        }
2249
+    }
2250
+    if ($version) {
2251
+        return in_array($version, $versions);
2252
+    }
2253 2253
 
2254
-	return $versions;
2254
+    return $versions;
2255 2255
 }
2256 2256
 
2257 2257
 
@@ -2289,147 +2289,147 @@  discard block
 block discarded – undo
2289 2289
  */
2290 2290
 function _sqlite_modifier_table($table, $colonne, $opt = [], $serveur = '') {
2291 2291
 
2292
-	if (is_array($table)) {
2293
-		$table_destination = reset($table);
2294
-		$table_origine = key($table);
2295
-	} else {
2296
-		$table_origine = $table_destination = $table;
2297
-	}
2298
-	// ne prend actuellement qu'un changement
2299
-	// mais pourra etre adapte pour changer plus qu'une colonne a la fois
2300
-	if (is_array($colonne)) {
2301
-		$colonne_destination = reset($colonne);
2302
-		$colonne_origine = key($colonne);
2303
-	} else {
2304
-		$colonne_origine = $colonne_destination = $colonne;
2305
-	}
2306
-	if (!isset($opt['field'])) {
2307
-		$opt['field'] = [];
2308
-	}
2309
-	if (!isset($opt['key'])) {
2310
-		$opt['key'] = [];
2311
-	}
2312
-
2313
-	// si les noms de tables sont differents, pas besoin de table temporaire
2314
-	// on prendra directement le nom de la future table
2315
-	$meme_table = ($table_origine == $table_destination);
2316
-
2317
-	$def_origine = sql_showtable($table_origine, false, $serveur);
2318
-	if (!$def_origine or !isset($def_origine['field'])) {
2319
-		spip_log("Alter table impossible sur $table_origine : table non trouvee", 'sqlite' . _LOG_ERREUR);
2320
-
2321
-		return false;
2322
-	}
2323
-
2324
-
2325
-	$table_tmp = $table_origine . '_tmp';
2326
-
2327
-	// 1) creer une table temporaire avec les modifications
2328
-	// - DROP : suppression de la colonne
2329
-	// - CHANGE : modification de la colonne
2330
-	// (foreach pour conserver l'ordre des champs)
2331
-
2332
-	// field
2333
-	$fields = [];
2334
-	// pour le INSERT INTO plus loin
2335
-	// stocker la correspondance nouvelles->anciennes colonnes
2336
-	$fields_correspondances = [];
2337
-	foreach ($def_origine['field'] as $c => $d) {
2338
-		if ($colonne_origine && ($c == $colonne_origine)) {
2339
-			// si pas DROP
2340
-			if ($colonne_destination) {
2341
-				$fields[$colonne_destination] = $opt['field'][$colonne_destination];
2342
-				$fields_correspondances[$colonne_destination] = $c;
2343
-			}
2344
-		} else {
2345
-			$fields[$c] = $d;
2346
-			$fields_correspondances[$c] = $c;
2347
-		}
2348
-	}
2349
-	// cas de ADD sqlite2 (ajout du champ en fin de table):
2350
-	if (!$colonne_origine && $colonne_destination) {
2351
-		$fields[$colonne_destination] = $opt['field'][$colonne_destination];
2352
-	}
2353
-
2354
-	// key...
2355
-	$keys = [];
2356
-	foreach ($def_origine['key'] as $c => $d) {
2357
-		$c = str_replace($colonne_origine, $colonne_destination, $c);
2358
-		$d = str_replace($colonne_origine, $colonne_destination, $d);
2359
-		// seulement si on ne supprime pas la colonne !
2360
-		if ($d) {
2361
-			$keys[$c] = $d;
2362
-		}
2363
-	}
2364
-
2365
-	// autres keys, on merge
2366
-	$keys = array_merge($keys, $opt['key']);
2367
-	$queries = [];
2368
-
2369
-	// copier dans destination (si differente de origine), sinon tmp
2370
-	$table_copie = ($meme_table) ? $table_tmp : $table_destination;
2371
-	$autoinc = (isset($keys['PRIMARY KEY'])
2372
-		and $keys['PRIMARY KEY']
2373
-		and stripos($keys['PRIMARY KEY'], ',') === false
2374
-		and stripos($fields[$keys['PRIMARY KEY']], 'default') === false);
2375
-
2376
-	if (
2377
-		$q = _sqlite_requete_create(
2378
-			$table_copie,
2379
-			$fields,
2380
-			$keys,
2381
-			$autoinc,
2382
-			$temporary = false,
2383
-			$ifnotexists = true,
2384
-			$serveur
2385
-		)
2386
-	) {
2387
-		$queries[] = $q;
2388
-	}
2389
-
2390
-
2391
-	// 2) y copier les champs qui vont bien
2392
-	$champs_dest = join(', ', array_keys($fields_correspondances));
2393
-	$champs_ori = join(', ', $fields_correspondances);
2394
-	$queries[] = "INSERT INTO $table_copie ($champs_dest) SELECT $champs_ori FROM $table_origine";
2395
-
2396
-	// 3) supprimer la table d'origine
2397
-	$queries[] = "DROP TABLE $table_origine";
2398
-
2399
-	// 4) renommer la table temporaire
2400
-	// avec le nom de la table destination
2401
-	// si necessaire
2402
-	if ($meme_table) {
2403
-		$queries[] = "ALTER TABLE $table_copie RENAME TO $table_destination";
2404
-	}
2405
-
2406
-	// 5) remettre les index !
2407
-	foreach ($keys as $k => $v) {
2408
-		if ($k == 'PRIMARY KEY') {
2409
-		} else {
2410
-			// enlever KEY
2411
-			$k = substr($k, 4);
2412
-			$queries[] = "CREATE INDEX $table_destination" . "_$k ON $table_destination ($v)";
2413
-		}
2414
-	}
2415
-
2416
-
2417
-	if (count($queries)) {
2418
-		spip_sqlite::demarrer_transaction($serveur);
2419
-		// il faut les faire une par une car $query = join('; ', $queries).";"; ne fonctionne pas
2420
-		foreach ($queries as $q) {
2421
-			if (!spip_sqlite::executer_requete($q, $serveur)) {
2422
-				spip_log('SQLite : ALTER TABLE table :'
2423
-					. " Erreur a l'execution de la requete : $q", 'sqlite.' . _LOG_ERREUR);
2424
-				spip_sqlite::annuler_transaction($serveur);
2425
-
2426
-				return false;
2427
-			}
2428
-		}
2429
-		spip_sqlite::finir_transaction($serveur);
2430
-	}
2431
-
2432
-	return true;
2292
+    if (is_array($table)) {
2293
+        $table_destination = reset($table);
2294
+        $table_origine = key($table);
2295
+    } else {
2296
+        $table_origine = $table_destination = $table;
2297
+    }
2298
+    // ne prend actuellement qu'un changement
2299
+    // mais pourra etre adapte pour changer plus qu'une colonne a la fois
2300
+    if (is_array($colonne)) {
2301
+        $colonne_destination = reset($colonne);
2302
+        $colonne_origine = key($colonne);
2303
+    } else {
2304
+        $colonne_origine = $colonne_destination = $colonne;
2305
+    }
2306
+    if (!isset($opt['field'])) {
2307
+        $opt['field'] = [];
2308
+    }
2309
+    if (!isset($opt['key'])) {
2310
+        $opt['key'] = [];
2311
+    }
2312
+
2313
+    // si les noms de tables sont differents, pas besoin de table temporaire
2314
+    // on prendra directement le nom de la future table
2315
+    $meme_table = ($table_origine == $table_destination);
2316
+
2317
+    $def_origine = sql_showtable($table_origine, false, $serveur);
2318
+    if (!$def_origine or !isset($def_origine['field'])) {
2319
+        spip_log("Alter table impossible sur $table_origine : table non trouvee", 'sqlite' . _LOG_ERREUR);
2320
+
2321
+        return false;
2322
+    }
2323
+
2324
+
2325
+    $table_tmp = $table_origine . '_tmp';
2326
+
2327
+    // 1) creer une table temporaire avec les modifications
2328
+    // - DROP : suppression de la colonne
2329
+    // - CHANGE : modification de la colonne
2330
+    // (foreach pour conserver l'ordre des champs)
2331
+
2332
+    // field
2333
+    $fields = [];
2334
+    // pour le INSERT INTO plus loin
2335
+    // stocker la correspondance nouvelles->anciennes colonnes
2336
+    $fields_correspondances = [];
2337
+    foreach ($def_origine['field'] as $c => $d) {
2338
+        if ($colonne_origine && ($c == $colonne_origine)) {
2339
+            // si pas DROP
2340
+            if ($colonne_destination) {
2341
+                $fields[$colonne_destination] = $opt['field'][$colonne_destination];
2342
+                $fields_correspondances[$colonne_destination] = $c;
2343
+            }
2344
+        } else {
2345
+            $fields[$c] = $d;
2346
+            $fields_correspondances[$c] = $c;
2347
+        }
2348
+    }
2349
+    // cas de ADD sqlite2 (ajout du champ en fin de table):
2350
+    if (!$colonne_origine && $colonne_destination) {
2351
+        $fields[$colonne_destination] = $opt['field'][$colonne_destination];
2352
+    }
2353
+
2354
+    // key...
2355
+    $keys = [];
2356
+    foreach ($def_origine['key'] as $c => $d) {
2357
+        $c = str_replace($colonne_origine, $colonne_destination, $c);
2358
+        $d = str_replace($colonne_origine, $colonne_destination, $d);
2359
+        // seulement si on ne supprime pas la colonne !
2360
+        if ($d) {
2361
+            $keys[$c] = $d;
2362
+        }
2363
+    }
2364
+
2365
+    // autres keys, on merge
2366
+    $keys = array_merge($keys, $opt['key']);
2367
+    $queries = [];
2368
+
2369
+    // copier dans destination (si differente de origine), sinon tmp
2370
+    $table_copie = ($meme_table) ? $table_tmp : $table_destination;
2371
+    $autoinc = (isset($keys['PRIMARY KEY'])
2372
+        and $keys['PRIMARY KEY']
2373
+        and stripos($keys['PRIMARY KEY'], ',') === false
2374
+        and stripos($fields[$keys['PRIMARY KEY']], 'default') === false);
2375
+
2376
+    if (
2377
+        $q = _sqlite_requete_create(
2378
+            $table_copie,
2379
+            $fields,
2380
+            $keys,
2381
+            $autoinc,
2382
+            $temporary = false,
2383
+            $ifnotexists = true,
2384
+            $serveur
2385
+        )
2386
+    ) {
2387
+        $queries[] = $q;
2388
+    }
2389
+
2390
+
2391
+    // 2) y copier les champs qui vont bien
2392
+    $champs_dest = join(', ', array_keys($fields_correspondances));
2393
+    $champs_ori = join(', ', $fields_correspondances);
2394
+    $queries[] = "INSERT INTO $table_copie ($champs_dest) SELECT $champs_ori FROM $table_origine";
2395
+
2396
+    // 3) supprimer la table d'origine
2397
+    $queries[] = "DROP TABLE $table_origine";
2398
+
2399
+    // 4) renommer la table temporaire
2400
+    // avec le nom de la table destination
2401
+    // si necessaire
2402
+    if ($meme_table) {
2403
+        $queries[] = "ALTER TABLE $table_copie RENAME TO $table_destination";
2404
+    }
2405
+
2406
+    // 5) remettre les index !
2407
+    foreach ($keys as $k => $v) {
2408
+        if ($k == 'PRIMARY KEY') {
2409
+        } else {
2410
+            // enlever KEY
2411
+            $k = substr($k, 4);
2412
+            $queries[] = "CREATE INDEX $table_destination" . "_$k ON $table_destination ($v)";
2413
+        }
2414
+    }
2415
+
2416
+
2417
+    if (count($queries)) {
2418
+        spip_sqlite::demarrer_transaction($serveur);
2419
+        // il faut les faire une par une car $query = join('; ', $queries).";"; ne fonctionne pas
2420
+        foreach ($queries as $q) {
2421
+            if (!spip_sqlite::executer_requete($q, $serveur)) {
2422
+                spip_log('SQLite : ALTER TABLE table :'
2423
+                    . " Erreur a l'execution de la requete : $q", 'sqlite.' . _LOG_ERREUR);
2424
+                spip_sqlite::annuler_transaction($serveur);
2425
+
2426
+                return false;
2427
+            }
2428
+        }
2429
+        spip_sqlite::finir_transaction($serveur);
2430
+    }
2431
+
2432
+    return true;
2433 2433
 }
2434 2434
 
2435 2435
 
@@ -2439,61 +2439,61 @@  discard block
 block discarded – undo
2439 2439
  * @return array
2440 2440
  */
2441 2441
 function _sqlite_ref_fonctions() {
2442
-	$fonctions = [
2443
-		'alter' => 'spip_sqlite_alter',
2444
-		'count' => 'spip_sqlite_count',
2445
-		'countsel' => 'spip_sqlite_countsel',
2446
-		'create' => 'spip_sqlite_create',
2447
-		'create_base' => 'spip_sqlite_create_base',
2448
-		'create_view' => 'spip_sqlite_create_view',
2449
-		'date_proche' => 'spip_sqlite_date_proche',
2450
-		'delete' => 'spip_sqlite_delete',
2451
-		'drop_table' => 'spip_sqlite_drop_table',
2452
-		'drop_view' => 'spip_sqlite_drop_view',
2453
-		'errno' => 'spip_sqlite_errno',
2454
-		'error' => 'spip_sqlite_error',
2455
-		'explain' => 'spip_sqlite_explain',
2456
-		'fetch' => 'spip_sqlite_fetch',
2457
-		'seek' => 'spip_sqlite_seek',
2458
-		'free' => 'spip_sqlite_free',
2459
-		'hex' => 'spip_sqlite_hex',
2460
-		'in' => 'spip_sqlite_in',
2461
-		'insert' => 'spip_sqlite_insert',
2462
-		'insertq' => 'spip_sqlite_insertq',
2463
-		'insertq_multi' => 'spip_sqlite_insertq_multi',
2464
-		'listdbs' => 'spip_sqlite_listdbs',
2465
-		'multi' => 'spip_sqlite_multi',
2466
-		'optimize' => 'spip_sqlite_optimize',
2467
-		'query' => 'spip_sqlite_query',
2468
-		'quote' => 'spip_sqlite_quote',
2469
-		'repair' => 'spip_sqlite_repair',
2470
-		'replace' => 'spip_sqlite_replace',
2471
-		'replace_multi' => 'spip_sqlite_replace_multi',
2472
-		'select' => 'spip_sqlite_select',
2473
-		'selectdb' => 'spip_sqlite_selectdb',
2474
-		'set_charset' => 'spip_sqlite_set_charset',
2475
-		'get_charset' => 'spip_sqlite_get_charset',
2476
-		'showbase' => 'spip_sqlite_showbase',
2477
-		'showtable' => 'spip_sqlite_showtable',
2478
-		'table_exists' => 'spip_sqlite_table_exists',
2479
-		'update' => 'spip_sqlite_update',
2480
-		'updateq' => 'spip_sqlite_updateq',
2481
-		'preferer_transaction' => 'spip_sqlite_preferer_transaction',
2482
-		'demarrer_transaction' => 'spip_sqlite_demarrer_transaction',
2483
-		'terminer_transaction' => 'spip_sqlite_terminer_transaction',
2484
-	];
2485
-
2486
-	// association de chaque nom http d'un charset aux couples sqlite
2487
-	// SQLite supporte utf-8 et utf-16 uniquement.
2488
-	$charsets = [
2489
-		'utf-8' => ['charset' => 'utf8', 'collation' => 'utf8_general_ci'],
2490
-		//'utf-16be'=>array('charset'=>'utf16be','collation'=>'UTF-16BE'),// aucune idee de quoi il faut remplir dans es champs la
2491
-		//'utf-16le'=>array('charset'=>'utf16le','collation'=>'UTF-16LE')
2492
-	];
2493
-
2494
-	$fonctions['charsets'] = $charsets;
2495
-
2496
-	return $fonctions;
2442
+    $fonctions = [
2443
+        'alter' => 'spip_sqlite_alter',
2444
+        'count' => 'spip_sqlite_count',
2445
+        'countsel' => 'spip_sqlite_countsel',
2446
+        'create' => 'spip_sqlite_create',
2447
+        'create_base' => 'spip_sqlite_create_base',
2448
+        'create_view' => 'spip_sqlite_create_view',
2449
+        'date_proche' => 'spip_sqlite_date_proche',
2450
+        'delete' => 'spip_sqlite_delete',
2451
+        'drop_table' => 'spip_sqlite_drop_table',
2452
+        'drop_view' => 'spip_sqlite_drop_view',
2453
+        'errno' => 'spip_sqlite_errno',
2454
+        'error' => 'spip_sqlite_error',
2455
+        'explain' => 'spip_sqlite_explain',
2456
+        'fetch' => 'spip_sqlite_fetch',
2457
+        'seek' => 'spip_sqlite_seek',
2458
+        'free' => 'spip_sqlite_free',
2459
+        'hex' => 'spip_sqlite_hex',
2460
+        'in' => 'spip_sqlite_in',
2461
+        'insert' => 'spip_sqlite_insert',
2462
+        'insertq' => 'spip_sqlite_insertq',
2463
+        'insertq_multi' => 'spip_sqlite_insertq_multi',
2464
+        'listdbs' => 'spip_sqlite_listdbs',
2465
+        'multi' => 'spip_sqlite_multi',
2466
+        'optimize' => 'spip_sqlite_optimize',
2467
+        'query' => 'spip_sqlite_query',
2468
+        'quote' => 'spip_sqlite_quote',
2469
+        'repair' => 'spip_sqlite_repair',
2470
+        'replace' => 'spip_sqlite_replace',
2471
+        'replace_multi' => 'spip_sqlite_replace_multi',
2472
+        'select' => 'spip_sqlite_select',
2473
+        'selectdb' => 'spip_sqlite_selectdb',
2474
+        'set_charset' => 'spip_sqlite_set_charset',
2475
+        'get_charset' => 'spip_sqlite_get_charset',
2476
+        'showbase' => 'spip_sqlite_showbase',
2477
+        'showtable' => 'spip_sqlite_showtable',
2478
+        'table_exists' => 'spip_sqlite_table_exists',
2479
+        'update' => 'spip_sqlite_update',
2480
+        'updateq' => 'spip_sqlite_updateq',
2481
+        'preferer_transaction' => 'spip_sqlite_preferer_transaction',
2482
+        'demarrer_transaction' => 'spip_sqlite_demarrer_transaction',
2483
+        'terminer_transaction' => 'spip_sqlite_terminer_transaction',
2484
+    ];
2485
+
2486
+    // association de chaque nom http d'un charset aux couples sqlite
2487
+    // SQLite supporte utf-8 et utf-16 uniquement.
2488
+    $charsets = [
2489
+        'utf-8' => ['charset' => 'utf8', 'collation' => 'utf8_general_ci'],
2490
+        //'utf-16be'=>array('charset'=>'utf16be','collation'=>'UTF-16BE'),// aucune idee de quoi il faut remplir dans es champs la
2491
+        //'utf-16le'=>array('charset'=>'utf16le','collation'=>'UTF-16LE')
2492
+    ];
2493
+
2494
+    $fonctions['charsets'] = $charsets;
2495
+
2496
+    return $fonctions;
2497 2497
 }
2498 2498
 
2499 2499
 
@@ -2505,56 +2505,56 @@  discard block
 block discarded – undo
2505 2505
  * @return mixed
2506 2506
  */
2507 2507
 function _sqlite_remplacements_definitions_table($query, $autoinc = false) {
2508
-	// quelques remplacements
2509
-	$num = '(\s*\([0-9]*\))?';
2510
-	$enum = '(\s*\([^\)]*\))?';
2511
-
2512
-	$remplace = [
2513
-		'/enum' . $enum . '/is' => 'VARCHAR(255)',
2514
-		'/COLLATE \w+_bin/is' => 'COLLATE BINARY',
2515
-		'/COLLATE \w+_ci/is' => 'COLLATE NOCASE',
2516
-		'/auto_increment/is' => '',
2517
-		'/current_timestamp\(\)/is' => 'CURRENT_TIMESTAMP', // Fix export depuis mariaDB #4374
2518
-		'/(timestamp .* )ON .*$/is' => '\\1',
2519
-		'/character set \w+/is' => '',
2520
-		'/((big|small|medium|tiny)?int(eger)?)' . $num . '\s*unsigned/is' => '\\1 UNSIGNED',
2521
-		'/(text\s+not\s+null(\s+collate\s+\w+)?)\s*$/is' => "\\1 DEFAULT ''",
2522
-		'/((char|varchar)' . $num . '\s+not\s+null(\s+collate\s+\w+)?)\s*$/is' => "\\1 DEFAULT ''",
2523
-		'/(datetime\s+not\s+null)\s*$/is' => "\\1 DEFAULT '0000-00-00 00:00:00'",
2524
-		'/(date\s+not\s+null)\s*$/is' => "\\1 DEFAULT '0000-00-00'",
2525
-	];
2526
-
2527
-	// pour l'autoincrement, il faut des INTEGER NOT NULL PRIMARY KEY
2528
-	$remplace_autocinc = [
2529
-		'/(big|small|medium|tiny)?int(eger)?' . $num . '/is' => 'INTEGER'
2530
-	];
2531
-	// pour les int non autoincrement, il faut un DEFAULT
2532
-	$remplace_nonautocinc = [
2533
-		'/((big|small|medium|tiny)?int(eger)?' . $num . '\s+not\s+null)\s*$/is' => "\\1 DEFAULT 0",
2534
-	];
2535
-
2536
-	if (is_string($query)) {
2537
-		$query = preg_replace(array_keys($remplace), $remplace, $query);
2538
-		if ($autoinc or preg_match(',AUTO_INCREMENT,is', $query)) {
2539
-			$query = preg_replace(array_keys($remplace_autocinc), $remplace_autocinc, $query);
2540
-		} else {
2541
-			$query = preg_replace(array_keys($remplace_nonautocinc), $remplace_nonautocinc, $query);
2542
-			$query = _sqlite_collate_ci($query);
2543
-		}
2544
-	} elseif (is_array($query)) {
2545
-		foreach ($query as $k => $q) {
2546
-			$ai = ($autoinc ? $k == $autoinc : preg_match(',AUTO_INCREMENT,is', $q));
2547
-			$query[$k] = preg_replace(array_keys($remplace), $remplace, $query[$k]);
2548
-			if ($ai) {
2549
-				$query[$k] = preg_replace(array_keys($remplace_autocinc), $remplace_autocinc, $query[$k]);
2550
-			} else {
2551
-				$query[$k] = preg_replace(array_keys($remplace_nonautocinc), $remplace_nonautocinc, $query[$k]);
2552
-				$query[$k] = _sqlite_collate_ci($query[$k]);
2553
-			}
2554
-		}
2555
-	}
2556
-
2557
-	return $query;
2508
+    // quelques remplacements
2509
+    $num = '(\s*\([0-9]*\))?';
2510
+    $enum = '(\s*\([^\)]*\))?';
2511
+
2512
+    $remplace = [
2513
+        '/enum' . $enum . '/is' => 'VARCHAR(255)',
2514
+        '/COLLATE \w+_bin/is' => 'COLLATE BINARY',
2515
+        '/COLLATE \w+_ci/is' => 'COLLATE NOCASE',
2516
+        '/auto_increment/is' => '',
2517
+        '/current_timestamp\(\)/is' => 'CURRENT_TIMESTAMP', // Fix export depuis mariaDB #4374
2518
+        '/(timestamp .* )ON .*$/is' => '\\1',
2519
+        '/character set \w+/is' => '',
2520
+        '/((big|small|medium|tiny)?int(eger)?)' . $num . '\s*unsigned/is' => '\\1 UNSIGNED',
2521
+        '/(text\s+not\s+null(\s+collate\s+\w+)?)\s*$/is' => "\\1 DEFAULT ''",
2522
+        '/((char|varchar)' . $num . '\s+not\s+null(\s+collate\s+\w+)?)\s*$/is' => "\\1 DEFAULT ''",
2523
+        '/(datetime\s+not\s+null)\s*$/is' => "\\1 DEFAULT '0000-00-00 00:00:00'",
2524
+        '/(date\s+not\s+null)\s*$/is' => "\\1 DEFAULT '0000-00-00'",
2525
+    ];
2526
+
2527
+    // pour l'autoincrement, il faut des INTEGER NOT NULL PRIMARY KEY
2528
+    $remplace_autocinc = [
2529
+        '/(big|small|medium|tiny)?int(eger)?' . $num . '/is' => 'INTEGER'
2530
+    ];
2531
+    // pour les int non autoincrement, il faut un DEFAULT
2532
+    $remplace_nonautocinc = [
2533
+        '/((big|small|medium|tiny)?int(eger)?' . $num . '\s+not\s+null)\s*$/is' => "\\1 DEFAULT 0",
2534
+    ];
2535
+
2536
+    if (is_string($query)) {
2537
+        $query = preg_replace(array_keys($remplace), $remplace, $query);
2538
+        if ($autoinc or preg_match(',AUTO_INCREMENT,is', $query)) {
2539
+            $query = preg_replace(array_keys($remplace_autocinc), $remplace_autocinc, $query);
2540
+        } else {
2541
+            $query = preg_replace(array_keys($remplace_nonautocinc), $remplace_nonautocinc, $query);
2542
+            $query = _sqlite_collate_ci($query);
2543
+        }
2544
+    } elseif (is_array($query)) {
2545
+        foreach ($query as $k => $q) {
2546
+            $ai = ($autoinc ? $k == $autoinc : preg_match(',AUTO_INCREMENT,is', $q));
2547
+            $query[$k] = preg_replace(array_keys($remplace), $remplace, $query[$k]);
2548
+            if ($ai) {
2549
+                $query[$k] = preg_replace(array_keys($remplace_autocinc), $remplace_autocinc, $query[$k]);
2550
+            } else {
2551
+                $query[$k] = preg_replace(array_keys($remplace_nonautocinc), $remplace_nonautocinc, $query[$k]);
2552
+                $query[$k] = _sqlite_collate_ci($query[$k]);
2553
+            }
2554
+        }
2555
+    }
2556
+
2557
+    return $query;
2558 2558
 }
2559 2559
 
2560 2560
 /**
@@ -2565,17 +2565,17 @@  discard block
 block discarded – undo
2565 2565
  * @return string
2566 2566
  */
2567 2567
 function _sqlite_collate_ci($champ) {
2568
-	if (stripos($champ, 'COLLATE') !== false) {
2569
-		return $champ;
2570
-	}
2571
-	if (stripos($champ, 'BINARY') !== false) {
2572
-		return str_ireplace('BINARY', 'COLLATE BINARY', $champ);
2573
-	}
2574
-	if (preg_match(',^(char|varchar|(long|small|medium|tiny)?text),i', $champ)) {
2575
-		return $champ . ' COLLATE NOCASE';
2576
-	}
2568
+    if (stripos($champ, 'COLLATE') !== false) {
2569
+        return $champ;
2570
+    }
2571
+    if (stripos($champ, 'BINARY') !== false) {
2572
+        return str_ireplace('BINARY', 'COLLATE BINARY', $champ);
2573
+    }
2574
+    if (preg_match(',^(char|varchar|(long|small|medium|tiny)?text),i', $champ)) {
2575
+        return $champ . ' COLLATE NOCASE';
2576
+    }
2577 2577
 
2578
-	return $champ;
2578
+    return $champ;
2579 2579
 }
2580 2580
 
2581 2581
 
@@ -2594,84 +2594,84 @@  discard block
 block discarded – undo
2594 2594
  * @return bool|string
2595 2595
  */
2596 2596
 function _sqlite_requete_create(
2597
-	$nom,
2598
-	$champs,
2599
-	$cles,
2600
-	$autoinc = false,
2601
-	$temporary = false,
2602
-	$_ifnotexists = true,
2603
-	$serveur = '',
2604
-	$requeter = true
2597
+    $nom,
2598
+    $champs,
2599
+    $cles,
2600
+    $autoinc = false,
2601
+    $temporary = false,
2602
+    $_ifnotexists = true,
2603
+    $serveur = '',
2604
+    $requeter = true
2605 2605
 ) {
2606
-	$query = $keys = $s = $p = '';
2607
-
2608
-	// certains plugins declarent les tables  (permet leur inclusion dans le dump)
2609
-	// sans les renseigner (laisse le compilo recuperer la description)
2610
-	if (!is_array($champs) || !is_array($cles)) {
2611
-		return;
2612
-	}
2613
-
2614
-	// sqlite ne gere pas KEY tout court dans une requete CREATE TABLE
2615
-	// il faut passer par des create index
2616
-	// Il gere par contre primary key !
2617
-	// Soit la PK est definie dans les cles, soit dans un champs
2618
-	// soit faussement dans les 2 (et dans ce cas, il faut l’enlever à un des 2 endroits !)
2619
-	$pk = 'PRIMARY KEY';
2620
-	// le champ de cle primaire
2621
-	$champ_pk = !empty($cles[$pk]) ? $cles[$pk] : '';
2622
-
2623
-	foreach ($champs as $k => $v) {
2624
-		if (false !== stripos($v, $pk)) {
2625
-			$champ_pk = $k;
2626
-			// on n'en a plus besoin dans field, vu que defini dans key
2627
-			$champs[$k] = preg_replace("/$pk/is", '', $champs[$k]);
2628
-			break;
2629
-		}
2630
-	}
2631
-
2632
-	if ($champ_pk) {
2633
-		$keys = "\n\t\t$pk ($champ_pk)";
2634
-	}
2635
-	// Pas de DEFAULT 0 sur les cles primaires en auto-increment
2636
-	if (
2637
-		isset($champs[$champ_pk])
2638
-		and stripos($champs[$champ_pk], 'default 0') !== false
2639
-	) {
2640
-		$champs[$champ_pk] = trim(str_ireplace('default 0', '', $champs[$champ_pk]));
2641
-	}
2642
-
2643
-	$champs = _sqlite_remplacements_definitions_table($champs, $autoinc ? $champ_pk : false);
2644
-	foreach ($champs as $k => $v) {
2645
-		$query .= "$s\n\t\t$k $v";
2646
-		$s = ',';
2647
-	}
2648
-
2649
-	$ifnotexists = '';
2650
-	if ($_ifnotexists) {
2651
-		$version = spip_sqlite_fetch(
2652
-			spip_sqlite_query('select sqlite_version() AS sqlite_version', $serveur),
2653
-			'',
2654
-			$serveur
2655
-		);
2656
-		if (!function_exists('spip_version_compare')) {
2657
-			include_spip('plugins/installer');
2658
-		}
2659
-
2660
-		if ($version and spip_version_compare($version['sqlite_version'], '3.3.0', '>=')) {
2661
-			$ifnotexists = ' IF NOT EXISTS';
2662
-		} else {
2663
-			/* simuler le IF EXISTS - version 2 et sqlite < 3.3a */
2664
-			$a = spip_sqlite_showtable($nom, $serveur);
2665
-			if (isset($a['key']['KEY ' . $nom])) {
2666
-				return true;
2667
-			}
2668
-		}
2669
-	}
2670
-
2671
-	$temporary = $temporary ? ' TEMPORARY' : '';
2672
-	$q = "CREATE$temporary TABLE$ifnotexists $nom ($query" . ($keys ? ",$keys" : '') . ")\n";
2673
-
2674
-	return $q;
2606
+    $query = $keys = $s = $p = '';
2607
+
2608
+    // certains plugins declarent les tables  (permet leur inclusion dans le dump)
2609
+    // sans les renseigner (laisse le compilo recuperer la description)
2610
+    if (!is_array($champs) || !is_array($cles)) {
2611
+        return;
2612
+    }
2613
+
2614
+    // sqlite ne gere pas KEY tout court dans une requete CREATE TABLE
2615
+    // il faut passer par des create index
2616
+    // Il gere par contre primary key !
2617
+    // Soit la PK est definie dans les cles, soit dans un champs
2618
+    // soit faussement dans les 2 (et dans ce cas, il faut l’enlever à un des 2 endroits !)
2619
+    $pk = 'PRIMARY KEY';
2620
+    // le champ de cle primaire
2621
+    $champ_pk = !empty($cles[$pk]) ? $cles[$pk] : '';
2622
+
2623
+    foreach ($champs as $k => $v) {
2624
+        if (false !== stripos($v, $pk)) {
2625
+            $champ_pk = $k;
2626
+            // on n'en a plus besoin dans field, vu que defini dans key
2627
+            $champs[$k] = preg_replace("/$pk/is", '', $champs[$k]);
2628
+            break;
2629
+        }
2630
+    }
2631
+
2632
+    if ($champ_pk) {
2633
+        $keys = "\n\t\t$pk ($champ_pk)";
2634
+    }
2635
+    // Pas de DEFAULT 0 sur les cles primaires en auto-increment
2636
+    if (
2637
+        isset($champs[$champ_pk])
2638
+        and stripos($champs[$champ_pk], 'default 0') !== false
2639
+    ) {
2640
+        $champs[$champ_pk] = trim(str_ireplace('default 0', '', $champs[$champ_pk]));
2641
+    }
2642
+
2643
+    $champs = _sqlite_remplacements_definitions_table($champs, $autoinc ? $champ_pk : false);
2644
+    foreach ($champs as $k => $v) {
2645
+        $query .= "$s\n\t\t$k $v";
2646
+        $s = ',';
2647
+    }
2648
+
2649
+    $ifnotexists = '';
2650
+    if ($_ifnotexists) {
2651
+        $version = spip_sqlite_fetch(
2652
+            spip_sqlite_query('select sqlite_version() AS sqlite_version', $serveur),
2653
+            '',
2654
+            $serveur
2655
+        );
2656
+        if (!function_exists('spip_version_compare')) {
2657
+            include_spip('plugins/installer');
2658
+        }
2659
+
2660
+        if ($version and spip_version_compare($version['sqlite_version'], '3.3.0', '>=')) {
2661
+            $ifnotexists = ' IF NOT EXISTS';
2662
+        } else {
2663
+            /* simuler le IF EXISTS - version 2 et sqlite < 3.3a */
2664
+            $a = spip_sqlite_showtable($nom, $serveur);
2665
+            if (isset($a['key']['KEY ' . $nom])) {
2666
+                return true;
2667
+            }
2668
+        }
2669
+    }
2670
+
2671
+    $temporary = $temporary ? ' TEMPORARY' : '';
2672
+    $q = "CREATE$temporary TABLE$ifnotexists $nom ($query" . ($keys ? ",$keys" : '') . ")\n";
2673
+
2674
+    return $q;
2675 2675
 }
2676 2676
 
2677 2677
 
@@ -2690,41 +2690,41 @@  discard block
 block discarded – undo
2690 2690
  * @return
2691 2691
  */
2692 2692
 function _sqlite_ajouter_champs_timestamp($table, $couples, $desc = '', $serveur = '') {
2693
-	static $tables = [];
2694
-
2695
-	if (!isset($tables[$table])) {
2696
-		if (!$desc) {
2697
-			$trouver_table = charger_fonction('trouver_table', 'base');
2698
-			$desc = $trouver_table($table, $serveur);
2699
-			// si pas de description, on ne fait rien, ou on die() ?
2700
-			if (!$desc) {
2701
-				return $couples;
2702
-			}
2703
-		}
2704
-
2705
-		// recherche des champs avec simplement 'TIMESTAMP'
2706
-		// cependant, il faudra peut etre etendre
2707
-		// avec la gestion de DEFAULT et ON UPDATE
2708
-		// mais ceux-ci ne sont pas utilises dans le core
2709
-		$tables[$table] = ['valeur' => [], 'cite' => [], 'desc' => []];
2710
-
2711
-		$now = _sqlite_func_now(true);
2712
-		foreach ($desc['field'] as $k => $v) {
2713
-			if (strpos(strtolower(ltrim($v)), 'timestamp') === 0) {
2714
-				$tables[$table]['desc'][$k] = $v;
2715
-				$tables[$table]['valeur'][$k] = _sqlite_calculer_cite($now, $tables[$table]['desc'][$k]);
2716
-			}
2717
-		}
2718
-	}
2719
-	else {
2720
-		$now = _sqlite_func_now(true);
2721
-		foreach (array_keys($tables[$table]['desc']) as $k) {
2722
-			$tables[$table]['valeur'][$k] = _sqlite_calculer_cite($now, $tables[$table]['desc'][$k]);
2723
-		}
2724
-	}
2725
-
2726
-	// ajout des champs type 'timestamp' absents
2727
-	return array_merge($tables[$table]['valeur'], $couples);
2693
+    static $tables = [];
2694
+
2695
+    if (!isset($tables[$table])) {
2696
+        if (!$desc) {
2697
+            $trouver_table = charger_fonction('trouver_table', 'base');
2698
+            $desc = $trouver_table($table, $serveur);
2699
+            // si pas de description, on ne fait rien, ou on die() ?
2700
+            if (!$desc) {
2701
+                return $couples;
2702
+            }
2703
+        }
2704
+
2705
+        // recherche des champs avec simplement 'TIMESTAMP'
2706
+        // cependant, il faudra peut etre etendre
2707
+        // avec la gestion de DEFAULT et ON UPDATE
2708
+        // mais ceux-ci ne sont pas utilises dans le core
2709
+        $tables[$table] = ['valeur' => [], 'cite' => [], 'desc' => []];
2710
+
2711
+        $now = _sqlite_func_now(true);
2712
+        foreach ($desc['field'] as $k => $v) {
2713
+            if (strpos(strtolower(ltrim($v)), 'timestamp') === 0) {
2714
+                $tables[$table]['desc'][$k] = $v;
2715
+                $tables[$table]['valeur'][$k] = _sqlite_calculer_cite($now, $tables[$table]['desc'][$k]);
2716
+            }
2717
+        }
2718
+    }
2719
+    else {
2720
+        $now = _sqlite_func_now(true);
2721
+        foreach (array_keys($tables[$table]['desc']) as $k) {
2722
+            $tables[$table]['valeur'][$k] = _sqlite_calculer_cite($now, $tables[$table]['desc'][$k]);
2723
+        }
2724
+    }
2725
+
2726
+    // ajout des champs type 'timestamp' absents
2727
+    return array_merge($tables[$table]['valeur'], $couples);
2728 2728
 }
2729 2729
 
2730 2730
 
@@ -2735,7 +2735,7 @@  discard block
 block discarded – undo
2735 2735
  * @return array|bool
2736 2736
  */
2737 2737
 function spip_versions_sqlite() {
2738
-	return _sqlite_charger_version();
2738
+    return _sqlite_charger_version();
2739 2739
 }
2740 2740
 
2741 2741
 /**
@@ -2743,114 +2743,114 @@  discard block
 block discarded – undo
2743 2743
  * encadrées de transactions.
2744 2744
  **/
2745 2745
 class spip_sqlite {
2746
-	/** @var sqlite_requeteur[] Liste des instances de requêteurs créés */
2747
-	public static $requeteurs = [];
2748
-	/** @var bool[] Pour chaque connexion, flag pour savoir si une transaction est en cours */
2749
-	public static $transaction_en_cours = [];
2750
-
2751
-
2752
-	/**
2753
-	 * Retourne une unique instance du requêteur
2754
-	 *
2755
-	 * Retourne une instance unique du requêteur pour une connexion SQLite
2756
-	 * donnée
2757
-	 *
2758
-	 * @param string $serveur
2759
-	 *    Nom du connecteur
2760
-	 * @return sqlite_requeteur
2761
-	 *    Instance unique du requêteur
2762
-	 **/
2763
-	public static function requeteur($serveur) {
2764
-		if (!isset(spip_sqlite::$requeteurs[$serveur])) {
2765
-			spip_sqlite::$requeteurs[$serveur] = new sqlite_requeteur($serveur);
2766
-		}
2767
-
2768
-		return spip_sqlite::$requeteurs[$serveur];
2769
-	}
2770
-
2771
-	/**
2772
-	 * Prépare le texte d'une requête avant son exécution
2773
-	 *
2774
-	 * Adapte la requête au format plus ou moins MySQL par un format
2775
-	 * compris de SQLite.
2776
-	 *
2777
-	 * Change les préfixes de tables SPIP par ceux véritables
2778
-	 *
2779
-	 * @param string $query Requête à préparer
2780
-	 * @param string $serveur Nom de la connexion
2781
-	 * @return string           Requête préparée
2782
-	 */
2783
-	public static function traduire_requete($query, $serveur) {
2784
-		$requeteur = spip_sqlite::requeteur($serveur);
2785
-		$traducteur = new sqlite_traducteur($query, $requeteur->prefixe, $requeteur->sqlite_version);
2786
-
2787
-		return $traducteur->traduire_requete();
2788
-	}
2789
-
2790
-	/**
2791
-	 * Démarre une transaction
2792
-	 *
2793
-	 * @param string $serveur Nom de la connexion
2794
-	 **/
2795
-	public static function demarrer_transaction($serveur) {
2796
-		spip_sqlite::executer_requete('BEGIN TRANSACTION', $serveur);
2797
-		spip_sqlite::$transaction_en_cours[$serveur] = true;
2798
-	}
2799
-
2800
-	/**
2801
-	 * Exécute la requête donnée
2802
-	 *
2803
-	 * @param string $query Requête
2804
-	 * @param string $serveur Nom de la connexion
2805
-	 * @param null|bool $tracer Demander des statistiques (temps) ?
2806
-	 **/
2807
-	public static function executer_requete($query, $serveur, $tracer = null) {
2808
-		$requeteur = spip_sqlite::requeteur($serveur);
2809
-
2810
-		return $requeteur->executer_requete($query, $tracer);
2811
-	}
2812
-
2813
-	/**
2814
-	 * Obtient l'identifiant de la dernière ligne insérée ou modifiée
2815
-	 *
2816
-	 * @param string $serveur Nom de la connexion
2817
-	 * return int                Identifiant
2818
-	 **/
2819
-	public static function last_insert_id($serveur) {
2820
-		$requeteur = spip_sqlite::requeteur($serveur);
2821
-
2822
-		return $requeteur->last_insert_id($serveur);
2823
-	}
2824
-
2825
-	/**
2826
-	 * Annule une transaction
2827
-	 *
2828
-	 * @param string $serveur Nom de la connexion
2829
-	 **/
2830
-	public static function annuler_transaction($serveur) {
2831
-		spip_sqlite::executer_requete('ROLLBACK', $serveur);
2832
-		spip_sqlite::$transaction_en_cours[$serveur] = false;
2833
-	}
2834
-
2835
-	/**
2836
-	 * Termine une transaction
2837
-	 *
2838
-	 * @param string $serveur Nom de la connexion
2839
-	 **/
2840
-	public static function finir_transaction($serveur) {
2841
-		// si pas de transaction en cours, ne rien faire et le dire
2842
-		if (
2843
-			!isset(spip_sqlite::$transaction_en_cours[$serveur])
2844
-			or spip_sqlite::$transaction_en_cours[$serveur] == false
2845
-		) {
2846
-			return false;
2847
-		}
2848
-		// sinon fermer la transaction et retourner true
2849
-		spip_sqlite::executer_requete('COMMIT', $serveur);
2850
-		spip_sqlite::$transaction_en_cours[$serveur] = false;
2851
-
2852
-		return true;
2853
-	}
2746
+    /** @var sqlite_requeteur[] Liste des instances de requêteurs créés */
2747
+    public static $requeteurs = [];
2748
+    /** @var bool[] Pour chaque connexion, flag pour savoir si une transaction est en cours */
2749
+    public static $transaction_en_cours = [];
2750
+
2751
+
2752
+    /**
2753
+     * Retourne une unique instance du requêteur
2754
+     *
2755
+     * Retourne une instance unique du requêteur pour une connexion SQLite
2756
+     * donnée
2757
+     *
2758
+     * @param string $serveur
2759
+     *    Nom du connecteur
2760
+     * @return sqlite_requeteur
2761
+     *    Instance unique du requêteur
2762
+     **/
2763
+    public static function requeteur($serveur) {
2764
+        if (!isset(spip_sqlite::$requeteurs[$serveur])) {
2765
+            spip_sqlite::$requeteurs[$serveur] = new sqlite_requeteur($serveur);
2766
+        }
2767
+
2768
+        return spip_sqlite::$requeteurs[$serveur];
2769
+    }
2770
+
2771
+    /**
2772
+     * Prépare le texte d'une requête avant son exécution
2773
+     *
2774
+     * Adapte la requête au format plus ou moins MySQL par un format
2775
+     * compris de SQLite.
2776
+     *
2777
+     * Change les préfixes de tables SPIP par ceux véritables
2778
+     *
2779
+     * @param string $query Requête à préparer
2780
+     * @param string $serveur Nom de la connexion
2781
+     * @return string           Requête préparée
2782
+     */
2783
+    public static function traduire_requete($query, $serveur) {
2784
+        $requeteur = spip_sqlite::requeteur($serveur);
2785
+        $traducteur = new sqlite_traducteur($query, $requeteur->prefixe, $requeteur->sqlite_version);
2786
+
2787
+        return $traducteur->traduire_requete();
2788
+    }
2789
+
2790
+    /**
2791
+     * Démarre une transaction
2792
+     *
2793
+     * @param string $serveur Nom de la connexion
2794
+     **/
2795
+    public static function demarrer_transaction($serveur) {
2796
+        spip_sqlite::executer_requete('BEGIN TRANSACTION', $serveur);
2797
+        spip_sqlite::$transaction_en_cours[$serveur] = true;
2798
+    }
2799
+
2800
+    /**
2801
+     * Exécute la requête donnée
2802
+     *
2803
+     * @param string $query Requête
2804
+     * @param string $serveur Nom de la connexion
2805
+     * @param null|bool $tracer Demander des statistiques (temps) ?
2806
+     **/
2807
+    public static function executer_requete($query, $serveur, $tracer = null) {
2808
+        $requeteur = spip_sqlite::requeteur($serveur);
2809
+
2810
+        return $requeteur->executer_requete($query, $tracer);
2811
+    }
2812
+
2813
+    /**
2814
+     * Obtient l'identifiant de la dernière ligne insérée ou modifiée
2815
+     *
2816
+     * @param string $serveur Nom de la connexion
2817
+     * return int                Identifiant
2818
+     **/
2819
+    public static function last_insert_id($serveur) {
2820
+        $requeteur = spip_sqlite::requeteur($serveur);
2821
+
2822
+        return $requeteur->last_insert_id($serveur);
2823
+    }
2824
+
2825
+    /**
2826
+     * Annule une transaction
2827
+     *
2828
+     * @param string $serveur Nom de la connexion
2829
+     **/
2830
+    public static function annuler_transaction($serveur) {
2831
+        spip_sqlite::executer_requete('ROLLBACK', $serveur);
2832
+        spip_sqlite::$transaction_en_cours[$serveur] = false;
2833
+    }
2834
+
2835
+    /**
2836
+     * Termine une transaction
2837
+     *
2838
+     * @param string $serveur Nom de la connexion
2839
+     **/
2840
+    public static function finir_transaction($serveur) {
2841
+        // si pas de transaction en cours, ne rien faire et le dire
2842
+        if (
2843
+            !isset(spip_sqlite::$transaction_en_cours[$serveur])
2844
+            or spip_sqlite::$transaction_en_cours[$serveur] == false
2845
+        ) {
2846
+            return false;
2847
+        }
2848
+        // sinon fermer la transaction et retourner true
2849
+        spip_sqlite::executer_requete('COMMIT', $serveur);
2850
+        spip_sqlite::$transaction_en_cours[$serveur] = false;
2851
+
2852
+        return true;
2853
+    }
2854 2854
 }
2855 2855
 
2856 2856
 /*
@@ -2863,127 +2863,127 @@  discard block
 block discarded – undo
2863 2863
  */
2864 2864
 
2865 2865
 class sqlite_requeteur {
2866
-	/** @var string Texte de la requête */
2867
-	public $query = ''; // la requete
2868
-	/** @var string Nom de la connexion */
2869
-	public $serveur = '';
2870
-	/** @var PDO Identifiant de la connexion SQLite */
2871
-	public $link = '';
2872
-	/** @var string Prefixe des tables SPIP */
2873
-	public $prefixe = '';
2874
-	/** @var string Nom de la base de donnée */
2875
-	public $db = '';
2876
-	/** @var bool Doit-on tracer les requetes (var_profile) ? */
2877
-	public $tracer = false; // doit-on tracer les requetes (var_profile)
2878
-
2879
-	/** @var string Version de SQLite (2 ou 3) */
2880
-	public $sqlite_version = '';
2881
-
2882
-	/**
2883
-	 * Constructeur
2884
-	 *
2885
-	 * @param string $serveur
2886
-	 * @return bool
2887
-	 */
2888
-	public function __construct($serveur = '') {
2889
-		_sqlite_init();
2890
-		$this->serveur = strtolower($serveur);
2891
-
2892
-		if (!($this->link = _sqlite_link($this->serveur)) && (!defined('_ECRIRE_INSTALL') || !_ECRIRE_INSTALL)) {
2893
-			spip_log('Aucune connexion sqlite (link)', 'sqlite.' . _LOG_ERREUR);
2894
-
2895
-			return false;
2896
-		}
2897
-
2898
-		$this->sqlite_version = _sqlite_is_version('', $this->link);
2899
-
2900
-		$this->prefixe = $GLOBALS['connexions'][$this->serveur ? $this->serveur : 0]['prefixe'];
2901
-		$this->db = $GLOBALS['connexions'][$this->serveur ? $this->serveur : 0]['db'];
2902
-
2903
-		// tracage des requetes ?
2904
-		$this->tracer = (isset($_GET['var_profile']) && $_GET['var_profile']);
2905
-	}
2906
-
2907
-	/**
2908
-	 * Lancer la requête transmise et faire le tracage si demandé
2909
-	 *
2910
-	 * @param string $query
2911
-	 *     Requête à exécuter
2912
-	 * @param bool|null $tracer
2913
-	 *     true pour tracer la requête
2914
-	 * @return bool|PDOStatement|array
2915
-	 */
2916
-	public function executer_requete($query, $tracer = null) {
2917
-		if (is_null($tracer)) {
2918
-			$tracer = $this->tracer;
2919
-		}
2920
-		$err = '';
2921
-		$t = 0;
2922
-		if ($tracer or (defined('_DEBUG_TRACE_QUERIES') and _DEBUG_TRACE_QUERIES)) {
2923
-			include_spip('public/tracer');
2924
-			$t = trace_query_start();
2925
-		}
2926
-
2927
-		# spip_log("requete: $this->serveur >> $query",'sqlite.'._LOG_DEBUG); // boum ? pourquoi ?
2928
-		if ($this->link) {
2929
-			// memoriser la derniere erreur PHP vue
2930
-			$last_error = (function_exists('error_get_last') ? error_get_last() : '');
2931
-			$e = null;
2932
-			// sauver la derniere requete
2933
-			$GLOBALS['connexions'][$this->serveur ? $this->serveur : 0]['last'] = $query;
2934
-			$GLOBALS['connexions'][$this->serveur ? $this->serveur : 0]['total_requetes']++;
2935
-
2936
-			try {
2937
-				$r = $this->link->query($query);
2938
-			} catch (\PDOException $e) {
2939
-				spip_log('PDOException: ' . $e->getMessage(), 'sqlite.' . _LOG_DEBUG);
2940
-				$r = false;
2941
-			}
2942
-			// sauvegarde de la requete (elle y est deja dans $r->queryString)
2943
-			# $r->spipQueryString = $query;
2944
-
2945
-			// comptage : oblige de compter le nombre d'entrees retournees
2946
-			// par une requete SELECT
2947
-			// aucune autre solution ne donne le nombre attendu :( !
2948
-			// particulierement s'il y a des LIMIT dans la requete.
2949
-			if (strtoupper(substr(ltrim($query), 0, 6)) == 'SELECT') {
2950
-				if ($r) {
2951
-					// noter le link et la query pour faire le comptage *si* on en a besoin
2952
-					$r->spipSqliteRowCount = [$this->link, $query];
2953
-				} elseif ($r instanceof PDOStatement) {
2954
-					$r->spipSqliteRowCount = 0;
2955
-				}
2956
-			}
2957
-
2958
-			// loger les warnings/erreurs eventuels de sqlite remontant dans PHP
2959
-			if ($e and $e instanceof \PDOException) {
2960
-				$err = strip_tags($e->getMessage()) . ' in ' . $e->getFile() . ' line ' . $e->getLine();
2961
-				spip_log("$err - " . $query, 'sqlite.' . _LOG_ERREUR);
2962
-			} elseif ($err = (function_exists('error_get_last') ? error_get_last() : '') and $err != $last_error) {
2963
-				$err = strip_tags($err['message']) . ' in ' . $err['file'] . ' line ' . $err['line'];
2964
-				spip_log("$err - " . $query, 'sqlite.' . _LOG_ERREUR);
2965
-			} else {
2966
-				$err = '';
2967
-			}
2968
-		} else {
2969
-			$r = false;
2970
-		}
2971
-
2972
-		if (spip_sqlite_errno($this->serveur)) {
2973
-			$err .= spip_sqlite_error($query, $this->serveur);
2974
-		}
2975
-
2976
-		return $t ? trace_query_end($query, $t, $r, $err, $this->serveur) : $r;
2977
-	}
2978
-
2979
-	/**
2980
-	 * Obtient l'identifiant de la dernière ligne insérée ou modifiée
2981
-	 *
2982
-	 * @return string|false
2983
-	 **/
2984
-	public function last_insert_id() {
2985
-		return $this->link->lastInsertId();
2986
-	}
2866
+    /** @var string Texte de la requête */
2867
+    public $query = ''; // la requete
2868
+    /** @var string Nom de la connexion */
2869
+    public $serveur = '';
2870
+    /** @var PDO Identifiant de la connexion SQLite */
2871
+    public $link = '';
2872
+    /** @var string Prefixe des tables SPIP */
2873
+    public $prefixe = '';
2874
+    /** @var string Nom de la base de donnée */
2875
+    public $db = '';
2876
+    /** @var bool Doit-on tracer les requetes (var_profile) ? */
2877
+    public $tracer = false; // doit-on tracer les requetes (var_profile)
2878
+
2879
+    /** @var string Version de SQLite (2 ou 3) */
2880
+    public $sqlite_version = '';
2881
+
2882
+    /**
2883
+     * Constructeur
2884
+     *
2885
+     * @param string $serveur
2886
+     * @return bool
2887
+     */
2888
+    public function __construct($serveur = '') {
2889
+        _sqlite_init();
2890
+        $this->serveur = strtolower($serveur);
2891
+
2892
+        if (!($this->link = _sqlite_link($this->serveur)) && (!defined('_ECRIRE_INSTALL') || !_ECRIRE_INSTALL)) {
2893
+            spip_log('Aucune connexion sqlite (link)', 'sqlite.' . _LOG_ERREUR);
2894
+
2895
+            return false;
2896
+        }
2897
+
2898
+        $this->sqlite_version = _sqlite_is_version('', $this->link);
2899
+
2900
+        $this->prefixe = $GLOBALS['connexions'][$this->serveur ? $this->serveur : 0]['prefixe'];
2901
+        $this->db = $GLOBALS['connexions'][$this->serveur ? $this->serveur : 0]['db'];
2902
+
2903
+        // tracage des requetes ?
2904
+        $this->tracer = (isset($_GET['var_profile']) && $_GET['var_profile']);
2905
+    }
2906
+
2907
+    /**
2908
+     * Lancer la requête transmise et faire le tracage si demandé
2909
+     *
2910
+     * @param string $query
2911
+     *     Requête à exécuter
2912
+     * @param bool|null $tracer
2913
+     *     true pour tracer la requête
2914
+     * @return bool|PDOStatement|array
2915
+     */
2916
+    public function executer_requete($query, $tracer = null) {
2917
+        if (is_null($tracer)) {
2918
+            $tracer = $this->tracer;
2919
+        }
2920
+        $err = '';
2921
+        $t = 0;
2922
+        if ($tracer or (defined('_DEBUG_TRACE_QUERIES') and _DEBUG_TRACE_QUERIES)) {
2923
+            include_spip('public/tracer');
2924
+            $t = trace_query_start();
2925
+        }
2926
+
2927
+        # spip_log("requete: $this->serveur >> $query",'sqlite.'._LOG_DEBUG); // boum ? pourquoi ?
2928
+        if ($this->link) {
2929
+            // memoriser la derniere erreur PHP vue
2930
+            $last_error = (function_exists('error_get_last') ? error_get_last() : '');
2931
+            $e = null;
2932
+            // sauver la derniere requete
2933
+            $GLOBALS['connexions'][$this->serveur ? $this->serveur : 0]['last'] = $query;
2934
+            $GLOBALS['connexions'][$this->serveur ? $this->serveur : 0]['total_requetes']++;
2935
+
2936
+            try {
2937
+                $r = $this->link->query($query);
2938
+            } catch (\PDOException $e) {
2939
+                spip_log('PDOException: ' . $e->getMessage(), 'sqlite.' . _LOG_DEBUG);
2940
+                $r = false;
2941
+            }
2942
+            // sauvegarde de la requete (elle y est deja dans $r->queryString)
2943
+            # $r->spipQueryString = $query;
2944
+
2945
+            // comptage : oblige de compter le nombre d'entrees retournees
2946
+            // par une requete SELECT
2947
+            // aucune autre solution ne donne le nombre attendu :( !
2948
+            // particulierement s'il y a des LIMIT dans la requete.
2949
+            if (strtoupper(substr(ltrim($query), 0, 6)) == 'SELECT') {
2950
+                if ($r) {
2951
+                    // noter le link et la query pour faire le comptage *si* on en a besoin
2952
+                    $r->spipSqliteRowCount = [$this->link, $query];
2953
+                } elseif ($r instanceof PDOStatement) {
2954
+                    $r->spipSqliteRowCount = 0;
2955
+                }
2956
+            }
2957
+
2958
+            // loger les warnings/erreurs eventuels de sqlite remontant dans PHP
2959
+            if ($e and $e instanceof \PDOException) {
2960
+                $err = strip_tags($e->getMessage()) . ' in ' . $e->getFile() . ' line ' . $e->getLine();
2961
+                spip_log("$err - " . $query, 'sqlite.' . _LOG_ERREUR);
2962
+            } elseif ($err = (function_exists('error_get_last') ? error_get_last() : '') and $err != $last_error) {
2963
+                $err = strip_tags($err['message']) . ' in ' . $err['file'] . ' line ' . $err['line'];
2964
+                spip_log("$err - " . $query, 'sqlite.' . _LOG_ERREUR);
2965
+            } else {
2966
+                $err = '';
2967
+            }
2968
+        } else {
2969
+            $r = false;
2970
+        }
2971
+
2972
+        if (spip_sqlite_errno($this->serveur)) {
2973
+            $err .= spip_sqlite_error($query, $this->serveur);
2974
+        }
2975
+
2976
+        return $t ? trace_query_end($query, $t, $r, $err, $this->serveur) : $r;
2977
+    }
2978
+
2979
+    /**
2980
+     * Obtient l'identifiant de la dernière ligne insérée ou modifiée
2981
+     *
2982
+     * @return string|false
2983
+     **/
2984
+    public function last_insert_id() {
2985
+        return $this->link->lastInsertId();
2986
+    }
2987 2987
 }
2988 2988
 
2989 2989
 
@@ -2993,206 +2993,206 @@  discard block
 block discarded – undo
2993 2993
  * (fonction pour proteger les textes)
2994 2994
  */
2995 2995
 class sqlite_traducteur {
2996
-	/** @var string $query Texte de la requête */
2997
-	public $query = '';
2998
-	/** @var string $prefixe Préfixe des tables */
2999
-	public $prefixe = '';
3000
-	/** @var string $sqlite_version Version de sqlite (2 ou 3) */
3001
-	public $sqlite_version = '';
3002
-
3003
-	/** Pour les corrections à effectuer sur les requêtes : array(code=>'texte') trouvé
3004
-	 *
3005
-	 * @var array
3006
-	 */
3007
-	public $textes = [];
3008
-
3009
-	/**
3010
-	 * Constructeur
3011
-	 *
3012
-	 * @param string $query Requête à préparer
3013
-	 * @param string $prefixe Prefixe des tables à utiliser
3014
-	 * @param string $sqlite_version Version SQLite (2 ou 3)
3015
-	 */
3016
-	public function __construct($query, $prefixe, $sqlite_version) {
3017
-		$this->query = $query;
3018
-		$this->prefixe = $prefixe;
3019
-		$this->sqlite_version = $sqlite_version;
3020
-	}
3021
-
3022
-	/**
3023
-	 * Transformer la requete pour SQLite
3024
-	 *
3025
-	 * Enlève les textes, transforme la requête pour quelle soit
3026
-	 * bien interprétée par SQLite, puis remet les textes
3027
-	 * la fonction affecte `$this->query`
3028
-	 */
3029
-	public function traduire_requete() {
3030
-		//
3031
-		// 1) Protection des textes en les remplacant par des codes
3032
-		//
3033
-		// enlever les 'textes' et initialiser avec
3034
-		list($this->query, $textes) = query_echappe_textes($this->query);
3035
-
3036
-		//
3037
-		// 2) Corrections de la requete
3038
-		//
3039
-		// Correction Create Database
3040
-		// Create Database -> requete ignoree
3041
-		if (strpos($this->query, 'CREATE DATABASE') === 0) {
3042
-			spip_log("Sqlite : requete non executee -> $this->query", 'sqlite.' . _LOG_AVERTISSEMENT);
3043
-			$this->query = 'SELECT 1';
3044
-		}
3045
-
3046
-		// Correction Insert Ignore
3047
-		// INSERT IGNORE -> insert (tout court et pas 'insert or replace')
3048
-		if (strpos($this->query, 'INSERT IGNORE') === 0) {
3049
-			spip_log("Sqlite : requete transformee -> $this->query", 'sqlite.' . _LOG_DEBUG);
3050
-			$this->query = 'INSERT ' . substr($this->query, '13');
3051
-		}
3052
-
3053
-		// Correction des dates avec INTERVAL
3054
-		// utiliser sql_date_proche() de preference
3055
-		if (strpos($this->query, 'INTERVAL') !== false) {
3056
-			$this->query = preg_replace_callback(
3057
-				'/DATE_(ADD|SUB)(.*)INTERVAL\s+(\d+)\s+([a-zA-Z]+)\)/U',
3058
-				[&$this, '_remplacerDateParTime'],
3059
-				$this->query
3060
-			);
3061
-		}
3062
-
3063
-		if (strpos($this->query, 'LEFT(') !== false) {
3064
-			$this->query = str_replace('LEFT(', '_LEFT(', $this->query);
3065
-		}
3066
-
3067
-		if (strpos($this->query, 'TIMESTAMPDIFF(') !== false) {
3068
-			$this->query = preg_replace('/TIMESTAMPDIFF\(\s*([^,]*)\s*,/Uims', "TIMESTAMPDIFF('\\1',", $this->query);
3069
-		}
3070
-
3071
-
3072
-		// Correction Using
3073
-		// USING (non reconnu en sqlite2)
3074
-		// problematique car la jointure ne se fait pas du coup.
3075
-		if (($this->sqlite_version == 2) && (strpos($this->query, 'USING') !== false)) {
3076
-			spip_log(
3077
-				"'USING (champ)' n'est pas reconnu en SQLite 2. Utilisez 'ON table1.champ = table2.champ'",
3078
-				'sqlite.' . _LOG_ERREUR
3079
-			);
3080
-			$this->query = preg_replace('/USING\s*\([^\)]*\)/', '', $this->query);
3081
-		}
3082
-
3083
-		// Correction Field
3084
-		// remplace FIELD(table,i,j,k...) par CASE WHEN table=i THEN n ... ELSE 0 END
3085
-		if (strpos($this->query, 'FIELD') !== false) {
3086
-			$this->query = preg_replace_callback(
3087
-				'/FIELD\s*\(([^\)]*)\)/',
3088
-				[&$this, '_remplacerFieldParCase'],
3089
-				$this->query
3090
-			);
3091
-		}
3092
-
3093
-		// Correction des noms de tables FROM
3094
-		// mettre les bons noms de table dans from, update, insert, replace...
3095
-		if (preg_match('/\s(SET|VALUES|WHERE|DATABASE)\s/iS', $this->query, $regs)) {
3096
-			$suite = strstr($this->query, $regs[0]);
3097
-			$this->query = substr($this->query, 0, -strlen($suite));
3098
-		} else {
3099
-			$suite = '';
3100
-		}
3101
-		$pref = ($this->prefixe) ? $this->prefixe . '_' : '';
3102
-		$this->query = preg_replace('/([,\s])spip_/S', '\1' . $pref, $this->query) . $suite;
3103
-
3104
-		// Correction zero AS x
3105
-		// pg n'aime pas 0+x AS alias, sqlite, dans le meme style,
3106
-		// n'apprecie pas du tout SELECT 0 as x ... ORDER BY x
3107
-		// il dit que x ne doit pas être un integer dans le order by !
3108
-		// on remplace du coup x par vide() dans ce cas uniquement
3109
-		//
3110
-		// apparait dans public/vertebrer.php et dans le plugin menu aussi qui genere aussi ce genre de requete via un {par num #GET{tri_num}}
3111
-		// mais est-ce encore un soucis pour sqlite en 2021 ? (ie commenter le preg_replace marche très bien en sqlite 3.28)
3112
-		if ((strpos($this->query, '0 AS') !== false)) {
3113
-			// on ne remplace que dans ORDER BY ou GROUP BY
3114
-			if (preg_match('/\s(ORDER|GROUP) BY\s/i', $this->query, $regs)) {
3115
-				$suite = strstr($this->query, $regs[0]);
3116
-				$this->query = substr($this->query, 0, -strlen($suite));
3117
-
3118
-				// on cherche les noms des x dans 0 AS x
3119
-				// on remplace dans $suite le nom par vide()
3120
-				preg_match_all('/\b0 AS\s*([^\s,]+)/', $this->query, $matches, PREG_PATTERN_ORDER);
3121
-				foreach ($matches[1] as $m) {
3122
-					if (strpos($suite, $m) !== false) {
3123
-						$suite = preg_replace(",\b$m\b,", 'VIDE()', $suite);
3124
-					}
3125
-				}
3126
-				$this->query .= $suite;
3127
-			}
3128
-		}
3129
-
3130
-		// Correction possible des divisions entieres
3131
-		// Le standard SQL (lequel? ou?) semble indiquer que
3132
-		// a/b=c doit donner c entier si a et b sont entiers 4/3=1.
3133
-		// C'est ce que retournent effectivement SQL Server et SQLite
3134
-		// Ce n'est pas ce qu'applique MySQL qui retourne un reel : 4/3=1.333...
3135
-		//
3136
-		// On peut forcer la conversion en multipliant par 1.0 avant la division
3137
-		// /!\ SQLite 3.5.9 Debian/Ubuntu est victime d'un bug en plus !
3138
-		// cf. https://bugs.launchpad.net/ubuntu/+source/sqlite3/+bug/254228
3139
-		//     http://www.sqlite.org/cvstrac/tktview?tn=3202
3140
-		// (4*1.0/3) n'est pas rendu dans ce cas !
3141
-		# $this->query = str_replace('/','* 1.00 / ',$this->query);
3142
-
3143
-
3144
-		// Correction critere REGEXP, non reconnu en sqlite2
3145
-		if (($this->sqlite_version == 2) && (strpos($this->query, 'REGEXP') !== false)) {
3146
-			$this->query = preg_replace('/([^\s\(]*)(\s*)REGEXP(\s*)([^\s\)]*)/', 'REGEXP($4, $1)', $this->query);
3147
-		}
3148
-
3149
-		//
3150
-		// 3) Remise en place des textes d'origine
3151
-		//
3152
-		// Correction Antiquotes et echappements
3153
-		// ` => rien
3154
-		if (strpos($this->query, '`') !== false) {
3155
-			$this->query = str_replace('`', '', $this->query);
3156
-		}
3157
-
3158
-		$this->query = query_reinjecte_textes($this->query, $textes);
3159
-
3160
-		return $this->query;
3161
-	}
3162
-
3163
-
3164
-	/**
3165
-	 * Callback pour remplacer `DATE_` / `INTERVAL`
3166
-	 * par `DATE ... strtotime`
3167
-	 *
3168
-	 * @param array $matches Captures
3169
-	 * @return string Texte de date compris par SQLite
3170
-	 */
3171
-	public function _remplacerDateParTime($matches) {
3172
-		$op = strtoupper($matches[1] == 'ADD') ? '+' : '-';
3173
-
3174
-		return "datetime$matches[2] '$op$matches[3] $matches[4]')";
3175
-	}
3176
-
3177
-	/**
3178
-	 * Callback pour remplacer `FIELD(table,i,j,k...)`
3179
-	 * par `CASE WHEN table=i THEN n ... ELSE 0 END`
3180
-	 *
3181
-	 * @param array $matches Captures
3182
-	 * @return string Texte de liste ordonnée compris par SQLite
3183
-	 */
3184
-	public function _remplacerFieldParCase($matches) {
3185
-		$fields = substr($matches[0], 6, -1); // ne recuperer que l'interieur X de field(X)
3186
-		$t = explode(',', $fields);
3187
-		$index = array_shift($t);
3188
-
3189
-		$res = '';
3190
-		$n = 0;
3191
-		foreach ($t as $v) {
3192
-			$n++;
3193
-			$res .= "\nWHEN $index=$v THEN $n";
3194
-		}
3195
-
3196
-		return "CASE $res ELSE 0 END ";
3197
-	}
2996
+    /** @var string $query Texte de la requête */
2997
+    public $query = '';
2998
+    /** @var string $prefixe Préfixe des tables */
2999
+    public $prefixe = '';
3000
+    /** @var string $sqlite_version Version de sqlite (2 ou 3) */
3001
+    public $sqlite_version = '';
3002
+
3003
+    /** Pour les corrections à effectuer sur les requêtes : array(code=>'texte') trouvé
3004
+     *
3005
+     * @var array
3006
+     */
3007
+    public $textes = [];
3008
+
3009
+    /**
3010
+     * Constructeur
3011
+     *
3012
+     * @param string $query Requête à préparer
3013
+     * @param string $prefixe Prefixe des tables à utiliser
3014
+     * @param string $sqlite_version Version SQLite (2 ou 3)
3015
+     */
3016
+    public function __construct($query, $prefixe, $sqlite_version) {
3017
+        $this->query = $query;
3018
+        $this->prefixe = $prefixe;
3019
+        $this->sqlite_version = $sqlite_version;
3020
+    }
3021
+
3022
+    /**
3023
+     * Transformer la requete pour SQLite
3024
+     *
3025
+     * Enlève les textes, transforme la requête pour quelle soit
3026
+     * bien interprétée par SQLite, puis remet les textes
3027
+     * la fonction affecte `$this->query`
3028
+     */
3029
+    public function traduire_requete() {
3030
+        //
3031
+        // 1) Protection des textes en les remplacant par des codes
3032
+        //
3033
+        // enlever les 'textes' et initialiser avec
3034
+        list($this->query, $textes) = query_echappe_textes($this->query);
3035
+
3036
+        //
3037
+        // 2) Corrections de la requete
3038
+        //
3039
+        // Correction Create Database
3040
+        // Create Database -> requete ignoree
3041
+        if (strpos($this->query, 'CREATE DATABASE') === 0) {
3042
+            spip_log("Sqlite : requete non executee -> $this->query", 'sqlite.' . _LOG_AVERTISSEMENT);
3043
+            $this->query = 'SELECT 1';
3044
+        }
3045
+
3046
+        // Correction Insert Ignore
3047
+        // INSERT IGNORE -> insert (tout court et pas 'insert or replace')
3048
+        if (strpos($this->query, 'INSERT IGNORE') === 0) {
3049
+            spip_log("Sqlite : requete transformee -> $this->query", 'sqlite.' . _LOG_DEBUG);
3050
+            $this->query = 'INSERT ' . substr($this->query, '13');
3051
+        }
3052
+
3053
+        // Correction des dates avec INTERVAL
3054
+        // utiliser sql_date_proche() de preference
3055
+        if (strpos($this->query, 'INTERVAL') !== false) {
3056
+            $this->query = preg_replace_callback(
3057
+                '/DATE_(ADD|SUB)(.*)INTERVAL\s+(\d+)\s+([a-zA-Z]+)\)/U',
3058
+                [&$this, '_remplacerDateParTime'],
3059
+                $this->query
3060
+            );
3061
+        }
3062
+
3063
+        if (strpos($this->query, 'LEFT(') !== false) {
3064
+            $this->query = str_replace('LEFT(', '_LEFT(', $this->query);
3065
+        }
3066
+
3067
+        if (strpos($this->query, 'TIMESTAMPDIFF(') !== false) {
3068
+            $this->query = preg_replace('/TIMESTAMPDIFF\(\s*([^,]*)\s*,/Uims', "TIMESTAMPDIFF('\\1',", $this->query);
3069
+        }
3070
+
3071
+
3072
+        // Correction Using
3073
+        // USING (non reconnu en sqlite2)
3074
+        // problematique car la jointure ne se fait pas du coup.
3075
+        if (($this->sqlite_version == 2) && (strpos($this->query, 'USING') !== false)) {
3076
+            spip_log(
3077
+                "'USING (champ)' n'est pas reconnu en SQLite 2. Utilisez 'ON table1.champ = table2.champ'",
3078
+                'sqlite.' . _LOG_ERREUR
3079
+            );
3080
+            $this->query = preg_replace('/USING\s*\([^\)]*\)/', '', $this->query);
3081
+        }
3082
+
3083
+        // Correction Field
3084
+        // remplace FIELD(table,i,j,k...) par CASE WHEN table=i THEN n ... ELSE 0 END
3085
+        if (strpos($this->query, 'FIELD') !== false) {
3086
+            $this->query = preg_replace_callback(
3087
+                '/FIELD\s*\(([^\)]*)\)/',
3088
+                [&$this, '_remplacerFieldParCase'],
3089
+                $this->query
3090
+            );
3091
+        }
3092
+
3093
+        // Correction des noms de tables FROM
3094
+        // mettre les bons noms de table dans from, update, insert, replace...
3095
+        if (preg_match('/\s(SET|VALUES|WHERE|DATABASE)\s/iS', $this->query, $regs)) {
3096
+            $suite = strstr($this->query, $regs[0]);
3097
+            $this->query = substr($this->query, 0, -strlen($suite));
3098
+        } else {
3099
+            $suite = '';
3100
+        }
3101
+        $pref = ($this->prefixe) ? $this->prefixe . '_' : '';
3102
+        $this->query = preg_replace('/([,\s])spip_/S', '\1' . $pref, $this->query) . $suite;
3103
+
3104
+        // Correction zero AS x
3105
+        // pg n'aime pas 0+x AS alias, sqlite, dans le meme style,
3106
+        // n'apprecie pas du tout SELECT 0 as x ... ORDER BY x
3107
+        // il dit que x ne doit pas être un integer dans le order by !
3108
+        // on remplace du coup x par vide() dans ce cas uniquement
3109
+        //
3110
+        // apparait dans public/vertebrer.php et dans le plugin menu aussi qui genere aussi ce genre de requete via un {par num #GET{tri_num}}
3111
+        // mais est-ce encore un soucis pour sqlite en 2021 ? (ie commenter le preg_replace marche très bien en sqlite 3.28)
3112
+        if ((strpos($this->query, '0 AS') !== false)) {
3113
+            // on ne remplace que dans ORDER BY ou GROUP BY
3114
+            if (preg_match('/\s(ORDER|GROUP) BY\s/i', $this->query, $regs)) {
3115
+                $suite = strstr($this->query, $regs[0]);
3116
+                $this->query = substr($this->query, 0, -strlen($suite));
3117
+
3118
+                // on cherche les noms des x dans 0 AS x
3119
+                // on remplace dans $suite le nom par vide()
3120
+                preg_match_all('/\b0 AS\s*([^\s,]+)/', $this->query, $matches, PREG_PATTERN_ORDER);
3121
+                foreach ($matches[1] as $m) {
3122
+                    if (strpos($suite, $m) !== false) {
3123
+                        $suite = preg_replace(",\b$m\b,", 'VIDE()', $suite);
3124
+                    }
3125
+                }
3126
+                $this->query .= $suite;
3127
+            }
3128
+        }
3129
+
3130
+        // Correction possible des divisions entieres
3131
+        // Le standard SQL (lequel? ou?) semble indiquer que
3132
+        // a/b=c doit donner c entier si a et b sont entiers 4/3=1.
3133
+        // C'est ce que retournent effectivement SQL Server et SQLite
3134
+        // Ce n'est pas ce qu'applique MySQL qui retourne un reel : 4/3=1.333...
3135
+        //
3136
+        // On peut forcer la conversion en multipliant par 1.0 avant la division
3137
+        // /!\ SQLite 3.5.9 Debian/Ubuntu est victime d'un bug en plus !
3138
+        // cf. https://bugs.launchpad.net/ubuntu/+source/sqlite3/+bug/254228
3139
+        //     http://www.sqlite.org/cvstrac/tktview?tn=3202
3140
+        // (4*1.0/3) n'est pas rendu dans ce cas !
3141
+        # $this->query = str_replace('/','* 1.00 / ',$this->query);
3142
+
3143
+
3144
+        // Correction critere REGEXP, non reconnu en sqlite2
3145
+        if (($this->sqlite_version == 2) && (strpos($this->query, 'REGEXP') !== false)) {
3146
+            $this->query = preg_replace('/([^\s\(]*)(\s*)REGEXP(\s*)([^\s\)]*)/', 'REGEXP($4, $1)', $this->query);
3147
+        }
3148
+
3149
+        //
3150
+        // 3) Remise en place des textes d'origine
3151
+        //
3152
+        // Correction Antiquotes et echappements
3153
+        // ` => rien
3154
+        if (strpos($this->query, '`') !== false) {
3155
+            $this->query = str_replace('`', '', $this->query);
3156
+        }
3157
+
3158
+        $this->query = query_reinjecte_textes($this->query, $textes);
3159
+
3160
+        return $this->query;
3161
+    }
3162
+
3163
+
3164
+    /**
3165
+     * Callback pour remplacer `DATE_` / `INTERVAL`
3166
+     * par `DATE ... strtotime`
3167
+     *
3168
+     * @param array $matches Captures
3169
+     * @return string Texte de date compris par SQLite
3170
+     */
3171
+    public function _remplacerDateParTime($matches) {
3172
+        $op = strtoupper($matches[1] == 'ADD') ? '+' : '-';
3173
+
3174
+        return "datetime$matches[2] '$op$matches[3] $matches[4]')";
3175
+    }
3176
+
3177
+    /**
3178
+     * Callback pour remplacer `FIELD(table,i,j,k...)`
3179
+     * par `CASE WHEN table=i THEN n ... ELSE 0 END`
3180
+     *
3181
+     * @param array $matches Captures
3182
+     * @return string Texte de liste ordonnée compris par SQLite
3183
+     */
3184
+    public function _remplacerFieldParCase($matches) {
3185
+        $fields = substr($matches[0], 6, -1); // ne recuperer que l'interieur X de field(X)
3186
+        $t = explode(',', $fields);
3187
+        $index = array_shift($t);
3188
+
3189
+        $res = '';
3190
+        $n = 0;
3191
+        foreach ($t as $v) {
3192
+            $n++;
3193
+            $res .= "\nWHEN $index=$v THEN $n";
3194
+        }
3195
+
3196
+        return "CASE $res ELSE 0 END ";
3197
+    }
3198 3198
 }
Please login to merge, or discard this patch.