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