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