Completed
Push — master ( 204c16...802cc1 )
by cam
01:37 queued 14s
created
ecrire/inc/cvt_configurer.php 1 patch
Indentation   +147 added lines, -147 removed lines patch added patch discarded remove patch
@@ -20,7 +20,7 @@  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
 include_spip('inc/config');
@@ -32,31 +32,31 @@  discard block
 block discarded – undo
32 32
  * @return array|false
33 33
  */
34 34
 function cvtconf_formulaire_charger($flux) {
35
-	if (
36
-		$form = $flux['args']['form']
37
-		and strncmp($form, 'configurer_', 11) == 0 // un #FORMULAIRE_CONFIGURER_XXX
38
-	) {
39
-		// Pour tous les formulaires CONFIGURER, ayant une fonction charger ou pas, on teste si autorisé
40
-		include_spip('inc/autoriser');
41
-		if (!autoriser('configurer', '_' . substr($form, 11))) {
42
-			return false;
43
-		}
35
+    if (
36
+        $form = $flux['args']['form']
37
+        and strncmp($form, 'configurer_', 11) == 0 // un #FORMULAIRE_CONFIGURER_XXX
38
+    ) {
39
+        // Pour tous les formulaires CONFIGURER, ayant une fonction charger ou pas, on teste si autorisé
40
+        include_spip('inc/autoriser');
41
+        if (!autoriser('configurer', '_' . substr($form, 11))) {
42
+            return false;
43
+        }
44 44
 
45
-		// S'il n'y a pas de fonction charger(), on génère un contexte automatiquement
46
-		if (!charger_fonction('charger', "formulaires/$form/", true)) {
47
-			$flux['data'] = cvtconf_formulaires_configurer_recense($form);
48
-			$flux['data']['editable'] = true;
49
-			if (_request('var_mode') == 'configurer' and autoriser('webmestre')) {
50
-				if (!_AJAX) {
51
-					var_dump($flux['data']);
52
-				}
53
-				// reinjecter pour la trace au traitement
54
-				$flux['data']['_hidden'] = "<input type='hidden' name='var_mode' value='configurer' />";
55
-			}
56
-		}
57
-	}
45
+        // S'il n'y a pas de fonction charger(), on génère un contexte automatiquement
46
+        if (!charger_fonction('charger', "formulaires/$form/", true)) {
47
+            $flux['data'] = cvtconf_formulaires_configurer_recense($form);
48
+            $flux['data']['editable'] = true;
49
+            if (_request('var_mode') == 'configurer' and autoriser('webmestre')) {
50
+                if (!_AJAX) {
51
+                    var_dump($flux['data']);
52
+                }
53
+                // reinjecter pour la trace au traitement
54
+                $flux['data']['_hidden'] = "<input type='hidden' name='var_mode' value='configurer' />";
55
+            }
56
+        }
57
+    }
58 58
 
59
-	return $flux;
59
+    return $flux;
60 60
 }
61 61
 
62 62
 /**
@@ -66,16 +66,16 @@  discard block
 block discarded – undo
66 66
  * @return array
67 67
  */
68 68
 function cvtconf_formulaire_traiter($flux) {
69
-	if (
70
-		$form = $flux['args']['form']
71
-		and strncmp($form, 'configurer_', 11) == 0 // un #FORMULAIRE_CONFIGURER_XXX
72
-		and !charger_fonction('traiter', "formulaires/$form/", true) // sans fonction traiter()
73
-	) {
74
-		$trace = cvtconf_formulaires_configurer_enregistre($form, $flux['args']['args']);
75
-		$flux['data'] = ['message_ok' => _T('config_info_enregistree') . $trace, 'editable' => true];
76
-	}
69
+    if (
70
+        $form = $flux['args']['form']
71
+        and strncmp($form, 'configurer_', 11) == 0 // un #FORMULAIRE_CONFIGURER_XXX
72
+        and !charger_fonction('traiter', "formulaires/$form/", true) // sans fonction traiter()
73
+    ) {
74
+        $trace = cvtconf_formulaires_configurer_enregistre($form, $flux['args']['args']);
75
+        $flux['data'] = ['message_ok' => _T('config_info_enregistree') . $trace, 'editable' => true];
76
+    }
77 77
 
78
-	return $flux;
78
+    return $flux;
79 79
 }
80 80
 
81 81
 /**
@@ -91,32 +91,32 @@  discard block
 block discarded – undo
91 91
  * @return string
92 92
  */
93 93
 function cvtconf_formulaires_configurer_enregistre($form, $args) {
94
-	$valeurs = [];
95
-	// charger les valeurs
96
-	// ce qui permet de prendre en charge une fonction charger() existante
97
-	// qui prend alors la main sur l'auto detection
98
-	if ($charger_valeurs = charger_fonction('charger', "formulaires/$form/", true)) {
99
-		$valeurs = $charger_valeurs(...$args);
100
-	}
101
-	$valeurs = pipeline(
102
-		'formulaire_charger',
103
-		[
104
-			'args' => ['form' => $form, 'args' => $args, 'je_suis_poste' => false],
105
-			'data' => $valeurs
106
-		]
107
-	);
108
-	// ne pas stocker editable !
109
-	unset($valeurs['editable']);
94
+    $valeurs = [];
95
+    // charger les valeurs
96
+    // ce qui permet de prendre en charge une fonction charger() existante
97
+    // qui prend alors la main sur l'auto detection
98
+    if ($charger_valeurs = charger_fonction('charger', "formulaires/$form/", true)) {
99
+        $valeurs = $charger_valeurs(...$args);
100
+    }
101
+    $valeurs = pipeline(
102
+        'formulaire_charger',
103
+        [
104
+            'args' => ['form' => $form, 'args' => $args, 'je_suis_poste' => false],
105
+            'data' => $valeurs
106
+        ]
107
+    );
108
+    // ne pas stocker editable !
109
+    unset($valeurs['editable']);
110 110
 
111
-	// recuperer les valeurs postees
112
-	$store = [];
113
-	foreach ($valeurs as $k => $v) {
114
-		if (substr($k, 0, 1) !== '_') {
115
-			$store[$k] = _request($k);
116
-		}
117
-	}
111
+    // recuperer les valeurs postees
112
+    $store = [];
113
+    foreach ($valeurs as $k => $v) {
114
+        if (substr($k, 0, 1) !== '_') {
115
+            $store[$k] = _request($k);
116
+        }
117
+    }
118 118
 
119
-	return cvtconf_configurer_stocker($form, $valeurs, $store);
119
+    return cvtconf_configurer_stocker($form, $valeurs, $store);
120 120
 }
121 121
 
122 122
 /**
@@ -132,31 +132,31 @@  discard block
 block discarded – undo
132 132
  * @return array
133 133
  */
134 134
 function cvtconf_definir_configurer_conteneur($form, $valeurs) {
135
-	// stocker en base
136
-	// par defaut, dans un casier serialize dans spip_meta (idem CFG)
137
-	$casier = substr($form, 11);
138
-	$table = 'meta';
139
-	$prefixe = '';
140
-	$stockage = '';
135
+    // stocker en base
136
+    // par defaut, dans un casier serialize dans spip_meta (idem CFG)
137
+    $casier = substr($form, 11);
138
+    $table = 'meta';
139
+    $prefixe = '';
140
+    $stockage = '';
141 141
 
142
-	if (isset($valeurs['_meta_casier'])) {
143
-		$casier = $valeurs['_meta_casier'];
144
-	}
145
-	if (isset($valeurs['_meta_prefixe'])) {
146
-		$prefixe = $valeurs['_meta_prefixe'];
147
-	}
148
-	if (isset($valeurs['_meta_stockage'])) {
149
-		$stockage = $valeurs['_meta_stockage'] . '::';
150
-	}
142
+    if (isset($valeurs['_meta_casier'])) {
143
+        $casier = $valeurs['_meta_casier'];
144
+    }
145
+    if (isset($valeurs['_meta_prefixe'])) {
146
+        $prefixe = $valeurs['_meta_prefixe'];
147
+    }
148
+    if (isset($valeurs['_meta_stockage'])) {
149
+        $stockage = $valeurs['_meta_stockage'] . '::';
150
+    }
151 151
 
152
-	// si on indique juste une table, il faut vider les autres proprietes
153
-	// car par defaut on utilise ni casier ni prefixe dans ce cas
154
-	if (isset($valeurs['_meta_table'])) {
155
-		$table = $valeurs['_meta_table'];
156
-		$casier = ($valeurs['_meta_casier'] ?? '');
157
-	}
152
+    // si on indique juste une table, il faut vider les autres proprietes
153
+    // car par defaut on utilise ni casier ni prefixe dans ce cas
154
+    if (isset($valeurs['_meta_table'])) {
155
+        $table = $valeurs['_meta_table'];
156
+        $casier = ($valeurs['_meta_casier'] ?? '');
157
+    }
158 158
 
159
-	return [$table, $casier, $prefixe, $stockage];
159
+    return [$table, $casier, $prefixe, $stockage];
160 160
 }
161 161
 
162 162
 /**
@@ -167,48 +167,48 @@  discard block
 block discarded – undo
167 167
  * @return array
168 168
  */
169 169
 function cvtconf_formulaires_configurer_recense($form) {
170
-	$valeurs = ['editable' => ' '];
170
+    $valeurs = ['editable' => ' '];
171 171
 
172
-	// sinon cas analyse du squelette
173
-	if (
174
-		$f = find_in_path($form . '.' . _EXTENSION_SQUELETTES, 'formulaires/')
175
-		and lire_fichier($f, $contenu)
176
-	) {
177
-		for ($i = 0; $i < 2; $i++) {
178
-			// a la seconde iteration, evaluer le fond avec les valeurs deja trouvees
179
-			// permet de trouver aussi les name="#GET{truc}"
180
-			if ($i == 1) {
181
-				$contenu = recuperer_fond("formulaires/$form", $valeurs);
182
-			}
172
+    // sinon cas analyse du squelette
173
+    if (
174
+        $f = find_in_path($form . '.' . _EXTENSION_SQUELETTES, 'formulaires/')
175
+        and lire_fichier($f, $contenu)
176
+    ) {
177
+        for ($i = 0; $i < 2; $i++) {
178
+            // a la seconde iteration, evaluer le fond avec les valeurs deja trouvees
179
+            // permet de trouver aussi les name="#GET{truc}"
180
+            if ($i == 1) {
181
+                $contenu = recuperer_fond("formulaires/$form", $valeurs);
182
+            }
183 183
 
184
-			$balises = array_merge(
185
-				extraire_balises($contenu, 'input'),
186
-				extraire_balises($contenu, 'textarea'),
187
-				extraire_balises($contenu, 'select')
188
-			);
184
+            $balises = array_merge(
185
+                extraire_balises($contenu, 'input'),
186
+                extraire_balises($contenu, 'textarea'),
187
+                extraire_balises($contenu, 'select')
188
+            );
189 189
 
190
-			foreach ($balises as $b) {
191
-				if (
192
-					$n = extraire_attribut($b, 'name')
193
-					and preg_match(',^([\w\-]+)(\[\w*\])?$,', $n, $r)
194
-					and !in_array($n, ['formulaire_action', 'formulaire_action_args', 'formulaire_action_sign'])
195
-					and extraire_attribut($b, 'type') !== 'submit'
196
-				) {
197
-					$valeurs[$r[1]] = '';
198
-					// recuperer les valeurs _meta_xx qui peuvent etre fournies
199
-					// en input hidden dans le squelette
200
-					if (strncmp($r[1], '_meta_', 6) == 0) {
201
-						$valeurs[$r[1]] = extraire_attribut($b, 'value');
202
-					}
203
-				}
204
-			}
205
-		}
206
-	}
190
+            foreach ($balises as $b) {
191
+                if (
192
+                    $n = extraire_attribut($b, 'name')
193
+                    and preg_match(',^([\w\-]+)(\[\w*\])?$,', $n, $r)
194
+                    and !in_array($n, ['formulaire_action', 'formulaire_action_args', 'formulaire_action_sign'])
195
+                    and extraire_attribut($b, 'type') !== 'submit'
196
+                ) {
197
+                    $valeurs[$r[1]] = '';
198
+                    // recuperer les valeurs _meta_xx qui peuvent etre fournies
199
+                    // en input hidden dans le squelette
200
+                    if (strncmp($r[1], '_meta_', 6) == 0) {
201
+                        $valeurs[$r[1]] = extraire_attribut($b, 'value');
202
+                    }
203
+                }
204
+            }
205
+        }
206
+    }
207 207
 
208 208
 
209
-	cvtconf_configurer_lire_meta($form, $valeurs);
209
+    cvtconf_configurer_lire_meta($form, $valeurs);
210 210
 
211
-	return $valeurs;
211
+    return $valeurs;
212 212
 }
213 213
 
214 214
 /**
@@ -220,26 +220,26 @@  discard block
 block discarded – undo
220 220
  * @return string
221 221
  */
222 222
 function cvtconf_configurer_stocker($form, $valeurs, $store) {
223
-	$trace = '';
224
-	[$table, $casier, $prefixe, $stockage] = cvtconf_definir_configurer_conteneur($form, $valeurs);
225
-	// stocker en base
226
-	// par defaut, dans un casier serialize dans spip_meta (idem CFG)
227
-	if (!isset($GLOBALS[$table])) {
228
-		lire_metas($table);
229
-	}
223
+    $trace = '';
224
+    [$table, $casier, $prefixe, $stockage] = cvtconf_definir_configurer_conteneur($form, $valeurs);
225
+    // stocker en base
226
+    // par defaut, dans un casier serialize dans spip_meta (idem CFG)
227
+    if (!isset($GLOBALS[$table])) {
228
+        lire_metas($table);
229
+    }
230 230
 
231
-	$prefixe = ($prefixe ? $prefixe . '_' : '');
232
-	$table = ($table) ? "/$table/" : '';
233
-	$casier = ($casier) ? rtrim($casier, '/') . '/' : ''; // slash final, sinon rien
231
+    $prefixe = ($prefixe ? $prefixe . '_' : '');
232
+    $table = ($table) ? "/$table/" : '';
233
+    $casier = ($casier) ? rtrim($casier, '/') . '/' : ''; // slash final, sinon rien
234 234
 
235
-	foreach ($store as $k => $v) {
236
-		ecrire_config("$stockage$table$prefixe$casier$k", $v);
237
-		if (_request('var_mode') == 'configurer' and autoriser('webmestre')) {
238
-			$trace .= "<br />table $table : " . $prefixe . $k . " = $v;";
239
-		}
240
-	}
235
+    foreach ($store as $k => $v) {
236
+        ecrire_config("$stockage$table$prefixe$casier$k", $v);
237
+        if (_request('var_mode') == 'configurer' and autoriser('webmestre')) {
238
+            $trace .= "<br />table $table : " . $prefixe . $k . " = $v;";
239
+        }
240
+    }
241 241
 
242
-	return $trace;
242
+    return $trace;
243 243
 }
244 244
 
245 245
 /**
@@ -249,21 +249,21 @@  discard block
 block discarded – undo
249 249
  * @param array $valeurs
250 250
  */
251 251
 function cvtconf_configurer_lire_meta($form, &$valeurs) {
252
-	[$table, $casier, $prefixe, $stockage] = cvtconf_definir_configurer_conteneur($form, $valeurs);
252
+    [$table, $casier, $prefixe, $stockage] = cvtconf_definir_configurer_conteneur($form, $valeurs);
253 253
 
254
-	$table = ($table) ? "/$table/" : '';
255
-	$prefixe = ($prefixe ? $prefixe . '_' : '');
256
-	if ($casier) {
257
-		$meta = lire_config("$stockage$table$prefixe$casier");
258
-		$prefixe = '';
259
-	} else {
260
-		$table = rtrim($table, '/');
261
-		$meta = lire_config("$stockage$table");
262
-	}
254
+    $table = ($table) ? "/$table/" : '';
255
+    $prefixe = ($prefixe ? $prefixe . '_' : '');
256
+    if ($casier) {
257
+        $meta = lire_config("$stockage$table$prefixe$casier");
258
+        $prefixe = '';
259
+    } else {
260
+        $table = rtrim($table, '/');
261
+        $meta = lire_config("$stockage$table");
262
+    }
263 263
 
264
-	foreach ($valeurs as $k => $v) {
265
-		if (substr($k, 0, 1) !== '_') {
266
-			$valeurs[$k] = ($meta[$prefixe . $k] ?? null);
267
-		}
268
-	}
264
+    foreach ($valeurs as $k => $v) {
265
+        if (substr($k, 0, 1) !== '_') {
266
+            $valeurs[$k] = ($meta[$prefixe . $k] ?? null);
267
+        }
268
+    }
269 269
 }
Please login to merge, or discard this patch.
ecrire/inc/exporter_csv.php 1 patch
Indentation   +114 added lines, -114 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
 include_spip('inc/charsets');
@@ -32,13 +32,13 @@  discard block
 block discarded – undo
32 32
  * @return string
33 33
  */
34 34
 function exporter_csv_champ($champ) {
35
-	#$champ = str_replace("\r", "\n", $champ);
36
-	#$champ = preg_replace(",[\n]+,ms", "\n", $champ);
37
-	#$champ = str_replace("\n", ", ", $champ);
38
-	$champ = preg_replace(',[\s]+,ms', ' ', $champ);
39
-	$champ = str_replace('"', '""', $champ);
35
+    #$champ = str_replace("\r", "\n", $champ);
36
+    #$champ = preg_replace(",[\n]+,ms", "\n", $champ);
37
+    #$champ = str_replace("\n", ", ", $champ);
38
+    $champ = preg_replace(',[\s]+,ms', ' ', $champ);
39
+    $champ = str_replace('"', '""', $champ);
40 40
 
41
-	return '"' . $champ . '"';
41
+    return '"' . $champ . '"';
42 42
 }
43 43
 
44 44
 /**
@@ -55,15 +55,15 @@  discard block
 block discarded – undo
55 55
  * @return string
56 56
  */
57 57
 function exporter_csv_ligne_numerotee($nb, $ligne, $delim = ',', $importer_charset = null, ?callable $callback = null) {
58
-	if ($callback) {
59
-		$ligne = $callback($nb, $ligne, $delim, $importer_charset);
60
-	}
61
-	$output = join($delim, array_map('exporter_csv_champ', $ligne)) . "\r\n";
62
-	if ($importer_charset) {
63
-		$output = str_replace('’', '\'', $output);
64
-		$output = unicode2charset(html2unicode(charset2unicode($output)), $importer_charset);
65
-	}
66
-	return $output;
58
+    if ($callback) {
59
+        $ligne = $callback($nb, $ligne, $delim, $importer_charset);
60
+    }
61
+    $output = join($delim, array_map('exporter_csv_champ', $ligne)) . "\r\n";
62
+    if ($importer_charset) {
63
+        $output = str_replace('’', '\'', $output);
64
+        $output = unicode2charset(html2unicode(charset2unicode($output)), $importer_charset);
65
+    }
66
+    return $output;
67 67
 }
68 68
 
69 69
 /**
@@ -75,7 +75,7 @@  discard block
 block discarded – undo
75 75
  * @return string
76 76
  */
77 77
 function exporter_csv_ligne($ligne, $delim = ',', $importer_charset = null) {
78
-	return exporter_csv_ligne_numerotee(null, $ligne, $delim, $importer_charset);
78
+    return exporter_csv_ligne_numerotee(null, $ligne, $delim, $importer_charset);
79 79
 }
80 80
 
81 81
 /**
@@ -101,101 +101,101 @@  discard block
 block discarded – undo
101 101
  */
102 102
 function inc_exporter_csv_dist($titre, $resource, $options = []) {
103 103
 
104
-	// support ancienne syntaxe
105
-	// inc_exporter_csv_dist($titre, $resource, $delim = ', ', $entetes = null, $envoyer = true)
106
-	if (is_string($options)) {
107
-		$args = func_get_args();
108
-		$options = [];
109
-		foreach ([2 => 'delim', 3 => 'entetes', 4 => 'envoyer'] as $k => $option) {
110
-			if (!empty($args[$k])) {
111
-				$options[$option] = $args[$k];
112
-			}
113
-		}
114
-	}
115
-
116
-	$default_options = [
117
-		'delim' => ', ',
118
-		'entetes' => null,
119
-		'envoyer' => true,
120
-		'charset' => null,
121
-		'callback' => null,
122
-	];
123
-	$options = array_merge($default_options, $options);
124
-
125
-	$filename = preg_replace(',[^-_\w]+,', '_', translitteration(textebrut(typo($titre))));
126
-
127
-	if ($options['delim'] == 'TAB') {
128
-		$options['delim'] = "\t";
129
-	}
130
-	if (!in_array($options['delim'], [',', ';', "\t"])) {
131
-		$options['delim'] = ',';
132
-	}
133
-
134
-	$charset = $GLOBALS['meta']['charset'];
135
-	$importer_charset = null;
136
-	if ($options['delim'] == ',') {
137
-		$extension = 'csv';
138
-	} else {
139
-		$extension = 'xls';
140
-		# Excel n'accepte pas l'utf-8 ni les entites html... on transcode tout ce qu'on peut
141
-		$charset = 'iso-8859-1';
142
-	}
143
-	// mais si une option charset est explicite, elle a la priorite
144
-	if (!empty($options['charset'])) {
145
-		$charset = $options['charset'];
146
-	}
147
-
148
-	$importer_charset = (($charset === $GLOBALS['meta']['charset']) ? null : $charset);
149
-
150
-	$filename = "$filename.$extension";
151
-
152
-	$output = '';
153
-	$nb = 0;
154
-	if (!empty($options['entetes']) and is_array($options['entetes'])) {
155
-		$output = exporter_csv_ligne_numerotee($nb, $options['entetes'], $options['delim'], $importer_charset, $options['callback']);
156
-	}
157
-	// les donnees commencent toujours a la ligne 1, qu'il y ait ou non des entetes
158
-	$nb++;
159
-
160
-	if ($options['envoyer']) {
161
-		$disposition = ($options['envoyer'] === 'attachment' ? 'attachment' : 'inline');
162
-		header("Content-Type: text/comma-separated-values; charset=$charset");
163
-		header("Content-Disposition: $disposition; filename=$filename");
164
-
165
-		// Vider tous les tampons
166
-		$level = @ob_get_level();
167
-		while ($level--) {
168
-			@ob_end_flush();
169
-		}
170
-	}
171
-
172
-	// si envoyer=='attachment' on passe par un fichier temporaire
173
-	// sinon on ecrit directement sur stdout
174
-	if ($options['envoyer'] and $options['envoyer'] !== 'attachment') {
175
-		$fichier = 'php://output';
176
-	}
177
-	else {
178
-	$fichier = sous_repertoire(_DIR_CACHE, 'export') . $filename;
179
-	}
180
-
181
-	$fp = fopen($fichier, 'w');
182
-	$length = fwrite($fp, $output);
183
-
184
-	while ($row = is_array($resource) ? array_shift($resource) : sql_fetch($resource)) {
185
-		$output = exporter_csv_ligne_numerotee($nb, $row, $options['delim'], $importer_charset, $options['callback']);
186
-		$length += fwrite($fp, $output);
187
-		$nb++;
188
-	}
189
-	fclose($fp);
190
-
191
-	if ($options['envoyer']) {
192
-		if ($options['envoyer'] === 'attachment') {
193
-			header("Content-Length: $length");
194
-			readfile($fichier);
195
-		}
196
-		// si on a envoye inline, c'est deja tout bon
197
-		exit;
198
-	}
199
-
200
-	return $fichier;
104
+    // support ancienne syntaxe
105
+    // inc_exporter_csv_dist($titre, $resource, $delim = ', ', $entetes = null, $envoyer = true)
106
+    if (is_string($options)) {
107
+        $args = func_get_args();
108
+        $options = [];
109
+        foreach ([2 => 'delim', 3 => 'entetes', 4 => 'envoyer'] as $k => $option) {
110
+            if (!empty($args[$k])) {
111
+                $options[$option] = $args[$k];
112
+            }
113
+        }
114
+    }
115
+
116
+    $default_options = [
117
+        'delim' => ', ',
118
+        'entetes' => null,
119
+        'envoyer' => true,
120
+        'charset' => null,
121
+        'callback' => null,
122
+    ];
123
+    $options = array_merge($default_options, $options);
124
+
125
+    $filename = preg_replace(',[^-_\w]+,', '_', translitteration(textebrut(typo($titre))));
126
+
127
+    if ($options['delim'] == 'TAB') {
128
+        $options['delim'] = "\t";
129
+    }
130
+    if (!in_array($options['delim'], [',', ';', "\t"])) {
131
+        $options['delim'] = ',';
132
+    }
133
+
134
+    $charset = $GLOBALS['meta']['charset'];
135
+    $importer_charset = null;
136
+    if ($options['delim'] == ',') {
137
+        $extension = 'csv';
138
+    } else {
139
+        $extension = 'xls';
140
+        # Excel n'accepte pas l'utf-8 ni les entites html... on transcode tout ce qu'on peut
141
+        $charset = 'iso-8859-1';
142
+    }
143
+    // mais si une option charset est explicite, elle a la priorite
144
+    if (!empty($options['charset'])) {
145
+        $charset = $options['charset'];
146
+    }
147
+
148
+    $importer_charset = (($charset === $GLOBALS['meta']['charset']) ? null : $charset);
149
+
150
+    $filename = "$filename.$extension";
151
+
152
+    $output = '';
153
+    $nb = 0;
154
+    if (!empty($options['entetes']) and is_array($options['entetes'])) {
155
+        $output = exporter_csv_ligne_numerotee($nb, $options['entetes'], $options['delim'], $importer_charset, $options['callback']);
156
+    }
157
+    // les donnees commencent toujours a la ligne 1, qu'il y ait ou non des entetes
158
+    $nb++;
159
+
160
+    if ($options['envoyer']) {
161
+        $disposition = ($options['envoyer'] === 'attachment' ? 'attachment' : 'inline');
162
+        header("Content-Type: text/comma-separated-values; charset=$charset");
163
+        header("Content-Disposition: $disposition; filename=$filename");
164
+
165
+        // Vider tous les tampons
166
+        $level = @ob_get_level();
167
+        while ($level--) {
168
+            @ob_end_flush();
169
+        }
170
+    }
171
+
172
+    // si envoyer=='attachment' on passe par un fichier temporaire
173
+    // sinon on ecrit directement sur stdout
174
+    if ($options['envoyer'] and $options['envoyer'] !== 'attachment') {
175
+        $fichier = 'php://output';
176
+    }
177
+    else {
178
+    $fichier = sous_repertoire(_DIR_CACHE, 'export') . $filename;
179
+    }
180
+
181
+    $fp = fopen($fichier, 'w');
182
+    $length = fwrite($fp, $output);
183
+
184
+    while ($row = is_array($resource) ? array_shift($resource) : sql_fetch($resource)) {
185
+        $output = exporter_csv_ligne_numerotee($nb, $row, $options['delim'], $importer_charset, $options['callback']);
186
+        $length += fwrite($fp, $output);
187
+        $nb++;
188
+    }
189
+    fclose($fp);
190
+
191
+    if ($options['envoyer']) {
192
+        if ($options['envoyer'] === 'attachment') {
193
+            header("Content-Length: $length");
194
+            readfile($fichier);
195
+        }
196
+        // si on a envoye inline, c'est deja tout bon
197
+        exit;
198
+    }
199
+
200
+    return $fichier;
201 201
 }
Please login to merge, or discard this patch.
ecrire/base/upgrade.php 1 patch
Indentation   +284 added lines, -284 removed lines patch added patch discarded remove patch
@@ -17,17 +17,17 @@  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
 if (!defined('_UPGRADE_TIME_OUT')) {
24
-	/**
25
-	 * Durée en secondes pour relancer les scripts de mises à jour, x secondes
26
-	 * avant que la durée d'exécution du script provoque un timeout
27
-	 *
28
-	 * @var int
29
-	 **/
30
-	define('_UPGRADE_TIME_OUT', 20);
24
+    /**
25
+     * Durée en secondes pour relancer les scripts de mises à jour, x secondes
26
+     * avant que la durée d'exécution du script provoque un timeout
27
+     *
28
+     * @var int
29
+     **/
30
+    define('_UPGRADE_TIME_OUT', 20);
31 31
 }
32 32
 
33 33
 /**
@@ -50,40 +50,40 @@  discard block
 block discarded – undo
50 50
  * @return void
51 51
  */
52 52
 function base_upgrade_dist($titre = '', $reprise = '') {
53
-	if (!$titre) {
54
-		return;
55
-	} // anti-testeur automatique
56
-	if ($GLOBALS['spip_version_base'] != $GLOBALS['meta']['version_installee']) {
57
-		if (!is_numeric(_request('reinstall'))) {
58
-			include_spip('base/create');
59
-			spip_log('recree les tables eventuellement disparues', 'maj.' . _LOG_INFO_IMPORTANTE);
60
-			creer_base();
61
-		}
62
-
63
-		// quand on rentre par ici, c'est toujours une mise a jour de SPIP
64
-		// lancement de l'upgrade SPIP
65
-		$res = maj_base();
66
-
67
-		if ($res) {
68
-			// on arrete tout ici !
69
-			exit;
70
-		}
71
-	}
72
-	spip_log('Fin de mise a jour SQL. Debut m-a-j acces et config', 'maj.' . _LOG_INFO_IMPORTANTE);
73
-
74
-	// supprimer quelques fichiers temporaires qui peuvent se retrouver invalides
75
-	@spip_unlink(_CACHE_RUBRIQUES);
76
-	@spip_unlink(_CACHE_PIPELINES);
77
-	@spip_unlink(_CACHE_PLUGINS_PATH);
78
-	@spip_unlink(_CACHE_PLUGINS_OPT);
79
-	@spip_unlink(_CACHE_PLUGINS_FCT);
80
-	@spip_unlink(_CACHE_CHEMIN);
81
-	@spip_unlink(_DIR_TMP . 'plugin_xml_cache.gz');
82
-
83
-	include_spip('inc/auth');
84
-	auth_synchroniser_distant();
85
-	$config = charger_fonction('config', 'inc');
86
-	$config();
53
+    if (!$titre) {
54
+        return;
55
+    } // anti-testeur automatique
56
+    if ($GLOBALS['spip_version_base'] != $GLOBALS['meta']['version_installee']) {
57
+        if (!is_numeric(_request('reinstall'))) {
58
+            include_spip('base/create');
59
+            spip_log('recree les tables eventuellement disparues', 'maj.' . _LOG_INFO_IMPORTANTE);
60
+            creer_base();
61
+        }
62
+
63
+        // quand on rentre par ici, c'est toujours une mise a jour de SPIP
64
+        // lancement de l'upgrade SPIP
65
+        $res = maj_base();
66
+
67
+        if ($res) {
68
+            // on arrete tout ici !
69
+            exit;
70
+        }
71
+    }
72
+    spip_log('Fin de mise a jour SQL. Debut m-a-j acces et config', 'maj.' . _LOG_INFO_IMPORTANTE);
73
+
74
+    // supprimer quelques fichiers temporaires qui peuvent se retrouver invalides
75
+    @spip_unlink(_CACHE_RUBRIQUES);
76
+    @spip_unlink(_CACHE_PIPELINES);
77
+    @spip_unlink(_CACHE_PLUGINS_PATH);
78
+    @spip_unlink(_CACHE_PLUGINS_OPT);
79
+    @spip_unlink(_CACHE_PLUGINS_FCT);
80
+    @spip_unlink(_CACHE_CHEMIN);
81
+    @spip_unlink(_DIR_TMP . 'plugin_xml_cache.gz');
82
+
83
+    include_spip('inc/auth');
84
+    auth_synchroniser_distant();
85
+    $config = charger_fonction('config', 'inc');
86
+    $config();
87 87
 }
