bbe6ba01fc3809a29a6860a95e5a9de20feae707
[lhc/web/www.git] / www / ecrire / public / assembler.php
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 /**
14 * Ce fichier regroupe les fonctions permettant de calculer la page et les entĂȘtes
15 *
16 * Determine le contexte donne par l'URL (en tenant compte des reecritures)
17 * grace a la fonction de passage d'URL a id (reciproque dans urls/*php)
18 *
19 * @package SPIP\Core\Compilateur\Assembler
20 **/
21
22 if (!defined('_ECRIRE_INC_VERSION')) {
23 return;
24 }
25
26 if (!defined('_CONTEXTE_IGNORE_VARIABLES')) {
27 define('_CONTEXTE_IGNORE_VARIABLES', "/(^var_|^PHPSESSID$|^fbclid$|^utm_)/");
28 }
29
30 // http://code.spip.net/@assembler
31 function assembler($fond, $connect = '') {
32
33 // flag_preserver est modifie ici, et utilise en globale
34 // use_cache sert a informer le bouton d'admin pr savoir s'il met un *
35 // contexte est utilise en globale dans le formulaire d'admin
36
37 $GLOBALS['contexte'] = calculer_contexte();
38 $page = array('contexte_implicite' => calculer_contexte_implicite());
39 $page['contexte_implicite']['cache'] = $fond . preg_replace(',\.[a-zA-Z0-9]*$,', '',
40 preg_replace('/[?].*$/', '', $GLOBALS['REQUEST_URI']));
41 // Cette fonction est utilisee deux fois
42 $cacher = charger_fonction('cacher', 'public', true);
43 // Les quatre derniers parametres sont modifies par la fonction:
44 // emplacement, validite, et, s'il est valide, contenu & age
45 if ($cacher) {
46 $res = $cacher($GLOBALS['contexte'], $GLOBALS['use_cache'], $chemin_cache, $page, $lastmodified);
47 } else {
48 $GLOBALS['use_cache'] = -1;
49 }
50 // Si un resultat est retourne, c'est un message d'impossibilite
51 if ($res) {
52 return array('texte' => $res);
53 }
54
55 if (!$chemin_cache || !$lastmodified) {
56 $lastmodified = time();
57 }
58
59 $headers_only = ($_SERVER['REQUEST_METHOD'] == 'HEAD');
60 $calculer_page = true;
61
62 // Pour les pages non-dynamiques (indiquees par #CACHE{duree,cache-client})
63 // une perennite valide a meme reponse qu'une requete HEAD (par defaut les
64 // pages sont dynamiques)
65 if (isset($_SERVER['HTTP_IF_MODIFIED_SINCE'])
66 and (!defined('_VAR_MODE') or !_VAR_MODE)
67 and $chemin_cache
68 and isset($page['entetes'])
69 and isset($page['entetes']['Cache-Control'])
70 and strstr($page['entetes']['Cache-Control'], 'max-age=')
71 and !strstr($_SERVER['SERVER_SOFTWARE'], 'IIS/')
72 ) {
73 $since = preg_replace('/;.*/', '',
74 $_SERVER['HTTP_IF_MODIFIED_SINCE']);
75 $since = str_replace('GMT', '', $since);
76 if (trim($since) == gmdate("D, d M Y H:i:s", $lastmodified)) {
77 $page['status'] = 304;
78 $headers_only = true;
79 $calculer_page = false;
80 }
81 }
82
83 // Si requete HEAD ou Last-modified compatible, ignorer le texte
84 // et pas de content-type (pour contrer le bouton admin de inc-public)
85 if (!$calculer_page) {
86 $page['texte'] = "";
87 } else {
88 // si la page est prise dans le cache
89 if (!$GLOBALS['use_cache']) {
90 // Informer les boutons d'admin du contexte
91 // (fourni par urls_decoder_url ci-dessous lors de la mise en cache)
92 $GLOBALS['contexte'] = $page['contexte'];
93
94 // vider les globales url propres qui ne doivent plus etre utilisees en cas
95 // d'inversion url => objet
96 // plus necessaire si on utilise bien la fonction urls_decoder_url
97 #unset($_SERVER['REDIRECT_url_propre']);
98 #unset($_ENV['url_propre']);
99 } else {
100 // Compat ascendante :
101 // 1. $contexte est global
102 // (a evacuer car urls_decoder_url gere ce probleme ?)
103 // et calculer la page
104 if (!test_espace_prive()) {
105 include_spip('inc/urls');
106 list($fond, $GLOBALS['contexte'], $url_redirect) = urls_decoder_url(nettoyer_uri(), $fond, $GLOBALS['contexte'],
107 true);
108 }
109 // squelette par defaut
110 if (!strlen($fond)) {
111 $fond = 'sommaire';
112 }
113
114 // produire la page : peut mettre a jour $lastmodified
115 $produire_page = charger_fonction('produire_page', 'public');
116 $page = $produire_page($fond, $GLOBALS['contexte'], $GLOBALS['use_cache'], $chemin_cache, null, $page,
117 $lastmodified, $connect);
118 if ($page === '') {
119 $erreur = _T('info_erreur_squelette2',
120 array('fichier' => spip_htmlspecialchars($fond) . '.' . _EXTENSION_SQUELETTES));
121 erreur_squelette($erreur);
122 // eviter des erreurs strictes ensuite sur $page['cle'] en PHP >= 5.4
123 $page = array('texte' => '', 'erreur' => $erreur);
124 }
125 }
126
127 if ($page and $chemin_cache) {
128 $page['cache'] = $chemin_cache;
129 }
130
131 auto_content_type($page);
132
133 $GLOBALS['flag_preserver'] |= headers_sent();
134
135 // Definir les entetes si ce n'est fait
136 if (!$GLOBALS['flag_preserver']) {
137 if ($GLOBALS['flag_ob']) {
138 // Si la page est vide, produire l'erreur 404 ou message d'erreur pour les inclusions
139 if (trim($page['texte']) === ''
140 and _VAR_MODE != 'debug'
141 and !isset($page['entetes']['Location']) // cette page realise une redirection, donc pas d'erreur
142 ) {
143 $GLOBALS['contexte']['fond_erreur'] = $fond;
144 $page = message_page_indisponible($page, $GLOBALS['contexte']);
145 }
146 // pas de cache client en mode 'observation'
147 if (defined('_VAR_MODE') and _VAR_MODE) {
148 $page['entetes']["Cache-Control"] = "no-cache,must-revalidate";
149 $page['entetes']["Pragma"] = "no-cache";
150 }
151 }
152 }
153 }
154
155 // Entete Last-Modified:
156 // eviter d'etre incoherent en envoyant un lastmodified identique
157 // a celui qu'on a refuse d'honorer plus haut (cf. #655)
158 if ($lastmodified
159 and !isset($_SERVER['HTTP_IF_MODIFIED_SINCE'])
160 and !isset($page['entetes']["Last-Modified"])
161 ) {
162 $page['entetes']["Last-Modified"] = gmdate("D, d M Y H:i:s", $lastmodified) . " GMT";
163 }
164
165 // fermer la connexion apres les headers si requete HEAD
166 if ($headers_only) {
167 $page['entetes']["Connection"] = "close";
168 }
169
170 return $page;
171 }
172
173 /**
174 * Calcul le contexte de la page
175 *
176 * lors du calcul d'une page spip etablit le contexte a partir
177 * des variables $_GET et $_POST, purgees des fausses variables var_*
178 *
179 * Note : pour hacker le contexte depuis le fichier d'appel (page.php),
180 * il est recommande de modifier $_GET['toto'] (meme si la page est
181 * appelee avec la methode POST).
182 *
183 * http://code.spip.net/@calculer_contexte
184 *
185 * @return array Un tableau du contexte de la page
186 */
187 function calculer_contexte() {
188
189 $contexte = array();
190 foreach ($_GET as $var => $val) {
191 if (!preg_match(_CONTEXTE_IGNORE_VARIABLES, $var)) {
192 $contexte[$var] = $val;
193 }
194 }
195 foreach ($_POST as $var => $val) {
196 if (!preg_match(_CONTEXTE_IGNORE_VARIABLES, $var)) {
197 $contexte[$var] = $val;
198 }
199 }
200
201 return $contexte;
202 }
203
204 /**
205 * Calculer le contexte implicite, qui n'apparait pas dans le ENV d'un cache
206 * mais est utilise pour distinguer deux caches differents
207 *
208 * @staticvar string $notes
209 * @return array
210 */
211 function calculer_contexte_implicite() {
212 static $notes = null;
213 if (is_null($notes)) {
214 $notes = charger_fonction('notes', 'inc', true);
215 }
216 $contexte_implicite = array(
217 'squelettes' => $GLOBALS['dossier_squelettes'], // devrait etre 'chemin' => $GLOBALS['path_sig'], ?
218 'host' => (isset($_SERVER['HTTP_HOST']) ? $_SERVER['HTTP_HOST'] : null),
219 'https' => (isset($_SERVER['HTTPS']) ? $_SERVER['HTTPS'] : ''),
220 'espace' => test_espace_prive(),
221 'marqueur' => (isset($GLOBALS['marqueur']) ? $GLOBALS['marqueur'] : ''),
222 'marqueur_skel' => (isset($GLOBALS['marqueur_skel']) ? $GLOBALS['marqueur_skel'] : ''),
223 'notes' => $notes ? $notes('', 'contexter_cache') : '',
224 'spip_version_code' => $GLOBALS['spip_version_code'],
225 );
226 if (isset($_SERVER['HTTP_X_FORWARDED_HOST'])) {
227 $contexte_implicite['host'] .= "|" . $_SERVER['HTTP_X_FORWARDED_HOST'];
228 }
229
230 return $contexte_implicite;
231 }
232
233 //
234 // fonction pour compatibilite arriere, probablement superflue
235 //
236
237 // http://code.spip.net/@auto_content_type
238 function auto_content_type($page) {
239
240 if (!isset($GLOBALS['flag_preserver'])) {
241 $GLOBALS['flag_preserver'] = ($page && preg_match("/header\s*\(\s*.content\-type:/isx",
242 $page['texte']) || (isset($page['entetes']['Content-Type'])));
243 }
244 }
245
246 // http://code.spip.net/@inclure_page
247 function inclure_page($fond, $contexte, $connect = '') {
248 static $cacher, $produire_page;
249
250 // enlever le fond de contexte inclus car sinon il prend la main
251 // dans les sous inclusions -> boucle infinie d'inclusion identique
252 // (cette precaution n'est probablement plus utile)
253 unset($contexte['fond']);
254 $page = array('contexte_implicite' => calculer_contexte_implicite());
255 $page['contexte_implicite']['cache'] = $fond;
256 if (is_null($cacher)) {
257 $cacher = charger_fonction('cacher', 'public', true);
258 }
259 // Les quatre derniers parametres sont modifies par la fonction:
260 // emplacement, validite, et, s'il est valide, contenu & age
261 if ($cacher) {
262 $res = $cacher($contexte, $use_cache, $chemin_cache, $page, $lastinclude);
263 } else {
264 $use_cache = -1;
265 }
266 // $res = message d'erreur : on sort de la
267 if ($res) {
268 return array('texte' => $res);
269 }
270
271 // Si use_cache ne vaut pas 0, la page doit etre calculee
272 // produire la page : peut mettre a jour $lastinclude
273 // le contexte_cache envoye a cacher() a ete conserve et est passe a produire
274 if ($use_cache) {
275 if (is_null($produire_page)) {
276 $produire_page = charger_fonction('produire_page', 'public');
277 }
278 $page = $produire_page($fond, $contexte, $use_cache, $chemin_cache, $contexte, $page, $lastinclude, $connect);
279 }
280 // dans tous les cas, mettre a jour $GLOBALS['lastmodified']
281 $GLOBALS['lastmodified'] = max((isset($GLOBALS['lastmodified']) ? $GLOBALS['lastmodified'] : 0), $lastinclude);
282
283 return $page;
284 }
285
286 /**
287 * Produire la page et la mettre en cache
288 * lorsque c'est necessaire
289 *
290 * @param string $fond
291 * @param array $contexte
292 * @param int $use_cache
293 * @param string $chemin_cache
294 * @param array $contexte_cache
295 * @param array $page
296 * @param int $lastinclude
297 * @param string $connect
298 * @return array
299 */
300 function public_produire_page_dist(
301 $fond,
302 $contexte,
303 $use_cache,
304 $chemin_cache,
305 $contexte_cache,
306 &$page,
307 &$lastinclude,
308 $connect = ''
309 ) {
310 static $parametrer, $cacher;
311 if (!$parametrer) {
312 $parametrer = charger_fonction('parametrer', 'public');
313 }
314 $page = $parametrer($fond, $contexte, $chemin_cache, $connect);
315 // et on l'enregistre sur le disque
316 if ($chemin_cache
317 and $use_cache > -1
318 and is_array($page)
319 and count($page)
320 and isset($page['entetes']['X-Spip-Cache'])
321 and $page['entetes']['X-Spip-Cache'] > 0
322 ) {
323 if (is_null($cacher)) {
324 $cacher = charger_fonction('cacher', 'public', true);
325 }
326 $lastinclude = time();
327 if ($cacher) {
328 $cacher($contexte_cache, $use_cache, $chemin_cache, $page, $lastinclude);
329 } else {
330 $use_cache = -1;
331 }
332 }
333
334 return $page;
335 }
336
337 // Fonction inseree par le compilateur dans le code compile.
338 // Elle recoit un contexte pour inclure un squelette,
339 // et les valeurs du contexte de compil prepare par memoriser_contexte_compil
340 // elle-meme appelee par calculer_balise_dynamique dans references.php:
341 // 0: sourcefile
342 // 1: codefile
343 // 2: id_boucle
344 // 3: ligne
345 // 4: langue
346
347 function inserer_balise_dynamique($contexte_exec, $contexte_compil) {
348 arguments_balise_dyn_depuis_modele(null, 'reset');
349
350 if (!is_array($contexte_exec)) {
351 echo $contexte_exec;
352 } // message d'erreur etc
353 else {
354 inclure_balise_dynamique($contexte_exec, true, $contexte_compil);
355 }
356 }
357
358 /**
359 * Inclusion de balise dynamique
360 * Attention, un appel explicite a cette fonction suppose certains include
361 *
362 * http://code.spip.net/@inclure_balise_dynamique
363 *
364 * @param string|array $texte
365 * @param bool $echo Faut-il faire echo ou return
366 * @param array $contexte_compil Contexte de la compilation
367 * @return string
368 */
369 function inclure_balise_dynamique($texte, $echo = true, $contexte_compil = array()) {
370 if (is_array($texte)) {
371
372 list($fond, $delainc, $contexte_inclus) = $texte;
373
374 // delais a l'ancienne, c'est pratiquement mort
375 $d = isset($GLOBALS['delais']) ? $GLOBALS['delais'] : null;
376 $GLOBALS['delais'] = $delainc;
377
378 $page = recuperer_fond($fond, $contexte_inclus,
379 array('trim' => false, 'raw' => true, 'compil' => $contexte_compil));
380
381 $texte = $page['texte'];
382
383 $GLOBALS['delais'] = $d;
384 // Faire remonter les entetes
385 if (is_array($page['entetes'])) {
386 // mais pas toutes
387 unset($page['entetes']['X-Spip-Cache']);
388 unset($page['entetes']['Content-Type']);
389 if (isset($GLOBALS['page']) and is_array($GLOBALS['page'])) {
390 if (!is_array($GLOBALS['page']['entetes'])) {
391 $GLOBALS['page']['entetes'] = array();
392 }
393 $GLOBALS['page']['entetes'] =
394 array_merge($GLOBALS['page']['entetes'], $page['entetes']);
395 }
396 }
397 // _pipelines au pluriel array('nom_pipeline' => $args...) avec une syntaxe permettant plusieurs pipelines
398 if (isset($page['contexte']['_pipelines'])
399 and is_array($page['contexte']['_pipelines'])
400 and count($page['contexte']['_pipelines'])
401 ) {
402 foreach ($page['contexte']['_pipelines'] as $pipe => $args) {
403 $args['contexte'] = $page['contexte'];
404 unset($args['contexte']['_pipelines']); // par precaution, meme si le risque de boucle infinie est a priori nul
405 $texte = pipeline(
406 $pipe,
407 array(
408 'data' => $texte,
409 'args' => $args
410 ),
411 false
412 );
413 }
414 }
415 }
416
417 if (defined('_VAR_MODE') and _VAR_MODE == 'debug') {
418 // compatibilite : avant on donnait le numero de ligne ou rien.
419 $ligne = intval(isset($contexte_compil[3]) ? $contexte_compil[3] : $contexte_compil);
420 $GLOBALS['debug_objets']['resultat'][$ligne] = $texte;
421 }
422 if ($echo) {
423 echo $texte;
424 } else {
425 return $texte;
426 }
427 }
428
429 // http://code.spip.net/@message_page_indisponible
430 function message_page_indisponible($page, $contexte) {
431 static $deja = false;
432 if ($deja) {
433 return "erreur";
434 }
435 $codes = array(
436 '404' => '404 Not Found',
437 '503' => '503 Service Unavailable',
438 );
439
440 $contexte['status'] = ($page !== false) ? '404' : '503';
441 $contexte['code'] = $codes[$contexte['status']];
442 $contexte['fond'] = '404'; // gere les 2 erreurs
443 if (!isset($contexte['lang'])) {
444 $contexte['lang'] = $GLOBALS['spip_lang'];
445 }
446
447 $deja = true;
448 // passer aux plugins qui peuvent decider d'une page d'erreur plus pertinent
449 // ex restriction d'acces => 401
450 $contexte = pipeline('page_indisponible', $contexte);
451
452 // produire la page d'erreur
453 $page = inclure_page($contexte['fond'], $contexte);
454 if (!$page) {
455 $page = inclure_page('404', $contexte);
456 }
457 $page['status'] = $contexte['status'];
458
459 return $page;
460 }
461
462 /**
463 * gerer le flag qui permet de reperer qu'une balise dynamique a ete inseree depuis un modele
464 * utilisee dans les #FORMULAIRE_xx
465 *
466 * @param string|null $arg
467 * @param string $operation
468 * @return mixed
469 */
470 function arguments_balise_dyn_depuis_modele($arg, $operation = 'set') {
471 static $balise_dyn_appellee_par_modele = null;
472 switch ($operation) {
473 case 'read':
474 return $balise_dyn_appellee_par_modele;
475 case 'reset':
476 $balise_dyn_appellee_par_modele = null;
477 return null;
478 case 'set':
479 default:
480 $balise_dyn_appellee_par_modele = $arg;
481 return $arg;
482 }
483 }
484
485 // temporairement ici : a mettre dans le futur inc/modeles
486 // creer_contexte_de_modele('left', 'autostart=true', ...) renvoie un array()
487 // http://code.spip.net/@creer_contexte_de_modele
488 function creer_contexte_de_modele($args) {
489 $contexte = array();
490 foreach ($args as $var => $val) {
491 if (is_int($var)) { // argument pas formate
492 if (in_array($val, array('left', 'right', 'center'))) {
493 $var = 'align';
494 $contexte[$var] = $val;
495 } else {
496 $args = explode('=', $val);
497 if (count($args) >= 2) // Flashvars=arg1=machin&arg2=truc genere plus de deux args
498 {
499 $contexte[trim($args[0])] = substr($val, strlen($args[0]) + 1);
500 } else // notation abregee
501 {
502 $contexte[trim($val)] = trim($val);
503 }
504 }
505 } else {
506 $contexte[$var] = $val;
507 }
508 }
509
510 return $contexte;
511 }
512
513 /**
514 * Calcule le modele et retourne la mini-page ainsi calculee
515 *
516 * http://code.spip.net/@inclure_modele
517 *
518 * @param $type string Nom du modele
519 * @param $id int
520 * @param $params array ParamĂštres du modĂšle
521 * @param $lien array Informations du lien entourant l'appel du modÚle en base de données
522 * @param $connect string
523 * @param $env array
524 * @staticvar string $compteur
525 * @return string
526 */
527 function inclure_modele($type, $id, $params, $lien, $connect = '', $env = array()) {
528
529 static $compteur;
530 if (++$compteur > 10) {
531 return '';
532 } # ne pas boucler indefiniment
533
534 $type = strtolower($type);
535
536 $fond = $class = '';
537
538 $params = array_filter(explode('|', $params));
539 if ($params) {
540 list(, $soustype) = each($params);
541 $soustype = strtolower(trim($soustype));
542 if (in_array($soustype,
543 array('left', 'right', 'center', 'ajax'))) {
544 list(, $soustype) = each($params);
545 $soustype = strtolower($soustype);
546 }
547
548 if (preg_match(',^[a-z0-9_]+$,', $soustype)) {
549 if (!trouve_modele($fond = ($type . '_' . $soustype))) {
550 $fond = '';
551 $class = $soustype;
552 }
553 // enlever le sous type des params
554 $params = array_diff($params, array($soustype));
555 }
556 }
557
558 // Si ca marche pas en precisant le sous-type, prendre le type
559 if (!$fond and !trouve_modele($fond = $type)) {
560 spip_log("Modele $type introuvable", _LOG_INFO_IMPORTANTE);
561
562 return false;
563 }
564 $fond = 'modeles/' . $fond;
565 // Creer le contexte
566 $contexte = $env;
567 $contexte['dir_racine'] = _DIR_RACINE; # eviter de mixer un cache racine et un cache ecrire (meme si pour l'instant les modeles ne sont pas caches, le resultat etant different il faut que le contexte en tienne compte
568
569 // Le numero du modele est mis dans l'environnement
570 // d'une part sous l'identifiant "id"
571 // et d'autre part sous l'identifiant de la cle primaire
572 // par la fonction id_table_objet,
573 // (<article1> =>> article =>> id_article =>> id_article=1)
574 $_id = id_table_objet($type);
575 $contexte['id'] = $contexte[$_id] = $id;
576
577 if (isset($class)) {
578 $contexte['class'] = $class;
579 }
580
581 // Si un lien a ete passe en parametre, ex: [<modele1>->url] ou [<modele1|title_du_lien{hreflang}->url]
582 if ($lien) {
583 # un eventuel guillemet (") sera reechappe par #ENV
584 $contexte['lien'] = str_replace("&quot;", '"', $lien['href']);
585 $contexte['lien_class'] = $lien['class'];
586 $contexte['lien_mime'] = $lien['mime'];
587 $contexte['lien_title'] = $lien['title'];
588 $contexte['lien_hreflang'] = $lien['hreflang'];
589 }
590
591 // Traiter les parametres
592 // par exemple : <img1|center>, <emb12|autostart=true> ou <doc1|lang=en>
593 $arg_list = creer_contexte_de_modele($params);
594 $contexte['args'] = $arg_list; // on passe la liste des arguments du modeles dans une variable args
595 $contexte = array_merge($contexte, $arg_list);
596
597 // Appliquer le modele avec le contexte
598 $retour = recuperer_fond($fond, $contexte, array(), $connect);
599
600 // Regarder si le modele tient compte des liens (il *doit* alors indiquer
601 // spip_lien_ok dans les classes de son conteneur de premier niveau ;
602 // sinon, s'il y a un lien, on l'ajoute classiquement
603 if (strstr(' ' . ($classes = extraire_attribut($retour, 'class')) . ' ',
604 'spip_lien_ok')) {
605 $retour = inserer_attribut($retour, 'class',
606 trim(str_replace(' spip_lien_ok ', ' ', " $classes ")));
607 } else {
608 if ($lien) {
609 $retour = "<a href='" . $lien['href'] . "' class='" . $lien['class'] . "'>" . $retour . "</a>";
610 }
611 }
612
613 $compteur--;
614
615 return (isset($arg_list['ajax']) and $arg_list['ajax'] == 'ajax')
616 ? encoder_contexte_ajax($contexte, '', $retour)
617 : $retour;
618 }
619
620 // Un inclure_page qui marche aussi pour l'espace prive
621 // fonction interne a spip, ne pas appeler directement
622 // pour recuperer $page complet, utiliser:
623 // recuperer_fond($fond,$contexte,array('raw'=>true))
624 // http://code.spip.net/@evaluer_fond
625 function evaluer_fond($fond, $contexte = array(), $connect = null) {
626
627 $page = inclure_page($fond, $contexte, $connect);
628
629 if (!$page) {
630 return $page;
631 }
632 // eval $page et affecte $res
633 include _ROOT_RESTREINT . "public/evaluer_page.php";
634
635 // Lever un drapeau (global) si le fond utilise #SESSION
636 // a destination de public/parametrer
637 // pour remonter vers les inclusions appelantes
638 // il faut bien lever ce drapeau apres avoir evalue le fond
639 // pour ne pas faire descendre le flag vers les inclusions appelees
640 if (isset($page['invalideurs'])
641 and isset($page['invalideurs']['session'])
642 ) {
643 $GLOBALS['cache_utilise_session'] = $page['invalideurs']['session'];
644 }
645
646 return $page;
647 }
648
649
650 // http://code.spip.net/@page_base_href
651 function page_base_href(&$texte) {
652 static $set_html_base = null;
653 if (is_null($set_html_base)) {
654 if (!defined('_SET_HTML_BASE'))
655 // si la profondeur est superieure a 1
656 // est que ce n'est pas une url page ni une url action
657 // activer par defaut
658 {
659 $set_html_base = ((
660 $GLOBALS['profondeur_url'] >= (_DIR_RESTREINT ? 1 : 2)
661 and _request(_SPIP_PAGE) !== 'login'
662 and !_request('action')) ? true : false);
663 } else {
664 $set_html_base = _SET_HTML_BASE;
665 }
666 }
667
668 if ($set_html_base
669 and isset($GLOBALS['html']) and $GLOBALS['html']
670 and $GLOBALS['profondeur_url'] > 0
671 and ($poshead = strpos($texte, '</head>')) !== false
672 ) {
673 $head = substr($texte, 0, $poshead);
674 $insert = false;
675 if (strpos($head, '<base') === false) {
676 $insert = true;
677 } else {
678 // si aucun <base ...> n'a de href c'est bon quand meme !
679 $insert = true;
680 include_spip('inc/filtres');
681 $bases = extraire_balises($head, 'base');
682 foreach ($bases as $base) {
683 if (extraire_attribut($base, 'href')) {
684 $insert = false;
685 }
686 }
687 }
688 if ($insert) {
689 include_spip('inc/filtres_mini');
690 // ajouter un base qui reglera tous les liens relatifs
691 $base = url_absolue('./');
692 $bbase = "\n<base href=\"$base\" />";
693 if (($pos = strpos($head, '<head>')) !== false) {
694 $head = substr_replace($head, $bbase, $pos + 6, 0);
695 } elseif (preg_match(",<head[^>]*>,i", $head, $r)) {
696 $head = str_replace($r[0], $r[0] . $bbase, $head);
697 }
698 $texte = $head . substr($texte, $poshead);
699 // gerer les ancres
700 $base = $_SERVER['REQUEST_URI'];
701 // pas de guillemets ni < dans l'URL qu'on insere dans le HTML
702 if (strpos($base,"'") or strpos($base,'"') or strpos($base,'<')) {
703 $base = str_replace(array("'",'"','<'),array("%27",'%22','%3C'), $base);
704 }
705 if (strpos($texte, "href='#") !== false) {
706 $texte = str_replace("href='#", "href='$base#", $texte);
707 }
708 if (strpos($texte, "href=\"#") !== false) {
709 $texte = str_replace("href=\"#", "href=\"$base#", $texte);
710 }
711 }
712 }
713 }
714
715
716 // Envoyer les entetes, en retenant ceux qui sont a usage interne
717 // et demarrent par X-Spip-...
718 // http://code.spip.net/@envoyer_entetes
719 function envoyer_entetes($entetes) {
720 foreach ($entetes as $k => $v) # if (strncmp($k, 'X-Spip-', 7))
721 {
722 @header(strlen($v) ? "$k: $v" : $k);
723 }
724 }