3 /***************************************************************************\
4 * SPIP, Systeme de publication pour l'internet *
6 * Copyright (c) 2001-2017 *
7 * Arnaud Martin, Antoine Pitrou, Philippe Riviere, Emmanuel Saint-James *
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 \***************************************************************************/
13 if (!defined('_ECRIRE_INC_VERSION')) {
17 include_spip('inc/lang');
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);
26 if (@is_readable
(_CACHE_PLUGINS_FCT
)) {
27 // chargement optimise precompile
28 include_once(_CACHE_PLUGINS_FCT
);
30 if (test_espace_prive()) {
31 include_spip('inc/filtres_ecrire');
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)
45 # En cas d'erreur process_ins est absent et texte est un tableau de 2 chaines
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);
55 if (isset($contexte['lang'])) {
56 $lang = $contexte['lang'];
57 } elseif (!isset($lang)) {
58 $lang = $GLOBALS['meta']['langue_site'];
61 $select = ((!isset($GLOBALS['forcer_lang']) or !$GLOBALS['forcer_lang']) and $lang <> $GLOBALS['spip_lang']);
63 $select = lang_select($lang);
66 $debug = (defined('_VAR_MODE') && _VAR_MODE
== 'debug');
69 $styliser = charger_fonction('styliser', 'public');
71 list($skel, $mime_type, $gram, $sourcefile) =
72 $styliser($fond, $contexte, $GLOBALS['spip_lang'], $connect);
76 // sauver le nom de l'eventuel squelette en cours d'execution
77 // (recursion possible a cause des modeles)
79 $courant = @$GLOBALS['debug_objets']['courant'];
80 $GLOBALS['debug_objets']['contexte'][$sourcefile] = $contexte;
83 // charger le squelette en specifiant les langages cibles et source
84 // au cas il faudrait le compiler (source posterieure au resultat)
87 $composer = charger_fonction('composer', 'public');
89 $fonc = $composer($skel, $mime_type, $gram, $sourcefile, $connect);
94 if (!$fonc) { // squelette inconnu (==='') ou faux (===false)
97 // Preparer l'appel de la fonction principale du squelette
99 spip_timer($a = 'calcul page ' . rand(0, 1000));
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);
107 $notes('', 'empiler');
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 if (!isset($contexte['date'])) {
114 $contexte['date'] = date("Y-m-d H:i:s");
115 $contexte['date_default'] = true;
117 $contexte['date'] = normaliser_date($contexte['date'], true);
120 if (!isset($contexte['date_redac'])) {
121 $contexte['date_redac'] = date("Y-m-d H:i:s");
122 $contexte['date_redac_default'] = true;
124 $contexte['date_redac'] = normaliser_date($contexte['date_redac'], true);
127 // Passer le nom du cache pour produire sa destruction automatique
128 $page = $fonc(array('cache' => $cache), array($contexte));
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)
136 $notes('', 'depiler');
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)
145 $page['notes'] = $notes('', 'sauver_etat');
148 // spip_log: un joli contexte
150 foreach (array_filter($contexte) as $var => $val) {
151 if (is_array($val)) {
152 $val = serialize($val);
154 if (strlen("$val") > 30) {
155 $val = substr("$val", 0, 27) . '..';
157 if (strstr($val, ' ')) {
160 $infos[] = $var . '=' . $val;
162 $profile = spip_timer($a);
163 spip_log("calcul ($profile) [$skel] "
165 . ' (' . strlen($page['texte']) . ' octets)');
167 if (defined('_CALCUL_PROFILER') AND intval($profile)>_CALCUL_PROFILER
){
168 spip_log("calcul ($profile) [$skel] "
170 .' ('.strlen($page['texte']).' octets) | '.$_SERVER['REQUEST_URI'],"profiler"._LOG_AVERTISSEMENT
);
174 // si c'est ce que demande le debusqueur, lui passer la main
175 $t = strlen($page['texte']) ?
$page['texte'] : " ";
176 $GLOBALS['debug_objets']['resultat'][$fonc . 'tout'] = $t;
177 $GLOBALS['debug_objets']['courant'] = $courant;
178 $GLOBALS['debug_objets']['profile'][$sourcefile] = $profile;
179 if ($GLOBALS['debug_objets']['sourcefile']
180 and (_request('var_mode_objet') == $fonc)
181 and (_request('var_mode_affiche') == 'resultat')
186 // Si #CACHE{} n'etait pas la, le mettre a $delais
187 if (!isset($page['entetes']['X-Spip-Cache'])) {
188 // Dans l'espace prive ou dans un modeles/ on pose un cache 0 par defaut
189 // si aucun #CACHE{} spécifié
190 // le contexte implicite qui conditionne le cache assure qu'on retombe pas sur le meme
191 // entre public et prive
192 if (test_espace_prive() or strncmp($fond, 'modeles/', 8) == 0) {
193 $page['entetes']['X-Spip-Cache'] = 0;
195 $page['entetes']['X-Spip-Cache'] = isset($GLOBALS['delais']) ?
$GLOBALS['delais'] : 36000;
199 $page['contexte'] = $contexte;
201 // faire remonter le fichier source
202 static $js_inclus = false;
203 if (defined('_VAR_INCLURE') and _VAR_INCLURE
) {
204 $page['sourcefile'] = $sourcefile;
206 "<div class='inclure_blocs'><h6>" . $page['sourcefile'] . "</h6>" . $page['texte'] . "</div>"
207 . ($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>");
211 // Si un modele contenait #SESSION, on note l'info dans $page
212 if (isset($GLOBALS['cache_utilise_session'])) {
213 $page['invalideurs']['session'] = $GLOBALS['cache_utilise_session'];
214 unset($GLOBALS['cache_utilise_session']);
227 * Si le champ virtuel est non vide c'est une redirection.
228 * avec un eventuel raccourci Spip
230 * si le raccourci a un titre il sera pris comme corps du 302
232 * @uses public_tester_redirection_dist()
233 * @param string $fond
234 * @param array $contexte
235 * @param string $connect
238 function tester_redirection($fond, $contexte, $connect) {
239 static $tester_redirection = null;
240 if (is_null($tester_redirection)) {
241 $tester_redirection = charger_fonction('tester_redirection', 'public');
243 return $tester_redirection($fond, $contexte, $connect);
248 * Si le champ virtuel est non vide c'est une redirection.
249 * avec un eventuel raccourci Spip
251 * si le raccourci a un titre il sera pris comme corps du 302
253 * @param string $fond
254 * @param array $contexte
255 * @param string $connect
258 function public_tester_redirection_dist($fond, $contexte, $connect) {
259 if ($fond == 'article'
260 and $id_article = intval($contexte['id_article'])
262 include_spip('public/quete'); // pour quete_virtuel et ses dependances
263 $m = quete_virtuel($id_article, $connect);
265 include_spip('inc/texte');
266 // les navigateurs pataugent si l'URL est vide
267 if ($url = virtuel_redirige($m, true)) {
268 // passer en url absolue car cette redirection pourra
269 // etre utilisee dans un contexte d'url qui change
270 // y compris url arbo
272 if (defined('_STATUS_REDIRECTION_VIRTUEL')) {
273 $status = _STATUS_REDIRECTION_VIRTUEL
;
275 if (!preg_match(',^\w+:,', $url)) {
276 include_spip('inc/filtres_mini');
277 $url = url_absolue($url);
279 $url = str_replace('&', '&', $url);
283 . "?php include_spip('inc/headers');redirige_par_entete('"
287 'process_ins' => 'php',