88 88
 
89 89
 /**
@@ -114,51 +114,51 @@  discard block
 block discarded – undo
114 114
  */
115 115
 function maj_base($version_cible = 0, $redirect = '', $debut_page = true) {
116 116
 
117
-	$version_installee = $GLOBALS['meta']['version_installee'] ?? null;
118
-
119
-	spip_log(
120
-		"Version anterieure: $version_installee. Courante: " . $GLOBALS['spip_version_base'],
121
-		'maj.' . _LOG_INFO_IMPORTANTE
122
-	);
123
-	if (!$version_installee or ($GLOBALS['spip_version_base'] < $version_installee)) {
124
-		sql_replace(
125
-			'spip_meta',
126
-			[
127
-				'nom' => 'version_installee',
128
-				'valeur' => $GLOBALS['spip_version_base'],
129
-				'impt' => 'non'
130
-			]
131
-		);
132
-		return false;
133
-	}
134
-	if (!upgrade_test()) {
135
-		return true;
136
-	}
137
-
138
-	$cible = ($version_cible ?: $GLOBALS['spip_version_base']);
139
-
140
-	if ($version_installee < 2021_01_01_00) {
141
-		include_spip('maj/legacy/v21');
142
-		include_spip('maj/legacy/v30');
143
-		include_spip('maj/legacy/v31');
144
-		include_spip('maj/legacy/v32');
145
-		include_spip('maj/legacy/v40');
146
-	}
147
-
148
-	include_spip('maj/2021');
149
-
150
-	ksort($GLOBALS['maj']);
151
-	$res = maj_while($version_installee, $cible, $GLOBALS['maj'], 'version_installee', 'meta', $redirect, $debut_page);
152
-	if ($res) {
153
-		if (!is_array($res)) {
154
-			spip_log("Pb d'acces SQL a la mise a jour", 'maj.' . _LOG_ERREUR);
155
-		} else {
156
-			echo _T('avis_operation_echec') . ' ' . join(' ', $res);
157
-			echo install_fin_html();
158
-		}
159
-	}
160
-
161
-	return $res;
117
+    $version_installee = $GLOBALS['meta']['version_installee'] ?? null;
118
+
119
+    spip_log(
120
+        "Version anterieure: $version_installee. Courante: " . $GLOBALS['spip_version_base'],
121
+        'maj.' . _LOG_INFO_IMPORTANTE
122
+    );
123
+    if (!$version_installee or ($GLOBALS['spip_version_base'] < $version_installee)) {
124
+        sql_replace(
125
+            'spip_meta',
126
+            [
127
+                'nom' => 'version_installee',
128
+                'valeur' => $GLOBALS['spip_version_base'],
129
+                'impt' => 'non'
130
+            ]
131
+        );
132
+        return false;
133
+    }
134
+    if (!upgrade_test()) {
135
+        return true;
136
+    }
137
+
138
+    $cible = ($version_cible ?: $GLOBALS['spip_version_base']);
139
+
140
+    if ($version_installee < 2021_01_01_00) {
141
+        include_spip('maj/legacy/v21');
142
+        include_spip('maj/legacy/v30');
143
+        include_spip('maj/legacy/v31');
144
+        include_spip('maj/legacy/v32');
145
+        include_spip('maj/legacy/v40');
146
+    }
147
+
148
+    include_spip('maj/2021');
149
+
150
+    ksort($GLOBALS['maj']);
151
+    $res = maj_while($version_installee, $cible, $GLOBALS['maj'], 'version_installee', 'meta', $redirect, $debut_page);
152
+    if ($res) {
153
+        if (!is_array($res)) {
154
+            spip_log("Pb d'acces SQL a la mise a jour", 'maj.' . _LOG_ERREUR);
155
+        } else {
156
+            echo _T('avis_operation_echec') . ' ' . join(' ', $res);
157
+            echo install_fin_html();
158
+        }
159
+    }
160
+
161
+    return $res;
162 162
 }
163 163
 
164 164
 /**
@@ -200,53 +200,53 @@  discard block
 block discarded – undo
200 200
  */
201 201
 function maj_plugin($nom_meta_base_version, $version_cible, $maj, $table_meta = 'meta') {
202 202
 
203
-	if ($table_meta !== 'meta') {
204
-		installer_table_meta($table_meta);
205
-	}
206
-
207
-	$current_version = null;
208
-
209
-	if (
210
-		(!isset($GLOBALS[$table_meta][$nom_meta_base_version]))
211
-		|| (!spip_version_compare($current_version = $GLOBALS[$table_meta][$nom_meta_base_version], $version_cible, '='))
212
-	) {
213
-		// $maj['create'] contient les directives propres a la premiere creation de base
214
-		// c'est une operation derogatoire qui fait aboutir directement dans la version_cible
215
-		if (isset($maj['create'])) {
216
-			if (!isset($GLOBALS[$table_meta][$nom_meta_base_version])) {
217
-				// installation : on ne fait que l'operation create
218
-				$maj = ['init' => $maj['create']];
219
-				// et on lui ajoute un appel a inc/config
220
-				// pour creer les metas par defaut
221
-				$config = charger_fonction('config', 'inc');
222
-				$maj[$version_cible] = [[$config]];
223
-			}
224
-			// dans tous les cas enlever cet index du tableau
225
-			unset($maj['create']);
226
-		}
227
-		// si init, deja dans le bon ordre
228
-		if (!isset($maj['init'])) {
229
-			include_spip('inc/plugin'); // pour spip_version_compare
230
-			uksort($maj, 'spip_version_compare');
231
-		}
232
-
233
-		// la redirection se fait par defaut sur la page d'administration des plugins
234
-		// sauf lorsque nous sommes sur l'installation de SPIP
235
-		// ou define _REDIRECT_MAJ_PLUGIN
236
-		$redirect = (defined('_REDIRECT_MAJ_PLUGIN') ? _REDIRECT_MAJ_PLUGIN : generer_url_ecrire('admin_plugin'));
237
-		if (defined('_ECRIRE_INSTALL')) {
238
-			$redirect = parametre_url(generer_url_ecrire('install'), 'etape', _request('etape'));
239
-		}
240
-
241
-		$res = maj_while($current_version, $version_cible, $maj, $nom_meta_base_version, $table_meta, $redirect);
242
-		if ($res) {
243
-			if (!is_array($res)) {
244
-				spip_log("Pb d'acces SQL a la mise a jour", 'maj.' . _LOG_ERREUR);
245
-			} else {
246
-				echo '<p>' . _T('avis_operation_echec') . ' ' . join(' ', $res) . '</p>';
247
-			}
248
-		}
249
-	}
203
+    if ($table_meta !== 'meta') {
204
+        installer_table_meta($table_meta);
205
+    }
206
+
207
+    $current_version = null;
208
+
209
+    if (
210
+        (!isset($GLOBALS[$table_meta][$nom_meta_base_version]))
211
+        || (!spip_version_compare($current_version = $GLOBALS[$table_meta][$nom_meta_base_version], $version_cible, '='))
212
+    ) {
213
+        // $maj['create'] contient les directives propres a la premiere creation de base
214
+        // c'est une operation derogatoire qui fait aboutir directement dans la version_cible
215
+        if (isset($maj['create'])) {
216
+            if (!isset($GLOBALS[$table_meta][$nom_meta_base_version])) {
217
+                // installation : on ne fait que l'operation create
218
+                $maj = ['init' => $maj['create']];
219
+                // et on lui ajoute un appel a inc/config
220
+                // pour creer les metas par defaut
221
+                $config = charger_fonction('config', 'inc');
222
+                $maj[$version_cible] = [[$config]];
223
+            }
224
+            // dans tous les cas enlever cet index du tableau
225
+            unset($maj['create']);
226
+        }
227
+        // si init, deja dans le bon ordre
228
+        if (!isset($maj['init'])) {
229
+            include_spip('inc/plugin'); // pour spip_version_compare
230
+            uksort($maj, 'spip_version_compare');
231
+        }
232
+
233
+        // la redirection se fait par defaut sur la page d'administration des plugins
234
+        // sauf lorsque nous sommes sur l'installation de SPIP
235
+        // ou define _REDIRECT_MAJ_PLUGIN
236
+        $redirect = (defined('_REDIRECT_MAJ_PLUGIN') ? _REDIRECT_MAJ_PLUGIN : generer_url_ecrire('admin_plugin'));
237
+        if (defined('_ECRIRE_INSTALL')) {
238
+            $redirect = parametre_url(generer_url_ecrire('install'), 'etape', _request('etape'));
239
+        }
240
+
241
+        $res = maj_while($current_version, $version_cible, $maj, $nom_meta_base_version, $table_meta, $redirect);
242
+        if ($res) {
243
+            if (!is_array($res)) {
244
+                spip_log("Pb d'acces SQL a la mise a jour", 'maj.' . _LOG_ERREUR);
245
+            } else {
246
+                echo '<p>' . _T('avis_operation_echec') . ' ' . join(' ', $res) . '</p>';
247
+            }
248
+        }
249
+    }
250 250
 }
251 251
 
252 252
 /**
@@ -263,17 +263,17 @@  discard block
 block discarded – undo
263 263
  * @return void
264 264
  */
265 265
 function relance_maj($meta, $table, $redirect = '') {
266
-	include_spip('inc/headers');
267
-	if (!$redirect) {
268
-		// recuperer la valeur installee en cours
269
-		// on la tronque numeriquement, elle ne sert pas reellement
270
-		// sauf pour verifier que ce n'est pas oui ou non
271
-		// sinon is_numeric va echouer sur un numero de version 1.2.3
272
-		$installee = intval($GLOBALS[$table][$meta]);
273
-		$redirect = generer_url_ecrire('upgrade', "reinstall=$installee&meta=$meta&table=$table", true);
274
-	}
275
-	echo redirige_formulaire($redirect);
276
-	exit();
266
+    include_spip('inc/headers');
267
+    if (!$redirect) {
268
+        // recuperer la valeur installee en cours
269
+        // on la tronque numeriquement, elle ne sert pas reellement
270
+        // sauf pour verifier que ce n'est pas oui ou non
271
+        // sinon is_numeric va echouer sur un numero de version 1.2.3
272
+        $installee = intval($GLOBALS[$table][$meta]);
273
+        $redirect = generer_url_ecrire('upgrade', "reinstall=$installee&meta=$meta&table=$table", true);
274
+    }
275
+    echo redirige_formulaire($redirect);
276
+    exit();
277 277
 }
278 278
 
279 279
 /**
@@ -286,28 +286,28 @@  discard block
 block discarded – undo
286 286
  * @return void
287 287
  */
288 288
 function maj_debut_page($installee, $meta, $table) {
289
-	static $done = false;
290
-	if ($done) {
291
-		return;
292
-	}
293
-	include_spip('inc/minipres');
294
-	if (function_exists('ini_set')) {
295
-		@ini_set('zlib.output_compression', '0'); // pour permettre l'affichage au fur et a mesure
296
-	}
297
-	$timeout = _UPGRADE_TIME_OUT * 2;
298
-	$titre = _T('titre_page_upgrade');
299
-	$balise_img = charger_filtre('balise_img');
300
-	$titre .= $balise_img(chemin_image('loader.svg'), '', 'loader');
301
-	echo(install_debut_html($titre));
302
-	// script de rechargement auto sur timeout
303
-	$redirect = generer_url_ecrire('upgrade', "reinstall=$installee&meta=$meta&table=$table", true);
304
-	echo http_script("window.setTimeout('location.href=\"" . $redirect . "\";'," . ($timeout * 1000) . ')');
305
-	echo "<div style='text-align: left'>\n";
306
-	if (ob_get_level()) {
307
-		ob_flush();
308
-	}
309
-	flush();
310
-	$done = true;
289
+    static $done = false;
290
+    if ($done) {
291
+        return;
292
+    }
293
+    include_spip('inc/minipres');
294
+    if (function_exists('ini_set')) {
295
+        @ini_set('zlib.output_compression', '0'); // pour permettre l'affichage au fur et a mesure
296
+    }
297
+    $timeout = _UPGRADE_TIME_OUT * 2;
298
+    $titre = _T('titre_page_upgrade');
299
+    $balise_img = charger_filtre('balise_img');
300
+    $titre .= $balise_img(chemin_image('loader.svg'), '', 'loader');
301
+    echo(install_debut_html($titre));
302
+    // script de rechargement auto sur timeout
303
+    $redirect = generer_url_ecrire('upgrade', "reinstall=$installee&meta=$meta&table=$table", true);
304
+    echo http_script("window.setTimeout('location.href=\"" . $redirect . "\";'," . ($timeout * 1000) . ')');
305
+    echo "<div style='text-align: left'>\n";
306
+    if (ob_get_level()) {
307
+        ob_flush();
308
+    }
309
+    flush();
310
+    $done = true;
311 311
 }
312 312
 
313 313
 
@@ -351,64 +351,64 @@  discard block
 block discarded – undo
351 351
  *    - tableau vide sinon.
352 352
  */
353 353
 function maj_while($installee, $cible, $maj, $meta = '', $table = 'meta', $redirect = '', $debut_page = false) {
354
-	# inclusions pour que les procedures d'upgrade disposent des fonctions de base
355
-	include_spip('base/create');
356
-	include_spip('base/abstract_sql');
357
-	$trouver_table = charger_fonction('trouver_table', 'base');
358
-	include_spip('inc/plugin'); // pour spip_version_compare
359
-	$n = 0;
360
-	$time = time();
361
-
362
-	if (!defined('_TIME_OUT')) {
363
-		/**
364
-		 * Définir le timeout qui peut-être utilisé dans les fonctions
365
-		 * de mises à jour qui durent trop longtemps
366
-		 *
367
-		 * À utiliser tel que : `if (time() >= _TIME_OUT)`
368
-		 *
369
-		 * @var int
370
-		 */
371
-		define('_TIME_OUT', $time + _UPGRADE_TIME_OUT);
372
-	}
373
-
374
-	foreach ($maj as $v => $operations) {
375
-		// si une maj pour cette version
376
-		if (
377
-			$v == 'init' or
378
-			(spip_version_compare($v, $installee, '>')
379
-				and spip_version_compare($v, $cible, '<='))
380
-		) {
381
-			if ($debut_page) {
382
-				maj_debut_page($v, $meta, $table);
383
-			}
384
-			echo "MAJ $v";
385
-			$etape = serie_alter($v, $operations, $meta, $table, $redirect);
386
-			$trouver_table(''); // vider le cache des descriptions de table
387
-			# echec sur une etape en cours ?
388
-			# on sort
389
-			if ($etape) {
390
-				return [$v, $etape];
391
-			}
392
-			$n = time() - $time;
393
-			spip_log("$table $meta: $v en $n secondes", 'maj.' . _LOG_INFO_IMPORTANTE);
394
-			if ($meta) {
395
-				ecrire_meta($meta, $installee = $v, 'oui', $table);
396
-			}
397
-			echo (_IS_CLI ? "\n" : '<br />');
398
-		}
399
-		if (time() >= _TIME_OUT) {
400
-			relance_maj($meta, $table, $redirect);
401
-		}
402
-	}
403
-	$trouver_table(''); // vider le cache des descriptions de table
404
-	// indispensable pour les chgt de versions qui n'ecrivent pas en base
405
-	// tant pis pour la redondance eventuelle avec ci-dessus
406
-	if ($meta) {
407
-		ecrire_meta($meta, $cible, 'oui', $table);
408
-	}
409
-	spip_log("MAJ terminee. $meta: $installee", 'maj.' . _LOG_INFO_IMPORTANTE);
410
-
411
-	return [];
354
+    # inclusions pour que les procedures d'upgrade disposent des fonctions de base
355
+    include_spip('base/create');
356
+    include_spip('base/abstract_sql');
357
+    $trouver_table = charger_fonction('trouver_table', 'base');
358
+    include_spip('inc/plugin'); // pour spip_version_compare
359
+    $n = 0;
360
+    $time = time();
361
+
362
+    if (!defined('_TIME_OUT')) {
363
+        /**
364
+         * Définir le timeout qui peut-être utilisé dans les fonctions
365
+         * de mises à jour qui durent trop longtemps
366
+         *
367
+         * À utiliser tel que : `if (time() >= _TIME_OUT)`
368
+         *
369
+         * @var int
370
+         */
371
+        define('_TIME_OUT', $time + _UPGRADE_TIME_OUT);
372
+    }
373
+
374
+    foreach ($maj as $v => $operations) {
375
+        // si une maj pour cette version
376
+        if (
377
+            $v == 'init' or
378
+            (spip_version_compare($v, $installee, '>')
379
+                and spip_version_compare($v, $cible, '<='))
380
+        ) {
381
+            if ($debut_page) {
382
+                maj_debut_page($v, $meta, $table);
383
+            }
384
+            echo "MAJ $v";
385
+            $etape = serie_alter($v, $operations, $meta, $table, $redirect);
386
+            $trouver_table(''); // vider le cache des descriptions de table
387
+            # echec sur une etape en cours ?
388
+            # on sort
389
+            if ($etape) {
390
+                return [$v, $etape];
391
+            }
392
+            $n = time() - $time;
393
+            spip_log("$table $meta: $v en $n secondes", 'maj.' . _LOG_INFO_IMPORTANTE);
394
+            if ($meta) {
395
+                ecrire_meta($meta, $installee = $v, 'oui', $table);
396
+            }
397
+            echo (_IS_CLI ? "\n" : '<br />');
398
+        }
399
+        if (time() >= _TIME_OUT) {
400
+            relance_maj($meta, $table, $redirect);
401
+        }
402
+    }
403
+    $trouver_table(''); // vider le cache des descriptions de table
404
+    // indispensable pour les chgt de versions qui n'ecrivent pas en base
405
+    // tant pis pour la redondance eventuelle avec ci-dessus
406
+    if ($meta) {
407
+        ecrire_meta($meta, $cible, 'oui', $table);
408
+    }
409
+    spip_log("MAJ terminee. $meta: $installee", 'maj.' . _LOG_INFO_IMPORTANTE);
410
+
411
+    return [];
412 412
 }
413 413
 
414 414
 /**
@@ -431,53 +431,53 @@  discard block
 block discarded – undo
431 431
  * @return int
432 432
  */
433 433
 function serie_alter($serie, $q = [], $meta = '', $table = 'meta', $redirect = '') {
434
-	$meta2 = $meta . '_maj_' . $serie;
435
-	$etape = 0;
436
-	if (isset($GLOBALS[$table][$meta2])) {
437
-		$etape = intval($GLOBALS[$table][$meta2]);
438
-	}
439
-	foreach ($q as $i => $r) {
440
-		if ($i >= $etape) {
441
-			$msg = "maj $table $meta2 etape $i";
442
-			if (
443
-				is_array($r)
444
-				and function_exists($f = array_shift($r))
445
-			) {
446
-				// note: $r (arguments de la fonction $f) peut avoir des données tabulaires
447
-				spip_log("$msg: $f " . @join(',', $r), 'maj.' . _LOG_INFO_IMPORTANTE);
448
-				// pour les fonctions atomiques sql_xx
449
-				// on enregistre le meta avant de lancer la fonction,
450
-				// de maniere a eviter de boucler sur timeout
451
-				// mais pour les fonctions complexes,
452
-				// il faut les rejouer jusqu'a achevement.
453
-				// C'est a elle d'assurer qu'elles progressent a chaque rappel
454
-				if (strncmp($f, 'sql_', 4) == 0) {
455
-					ecrire_meta($meta2, $i + 1, 'non', $table);
456
-				}
457
-				echo (_IS_CLI ? '.' : " <span title='$i'>.</span>");
458
-				$f(...$r);
459
-				// si temps imparti depasse, on relance sans ecrire en meta
460
-				// car on est peut etre sorti sur timeout si c'est une fonction longue
461
-				if (time() >= _TIME_OUT) {
462
-					relance_maj($meta, $table, $redirect);
463
-				}
464
-				ecrire_meta($meta2, $i + 1, 'non', $table);
465
-				spip_log("$meta2: ok", 'maj.' . _LOG_INFO_IMPORTANTE);
466
-			} else {
467
-				if (!is_array($r)) {
468
-					spip_log("maj $i format incorrect", 'maj.' . _LOG_ERREUR);
469
-				} else {
470
-					spip_log("maj $i fonction $f non definie", 'maj.' . _LOG_ERREUR);
471
-				}
472
-				// en cas d'erreur serieuse, on s'arrete
473
-				// mais on permet de passer par dessus en rechargeant la page.
474
-				return $i + 1;
475
-			}
476
-		}
477
-	}
478
-	effacer_meta($meta2, $table);
479
-
480
-	return 0;
434
+    $meta2 = $meta . '_maj_' . $serie;
435
+    $etape = 0;
436
+    if (isset($GLOBALS[$table][$meta2])) {
437
+        $etape = intval($GLOBALS[$table][$meta2]);
438
+    }
439
+    foreach ($q as $i => $r) {
440
+        if ($i >= $etape) {
441
+            $msg = "maj $table $meta2 etape $i";
442
+            if (
443
+                is_array($r)
444
+                and function_exists($f = array_shift($r))
445
+            ) {
446
+                // note: $r (arguments de la fonction $f) peut avoir des données tabulaires
447
+                spip_log("$msg: $f " . @join(',', $r), 'maj.' . _LOG_INFO_IMPORTANTE);
448
+                // pour les fonctions atomiques sql_xx
449
+                // on enregistre le meta avant de lancer la fonction,
450
+                // de maniere a eviter de boucler sur timeout
451
+                // mais pour les fonctions complexes,
452
+                // il faut les rejouer jusqu'a achevement.
453
+                // C'est a elle d'assurer qu'elles progressent a chaque rappel
454
+                if (strncmp($f, 'sql_', 4) == 0) {
455
+                    ecrire_meta($meta2, $i + 1, 'non', $table);
456
+                }
457
+                echo (_IS_CLI ? '.' : " <span title='$i'>.</span>");
458
+                $f(...$r);
459
+                // si temps imparti depasse, on relance sans ecrire en meta
460
+                // car on est peut etre sorti sur timeout si c'est une fonction longue
461
+                if (time() >= _TIME_OUT) {
462
+                    relance_maj($meta, $table, $redirect);
463
+                }
464
+                ecrire_meta($meta2, $i + 1, 'non', $table);
465
+                spip_log("$meta2: ok", 'maj.' . _LOG_INFO_IMPORTANTE);
466
+            } else {
467
+                if (!is_array($r)) {
468
+                    spip_log("maj $i format incorrect", 'maj.' . _LOG_ERREUR);
469
+                } else {
470
+                    spip_log("maj $i fonction $f non definie", 'maj.' . _LOG_ERREUR);
471
+                }
472
+                // en cas d'erreur serieuse, on s'arrete
473
+                // mais on permet de passer par dessus en rechargeant la page.
474
+                return $i + 1;
475
+            }
476
+        }
477
+    }
478
+    effacer_meta($meta2, $table);
479
+
480
+    return 0;
481 481
 }
482 482
 
483 483
 /**
@@ -486,16 +486,16 @@  discard block
 block discarded – undo
486 486
  * @return bool True si possible.
487 487
  **/
488 488
 function upgrade_test() {
489
-	sql_drop_table('spip_test', true);
490
-	sql_create('spip_test', ['a' => 'int']);
491
-	sql_alter('TABLE spip_test ADD b INT');
492
-	sql_insertq('spip_test', ['b' => 1], ['field' => ['b' => 'int']]);
493
-	$result = sql_select('b', 'spip_test');
494
-	// ne pas garder le resultat de la requete sinon sqlite3
495
-	// ne peut pas supprimer la table spip_test lors du sql_alter qui suit
496
-	// car cette table serait alors 'verouillee'
497
-	$result = $result ? true : false;
498
-	sql_alter('TABLE spip_test DROP b');
499
-
500
-	return $result;
489
+    sql_drop_table('spip_test', true);
490
+    sql_create('spip_test', ['a' => 'int']);
491
+    sql_alter('TABLE spip_test ADD b INT');
492
+    sql_insertq('spip_test', ['b' => 1], ['field' => ['b' => 'int']]);
493
+    $result = sql_select('b', 'spip_test');
494
+    // ne pas garder le resultat de la requete sinon sqlite3
495
+    // ne peut pas supprimer la table spip_test lors du sql_alter qui suit
496
+    // car cette table serait alors 'verouillee'
497
+    $result = $result ? true : false;
498
+    sql_alter('TABLE spip_test DROP b');
499
+
500
+    return $result;
501 501
 }
Please login to merge, or discard this patch.
ecrire/xml/sax.php 1 patch
Indentation   +257 added lines, -257 removed lines patch added patch discarded remove patch
@@ -11,7 +11,7 @@  discard block
 block discarded – undo
11 11
 \***************************************************************************/
12 12
 
13 13
 if (!defined('_ECRIRE_INC_VERSION')) {
14
-	return;
14
+    return;
15 15
 }
16 16
 
17 17
 include_spip('inc/charsets');
@@ -24,222 +24,222 @@  discard block
 block discarded – undo
24 24
  * @return string
25 25
  */
26 26
 function xml_entites_html($texte) {
27
-	if (
28
-		!is_string($texte) or !$texte
29
-		or strpbrk($texte, "&\"'<>") == false
30
-	) {
31
-		return $texte;
32
-	}
33
-
34
-	if (!function_exists('spip_htmlspecialchars')) {
35
-		include_spip('inc/filtres_mini');
36
-	}
37
-	$texte = spip_htmlspecialchars($texte, ENT_QUOTES);
38
-
39
-	return $texte;
27
+    if (
28
+        !is_string($texte) or !$texte
29
+        or strpbrk($texte, "&\"'<>") == false
30
+    ) {
31
+        return $texte;
32
+    }
33
+
34
+    if (!function_exists('spip_htmlspecialchars')) {
35
+        include_spip('inc/filtres_mini');
36
+    }
37
+    $texte = spip_htmlspecialchars($texte, ENT_QUOTES);
38
+
39
+    return $texte;
40 40
 }
41 41
 
42 42
 function xml_debutElement($phraseur, $name, $attrs) {
43
-	$depth = $phraseur->depth;
44
-
45
-	$t = $phraseur->ouvrant[$depth] ?? ' ';
46
-	// espace initial signifie: deja integree au resultat
47
-	if ($t[0] != ' ') {
48
-		$phraseur->res .= '<' . $t . '>';
49
-		$phraseur->ouvrant[$depth] = ' ' . $t;
50
-	}
51
-	$t = $phraseur->contenu[$depth];
52
-	// n'indenter que s'il y a un separateur avant
53
-	$phraseur->res .= preg_replace("/[\n\t ]+$/", "\n$depth", $t);
54
-	$phraseur->contenu[$depth] = '';
55
-	$att = '';
56
-	$sep = ' ';
57
-	foreach ($attrs as $k => $v) {
58
-		$delim = strpos($v, "'") === false ? "'" : '"';
59
-		$val = xml_entites_html($v);
60
-		$att .= $sep . $k . '=' . $delim
61
-			. ($delim !== '"' ? str_replace('&quot;', '"', $val) : $val)
62
-			. $delim;
63
-		$sep = "\n $depth";
64
-	}
65
-	$phraseur->depth .= '  ';
66
-	$phraseur->contenu[$phraseur->depth] = '';
67
-	$phraseur->ouvrant[$phraseur->depth] = $name . $att;
68
-	$phraseur->reperes[$phraseur->depth] = xml_get_current_line_number($phraseur->sax);
43
+    $depth = $phraseur->depth;
44
+
45
+    $t = $phraseur->ouvrant[$depth] ?? ' ';
46
+    // espace initial signifie: deja integree au resultat
47
+    if ($t[0] != ' ') {
48
+        $phraseur->res .= '<' . $t . '>';
49
+        $phraseur->ouvrant[$depth] = ' ' . $t;
50
+    }
51
+    $t = $phraseur->contenu[$depth];
52
+    // n'indenter que s'il y a un separateur avant
53
+    $phraseur->res .= preg_replace("/[\n\t ]+$/", "\n$depth", $t);
54
+    $phraseur->contenu[$depth] = '';
55
+    $att = '';
56
+    $sep = ' ';
57
+    foreach ($attrs as $k => $v) {
58
+        $delim = strpos($v, "'") === false ? "'" : '"';
59
+        $val = xml_entites_html($v);
60
+        $att .= $sep . $k . '=' . $delim
61
+            . ($delim !== '"' ? str_replace('&quot;', '"', $val) : $val)
62
+            . $delim;
63
+        $sep = "\n $depth";
64
+    }
65
+    $phraseur->depth .= '  ';
66
+    $phraseur->contenu[$phraseur->depth] = '';
67
+    $phraseur->ouvrant[$phraseur->depth] = $name . $att;
68
+    $phraseur->reperes[$phraseur->depth] = xml_get_current_line_number($phraseur->sax);
69 69
 }
70 70
 
71 71
 function xml_finElement($phraseur, $name, $fusion_bal = false) {
72
-	$ouv = $phraseur->ouvrant[$phraseur->depth];
73
-
74
-	if ($ouv[0] != ' ') {
75
-		$phraseur->ouvrant[$phraseur->depth] = ' ' . $ouv;
76
-	} else {
77
-		$ouv = '';
78
-	}
79
-	$t = $phraseur->contenu[$phraseur->depth];
80
-	$phraseur->depth = substr($phraseur->depth, 2);
81
-	$t = preg_replace("/[\n\t ]+$/", "\n" . $phraseur->depth, $t);
82
-
83
-	// fusion <balise></balise> en <balise />.
84
-	// ATTENTION,  certains clients http croient que fusion ==> pas d'atttributs
85
-	// en particulier pour les balises Script et A.
86
-	// en presence d'attributs ne le faire que si la DTD est dispo et d'accord
87
-	// (param fusion_bal)
88
-
89
-	if ($t || (($ouv != $name) and !$fusion_bal)) {
90
-		$phraseur->res .= ($ouv ? ('<' . $ouv . '>') : '') . $t . '</' . $name . '>';
91
-	} else {
92
-		$phraseur->res .= ($ouv ? ('<' . $ouv . ' />') : ('</' . $name . '>'));
93
-	}
72
+    $ouv = $phraseur->ouvrant[$phraseur->depth];
73
+
74
+    if ($ouv[0] != ' ') {
75
+        $phraseur->ouvrant[$phraseur->depth] = ' ' . $ouv;
76
+    } else {
77
+        $ouv = '';
78
+    }
79
+    $t = $phraseur->contenu[$phraseur->depth];
80
+    $phraseur->depth = substr($phraseur->depth, 2);
81
+    $t = preg_replace("/[\n\t ]+$/", "\n" . $phraseur->depth, $t);
82
+
83
+    // fusion <balise></balise> en <balise />.
84
+    // ATTENTION,  certains clients http croient que fusion ==> pas d'atttributs
85
+    // en particulier pour les balises Script et A.
86
+    // en presence d'attributs ne le faire que si la DTD est dispo et d'accord
87
+    // (param fusion_bal)
88
+
89
+    if ($t || (($ouv != $name) and !$fusion_bal)) {
90
+        $phraseur->res .= ($ouv ? ('<' . $ouv . '>') : '') . $t . '</' . $name . '>';
91
+    } else {
92
+        $phraseur->res .= ($ouv ? ('<' . $ouv . ' />') : ('</' . $name . '>'));
93
+    }
94 94
 }
