|
1
|
|
|
<?php |
|
2
|
|
|
|
|
3
|
|
|
/***************************************************************************\ |
|
4
|
|
|
* SPIP, Systeme de publication pour l'internet * |
|
5
|
|
|
* * |
|
6
|
|
|
* Copyright (c) 2001-2019 * |
|
7
|
|
|
* Arnaud Martin, Antoine Pitrou, Philippe Riviere, Emmanuel Saint-James * |
|
8
|
|
|
* * |
|
9
|
|
|
* Ce programme est un logiciel libre distribue sous licence GNU/GPL. * |
|
10
|
|
|
* Pour plus de details voir le fichier COPYING.txt ou l'aide en ligne. * |
|
11
|
|
|
\***************************************************************************/ |
|
12
|
|
|
|
|
13
|
|
|
if (!defined('_ECRIRE_INC_VERSION')) { |
|
14
|
|
|
return; |
|
15
|
|
|
} |
|
16
|
|
|
|
|
17
|
|
|
include_spip('inc/lang'); |
|
18
|
|
|
|
|
19
|
|
|
// NB: mes_fonctions peut initialiser $dossier_squelettes (old-style) |
|
20
|
|
|
// donc il faut l'inclure "en globals" |
|
21
|
|
|
if ($f = find_in_path('mes_fonctions.php')) { |
|
22
|
|
|
global $dossier_squelettes; |
|
23
|
|
|
include_once(_ROOT_CWD . $f); |
|
24
|
|
|
} |
|
25
|
|
|
|
|
26
|
|
|
if (@is_readable(_CACHE_PLUGINS_FCT)) { |
|
27
|
|
|
// chargement optimise precompile |
|
28
|
|
|
include_once(_CACHE_PLUGINS_FCT); |
|
29
|
|
|
} |
|
30
|
|
|
if (test_espace_prive()) { |
|
31
|
|
|
include_spip('inc/filtres_ecrire'); |
|
32
|
|
|
} |
|
33
|
|
|
|
|
34
|
|
|
# Determine le squelette associe a une requete |
|
35
|
|
|
# et l'applique sur le contexte, le nom du cache et le serveur |
|
36
|
|
|
# en ayant evacue au prealable le cas de la redirection |
|
37
|
|
|
# Retourne un tableau ainsi construit |
|
38
|
|
|
# 'texte' => la page calculee |
|
39
|
|
|
# 'process_ins' => 'html' ou 'php' si presence d'un '< ?php' |
|
40
|
|
|
# 'invalideurs' => les invalideurs de ce cache |
|
41
|
|
|
# 'entetes' => headers http |
|
42
|
|
|
# 'duree' => duree de vie du cache |
|
43
|
|
|
# 'signal' => contexte (les id_* globales) |
|
44
|
|
|
|
|
45
|
|
|
# En cas d'erreur process_ins est absent et texte est un tableau de 2 chaines |
|
46
|
|
|
|
|
47
|
|
|
// http://code.spip.net/@public_parametrer_dist |
|
48
|
|
|
function public_parametrer_dist($fond, $contexte = '', $cache = '', $connect = '') { |
|
49
|
|
|
static $composer, $styliser, $notes = null; |
|
50
|
|
|
$page = tester_redirection($fond, $contexte, $connect); |
|
51
|
|
|
if ($page) { |
|
52
|
|
|
return $page; |
|
53
|
|
|
} |
|
54
|
|
|
|
|
55
|
|
|
if (isset($contexte['lang'])) { |
|
56
|
|
|
$lang = $contexte['lang']; |
|
57
|
|
|
} elseif (!isset($lang)) { |
|
|
|
|
|
|
58
|
|
|
$lang = $GLOBALS['meta']['langue_site']; |
|
59
|
|
|
} |
|
60
|
|
|
|
|
61
|
|
|
$select = ((!isset($GLOBALS['forcer_lang']) or !$GLOBALS['forcer_lang']) and $lang <> $GLOBALS['spip_lang']); |
|
62
|
|
|
if ($select) { |
|
63
|
|
|
$select = lang_select($lang); |
|
64
|
|
|
} |
|
65
|
|
|
|
|
66
|
|
|
$debug = (defined('_VAR_MODE') && _VAR_MODE == 'debug'); |
|
67
|
|
|
|
|
68
|
|
|
if (!$styliser) { |
|
69
|
|
|
$styliser = charger_fonction('styliser', 'public'); |
|
70
|
|
|
} |
|
71
|
|
|
list($skel, $mime_type, $gram, $sourcefile) = |
|
72
|
|
|
$styliser($fond, $contexte, $GLOBALS['spip_lang'], $connect); |
|
73
|
|
|
|
|
74
|
|
|
if ($skel) { |
|
75
|
|
|
|
|
76
|
|
|
// sauver le nom de l'eventuel squelette en cours d'execution |
|
77
|
|
|
// (recursion possible a cause des modeles) |
|
78
|
|
|
if ($debug) { |
|
79
|
|
|
$courant = @$GLOBALS['debug_objets']['courant']; |
|
80
|
|
|
$GLOBALS['debug_objets']['contexte'][$sourcefile] = $contexte; |
|
81
|
|
|
} |
|
82
|
|
|
|
|
83
|
|
|
// charger le squelette en specifiant les langages cibles et source |
|
84
|
|
|
// au cas il faudrait le compiler (source posterieure au resultat) |
|
85
|
|
|
|
|
86
|
|
|
if (!$composer) { |
|
87
|
|
|
$composer = charger_fonction('composer', 'public'); |
|
88
|
|
|
} |
|
89
|
|
|
$fonc = $composer($skel, $mime_type, $gram, $sourcefile, $connect); |
|
90
|
|
|
} else { |
|
91
|
|
|
$fonc = ''; |
|
92
|
|
|
} |
|
93
|
|
|
|
|
94
|
|
|
if (!$fonc) { // squelette inconnu (==='') ou faux (===false) |
|
95
|
|
|
$page = $fonc; |
|
96
|
|
|
} else { |
|
97
|
|
|
// Preparer l'appel de la fonction principale du squelette |
|
98
|
|
|
|
|
99
|
|
|
spip_timer($a = 'calcul page ' . rand(0, 1000)); |
|
100
|
|
|
|
|
101
|
|
|
// On cree un marqueur de notes unique lie a cette composition |
|
102
|
|
|
// et on enregistre l'etat courant des globales de notes... |
|
103
|
|
|
if (is_null($notes)) { |
|
104
|
|
|
$notes = charger_fonction('notes', 'inc', true); |
|
105
|
|
|
} |
|
106
|
|
|
if ($notes) { |
|
107
|
|
|
$notes('', 'empiler'); |
|
108
|
|
|
} |
|
109
|
|
|
|
|
110
|
|
|
// Rajouter d'office ces deux parametres |
|
111
|
|
|
// (mais vaudrait mieux que le compilateur sache le simuler |
|
112
|
|
|
// car ca interdit l'usage de criteres conditionnels dessus). |
|
113
|
|
View Code Duplication |
if (!isset($contexte['date'])) { |
|
|
|
|
|
|
114
|
|
|
$contexte['date'] = date("Y-m-d H:i:s"); |
|
115
|
|
|
$contexte['date_default'] = true; |
|
116
|
|
|
} else { |
|
117
|
|
|
$contexte['date'] = normaliser_date($contexte['date'], true); |
|
118
|
|
|
} |
|
119
|
|
|
|
|
120
|
|
View Code Duplication |
if (!isset($contexte['date_redac'])) { |
|
|
|
|
|
|
121
|
|
|
$contexte['date_redac'] = date("Y-m-d H:i:s"); |
|
122
|
|
|
$contexte['date_redac_default'] = true; |
|
123
|
|
|
} else { |
|
124
|
|
|
$contexte['date_redac'] = normaliser_date($contexte['date_redac'], true); |
|
125
|
|
|
} |
|
126
|
|
|
|
|
127
|
|
|
// Passer le nom du cache pour produire sa destruction automatique |
|
128
|
|
|
$page = $fonc(array('cache' => $cache), array($contexte)); |
|
129
|
|
|
|
|
130
|
|
|
// Restituer les globales de notes telles qu'elles etaient avant l'appel |
|
131
|
|
|
// Si l'inclus n'a pas affiche ses notes, tant pis (elles *doivent* |
|
132
|
|
|
// etre dans son resultat, autrement elles ne seraient pas prises en |
|
133
|
|
|
// compte a chaque calcul d'un texte contenant un modele, mais seulement |
|
134
|
|
|
// quand le modele serait calcule, et on aurait des resultats incoherents) |
|
135
|
|
|
if ($notes) { |
|
136
|
|
|
$notes('', 'depiler'); |
|
137
|
|
|
} |
|
138
|
|
|
|
|
139
|
|
|
// reinjecter en dynamique la pile des notes |
|
140
|
|
|
// si il y a des inclure dynamiques |
|
141
|
|
|
// si la pile n'est pas vide |
|
142
|
|
|
// la generalisation de cette injection permettrait de corriger le point juste au dessus |
|
143
|
|
|
// en faisant remonter les notes a l'incluant (A tester et valider avant application) |
|
144
|
|
|
if ($notes) { |
|
145
|
|
|
$page['notes'] = $notes('', 'sauver_etat'); |
|
146
|
|
|
} |
|
147
|
|
|
|
|
148
|
|
|
// spip_log: un joli contexte |
|
149
|
|
|
$infos = presenter_contexte(array_filter($contexte)); |
|
150
|
|
|
|
|
151
|
|
|
$profile = spip_timer($a); |
|
152
|
|
|
spip_log("calcul ($profile) [$skel] $infos" |
|
153
|
|
|
. ' (' . strlen($page['texte']) . ' octets)'); |
|
154
|
|
|
|
|
155
|
|
|
if (defined('_CALCUL_PROFILER') AND intval($profile)>_CALCUL_PROFILER){ |
|
156
|
|
|
spip_log("calcul ($profile) [$skel] $infos" |
|
157
|
|
|
.' ('.strlen($page['texte']).' octets) | '.$_SERVER['REQUEST_URI'],"profiler"._LOG_AVERTISSEMENT); |
|
158
|
|
|
} |
|
159
|
|
|
|
|
160
|
|
|
if ($debug) { |
|
161
|
|
|
// si c'est ce que demande le debusqueur, lui passer la main |
|
162
|
|
|
$t = strlen($page['texte']) ? $page['texte'] : " "; |
|
163
|
|
|
$GLOBALS['debug_objets']['resultat'][$fonc . 'tout'] = $t; |
|
164
|
|
|
$GLOBALS['debug_objets']['courant'] = $courant; |
|
|
|
|
|
|
165
|
|
|
$GLOBALS['debug_objets']['profile'][$sourcefile] = $profile; |
|
166
|
|
View Code Duplication |
if ($GLOBALS['debug_objets']['sourcefile'] |
|
|
|
|
|
|
167
|
|
|
and (_request('var_mode_objet') == $fonc) |
|
168
|
|
|
and (_request('var_mode_affiche') == 'resultat') |
|
169
|
|
|
) { |
|
170
|
|
|
erreur_squelette(); |
|
171
|
|
|
} |
|
172
|
|
|
} |
|
173
|
|
|
// Si #CACHE{} n'etait pas la, le mettre a $delais |
|
174
|
|
|
if (!isset($page['entetes']['X-Spip-Cache'])) { |
|
175
|
|
|
// Dans l'espace prive ou dans un modeles/ on pose un cache 0 par defaut |
|
176
|
|
|
// si aucun #CACHE{} spécifié |
|
177
|
|
|
// le contexte implicite qui conditionne le cache assure qu'on retombe pas sur le meme |
|
178
|
|
|
// entre public et prive |
|
179
|
|
|
if (test_espace_prive() or strncmp($fond, 'modeles/', 8) == 0) { |
|
180
|
|
|
$page['entetes']['X-Spip-Cache'] = 0; |
|
181
|
|
|
} else { |
|
182
|
|
|
$page['entetes']['X-Spip-Cache'] = isset($GLOBALS['delais']) ? $GLOBALS['delais'] : 36000; |
|
183
|
|
|
} |
|
184
|
|
|
} |
|
185
|
|
|
|
|
186
|
|
|
$page['contexte'] = $contexte; |
|
187
|
|
|
|
|
188
|
|
|
// faire remonter le fichier source |
|
189
|
|
|
static $js_inclus = false; |
|
190
|
|
|
if (defined('_VAR_INCLURE') and _VAR_INCLURE) { |
|
191
|
|
|
$page['sourcefile'] = $sourcefile; |
|
192
|
|
|
$page['texte'] = |
|
193
|
|
|
"<div class='inclure_blocs'><h6>" . $page['sourcefile'] . "</h6>" . $page['texte'] . "</div>" |
|
194
|
|
|
. ($js_inclus ? "" : "<script type='text/javascript'>jQuery(function(){jQuery('.inclure_blocs > h6:first-child').hover(function(){jQuery(this).parent().addClass('hover')},function(){jQuery(this).parent().removeClass('hover')})});</script>"); |
|
195
|
|
|
$js_inclus = true; |
|
196
|
|
|
} |
|
197
|
|
|
|
|
198
|
|
|
// Si un modele contenait #SESSION, on note l'info dans $page |
|
199
|
|
View Code Duplication |
if (isset($GLOBALS['cache_utilise_session'])) { |
|
|
|
|
|
|
200
|
|
|
$page['invalideurs']['session'] = $GLOBALS['cache_utilise_session']; |
|
201
|
|
|
unset($GLOBALS['cache_utilise_session']); |
|
202
|
|
|
} |
|
203
|
|
|
} |
|
204
|
|
|
|
|
205
|
|
|
if ($select) { |
|
206
|
|
|
lang_select(); |
|
207
|
|
|
} |
|
208
|
|
|
|
|
209
|
|
|
return $page; |
|
210
|
|
|
} |
|
211
|
|
|
|
|
212
|
|
|
/** |
|
213
|
|
|
* Retourne une présentation succincte du contexte pour les logs |
|
214
|
|
|
* @param array $contexte |
|
215
|
|
|
* @return string |
|
216
|
|
|
*/ |
|
217
|
|
|
function presenter_contexte($contexte, $profondeur_max = 1, $max_lines = 0) { |
|
218
|
|
|
$infos = array(); |
|
219
|
|
|
$line = 0; |
|
220
|
|
|
foreach ($contexte as $var => $val) { |
|
221
|
|
|
$line++; |
|
222
|
|
|
if ($max_lines and $max_lines < $line) { |
|
223
|
|
|
$infos[] = '…'; |
|
224
|
|
|
break; |
|
225
|
|
|
} |
|
226
|
|
|
if (is_array($val)) { |
|
227
|
|
|
if ($profondeur_max > 0) { |
|
228
|
|
|
$val = 'array:' . count($val) . '(' . presenter_contexte($val, $profondeur_max - 1, 3) . ')'; |
|
229
|
|
|
} else { |
|
230
|
|
|
$val = 'array:' . count($val); |
|
231
|
|
|
} |
|
232
|
|
|
} elseif (is_object($val)) { |
|
233
|
|
|
$val = get_class($val); |
|
234
|
|
|
} elseif (strlen("$val") > 30) { |
|
235
|
|
|
$val = substr("$val", 0, 29) . '…'; |
|
236
|
|
|
if (strstr($val, ' ')) { |
|
237
|
|
|
$val = "'$val'"; |
|
238
|
|
|
} |
|
239
|
|
|
} elseif (strstr($val, ' ')) { |
|
240
|
|
|
$val = "'$val'"; |
|
241
|
|
|
} |
|
242
|
|
|
$infos[] = $var . '=' . $val; |
|
243
|
|
|
} |
|
244
|
|
|
return join(', ', $infos); |
|
245
|
|
|
} |
|
246
|
|
|
|
|
247
|
|
|
|
|
248
|
|
|
/** |
|
249
|
|
|
* Si le champ virtuel est non vide c'est une redirection. |
|
250
|
|
|
* avec un eventuel raccourci Spip |
|
251
|
|
|
* |
|
252
|
|
|
* si le raccourci a un titre il sera pris comme corps du 302 |
|
253
|
|
|
* |
|
254
|
|
|
* @uses public_tester_redirection_dist() |
|
255
|
|
|
* @param string $fond |
|
256
|
|
|
* @param array $contexte |
|
257
|
|
|
* @param string $connect |
|
258
|
|
|
* @return array|bool |
|
259
|
|
|
*/ |
|
260
|
|
|
function tester_redirection($fond, $contexte, $connect) { |
|
261
|
|
|
static $tester_redirection = null; |
|
262
|
|
|
if (is_null($tester_redirection)) { |
|
263
|
|
|
$tester_redirection = charger_fonction('tester_redirection', 'public'); |
|
264
|
|
|
} |
|
265
|
|
|
return $tester_redirection($fond, $contexte, $connect); |
|
266
|
|
|
} |
|
267
|
|
|
|
|
268
|
|
|
|
|
269
|
|
|
/** |
|
270
|
|
|
* Si le champ virtuel est non vide c'est une redirection. |
|
271
|
|
|
* avec un eventuel raccourci Spip |
|
272
|
|
|
* |
|
273
|
|
|
* si le raccourci a un titre il sera pris comme corps du 302 |
|
274
|
|
|
* |
|
275
|
|
|
* @param string $fond |
|
276
|
|
|
* @param array $contexte |
|
277
|
|
|
* @param string $connect |
|
278
|
|
|
* @return array|bool |
|
|
|
|
|
|
279
|
|
|
*/ |
|
280
|
|
|
function public_tester_redirection_dist($fond, $contexte, $connect) { |
|
281
|
|
|
if ($fond == 'article' |
|
282
|
|
|
and $id_article = intval($contexte['id_article']) |
|
283
|
|
|
) { |
|
284
|
|
|
include_spip('public/quete'); // pour quete_virtuel et ses dependances |
|
285
|
|
|
$m = quete_virtuel($id_article, $connect); |
|
286
|
|
|
if (strlen($m)) { |
|
287
|
|
|
include_spip('inc/texte'); |
|
288
|
|
|
// les navigateurs pataugent si l'URL est vide |
|
289
|
|
|
if ($url = virtuel_redirige($m, true)) { |
|
290
|
|
|
// passer en url absolue car cette redirection pourra |
|
291
|
|
|
// etre utilisee dans un contexte d'url qui change |
|
292
|
|
|
// y compris url arbo |
|
293
|
|
|
$status = 302; |
|
294
|
|
|
if (defined('_STATUS_REDIRECTION_VIRTUEL')) { |
|
295
|
|
|
$status = _STATUS_REDIRECTION_VIRTUEL; |
|
296
|
|
|
} |
|
297
|
|
|
if (!preg_match(',^\w+:,', $url)) { |
|
298
|
|
|
include_spip('inc/filtres_mini'); |
|
299
|
|
|
$url = url_absolue($url); |
|
300
|
|
|
} |
|
301
|
|
|
$url = str_replace('&', '&', $url); |
|
302
|
|
|
|
|
303
|
|
|
return array( |
|
304
|
|
|
'texte' => "<" |
|
305
|
|
|
. "?php include_spip('inc/headers');redirige_par_entete('" |
|
306
|
|
|
. texte_script($url) |
|
307
|
|
|
. "','',$status);" |
|
308
|
|
|
. "?" . ">", |
|
309
|
|
|
'process_ins' => 'php', |
|
310
|
|
|
'status' => $status |
|
311
|
|
|
); |
|
312
|
|
|
} |
|
313
|
|
|
} |
|
314
|
|
|
} |
|
315
|
|
|
|
|
316
|
|
|
return false; |
|
317
|
|
|
} |
|
318
|
|
|
|
This check marks calls to
isset(...)orempty(...)that are found before the variable itself is defined. These will always have the same result.This is likely the result of code being shifted around. Consider removing these calls.