95 95
 
96 96
 function xml_textElement($phraseur, $data) {
97
-	$depth = $phraseur->depth;
98
-	$phraseur->contenu[$depth] .= preg_match('/^script/', $phraseur->ouvrant[$depth])
99
-		? $data
100
-		: xml_entites_html($data);
97
+    $depth = $phraseur->depth;
98
+    $phraseur->contenu[$depth] .= preg_match('/^script/', $phraseur->ouvrant[$depth])
99
+        ? $data
100
+        : xml_entites_html($data);
101 101
 }
102 102
 
103 103
 function xml_piElement($phraseur, $target, $data) {
104
-	$depth = $phraseur->depth;
105
-
106
-	if (strtolower($target) != 'php') {
107
-		$phraseur->contenu[$depth] .= $data;
108
-	} else {
109
-		ob_start();
110
-		eval($data);
111
-		$data = ob_get_contents();
112
-		ob_end_clean();
113
-		$phraseur->contenu[$depth] .= $data;
114
-	}
104
+    $depth = $phraseur->depth;
105
+
106
+    if (strtolower($target) != 'php') {
107
+        $phraseur->contenu[$depth] .= $data;
108
+    } else {
109
+        ob_start();
110
+        eval($data);
111
+        $data = ob_get_contents();
112
+        ob_end_clean();
113
+        $phraseur->contenu[$depth] .= $data;
114
+    }
115 115
 }
116 116
 
117 117
 
118 118
 function xml_defaultElement($phraseur, $data) {
119
-	$depth = $phraseur->depth;
119
+    $depth = $phraseur->depth;
120 120
 
121
-	if (!isset($phraseur->contenu[$depth])) {
122
-		$phraseur->contenu[$depth] = '';
123
-	}
124
-	$phraseur->contenu[$depth] .= $data;
121
+    if (!isset($phraseur->contenu[$depth])) {
122
+        $phraseur->contenu[$depth] = '';
123
+    }
124
+    $phraseur->contenu[$depth] .= $data;
125 125
 }
126 126
 
127 127
 function xml_parsestring($phraseur, $data) {
128
-	$phraseur->contenu[$phraseur->depth] = '';
129
-
130
-	if (!xml_parse($phraseur->sax, $data, true)) {
131
-		coordonnees_erreur(
132
-			$phraseur,
133
-			xml_error_string(xml_get_error_code($phraseur->sax))
134
-			. "<br />\n" .
135
-			(!$phraseur->depth ? '' :
136
-				('(' .
137
-					_T('erreur_balise_non_fermee') .
138
-					' <tt>' .
139
-					$phraseur->ouvrant[$phraseur->depth] .
140
-					'</tt> ' .
141
-					_T('ligne') .
142
-					' ' .
143
-					$phraseur->reperes[$phraseur->depth] .
144
-			") <br />\n"))
145
-		);
146
-	}
128
+    $phraseur->contenu[$phraseur->depth] = '';
129
+
130
+    if (!xml_parse($phraseur->sax, $data, true)) {
131
+        coordonnees_erreur(
132
+            $phraseur,
133
+            xml_error_string(xml_get_error_code($phraseur->sax))
134
+            . "<br />\n" .
135
+            (!$phraseur->depth ? '' :
136
+                ('(' .
137
+                    _T('erreur_balise_non_fermee') .
138
+                    ' <tt>' .
139
+                    $phraseur->ouvrant[$phraseur->depth] .
140
+                    '</tt> ' .
141
+                    _T('ligne') .
142
+                    ' ' .
143
+                    $phraseur->reperes[$phraseur->depth] .
144
+            ") <br />\n"))
145
+        );
146
+    }
147 147
 }
148 148
 
149 149
 function coordonnees_erreur($phraseur, $msg) {
150
-	$entete_length = substr_count($phraseur->entete, "\n");
151
-	$phraseur->err[] = [
152
-		$msg,
153
-		xml_get_current_line_number($phraseur->sax) + $entete_length,
154
-		xml_get_current_column_number($phraseur->sax)
155
-	];
150
+    $entete_length = substr_count($phraseur->entete, "\n");
151
+    $phraseur->err[] = [
152
+        $msg,
153
+        xml_get_current_line_number($phraseur->sax) + $entete_length,
154
+        xml_get_current_column_number($phraseur->sax)
155
+    ];
156 156
 }
157 157
 
158 158
 function xml_sax_dist($page, $apply = false, $phraseur = null, $doctype = '', $charset = null) {
159
-	if (is_null($charset)) {
160
-		$charset = $GLOBALS['meta']['charset'];
161
-	}
162
-	if ($apply) {
163
-		ob_start();
164
-		if (is_array($apply)) {
165
-			$r = $page(...$apply);
166
-		} else {
167
-			$r = $page();
168
-		}
169
-		$page = ob_get_contents();
170
-		ob_end_clean();
171
-		// fonction sans aucun "echo", ca doit etre le resultat
172
-		if (!$page) {
173
-			$page = $r;
174
-		}
175
-	}
176
-
177
-	if (!$page) {
178
-		return '';
179
-	}
180
-	// charger la DTD et transcoder les entites,
181
-	// et escamoter le doctype que sax mange en php5 mais pas en  php4
182
-	if (!$doctype) {
183
-		if (!$r = analyser_doctype($page)) {
184
-			$page = _MESSAGE_DOCTYPE . _DOCTYPE_ECRIRE
185
-				. preg_replace(_REGEXP_DOCTYPE, '', $page);
186
-			$r = analyser_doctype($page);
187
-		}
188
-		[$entete, $avail, $grammaire, $rotlvl] = array_pad($r, 4, null);
189
-		$page = substr($page, strlen($entete));
190
-	} else {
191
-		$avail = 'SYSTEM';
192
-		$grammaire = $doctype;
193
-		$rotlvl = basename($grammaire);
194
-	}
195
-
196
-	include_spip('xml/analyser_dtd');
197
-	$dtc = charger_dtd($grammaire, $avail, $rotlvl);
198
-	$page = sax_bug($page, $dtc, $charset);
199
-
200
-	// compatibilite Tidy espace public
201
-	if (!$phraseur) {
202
-		$indenter_xml = charger_fonction('indenter', 'xml');
203
-
204
-		return $indenter_xml($page, $apply);
205
-	}
206
-
207
-	$xml_parser = xml_parser_create($charset);
208
-
209
-	xml_set_element_handler(
210
-		$xml_parser,
211
-		[$phraseur, 'debutElement'],
212
-		[$phraseur, 'finElement']
213
-	);
214
-
215
-	xml_set_character_data_handler(
216
-		$xml_parser,
217
-		[$phraseur, 'textElement']
218
-	);
219
-
220
-	xml_set_processing_instruction_handler(
221
-		$xml_parser,
222
-		[$phraseur, 'piElement']
223
-	);
224
-
225
-	xml_set_default_handler(
226
-		$xml_parser,
227
-		[$phraseur, 'defaultElement']
228
-	);
229
-
230
-	xml_parser_set_option($xml_parser, XML_OPTION_CASE_FOLDING, false);
231
-
232
-	$phraseur->sax = $xml_parser;
233
-	if (isset($entete)) {
234
-		$phraseur->entete = $entete;
235
-	}
236
-	$phraseur->page = $page;
237
-	$phraseur->dtc = $dtc;
238
-	$phraseur->phraserTout($xml_parser, $page);
239
-	xml_parser_free($xml_parser);
240
-	$phraseur->sax = '';
241
-
242
-	return $phraseur;
159
+    if (is_null($charset)) {
160
+        $charset = $GLOBALS['meta']['charset'];
161
+    }
162
+    if ($apply) {
163
+        ob_start();
164
+        if (is_array($apply)) {
165
+            $r = $page(...$apply);
166
+        } else {
167
+            $r = $page();
168
+        }
169
+        $page = ob_get_contents();
170
+        ob_end_clean();
171
+        // fonction sans aucun "echo", ca doit etre le resultat
172
+        if (!$page) {
173
+            $page = $r;
174
+        }
175
+    }
176
+
177
+    if (!$page) {
178
+        return '';
179
+    }
180
+    // charger la DTD et transcoder les entites,
181
+    // et escamoter le doctype que sax mange en php5 mais pas en  php4
182
+    if (!$doctype) {
183
+        if (!$r = analyser_doctype($page)) {
184
+            $page = _MESSAGE_DOCTYPE . _DOCTYPE_ECRIRE
185
+                . preg_replace(_REGEXP_DOCTYPE, '', $page);
186
+            $r = analyser_doctype($page);
187
+        }
188
+        [$entete, $avail, $grammaire, $rotlvl] = array_pad($r, 4, null);
189
+        $page = substr($page, strlen($entete));
190
+    } else {
191
+        $avail = 'SYSTEM';
192
+        $grammaire = $doctype;
193
+        $rotlvl = basename($grammaire);
194
+    }
195
+
196
+    include_spip('xml/analyser_dtd');
197
+    $dtc = charger_dtd($grammaire, $avail, $rotlvl);
198
+    $page = sax_bug($page, $dtc, $charset);
199
+
200
+    // compatibilite Tidy espace public
201
+    if (!$phraseur) {
202
+        $indenter_xml = charger_fonction('indenter', 'xml');
203
+
204
+        return $indenter_xml($page, $apply);
205
+    }
206
+
207
+    $xml_parser = xml_parser_create($charset);
208
+
209
+    xml_set_element_handler(
210
+        $xml_parser,
211
+        [$phraseur, 'debutElement'],
212
+        [$phraseur, 'finElement']
213
+    );
214
+
215
+    xml_set_character_data_handler(
216
+        $xml_parser,
217
+        [$phraseur, 'textElement']
218
+    );
219
+
220
+    xml_set_processing_instruction_handler(
221
+        $xml_parser,
222
+        [$phraseur, 'piElement']
223
+    );
224
+
225
+    xml_set_default_handler(
226
+        $xml_parser,
227
+        [$phraseur, 'defaultElement']
228
+    );
229
+
230
+    xml_parser_set_option($xml_parser, XML_OPTION_CASE_FOLDING, false);
231
+
232
+    $phraseur->sax = $xml_parser;
233
+    if (isset($entete)) {
234
+        $phraseur->entete = $entete;
235
+    }
236
+    $phraseur->page = $page;
237
+    $phraseur->dtc = $dtc;
238
+    $phraseur->phraserTout($xml_parser, $page);
239
+    xml_parser_free($xml_parser);
240
+    $phraseur->sax = '';
241
+
242
+    return $phraseur;
243 243
 }
244 244
 
245 245
 // SAX ne dit pas si une Entite est dans un attribut ou non.
@@ -250,24 +250,24 @@  discard block
 block discarded – undo
250 250
 // sinon on se rabat sur ce qu'en connait SPIP en standard.
251 251
 
252 252
 function sax_bug($data, $dtc, $charset = null) {
253
-	if (is_null($charset)) {
254
-		$charset = $GLOBALS['meta']['charset'];
255
-	}
256
-
257
-	if ($dtc) {
258
-		$trans = [];
259
-
260
-		foreach ($dtc->entites as $k => $v) {
261
-			if (!strpos(' amp lt gt quot ', (string) $k)) {
262
-				$trans["&$k;"] = $v;
263
-			}
264
-		}
265
-		$data = strtr($data, $trans);
266
-	} else {
267
-		$data = html2unicode($data, true);
268
-	}
269
-
270
-	return unicode2charset($data, $charset);
253
+    if (is_null($charset)) {
254
+        $charset = $GLOBALS['meta']['charset'];
255
+    }
256
+
257
+    if ($dtc) {
258
+        $trans = [];
259
+
260
+        foreach ($dtc->entites as $k => $v) {
261
+            if (!strpos(' amp lt gt quot ', (string) $k)) {
262
+                $trans["&$k;"] = $v;
263
+            }
264
+        }
265
+        $data = strtr($data, $trans);
266
+    } else {
267
+        $data = html2unicode($data, true);
268
+    }
269
+
270
+    return unicode2charset($data, $charset);
271 271
 }
272 272
 
273 273
 // Retirer < ? xml... ? > et autre PI, ainsi que les commentaires en debut
@@ -277,52 +277,52 @@  discard block
 block discarded – undo
277 277
 // les autres formats RSS n'ont pas de DTD,
278 278
 // mais un XML Schema que SPIP ne fait pas encore lire.
279 279
 function analyser_doctype($data) {
280
-	if (!preg_match(_REGEXP_DOCTYPE, $data, $page)) {
281
-		if (preg_match(_REGEXP_XML, $data, $page)) {
282
-			[, $entete, $topelement] = $page;
283
-			if ($topelement == 'rss') {
284
-				return [
285
-					$entete,
286
-					'PUBLIC',
287
-					_DOCTYPE_RSS,
288
-					'rss-0.91.dtd'
289
-				];
290
-			} else {
291
-				$dtd = $topelement . '.dtd';
292
-				$f = find_in_path($dtd);
293
-				if (file_exists($f)) {
294
-					return [$entete, 'SYSTEM', $f, $dtd];
295
-				}
296
-			}
297
-		}
298
-		spip_log('Dtd pas vu pour ' . substr($data, 0, 100));
299
-
300
-		return [];
301
-	}
302
-	[$entete, , $topelement, $avail, $suite] = $page;
303
-
304
-	if (!preg_match('/^"([^"]*)"\s*(.*)$/', $suite, $r)) {
305
-		if (!preg_match("/^'([^']*)'\s*(.*)$/", $suite, $r)) {
306
-			return [];
307
-		}
308
-	}
309
-	[, $rotlvl, $suite] = $r;
310
-
311
-	if (!$suite) {
312
-		if ($avail != 'SYSTEM') {
313
-			return [];
314
-		}
315
-		$grammaire = $rotlvl;
316
-		$rotlvl = '';
317
-	} else {
318
-		if (!preg_match('/^"([^"]*)"\s*$/', $suite, $r)) {
319
-			if (!preg_match("/^'([^']*)'\s*$/", $suite, $r)) {
320
-				return [];
321
-			}
322
-		}
323
-
324
-		$grammaire = $r[1];
325
-	}
326
-
327
-	return [$entete, $avail, $grammaire, $rotlvl];
280
+    if (!preg_match(_REGEXP_DOCTYPE, $data, $page)) {
281
+        if (preg_match(_REGEXP_XML, $data, $page)) {
282
+            [, $entete, $topelement] = $page;
283
+            if ($topelement == 'rss') {
284
+                return [
285
+                    $entete,
286
+                    'PUBLIC',
287
+                    _DOCTYPE_RSS,
288
+                    'rss-0.91.dtd'
289
+                ];
290
+            } else {
291
+                $dtd = $topelement . '.dtd';
292
+                $f = find_in_path($dtd);
293
+                if (file_exists($f)) {
294
+                    return [$entete, 'SYSTEM', $f, $dtd];
295
+                }
296
+            }
297
+        }
298
+        spip_log('Dtd pas vu pour ' . substr($data, 0, 100));
299
+
300
+        return [];
301
+    }
302
+    [$entete, , $topelement, $avail, $suite] = $page;
303
+
304
+    if (!preg_match('/^"([^"]*)"\s*(.*)$/', $suite, $r)) {
305
+        if (!preg_match("/^'([^']*)'\s*(.*)$/", $suite, $r)) {
306
+            return [];
307
+        }
308
+    }
309
+    [, $rotlvl, $suite] = $r;
310
+
311
+    if (!$suite) {
312
+        if ($avail != 'SYSTEM') {
313
+            return [];
314
+        }
315
+        $grammaire = $rotlvl;
316
+        $rotlvl = '';
317
+    } else {
318
+        if (!preg_match('/^"([^"]*)"\s*$/', $suite, $r)) {
319
+            if (!preg_match("/^'([^']*)'\s*$/", $suite, $r)) {
320
+                return [];
321
+            }
322
+        }
323
+
324
+        $grammaire = $r[1];
325
+    }
326
+
327
+    return [$entete, $avail, $grammaire, $rotlvl];
328 328
 }
Please login to merge, or discard this patch.
ecrire/action/api_transmettre.php 1 patch
Indentation   +79 added lines, -79 removed lines patch added patch discarded remove patch
@@ -17,91 +17,91 @@
 block discarded – undo
17 17
  **/
18 18
 
19 19
 if (!defined('_ECRIRE_INC_VERSION')) {
20
-	return;
20
+    return;
21 21
 }
22 22
 
23 23
 
24 24
 function action_api_transmettre_dist($arg = null) {
25 25
 
26
-	// Obtenir l'argument 'id_auteur/cle/format/fond'
27
-	if (is_null($arg)) {
28
-		$arg = _request('arg');
29
-	}
30
-
31
-	$args = explode('/', $arg);
32
-
33
-	if (count($args) !== 4) {
34
-		action_api_transmettre_fail($arg);
35
-	}
36
-
37
-	[$id_auteur, $cle, $format, $fond] = $args;
38
-	$id_auteur = intval($id_auteur);
39
-
40
-	if (preg_match(',[^\w\\.-],', $format)) {
41
-		action_api_transmettre_fail("format $format ??");
42
-	}
43
-	if (preg_match(',[^\w\\.-],', $fond)) {
44
-		action_api_transmettre_fail("fond $fond ??");
45
-	}
46
-
47
-	// verifier la cle
48
-	//[(#ENV{id,0}|securiser_acces{#ENV{cle}, voirstats, #ENV{op}, #ENV{args}}|?{1,0})]
49
-	//[(#ENV{id,0}|securiser_acces{#ENV{cle}, voirstats, #ENV{op}, #ENV{args}}|?{1,0})]
50
-
51
-	$qs = $_SERVER['QUERY_STRING'];
52
-	// retirer action et arg de la qs
53
-	$contexte = [];
54
-	parse_str($qs, $contexte);
55
-	foreach ($contexte as $k => $v) {
56
-		if (in_array($k, ['action', 'arg', 'var_mode'])) {
57
-			unset($contexte[$k]);
58
-		}
59
-	}
60
-	$qs = http_build_query($contexte);
61
-	if (!securiser_acces_low_sec(intval($id_auteur), $cle, "transmettre/$format", $fond, $qs)) {
62
-		// si le autoriser low_sec n'est pas bon, on peut valider l'appel si l'auteur est identifie
63
-		include_spip('inc/autoriser');
64
-		$autoriser_type = preg_replace(',\W+,', '', "_{$format}{$fond}");
65
-		if (
66
-			!$id_auteur
67
-			or empty($GLOBALS['visiteur_session']['id_auteur'])
68
-			or $GLOBALS['visiteur_session']['id_auteur'] != $id_auteur
69
-			or !autoriser('transmettre', $autoriser_type, $id_auteur)
70
-		) {
71
-			action_api_transmettre_fail("auth QS $qs ??");
72
-		}
73
-	}
74
-
75
-	$contexte['id_auteur'] = $id_auteur;
76
-
77
-	$fond = "transmettre/$format/$fond";
78
-
79
-	if (!trouver_fond($fond)) {
80
-		$fond = "prive/$fond";
81
-	}
82
-
83
-	if (!trouver_fond($fond)) {
84
-		action_api_transmettre_fail("fond $fond ??");
85
-	}
86
-
87
-	$res = recuperer_fond($fond, $contexte, ['raw' => true]);
88
-	if (!empty($res['entetes'])) {
89
-		foreach ($res['entetes'] as $h => $v) {
90
-			header("$h: $v");
91
-		}
92
-	}
93
-
94
-	$res = ltrim($res['texte']);
95
-	if (empty($res)) {
96
-		spip_log("$arg $qs resultat vide", 'transmettre' . _LOG_INFO_IMPORTANTE);
97
-	}
98
-
99
-	echo $res;
100
-	exit();
26
+    // Obtenir l'argument 'id_auteur/cle/format/fond'
27
+    if (is_null($arg)) {
28
+        $arg = _request('arg');
29
+    }
30
+
31
+    $args = explode('/', $arg);
32
+
33
+    if (count($args) !== 4) {
34
+        action_api_transmettre_fail($arg);
35
+    }
36
+
37
+    [$id_auteur, $cle, $format, $fond] = $args;
38
+    $id_auteur = intval($id_auteur);
39
+
40
+    if (preg_match(',[^\w\\.-],', $format)) {
41
+        action_api_transmettre_fail("format $format ??");
42
+    }
43
+    if (preg_match(',[^\w\\.-],', $fond)) {
44
+        action_api_transmettre_fail("fond $fond ??");
45
+    }
46
+
47
+    // verifier la cle
48
+    //[(#ENV{id,0}|securiser_acces{#ENV{cle}, voirstats, #ENV{op}, #ENV{args}}|?{1,0})]
49
+    //[(#ENV{id,0}|securiser_acces{#ENV{cle}, voirstats, #ENV{op}, #ENV{args}}|?{1,0})]
50
+
51
+    $qs = $_SERVER['QUERY_STRING'];
52
+    // retirer action et arg de la qs
53
+    $contexte = [];
54
+    parse_str($qs, $contexte);
55
+    foreach ($contexte as $k => $v) {
56
+        if (in_array($k, ['action', 'arg', 'var_mode'])) {
57
+            unset($contexte[$k]);
58
+        }
59
+    }
60
+    $qs = http_build_query($contexte);
61
+    if (!securiser_acces_low_sec(intval($id_auteur), $cle, "transmettre/$format", $fond, $qs)) {
62
+        // si le autoriser low_sec n'est pas bon, on peut valider l'appel si l'auteur est identifie
63
+        include_spip('inc/autoriser');
64
+        $autoriser_type = preg_replace(',\W+,', '', "_{$format}{$fond}");
65
+        if (
66
+            !$id_auteur
67
+            or empty($GLOBALS['visiteur_session']['id_auteur'])
68
+            or $GLOBALS['visiteur_session']['id_auteur'] != $id_auteur
69
+            or !autoriser('transmettre', $autoriser_type, $id_auteur)
70
+        ) {
71
+            action_api_transmettre_fail("auth QS $qs ??");
72
+        }
73
+    }
74
+
75
+    $contexte['id_auteur'] = $id_auteur;
76
+
77
+    $fond = "transmettre/$format/$fond";
78
+
79
+    if (!trouver_fond($fond)) {
80
+        $fond = "prive/$fond";
81
+    }
82
+
83
+    if (!trouver_fond($fond)) {
84
+        action_api_transmettre_fail("fond $fond ??");
85
+    }
86
+
87
+    $res = recuperer_fond($fond, $contexte, ['raw' => true]);
88
+    if (!empty($res['entetes'])) {
89
+        foreach ($res['entetes'] as $h => $v) {
90
+            header("$h: $v");
91
+        }
92
+    }
93
+
94
+    $res = ltrim($res['texte']);
95
+    if (empty($res)) {
96
+        spip_log("$arg $qs resultat vide", 'transmettre' . _LOG_INFO_IMPORTANTE);
97
+    }
98
+
99
+    echo $res;
100
+    exit();
101 101
 }
102 102
 
103 103
 function action_api_transmettre_fail($arg) {
104
-	include_spip('inc/minipres');
105
-	echo minipres(_T('info_acces_interdit'), $arg);
106
-	exit;
104
+    include_spip('inc/minipres');
105
+    echo minipres(_T('info_acces_interdit'), $arg);
106
+    exit;
107 107
 }
Please login to merge, or discard this patch.
ecrire/public/iterateur.php 1 patch
Indentation   +654 added lines, -654 removed lines patch added patch discarded remove patch
@@ -11,7 +11,7 @@  discard block
 block discarded – undo
11 11
 \***************************************************************************/
12 12
 
13 13
 if (!defined('_ECRIRE_INC_VERSION')) {
14
-	return;
14
+    return;
15 15
 }
16 16
 
17 17
 /**
@@ -21,667 +21,667 @@  discard block
 block discarded – undo
21 21
  *
22 22
  */
23 23
 class IterFactory {
24
-	public static function create($iterateur, $command, $info = null) {
25
-
26
-		$iter = null;
27
-		// cas des SI {si expression} analises tres tot
28
-		// pour eviter le chargement de tout iterateur
29
-		if (isset($command['si'])) {
30
-			foreach ($command['si'] as $si) {
31
-				if (!$si) {
32
-					// $command pour boucle SQL peut generer des erreurs de compilation
33
-					// s'il est transmis alors qu'on est dans un iterateur vide
34
-					return new IterDecorator(new EmptyIterator(), [], $info);
35
-				}
36
-			}
37
-		}
38
-
39
-		// chercher un iterateur PHP existant (par exemple dans SPL)
40
-		// (il faudrait passer l'argument ->sql_serveur
41
-		// pour etre certain qu'on est sur un "php:")
42
-		if (class_exists($iterateur)) {
43
-			$a = $command['args'] ?? [];
44
-
45
-			// permettre de passer un Iterateur directement {args #ITERATEUR} :
46
-			// si on recoit deja un iterateur en argument, on l'utilise
47
-			if ((is_countable($a) ? count($a) : 0) == 1 and is_object($a[0]) and is_subclass_of($a[0], \Iterator::class)) {
48
-				$iter = $a[0];
49
-
50
-				// sinon, on cree un iterateur du type donne
51
-			} else {
52
-				// arguments de creation de l'iterateur...
53
-				// (pas glop)
54
-				try {
55
-					switch (is_countable($a) ? count($a) : 0) {
56
-						case 0:
57
-							$iter = new $iterateur();
58
-							break;
59
-						case 1:
60
-							$iter = new $iterateur($a[0]);
61
-							break;
62
-						case 2:
63
-							$iter = new $iterateur($a[0], $a[1]);
64
-							break;
65
-						case 3:
66
-							$iter = new $iterateur($a[0], $a[1], $a[2]);
67
-							break;
68
-						case 4:
69
-							$iter = new $iterateur($a[0], $a[1], $a[2], $a[3]);
70
-							break;
71
-					}
72
-				} catch (Exception $e) {
73
-					spip_log("Erreur de chargement de l'iterateur $iterateur");
74
-					spip_log($e->getMessage());
75
-					$iter = new EmptyIterator();
76
-				}
77
-			}
78
-		} else {
79
-			// chercher la classe d'iterateur
80
-			// IterateurXXX
81
-			// definie dans le fichier iterateurs/xxx.php
82
-			$class = 'Iterateur' . $iterateur;
83
-			if (!class_exists($class)) {
84
-				if (
85
-					!include_spip('iterateur/' . strtolower($iterateur))
86
-					or !class_exists($class)
87
-				) {
88
-					die("Iterateur $iterateur non trouv&#233;");
89
-					// si l'iterateur n'existe pas, on se rabat sur le generique
90
-					# $iter = new EmptyIterator();
91
-				}
92
-			}
93
-			$iter = new $class($command, $info);
94
-		}
95
-
96
-		return new IterDecorator($iter, $command, $info);
97
-	}
24
+    public static function create($iterateur, $command, $info = null) {
25
+
26
+        $iter = null;
27
+        // cas des SI {si expression} analises tres tot
28
+        // pour eviter le chargement de tout iterateur
29
+        if (isset($command['si'])) {
30
+            foreach ($command['si'] as $si) {
31
+                if (!$si) {
32
+                    // $command pour boucle SQL peut generer des erreurs de compilation
33
+                    // s'il est transmis alors qu'on est dans un iterateur vide
34
+                    return new IterDecorator(new EmptyIterator(), [], $info);
35
+                }
36
+            }
37
+        }
38
+
39
+        // chercher un iterateur PHP existant (par exemple dans SPL)
40
+        // (il faudrait passer l'argument ->sql_serveur
41
+        // pour etre certain qu'on est sur un "php:")
42
+        if (class_exists($iterateur)) {
43
+            $a = $command['args'] ?? [];
44
+
45
+            // permettre de passer un Iterateur directement {args #ITERATEUR} :
46
+            // si on recoit deja un iterateur en argument, on l'utilise
47
+            if ((is_countable($a) ? count($a) : 0) == 1 and is_object($a[0]) and is_subclass_of($a[0], \Iterator::class)) {
48
+                $iter = $a[0];
49
+
50
+                // sinon, on cree un iterateur du type donne
51
+            } else {
52
+                // arguments de creation de l'iterateur...
53
+                // (pas glop)
54
+                try {
55
+                    switch (is_countable($a) ? count($a) : 0) {
56
+                        case 0:
57
+                            $iter = new $iterateur();
58
+                            break;
59
+                        case 1:
60
+                            $iter = new $iterateur($a[0]);
61
+                            break;
62
+                        case 2:
63
+                            $iter = new $iterateur($a[0], $a[1]);
64
+                            break;
65
+                        case 3:
66
+                            $iter = new $iterateur($a[0], $a[1], $a[2]);
67
+                            break;
68
+                        case 4:
69
+                            $iter = new $iterateur($a[0], $a[1], $a[2], $a[3]);
70
+                            break;
71
+                    }
72
+                } catch (Exception $e) {
73
+                    spip_log("Erreur de chargement de l'iterateur $iterateur");
74
+                    spip_log($e->getMessage());
75
+                    $iter = new EmptyIterator();
76
+                }
77
+            }
78
+        } else {
79
+            // chercher la classe d'iterateur
80
+            // IterateurXXX
81
+            // definie dans le fichier iterateurs/xxx.php
82
+            $class = 'Iterateur' . $iterateur;
83
+            if (!class_exists($class)) {
84
+                if (
85
+                    !include_spip('iterateur/' . strtolower($iterateur))
86
+                    or !class_exists($class)
87
+                ) {
88
+                    die("Iterateur $iterateur non trouv&#233;");
89
+                    // si l'iterateur n'existe pas, on se rabat sur le generique
90
+                    # $iter = new EmptyIterator();
91
+                }
92
+            }
93
+            $iter = new $class($command, $info);
94
+        }
95
+
96
+        return new IterDecorator($iter, $command, $info);
97
+    }
98 98
 }
99 99
 
100 100
 
101 101
 class IterDecorator extends FilterIterator {
102
-	private $iter;
103
-
104
-	/**
105
-	 * Conditions de filtrage
106
-	 * ie criteres de selection
107
-	 *
108
-	 * @var array
109
-	 */
110
-	protected $filtre = [];
111
-
112
-	/**
113
-	 * Fonction de filtrage compilee a partir des criteres de filtre
114
-	 *
115
-	 * @var string
116
-	 */
117
-	protected $func_filtre = null;
118
-
119
-	/**
120
-	 * Critere {offset, limit}
121
-	 *
122
-	 * @var int
123
-	 * @var int
124
-	 */
125
-	protected $offset = null;
126
-	protected $limit = null;
127
-
128
-	/**
129
-	 * nombre d'elements recuperes depuis la position 0,
130
-	 * en tenant compte des filtres
131
-	 *
132
-	 * @var int
133
-	 */
134
-	protected $fetched = 0;
135
-
136
-	/**
137
-	 * Y a t'il une erreur ?
138
-	 *
139
-	 * @var bool
140
-	 **/
141
-	protected $err = false;
142
-
143
-	/**
144
-	 * Drapeau a activer en cas d'echec
145
-	 * (select SQL errone, non chargement des DATA, etc)
146
-	 */
147
-	public function err() {
148
-		if (method_exists($this->iter, 'err')) {
149
-			return $this->iter->err();
150
-		}
151
-		if (property_exists($this->iter, 'err')) {
152
-			return $this->iter->err;
153
-		}
154
-
155
-		return false;
156
-	}
157
-
158
-	public function __construct(Iterator $iter, $command, $info) {
159
-		parent::__construct($iter);
160
-		parent::rewind(); // remettre a la premiere position (bug? connu de FilterIterator)
161
-
162
-		// recuperer l'iterateur transmis
163
-		$this->iter = $this->getInnerIterator();
164
-		$this->command = $command;
165
-		$this->info = $info;
166
-		$this->pos = 0;
167
-		$this->fetched = 0;
168
-
169
-		// chercher la liste des champs a retourner par
170
-		// fetch si l'objet ne les calcule pas tout seul
171
-		if (!method_exists($this->iter, 'fetch')) {
172
-			$this->calculer_select();
173
-			$this->calculer_filtres();
174
-		}
175
-
176
-		// emptyIterator critere {si} faux n'a pas d'erreur !
177
-		if (isset($this->iter->err)) {
178
-			$this->err = $this->iter->err;
179
-		}
180
-
181
-		// pas d'init a priori, le calcul ne sera fait qu'en cas de besoin (provoque une double requete souvent inutile en sqlite)
182
-		//$this->total = $this->count();
183
-	}
184
-
185
-
186
-	// calcule les elements a retournes par fetch()
187
-	// enleve les elements inutiles du select()
188
-	//
189
-	private function calculer_select() {
190
-		if ($select = &$this->command['select']) {
191
-			foreach ($select as $s) {
192
-				// /!\ $s = '.nom'
193
-				if ($s[0] == '.') {
194
-					$s = substr($s, 1);
195
-				}
196
-				$this->select[] = $s;
197
-			}
198
-		}
199
-	}
200
-
201
-	// recuperer la valeur d'une balise #X
202
-	// en fonction des methodes
203
-	// et proprietes disponibles
204
-	public function get_select($nom) {
205
-		if (
206
-			is_object($this->iter)
207
-			and method_exists($this->iter, $nom)
208
-		) {
209
-			try {
210
-				return $this->iter->$nom();
211
-			} catch (Exception $e) {
212
-				// #GETCHILDREN sur un fichier de DirectoryIterator ...
213
-				spip_log("Methode $nom en echec sur " . get_class($this->iter));
214
-				spip_log("Cela peut être normal : retour d'une ligne de resultat ne pouvant pas calculer cette methode");
215
-
216
-				return '';
217
-			}
218
-		}
219
-		/*
102
+    private $iter;
103
+
104
+    /**
105
+     * Conditions de filtrage
106
+     * ie criteres de selection
107
+     *
108
+     * @var array
109
+     */
110
+    protected $filtre = [];
111
+
112
+    /**
113
+     * Fonction de filtrage compilee a partir des criteres de filtre
114
+     *
115
+     * @var string
116
+     */
117
+    protected $func_filtre = null;
118
+
119
+    /**
120
+     * Critere {offset, limit}
121
+     *
122
+     * @var int
123
+     * @var int
124
+     */
125
+    protected $offset = null;
126
+    protected $limit = null;
127
+
128
+    /**
129
+     * nombre d'elements recuperes depuis la position 0,
130
+     * en tenant compte des filtres
131
+     *
132
+     * @var int
133
+     */
134
+    protected $fetched = 0;
135
+
136
+    /**
137
+     * Y a t'il une erreur ?
138
+     *
139
+     * @var bool
140
+     **/
141
+    protected $err = false;
142
+
143
+    /**
144
+     * Drapeau a activer en cas d'echec
145
+     * (select SQL errone, non chargement des DATA, etc)
146
+     */
147
+    public function err() {
148
+        if (method_exists($this->iter, 'err')) {
149
+            return $this->iter->err();
150
+        }
151
+        if (property_exists($this->iter, 'err')) {
152
+            return $this->iter->err;
153
+        }
154
+
155
+        return false;
156
+    }
157
+
158
+    public function __construct(Iterator $iter, $command, $info) {
159
+        parent::__construct($iter);
160
+        parent::rewind(); // remettre a la premiere position (bug? connu de FilterIterator)
161
+
162
+        // recuperer l'iterateur transmis
163
+        $this->iter = $this->getInnerIterator();
164
+        $this->command = $command;
165
+        $this->info = $info;
166
+        $this->pos = 0;
167
+        $this->fetched = 0;
168
+
169
+        // chercher la liste des champs a retourner par
170
+        // fetch si l'objet ne les calcule pas tout seul
171
+        if (!method_exists($this->iter, 'fetch')) {
172
+            $this->calculer_select();
173
+            $this->calculer_filtres();
174
+        }
175
+
176
+        // emptyIterator critere {si} faux n'a pas d'erreur !
177
+        if (isset($this->iter->err)) {
178
+            $this->err = $this->iter->err;
179
+        }
180
+
181
+        // pas d'init a priori, le calcul ne sera fait qu'en cas de besoin (provoque une double requete souvent inutile en sqlite)
182
+        //$this->total = $this->count();
183
+    }
184
+
185
+
186
+    // calcule les elements a retournes par fetch()
187
+    // enleve les elements inutiles du select()
188
+    //
189
+    private function calculer_select() {
190
+        if ($select = &$this->command['select']) {
191
+            foreach ($select as $s) {
192
+                // /!\ $s = '.nom'
193
+                if ($s[0] == '.') {
194
+                    $s = substr($s, 1);
195
+                }
196
+                $this->select[] = $s;
197
+            }
198
+        }
199
+    }
200
+
201
+    // recuperer la valeur d'une balise #X
202
+    // en fonction des methodes
203
+    // et proprietes disponibles
204
+    public function get_select($nom) {
205
+        if (
206
+            is_object($this->iter)
207
+            and method_exists($this->iter, $nom)
208
+        ) {
209
+            try {
210
+                return $this->iter->$nom();
211
+            } catch (Exception $e) {
212
+                // #GETCHILDREN sur un fichier de DirectoryIterator ...
213
+                spip_log("Methode $nom en echec sur " . get_class($this->iter));
214
+                spip_log("Cela peut être normal : retour d'une ligne de resultat ne pouvant pas calculer cette methode");
215
+
216
+                return '';
217
+            }
218
+        }
219
+        /*
220 220
 		if (property_exists($this->iter, $nom)) {
221 221
 			return $this->iter->$nom;
222 222
 		}*/
223
-		// cle et valeur par defaut
224
-		// ICI PLANTAGE SI ON NE CONTROLE PAS $nom
225
-		if (
226
-			in_array($nom, ['cle', 'valeur'])
227
-			and method_exists($this, $nom)
228
-		) {
229
-			return $this->$nom();
230
-		}
231
-
232
-		// Par defaut chercher en xpath dans la valeur()
233
-		return table_valeur($this->valeur(), $nom, null);
234
-	}
235
-
236
-
237
-	private function calculer_filtres() {
238
-
239
-		// Issu de calculer_select() de public/composer L.519
240
-		// TODO: externaliser...
241
-		//
242
-		// retirer les criteres vides:
243
-		// {X ?} avec X absent de l'URL
244
-		// {par #ENV{X}} avec X absent de l'URL
245
-		// IN sur collection vide (ce dernier devrait pouvoir etre fait a la compil)
246
-		if ($where = &$this->command['where']) {
247
-			foreach ($where as $k => $v) {
248
-				$this->filtre[] = $this->traduire_condition_sql_en_filtre($v);
249
-			}
250
-		}
251
-
252
-		// critere {2,7}
253
-		if (isset($this->command['limit']) and $this->command['limit']) {
254
-			$limit = explode(',', $this->command['limit']);
255
-			$this->offset = $limit[0];
256
-			$this->limit = $limit[1];
257
-		}
258
-
259
-		// Creer la fonction de filtrage sur $this
260
-		if ($this->filtre) {
261
-			if ($filtres = $this->assembler_filtres($this->filtre)) {
262
-				$filtres = 'return ' . $filtres . ';';
263
-				$this->func_filtre = fn() => eval($filtres);
264
-			}
265
-			else {
266
-				$this->func_filtre = null;
267
-			}
268
-		}
269
-	}
270
-
271
-	/**
272
-	 * Assembler le tableau de filtres traduits depuis les conditions SQL
273
-	 * les filtres vides ou null sont ignores
274
-	 * @param $filtres
275
-	 * @param string $operateur
276
-	 * @return string|null
277
-	 */
278
-	protected function assembler_filtres($filtres, $operateur = 'AND') {
279
-
280
-		$filtres_string = [];
281
-		foreach ($filtres as $k => $v) {
282
-			// si c'est un tableau de OR/AND + 2 sous-filtres, on recurse pour transformer en chaine
283
-			if (is_array($v) and in_array(reset($v), ['OR', 'AND'])) {
284
-				$op = array_shift($v);
285
-				$v = $this->assembler_filtres($v, $op);
286
-			}
287
-			if (is_null($v) or !is_string($v) or empty($v)) {
288
-				continue;
289
-			}
290
-			$filtres_string[] = $v;
291
-		}
292
-
293
-		if (!count($filtres_string)) {
294
-			return null;
295
-		}
296
-
297
-		return '(' . implode(") $operateur (", $filtres_string) . ')';
298
-	}
299
-
300
-	/**
301
-	 * Traduire un element du tableau where SQL en un filtre
302
-	 * @param $v
303
-	 * @return string|array|null
304
-	 */
305
-	protected function traduire_condition_sql_en_filtre($v) {
306
-		if (is_array($v)) {
307
-			if ((count($v) >= 2) && ($v[0] == 'REGEXP') && ($v[2] == "'.*'")) {
308
-				return 'true';
309
-			} elseif ((count($v) >= 2) && ($v[0] == 'LIKE') && ($v[2] == "'%'")) {
310
-				return 'true';
311
-			} else {
312
-				$op = $v[0] ?: $v;
313
-			}
314
-		} else {
315
-			$op = $v;
316
-		}
317
-		if ((!$op) or ($op == 1) or ($op == '0=0')) {
318
-			return 'true';
319
-		}
320
-		if ($op === '0=1') {
321
-			return 'false';
322
-		}
323
-		// traiter {cle IN a,b} ou {valeur !IN a,b}
324
-		if (preg_match(',^\(([\w/]+)(\s+NOT)?\s+IN\s+(\(.*\))\)$,', $op, $regs)) {
325
-			return $this->composer_filtre($regs[1], 'IN', $regs[3], $regs[2]);
326
-		}
327
-
328
-		// 3 possibilites : count($v) =
329
-		// * 1 : {x y} ; on recoit $v[0] = y
330
-		// * 2 : {x !op y} ; on recoit $v[0] = 'NOT', $v[1] = array() // array du type {x op y}
331
-		// * 3 : {x op y} ; on recoit $v[0] = 'op', $v[1] = x, $v[2] = y
332
-
333
-		// 1 : forcement traite par un critere, on passe
334
-		if (!$v or !is_array($v) or count($v) == 1) {
335
-			return null; // sera ignore
336
-		}
337
-		if (count($v) == 2 and is_array($v[1])) {
338
-			return $this->composer_filtre($v[1][1], $v[1][0], $v[1][2], 'NOT');
339
-		}
340
-		if (count($v) == 3) {
341
-			// traiter le OR/AND suivi de 2 valeurs
342
-			if (in_array($op, ['OR', 'AND'])) {
343
-				array_shift($v);
344
-				foreach (array_keys($v) as $k) {
345
-					$v[$k] = $this->traduire_condition_sql_en_filtre($v[$k]);
346
-					if ($v[$k] === null) {
347
-						unset($v[$k]);
348
-					}
349
-					elseif ($v[$k] === 'true') {
350
-						if ($op === 'OR') {
351
-							return 'true';
352
-						}
353
-						if ($op === 'AND') {
354
-							unset($v[$k]);
355
-						}
356
-					}
357
-					elseif ($v[$k] === 'false') {
358
-						if ($op === 'OR') {
359
-							unset($v[$k]);
360
-						}
361
-						if ($op === 'AND') {
362
-							return 'false';
363
-						}
364
-					}
365
-				}
366
-				if (!count($v)) {
367
-					return null;
368
-				}
369
-				if (count($v) === 1) {
370
-					return reset($v);
371
-				}
372
-				array_unshift($v, $op);
373
-				return $v;
374
-			}
375
-			return $this->composer_filtre($v[1], $v[0], $v[2]);
376
-		}
377
-
378
-		return null;  // sera ignore
379
-	}
380
-
381
-	/**
382
-	 * Calculer un filtre sur un champ du tableau
383
-	 * @param $cle
384
-	 * @param $op
385
-	 * @param $valeur
386
-	 * @param false $not
387
-	 * @return string|null
388
-	 */
389
-	protected function composer_filtre($cle, $op, $valeur, $not = false) {
390
-		if (method_exists($this->iter, 'exception_des_criteres')) {
391
-			if (in_array($cle, $this->iter->exception_des_criteres())) {
392
-				return null;
393
-			}
394
-		}
395
-		// TODO: analyser le filtre pour refuser ce qu'on ne sait pas traiter ?
396
-		# mais c'est normalement deja opere par calculer_critere_infixe()
397
-		# qui regarde la description 'desc' (en casse reelle d'ailleurs : {isDir=1}
398
-		# ne sera pas vu si l'on a defini desc['field']['isdir'] pour que #ISDIR soit present.
399
-		# il faudrait peut etre definir les 2 champs isDir et isdir... a reflechir...
400
-
401
-		# if (!in_array($cle, array('cle', 'valeur')))
402
-		#	return;
403
-
404
-		$a = '$this->get_select(\'' . $cle . '\')';
405
-
406
-		$filtre = '';
407
-
408
-		if ($op == 'REGEXP') {
409
-			$filtre = 'filtrer("match", ' . $a . ', ' . str_replace('\"', '"', $valeur) . ')';
410
-			$op = '';
411
-		} else {
412
-			if ($op == 'LIKE') {
413
-				$valeur = str_replace(['\"', '_', '%'], ['"', '.', '.*'], preg_quote($valeur));
414
-				$filtre = 'filtrer("match", ' . $a . ', ' . $valeur . ')';
415
-				$op = '';
416
-			} else {
417
-				if ($op == '=') {
418
-					$op = '==';
419
-				} else {
420
-					if ($op == 'IN') {
421
-						$filtre = 'in_array(' . $a . ', array' . $valeur . ')';
422
-						$op = '';
423
-					} else {
424
-						if (!in_array($op, ['<', '<=', '>', '>='])) {
425
-							spip_log('operateur non reconnu ' . $op); // [todo] mettre une erreur de squelette
426
-							$op = '';
427
-						}
428
-					}
429
-				}
430
-			}
431
-		}
432
-
433
-		if ($op) {
434
-			$filtre = $a . $op . str_replace('\"', '"', $valeur);
435
-		}
436
-
437
-		if ($not) {
438
-			$filtre = "!($filtre)";
439
-		}
440
-
441
-		return $filtre;
442
-	}
443
-
444
-
445
-	public function next(): void {
446
-		$this->pos++;
447
-		parent::next();
448
-	}
449
-
450
-	/**
451
-	 * revient au depart
452
-	 *
453
-	 * @return void
454
-	 */
455
-	public function rewind(): void {
456
-		$this->pos = 0;
457
-		$this->fetched = 0;
458
-		parent::rewind();
459
-	}
460
-
461
-
462
-	# Extension SPIP des iterateurs PHP
463
-	/**
464
-	 * type de l'iterateur
465
-	 *
466
-	 * @var string
467
-	 */
468
-	protected $type;
469
-
470
-	/**
471
-	 * parametres de l'iterateur
472
-	 *
473
-	 * @var array
474
-	 */
475
-	protected $command;
476
-
477
-	/**
478
-	 * infos de compilateur
479
-	 *
480
-	 * @var array
481
-	 */
482
-	protected $info;
483
-
484
-	/**
485
-	 * position courante de l'iterateur
486
-	 *
487
-	 * @var int
488
-	 */
489
-	protected $pos = null;
490
-
491
-	/**
492
-	 * nombre total resultats dans l'iterateur
493
-	 *
494
-	 * @var int
495
-	 */
496
-	protected $total = null;
497
-
498
-	/**
499
-	 * nombre maximal de recherche pour $total
500
-	 * si l'iterateur n'implemente pas de fonction specifique
501
-	 */
502
-	protected $max = 100000;
503
-
504
-
505
-	/**
506
-	 * Liste des champs a inserer dans les $row
507
-	 * retournes par ->fetch()
508
-	 */
509
-	protected $select = [];
510
-
511
-
512
-	/**
513
-	 * aller a la position absolue n,
514
-	 * comptee depuis le debut
515
-	 *
516
-	 * @param int $n
517
-	 *   absolute pos
518
-	 * @param string $continue
519
-	 *   param for sql_ api
520
-	 * @return bool
521
-	 *   success or fail if not implemented
522
-	 */
523
-	public function seek($n = 0, $continue = null) {
524
-		if ($this->func_filtre or !method_exists($this->iter, 'seek') or !$this->iter->seek($n)) {
525
-			$this->seek_loop($n);
526
-		}
527
-		$this->pos = $n;
528
-		$this->fetched = $n;
529
-
530
-		return true;
531
-	}
532
-
533
-	/*
223
+        // cle et valeur par defaut
224
+        // ICI PLANTAGE SI ON NE CONTROLE PAS $nom
225
+        if (
226
+            in_array($nom, ['cle', 'valeur'])
227
+            and method_exists($this, $nom)
228
+        ) {
229
+            return $this->$nom();
230
+        }
231
+
232
+        // Par defaut chercher en xpath dans la valeur()
233
+        return table_valeur($this->valeur(), $nom, null);
234
+    }
235
+
236
+
237
+    private function calculer_filtres() {
238
+
239
+        // Issu de calculer_select() de public/composer L.519
240
+        // TODO: externaliser...
241
+        //
242
+        // retirer les criteres vides:
243
+        // {X ?} avec X absent de l'URL
244
+        // {par #ENV{X}} avec X absent de l'URL
245
+        // IN sur collection vide (ce dernier devrait pouvoir etre fait a la compil)
246
+        if ($where = &$this->command['where']) {
247
+            foreach ($where as $k => $v) {
248
+                $this->filtre[] = $this->traduire_condition_sql_en_filtre($v);
249
+            }
250
+        }
251
+
252
+        // critere {2,7}
253
+        if (isset($this->command['limit']) and $this->command['limit']) {
254
+            $limit = explode(',', $this->command['limit']);
255
+            $this->offset = $limit[0];
256
+            $this->limit = $limit[1];
257
+        }
258
+
259
+        // Creer la fonction de filtrage sur $this
260
+        if ($this->filtre) {
261
+            if ($filtres = $this->assembler_filtres($this->filtre)) {
262
+                $filtres = 'return ' . $filtres . ';';
263
+                $this->func_filtre = fn() => eval($filtres);
264
+            }
265
+            else {
266
+                $this->func_filtre = null;
267
+            }
268
+        }
269
+    }
270
+
271
+    /**
272
+     * Assembler le tableau de filtres traduits depuis les conditions SQL
273
+     * les filtres vides ou null sont ignores
274
+     * @param $filtres
275
+     * @param string $operateur
276
+     * @return string|null
277
+     */
278
+    protected function assembler_filtres($filtres, $operateur = 'AND') {
279
+
280
+        $filtres_string = [];
281
+        foreach ($filtres as $k => $v) {
282
+            // si c'est un tableau de OR/AND + 2 sous-filtres, on recurse pour transformer en chaine
283
+            if (is_array($v) and in_array(reset($v), ['OR', 'AND'])) {
284
+                $op = array_shift($v);
285
+                $v = $this->assembler_filtres($v, $op);
286
+            }
287
+            if (is_null($v) or !is_string($v) or empty($v)) {
288
+                continue;
289
+            }
290
+            $filtres_string[] = $v;
291
+        }
292
+
293
+        if (!count($filtres_string)) {
294
+            return null;
295
+        }
296
+
297
+        return '(' . implode(") $operateur (", $filtres_string) . ')';
298
+    }
299
+
300
+    /**
301
+     * Traduire un element du tableau where SQL en un filtre
302
+     * @param $v
303
+     * @return string|array|null
304
+     */
305
+    protected function traduire_condition_sql_en_filtre($v) {
306
+        if (is_array($v)) {
307
+            if ((count($v) >= 2) && ($v[0] == 'REGEXP') && ($v[2] == "'.*'")) {
308
+                return 'true';
309
+            } elseif ((count($v) >= 2) && ($v[0] == 'LIKE') && ($v[2] == "'%'")) {
310
+                return 'true';
311
+            } else {
312
+                $op = $v[0] ?: $v;
313
+            }
314
+        } else {
315
+            $op = $v;
316
+        }
317
+        if ((!$op) or ($op == 1) or ($op == '0=0')) {
318
+            return 'true';
319
+        }
320
+        if ($op === '0=1') {
321
+            return 'false';
322
+        }
323
+        // traiter {cle IN a,b} ou {valeur !IN a,b}
324
+        if (preg_match(',^\(([\w/]+)(\s+NOT)?\s+IN\s+(\(.*\))\)$,', $op, $regs)) {
325
+            return $this->composer_filtre($regs[1], 'IN', $regs[3], $regs[2]);
326
+        }
327
+
328
+        // 3 possibilites : count($v) =
329
+        // * 1 : {x y} ; on recoit $v[0] = y
330
+        // * 2 : {x !op y} ; on recoit $v[0] = 'NOT', $v[1] = array() // array du type {x op y}
331
+        // * 3 : {x op y} ; on recoit $v[0] = 'op', $v[1] = x, $v[2] = y
332
+
333
+        // 1 : forcement traite par un critere, on passe
334
+        if (!$v or !is_array($v) or count($v) == 1) {
335
+            return null; // sera ignore
336
+        }
337
+        if (count($v) == 2 and is_array($v[1])) {
338
+            return $this->composer_filtre($v[1][1], $v[1][0], $v[1][2], 'NOT');
339
+        }
340
+        if (count($v) == 3) {
341
+            // traiter le OR/AND suivi de 2 valeurs
342
+            if (in_array($op, ['OR', 'AND'])) {
343
+                array_shift($v);
344
+                foreach (array_keys($v) as $k) {
345
+                    $v[$k] = $this->traduire_condition_sql_en_filtre($v[$k]);
346
+                    if ($v[$k] === null) {
347
+                        unset($v[$k]);
348
+                    }
349
+                    elseif ($v[$k] === 'true') {
350
+                        if ($op === 'OR') {
351
+                            return 'true';
352
+                        }
353
+                        if ($op === 'AND') {
354
+                            unset($v[$k]);
355
+                        }
356
+                    }
357
+                    elseif ($v[$k] === 'false') {
358
+                        if ($op === 'OR') {
359
+                            unset($v[$k]);
360
+                        }
361
+                        if ($op === 'AND') {
362
+                            return 'false';
363
+                        }
364
+                    }
365
+                }
366
+                if (!count($v)) {
367
+                    return null;
368
+                }
369
+                if (count($v) === 1) {
370
+                    return reset($v);
371
+                }
372
+                array_unshift($v, $op);
373
+                return $v;
374
+            }
375
+            return $this->composer_filtre($v[1], $v[0], $v[2]);
376
+        }
377
+
378
+        return null;  // sera ignore
379
+    }
380
+
381
+    /**
382
+     * Calculer un filtre sur un champ du tableau
383
+     * @param $cle
384
+     * @param $op
385
+     * @param $valeur
386
+     * @param false $not
387
+     * @return string|null
388
+     */
389
+    protected function composer_filtre($cle, $op, $valeur, $not = false) {
390
+        if (method_exists($this->iter, 'exception_des_criteres')) {
391
+            if (in_array($cle, $this->iter->exception_des_criteres())) {
392
+                return null;
393
+            }
394
+        }
395
+        // TODO: analyser le filtre pour refuser ce qu'on ne sait pas traiter ?
396
+        # mais c'est normalement deja opere par calculer_critere_infixe()
397
+        # qui regarde la description 'desc' (en casse reelle d'ailleurs : {isDir=1}
398
+        # ne sera pas vu si l'on a defini desc['field']['isdir'] pour que #ISDIR soit present.
399
+        # il faudrait peut etre definir les 2 champs isDir et isdir... a reflechir...
400
+
401
+        # if (!in_array($cle, array('cle', 'valeur')))
402
+        #	return;
403
+
404
+        $a = '$this->get_select(\'' . $cle . '\')';
405
+
406
+        $filtre = '';
407
+
408
+        if ($op == 'REGEXP') {
409
+            $filtre = 'filtrer("match", ' . $a . ', ' . str_replace('\"', '"', $valeur) . ')';
410
+            $op = '';
411
+        } else {
412
+            if ($op == 'LIKE') {
413
+                $valeur = str_replace(['\"', '_', '%'], ['"', '.', '.*'], preg_quote($valeur));
414
+                $filtre = 'filtrer("match", ' . $a . ', ' . $valeur . ')';
415
+                $op = '';
416
+            } else {
417
+                if ($op == '=') {
418
+                    $op = '==';
419
+                } else {
420
+                    if ($op == 'IN') {
421
+                        $filtre = 'in_array(' . $a . ', array' . $valeur . ')';
422
+                        $op = '';
423
+                    } else {
424
+                        if (!in_array($op, ['<', '<=', '>', '>='])) {
425
+                            spip_log('operateur non reconnu ' . $op); // [todo] mettre une erreur de squelette
426
+                            $op = '';
427
+                        }
428
+                    }
429
+                }
430
+            }
431
+        }
432
+
433
+        if ($op) {
434
+            $filtre = $a . $op . str_replace('\"', '"', $valeur);
435
+        }
436
+
437
+        if ($not) {
438
+            $filtre = "!($filtre)";
439
+        }
440
+
441
+        return $filtre;
442
+    }
443
+
444
+
445
+    public function next(): void {
446
+        $this->pos++;
447
+        parent::next();
448
+    }
449
+
450
+    /**
451
+     * revient au depart
452
+     *
453
+     * @return void
454
+     */
455
+    public function rewind(): void {
456
+        $this->pos = 0;
457
+        $this->fetched = 0;
458
+        parent::rewind();
459
+    }
460
+
461
+
462
+    # Extension SPIP des iterateurs PHP
463
+    /**
464
+     * type de l'iterateur
465
+     *
466
+     * @var string
467
+     */
468
+    protected $type;
469
+
470
+    /**
471
+     * parametres de l'iterateur
472
+     *
473
+     * @var array
474
+     */
475
+    protected $command;
476
+
477
+    /**
478
+     * infos de compilateur
479
+     *
480
+     * @var array
481
+     */
482
+    protected $info;
483
+
484
+    /**
485
+     * position courante de l'iterateur
486
+     *
487
+     * @var int
488
+     */
489
+    protected $pos = null;
490
+
491
+    /**
492
+     * nombre total resultats dans l'iterateur
493
+     *
494
+     * @var int
495
+     */
496
+    protected $total = null;
497
+
498
+    /**
499
+     * nombre maximal de recherche pour $total
500
+     * si l'iterateur n'implemente pas de fonction specifique
501
+     */
502
+    protected $max = 100000;
503
+
504
+
505
+    /**
506
+     * Liste des champs a inserer dans les $row
507
+     * retournes par ->fetch()
508
+     */
509
+    protected $select = [];
510
+
511
+
512
+    /**
513
+     * aller a la position absolue n,
514
+     * comptee depuis le debut
515
+     *
516
+     * @param int $n
517
+     *   absolute pos
518
+     * @param string $continue
519
+     *   param for sql_ api
520
+     * @return bool
521
+     *   success or fail if not implemented
522
+     */
523
+    public function seek($n = 0, $continue = null) {
524
+        if ($this->func_filtre or !method_exists($this->iter, 'seek') or !$this->iter->seek($n)) {
525
+            $this->seek_loop($n);
526
+        }
527
+        $this->pos = $n;
528
+        $this->fetched = $n;
529
+
530
+        return true;
531
+    }
532
+
533
+    /*
534 534
 	 * aller a la position $n en parcourant
535 535
 	 * un par un tous les elements
536 536
 	 */
537
-	private function seek_loop($n) {
538
-		if ($this->pos > $n) {
539
-			$this->rewind();
540
-		}
541
-
542
-		while ($this->pos < $n and $this->valid()) {
543
-			$this->next();
544
-		}
545
-
546
-		return true;
547
-	}
548
-
549
-	/**
550
-	 * Avancer de $saut pas
551
-	 *
552
-	 * @param  $saut
553
-	 * @param  $max
554
-	 * @return int
555
-	 */
556
-	public function skip($saut, $max = null) {
557
-		// pas de saut en arriere autorise pour cette fonction
558
-		if (($saut = intval($saut)) <= 0) {
559
-			return $this->pos;
560
-		}
561
-		$seek = $this->pos + $saut;
562
-		// si le saut fait depasser le maxi, on libere la resource
563
-		// et on sort
564
-		if (is_null($max)) {
565
-			$max = $this->count();
566
-		}
567
-
568
-		if ($seek >= $max or $seek >= $this->count()) {
569
-			// sortie plus rapide que de faire next() jusqu'a la fin !
570
-			$this->free();
571
-
572
-			return $max;
573
-		}
574
-
575
-		$this->seek($seek);
576
-
577
-		return $this->pos;
578
-	}
579
-
580
-	/**
581
-	 * Renvoyer un tableau des donnees correspondantes
582
-	 * a la position courante de l'iterateur
583
-	 * en controlant si on respecte le filtre
584
-	 * Appliquer aussi le critere {offset,limit}
585
-	 *
586
-	 * @return array|bool
587
-	 */
588
-	public function fetch() {
589
-		if (method_exists($this->iter, 'fetch')) {
590
-			return $this->iter->fetch();
591
-		} else {
592
-			while (
593
-				$this->valid()
594
-				and (
595
-					!$this->accept()
596
-					or (isset($this->offset) and $this->fetched++ < $this->offset)
597
-				)
598
-			) {
599
-				$this->next();
600
-			}
601
-
602
-			if (!$this->valid()) {
603
-				return false;
604
-			}
605
-
606
-			if (
607
-				isset($this->limit)
608
-				and $this->fetched > $this->offset + $this->limit
609
-			) {
610
-				return false;
611
-			}
612
-
613
-			$r = [];
614
-			foreach ($this->select as $nom) {
615
-				$r[$nom] = $this->get_select($nom);
616
-			}
617
-			$this->next();
618
-
619
-			return $r;
620
-		}
621
-	}
622
-
623
-	// retourner la cle pour #CLE
624
-	public function cle() {
625
-		return $this->key();
626
-	}
627
-
628
-	// retourner la valeur pour #VALEUR
629
-	public function valeur() {
630
-		return $this->current();
631
-	}
632
-
633
-	/**
634
-	 * Accepte-t-on l'entree courante lue ?
635
-	 * On execute les filtres pour le savoir.
636
-	 **/
637
-	public function accept(): bool {
638
-		if ($f = $this->func_filtre) {
639
-			return $f();
640
-		}
641
-
642
-		return true;
643
-	}
644
-
645
-	/**
646
-	 * liberer la ressource
647
-	 *
648
-	 * @return bool
649
-	 */
650
-	public function free() {
651
-		if (method_exists($this->iter, 'free')) {
652
-			$this->iter->free();
653
-		}
654
-		$this->pos = $this->total = 0;
655
-
656
-		return true;
657
-	}
658
-
659
-	/**
660
-	 * Compter le nombre total de resultats
661
-	 * pour #TOTAL_BOUCLE
662
-	 *
663
-	 * @return int
664
-	 */
665
-	public function count() {
666
-		if (is_null($this->total)) {
667
-			if (
668
-				method_exists($this->iter, 'count')
669
-				and !$this->func_filtre
670
-			) {
671
-				return $this->total = $this->iter->count();
672
-			} else {
673
-				// compter les lignes et rembobiner
674
-				$total = 0;
675
-				$pos = $this->pos; // sauver la position
676
-				$this->rewind();
677
-				while ($this->fetch() and $total < $this->max) {
678
-					$total++;
679
-				}
680
-				$this->seek($pos);
681
-				$this->total = $total;
682
-			}
683
-		}
684
-
685
-		return $this->total;
686
-	}
537
+    private function seek_loop($n) {
538
+        if ($this->pos > $n) {
539
+            $this->rewind();
540
+        }
541
+
542
+        while ($this->pos < $n and $this->valid()) {
543
+            $this->next();
544
+        }
545
+
546
+        return true;
547
+    }
548
+
549
+    /**
550
+     * Avancer de $saut pas
551
+     *
552
+     * @param  $saut
553
+     * @param  $max
554
+     * @return int
555
+     */
556
+    public function skip($saut, $max = null) {
557
+        // pas de saut en arriere autorise pour cette fonction
558
+        if (($saut = intval($saut)) <= 0) {
559
+            return $this->pos;
560
+        }
561
+        $seek = $this->pos + $saut;
562
+        // si le saut fait depasser le maxi, on libere la resource
563
+        // et on sort
564
+        if (is_null($max)) {
565
+            $max = $this->count();
566
+        }
567
+
568
+        if ($seek >= $max or $seek >= $this->count()) {
569
+            // sortie plus rapide que de faire next() jusqu'a la fin !
570
+            $this->free();
571
+
572
+            return $max;
573
+        }
574
+
575
+        $this->seek($seek);
576
+
577
+        return $this->pos;
578
+    }
579
+
580
+    /**
581
+     * Renvoyer un tableau des donnees correspondantes
582
+     * a la position courante de l'iterateur
583
+     * en controlant si on respecte le filtre
584
+     * Appliquer aussi le critere {offset,limit}
585
+     *
586
+     * @return array|bool
587
+     */
588
+    public function fetch() {
589
+        if (method_exists($this->iter, 'fetch')) {
590
+            return $this->iter->fetch();
591
+        } else {
592
+            while (
593
+                $this->valid()
594
+                and (
595
+                    !$this->accept()
596
+                    or (isset($this->offset) and $this->fetched++ < $this->offset)
597
+                )
598
+            ) {
599
+                $this->next();
600
+            }
601
+
602
+            if (!$this->valid()) {
603
+                return false;
604
+            }
605
+
606
+            if (
607
+                isset($this->limit)
608
+                and $this->fetched > $this->offset + $this->limit
609
+            ) {
610
+                return false;
611
+            }
612
+
613
+            $r = [];
614
+            foreach ($this->select as $nom) {
615
+                $r[$nom] = $this->get_select($nom);
616
+            }
617
+            $this->next();
618
+
619
+            return $r;
620
+        }
621
+    }
622
+
623
+    // retourner la cle pour #CLE
624
+    public function cle() {
625
+        return $this->key();
626
+    }
627
+
628
+    // retourner la valeur pour #VALEUR
629
+    public function valeur() {
630
+        return $this->current();
631
+    }
632
+
633
+    /**
634
+     * Accepte-t-on l'entree courante lue ?
635
+     * On execute les filtres pour le savoir.
636
+     **/
637
+    public function accept(): bool {
638
+        if ($f = $this->func_filtre) {
639
+            return $f();
640
+        }
641
+
642
+        return true;
643
+    }
644
+
645
+    /**
646
+     * liberer la ressource
647
+     *
648
+     * @return bool
649
+     */
650
+    public function free() {
651
+        if (method_exists($this->iter, 'free')) {
652
+            $this->iter->free();
653
+        }
654
+        $this->pos = $this->total = 0;
655
+
656
+        return true;
657
+    }
658
+
659
+    /**
660
+     * Compter le nombre total de resultats
661
+     * pour #TOTAL_BOUCLE
662
+     *
663
+     * @return int
664
+     */
665
+    public function count() {
666
+        if (is_null($this->total)) {
667
+            if (
668
+                method_exists($this->iter, 'count')
669
+                and !$this->func_filtre
670
+            ) {
671
+                return $this->total = $this->iter->count();
672
+            } else {
673
+                // compter les lignes et rembobiner
674
+                $total = 0;
675
+                $pos = $this->pos; // sauver la position
676
+                $this->rewind();
677
+                while ($this->fetch() and $total < $this->max) {
678
+                    $total++;
679
+                }
680
+                $this->seek($pos);
681
+                $this->total = $total;
682
+            }
683
+        }
684
+
685
+        return $this->total;
686
+    }
687 687
 }
Please login to merge, or discard this patch.
ecrire/inc/minipres.php 1 patch
Indentation   +138 added lines, -138 removed lines patch added patch discarded remove patch
@@ -16,7 +16,7 @@  discard block
 block discarded – undo
16 16
  * @package SPIP\Core\Minipres
17 17
  **/
18 18
 if (!defined('_ECRIRE_INC_VERSION')) {
19
-	return;
19
+    return;
20 20
 }
21 21
 
22 22
 include_spip('inc/headers');
@@ -46,61 +46,61 @@  discard block
 block discarded – undo
46 46
  */
47 47
 function install_debut_html($titre = 'AUTO', $onLoad = '', $all_inline = false) {
48 48
 
49
-	utiliser_langue_visiteur();
50
-
51
-	http_no_cache();
52
-
53
-	if ($titre == 'AUTO') {
54
-		$titre = _T('info_installation_systeme_publication');
55
-	}
56
-
57
-	# le charset est en utf-8, pour recuperer le nom comme il faut
58
-	# lors de l'installation
59
-	if (!headers_sent()) {
60
-		header('Content-Type: text/html; charset=utf-8');
61
-	}
62
-
63
-	$css = '';
64
-	$files = ['reset.css', 'clear.css', 'minipres.css'];
65
-	if ($all_inline) {
66
-		// inliner les CSS (optimisation de la page minipres qui passe en un seul hit a la demande)
67
-		foreach ($files as $name) {
68
-			$file = direction_css(find_in_theme($name));
69
-			if (function_exists('minifier')) {
70
-				$file = minifier($file);
71
-			} else {
72
-				$file = url_absolue_css($file); // precaution
73
-			}
74
-			lire_fichier($file, $c);
75
-			$css .= $c;
76
-		}
77
-		$css = "<style type='text/css'>" . $css . '</style>';
78
-	} else {
79
-		foreach ($files as $name) {
80
-			$file = direction_css(find_in_theme($name));
81
-			$css .= "<link rel='stylesheet' href='$file' type='text/css' />\n";
82
-		}
83
-	}
84
-
85
-	// au cas ou minipres() est appele avant spip_initialisation_suite()
86
-	if (!defined('_DOCTYPE_ECRIRE')) {
87
-		define('_DOCTYPE_ECRIRE', '');
88
-	}
89
-
90
-	return _DOCTYPE_ECRIRE .
91
-	html_lang_attributes() .
92
-	"<head>\n" .
93
-	'<title>' .
94
-	textebrut($titre) .
95
-	"</title>\n" .
96
-	"<meta name='viewport' content='width=device-width' />\n" .
97
-	$css .
98
-	'</head>
49
+    utiliser_langue_visiteur();
50
+
51
+    http_no_cache();
52
+
53
+    if ($titre == 'AUTO') {
54
+        $titre = _T('info_installation_systeme_publication');
55
+    }
56
+
57
+    # le charset est en utf-8, pour recuperer le nom comme il faut
58
+    # lors de l'installation
59
+    if (!headers_sent()) {
60
+        header('Content-Type: text/html; charset=utf-8');
61
+    }
62
+
63
+    $css = '';
64
+    $files = ['reset.css', 'clear.css', 'minipres.css'];
65
+    if ($all_inline) {
66
+        // inliner les CSS (optimisation de la page minipres qui passe en un seul hit a la demande)
67
+        foreach ($files as $name) {
68
+            $file = direction_css(find_in_theme($name));
69
+            if (function_exists('minifier')) {
70
+                $file = minifier($file);
71
+            } else {
72
+                $file = url_absolue_css($file); // precaution
73
+            }
74
+            lire_fichier($file, $c);
75
+            $css .= $c;
76
+        }
77
+        $css = "<style type='text/css'>" . $css . '</style>';
78
+    } else {
79
+        foreach ($files as $name) {
80
+            $file = direction_css(find_in_theme($name));
81
+            $css .= "<link rel='stylesheet' href='$file' type='text/css' />\n";
82
+        }
83
+    }
84
+
85
+    // au cas ou minipres() est appele avant spip_initialisation_suite()
86
+    if (!defined('_DOCTYPE_ECRIRE')) {
87
+        define('_DOCTYPE_ECRIRE', '');
88
+    }
89
+
90
+    return _DOCTYPE_ECRIRE .
91
+    html_lang_attributes() .
92
+    "<head>\n" .
93
+    '<title>' .
94
+    textebrut($titre) .
95
+    "</title>\n" .
96
+    "<meta name='viewport' content='width=device-width' />\n" .
97
+    $css .
98
+    '</head>
99 99
 <body' . $onLoad . " class='minipres'>
100 100
 	<div id='minipres'>
101 101
 	<h1>" .
102
-	$titre .
103
-	"</h1>
102
+    $titre .
103
+    "</h1>
104 104
 	<div>\n";
105 105
 }
106 106
 
@@ -110,7 +110,7 @@  discard block
 block discarded – undo
110 110
  * @return string Code HTML
111 111
  */
112 112
 function install_fin_html() {
113
-	return "\n\t</div>\n\t</div>\n</body>\n</html>";
113
+    return "\n\t</div>\n\t</div>\n</body>\n</html>";
114 114
 }
115 115
 
116 116
 
@@ -148,88 +148,88 @@  discard block
 block discarded – undo
148 148
  */
149 149
 function minipres($titre = '', $corps = '', $options = []) {
150 150
 
151
-	// compat signature old
152
-	// minipres($titre='', $corps="", $onload='', $all_inline = false)
153
-	$args = func_get_args();
154
-	if (isset($args[2]) and is_string($args[2])) {
155
-		$options = ['onload' => $args[2]];
156
-	}
157
-	if (isset($args[3])) {
158
-		$options['all_inline'] = $args[3];
159
-	}
160
-
161
-	$options = array_merge([
162
-		'onload' => '',
163
-		'all_inline' => false,
164
-	], $options);
165
-
166
-	if (!defined('_AJAX')) {
167
-		define('_AJAX', false);
168
-	} // par securite
169
-	if (!$titre) {
170
-		if (!isset($options['status'])) {
171
-			$options['status'] = 403;
172
-		}
173
-		if (
174
-			!$titre = _request('action')
175
-			and !$titre = _request('exec')
176
-			and !$titre = _request('page')
177
-		) {
178
-			$titre = '?';
179
-		}
180
-
181
-		$titre = spip_htmlspecialchars($titre);
182
-
183
-		$titre = ($titre == 'install')
184
-			? _T('avis_espace_interdit')
185
-			: $titre . '&nbsp;: ' . _T('info_acces_interdit');
186
-
187
-		$statut = $GLOBALS['visiteur_session']['statut'] ?? '';
188
-		$nom = $GLOBALS['visiteur_session']['nom'] ?? '';
189
-
190
-		if ($statut != '0minirezo') {
191
-			$titre = _T('info_acces_interdit');
192
-		}
193
-
194
-		if ($statut and test_espace_prive()) {
195
-			$corps = bouton_action(_T('public:accueil_site'), generer_url_ecrire('accueil'));
196
-		}
197
-		elseif (!empty($_COOKIE['spip_admin'])) {
198
-			$corps = bouton_action(_T('public:lien_connecter'), generer_url_public('login'));
199
-		}
200
-		else {
201
-			$corps = bouton_action(_T('public:accueil_site'), $GLOBALS['meta']['adresse_site']);
202
-		}
203
-		$corps = "<div class='boutons'>$corps</div>";
204
-		spip_log($nom . " $titre " . $_SERVER['REQUEST_URI']);
205
-	}
206
-
207
-	if (!_AJAX) {
208
-		if (isset($options['status'])) {
209
-			http_response_code($options['status']);
210
-		}
211
-
212
-		$html = install_debut_html($titre, $options['onload'], $options['all_inline'])
213
-				. $corps
214
-				. install_fin_html();
215
-
216
-		if (
217
-			$GLOBALS['profondeur_url'] >= (_DIR_RESTREINT ? 1 : 2)
218
-			and empty($options['all_inline'])
219
-		) {
220
-			define('_SET_HTML_BASE', true);
221
-			include_spip('public/assembler');
222
-			$GLOBALS['html'] = true;
223
-			page_base_href($html);
224
-		}
225
-		return $html;
226
-	} else {
227
-		include_spip('inc/headers');
228
-		include_spip('inc/actions');
229
-		$url = self('&', true);
230
-		foreach ($_POST as $v => $c) {
231
-			$url = parametre_url($url, $v, $c, '&');
232
-		}
233
-		ajax_retour('<div>' . $titre . redirige_formulaire($url) . '</div>', false);
234
-	}
151
+    // compat signature old
152
+    // minipres($titre='', $corps="", $onload='', $all_inline = false)
153
+    $args = func_get_args();
154
+    if (isset($args[2]) and is_string($args[2])) {
155
+        $options = ['onload' => $args[2]];
156
+    }
157
+    if (isset($args[3])) {
158
+        $options['all_inline'] = $args[3];
159
+    }
160
+
161
+    $options = array_merge([
162
+        'onload' => '',
163
+        'all_inline' => false,
164
+    ], $options);
165
+
166
+    if (!defined('_AJAX')) {
167
+        define('_AJAX', false);
168
+    } // par securite
169
+    if (!$titre) {
170
+        if (!isset($options['status'])) {
171
+            $options['status'] = 403;
172
+        }
173
+        if (
174
+            !$titre = _request('action')
175
+            and !$titre = _request('exec')
176
+            and !$titre = _request('page')
177
+        ) {
178
+            $titre = '?';
179
+        }
180
+
181
+        $titre = spip_htmlspecialchars($titre);
182
+
183
+        $titre = ($titre == 'install')
184
+            ? _T('avis_espace_interdit')
185
+            : $titre . '&nbsp;: ' . _T('info_acces_interdit');
186
+
187
+        $statut = $GLOBALS['visiteur_session']['statut'] ?? '';
188
+        $nom = $GLOBALS['visiteur_session']['nom'] ?? '';
189
+
190
+        if ($statut != '0minirezo') {
191
+            $titre = _T('info_acces_interdit');
192
+        }
193
+
194
+        if ($statut and test_espace_prive()) {
195
+            $corps = bouton_action(_T('public:accueil_site'), generer_url_ecrire('accueil'));
196
+        }
197
+        elseif (!empty($_COOKIE['spip_admin'])) {
198
+            $corps = bouton_action(_T('public:lien_connecter'), generer_url_public('login'));
199
+        }
200
+        else {
201
+            $corps = bouton_action(_T('public:accueil_site'), $GLOBALS['meta']['adresse_site']);
202
+        }
203
+        $corps = "<div class='boutons'>$corps</div>";
204
+        spip_log($nom . " $titre " . $_SERVER['REQUEST_URI']);
205
+    }
206
+
207
+    if (!_AJAX) {
208
+        if (isset($options['status'])) {
209
+            http_response_code($options['status']);
210
+        }
211
+
212
+        $html = install_debut_html($titre, $options['onload'], $options['all_inline'])
213
+                . $corps
214
+                . install_fin_html();
215
+
216
+        if (
217
+            $GLOBALS['profondeur_url'] >= (_DIR_RESTREINT ? 1 : 2)
218
+            and empty($options['all_inline'])
219
+        ) {
220
+            define('_SET_HTML_BASE', true);
221
+            include_spip('public/assembler');
222
+            $GLOBALS['html'] = true;
223
+            page_base_href($html);
224
+        }
225
+        return $html;
226
+    } else {
227
+        include_spip('inc/headers');
228
+        include_spip('inc/actions');
229
+        $url = self('&', true);
230
+        foreach ($_POST as $v => $c) {
231
+            $url = parametre_url($url, $v, $c, '&');
232
+        }
233
+        ajax_retour('<div>' . $titre . redirige_formulaire($url) . '</div>', false);
234
+    }
235 235
 }
Please login to merge, or discard this patch.
ecrire/inc/documents.php 1 patch
Indentation   +227 added lines, -227 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
 /**
@@ -30,12 +30,12 @@  discard block
 block discarded – undo
30 30
  * @return string
31 31
  */
32 32
 function set_spip_doc(?string $fichier): string {
33
-	if ($fichier and strpos($fichier, (string) _DIR_IMG) === 0) {
34
-		return substr($fichier, strlen(_DIR_IMG));
35
-	} else {
36
-		// ex: fichier distant
37
-		return $fichier ?? '';
38
-	}
33
+    if ($fichier and strpos($fichier, (string) _DIR_IMG) === 0) {
34
+        return substr($fichier, strlen(_DIR_IMG));
35
+    } else {
36
+        // ex: fichier distant
37
+        return $fichier ?? '';
38
+    }
39 39
 }
40 40
 
41 41
 /**
@@ -47,26 +47,26 @@  discard block
 block discarded – undo
47 47
  * @return bool|string
48 48
  */
49 49
 function get_spip_doc(?string $fichier) {
50
-	if ($fichier === null) {
51
-		return false;
52
-	}
53
-
54
-	// fichier distant
55
-	if (tester_url_absolue($fichier)) {
56
-		return $fichier;
57
-	}
58
-
59
-	// gestion d'erreurs, fichier=''
60
-	if (!strlen($fichier)) {
61
-		return false;
62
-	}
63
-
64
-	if (strncmp($fichier, _DIR_IMG, strlen(_DIR_IMG)) !== 0) {
65
-		$fichier = _DIR_IMG . $fichier;
66
-	}
67
-
68
-	// fichier normal
69
-	return $fichier;
50
+    if ($fichier === null) {
51
+        return false;
52
+    }
53
+
54
+    // fichier distant
55
+    if (tester_url_absolue($fichier)) {
56
+        return $fichier;
57
+    }
58
+
59
+    // gestion d'erreurs, fichier=''
60
+    if (!strlen($fichier)) {
61
+        return false;
62
+    }
63
+
64
+    if (strncmp($fichier, _DIR_IMG, strlen(_DIR_IMG)) !== 0) {
65
+        $fichier = _DIR_IMG . $fichier;
66
+    }
67
+
68
+    // fichier normal
69
+    return $fichier;
70 70
 }
71 71
 
72 72
 /**
@@ -80,26 +80,26 @@  discard block
 block discarded – undo
80 80
  * @return string
81 81
  */
82 82
 function creer_repertoire_documents($ext) {
83
-	$rep = sous_repertoire(_DIR_IMG, $ext);
84
-
85
-	if (!$ext or !$rep) {
86
-		spip_log("creer_repertoire_documents '$rep' interdit");
87
-		exit;
88
-	}
89
-
90
-	// Cette variable de configuration peut etre posee par un plugin
91
-	// par exemple acces_restreint
92
-	// sauf pour logo/ utilise pour stocker les logoon et logooff
93
-	if (
94
-		isset($GLOBALS['meta']['creer_htaccess'])
95
-		and $GLOBALS['meta']['creer_htaccess'] == 'oui'
96
-		and $ext !== 'logo'
97
-	) {
98
-		include_spip('inc/acces');
99
-		verifier_htaccess($rep);
100
-	}
101
-
102
-	return $rep;
83
+    $rep = sous_repertoire(_DIR_IMG, $ext);
84
+
85
+    if (!$ext or !$rep) {
86
+        spip_log("creer_repertoire_documents '$rep' interdit");
87
+        exit;
88
+    }
89
+
90
+    // Cette variable de configuration peut etre posee par un plugin
91
+    // par exemple acces_restreint
92
+    // sauf pour logo/ utilise pour stocker les logoon et logooff
93
+    if (
94
+        isset($GLOBALS['meta']['creer_htaccess'])
95
+        and $GLOBALS['meta']['creer_htaccess'] == 'oui'
96
+        and $ext !== 'logo'
97
+    ) {
98
+        include_spip('inc/acces');
99
+        verifier_htaccess($rep);
100
+    }
101
+
102
+    return $rep;
103 103
 }
104 104
 
105 105
 /**
@@ -108,22 +108,22 @@  discard block
 block discarded – undo
108 108
  * @param string $nom
109 109
  */
110 110
 function effacer_repertoire_temporaire($nom) {
111
-	if ($d = opendir($nom)) {
112
-		while (($f = readdir($d)) !== false) {
113
-			if (is_file("$nom/$f")) {
114
-				spip_unlink("$nom/$f");
115
-			} else {
116
-				if (
117
-					$f <> '.' and $f <> '..'
118
-					and is_dir("$nom/$f")
119
-				) {
120
-					effacer_repertoire_temporaire("$nom/$f");
121
-				}
122
-			}
123
-		}
124
-	}
125
-	closedir($d);
126
-	@rmdir($nom);
111
+    if ($d = opendir($nom)) {
112
+        while (($f = readdir($d)) !== false) {
113
+            if (is_file("$nom/$f")) {
114
+                spip_unlink("$nom/$f");
115
+            } else {
116
+                if (
117
+                    $f <> '.' and $f <> '..'
118
+                    and is_dir("$nom/$f")
119
+                ) {
120
+                    effacer_repertoire_temporaire("$nom/$f");
121
+                }
122
+            }
123
+        }
124
+    }
125
+    closedir($d);
126
+    @rmdir($nom);
127 127
 }
128 128
 
129 129
 //
@@ -140,45 +140,45 @@  discard block
 block discarded – undo
140 140
  */
141 141
 function copier_document($ext, $orig, $source, $subdir = null) {
142 142
 
143
-	$orig = preg_replace(',\.\.+,', '.', $orig); // pas de .. dans le nom du doc
144
-	$dir = creer_repertoire_documents($subdir ?: $ext);
145
-
146
-	$dest = preg_replace('/<[^>]*>/', '', basename($orig));
147
-	$dest = preg_replace('/\.([^.]+)$/', '', $dest);
148
-	$dest = translitteration($dest);
149
-	$dest = preg_replace('/[^.=\w-]+/', '_', $dest);
150
-
151
-	// ne pas accepter de noms de la forme -r90.jpg qui sont reserves
152
-	// pour les images transformees par rotation (action/documenter)
153
-	$dest = preg_replace(',-r(90|180|270)$,', '', $dest);
154
-
155
-	while (preg_match(',\.(\w+)$,', $dest, $m)) {
156
-		if (
157
-			!function_exists('verifier_upload_autorise')
158
-			or !$r = verifier_upload_autorise($dest)
159
-			or $r['autozip']
160
-		) {
161
-			$dest = substr($dest, 0, -strlen($m[0])) . '_' . $m[1];
162
-			break;
163
-		}
164
-		else {
165
-			$dest = substr($dest, 0, -strlen($m[0]));
166
-			$ext = $m[1] . '.' . $ext;
167
-		}
168
-	}
169
-
170
-	// Si le document "source" est deja au bon endroit, ne rien faire
171
-	if ($source == ($dir . $dest . '.' . $ext)) {
172
-		return $source;
173
-	}
174
-
175
-	// sinon tourner jusqu'a trouver un numero correct
176
-	$n = 0;
177
-	while (@file_exists($newFile = $dir . $dest . ($n++ ? ('-' . $n) : '') . '.' . $ext)) {
178
-		;
179
-	}
180
-
181
-	return deplacer_fichier_upload($source, $newFile);
143
+    $orig = preg_replace(',\.\.+,', '.', $orig); // pas de .. dans le nom du doc
144
+    $dir = creer_repertoire_documents($subdir ?: $ext);
145
+
146
+    $dest = preg_replace('/<[^>]*>/', '', basename($orig));
147
+    $dest = preg_replace('/\.([^.]+)$/', '', $dest);
148
+    $dest = translitteration($dest);
149
+    $dest = preg_replace('/[^.=\w-]+/', '_', $dest);
150
+
151
+    // ne pas accepter de noms de la forme -r90.jpg qui sont reserves
152
+    // pour les images transformees par rotation (action/documenter)
153
+    $dest = preg_replace(',-r(90|180|270)$,', '', $dest);
154
+
155
+    while (preg_match(',\.(\w+)$,', $dest, $m)) {
156
+        if (
157
+            !function_exists('verifier_upload_autorise')
158
+            or !$r = verifier_upload_autorise($dest)
159
+            or $r['autozip']
160
+        ) {
161
+            $dest = substr($dest, 0, -strlen($m[0])) . '_' . $m[1];
162
+            break;
163
+        }
164
+        else {
165
+            $dest = substr($dest, 0, -strlen($m[0]));
166
+            $ext = $m[1] . '.' . $ext;
167
+        }
168
+    }
169
+
170
+    // Si le document "source" est deja au bon endroit, ne rien faire
171
+    if ($source == ($dir . $dest . '.' . $ext)) {
172
+        return $source;
173
+    }
174
+
175
+    // sinon tourner jusqu'a trouver un numero correct
176
+    $n = 0;
177
+    while (@file_exists($newFile = $dir . $dest . ($n++ ? ('-' . $n) : '') . '.' . $ext)) {
178
+        ;
179
+    }
180
+
181
+    return deplacer_fichier_upload($source, $newFile);
182 182
 }
183 183
 
184 184
 /**
@@ -193,28 +193,28 @@  discard block
 block discarded – undo
193 193
  * @return bool|string
194 194
  */
195 195
 function determine_upload($type = '') {
196
-	if (!function_exists('autoriser')) {
197
-		include_spip('inc/autoriser');
198
-	}
199
-
200
-	if (
201
-		!autoriser('chargerftp')
202
-		or $type == 'logos'
203
-	) { # on ne le permet pas pour les logos
204
-	return false;
205
-	}
206
-
207
-	$repertoire = _DIR_TRANSFERT;
208
-	if (!@is_dir($repertoire)) {
209
-		$repertoire = str_replace(_DIR_TMP, '', $repertoire);
210
-		$repertoire = sous_repertoire(_DIR_TMP, $repertoire);
211
-	}
212
-
213
-	if (!$GLOBALS['visiteur_session']['restreint']) {
214
-		return $repertoire;
215
-	} else {
216
-		return sous_repertoire($repertoire, $GLOBALS['visiteur_session']['login']);
217
-	}
196
+    if (!function_exists('autoriser')) {
197
+        include_spip('inc/autoriser');
198
+    }
199
+
200
+    if (
201
+        !autoriser('chargerftp')
202
+        or $type == 'logos'
203
+    ) { # on ne le permet pas pour les logos
204
+    return false;
205
+    }
206
+
207
+    $repertoire = _DIR_TRANSFERT;
208
+    if (!@is_dir($repertoire)) {
209
+        $repertoire = str_replace(_DIR_TMP, '', $repertoire);
210
+        $repertoire = sous_repertoire(_DIR_TMP, $repertoire);
211
+    }
212
+
213
+    if (!$GLOBALS['visiteur_session']['restreint']) {
214
+        return $repertoire;
215
+    } else {
216
+        return sous_repertoire($repertoire, $GLOBALS['visiteur_session']['login']);
217
+    }
218 218
 }
219 219
 
220 220
 /**
@@ -233,35 +233,35 @@  discard block
 block discarded – undo
233 233
  * @return bool|mixed|string
234 234
  */
235 235
 function deplacer_fichier_upload($source, $dest, $move = false) {
236
-	// Securite
237
-	if (substr($dest, 0, strlen(_DIR_RACINE)) == _DIR_RACINE) {
238
-		$dest = _DIR_RACINE . preg_replace(',\.\.+,', '.', substr($dest, strlen(_DIR_RACINE)));
239
-	} else {
240
-		$dest = preg_replace(',\.\.+,', '.', $dest);
241
-	}
242
-
243
-	if ($move) {
244
-		$ok = @rename($source, $dest);
245
-	} else {
246
-		$ok = @copy($source, $dest);
247
-	}
248
-	if (!$ok) {
249
-		$ok = @move_uploaded_file($source, $dest);
250
-	}
251
-	if ($ok) {
252
-		@chmod($dest, _SPIP_CHMOD & ~0111);
253
-	} else {
254
-		$f = @fopen($dest, 'w');
255
-		if ($f) {
256
-			fclose($f);
257
-		} else {
258
-			include_spip('inc/flock');
259
-			raler_fichier($dest);
260
-		}
261
-		spip_unlink($dest);
262
-	}
263
-
264
-	return $ok ? $dest : false;
236
+    // Securite
237
+    if (substr($dest, 0, strlen(_DIR_RACINE)) == _DIR_RACINE) {
238
+        $dest = _DIR_RACINE . preg_replace(',\.\.+,', '.', substr($dest, strlen(_DIR_RACINE)));
239
+    } else {
240
+        $dest = preg_replace(',\.\.+,', '.', $dest);
241
+    }
242
+
243
+    if ($move) {
244
+        $ok = @rename($source, $dest);
245
+    } else {
246
+        $ok = @copy($source, $dest);
247
+    }
248
+    if (!$ok) {
249
+        $ok = @move_uploaded_file($source, $dest);
250
+    }
251
+    if ($ok) {
252
+        @chmod($dest, _SPIP_CHMOD & ~0111);
253
+    } else {
254
+        $f = @fopen($dest, 'w');
255
+        if ($f) {
256
+            fclose($f);
257
+        } else {
258
+            include_spip('inc/flock');
259
+            raler_fichier($dest);
260
+        }
261
+        spip_unlink($dest);
262
+    }
263
+
264
+    return $ok ? $dest : false;
265 265
 }
266 266
 
267 267
 
@@ -285,60 +285,60 @@  discard block
 block discarded – undo
285 285
  */
286 286
 function check_upload_error($error, $msg = '', $return = false) {
287 287
 
288
-	if (!$error) {
289
-		return false;
290
-	}
291
-
292
-	spip_log("Erreur upload $error -- cf. http://php.net/manual/fr/features.file-upload.errors.php");
293
-
294
-	switch ($error) {
295
-		case 4: /* UPLOAD_ERR_NO_FILE */
296
-			return true;
297
-
298
-		# on peut affiner les differents messages d'erreur
299
-		case 1: /* UPLOAD_ERR_INI_SIZE */
300
-			$msg = _T(
301
-				'upload_limit',
302
-				['max' => ini_get('upload_max_filesize')]
303
-			);
304
-			break;
305
-		case 2: /* UPLOAD_ERR_FORM_SIZE */
306
-			$msg = _T(
307
-				'upload_limit',
308
-				['max' => ini_get('upload_max_filesize')]
309
-			);
310
-			break;
311
-		case 3: /* UPLOAD_ERR_PARTIAL  */
312
-			$msg = _T(
313
-				'upload_limit',
314
-				['max' => ini_get('upload_max_filesize')]
315
-			);
316
-			break;
317
-
318
-		default: /* autre */
319
-			if (!$msg) {
320
-				$msg = _T('pass_erreur') . ' ' . $error
321
-					. '<br />' . propre('[->http://php.net/manual/fr/features.file-upload.errors.php]');
322
-			}
323
-			break;
324
-	}
325
-
326
-	spip_log("erreur upload $error");
327
-	if ($return) {
328
-		return $msg;
329
-	}
330
-
331
-	if (_request('iframe') == 'iframe') {
332
-		echo "<div class='upload_answer upload_error'>$msg</div>";
333
-		exit;
334
-	}
335
-
336
-	include_spip('inc/minipres');
337
-	echo minipres(
338
-		$msg,
339
-		"<div style='text-align: " . $GLOBALS['spip_lang_right'] . "'><a href='" . rawurldecode($GLOBALS['redirect']) . "'><button type='button'>" . _T('ecrire:bouton_suivant') . '</button></a></div>'
340
-	);
341
-	exit;
288
+    if (!$error) {
289
+        return false;
290
+    }
291
+
292
+    spip_log("Erreur upload $error -- cf. http://php.net/manual/fr/features.file-upload.errors.php");
293
+
294
+    switch ($error) {
295
+        case 4: /* UPLOAD_ERR_NO_FILE */
296
+            return true;
297
+
298
+        # on peut affiner les differents messages d'erreur
299
+        case 1: /* UPLOAD_ERR_INI_SIZE */
300
+            $msg = _T(
301
+                'upload_limit',
302
+                ['max' => ini_get('upload_max_filesize')]
303
+            );
304
+            break;
305
+        case 2: /* UPLOAD_ERR_FORM_SIZE */
306
+            $msg = _T(
307
+                'upload_limit',
308
+                ['max' => ini_get('upload_max_filesize')]
309
+            );
310
+            break;
311
+        case 3: /* UPLOAD_ERR_PARTIAL  */
312
+            $msg = _T(
313
+                'upload_limit',
314
+                ['max' => ini_get('upload_max_filesize')]
315
+            );
316
+            break;
317
+
318
+        default: /* autre */
319
+            if (!$msg) {
320
+                $msg = _T('pass_erreur') . ' ' . $error
321
+                    . '<br />' . propre('[->http://php.net/manual/fr/features.file-upload.errors.php]');
322
+            }
323
+            break;
324
+    }
325
+
326
+    spip_log("erreur upload $error");
327
+    if ($return) {
328
+        return $msg;
329
+    }
330
+
331
+    if (_request('iframe') == 'iframe') {
332
+        echo "<div class='upload_answer upload_error'>$msg</div>";
333
+        exit;
334
+    }
335
+
336
+    include_spip('inc/minipres');
337
+    echo minipres(
338
+        $msg,
339
+        "<div style='text-align: " . $GLOBALS['spip_lang_right'] . "'><a href='" . rawurldecode($GLOBALS['redirect']) . "'><button type='button'>" . _T('ecrire:bouton_suivant') . '</button></a></div>'
340
+    );
341
+    exit;
342 342
 }
343 343
 
344 344
 /**
@@ -355,24 +355,24 @@  discard block
 block discarded – undo
355 355
  * @return string
356 356
  */
357 357
 function corriger_extension($ext) {
358
-	$ext = preg_replace(',[^a-z0-9],i', '', $ext);
359
-	switch ($ext) {
360
-		case 'htm':
361
-			$ext = 'html';
362
-			break;
363
-		case 'jpeg':
364
-			$ext = 'jpg';
365
-			break;
366
-		case 'tiff':
367
-			$ext = 'tif';
368
-			break;
369
-		case 'aif':
370
-			$ext = 'aiff';
371
-			break;
372
-		case 'mpeg':
373
-			$ext = 'mpg';
374
-			break;
375
-	}
376
-
377
-	return $ext;
358
+    $ext = preg_replace(',[^a-z0-9],i', '', $ext);
359
+    switch ($ext) {
360
+        case 'htm':
361
+            $ext = 'html';
362
+            break;
363
+        case 'jpeg':
364
+            $ext = 'jpg';
365
+            break;
366
+        case 'tiff':
367
+            $ext = 'tif';
368
+            break;
369
+        case 'aif':
370
+            $ext = 'aiff';
371
+            break;
372
+        case 'mpeg':
373
+            $ext = 'mpg';
374
+            break;
375
+    }
376
+
377
+    return $ext;
378 378
 }
Please login to merge, or discard this patch.
ecrire/lang/spip_en.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' => 'Back to the full graphic interface',
14
-	'access_mode_texte' => 'Show the simplified text interface',
15
-	'admin_debug' => 'debug',
16
-	'admin_modifier_article' => 'Modify this article',
17
-	'admin_modifier_auteur' => 'Modify this author',
18
-	'admin_modifier_breve' => 'Modify this news item',
19
-	'admin_modifier_mot' => 'Modify this keyword',
20
-	'admin_modifier_rubrique' => 'Modify this section',
21
-	'admin_recalculer' => 'Re-process this page',
22
-	'afficher_calendrier' => 'Show the calendar',
23
-	'afficher_trad' => 'show translations',
24
-	'alerte_maj_impossible' => '<b>Warning!</b> Failed to update the SQL database to version @version@. This may be due to a permissions problem on the database. Please contact your ISP.',
25
-	'alerte_modif_info_concourante' => 'WARNING: This information has been modified elsewhere. The current value is :',
26
-	'analyse_xml' => 'XML parsing',
27
-	'annuler' => 'Cancel',
28
-	'antispam_champ_vide' => 'Please leave this field empty:',
29
-	'articles_recents' => 'Most recent articles',
30
-	'attention_champ_mini_nb_caractères' => 'Warning! At least @nb@ characters',
31
-	'avis_1_erreur_saisie' => 'Your entry contains an error, please check your information.',
32
-	'avis_archive_incorrect' => 'archive is not a valid SPIP file',
33
-	'avis_archive_invalide' => 'archive file is not valid',
34
-	'avis_attention' => 'CAUTION!',
35
-	'avis_champ_incorrect_type_objet' => 'Invalid field name @name@ for object of type @type@',
36
-	'avis_colonne_inexistante' => 'Column @col@ does not exist',
37
-	'avis_erreur' => 'Error: see below',
38
-	'avis_erreur_connexion' => 'Connection error',
39
-	'avis_erreur_cookie' => 'cookie problem',
40
-	'avis_erreur_fonction_contexte' => 'Programming error. This function cannot be called in this context.',
41
-	'avis_erreur_mysql' => 'SQL error',
42
-	'avis_erreur_sauvegarde' => 'Error in backup (@type@ @id_objet@)!',
43
-	'avis_erreur_visiteur' => 'Problem entering the private area',
44
-	'avis_nb_erreurs_saisie' => 'Your entry contains @nb@ errors, please check your information.',
12
+    // A
13
+    'access_interface_graphique' => 'Back to the full graphic interface',
14
+    'access_mode_texte' => 'Show the simplified text interface',
15
+    'admin_debug' => 'debug',
16
+    'admin_modifier_article' => 'Modify this article',
17
+    'admin_modifier_auteur' => 'Modify this author',
18
+    'admin_modifier_breve' => 'Modify this news item',
19
+    'admin_modifier_mot' => 'Modify this keyword',
20
+    'admin_modifier_rubrique' => 'Modify this section',
21
+    'admin_recalculer' => 'Re-process this page',
22
+    'afficher_calendrier' => 'Show the calendar',
23
+    'afficher_trad' => 'show translations',
24
+    'alerte_maj_impossible' => '<b>Warning!</b> Failed to update the SQL database to version @version@. This may be due to a permissions problem on the database. Please contact your ISP.',
25
+    'alerte_modif_info_concourante' => 'WARNING: This information has been modified elsewhere. The current value is :',
26
+    'analyse_xml' => 'XML parsing',
27
+    'annuler' => 'Cancel',
28
+    'antispam_champ_vide' => 'Please leave this field empty:',
29
+    'articles_recents' => 'Most recent articles',
30
+    'attention_champ_mini_nb_caractères' => 'Warning! At least @nb@ characters',
31
+    'avis_1_erreur_saisie' => 'Your entry contains an error, please check your information.',
32
+    'avis_archive_incorrect' => 'archive is not a valid SPIP file',
33
+    'avis_archive_invalide' => 'archive file is not valid',
34
+    'avis_attention' => 'CAUTION!',
35
+    'avis_champ_incorrect_type_objet' => 'Invalid field name @name@ for object of type @type@',
36
+    'avis_colonne_inexistante' => 'Column @col@ does not exist',
37
+    'avis_erreur' => 'Error: see below',
38
+    'avis_erreur_connexion' => 'Connection error',
39
+    'avis_erreur_cookie' => 'cookie problem',
40
+    'avis_erreur_fonction_contexte' => 'Programming error. This function cannot be called in this context.',
41
+    'avis_erreur_mysql' => 'SQL error',
42
+    'avis_erreur_sauvegarde' => 'Error in backup (@type@ @id_objet@)!',
43
+    'avis_erreur_visiteur' => 'Problem entering the private area',
44
+    'avis_nb_erreurs_saisie' => 'Your entry contains @nb@ errors, please check your information.',
45 45
 
46
-	// B
47
-	'barre_a_accent_grave' => 'Insert a capital A with grave accent',
48
-	'barre_aide' => 'Use the typographic short cuts to refine your layout',
49
-	'barre_e_accent_aigu' => 'Insert a capital E with acute accent',
50
-	'barre_eo' => 'Insert an oe-ligature',
51
-	'barre_eo_maj' => 'Insert a capital EO-ligature',
52
-	'barre_euro' => 'Insert a € symbol',
53
-	'barre_gras' => 'Put in {{bold type}}',
54
-	'barre_guillemets' => 'Place between "double quotes"',
55
-	'barre_guillemets_simples' => 'Place between ‘single quotes’',
56
-	'barre_intertitre' => 'Turn into a {{{subheading}}}',
57
-	'barre_italic' => 'Put in {italics}',
58
-	'barre_lien' => 'Turn into a [hyperlink->http://...]',
59
-	'barre_lien_input' => 'Please enter the link address. You may use either an external URL (http://www.mysite.com) or reference another article on this site by simplying entering its number.',
60
-	'barre_note' => 'Turn into a [[Footnote]]',
61
-	'barre_paragraphe' => 'Create a paragraph',
62
-	'barre_quote' => '<quote>Quote a message</quote>',
63
-	'bouton_changer' => 'Change',
64
-	'bouton_chercher' => 'Search',
65
-	'bouton_choisir' => 'Select',
66
-	'bouton_deplacer' => 'Move',
67
-	'bouton_download' => 'Download',
68
-	'bouton_enregistrer' => 'Save',
69
-	'bouton_radio_desactiver_messagerie_interne' => 'Disable internal messaging',
70
-	'bouton_radio_envoi_annonces' => 'Send editorial announcements',
71
-	'bouton_radio_non_envoi_annonces' => 'Do not send any announcements',
72
-	'bouton_radio_non_envoi_liste_nouveautes' => 'Do not send latest news list',
73
-	'bouton_recharger_page' => 'reload this page',
74
-	'bouton_telecharger' => 'Upload',
75
-	'bouton_upload' => 'Upload',
76
-	'bouton_valider' => 'Submit',
46
+    // B
47
+    'barre_a_accent_grave' => 'Insert a capital A with grave accent',
48
+    'barre_aide' => 'Use the typographic short cuts to refine your layout',
49
+    'barre_e_accent_aigu' => 'Insert a capital E with acute accent',
50
+    'barre_eo' => 'Insert an oe-ligature',
51
+    'barre_eo_maj' => 'Insert a capital EO-ligature',
52
+    'barre_euro' => 'Insert a € symbol',
53
+    'barre_gras' => 'Put in {{bold type}}',
54
+    'barre_guillemets' => 'Place between "double quotes"',
55
+    'barre_guillemets_simples' => 'Place between ‘single quotes’',
56
+    'barre_intertitre' => 'Turn into a {{{subheading}}}',
57
+    'barre_italic' => 'Put in {italics}',
58
+    'barre_lien' => 'Turn into a [hyperlink->http://...]',
59
+    'barre_lien_input' => 'Please enter the link address. You may use either an external URL (http://www.mysite.com) or reference another article on this site by simplying entering its number.',
60
+    'barre_note' => 'Turn into a [[Footnote]]',
61
+    'barre_paragraphe' => 'Create a paragraph',
62
+    'barre_quote' => '<quote>Quote a message</quote>',
63
+    'bouton_changer' => 'Change',
64
+    'bouton_chercher' => 'Search',
65
+    'bouton_choisir' => 'Select',
66
+    'bouton_deplacer' => 'Move',
67
+    'bouton_download' => 'Download',
68
+    'bouton_enregistrer' => 'Save',
69
+    'bouton_radio_desactiver_messagerie_interne' => 'Disable internal messaging',
70
+    'bouton_radio_envoi_annonces' => 'Send editorial announcements',
71
+    'bouton_radio_non_envoi_annonces' => 'Do not send any announcements',
72
+    'bouton_radio_non_envoi_liste_nouveautes' => 'Do not send latest news list',
73
+    'bouton_recharger_page' => 'reload this page',
74
+    'bouton_telecharger' => 'Upload',
75
+    'bouton_upload' => 'Upload',
76
+    'bouton_valider' => 'Submit',
77 77
 
78
-	// C
79
-	'cal_apresmidi' => 'afternoon (p.m.)',
80
-	'cal_jour_entier' => 'entire day',
81
-	'cal_matin' => 'morning (a.m.)',
82
-	'cal_par_jour' => 'daily calendar',
83
-	'cal_par_mois' => 'monthly calendar',
84
-	'cal_par_semaine' => 'weekly calendar',
85
-	'choix_couleur_interface' => 'colour',
86
-	'choix_interface' => 'choice of interface',
87
-	'colonne' => 'Column',
88
-	'confirm_changer_statut' => 'Warning: You are about to change this article’s status. Do you wish to continue?',
89
-	'correcte' => 'correct',
78
+    // C
79
+    'cal_apresmidi' => 'afternoon (p.m.)',
80
+    'cal_jour_entier' => 'entire day',
81
+    'cal_matin' => 'morning (a.m.)',
82
+    'cal_par_jour' => 'daily calendar',
83
+    'cal_par_mois' => 'monthly calendar',
84
+    'cal_par_semaine' => 'weekly calendar',
85
+    'choix_couleur_interface' => 'colour',
86
+    'choix_interface' => 'choice of interface',
87
+    'colonne' => 'Column',
88
+    'confirm_changer_statut' => 'Warning: You are about to change this article’s status. Do you wish to continue?',
89
+    'correcte' => 'correct',
90 90
 
91
-	// D
92
-	'date_aujourdhui' => 'today',
93
-	'date_avant_jc' => 'B.C.',
94
-	'date_dans' => 'in @delai@',
95
-	'date_de_mois_1' => '@j@ @nommois@',
96
-	'date_de_mois_10' => '@j@ @nommois@',
97
-	'date_de_mois_11' => '@j@ @nommois@',
98
-	'date_de_mois_12' => '@j@ @nommois@',
99
-	'date_de_mois_2' => '@j@ @nommois@',
100
-	'date_de_mois_3' => '@j@ @nommois@',
101
-	'date_de_mois_4' => '@j@ @nommois@',
102
-	'date_de_mois_5' => '@j@ @nommois@',
103
-	'date_de_mois_6' => '@j@ @nommois@',
104
-	'date_de_mois_7' => '@j@ @nommois@',
105
-	'date_de_mois_8' => '@j@ @nommois@',
106
-	'date_de_mois_9' => '@j@ @nommois@',
107
-	'date_demain' => 'tomorrow',
108
-	'date_fmt_heures_minutes' => '@h@:@m@',
109
-	'date_fmt_heures_minutes_court' => '@h@:@m@',
110
-	'date_fmt_jour' => '@nomjour@ @jour@',
111
-	'date_fmt_jour_heure' => '@jour@ at @heure@',
112
-	'date_fmt_jour_heure_debut_fin' => '@jour@ from @heure_debut@ to @heure_fin@',
113
-	'date_fmt_jour_heure_debut_fin_abbr' => '@dtstart@@jour@ from @heure_debut@@dtabbr@ to @dtend@@heure_fin@@dtabbr@',
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' => 'on @nomjour@ @date@',
119
-	'date_fmt_periode' => 'From @date_debut@ to @date_fin@',
120
-	'date_fmt_periode_abbr' => 'From @dtart@@date_debut@@dtabbr@ to @dtend@@date_fin@@dtabbr@',
121
-	'date_fmt_periode_from' => 'From',
122
-	'date_fmt_periode_to' => 'to',
123
-	'date_fmt_saison_annee' => '@saison@ @annee@',
124
-	'date_heures' => 'hours',
125
-	'date_hier' => 'yesterday',
126
-	'date_il_y_a' => '@delai@ ago',
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' => 'Sunday',
159
-	'date_jour_1_abbr' => 'Sun.',
160
-	'date_jour_1_initiale' => 'S.',
161
-	'date_jour_2' => 'Monday',
162
-	'date_jour_2_abbr' => 'Mon.',
163
-	'date_jour_2_initiale' => 'M.',
164
-	'date_jour_3' => 'Tuesday',
165
-	'date_jour_3_abbr' => 'Tue.',
166
-	'date_jour_3_initiale' => 'T.',
167
-	'date_jour_4' => 'Wednesday',
168
-	'date_jour_4_abbr' => 'Wed.',
169
-	'date_jour_4_initiale' => 'W.',
170
-	'date_jour_5' => 'Thursday',
171
-	'date_jour_5_abbr' => 'Thu.',
172
-	'date_jour_5_initiale' => 'T.',
173
-	'date_jour_6' => 'Friday',
174
-	'date_jour_6_abbr' => 'Fri.',
175
-	'date_jour_6_initiale' => 'F.',
176
-	'date_jour_7' => 'Saturday',
177
-	'date_jour_7_abbr' => 'Sat.',
178
-	'date_jour_7_initiale' => 'S.',
179
-	'date_jours' => 'days',
180
-	'date_minutes' => 'minutes',
181
-	'date_mois' => 'months',
182
-	'date_mois_1' => 'January',
183
-	'date_mois_10' => 'October',
184
-	'date_mois_10_abbr' => 'Oct',
185
-	'date_mois_11' => 'November',
186
-	'date_mois_11_abbr' => 'Nov',
187
-	'date_mois_12' => 'December',
188
-	'date_mois_12_abbr' => 'Dec',
189
-	'date_mois_1_abbr' => 'Jan',
190
-	'date_mois_2' => 'February',
191
-	'date_mois_2_abbr' => 'Feb',
192
-	'date_mois_3' => 'March',
193
-	'date_mois_3_abbr' => 'Mar',
194
-	'date_mois_4' => 'April',
195
-	'date_mois_4_abbr' => 'Apr',
196
-	'date_mois_5' => 'May',
197
-	'date_mois_5_abbr' => 'May',
198
-	'date_mois_6' => 'June',
199
-	'date_mois_6_abbr' => 'Jun',
200
-	'date_mois_7' => 'July',
201
-	'date_mois_7_abbr' => 'Jul',
202
-	'date_mois_8' => 'August',
203
-	'date_mois_8_abbr' => 'Aug',
204
-	'date_mois_9' => 'September',
205
-	'date_mois_9_abbr' => 'Sep',
206
-	'date_saison_1' => 'winter',
207
-	'date_saison_2' => 'spring',
208
-	'date_saison_3' => 'summer',
209
-	'date_saison_4' => 'autumn',
210
-	'date_secondes' => 'seconds',
211
-	'date_semaines' => 'weeks',
212
-	'date_un_mois' => 'month',
213
-	'date_une_heure' => 'hour',
214
-	'date_une_minute' => 'minute',
215
-	'date_une_seconde' => 'second',
216
-	'date_une_semaine' => 'week',
217
-	'dirs_commencer' => ' in order to start installation for real',
218
-	'dirs_preliminaire' => 'Preliminary: <b>Setting up access permissions</b>',
219
-	'dirs_probleme_droits' => 'Problem with access permissions',
220
-	'dirs_repertoires_absents' => '<p><b>The following directories were not found: </b></p><ul>@bad_dirs@.</ul>
91
+    // D
92
+    'date_aujourdhui' => 'today',
93
+    'date_avant_jc' => 'B.C.',
94
+    'date_dans' => 'in @delai@',
95
+    'date_de_mois_1' => '@j@ @nommois@',
96
+    'date_de_mois_10' => '@j@ @nommois@',
97
+    'date_de_mois_11' => '@j@ @nommois@',
98
+    'date_de_mois_12' => '@j@ @nommois@',
99
+    'date_de_mois_2' => '@j@ @nommois@',
100
+    'date_de_mois_3' => '@j@ @nommois@',
101
+    'date_de_mois_4' => '@j@ @nommois@',
102
+    'date_de_mois_5' => '@j@ @nommois@',
103
+    'date_de_mois_6' => '@j@ @nommois@',
104
+    'date_de_mois_7' => '@j@ @nommois@',
105
+    'date_de_mois_8' => '@j@ @nommois@',
106
+    'date_de_mois_9' => '@j@ @nommois@',
107
+    'date_demain' => 'tomorrow',
108
+    'date_fmt_heures_minutes' => '@h@:@m@',
109
+    'date_fmt_heures_minutes_court' => '@h@:@m@',
110
+    'date_fmt_jour' => '@nomjour@ @jour@',
111
+    'date_fmt_jour_heure' => '@jour@ at @heure@',
112
+    'date_fmt_jour_heure_debut_fin' => '@jour@ from @heure_debut@ to @heure_fin@',
113
+    'date_fmt_jour_heure_debut_fin_abbr' => '@dtstart@@jour@ from @heure_debut@@dtabbr@ to @dtend@@heure_fin@@dtabbr@',
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' => 'on @nomjour@ @date@',
119
+    'date_fmt_periode' => 'From @date_debut@ to @date_fin@',
120
+    'date_fmt_periode_abbr' => 'From @dtart@@date_debut@@dtabbr@ to @dtend@@date_fin@@dtabbr@',
121
+    'date_fmt_periode_from' => 'From',
122
+    'date_fmt_periode_to' => 'to',
123
+    'date_fmt_saison_annee' => '@saison@ @annee@',
124
+    'date_heures' => 'hours',
125
+    'date_hier' => 'yesterday',
126
+    'date_il_y_a' => '@delai@ ago',
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' => 'Sunday',
159
+    'date_jour_1_abbr' => 'Sun.',
160
+    'date_jour_1_initiale' => 'S.',
161
+    'date_jour_2' => 'Monday',
162
+    'date_jour_2_abbr' => 'Mon.',
163
+    'date_jour_2_initiale' => 'M.',
164
+    'date_jour_3' => 'Tuesday',
165
+    'date_jour_3_abbr' => 'Tue.',
166
+    'date_jour_3_initiale' => 'T.',
167
+    'date_jour_4' => 'Wednesday',
168
+    'date_jour_4_abbr' => 'Wed.',
169
+    'date_jour_4_initiale' => 'W.',
170
+    'date_jour_5' => 'Thursday',
171
+    'date_jour_5_abbr' => 'Thu.',
172
+    'date_jour_5_initiale' => 'T.',
173
+    'date_jour_6' => 'Friday',
174
+    'date_jour_6_abbr' => 'Fri.',
175
+    'date_jour_6_initiale' => 'F.',
176
+    'date_jour_7' => 'Saturday',
177
+    'date_jour_7_abbr' => 'Sat.',
178
+    'date_jour_7_initiale' => 'S.',
179
+    'date_jours' => 'days',
180
+    'date_minutes' => 'minutes',
181
+    'date_mois' => 'months',
182
+    'date_mois_1' => 'January',
183
+    'date_mois_10' => 'October',
184
+    'date_mois_10_abbr' => 'Oct',
185
+    'date_mois_11' => 'November',
186
+    'date_mois_11_abbr' => 'Nov',
187
+    'date_mois_12' => 'December',
188
+    'date_mois_12_abbr' => 'Dec',
189
+    'date_mois_1_abbr' => 'Jan',
190
+    'date_mois_2' => 'February',
191
+    'date_mois_2_abbr' => 'Feb',
192
+    'date_mois_3' => 'March',
193
+    'date_mois_3_abbr' => 'Mar',
194
+    'date_mois_4' => 'April',
195
+    'date_mois_4_abbr' => 'Apr',
196
+    'date_mois_5' => 'May',
197
+    'date_mois_5_abbr' => 'May',
198
+    'date_mois_6' => 'June',
199
+    'date_mois_6_abbr' => 'Jun',
200
+    'date_mois_7' => 'July',
201
+    'date_mois_7_abbr' => 'Jul',
202
+    'date_mois_8' => 'August',
203
+    'date_mois_8_abbr' => 'Aug',
204
+    'date_mois_9' => 'September',
205
+    'date_mois_9_abbr' => 'Sep',
206
+    'date_saison_1' => 'winter',
207
+    'date_saison_2' => 'spring',
208
+    'date_saison_3' => 'summer',
209
+    'date_saison_4' => 'autumn',
210
+    'date_secondes' => 'seconds',
211
+    'date_semaines' => 'weeks',
212
+    'date_un_mois' => 'month',
213
+    'date_une_heure' => 'hour',
214
+    'date_une_minute' => 'minute',
215
+    'date_une_seconde' => 'second',
216
+    'date_une_semaine' => 'week',
217
+    'dirs_commencer' => ' in order to start installation for real',
218
+    'dirs_preliminaire' => 'Preliminary: <b>Setting up access permissions</b>',
219
+    'dirs_probleme_droits' => 'Problem with access permissions',
220
+    'dirs_repertoires_absents' => '<p><b>The following directories were not found: </b></p><ul>@bad_dirs@.</ul>
221 221
   <p>It is possible that this is due to inappropriate lower or upper case letters in directory names.
222 222
   Please check that the case of the letters in the names of these directories match what is displayed
223 223
   above. If they don’t, correct the directory names using your FTP client.</p>
224 224
   <p>Once this is done, you can',
225
-	'dirs_repertoires_suivants' => '<p><b>The following directories do not have write permission: </b></p><ul>@bad_dirs@</ul>
225
+    'dirs_repertoires_suivants' => '<p><b>The following directories do not have write permission: </b></p><ul>@bad_dirs@</ul>
226 226
 <p>To change this, use your FTP client to set access permissions for each
227 227
  of these directories. The procedure is detailed in the installation guide.</p>
228 228
   <p>Once you have done this, you can ',
229
-	'double_occurrence' => 'Two instances of @balise@',
229
+    'double_occurrence' => 'Two instances of @balise@',
230 230
 
231
-	// E
232
-	'en_cours' => 'processing',
233
-	'envoi_via_le_site' => 'Sent via the site',
234
-	'erreur' => 'Error',
235
-	'erreur_balise_non_fermee' => 'last tag not closed:',
236
-	'erreur_technique_ajaxform' => 'Ooops. An unexpected error prevented to submit the form. You can try again.',
237
-	'erreur_technique_enregistrement_champs' => 'A technical error prevented the right registration of the field @champs@.',
238
-	'erreur_technique_enregistrement_impossible' => 'A technical error prevented the registration.',
239
-	'erreur_texte' => 'error(s)',
240
-	'etape' => 'Step',
231
+    // E
232
+    'en_cours' => 'processing',
233
+    'envoi_via_le_site' => 'Sent via the site',
234
+    'erreur' => 'Error',
235
+    'erreur_balise_non_fermee' => 'last tag not closed:',
236
+    'erreur_technique_ajaxform' => 'Ooops. An unexpected error prevented to submit the form. You can try again.',
237
+    'erreur_technique_enregistrement_champs' => 'A technical error prevented the right registration of the field @champs@.',
238
+    'erreur_technique_enregistrement_impossible' => 'A technical error prevented the registration.',
239
+    'erreur_texte' => 'error(s)',
240
+    'etape' => 'Step',
241 241
 
242
-	// F
243
-	'fichier_introuvable' => 'File not found: @fichier@',
244
-	'fonction_introuvable' => 'Function @fonction@() not found.',
245
-	'form_auteur_confirmation' => 'Please confirm your email address',
246
-	'form_auteur_email_modifie' => 'Your email address has been changed.',
247
-	'form_auteur_envoi_mail_confirmation' => 'A confirmation email has been sent to @email@. You must visit the URL mentioned in the message to validate your email address.',
248
-	'form_auteur_mail_confirmation' => 'Hello,
242
+    // F
243
+    'fichier_introuvable' => 'File not found: @fichier@',
244
+    'fonction_introuvable' => 'Function @fonction@() not found.',
245
+    'form_auteur_confirmation' => 'Please confirm your email address',
246
+    'form_auteur_email_modifie' => 'Your email address has been changed.',
247
+    'form_auteur_envoi_mail_confirmation' => 'A confirmation email has been sent to @email@. You must visit the URL mentioned in the message to validate your email address.',
248
+    'form_auteur_mail_confirmation' => 'Hello,
249 249
 
250 250
 You have asked to change your email address.
251 251
 To confirm your new address, you need to connect to
@@ -253,347 +253,347 @@  discard block
 block discarded – undo
253 253
 
254 254
     @url@
255 255
 ',
256
-	'form_deja_inscrit' => 'You are already registered.',
257
-	'form_email_non_valide' => 'Your email address is not valid.',
258
-	'form_forum_access_refuse' => 'You no longer have access to this site.',
259
-	'form_forum_bonjour' => 'Hello @nom@,',
260
-	'form_forum_confirmer_email' => 'To confirm your email address, follow this link: @url_confirm@',
261
-	'form_forum_email_deja_enregistre' => 'This email address is already registered. Enter your usual password.',
262
-	'form_forum_identifiant_mail' => 'Your new identifier has just been emailed to you.',
263
-	'form_forum_identifiants' => 'Personal identifiers',
264
-	'form_forum_indiquer_nom_email' => 'Enter your name and email address here. You will receive your personal identifier shortly by email.',
265
-	'form_forum_login' => 'login:',
266
-	'form_forum_message_auto' => '(this is an automated message)',
267
-	'form_forum_pass' => 'password:',
268
-	'form_forum_probleme_mail' => 'Mail problem: the identifier could not be sent.',
269
-	'form_forum_voici1' => 'Here are your identifiers. You may now participate on the site
256
+    'form_deja_inscrit' => 'You are already registered.',
257
+    'form_email_non_valide' => 'Your email address is not valid.',
258
+    'form_forum_access_refuse' => 'You no longer have access to this site.',
259
+    'form_forum_bonjour' => 'Hello @nom@,',
260
+    'form_forum_confirmer_email' => 'To confirm your email address, follow this link: @url_confirm@',
261
+    'form_forum_email_deja_enregistre' => 'This email address is already registered. Enter your usual password.',
262
+    'form_forum_identifiant_mail' => 'Your new identifier has just been emailed to you.',
263
+    'form_forum_identifiants' => 'Personal identifiers',
264
+    'form_forum_indiquer_nom_email' => 'Enter your name and email address here. You will receive your personal identifier shortly by email.',
265
+    'form_forum_login' => 'login:',
266
+    'form_forum_message_auto' => '(this is an automated message)',
267
+    'form_forum_pass' => 'password:',
268
+    'form_forum_probleme_mail' => 'Mail problem: the identifier could not be sent.',
269
+    'form_forum_voici1' => 'Here are your identifiers. You may now participate on the site
270 270
 "@nom_site_spip@" (@adresse_site@):',
271
-	'form_forum_voici2' => 'Here are your identifiers for submitting articles to
271
+    'form_forum_voici2' => 'Here are your identifiers for submitting articles to
272 272
 the site "@nom_site_spip@" (@adresse_login@):',
273
-	'form_indiquer_email' => 'Please enter your email address.',
274
-	'form_indiquer_nom' => 'Please enter your name.',
275
-	'form_indiquer_nom_site' => 'Please enter the name of your site.',
276
-	'form_pet_deja_enregistre' => 'This site is already registered',
277
-	'form_pet_signature_pasprise' => 'Your signature has been ignored.',
278
-	'form_prop_confirmer_envoi' => 'Confirm send',
279
-	'form_prop_description' => 'Description/comment',
280
-	'form_prop_enregistre' => 'Your suggestion has been recorded. It will appear online after being validated by the administrators of this site.',
281
-	'form_prop_envoyer' => 'Send a message',
282
-	'form_prop_indiquer_email' => 'Please enter a valid email address',
283
-	'form_prop_indiquer_nom_site' => 'Please enter the site’s name.',
284
-	'form_prop_indiquer_sujet' => 'Please enter a subject',
285
-	'form_prop_message_envoye' => 'Message sent',
286
-	'form_prop_non_enregistre' => 'Your suggestion has not been recorded.',
287
-	'form_prop_sujet' => 'Subject',
288
-	'form_prop_url_site' => 'Site URL',
289
-	'format_date_attendu' => 'Enter a date in jj/mm/aaaa format.',
290
-	'format_date_incorrecte' => 'The date or its format is incorrect.',
291
-	'format_heure_attendu' => 'Enter a time in hh:mm format.',
292
-	'format_heure_incorrecte' => 'The hour or its format is incorrect.',
293
-	'forum_non_inscrit' => 'Either you are not registered, or the address or password are wrong.',
294
-	'forum_par_auteur' => 'by @auteur@',
295
-	'forum_titre_erreur' => 'Error...',
273
+    'form_indiquer_email' => 'Please enter your email address.',
274
+    'form_indiquer_nom' => 'Please enter your name.',
275
+    'form_indiquer_nom_site' => 'Please enter the name of your site.',
276
+    'form_pet_deja_enregistre' => 'This site is already registered',
277
+    'form_pet_signature_pasprise' => 'Your signature has been ignored.',
278
+    'form_prop_confirmer_envoi' => 'Confirm send',
279
+    'form_prop_description' => 'Description/comment',
280
+    'form_prop_enregistre' => 'Your suggestion has been recorded. It will appear online after being validated by the administrators of this site.',
281
+    'form_prop_envoyer' => 'Send a message',
282
+    'form_prop_indiquer_email' => 'Please enter a valid email address',
283
+    'form_prop_indiquer_nom_site' => 'Please enter the site’s name.',
284
+    'form_prop_indiquer_sujet' => 'Please enter a subject',
285
+    'form_prop_message_envoye' => 'Message sent',
286
+    'form_prop_non_enregistre' => 'Your suggestion has not been recorded.',
287
+    'form_prop_sujet' => 'Subject',
288
+    'form_prop_url_site' => 'Site URL',
289
+    'format_date_attendu' => 'Enter a date in jj/mm/aaaa format.',
290
+    'format_date_incorrecte' => 'The date or its format is incorrect.',
291
+    'format_heure_attendu' => 'Enter a time in hh:mm format.',
292
+    'format_heure_incorrecte' => 'The hour or its format is incorrect.',
293
+    'forum_non_inscrit' => 'Either you are not registered, or the address or password are wrong.',
294
+    'forum_par_auteur' => 'by @auteur@',
295
+    'forum_titre_erreur' => 'Error...',
296 296
 
297
-	// I
298
-	'ical_texte_rss_articles' => 'The site’s backend file for articles is:',
299
-	'ical_texte_rss_articles2' => 'You can also get backend files for individual sections on the site:',
300
-	'ical_texte_rss_breves' => 'Furthermore, there is a file containing the site’s news items. By selecting a section number, you can choose to get news items in that section only.',
301
-	'icone_a_suivre' => 'Launch pad',
302
-	'icone_admin_site' => 'Site administration',
303
-	'icone_agenda' => 'Calendar',
304
-	'icone_aide_ligne' => 'Help',
305
-	'icone_articles' => 'Articles',
306
-	'icone_auteurs' => 'Authors',
307
-	'icone_brouteur' => 'Quick browsing',
308
-	'icone_configuration_site' => 'Configuration',
309
-	'icone_configurer_site' => 'Configure your site',
310
-	'icone_creer_nouvel_auteur' => 'Create a new author',
311
-	'icone_creer_rubrique' => 'Create a section',
312
-	'icone_creer_sous_rubrique' => 'Create a subsection',
313
-	'icone_deconnecter' => 'Log out',
314
-	'icone_discussions' => 'Discussions',
315
-	'icone_doc_rubrique' => 'Documents attached',
316
-	'icone_ecrire_article' => 'Write a new article',
317
-	'icone_edition_site' => 'Edit site',
318
-	'icone_gestion_langues' => 'Language options',
319
-	'icone_informations_personnelles' => 'Personal information',
320
-	'icone_interface_complet' => 'full interface',
321
-	'icone_interface_simple' => 'Simplified interface',
322
-	'icone_maintenance_site' => 'Site maintenance',
323
-	'icone_messagerie_personnelle' => 'Private messages',
324
-	'icone_repartition_debut' => 'Show distribution from the start',
325
-	'icone_rubriques' => 'Sections',
326
-	'icone_sauver_site' => 'Site backup',
327
-	'icone_site_entier' => 'The entire site',
328
-	'icone_sites_references' => 'Referenced sites',
329
-	'icone_statistiques' => 'Site statistics',
330
-	'icone_suivi_activite' => 'Follow site activity',
331
-	'icone_suivi_actualite' => 'Site statistics',
332
-	'icone_suivi_pettions' => 'Manage petitions',
333
-	'icone_suivi_revisions' => 'Article revisions',
334
-	'icone_supprimer_document' => 'Delete this document',
335
-	'icone_supprimer_image' => 'Delete this image',
336
-	'icone_tous_articles' => 'All your articles',
337
-	'icone_tous_auteur' => 'All authors',
338
-	'icone_tous_visiteur' => 'All visitors',
339
-	'icone_visiter_site' => 'View the public site',
340
-	'icone_voir_en_ligne' => 'View online',
341
-	'img_indisponible' => 'image unavailable',
342
-	'impossible' => 'impossible',
343
-	'info_a_suivre' => 'LAUNCH PAD»',
344
-	'info_acces_interdit' => 'Access forbidden',
345
-	'info_acces_refuse' => 'Access denied',
346
-	'info_action' => 'Action: @action@',
347
-	'info_administrer_rubriques' => 'You can manage this section and any subsections',
348
-	'info_adresse_non_indiquee' => 'You did not specify an address to test!',
349
-	'info_aide' => 'HELP:',
350
-	'info_ajouter_mot' => 'Add keyword',
351
-	'info_annonce' => 'ANNOUNCEMENT',
352
-	'info_annonces_generales' => 'General announcements:',
353
-	'info_article_propose' => 'Article submitted',
354
-	'info_article_publie' => 'Article published',
355
-	'info_article_redaction' => 'Article in progress',
356
-	'info_article_refuse' => 'Article rejected',
357
-	'info_article_supprime' => 'Article deleted',
358
-	'info_articles' => 'Articles',
359
-	'info_articles_a_valider' => 'Articles awaiting validation',
360
-	'info_articles_nb' => '@nb@ articles',
361
-	'info_articles_proposes' => 'Articles submitted',
362
-	'info_articles_un' => '1 article',
363
-	'info_auteurs_nombre' => 'author(s):',
364
-	'info_authentification_ftp' => 'Authentication (by FTP).',
365
-	'info_breves_2' => 'news',
366
-	'info_breves_nb' => '@nb@ news items',
367
-	'info_breves_un' => '1 news item',
368
-	'info_connexion_refusee' => 'Connection denied',
369
-	'info_contact_developpeur' => 'Please contact a developer.',
370
-	'info_contenance' => 'This site contains:',
371
-	'info_contribution' => 'contributions',
372
-	'info_copyright' => '@spip@ is free software distributed @lien_gpl@.',
373
-	'info_copyright_doc' => 'For more visit <a href="@spipnet@">@spipnet_affiche@</a>.',
374
-	'info_copyright_gpl' => 'under the GPL license',
375
-	'info_cours_edition' => 'In progress',
376
-	'info_creer_repertoire' => 'Please create a file or a directory called:',
377
-	'info_creer_repertoire_2' => 'inside the sub-directory <b>@repertoire@</b>, then',
378
-	'info_creer_vignette' => 'automatic thumbnail creation',
379
-	'info_creerdansrubrique_non_autorise' => 'You don’t have sufficient rights to create content in this section',
380
-	'info_deplier' => 'Unfold',
381
-	'info_descriptif_nombre' => 'description(s):',
382
-	'info_description' => 'Description:',
383
-	'info_description_2' => 'Description:',
384
-	'info_dimension' => 'Size:',
385
-	'info_documents_nb' => '@nb@ documents',
386
-	'info_documents_un' => '1 document',
387
-	'info_ecire_message_prive' => 'Write a private message',
388
-	'info_email_invalide' => 'Invalid email address.',
389
-	'info_en_cours_validation' => 'Your articles in progress',
390
-	'info_en_ligne' => 'Online now:',
391
-	'info_envoyer_message_prive' => 'Send a private message to this author',
392
-	'info_erreur_requete' => 'Error in query:',
393
-	'info_erreur_squelette2' => 'No <b>@fichier@</b> template available ...',
394
-	'info_erreur_systeme' => 'System error (errno @errsys@)',
395
-	'info_erreur_systeme2' => 'The hard disk may be full or the database damaged. <br />
297
+    // I
298
+    'ical_texte_rss_articles' => 'The site’s backend file for articles is:',
299
+    'ical_texte_rss_articles2' => 'You can also get backend files for individual sections on the site:',
300
+    'ical_texte_rss_breves' => 'Furthermore, there is a file containing the site’s news items. By selecting a section number, you can choose to get news items in that section only.',
301
+    'icone_a_suivre' => 'Launch pad',
302
+    'icone_admin_site' => 'Site administration',
303
+    'icone_agenda' => 'Calendar',
304
+    'icone_aide_ligne' => 'Help',
305
+    'icone_articles' => 'Articles',
306
+    'icone_auteurs' => 'Authors',
307
+    'icone_brouteur' => 'Quick browsing',
308
+    'icone_configuration_site' => 'Configuration',
309
+    'icone_configurer_site' => 'Configure your site',
310
+    'icone_creer_nouvel_auteur' => 'Create a new author',
311
+    'icone_creer_rubrique' => 'Create a section',
312
+    'icone_creer_sous_rubrique' => 'Create a subsection',
313
+    'icone_deconnecter' => 'Log out',
314
+    'icone_discussions' => 'Discussions',
315
+    'icone_doc_rubrique' => 'Documents attached',
316
+    'icone_ecrire_article' => 'Write a new article',
317
+    'icone_edition_site' => 'Edit site',
318
+    'icone_gestion_langues' => 'Language options',
319
+    'icone_informations_personnelles' => 'Personal information',
320
+    'icone_interface_complet' => 'full interface',
321
+    'icone_interface_simple' => 'Simplified interface',
322
+    'icone_maintenance_site' => 'Site maintenance',
323
+    'icone_messagerie_personnelle' => 'Private messages',
324
+    'icone_repartition_debut' => 'Show distribution from the start',
325
+    'icone_rubriques' => 'Sections',
326
+    'icone_sauver_site' => 'Site backup',
327
+    'icone_site_entier' => 'The entire site',
328
+    'icone_sites_references' => 'Referenced sites',
329
+    'icone_statistiques' => 'Site statistics',
330
+    'icone_suivi_activite' => 'Follow site activity',
331
+    'icone_suivi_actualite' => 'Site statistics',
332
+    'icone_suivi_pettions' => 'Manage petitions',
333
+    'icone_suivi_revisions' => 'Article revisions',
334
+    'icone_supprimer_document' => 'Delete this document',
335
+    'icone_supprimer_image' => 'Delete this image',
336
+    'icone_tous_articles' => 'All your articles',
337
+    'icone_tous_auteur' => 'All authors',
338
+    'icone_tous_visiteur' => 'All visitors',
339
+    'icone_visiter_site' => 'View the public site',
340
+    'icone_voir_en_ligne' => 'View online',
341
+    'img_indisponible' => 'image unavailable',
342
+    'impossible' => 'impossible',
343
+    'info_a_suivre' => 'LAUNCH PAD»',
344
+    'info_acces_interdit' => 'Access forbidden',
345
+    'info_acces_refuse' => 'Access denied',
346
+    'info_action' => 'Action: @action@',
347
+    'info_administrer_rubriques' => 'You can manage this section and any subsections',
348
+    'info_adresse_non_indiquee' => 'You did not specify an address to test!',
349
+    'info_aide' => 'HELP:',
350
+    'info_ajouter_mot' => 'Add keyword',
351
+    'info_annonce' => 'ANNOUNCEMENT',
352
+    'info_annonces_generales' => 'General announcements:',
353
+    'info_article_propose' => 'Article submitted',
354
+    'info_article_publie' => 'Article published',
355
+    'info_article_redaction' => 'Article in progress',
356
+    'info_article_refuse' => 'Article rejected',
357
+    'info_article_supprime' => 'Article deleted',
358
+    'info_articles' => 'Articles',
359
+    'info_articles_a_valider' => 'Articles awaiting validation',
360
+    'info_articles_nb' => '@nb@ articles',
361
+    'info_articles_proposes' => 'Articles submitted',
362
+    'info_articles_un' => '1 article',
363
+    'info_auteurs_nombre' => 'author(s):',
364
+    'info_authentification_ftp' => 'Authentication (by FTP).',
365
+    'info_breves_2' => 'news',
366
+    'info_breves_nb' => '@nb@ news items',
367
+    'info_breves_un' => '1 news item',
368
+    'info_connexion_refusee' => 'Connection denied',
369
+    'info_contact_developpeur' => 'Please contact a developer.',
370
+    'info_contenance' => 'This site contains:',
371
+    'info_contribution' => 'contributions',
372
+    'info_copyright' => '@spip@ is free software distributed @lien_gpl@.',
373
+    'info_copyright_doc' => 'For more visit <a href="@spipnet@">@spipnet_affiche@</a>.',
374
+    'info_copyright_gpl' => 'under the GPL license',
375
+    'info_cours_edition' => 'In progress',
376
+    'info_creer_repertoire' => 'Please create a file or a directory called:',
377
+    'info_creer_repertoire_2' => 'inside the sub-directory <b>@repertoire@</b>, then',
378
+    'info_creer_vignette' => 'automatic thumbnail creation',
379
+    'info_creerdansrubrique_non_autorise' => 'You don’t have sufficient rights to create content in this section',
380
+    'info_deplier' => 'Unfold',
381
+    'info_descriptif_nombre' => 'description(s):',
382
+    'info_description' => 'Description:',
383
+    'info_description_2' => 'Description:',
384
+    'info_dimension' => 'Size:',
385
+    'info_documents_nb' => '@nb@ documents',
386
+    'info_documents_un' => '1 document',
387
+    'info_ecire_message_prive' => 'Write a private message',
388
+    'info_email_invalide' => 'Invalid email address.',
389
+    'info_en_cours_validation' => 'Your articles in progress',
390
+    'info_en_ligne' => 'Online now:',
391
+    'info_envoyer_message_prive' => 'Send a private message to this author',
392
+    'info_erreur_requete' => 'Error in query:',
393
+    'info_erreur_squelette2' => 'No <b>@fichier@</b> template available ...',
394
+    'info_erreur_systeme' => 'System error (errno @errsys@)',
395
+    'info_erreur_systeme2' => 'The hard disk may be full or the database damaged. <br />
396 396
 <span style="color:red;">Try <a href=\'@script@\'>repairing the database</a>, or contact your service provider.</span>',
397
-	'info_fini' => 'Done!',
398
-	'info_format_image' => 'Image format to be used for vignettes: @gd_formats@.',
399
-	'info_format_non_defini' => 'undefined format',
400
-	'info_grand_ecran' => 'Large display',
401
-	'info_image_aide' => 'HELP',
402
-	'info_image_process_titre' => 'How to create thumbnails',
403
-	'info_impossible_lire_page' => '<b>Error!</b> The page <tt><html>@test_proxy@</html></tt> cannot be viewed through the proxy',
404
-	'info_installation_systeme_publication' => 'Installing publication system...',
405
-	'info_installer_documents' => 'You can automatically install all documents in the folder @upload@.',
406
-	'info_installer_ftp' => 'As an administrator, you can install files via FTP to the folder @upload@ in order to select them directly from here.',
407
-	'info_installer_images' => 'You can install images in the formats JPEG, GIF, and PNG.',
408
-	'info_installer_images_dossier' => 'Install images in folder @upload@ if you want to select them here.',
409
-	'info_interface_complete' => 'full interface',
410
-	'info_interface_simple' => 'Simplified interface',
411
-	'info_joindre_document_article' => 'You can attach the following types of document to your article',
412
-	'info_joindre_document_rubrique' => 'You can add documents of the following types to this section ',
413
-	'info_joindre_documents_article' => 'You can attach documents of the following types to your article:',
414
-	'info_l_article' => 'the article',
415
-	'info_la_breve' => 'the news item',
416
-	'info_la_rubrique' => 'the section',
417
-	'info_langue_principale' => 'Main language for site',
418
-	'info_largeur_vignette' => '@largeur_vignette@ × @hauteur_vignette@ pixels',
419
-	'info_les_auteurs_1' => 'by @les_auteurs@',
420
-	'info_logo_format_interdit' => 'Only logos in these formats @formats@ are allowed.',
421
-	'info_logo_max_poids' => 'Logos must be less than @maxi@ (this file is @actuel@).',
422
-	'info_mail_fournisseur' => '[email protected]',
423
-	'info_message_2' => 'MESSAGE',
424
-	'info_message_supprime' => 'MESSAGE DELETED',
425
-	'info_messages_nb' => '@nb@ messages',
426
-	'info_messages_un' => '1 message',
427
-	'info_mise_en_ligne' => 'Published on:',
428
-	'info_modification_parametres_securite' => 'modifying security parameters',
429
-	'info_mois_courant' => 'During the month:',
430
-	'info_mot_cle_ajoute' => 'The following keyword was added to',
431
-	'info_multi_herit' => 'Default language',
432
-	'info_multi_langues_soulignees' => 'The <u>languages underlined</u> provide partial or total translations for all the interface texts. If you select these languages, many elements of the public site (dates, forms) will be translated automatically. As for the languages that are not underlined, those elements will be displayed using the site’s default language.',
433
-	'info_multilinguisme' => 'Multilingual',
434
-	'info_nom_non_utilisateurs_connectes' => 'Your name does not appear in the list of users online.',
435
-	'info_nom_utilisateurs_connectes' => 'Your name appears in the list of users online.',
436
-	'info_nombre_en_ligne' => 'Online now:',
437
-	'info_non_resultat' => 'No results for "@cherche_mot@"',
438
-	'info_non_utilisation_messagerie' => 'You are not using private messaging on this site.',
439
-	'info_nouveau_message' => 'YOU HAVE A NEW MESSAGE',
440
-	'info_nouveaux_messages' => 'YOU HAVE @total_messages@ NEW MESSAGES',
441
-	'info_numero_abbreviation' => 'No',
442
-	'info_obligatoire' => 'This information is required',
443
-	'info_page_actuelle' => 'Actual page',
444
-	'info_pense_bete' => 'MEMO',
445
-	'info_petit_ecran' => 'Small display',
446
-	'info_petition_close' => 'Petition closed',
447
-	'info_pixels' => 'pixels',
448
-	'info_plusieurs_mots_trouves' => 'Several keywords were found for "@cherche_mot@":',
449
-	'info_portfolio_automatique' => 'Automated portfolio:',
450
-	'info_premier_resultat' => '[First @debut_limit@ results out of @total@]',
451
-	'info_premier_resultat_sur' => '[First @debut_limit@ results out of @total@]',
452
-	'info_propose_1' => '[@nom_site_spip@] Submitted: @titre@',
453
-	'info_propose_2' => 'Article submitted
397
+    'info_fini' => 'Done!',
398
+    'info_format_image' => 'Image format to be used for vignettes: @gd_formats@.',
399
+    'info_format_non_defini' => 'undefined format',
400
+    'info_grand_ecran' => 'Large display',
401
+    'info_image_aide' => 'HELP',
402
+    'info_image_process_titre' => 'How to create thumbnails',
403
+    'info_impossible_lire_page' => '<b>Error!</b> The page <tt><html>@test_proxy@</html></tt> cannot be viewed through the proxy',
404
+    'info_installation_systeme_publication' => 'Installing publication system...',
405
+    'info_installer_documents' => 'You can automatically install all documents in the folder @upload@.',
406
+    'info_installer_ftp' => 'As an administrator, you can install files via FTP to the folder @upload@ in order to select them directly from here.',
407
+    'info_installer_images' => 'You can install images in the formats JPEG, GIF, and PNG.',
408
+    'info_installer_images_dossier' => 'Install images in folder @upload@ if you want to select them here.',
409
+    'info_interface_complete' => 'full interface',
410
+    'info_interface_simple' => 'Simplified interface',
411
+    'info_joindre_document_article' => 'You can attach the following types of document to your article',
412
+    'info_joindre_document_rubrique' => 'You can add documents of the following types to this section ',
413
+    'info_joindre_documents_article' => 'You can attach documents of the following types to your article:',
414
+    'info_l_article' => 'the article',
415
+    'info_la_breve' => 'the news item',
416
+    'info_la_rubrique' => 'the section',
417
+    'info_langue_principale' => 'Main language for site',
418
+    'info_largeur_vignette' => '@largeur_vignette@ × @hauteur_vignette@ pixels',
419
+    'info_les_auteurs_1' => 'by @les_auteurs@',
420
+    'info_logo_format_interdit' => 'Only logos in these formats @formats@ are allowed.',
421
+    'info_logo_max_poids' => 'Logos must be less than @maxi@ (this file is @actuel@).',
422
+    'info_mail_fournisseur' => '[email protected]',
423
+    'info_message_2' => 'MESSAGE',
424
+    'info_message_supprime' => 'MESSAGE DELETED',
425
+    'info_messages_nb' => '@nb@ messages',
426
+    'info_messages_un' => '1 message',
427
+    'info_mise_en_ligne' => 'Published on:',
428
+    'info_modification_parametres_securite' => 'modifying security parameters',
429
+    'info_mois_courant' => 'During the month:',
430
+    'info_mot_cle_ajoute' => 'The following keyword was added to',
431
+    'info_multi_herit' => 'Default language',
432
+    'info_multi_langues_soulignees' => 'The <u>languages underlined</u> provide partial or total translations for all the interface texts. If you select these languages, many elements of the public site (dates, forms) will be translated automatically. As for the languages that are not underlined, those elements will be displayed using the site’s default language.',
433
+    'info_multilinguisme' => 'Multilingual',
434
+    'info_nom_non_utilisateurs_connectes' => 'Your name does not appear in the list of users online.',
435
+    'info_nom_utilisateurs_connectes' => 'Your name appears in the list of users online.',
436
+    'info_nombre_en_ligne' => 'Online now:',
437
+    'info_non_resultat' => 'No results for "@cherche_mot@"',
438
+    'info_non_utilisation_messagerie' => 'You are not using private messaging on this site.',
439
+    'info_nouveau_message' => 'YOU HAVE A NEW MESSAGE',
440
+    'info_nouveaux_messages' => 'YOU HAVE @total_messages@ NEW MESSAGES',
441
+    'info_numero_abbreviation' => 'No',
442
+    'info_obligatoire' => 'This information is required',
443
+    'info_page_actuelle' => 'Actual page',
444
+    'info_pense_bete' => 'MEMO',
445
+    'info_petit_ecran' => 'Small display',
446
+    'info_petition_close' => 'Petition closed',
447
+    'info_pixels' => 'pixels',
448
+    'info_plusieurs_mots_trouves' => 'Several keywords were found for "@cherche_mot@":',
449
+    'info_portfolio_automatique' => 'Automated portfolio:',
450
+    'info_premier_resultat' => '[First @debut_limit@ results out of @total@]',
451
+    'info_premier_resultat_sur' => '[First @debut_limit@ results out of @total@]',
452
+    'info_propose_1' => '[@nom_site_spip@] Submitted: @titre@',
453
+    'info_propose_2' => 'Article submitted
454 454
 -----------------',
455
-	'info_propose_3' => 'The article "@titre@" has been submitted for publication.',
456
-	'info_propose_4' => 'You are invited to review it and give your opinion',
457
-	'info_propose_5' => 'in the associated forum. It is available here:',
458
-	'info_publie_01' => 'The article "@titre@" was validated by @connect_nom@.',
459
-	'info_publie_1' => '[@nom_site_spip@] PUBLISHED: @titre@',
460
-	'info_publie_2' => 'Article published
455
+    'info_propose_3' => 'The article "@titre@" has been submitted for publication.',
456
+    'info_propose_4' => 'You are invited to review it and give your opinion',
457
+    'info_propose_5' => 'in the associated forum. It is available here:',
458
+    'info_publie_01' => 'The article "@titre@" was validated by @connect_nom@.',
459
+    'info_publie_1' => '[@nom_site_spip@] PUBLISHED: @titre@',
460
+    'info_publie_2' => 'Article published
461 461
 -----------------',
462
-	'info_rechercher' => 'Search',
463
-	'info_rechercher_02' => 'Search:',
464
-	'info_remplacer_vignette' => 'Replace the default vignette by a customised logo:',
465
-	'info_rubriques_nb' => '@nb@ sections',
466
-	'info_rubriques_un' => '1 section',
467
-	'info_sans_titre_2' => 'untitled',
468
-	'info_selectionner_fichier' => 'You can select a file from the folder @upload@',
469
-	'info_selectionner_fichier_2' => 'Select a file:',
470
-	'info_sites_nb' => '@nb@ sites',
471
-	'info_sites_un' => '1 site',
472
-	'info_supprimer_vignette' => 'delete the vignette',
473
-	'info_symbole_bleu' => 'A <b>blue</b> symbol indicates a <b>memo</b>: i.e. a message for your personal use.',
474
-	'info_symbole_jaune' => 'A <b>yellow</b> symbol indicates an <b>announcement to all editors</b>: it can be edited by all administrators, and is visible to all editors.',
475
-	'info_symbole_vert' => 'A <b>green</b> symbol indicates the <b>messages exchanged with other users</b> of the site.',
476
-	'info_telecharger_nouveau_logo' => 'Upload a new logo:',
477
-	'info_telecharger_ordinateur' => 'Upload from your computer:',
478
-	'info_tous_resultats_enregistres' => '[all the results are recorded]',
479
-	'info_tout_afficher' => 'Show all',
480
-	'info_travaux_texte' => 'This site is not yet set up. Please come back later...',
481
-	'info_travaux_titre' => 'Site under construction',
482
-	'info_trop_resultat' => 'Too many results for "@cherche_mot@"; please refine the search.',
483
-	'info_utilisation_messagerie_interne' => 'You are using the internal message system of this site.',
484
-	'info_valider_lien' => 'validate this link',
485
-	'info_verifier_image' => ', please make sure your images have been transferred correctly.',
486
-	'info_vignette_defaut' => 'Default vignette',
487
-	'info_vignette_personnalisee' => 'Custom vignette',
488
-	'info_visite' => 'visit:',
489
-	'info_vos_rendez_vous' => 'Your future appointments',
490
-	'infos_vos_pense_bete' => 'Your memos',
462
+    'info_rechercher' => 'Search',
463
+    'info_rechercher_02' => 'Search:',
464
+    'info_remplacer_vignette' => 'Replace the default vignette by a customised logo:',
465
+    'info_rubriques_nb' => '@nb@ sections',
466
+    'info_rubriques_un' => '1 section',
467
+    'info_sans_titre_2' => 'untitled',
468
+    'info_selectionner_fichier' => 'You can select a file from the folder @upload@',
469
+    'info_selectionner_fichier_2' => 'Select a file:',
470
+    'info_sites_nb' => '@nb@ sites',
471
+    'info_sites_un' => '1 site',
472
+    'info_supprimer_vignette' => 'delete the vignette',
473
+    'info_symbole_bleu' => 'A <b>blue</b> symbol indicates a <b>memo</b>: i.e. a message for your personal use.',
474
+    'info_symbole_jaune' => 'A <b>yellow</b> symbol indicates an <b>announcement to all editors</b>: it can be edited by all administrators, and is visible to all editors.',
475
+    'info_symbole_vert' => 'A <b>green</b> symbol indicates the <b>messages exchanged with other users</b> of the site.',
476
+    'info_telecharger_nouveau_logo' => 'Upload a new logo:',
477
+    'info_telecharger_ordinateur' => 'Upload from your computer:',
478
+    'info_tous_resultats_enregistres' => '[all the results are recorded]',
479
+    'info_tout_afficher' => 'Show all',
480
+    'info_travaux_texte' => 'This site is not yet set up. Please come back later...',
481
+    'info_travaux_titre' => 'Site under construction',
482
+    'info_trop_resultat' => 'Too many results for "@cherche_mot@"; please refine the search.',
483
+    'info_utilisation_messagerie_interne' => 'You are using the internal message system of this site.',
484
+    'info_valider_lien' => 'validate this link',
485
+    'info_verifier_image' => ', please make sure your images have been transferred correctly.',
486
+    'info_vignette_defaut' => 'Default vignette',
487
+    'info_vignette_personnalisee' => 'Custom vignette',
488
+    'info_visite' => 'visit:',
489
+    'info_vos_rendez_vous' => 'Your future appointments',
490
+    'infos_vos_pense_bete' => 'Your memos',
491 491
 
492
-	// L
493
-	'label_ajout_id_rapide' => 'Quick addition',
494
-	'label_poids_fichier' => 'Size',
495
-	'label_ponctuer' => '@label@:',
496
-	'lien_afficher_icones_seuls' => 'Show only icons',
497
-	'lien_afficher_texte_icones' => 'Show icons and text',
498
-	'lien_afficher_texte_seul' => 'Show only text',
499
-	'lien_aller_a_la_derniere_page' => 'Go to the last page',
500
-	'lien_aller_a_la_page_nb' => 'Go to page @nb@',
501
-	'lien_aller_a_la_page_precedente' => 'Go to the previous page',
502
-	'lien_aller_a_la_page_suivante' => 'Go to the next page',
503
-	'lien_aller_a_la_premiere_page' => 'Go to the first page',
504
-	'lien_liberer' => 'release',
505
-	'lien_liberer_tous' => 'Release all',
506
-	'lien_nouvea_pense_bete' => 'NEW MEMO',
507
-	'lien_nouveau_message' => 'NEW MESSAGE',
508
-	'lien_nouvelle_annonce' => 'NEW ANNOUNCEMENT',
509
-	'lien_petitions' => 'PETITION',
510
-	'lien_popularite' => 'popularity: @popularite@%',
511
-	'lien_racine_site' => 'SITE ROOT',
512
-	'lien_reessayer' => 'try again',
513
-	'lien_repondre_message' => 'Reply to this message',
514
-	'lien_supprimer' => 'delete',
515
-	'lien_tout_afficher' => 'Show all',
516
-	'lien_visite_site' => 'visit this site',
517
-	'lien_visites' => '@visites@ visits',
518
-	'lien_voir_auteur' => 'Check this author',
519
-	'ligne' => 'Line',
520
-	'login' => 'Connection',
521
-	'login_acces_prive' => 'access to the private area',
522
-	'login_autre_identifiant' => 'use a different ID',
523
-	'login_cookie_accepte' => 'Please configure your browser to accept them for this site.',
524
-	'login_cookie_oblige' => 'For secure identification, your browser must accept cookies.',
525
-	'login_deconnexion_ok' => 'Logged out.',
526
-	'login_erreur_pass' => 'Wrong password.',
527
-	'login_espace_prive' => 'private area',
528
-	'login_identifiant_inconnu' => 'The identifier "@login@" is unknown.',
529
-	'login_login' => 'Login:',
530
-	'login_login2' => 'Login or e-mail address:',
531
-	'login_login_pass_incorrect' => '(Wrong login or password).',
532
-	'login_motpasseoublie' => 'password forgotten?',
533
-	'login_non_securise' => 'Caution, this form is not secure.
492
+    // L
493
+    'label_ajout_id_rapide' => 'Quick addition',
494
+    'label_poids_fichier' => 'Size',
495
+    'label_ponctuer' => '@label@:',
496
+    'lien_afficher_icones_seuls' => 'Show only icons',
497
+    'lien_afficher_texte_icones' => 'Show icons and text',
498
+    'lien_afficher_texte_seul' => 'Show only text',
499
+    'lien_aller_a_la_derniere_page' => 'Go to the last page',
500
+    'lien_aller_a_la_page_nb' => 'Go to page @nb@',
501
+    'lien_aller_a_la_page_precedente' => 'Go to the previous page',
502
+    'lien_aller_a_la_page_suivante' => 'Go to the next page',
503
+    'lien_aller_a_la_premiere_page' => 'Go to the first page',
504
+    'lien_liberer' => 'release',
505
+    'lien_liberer_tous' => 'Release all',
506
+    'lien_nouvea_pense_bete' => 'NEW MEMO',
507
+    'lien_nouveau_message' => 'NEW MESSAGE',
508
+    'lien_nouvelle_annonce' => 'NEW ANNOUNCEMENT',
509
+    'lien_petitions' => 'PETITION',
510
+    'lien_popularite' => 'popularity: @popularite@%',
511
+    'lien_racine_site' => 'SITE ROOT',
512
+    'lien_reessayer' => 'try again',
513
+    'lien_repondre_message' => 'Reply to this message',
514
+    'lien_supprimer' => 'delete',
515
+    'lien_tout_afficher' => 'Show all',
516
+    'lien_visite_site' => 'visit this site',
517
+    'lien_visites' => '@visites@ visits',
518
+    'lien_voir_auteur' => 'Check this author',
519
+    'ligne' => 'Line',
520
+    'login' => 'Connection',
521
+    'login_acces_prive' => 'access to the private area',
522
+    'login_autre_identifiant' => 'use a different ID',
523
+    'login_cookie_accepte' => 'Please configure your browser to accept them for this site.',
524
+    'login_cookie_oblige' => 'For secure identification, your browser must accept cookies.',
525
+    'login_deconnexion_ok' => 'Logged out.',
526
+    'login_erreur_pass' => 'Wrong password.',
527
+    'login_espace_prive' => 'private area',
528
+    'login_identifiant_inconnu' => 'The identifier "@login@" is unknown.',
529
+    'login_login' => 'Login:',
530
+    'login_login2' => 'Login or e-mail address:',
531
+    'login_login_pass_incorrect' => '(Wrong login or password).',
532
+    'login_motpasseoublie' => 'password forgotten?',
533
+    'login_non_securise' => 'Caution, this form is not secure.
534 534
    If you do not want your password to be open to
535 535
    interception on the network, please activate Javascript
536 536
    in your browser and',
537
-	'login_nouvelle_tentative' => 'New attempt',
538
-	'login_par_ici' => 'You are registered... this way...',
539
-	'login_pass2' => 'Password:',
540
-	'login_preferez_refuser' => '<b>If you prefer to refuse cookies</b>, there is another, less secure, method of connection available:',
541
-	'login_recharger' => 'reload this page',
542
-	'login_rester_identifie' => 'Remember me',
543
-	'login_retour_public' => 'Back to the public site',
544
-	'login_retour_site' => 'Back to the public site',
545
-	'login_retoursitepublic' => 'back to the public site',
546
-	'login_sans_cookie' => 'Identification without cookie',
547
-	'login_securise' => 'Secure login',
548
-	'login_sinscrire' => 'register',
549
-	'login_test_navigateur' => 'testing browser/reconnection',
550
-	'login_verifiez_navigateur' => '(However, check that your browser did not memorise your password...)',
537
+    'login_nouvelle_tentative' => 'New attempt',
538
+    'login_par_ici' => 'You are registered... this way...',
539
+    'login_pass2' => 'Password:',
540
+    'login_preferez_refuser' => '<b>If you prefer to refuse cookies</b>, there is another, less secure, method of connection available:',
541
+    'login_recharger' => 'reload this page',
542
+    'login_rester_identifie' => 'Remember me',
543
+    'login_retour_public' => 'Back to the public site',
544
+    'login_retour_site' => 'Back to the public site',
545
+    'login_retoursitepublic' => 'back to the public site',
546
+    'login_sans_cookie' => 'Identification without cookie',
547
+    'login_securise' => 'Secure login',
548
+    'login_sinscrire' => 'register',
549
+    'login_test_navigateur' => 'testing browser/reconnection',
550
+    'login_verifiez_navigateur' => '(However, check that your browser did not memorise your password...)',
551 551
 
552
-	// M
553
-	'masquer_colonne' => 'Hide this column',
554
-	'masquer_trad' => 'hide translations',
555
-	'message_nouveaux_identifiants_echec' => 'New identifiers could not be created.',
556
-	'message_nouveaux_identifiants_echec_envoi' => 'The new connection identifiers could not be sent.',
557
-	'message_nouveaux_identifiants_ok' => 'The new connection identifiers were sent to @email@.',
558
-	'module_fichiers_langues' => 'Language files',
552
+    // M
553
+    'masquer_colonne' => 'Hide this column',
554
+    'masquer_trad' => 'hide translations',
555
+    'message_nouveaux_identifiants_echec' => 'New identifiers could not be created.',
556
+    'message_nouveaux_identifiants_echec_envoi' => 'The new connection identifiers could not be sent.',
557
+    'message_nouveaux_identifiants_ok' => 'The new connection identifiers were sent to @email@.',
558
+    'module_fichiers_langues' => 'Language files',
559 559
 
560
-	// N
561
-	'navigateur_pas_redirige' => 'If you are not automatically redirected, click here to continue.',
562
-	'numero' => 'Number',
560
+    // N
561
+    'navigateur_pas_redirige' => 'If you are not automatically redirected, click here to continue.',
562
+    'numero' => 'Number',
563 563
 
564
-	// O
565
-	'occurence' => 'Instance',
566
-	'onglet_affacer_base' => 'Delete the database',
567
-	'onglet_auteur' => 'The author',
568
-	'onglet_contenu_site' => 'Site content',
569
-	'onglet_evolution_visite_mod' => 'Trend in visits',
570
-	'onglet_fonctions_avances' => 'Advanced functions',
571
-	'onglet_informations_personnelles' => 'Personal Information',
572
-	'onglet_interactivite' => 'Interactivity',
573
-	'onglet_messagerie' => 'Messaging',
574
-	'onglet_repartition_rubrique' => 'Distribution by section',
575
-	'onglet_save_restaur_base' => 'Backup/restore the database',
576
-	'onglet_vider_cache' => 'Empty the cache',
564
+    // O
565
+    'occurence' => 'Instance',
566
+    'onglet_affacer_base' => 'Delete the database',
567
+    'onglet_auteur' => 'The author',
568
+    'onglet_contenu_site' => 'Site content',
569
+    'onglet_evolution_visite_mod' => 'Trend in visits',
570
+    'onglet_fonctions_avances' => 'Advanced functions',
571
+    'onglet_informations_personnelles' => 'Personal Information',
572
+    'onglet_interactivite' => 'Interactivity',
573
+    'onglet_messagerie' => 'Messaging',
574
+    'onglet_repartition_rubrique' => 'Distribution by section',
575
+    'onglet_save_restaur_base' => 'Backup/restore the database',
576
+    'onglet_vider_cache' => 'Empty the cache',
577 577
 
578
-	// P
579
-	'pass_choix_pass' => 'Please choose a new password:',
580
-	'pass_erreur' => 'Error',
581
-	'pass_erreur_acces_refuse' => '<b>Error:</b> you no longer have access to this site.',
582
-	'pass_erreur_code_inconnu' => '<b>Error:</b> this code does not match any visitors with access permission to this site.',
583
-	'pass_erreur_non_enregistre' => '<b>Error :</b> the address <tt>@email_oubli@</tt> is not registered on this site.',
584
-	'pass_erreur_non_valide' => '<b>Error :</b> the e-mail <tt>@email_oubli@</tt> is not valid!',
585
-	'pass_erreur_probleme_technique' => '<b>Error :</b> this e-mail could not be sent due to a technical problem.',
586
-	'pass_espace_prive_bla' => 'The private area of this site is open to
578
+    // P
579
+    'pass_choix_pass' => 'Please choose a new password:',
580
+    'pass_erreur' => 'Error',
581
+    'pass_erreur_acces_refuse' => '<b>Error:</b> you no longer have access to this site.',
582
+    'pass_erreur_code_inconnu' => '<b>Error:</b> this code does not match any visitors with access permission to this site.',
583
+    'pass_erreur_non_enregistre' => '<b>Error :</b> the address <tt>@email_oubli@</tt> is not registered on this site.',
584
+    'pass_erreur_non_valide' => '<b>Error :</b> the e-mail <tt>@email_oubli@</tt> is not valid!',
585
+    'pass_erreur_probleme_technique' => '<b>Error :</b> this e-mail could not be sent due to a technical problem.',
586
+    'pass_espace_prive_bla' => 'The private area of this site is open to
587 587
 visitors after registration. Once you have registered,
588 588
 you can review the articles in progress,
589 589
 submit articles and participate in forums.',
590
-	'pass_forum_bla' => 'You have requested to take part in a forum
590
+    'pass_forum_bla' => 'You have requested to take part in a forum
591 591
 reserved for registered visitors.',
592
-	'pass_indiquez_cidessous' => 'Enter the email address with which you
592
+    'pass_indiquez_cidessous' => 'Enter the email address with which you
593 593
 registered. You
594 594
 will receive an email explaining how you
595 595
 can retrieve your password.',
596
-	'pass_mail_passcookie' => '(this is an automated message)
596
+    'pass_mail_passcookie' => '(this is an automated message)
597 597
 
598 598
 To recover your access to the site
599 599
 @nom_site_spip@ (@adresse_site@)
@@ -604,146 +604,146 @@  discard block
 block discarded – undo
604 604
 You can then enter a new password
605 605
 and log in to the site.
606 606
 ',
607
-	'pass_mot_oublie' => 'Password forgotten',
608
-	'pass_nouveau_enregistre' => 'Your new password has been recorded.',
609
-	'pass_nouveau_pass' => 'New password',
610
-	'pass_ok' => 'OK',
611
-	'pass_oubli_mot' => 'Forgotten password',
612
-	'pass_procedure_changer' => 'In order to change your password, we have to check your identity first. Please enter the e-mail address associated with this account.',
613
-	'pass_quitter_fenetre' => 'Close this window',
614
-	'pass_rappel_login' => 'Reminder: your identifier (login) is "@login@".',
615
-	'pass_recevoir_mail' => 'A link to reset your password has been sent to your email address (if it is valid).',
616
-	'pass_retour_public' => 'Back to the public site',
617
-	'pass_rien_a_faire_ici' => 'Nothing to do here.',
618
-	'pass_vousinscrire' => 'Registering with the site',
619
-	'precedent' => 'previous',
620
-	'previsualisation' => 'Preview',
621
-	'previsualiser' => 'Show preview',
607
+    'pass_mot_oublie' => 'Password forgotten',
608
+    'pass_nouveau_enregistre' => 'Your new password has been recorded.',
609
+    'pass_nouveau_pass' => 'New password',
610
+    'pass_ok' => 'OK',
611
+    'pass_oubli_mot' => 'Forgotten password',
612
+    'pass_procedure_changer' => 'In order to change your password, we have to check your identity first. Please enter the e-mail address associated with this account.',
613
+    'pass_quitter_fenetre' => 'Close this window',
614
+    'pass_rappel_login' => 'Reminder: your identifier (login) is "@login@".',
615
+    'pass_recevoir_mail' => 'A link to reset your password has been sent to your email address (if it is valid).',
616
+    'pass_retour_public' => 'Back to the public site',
617
+    'pass_rien_a_faire_ici' => 'Nothing to do here.',
618
+    'pass_vousinscrire' => 'Registering with the site',
619
+    'precedent' => 'previous',
620
+    'previsualisation' => 'Preview',
621
+    'previsualiser' => 'Show preview',
622 622
 
623
-	// R
624
-	'retour' => 'Back',
623
+    // R
624
+    'retour' => 'Back',
625 625
 
626
-	// S
627
-	'spip_conforme_dtd' => 'SPIP finds this page to be in compliance with its DOCTYPE:',
628
-	'squelette' => 'template',
629
-	'squelette_inclus_ligne' => 'included template, line',
630
-	'squelette_ligne' => 'template, line',
631
-	'stats_visites_et_popularite' => '@visites@ visits; popularity: @popularite@',
632
-	'suivant' => 'next',
626
+    // S
627
+    'spip_conforme_dtd' => 'SPIP finds this page to be in compliance with its DOCTYPE:',
628
+    'squelette' => 'template',
629
+    'squelette_inclus_ligne' => 'included template, line',
630
+    'squelette_ligne' => 'template, line',
631
+    'stats_visites_et_popularite' => '@visites@ visits; popularity: @popularite@',
632
+    'suivant' => 'next',
633 633
 
634
-	// T
635
-	'taille_go' => '@taille@ Gb',
636
-	'taille_ko' => '@taille@ kb',
637
-	'taille_mo' => '@taille@ Mb',
638
-	'taille_octets' => '@taille@ bytes',
639
-	'texte_actualite_site_1' => 'When you are more familiar with the interface, click on "',
640
-	'texte_actualite_site_2' => 'full interface',
641
-	'texte_actualite_site_3' => '" to make more features available.',
642
-	'texte_creation_automatique_vignette' => 'Automatic creation of preview vignettes is enabled. If you use this form to install,  images in the format(s) @gd_formats@, they will be coupled with a vignette whose maximum size is @taille_preview@ pixels.',
643
-	'texte_documents_associes' => 'The following documents are associated with the article,,
634
+    // T
635
+    'taille_go' => '@taille@ Gb',
636
+    'taille_ko' => '@taille@ kb',
637
+    'taille_mo' => '@taille@ Mb',
638
+    'taille_octets' => '@taille@ bytes',
639
+    'texte_actualite_site_1' => 'When you are more familiar with the interface, click on "',
640
+    'texte_actualite_site_2' => 'full interface',
641
+    'texte_actualite_site_3' => '" to make more features available.',
642
+    'texte_creation_automatique_vignette' => 'Automatic creation of preview vignettes is enabled. If you use this form to install,  images in the format(s) @gd_formats@, they will be coupled with a vignette whose maximum size is @taille_preview@ pixels.',
643
+    'texte_documents_associes' => 'The following documents are associated with the article,,
644 644
     but they were not directly
645 645
     inserted. Depending on the layout of the public site,
646 646
     they may appear as attached documents.',
647
-	'texte_erreur_mise_niveau_base' => 'Database error during the upgrade.
647
+    'texte_erreur_mise_niveau_base' => 'Database error during the upgrade.
648 648
       The image <b>@fichier@</b> did not pass (article @id_article@).<p>
649 649
    Note this reference carefully, try the upgrade procedure again,
650 650
    and check afterwards that the images still appear
651 651
       in the articles.',
652
-	'texte_erreur_visiteur' => 'You have tried to enter the private area using an unauthorised login.',
653
-	'texte_inc_auth_1' => 'You used the login
652
+    'texte_erreur_visiteur' => 'You have tried to enter the private area using an unauthorised login.',
653
+    'texte_inc_auth_1' => 'You used the login
654 654
   <b>@auth_login@</b>, but it does not exist in the database.
655 655
   Try to',
656
-	'texte_inc_auth_2' => 'reconnect',
657
-	'texte_inc_auth_3' => ', having quit and
656
+    'texte_inc_auth_2' => 'reconnect',
657
+    'texte_inc_auth_3' => ', having quit and
658 658
   restarted your browser if necessary.',
659
-	'texte_inc_config' => 'Changes made to the options on these pages have a great effect on
659
+    'texte_inc_config' => 'Changes made to the options on these pages have a great effect on
660 660
   the functioning of the site. You are advised not to make any changes unless you are
661 661
  familiar with how SPIP works. <br /><br /><b>In
662 662
  general, you are strongly advised
663 663
  to let the main webmaster of the site deal with these pages.</b>',
664
-	'texte_inc_meta_1' => 'The system encountered an error when trying to write the file <code>@fichier@</code>. As a site administrator, please',
665
-	'texte_inc_meta_2' => 'verify write permissions',
666
-	'texte_inc_meta_3' => 'of the directory <code>@repertoire@</code>.',
667
-	'texte_statut_en_cours_redaction' => 'editing in progress',
668
-	'texte_statut_poubelle' => 'to the dustbin',
669
-	'texte_statut_propose_evaluation' => 'submitted for evaluation',
670
-	'texte_statut_publie' => 'published online',
671
-	'texte_statut_refuse' => 'rejected',
672
-	'titre_ajouter_mot_cle' => 'ADD A KEYWORD:',
673
-	'titre_cadre_raccourcis' => 'SHORTCUTS:',
674
-	'titre_changer_couleur_interface' => 'Changing interface colour',
675
-	'titre_image_admin_article' => 'You can administrate this article',
676
-	'titre_image_administrateur' => 'Administrator',
677
-	'titre_image_aide' => 'Help on this item',
678
-	'titre_image_auteur_supprime' => 'Author deleted',
679
-	'titre_image_redacteur' => 'Editor without access',
680
-	'titre_image_redacteur_02' => 'Editor',
681
-	'titre_image_selecteur' => 'Display list',
682
-	'titre_image_visiteur' => 'Visitor',
683
-	'titre_joindre_document' => 'ATTACH A DOCUMENT',
684
-	'titre_mots_cles' => 'KEYWORDS',
685
-	'titre_probleme_technique' => 'Warning: a technical problem (SQL server) is preventing access to this part of the site. Thank you for your patience.',
686
-	'titre_publier_document' => 'PUBLISH A DOCUMENT IN THIS SECTION',
687
-	'titre_signatures_attente' => 'Signatures awaiting validation',
688
-	'titre_signatures_confirmees' => 'Signatures confirmed',
689
-	'titre_statistiques' => 'Site statistics',
690
-	'titre_titre_document' => 'Document title:',
691
-	'todo' => 'to come',
692
-	'trad_definir_reference' => 'Choose "@titre@" as a reference for translations',
693
-	'trad_reference' => '(reference for translations)',
664
+    'texte_inc_meta_1' => 'The system encountered an error when trying to write the file <code>@fichier@</code>. As a site administrator, please',
665
+    'texte_inc_meta_2' => 'verify write permissions',
666
+    'texte_inc_meta_3' => 'of the directory <code>@repertoire@</code>.',
667
+    'texte_statut_en_cours_redaction' => 'editing in progress',
668
+    'texte_statut_poubelle' => 'to the dustbin',
669
+    'texte_statut_propose_evaluation' => 'submitted for evaluation',
670
+    'texte_statut_publie' => 'published online',
671
+    'texte_statut_refuse' => 'rejected',
672
+    'titre_ajouter_mot_cle' => 'ADD A KEYWORD:',
673
+    'titre_cadre_raccourcis' => 'SHORTCUTS:',
674
+    'titre_changer_couleur_interface' => 'Changing interface colour',
675
+    'titre_image_admin_article' => 'You can administrate this article',
676
+    'titre_image_administrateur' => 'Administrator',
677
+    'titre_image_aide' => 'Help on this item',
678
+    'titre_image_auteur_supprime' => 'Author deleted',
679
+    'titre_image_redacteur' => 'Editor without access',
680
+    'titre_image_redacteur_02' => 'Editor',
681
+    'titre_image_selecteur' => 'Display list',
682
+    'titre_image_visiteur' => 'Visitor',
683
+    'titre_joindre_document' => 'ATTACH A DOCUMENT',
684
+    'titre_mots_cles' => 'KEYWORDS',
685
+    'titre_probleme_technique' => 'Warning: a technical problem (SQL server) is preventing access to this part of the site. Thank you for your patience.',
686
+    'titre_publier_document' => 'PUBLISH A DOCUMENT IN THIS SECTION',
687
+    'titre_signatures_attente' => 'Signatures awaiting validation',
688
+    'titre_signatures_confirmees' => 'Signatures confirmed',
689
+    'titre_statistiques' => 'Site statistics',
690
+    'titre_titre_document' => 'Document title:',
691
+    'todo' => 'to come',
692
+    'trad_definir_reference' => 'Choose "@titre@" as a reference for translations',
693
+    'trad_reference' => '(reference for translations)',
694 694
 
695
-	// U
696
-	'upload_limit' => 'This file is too big for the server: the maximum size allowed for <i>upload</i> is @max@.',
695
+    // U
696
+    'upload_limit' => 'This file is too big for the server: the maximum size allowed for <i>upload</i> is @max@.',
697 697
 
698
-	// Z
699
-	'zbug_balise_b_aval' => ': B tag too late in loop',
700
-	'zbug_balise_inexistante' => 'Tag @balise@ wrongly declared for @from@',
701
-	'zbug_balise_sans_argument' => 'Missing argument in the @balise@ tag',
702
-	'zbug_boucle' => 'loop',
703
-	'zbug_boucle_recursive_undef' => 'undefined recursive loop: @nom@',
704
-	'zbug_calcul' => 'calculation',
705
-	'zbug_champ_hors_boucle' => 'Field @champ@ outside loop',
706
-	'zbug_champ_hors_critere' => 'Field @champ@ outside criterion @critere@',
707
-	'zbug_champ_hors_motif' => 'Field @champ@ outside context @motif@',
708
-	'zbug_code' => 'code',
709
-	'zbug_critere_inconnu' => 'Unknown criterion @critere@',
710
-	'zbug_critere_sur_table_sans_cle_primaire' => '{@critere@} on a table without atomic primary key',
711
-	'zbug_distant_interdit' => 'External data forbidden',
712
-	'zbug_doublon_table_sans_cle_primaire' => 'Duplicate entries on a table which does not have a simple primary key',
713
-	'zbug_doublon_table_sans_index' => 'Duplicate entries on a table without an index',
714
-	'zbug_erreur_boucle_double' => 'Loop @id@: double definition',
715
-	'zbug_erreur_boucle_fermant' => 'Loop @id@: missing closing tag',
716
-	'zbug_erreur_boucle_syntaxe' => 'Syntax error in loop (BOUCLE)',
717
-	'zbug_erreur_compilation' => 'Compilation error',
718
-	'zbug_erreur_execution_page' => 'Execution error',
719
-	'zbug_erreur_filtre' => 'Undefined filter @filtre@',
720
-	'zbug_erreur_filtre_nbarg_min' => '@filtre@ filter: @nb@ argument(s) missing',
721
-	'zbug_erreur_meme_parent' => '{meme_parent} only applies to loops (FORUMS) and (RUBRIQUES)',
722
-	'zbug_erreur_squelette' => 'Error(s) in template',
723
-	'zbug_hors_compilation' => 'Uncompiled',
724
-	'zbug_info_erreur_squelette' => 'Error in the site',
725
-	'zbug_inversion_ordre_inexistant' => 'Reversion of non-existent order',
726
-	'zbug_pagination_sans_critere' => '#PAGINATION tag without {pagination} criterion, or used in a recursive loop',
727
-	'zbug_parametres_inclus_incorrects' => 'Wrong inclusion parameter: @param@',
728
-	'zbug_profile' => 'Calculation time: @time@',
729
-	'zbug_resultat' => 'result',
730
-	'zbug_serveur_indefini' => 'Undefined SQL server',
731
-	'zbug_statistiques' => 'SQL query statistics in order of duration',
732
-	'zbug_table_inconnue' => 'Unknown SQL table "@table@"',
733
-	'zxml_connus_attributs' => 'known attributes',
734
-	'zxml_de' => 'from',
735
-	'zxml_inconnu_attribut' => 'unknown attribute',
736
-	'zxml_inconnu_balise' => 'unknown tag',
737
-	'zxml_inconnu_entite' => 'unknown entity',
738
-	'zxml_inconnu_id' => 'unknown ID',
739
-	'zxml_mais_de' => 'but from',
740
-	'zxml_non_conforme' => 'not true to the principle',
741
-	'zxml_non_fils' => 'is not a child of',
742
-	'zxml_nonvide_balise' => 'tag not empty',
743
-	'zxml_obligatoire_attribut' => 'required attribute absent in',
744
-	'zxml_succession_fils_incorrecte' => 'incorrect child inheritance',
745
-	'zxml_survoler' => 'to see the correct ones, hover with the cursor',
746
-	'zxml_valeur_attribut' => 'attribute value',
747
-	'zxml_vide_balise' => 'empty tag',
748
-	'zxml_vu' => 'seen before'
698
+    // Z
699
+    'zbug_balise_b_aval' => ': B tag too late in loop',
700
+    'zbug_balise_inexistante' => 'Tag @balise@ wrongly declared for @from@',
701
+    'zbug_balise_sans_argument' => 'Missing argument in the @balise@ tag',
702
+    'zbug_boucle' => 'loop',
703
+    'zbug_boucle_recursive_undef' => 'undefined recursive loop: @nom@',
704
+    'zbug_calcul' => 'calculation',
705
+    'zbug_champ_hors_boucle' => 'Field @champ@ outside loop',
706
+    'zbug_champ_hors_critere' => 'Field @champ@ outside criterion @critere@',
707
+    'zbug_champ_hors_motif' => 'Field @champ@ outside context @motif@',
708
+    'zbug_code' => 'code',
709
+    'zbug_critere_inconnu' => 'Unknown criterion @critere@',
710
+    'zbug_critere_sur_table_sans_cle_primaire' => '{@critere@} on a table without atomic primary key',
711
+    'zbug_distant_interdit' => 'External data forbidden',
712
+    'zbug_doublon_table_sans_cle_primaire' => 'Duplicate entries on a table which does not have a simple primary key',
713
+    'zbug_doublon_table_sans_index' => 'Duplicate entries on a table without an index',
714
+    'zbug_erreur_boucle_double' => 'Loop @id@: double definition',
715
+    'zbug_erreur_boucle_fermant' => 'Loop @id@: missing closing tag',
716
+    'zbug_erreur_boucle_syntaxe' => 'Syntax error in loop (BOUCLE)',
717
+    'zbug_erreur_compilation' => 'Compilation error',
718
+    'zbug_erreur_execution_page' => 'Execution error',
719
+    'zbug_erreur_filtre' => 'Undefined filter @filtre@',
720
+    'zbug_erreur_filtre_nbarg_min' => '@filtre@ filter: @nb@ argument(s) missing',
721
+    'zbug_erreur_meme_parent' => '{meme_parent} only applies to loops (FORUMS) and (RUBRIQUES)',
722
+    'zbug_erreur_squelette' => 'Error(s) in template',
723
+    'zbug_hors_compilation' => 'Uncompiled',
724
+    'zbug_info_erreur_squelette' => 'Error in the site',
725
+    'zbug_inversion_ordre_inexistant' => 'Reversion of non-existent order',
726
+    'zbug_pagination_sans_critere' => '#PAGINATION tag without {pagination} criterion, or used in a recursive loop',
727
+    'zbug_parametres_inclus_incorrects' => 'Wrong inclusion parameter: @param@',
728
+    'zbug_profile' => 'Calculation time: @time@',
729
+    'zbug_resultat' => 'result',
730
+    'zbug_serveur_indefini' => 'Undefined SQL server',
731
+    'zbug_statistiques' => 'SQL query statistics in order of duration',
732
+    'zbug_table_inconnue' => 'Unknown SQL table "@table@"',
733
+    'zxml_connus_attributs' => 'known attributes',
734
+    'zxml_de' => 'from',
735
+    'zxml_inconnu_attribut' => 'unknown attribute',
736
+    'zxml_inconnu_balise' => 'unknown tag',
737
+    'zxml_inconnu_entite' => 'unknown entity',
738
+    'zxml_inconnu_id' => 'unknown ID',
739
+    'zxml_mais_de' => 'but from',
740
+    'zxml_non_conforme' => 'not true to the principle',
741
+    'zxml_non_fils' => 'is not a child of',
742
+    'zxml_nonvide_balise' => 'tag not empty',
743
+    'zxml_obligatoire_attribut' => 'required attribute absent in',
744
+    'zxml_succession_fils_incorrecte' => 'incorrect child inheritance',
745
+    'zxml_survoler' => 'to see the correct ones, hover with the cursor',
746
+    'zxml_valeur_attribut' => 'attribute value',
747
+    'zxml_vide_balise' => 'empty tag',
748
+    'zxml_vu' => 'seen before'
749 749
 );
Please login to merge, or discard this patch.