[SPIP] ~2.1.12 -->2.1.25
[velocampus/web/www.git] / www / ecrire / inc / utils.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 //
16 // Utilitaires indispensables autour du serveur Http.
17 //
18
19 // charge un fichier perso ou, a defaut, standard
20 // et retourne si elle existe le nom de la fonction homonyme (exec_$nom),
21 // ou de suffixe _dist
22 // Peut etre appelee plusieurs fois, donc optimiser
23 // http://doc.spip.org/@charger_fonction
24 function charger_fonction($nom, $dossier='exec', $continue=false) {
25
26 if (strlen($dossier) AND substr($dossier,-1) != '/') $dossier .= '/';
27
28 if (function_exists($f = str_replace('/','_',$dossier) . $nom))
29 return $f;
30 if (function_exists($g = $f . '_dist'))
31 return $g;
32
33 // Sinon charger le fichier de declaration si plausible
34
35 if (!preg_match(',^\w+$,', $f))
36 die(htmlspecialchars($nom)." pas autorise");
37
38 // passer en minuscules (cf les balises de formulaires)
39 // et inclure le fichier
40 if (!$inc = include_spip($dossier.($d = strtolower($nom)))
41 // si le fichier truc/machin/nom.php n'existe pas,
42 // la fonction peut etre definie dans truc/machin.php qui regroupe plusieurs petites fonctions
43 AND strlen(dirname($dossier)) AND dirname($dossier)!='.')
44 include_spip(substr($dossier,0,-1));
45 if (function_exists($f)) return $f;
46 if (function_exists($g)) return $g;
47
48 if ($continue) return false;
49
50 // Echec : message d'erreur
51 spip_log("fonction $nom ($f ou $g) indisponible" .
52 ($inc ? "" : " (fichier $d absent de $dossier)"));
53
54 include_spip('inc/minipres');
55 echo minipres(_T('forum_titre_erreur'),
56 _T('fichier_introuvable', array('fichier'=> '<b>'.htmlentities($d).'</b>')));
57 exit;
58 }
59
60
61 //
62 // la fonction cherchant un fichier PHP dans le SPIP_PATH
63 //
64 // http://doc.spip.org/@include_spip
65 function include_spip($f, $include = true) {
66 return find_in_path($f . '.php', '', $include);
67 }
68
69 // un pipeline est lie a une action et une valeur
70 // chaque element du pipeline est autorise a modifier la valeur
71 //
72 // le pipeline execute les elements disponibles pour cette action,
73 // les uns apres les autres, et retourne la valeur finale
74 //
75 // Cf. compose_filtres dans references.php, qui est la
76 // version compilee de cette fonctionnalite
77
78 // appel unitaire d'une fonction du pipeline
79 // utilisee dans le script pipeline precompile
80 // on passe $val par reference pour limiter les allocations memoire
81 // http://doc.spip.org/@minipipe
82 function minipipe($fonc,&$val){
83 // fonction
84 if (function_exists($fonc))
85 $val = call_user_func($fonc, $val);
86
87 // Class::Methode
88 else if (preg_match("/^(\w*)::(\w*)$/S", $fonc, $regs)
89 AND $methode = array($regs[1], $regs[2])
90 AND is_callable($methode))
91 $val = call_user_func($methode, $val);
92 else
93 spip_log("Erreur - '$fonc' non definie !");
94 return $val;
95 }
96
97 // chargement du pipeline sous la forme d'un fichier php prepare
98 // http://doc.spip.org/@pipeline
99 function pipeline($action, $val=null) {
100 static $charger;
101
102 // chargement initial des fonctions mises en cache, ou generation du cache
103 if (!$charger) {
104 if (!($ok = @is_readable($charger = _CACHE_PIPELINES))) {
105 include_spip('inc/plugin');
106 // generer les fichiers php precompiles
107 // de chargement des plugins et des pipelines
108 actualise_plugins_actifs();
109 if (!($ok = @is_readable($charger)))
110 spip_log("fichier $charger pas cree");
111 }
112
113 if ($ok)
114 include_once $charger;
115 }
116
117 // appliquer notre fonction si elle existe
118 $fonc = 'execute_pipeline_'.strtolower($action);
119 if (function_exists($fonc)) {
120 $val = $fonc($val);
121 }
122 // plantage ?
123 else {
124 include_spip('inc/plugin');
125 // on passe $action en arg pour creer la fonction meme si le pipe
126 // n'est defini nul part ; vu qu'on est la c'est qu'il existe !
127 actualise_plugins_actifs(strtolower($action));
128 spip_log("fonction $fonc absente : pipeline desactive");
129 }
130
131 // si le flux est une table qui encapsule donnees et autres
132 // on ne ressort du pipe que les donnees
133 // array_key_exists pour php 4.1.0
134 if (is_array($val)
135 AND count($val)==2
136 AND (array_key_exists('data',$val)))
137 $val = $val['data'];
138 return $val;
139 }
140
141 //
142 // Enregistrement des evenements
143 //
144 // http://doc.spip.org/@spip_log
145 function spip_log($message, $logname=NULL, $logdir=NULL, $logsuf=NULL) {
146 $log = charger_fonction('log', 'inc');
147 $log( $message, $logname, $logdir, $logsuf);
148 }
149
150 // Renvoie le _GET ou le _POST emis par l'utilisateur
151 // ou pioche dans $c si c'est un array()
152 // http://doc.spip.org/@_request
153 function _request($var, $c=false) {
154
155 if (is_array($c))
156 return isset($c[$var]) ? $c[$var] : NULL;
157
158 if (isset($_GET[$var])) $a = $_GET[$var];
159 elseif (isset($_POST[$var])) $a = $_POST[$var];
160 else return NULL;
161
162 // Si on est en ajax et en POST tout a ete encode
163 // via encodeURIComponent, il faut donc repasser
164 // dans le charset local...
165 if (defined('_AJAX')
166 AND _AJAX
167 AND isset($GLOBALS['meta']['charset'])
168 AND $GLOBALS['meta']['charset'] != 'utf-8'
169 AND is_string($a)
170 AND preg_match(',[\x80-\xFF],', $a)) {
171 include_spip('inc/charsets');
172 return importer_charset($a, 'utf-8');
173 }
174
175 return $a;
176 }
177
178 // Methode set de la fonction _request()
179 // Attention au cas ou l'on fait set_request('truc', NULL);
180 // http://doc.spip.org/@set_request
181 function set_request($var, $val = NULL, $c=false) {
182 if (is_array($c)) {
183 unset($c[$var]);
184 if ($val !== NULL)
185 $c[$var] = $val;
186 return $c;
187 }
188
189 unset($_GET[$var]);
190 unset($_POST[$var]);
191 if ($val !== NULL)
192 $_GET[$var] = $val;
193
194 return false; # n'affecte pas $c
195 }
196
197
198 /**
199 * Tester si une url est absolue
200 * @param $url
201 * @return bool
202 */
203 function tester_url_absolue($url){
204 return preg_match(";^([a-z]+:)?//;Uims",trim($url))?true:false;
205 }
206
207 //
208 // Prend une URL et lui ajoute/retire un parametre.
209 // Exemples : [(#SELF|parametre_url{suite,18})] (ajout)
210 // [(#SELF|parametre_url{suite,''})] (supprime)
211 // [(#SELF|parametre_url{suite})] (prend $suite dans la _request)
212 // [(#SELF|parametre_url{suite[],1})] (tableaux valeurs multiples)
213 // http://doc.spip.org/@parametre_url
214 function parametre_url($url, $c, $v=NULL, $sep='&amp;') {
215
216 // lever l'#ancre
217 if (preg_match(',^([^#]*)(#.*)$,', $url, $r)) {
218 $url = $r[1];
219 $ancre = $r[2];
220 } else
221 $ancre = '';
222
223 // eclater
224 $url = preg_split(',[?]|&amp;|&,', $url);
225
226 // recuperer la base
227 $a = array_shift($url);
228 if (!$a) $a= './';
229
230 $regexp = ',^(' . str_replace('[]','\[\]',$c) . '[[]?[]]?)(=.*)?$,';
231 $ajouts = array_flip(explode('|',$c));
232 $u = is_array($v) ? $v : rawurlencode($v);
233 // lire les variables et agir
234 foreach ($url as $n => $val) {
235 if (preg_match($regexp, urldecode($val), $r)) {
236 if ($v === NULL) {
237 return $r[2]?substr($r[2],1):'';
238 }
239 // suppression
240 elseif (!$v) {
241 unset($url[$n]);
242 }
243 // Ajout. Pour une variable, remplacer au meme endroit,
244 // pour un tableau ce sera fait dans la prochaine boucle
245 elseif (substr($r[1],-2) != '[]') {
246 $url[$n] = $r[1].'='.$u;
247 unset($ajouts[$r[1]]);
248 }
249 }
250 }
251
252 // traiter les parametres pas encore trouves
253 if ($v === NULL
254 AND $args = func_get_args()
255 AND count($args)==2)
256 return $v;
257 elseif ($v) {
258 foreach($ajouts as $k => $n) {
259 if (!is_array($v))
260 $url[] = $k .'=' . $u;
261 else {
262 $id = (substr($k,-2) == '[]') ? $k : ($k ."[]");
263 foreach ($v as $w) $url[]= $id .'=' . $w;
264 }
265 }
266 }
267
268 // eliminer les vides
269 $url = array_filter($url);
270
271 // recomposer l'adresse
272 if ($url)
273 $a .= '?' . join($sep, $url);
274
275 return $a . $ancre;
276 }
277
278 // Prend une URL et lui ajoute/retire une ancre apres l'avoir nettoyee
279 // pour l'ancre on translitere, vire les non alphanum du debut,
280 // et on remplace ceux a l'interieur ou au bout par -
281 // http://doc.spip.org/@ancre_url
282 function ancre_url($url, $ancre) {
283 include_spip('inc/charsets');
284 // lever l'#ancre
285 if (preg_match(',^([^#]*)(#.*)$,', $url, $r)) {
286 $url = $r[1];
287 }
288 $ancre = preg_replace(array('/^[^-_a-zA-Z0-9]+/', '/[^-_a-zA-Z0-9]/'), array('', '-'),
289 translitteration($ancre));
290 return $url . (strlen($ancre) ? '#'. $ancre : '');
291 }
292
293 //
294 // pour le nom du cache, les types_urls et self
295 //
296 // http://doc.spip.org/@nettoyer_uri
297 function nettoyer_uri($reset = null)
298 {
299 static $done = false;
300 static $propre = '';
301 if (!is_null($reset)) return $propre=$reset;
302 if ($done) return $propre;
303 $done = true;
304
305 $uri1 = $GLOBALS['REQUEST_URI'];
306 do {
307 $uri = $uri1;
308 $uri1 = preg_replace
309 (',([?&])(PHPSESSID|(var_[^=&]*))=[^&]*(&|$),i',
310 '\1', $uri);
311 } while ($uri<>$uri1);
312
313 return $propre = (preg_replace(',[?&]$,', '', $uri1));
314 }
315
316 //
317 // donner l'URL de base d'un lien vers "soi-meme", modulo
318 // les trucs inutiles
319 //
320 // http://doc.spip.org/@self
321 function self($amp = '&amp;', $root = false) {
322 $url = nettoyer_uri();
323 if (!$root AND (!defined('_SET_HTML_BASE') OR !_SET_HTML_BASE OR !$GLOBALS['profondeur_url']))
324 $url = preg_replace(',^[^?]*/,', '', $url);
325
326 // ajouter le cas echeant les variables _POST['id_...']
327 foreach ($_POST as $v => $c)
328 if (substr($v,0,3) == 'id_')
329 $url = parametre_url($url, $v, $c, '&');
330
331 // supprimer les variables sans interet
332 if (test_espace_prive()) {
333 $url = preg_replace (',([?&])('
334 .'lang|show_docs|'
335 .'changer_lang|var_lang|action)=[^&]*,i', '\1', $url);
336 $url = preg_replace(',([?&])[&]+,', '\1', $url);
337 $url = preg_replace(',[&]$,', '\1', $url);
338 }
339
340 // eviter les hacks
341 $url = htmlspecialchars($url);
342
343 // &amp; ?
344 if ($amp != '&amp;')
345 $url = str_replace('&amp;', $amp, $url);
346
347 // Si ca demarre par ? ou vide, donner './'
348 $url = preg_replace(',^([?].*)?$,', './\1', $url);
349
350 return $url;
351 }
352
353 // Indique si on est dans l'espace prive
354 // http://doc.spip.org/@test_espace_prive
355 function test_espace_prive() {
356 return defined('_ESPACE_PRIVE') ? _ESPACE_PRIVE : false;
357 }
358
359 /**
360 * Verifie la presence d'un plugin active, identifie par son prefix
361 *
362 *
363 * @param string $plugin
364 * @return bool
365 */
366 function test_plugin_actif($plugin){
367 return ($plugin AND defined('_DIR_PLUGIN_'.strtoupper($plugin)))? true:false;
368 }
369
370 //
371 // Traduction des textes de SPIP
372 //
373 // http://doc.spip.org/@_T
374 function _T($texte, $args=array(), $class='') {
375
376 static $traduire=false ;
377
378 if (!$traduire) {
379 $traduire = charger_fonction('traduire', 'inc');
380 include_spip('inc/lang');
381 }
382 $text = $traduire($texte,$GLOBALS['spip_lang']);
383
384 if (!strlen($text))
385 // pour les chaines non traduites, assurer un service minimum
386 $text = str_replace('_', ' ',
387 (($n = strpos($texte,':')) === false ? $texte :
388 substr($texte, $n+1)));
389
390 return _L($text, $args, $class);
391
392 }
393
394 // Remplacer les variables @....@ par leur valeur dans une chaine de langue.
395 // Aussi appelee quand une chaine n'est pas encore dans les fichiers de langue
396 // http://doc.spip.org/@_L
397 function _L($text, $args=array(), $class=NULL) {
398 $f = $text;
399 if (is_array($args)) {
400 foreach ($args as $name => $value) {
401 if ($class)
402 $value = "<span class='$class'>$value</span>";
403 $t = str_replace ("@$name@", $value, $text);
404 if ($text !== $t) {unset($args[$name]); $text = $t;}
405 }
406 // Si des variables n'ont pas ete inserees, le signaler
407 // (chaines de langues pas a jour)
408 // NOTE: c'est du debug, gere comme tel pour SPIP >= 2.3
409 ## if ($args) spip_log("$f: variables inutilisees " . join(', ', array_keys($args)));
410 }
411
412 if ($GLOBALS['test_i18n'] AND $class===NULL)
413 return "<span style='color:red;'>$text</span>";
414 else
415 return $text;
416 }
417
418 // Afficher "ecrire/data/" au lieu de "data/" dans les messages
419 // ou tmp/ au lieu de ../tmp/
420 // http://doc.spip.org/@joli_repertoire
421 function joli_repertoire($rep) {
422 $a = substr($rep,0,1);
423 if ($a<>'.' AND $a<>'/')
424 $rep = (_DIR_RESTREINT?'':_DIR_RESTREINT_ABS).$rep;
425 $rep = preg_replace(',(^\.\.\/),', '', $rep);
426 return $rep;
427 }
428
429
430 //
431 // spip_timer : on l'appelle deux fois et on a la difference, affichable
432 //
433 // http://doc.spip.org/@spip_timer
434 function spip_timer($t='rien', $raw = false) {
435 static $time;
436 $a=time(); $b=microtime();
437 // microtime peut contenir les microsecondes et le temps
438 $b=explode(' ',$b);
439 if (count($b)==2) $a = end($b); // plus precis !
440 $b = reset($b);
441 if (!isset($time[$t])) {
442 $time[$t] = $a + $b;
443 } else {
444 $p = ($a + $b - $time[$t]) * 1000;
445 unset($time[$t]);
446 # echo "'$p'";exit;
447 if ($raw) return $p;
448 if ($p < 1000)
449 $s = '';
450 else {
451 $s = sprintf("%d ", $x = floor($p/1000));
452 $p -= ($x*1000);
453 }
454 return $s . sprintf("%.3f ms", $p);
455 }
456 }
457
458
459 // Renvoie False si un fichier n'est pas plus vieux que $duree secondes,
460 // sinon renvoie True et le date sauf si ca n'est pas souhaite
461 // http://doc.spip.org/@spip_touch
462 function spip_touch($fichier, $duree=0, $touch=true) {
463 if ($duree) {
464 clearstatcache();
465 if (file_exists($fichier) AND ($f=filemtime($fichier)) AND ($f >= time() - $duree))
466 return false;
467 }
468 if ($touch!==false) {
469 if (!@touch($fichier)) { spip_unlink($fichier); @touch($fichier); };
470 @chmod($fichier, _SPIP_CHMOD & ~0111);
471 }
472 return true;
473 }
474
475 // Ce declencheur de tache de fond, de l'espace prive (cf inc_presentation)
476 // et de l'espace public (cf #SPIP_CRON dans inc_balise), est appelee
477 // par un background-image car contrairement a un iframe vide,
478 // les navigateurs ne diront pas qu'ils n'ont pas fini de charger,
479 // c'est plus rassurant.
480 // C'est aussi plus discret qu'un <img> sous un navigateur non graphique.
481
482 // http://doc.spip.org/@action_cron
483 function action_cron() {
484 include_spip('inc/headers');
485 http_status(204); // No Content
486 header("Connection: close");
487 cron (2);
488 }
489
490 // cron() : execution des taches de fond
491 // Le premier argument indique l'intervalle demande entre deux taches
492 // par defaut, 60 secondes (quand il est appele par public.php)
493 // il vaut 2 quand il est appele par ?action=cron, voire 0 en urgence
494 // On peut lui passer en 2e arg le tableau de taches attendu par inc_genie()
495 // Retourne Vrai si un tache a pu etre effectuee
496
497 // http://doc.spip.org/@cron
498 function cron ($gourmand=false, $taches= array()) {
499 if (!defined(_CRON_DELAI_GOURMAND))
500 define('_CRON_DELAI_GOURMAND',60);
501 if (!defined(_CRON_DELAI))
502 define('_CRON_DELAI',is_int($gourmand) ? $gourmand : 2);
503
504 // Si on est gourmand, ou si le fichier gourmand n'existe pas
505 // ou est trop vieux (> 60 sec), on va voir si un cron est necessaire.
506 // Au passage si on est gourmand on le dit aux autres
507 if (!_CRON_DELAI_GOURMAND
508 OR spip_touch(_DIR_TMP.'cron.lock-gourmand', _CRON_DELAI_GOURMAND, $gourmand)
509 OR ($gourmand!==false)) {
510
511 // Le fichier cron.lock indique la date de la derniere tache
512 // Il permet d'imposer qu'il n'y ait qu'une tache a la fois
513 // et 2 secondes minimum entre chaque:
514 // ca soulage le serveur et ca evite
515 // les conflits sur la base entre taches.
516
517 if (!_CRON_DELAI
518 OR spip_touch(_DIR_TMP.'cron.lock',_CRON_DELAI)) {
519 // Si base inaccessible, laisser tomber.
520 if (!spip_connect()) return false;
521
522 $genie = charger_fonction('genie', 'inc', true);
523 if ($genie) {
524 $genie($taches);
525 // redater a la fin du cron
526 // car il peut prendre plus de 2 secondes.
527 spip_touch(_DIR_TMP.'cron.lock', 0);
528 return true;
529 }
530 }# else spip_log("busy");
531 }
532 return false;
533 }
534
535
536 // transformation XML des "&" en "&amp;"
537 // http://doc.spip.org/@quote_amp
538 function quote_amp($u) {
539 return preg_replace(
540 "/&(?![a-z]{0,4}\w{2,3};|#x?[0-9a-f]{2,5};)/i",
541 "&amp;",$u);
542 }
543
544 // Production d'une balise Script valide
545 // http://doc.spip.org/@http_script
546 function http_script($script, $src='', $noscript='') {
547 static $done = array();
548
549 if ($src && !isset($done[$src])){
550 $done[$src] = true;
551 $src = find_in_path($src, _JAVASCRIPT);
552 $src = " src='$src'";
553 }
554 else $src = '';
555 if ($script)
556 $script = ("<!--\n" .
557 preg_replace(',</([^>]*)>,','<\/\1>', $script) .
558 "\n//-->\n");
559 if ($noscript)
560 $noscript = "<noscript>\n\t$noscript\n</noscript>\n";
561
562 return ($src OR $script OR $noscript)
563 ? "<script type='text/javascript'$src>$script</script>$noscript"
564 : '';
565 }
566
567 // Transforme n'importe quel champ en une chaine utilisable
568 // en PHP ou Javascript en toute securite
569 // < ? php $x = '[(#TEXTE|texte_script)]'; ? >
570 // http://doc.spip.org/@texte_script
571 function texte_script($texte) {
572 return str_replace('\'', '\\\'', str_replace('\\', '\\\\', $texte));
573 }
574
575 // la fonction _chemin ajoute un repertoire au chemin courant si un repertoire lui est passe en parametre
576 // retourne le chemin courant sinon, sous forme de array
577 // seul le dossier squelette peut etre modifie en dehors de cette fonction, pour raison historique
578 // http://doc.spip.org/@_chemin
579 function _chemin($dir_path=NULL){
580 static $path_base = NULL;
581 static $path_full = NULL;
582 if ($path_base==NULL){
583 // Chemin standard depuis l'espace public
584 $path = defined('_SPIP_PATH') ? _SPIP_PATH :
585 _DIR_RACINE.':'.
586 _DIR_RACINE.'squelettes-dist/:'.
587 _DIR_RACINE.'prive/:'.
588 _DIR_RESTREINT.':';
589 // Ajouter squelettes/
590 if (@is_dir(_DIR_RACINE.'squelettes'))
591 $path = _DIR_RACINE.'squelettes/:' . $path;
592 foreach (explode(':', $path) as $dir) {
593 if (strlen($dir) AND substr($dir,-1) != '/')
594 $dir .= "/";
595 $path_base[] = $dir;
596 }
597 $path_full = $path_base;
598 // Et le(s) dossier(s) des squelettes nommes
599 if (strlen($GLOBALS['dossier_squelettes']))
600 foreach (array_reverse(explode(':', $GLOBALS['dossier_squelettes'])) as $d)
601 array_unshift($path_full, ($d[0] == '/' ? '' : _DIR_RACINE) . $d . '/');
602 $GLOBALS['path_sig'] = md5(serialize($path_full));
603 }
604 if ($dir_path===NULL) return $path_full;
605
606 if (strlen($dir_path)){
607 $tete = "";
608 if (reset($path_base)==_DIR_RACINE.'squelettes/')
609 $tete = array_shift($path_base);
610 $dirs = array_reverse(explode(':',$dir_path));
611 foreach($dirs as $dir_path){
612 #if ($dir_path{0}!='/')
613 # $dir_path = $dir_path;
614 if (substr($dir_path,-1) != '/')
615 $dir_path .= "/";
616 if (!in_array($dir_path,$path_base))
617 array_unshift($path_base,$dir_path);
618 }
619 if (strlen($tete))
620 array_unshift($path_base,$tete);
621 }
622 $path_full = $path_base;
623 // Et le(s) dossier(s) des squelettes nommes
624 if (strlen($GLOBALS['dossier_squelettes']))
625 foreach (array_reverse(explode(':', $GLOBALS['dossier_squelettes'])) as $d)
626 array_unshift($path_full, ($d[0] == '/' ? '' : _DIR_RACINE) . $d . '/');
627
628 $GLOBALS['path_sig'] = md5(serialize($path_full));
629 return $path_full;
630 }
631
632 // http://doc.spip.org/@creer_chemin
633 function creer_chemin() {
634 $path_a = _chemin();
635 static $c = '';
636
637 // on calcule le chemin si le dossier skel a change
638 if ($c != $GLOBALS['dossier_squelettes']) {
639 // assurer le non plantage lors de la montee de version :
640 $c = $GLOBALS['dossier_squelettes'];
641 $path_a = _chemin(''); // forcer un recalcul du chemin
642 }
643 return $path_a;
644 }
645
646
647
648 // Cherche une image dans les dossiers images
649 // definis par _NOM_IMG_PACK et _DIR_IMG_PACK
650 // http://doc.spip.org/@chemin_image
651 function chemin_image($file){
652 return _DIR_IMG_PACK . $file;
653 #return find_in_path ($file, _NOM_IMG_PACK);
654 }
655
656
657 // Alias de find_in_path
658 // http://doc.spip.org/@chemin
659 function chemin($file, $dirname='', $include=false){
660 return find_in_path ($file, $dirname, $include);
661 }
662
663
664 //
665 // chercher un fichier $file dans le SPIP_PATH
666 // si on donne un sous-repertoire en 2e arg optionnel, il FAUT le / final
667 // si 3e arg vrai, on inclut si ce n'est fait.
668 $GLOBALS['path_sig'] = '';
669 $GLOBALS['path_files'] = null;
670
671 // http://doc.spip.org/@find_in_path
672 function find_in_path ($file, $dirname='', $include=false) {
673 static $dirs=array();
674 static $inc = array(); # cf http://trac.rezo.net/trac/spip/changeset/14743
675 static $c = '';
676
677 // on calcule le chemin si le dossier skel a change
678 if ($c != $GLOBALS['dossier_squelettes']){
679 // assurer le non plantage lors de la montee de version :
680 $c = $GLOBALS['dossier_squelettes'];
681 creer_chemin(); // forcer un recalcul du chemin et la mise a jour de path_sig
682 }
683
684 if (isset($GLOBALS['path_files'][$GLOBALS['path_sig']][$dirname][$file])) {
685 if (!$GLOBALS['path_files'][$GLOBALS['path_sig']][$dirname][$file])
686 return false;
687 if ($include AND !isset($inc[$dirname][$file])) {
688 include_once _ROOT_CWD . $GLOBALS['path_files'][$GLOBALS['path_sig']][$dirname][$file];
689 $inc[$dirname][$file] = $inc[''][$dirname . $file] = true;
690 }
691 return $GLOBALS['path_files'][$GLOBALS['path_sig']][$dirname][$file];
692 }
693
694 $a = strrpos($file,'/');
695 if ($a !== false) {
696 $dirname .= substr($file, 0, ++$a);
697 $file = substr($file, $a);
698 }
699
700 foreach(creer_chemin() as $dir) {
701 if (!isset($dirs[$a = $dir . $dirname]))
702 $dirs[$a] = (is_dir(_ROOT_CWD . $a) || !$a) ;
703 if ($dirs[$a]) {
704 if (file_exists(_ROOT_CWD . ($a .= $file))) {
705 if ($include AND !isset($inc[$dirname][$file])) {
706 include_once _ROOT_CWD . $a;
707 $inc[$dirname][$file] = $inc[''][$dirname . $file] = true;
708 }
709 if (!defined('_SAUVER_CHEMIN'))
710 define('_SAUVER_CHEMIN',true);
711 return $GLOBALS['path_files'][$GLOBALS['path_sig']][$dirname][$file] = $GLOBALS['path_files'][$GLOBALS['path_sig']][''][$dirname . $file] = $a;
712 }
713 }
714 }
715
716 if (!defined('_SAUVER_CHEMIN'))
717 define('_SAUVER_CHEMIN',true);
718 return $GLOBALS['path_files'][$GLOBALS['path_sig']][$dirname][$file] = $GLOBALS['path_files'][$GLOBALS['path_sig']][''][$dirname . $file] = false;
719 }
720
721 function clear_path_cache(){
722 $GLOBALS['path_files'] = array();
723 spip_unlink(_CACHE_CHEMIN);
724 }
725 function load_path_cache(){
726 // charger le path des plugins
727 if (@is_readable(_CACHE_PLUGINS_PATH)){
728 include_once(_CACHE_PLUGINS_PATH);
729 }
730 $GLOBALS['path_files'] = array();
731 // si le visiteur est admin,
732 // on ne recharge pas le cache pour forcer sa mise a jour
733 // le cache de chemin n'est utilise que dans le public
734 if (_DIR_RESTREINT
735 // la session n'est pas encore chargee a ce moment, on ne peut donc pas s'y fier
736 //AND (!isset($GLOBALS['visiteur_session']['statut']) OR $GLOBALS['visiteur_session']['statut']!='0minirezo')
737 // utiliser le cookie est un pis aller qui marche 'en general'
738 // on blinde par un second test au moment de la lecture de la session
739 AND !isset($_COOKIE[$GLOBALS['cookie_prefix'].'_admin'])
740 // et en ignorant ce cache en cas de recalcul explicite
741 AND _request('var_mode')!=='recalcul'
742 ){
743 // on essaye de lire directement sans verrou pour aller plus vite
744 if ($contenu = spip_file_get_contents(_CACHE_CHEMIN)){
745 // mais si semble corrompu on relit avec un verrou
746 if (!$GLOBALS['path_files']=unserialize($contenu)){
747 lire_fichier(_CACHE_CHEMIN,$contenu);
748 if (!$GLOBALS['path_files']=unserialize($contenu))
749 $GLOBALS['path_files'] = array();
750 }
751 }
752 }
753 // pas de sauvegarde du chemin si on est pas dans le public
754 if (!_DIR_RESTREINT)
755 define('_SAUVER_CHEMIN',false);
756 }
757
758 function save_path_cache(){
759 if (defined('_SAUVER_CHEMIN')
760 AND _SAUVER_CHEMIN)
761 ecrire_fichier(_CACHE_CHEMIN,serialize($GLOBALS['path_files']));
762 }
763
764
765 /**
766 * Trouve tous les fichiers du path correspondants a un pattern
767 * pour un nom de fichier donne, ne retourne que le premier qui sera trouve
768 * par un find_in_path
769 *
770 * @param string $dir
771 * @param string $pattern
772 * @param bool $recurs
773 * @return array
774 */
775 // http://doc.spip.org/@find_all_in_path
776 function find_all_in_path($dir,$pattern, $recurs=false){
777 $liste_fichiers=array();
778 $maxfiles = 10000;
779
780 // Parcourir le chemin
781 foreach (creer_chemin() as $d) {
782 $f = $d.$dir;
783 if (@is_dir($f)){
784 $liste = preg_files($f,$pattern,$maxfiles-count($liste_fichiers),$recurs);
785 foreach($liste as $chemin){
786 $nom = basename($chemin);
787 // ne prendre que les fichiers pas deja trouves
788 // car find_in_path prend le premier qu'il trouve,
789 // les autres sont donc masques
790 if (!isset($liste_fichiers[$nom]))
791 $liste_fichiers[$nom] = $chemin;
792 }
793 }
794 }
795 return $liste_fichiers;
796 }
797
798 // predicat sur les scripts de ecrire qui n'authentifient pas par cookie
799
800 // http://doc.spip.org/@autoriser_sans_cookie
801 function autoriser_sans_cookie($nom)
802 {
803 static $autsanscookie = array('aide_index', 'install', 'admin_repair');
804 $nom = preg_replace('/.php[3]?$/', '', basename($nom));
805 return in_array($nom, $autsanscookie);
806 }
807
808 // Fonction codant et decodant les URLS des objets SQL mis en page par SPIP
809 // $id = numero de la cle primaire si nombre, URL a decoder si pas numerique
810 // $entite = surnom de la table SQL (donne acces au nom de cle primaire)
811 // $args = query_string a placer apres cle=$id&....
812 // $ancre = ancre a mettre a la fin de l'URL a produire
813 // $public = produire l'URL publique ou privee (par defaut: selon espace)
814 // $type = fichier dans le repertoire ecrire/urls determinant l'apparence
815 // @return string : url codee
816 // @return string : fonction de decodage
817 // http://doc.spip.org/@generer_url_entite
818 function generer_url_entite($id='', $entite='', $args='', $ancre='', $public=NULL, $type=NULL)
819 {
820 if ($public === NULL) $public = !test_espace_prive();
821
822 if (!$public) {
823 if (!$entite) return '';
824 include_spip('inc/urls');
825 $f = 'generer_url_ecrire_' . $entite;
826 $res = !function_exists($f) ? '' : $f($id, $args, $ancre, ' ');
827 } else {
828 if (is_string($public)) {
829 include_spip('base/connect_sql');
830 $id_type = id_table_objet($entite,$public);
831 return _DIR_RACINE . get_spip_script('./')
832 . "?"._SPIP_PAGE."=$entite&$id_type=$id&connect=$public"
833 . (!$args ? '' : "&$args")
834 . (!$ancre ? '' : "#$ancre");
835 } else {
836 if ($type === NULL) {
837 $type = ($GLOBALS['type_urls'] === 'page'
838 AND $GLOBALS['meta']['type_urls'])
839 ? $GLOBALS['meta']['type_urls']
840 : $GLOBALS['type_urls']; // pour SPIP <2
841 }
842
843 $f = charger_fonction($type, 'urls', true);
844 // si $entite='', on veut la fonction de passage URL ==> id
845 if (!$entite) return $f;
846 // sinon on veut effectuer le passage id ==> URL
847 $res = !$f ? '' : $f(intval($id), $entite, $args, $ancre);
848 }
849 }
850 if ($res) return $res;
851 // Sinon c'est un raccourci ou compat SPIP < 2
852 include_spip('inc/lien');
853 if (!function_exists($f = 'generer_url_' . $entite)) {
854 if (!function_exists($f .= '_dist')) $f = '';
855 }
856 if ($f) {
857 $url = $f($id, $args, $ancre);
858 if (strlen($args))
859 $url .= strstr($url, '?')
860 ? '&amp;'.$args
861 : '?'.$args;
862 return $url;
863 }
864 // On a ete gentil mais la ....
865 spip_log("generer_url_entite: entite $entite ($f) inconnue $type $public");
866 return '';
867 }
868
869 // Transformer les caracteres utf8 d'une URL (farsi par ex) selon la RFC 1738
870 function urlencode_1738($url) {
871 $uri = '';
872 for ($i=0; $i < strlen($url); $i++) {
873 if (ord($a = $url[$i]) > 127)
874 $a = rawurlencode($a);
875 $uri .= $a;
876 }
877 return quote_amp($uri);
878 }
879
880 // http://doc.spip.org/@generer_url_entite_absolue
881 function generer_url_entite_absolue($id='', $entite='', $args='', $ancre='', $connect=NULL)
882 {
883 if (!$connect) $connect = true;
884 $h = generer_url_entite($id, $entite, $args, $ancre, $connect);
885 if (!preg_match(',^\w+:,', $h)) {
886 include_spip('inc/filtres_mini');
887 $h = url_absolue($h);
888 }
889 return $h;
890 }
891
892 // Sur certains serveurs, la valeur 'Off' tient lieu de false dans certaines
893 // variables d'environnement comme $_SERVER[HTTPS] ou ini_get(register_globals)
894 // http://doc.spip.org/@test_valeur_serveur
895 function test_valeur_serveur($truc) {
896 if (!$truc) return false;
897 return (strtolower($truc) !== 'off');
898 }
899
900 //
901 // Fonctions de fabrication des URL des scripts de Spip
902 //
903
904 // l'URL de base du site, sans se fier a meta(adresse_site) qui
905 // peut etre fausse (sites a plusieurs noms d'hotes, deplacements, erreurs)
906 // Note : la globale $profondeur_url doit etre initialisee de maniere a
907 // indiquer le nombre de sous-repertoires de l'url courante par rapport a la
908 // racine de SPIP : par exemple, sur ecrire/ elle vaut 1, sur sedna/ 1, et a
909 // la racine 0. Sur url/perso/ elle vaut 2
910 // http://doc.spip.org/@url_de_base
911 function url_de_base($profondeur=null) {
912
913 static $url = array();
914 if (is_array($profondeur)) return $url = $profondeur;
915 if ($profondeur===false) return $url;
916
917 if (is_null($profondeur)) $profondeur = $GLOBALS['profondeur_url'];
918
919 if (isset($url[$profondeur]))
920 return $url[$profondeur];
921
922 $http = (
923 (isset($_SERVER["SCRIPT_URI"]) AND
924 substr($_SERVER["SCRIPT_URI"],0,5) == 'https')
925 OR (isset($_SERVER['HTTPS']) AND
926 test_valeur_serveur($_SERVER['HTTPS']))
927 ) ? 'https' : 'http';
928 # note : HTTP_HOST contient le :port si necessaire
929 if (!$GLOBALS['REQUEST_URI']){
930 if (isset($_SERVER['REQUEST_URI'])) {
931 $GLOBALS['REQUEST_URI'] = $_SERVER['REQUEST_URI'];
932 } else {
933 $GLOBALS['REQUEST_URI'] = $_SERVER['PHP_SELF'];
934 if ($_SERVER['QUERY_STRING']
935 AND !strpos($_SERVER['REQUEST_URI'], '?'))
936 $GLOBALS['REQUEST_URI'] .= '?'.$_SERVER['QUERY_STRING'];
937 }
938 }
939
940 $url[$profondeur] = url_de_($http,$_SERVER['HTTP_HOST'],$GLOBALS['REQUEST_URI'],$profondeur);
941
942 return $url[$profondeur];
943 }
944 /**
945 * fonction testable de construction d'une url appelee par url_de_base()
946 * @param string $http
947 * @param string $host
948 * @param string $request
949 * @param int $prof
950 * @return string
951 */
952 function url_de_($http,$host,$request,$prof=0){
953 $prof = max($prof,0);
954
955 $myself = ltrim($request,'/');
956 # supprimer la chaine de GET
957 list($myself) = explode('?', $myself);
958 $url = join('/', array_slice(explode('/', $myself), 0, -1-$prof)).'/';
959
960 $url = $http.'://'.rtrim($host,'/').'/'.ltrim($url,'/');
961 return $url;
962 }
963
964
965 function tester_url_ecrire($nom){
966 // tester si c'est une page en squelette
967 if (find_in_path('prive/exec/' . $nom . '.' . _EXTENSION_SQUELETTES))
968 return 'fond';
969 // attention, il ne faut pas inclure l'exec ici car sinon on modifie l'environnement
970 // par un simple #URL_ECRIRE dans un squelette (cas d'un define en debut d'exec/nom )
971 return (find_in_path("{$nom}.php",'exec/') OR charger_fonction($nom,'exec',true))?$nom:'';
972 }
973
974 // Pour une redirection, la liste des arguments doit etre separee par "&"
975 // Pour du code XHTML, ca doit etre &amp;
976 // Bravo au W3C qui n'a pas ete capable de nous eviter ca
977 // faute de separer proprement langage et meta-langage
978
979 // Attention, X?y=z et "X/?y=z" sont completement differents!
980 // http://httpd.apache.org/docs/2.0/mod/mod_dir.html
981
982 // http://doc.spip.org/@generer_url_ecrire
983 function generer_url_ecrire($script='', $args="", $no_entities=false, $rel=false) {
984 if (!$rel)
985 $rel = url_de_base() . _DIR_RESTREINT_ABS . _SPIP_ECRIRE_SCRIPT;
986 else if (!is_string($rel))
987 $rel = _DIR_RESTREINT ? _DIR_RESTREINT :
988 ('./' . _SPIP_ECRIRE_SCRIPT);
989
990 @list($script, $ancre) = explode('#', $script);
991 if ($script AND ($script<>'accueil' OR $rel))
992 $args = "?exec=$script" . (!$args ? '' : "&$args");
993 elseif ($args)
994 $args ="?$args";
995 if ($ancre) $args .= "#$ancre";
996 return $rel . ($no_entities ? $args : str_replace('&', '&amp;', $args));
997 }
998
999 // http://doc.spip.org/@generer_url_retour
1000 function generer_url_retour($script, $args="")
1001 {
1002 return rawurlencode(generer_url_ecrire($script, $args, true, true));
1003 }
1004
1005 //
1006 // Adresse des scripts publics (a passer dans inc-urls...)
1007 //
1008
1009 // Detecter le fichier de base, a la racine, comme etant spip.php ou ''
1010 // dans le cas de '', un $default = './' peut servir (comme dans urls/page.php)
1011 // http://doc.spip.org/@get_spip_script
1012 function get_spip_script($default='') {
1013 # cas define('_SPIP_SCRIPT', '');
1014 if (_SPIP_SCRIPT)
1015 return _SPIP_SCRIPT;
1016 else
1017 return $default;
1018 }
1019
1020 // http://doc.spip.org/@generer_url_public
1021 function generer_url_public($script='', $args="", $no_entities=false, $rel=false, $action='') {
1022 // si le script est une action (spip_pass, spip_inscription),
1023 // standardiser vers la nouvelle API
1024
1025 if (!$action) $action = get_spip_script();
1026 if ($script)
1027 $action = parametre_url($action, _SPIP_PAGE, $script, '&');
1028
1029 if ($args) {
1030 if (is_array($args)) {
1031 $r = '';
1032 foreach($args as $k => $v) $r .= '&' . $k . '=' . $v;
1033 $args = substr($r,1);
1034 }
1035 $action .=
1036 (strpos($action, '?') !== false ? '&' : '?') . $args;
1037 }
1038 if (!$no_entities)
1039 $action = quote_amp($action);
1040
1041 // ne pas generer une url avec /./?page= en cas d'url absolue et de _SPIP_SCRIPT vide
1042 return ($rel ? _DIR_RACINE . $action : rtrim(url_de_base(),'/') . preg_replace(",^/[.]/,","/","/$action"));
1043 }
1044
1045 // http://doc.spip.org/@generer_url_prive
1046 function generer_url_prive($script, $args="", $no_entities=false) {
1047
1048 return generer_url_public($script, $args, $no_entities, false, _DIR_RESTREINT_ABS . 'prive.php');
1049 }
1050
1051 // Pour les formulaires en methode POST,
1052 // mettre le nom du script a la fois en input-hidden et dans le champ action:
1053 // 1) on peut ainsi memoriser le signet comme si c'etait un GET
1054 // 2) ca suit http://en.wikipedia.org/wiki/Representational_State_Transfer
1055
1056 // http://doc.spip.org/@generer_form_ecrire
1057 function generer_form_ecrire($script, $corps, $atts='', $submit='') {
1058 global $spip_lang_right;
1059
1060 $script1 = explode('&', $script);
1061 $script1 = array_shift($script1);
1062
1063 return "<form action='"
1064 . ($script ? generer_url_ecrire($script) : '')
1065 . "' "
1066 . ($atts ? $atts : " method='post'")
1067 . "><div>\n"
1068 . "<input type='hidden' name='exec' value='$script1' />"
1069 . $corps
1070 . (!$submit ? '' :
1071 ("<div style='text-align: $spip_lang_right'><input type='submit' value=\"".attribut_html($submit)."\" /></div>"))
1072 . "</div></form>\n";
1073 }
1074
1075 // Attention, JS/Ajax n'aime pas le melange de param GET/POST
1076 // On n'applique pas la recommandation ci-dessus pour les scripts publics
1077 // qui ne sont pas destines a etre mis en signets
1078
1079 // http://doc.spip.org/@generer_form_action
1080 function generer_form_action($script, $corps, $atts='', $public=false) {
1081 // si l'on est dans l'espace prive, on garde dans l'url
1082 // l'exec a l'origine de l'action, qui permet de savoir si il est necessaire
1083 // ou non de proceder a l'authentification (cas typique de l'install par exemple)
1084 $h = (_DIR_RACINE AND !$public)
1085 ? generer_url_ecrire(_request('exec'))
1086 : generer_url_public();
1087
1088 return "\n<form action='" .
1089 $h .
1090 "'" .
1091 $atts .
1092 ">\n" .
1093 "<div>" .
1094 "\n<input type='hidden' name='action' value='$script' />" .
1095 $corps .
1096 "</div></form>";
1097 }
1098
1099 // http://doc.spip.org/@generer_url_action
1100 function generer_url_action($script, $args="", $no_entities=false , $public = false) {
1101 // si l'on est dans l'espace prive, on garde dans l'url
1102 // l'exec a l'origine de l'action, qui permet de savoir si il est necessaire
1103 // ou non de proceder a l'authentification (cas typique de l'install par exemple)
1104 $url = (_DIR_RACINE AND !$public)
1105 ? generer_url_ecrire(_request('exec'))
1106 : generer_url_public();
1107 $url = parametre_url($url,'action',$script);
1108 if ($args) $url .= quote_amp('&'.$args);
1109
1110 if ($no_entities) $url = str_replace('&amp;','&',$url);
1111 return $url;
1112 }
1113
1114
1115 /**
1116 * Fonction d'initialisation groupee pour compatibilite ascendante
1117 *
1118 * @param string $pi
1119 * @param string $pa
1120 * @param string $ti
1121 * @param string $ta
1122 */
1123 function spip_initialisation($pi=NULL, $pa=NULL, $ti=NULL, $ta=NULL) {
1124 spip_initialisation_core($pi,$pa,$ti,$ta);
1125 spip_initialisation_suite();
1126 }
1127
1128 /**
1129 * Fonction d'initialisation, appellee dans inc_version ou mes_options
1130 * Elle definit les repertoires et fichiers non partageables
1131 * et indique dans $test_dirs ceux devant etre accessibles en ecriture
1132 * mais ne touche pas a cette variable si elle est deja definie
1133 * afin que mes_options.php puisse en specifier d'autres.
1134 * Elle definit ensuite les noms des fichiers et les droits.
1135 * Puis simule un register_global=on securise.
1136 *
1137 * @param string $pi
1138 * @param string $pa
1139 * @param string $ti
1140 * @param string $ta
1141 */
1142 function spip_initialisation_core($pi=NULL, $pa=NULL, $ti=NULL, $ta=NULL) {
1143 static $too_late = 0;
1144 if ($too_late++) return;
1145
1146 // Declaration des repertoires
1147
1148 // le nom du repertoire plugins/ activables/desactivables
1149 define('_DIR_PLUGINS', _DIR_RACINE . "plugins/");
1150
1151 // le nom du repertoire des extensions/ permanentes du core, toujours actives
1152 define('_DIR_EXTENSIONS', _DIR_RACINE . "extensions/");
1153
1154 define('_DIR_IMG', $pa);
1155 define('_DIR_LOGOS', $pa);
1156 define('_DIR_IMG_ICONES', _DIR_LOGOS . "icones/");
1157
1158 define('_DIR_DUMP', $ti . "dump/");
1159 define('_DIR_SESSIONS', $ti . "sessions/");
1160 define('_DIR_TRANSFERT', $ti . "upload/");
1161 define('_DIR_CACHE', $ti . "cache/");
1162 define('_DIR_CACHE_XML', _DIR_CACHE . "xml/");
1163 define('_DIR_SKELS', _DIR_CACHE . "skel/");
1164 define('_DIR_AIDE', _DIR_CACHE . "aide/");
1165 define('_DIR_TMP', $ti);
1166
1167 define('_DIR_VAR', $ta);
1168
1169 define('_DIR_ETC', $pi);
1170 define('_DIR_CONNECT', $pi);
1171 define('_DIR_CHMOD', $pi);
1172
1173 if (!isset($GLOBALS['test_dirs']))
1174 // Pas $pi car il est bon de le mettre hors ecriture apres intstall
1175 // il sera rajoute automatiquement si besoin a l'etape 2 de l'install
1176 $GLOBALS['test_dirs'] = array($pa, $ti, $ta);
1177
1178 // Declaration des fichiers
1179
1180 define('_CACHE_PLUGINS_PATH', _DIR_CACHE . "charger_plugins_chemins.php");
1181 define('_CACHE_PLUGINS_OPT', _DIR_CACHE . "charger_plugins_options.php");
1182 define('_CACHE_PLUGINS_FCT', _DIR_CACHE . "charger_plugins_fonctions.php");
1183 define('_CACHE_PLUGINS_VERIF', _DIR_CACHE . "verifier_plugins.txt");
1184 define('_CACHE_PIPELINES', _DIR_CACHE."charger_pipelines.php");
1185 define('_CACHE_CHEMIN', _DIR_CACHE."chemin.txt");
1186
1187 # attention .php obligatoire pour ecrire_fichier_securise
1188 define('_FILE_META', $ti . 'meta_cache.php');
1189 define('_DIR_LOG', _DIR_TMP);
1190 define('_FILE_LOG', 'spip');
1191 define('_FILE_LOG_SUFFIX', '.log');
1192
1193 // Le fichier de connexion a la base de donnees
1194 // tient compte des anciennes versions (inc_connect...)
1195 define('_FILE_CONNECT_INS', 'connect');
1196 define('_FILE_CONNECT',
1197 (@is_readable($f = _DIR_CONNECT . _FILE_CONNECT_INS . '.php') ? $f
1198 : (@is_readable($f = _DIR_RESTREINT . 'inc_connect.php') ? $f
1199 : (@is_readable($f = _DIR_RESTREINT . 'inc_connect.php3') ? $f
1200 : false))));
1201
1202 // Le fichier de reglages des droits
1203 define('_FILE_CHMOD_INS', 'chmod');
1204 define('_FILE_CHMOD',
1205 (@is_readable($f = _DIR_CHMOD . _FILE_CHMOD_INS . '.php') ? $f
1206 : false));
1207
1208 define('_FILE_LDAP', 'ldap.php');
1209
1210 define('_FILE_TMP_SUFFIX', '.tmp.php');
1211 define('_FILE_CONNECT_TMP', _DIR_CONNECT . _FILE_CONNECT_INS . _FILE_TMP_SUFFIX);
1212 define('_FILE_CHMOD_TMP', _DIR_CHMOD . _FILE_CHMOD_INS . _FILE_TMP_SUFFIX);
1213
1214 // Definition des droits d'acces en ecriture
1215 if (!defined('_SPIP_CHMOD') AND _FILE_CHMOD)
1216 include_once _FILE_CHMOD;
1217
1218 // Se mefier des fichiers mal remplis!
1219 if (!defined('_SPIP_CHMOD')) define('_SPIP_CHMOD', 0777);
1220
1221 // Le charset par defaut lors de l'installation
1222 define('_DEFAULT_CHARSET', 'utf-8');
1223
1224 define('_ROOT_PLUGINS', _ROOT_RACINE . "plugins/");
1225 define('_ROOT_EXTENSIONS', _ROOT_RACINE . "extensions/");
1226
1227 // La taille des Log
1228 define('_MAX_LOG', 100);
1229
1230 // Sommes-nous dans l'empire du Mal ?
1231 // (ou sous le signe du Pingouin, ascendant GNU ?)
1232 if (strpos($_SERVER['SERVER_SOFTWARE'], '(Win') !== false){
1233 define ('_OS_SERVEUR', 'windows');
1234 define('_SPIP_LOCK_MODE',1); // utiliser le flock php
1235 }
1236 else {
1237 define ('_OS_SERVEUR', '');
1238 define('_SPIP_LOCK_MODE',1); // utiliser le flock php
1239 #define('_SPIP_LOCK_MODE',2); // utiliser le nfslock de spip mais link() est tres souvent interdite
1240 }
1241
1242 //
1243 // Module de lecture/ecriture/suppression de fichiers utilisant flock()
1244 // (non surchargeable en l'etat ; attention si on utilise include_spip()
1245 // pour le rendre surchargeable, on va provoquer un reecriture
1246 // systematique du noyau ou une baisse de perfs => a etudier)
1247 include_once _ROOT_RESTREINT . 'inc/flock.php';
1248
1249 // charger tout de suite le path et son cache
1250 load_path_cache();
1251
1252 // *********** traiter les variables ************
1253
1254 //
1255 // Securite
1256 //
1257
1258 // Ne pas se faire manger par un bug php qui accepte ?GLOBALS[truc]=toto
1259 if (isset($_REQUEST['GLOBALS'])) die();
1260 // nettoyer les magic quotes \' et les caracteres nuls %00
1261 spip_desinfecte($_GET);
1262 spip_desinfecte($_POST);
1263 spip_desinfecte($_COOKIE);
1264 spip_desinfecte($_REQUEST);
1265
1266 // Par ailleurs on ne veut pas de magic_quotes au cours de l'execution
1267 @set_magic_quotes_runtime(0);
1268
1269 // Si les variables sont passees en global par le serveur,
1270 // ou si on veut la compatibilite php3
1271 // il faut faire quelques verifications de base
1272 if ($x = test_valeur_serveur(@ini_get('register_globals'))
1273 OR _FEED_GLOBALS) {
1274 // ne pas desinfecter les globales en profondeur car elle contient aussi les
1275 // precedentes, qui seraient desinfectees 2 fois.
1276 spip_desinfecte($GLOBALS,false);
1277 include_spip('inc/php3');
1278 spip_register_globals($x);
1279 }
1280
1281 // appliquer le cookie_prefix
1282 if ($GLOBALS['cookie_prefix'] != 'spip') {
1283 include_spip('inc/cookie');
1284 recuperer_cookies_spip($GLOBALS['cookie_prefix']);
1285 }
1286
1287 //
1288 // Capacites php (en fonction de la version)
1289 //
1290 $GLOBALS['flag_ob'] = (function_exists("ob_start")
1291 && function_exists("ini_get")
1292 && !strstr(@ini_get('disable_functions'), 'ob_'));
1293 $GLOBALS['flag_sapi_name'] = function_exists("php_sapi_name");
1294 $GLOBALS['flag_get_cfg_var'] = (@get_cfg_var('error_reporting') != "");
1295 $GLOBALS['flag_upload'] = (!$GLOBALS['flag_get_cfg_var'] ||
1296 (get_cfg_var('upload_max_filesize') > 0));
1297
1298
1299 // Compatibilite avec serveurs ne fournissant pas $REQUEST_URI
1300 if (isset($_SERVER['REQUEST_URI'])) {
1301 $GLOBALS['REQUEST_URI'] = $_SERVER['REQUEST_URI'];
1302 } else {
1303 $GLOBALS['REQUEST_URI'] = $_SERVER['PHP_SELF'];
1304 if ($_SERVER['QUERY_STRING']
1305 AND !strpos($_SERVER['REQUEST_URI'], '?'))
1306 $GLOBALS['REQUEST_URI'] .= '?'.$_SERVER['QUERY_STRING'];
1307 }
1308
1309 // Duree de validite de l'alea pour les cookies et ce qui s'ensuit.
1310 define('_RENOUVELLE_ALEA', 12 * 3600);
1311
1312 // charger les meta si possible et renouveller l'alea au besoin
1313 // charge aussi effacer_meta et ecrire_meta
1314 $inc_meta = charger_fonction('meta', 'inc');
1315 $inc_meta();
1316
1317 // nombre de repertoires depuis la racine
1318 // on compare a l'adresse de spip.php : $_SERVER["SCRIPT_NAME"]
1319 // ou a defaut celle donnee en meta ; (mais si celle-ci est fausse
1320 // le calcul est faux)
1321 if (!_DIR_RESTREINT)
1322 $GLOBALS['profondeur_url'] = 1;
1323 else {
1324 $uri = isset($_SERVER['REQUEST_URI']) ? explode('?', $_SERVER['REQUEST_URI']) : '';
1325 $uri_ref = $_SERVER["SCRIPT_NAME"];
1326 if (!$uri_ref
1327 // si on est appele avec un autre ti, on est sans doute en mutu
1328 // si jamais c'est de la mutu avec sous rep, on est perdu si on se fie
1329 // a spip.php qui est a la racine du spip, et vue qu'on sait pas se reperer
1330 // s'en remettre a l'adresse du site. alea jacta est.
1331 OR $ti!==_NOM_TEMPORAIRES_INACCESSIBLES){
1332
1333 if (isset($GLOBALS['meta']['adresse_site'])) {
1334 $uri_ref = parse_url($GLOBALS['meta']['adresse_site']);
1335 $uri_ref = $uri_ref['path'].'/';
1336 }
1337 else
1338 $uri_ref = "";
1339 }
1340 if (!$uri OR !$uri_ref)
1341 $GLOBALS['profondeur_url'] = 0;
1342 else {
1343 $GLOBALS['profondeur_url'] = max(0,
1344 substr_count($uri[0], '/')
1345 - substr_count($uri_ref,'/'));
1346 }
1347 }
1348 // s'il y a un cookie ou PHP_AUTH, initialiser visiteur_session
1349 if (_FILE_CONNECT) {
1350 if (verifier_visiteur()=='0minirezo'
1351 // si c'est un admin sans cookie admin, il faut ignorer le cache chemin !
1352 AND !isset($COOKIE['spip_admin']))
1353 clear_path_cache();
1354 }
1355
1356 }
1357
1358 /**
1359 * Complements d'initialisation non critiques pouvant etre realises
1360 * par les plugins
1361 *
1362 */
1363 function spip_initialisation_suite() {
1364 static $too_late = 0;
1365 if ($too_late++) return;
1366
1367 // taille mini des login
1368 if (!defined('_LOGIN_TROP_COURT')) define('_LOGIN_TROP_COURT', 4);
1369
1370 // la taille maxi des logos (0 : pas de limite)
1371 if (!defined('_LOGO_MAX_SIZE')) define('_LOGO_MAX_SIZE', 0); # poids en ko
1372 if (!defined('_LOGO_MAX_WIDTH')) define('_LOGO_MAX_WIDTH', 0); # largeur en pixels
1373 if (!defined('_LOGO_MAX_HEIGHT')) define('_LOGO_MAX_HEIGHT', 0); # hauteur en pixels
1374
1375 if (!defined('_DOC_MAX_SIZE')) define('_DOC_MAX_SIZE', 0); # poids en ko
1376
1377 if (!defined('_IMG_MAX_SIZE')) define('_IMG_MAX_SIZE', 0); # poids en ko
1378 if (!defined('_IMG_MAX_WIDTH')) define('_IMG_MAX_WIDTH', 0); # largeur en pixels
1379 if (!defined('_IMG_MAX_HEIGHT')) define('_IMG_MAX_HEIGHT', 0); # hauteur en pixels
1380
1381 if (!defined('_COPIE_LOCALE_MAX_SIZE')) define('_COPIE_LOCALE_MAX_SIZE',16777216); // poids en octet
1382
1383 // qq chaines standard
1384 if (!defined('_ACCESS_FILE_NAME')) define('_ACCESS_FILE_NAME', '.htaccess');
1385 if (!defined('_AUTH_USER_FILE')) define('_AUTH_USER_FILE', '.htpasswd');
1386 if (!defined('_SPIP_DUMP')) define('_SPIP_DUMP', 'dump@nom_site@@stamp@.xml');
1387 if (!defined('_CACHE_RUBRIQUES')) define('_CACHE_RUBRIQUES', _DIR_TMP.'menu-rubriques-cache.txt');
1388 if (!defined('_CACHE_RUBRIQUES_MAX')) define('_CACHE_RUBRIQUES_MAX', 500);
1389
1390 if (!defined('_EXTENSION_SQUELETTES')) define('_EXTENSION_SQUELETTES', 'html');
1391
1392 if (!defined('_DOCTYPE_ECRIRE')) define('_DOCTYPE_ECRIRE',
1393 // "<!DOCTYPE HTML PUBLIC '-//W3C//DTD HTML 4.01 Transitional//EN' 'http://www.w3.org/TR/html4/loose.dtd'>\n");
1394 //"<!DOCTYPE html PUBLIC '-//W3C//DTD XHTML 1.0 Transitional//EN' 'http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd'>\n");
1395 "<!DOCTYPE html PUBLIC '-//W3C//DTD XHTML 1.0 Strict//EN' 'http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd'>\n");
1396 // "<!DOCTYPE html PUBLIC '-//W3C//DTD XHTML 1.1 //EN' 'http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd'>\n");
1397 if (!defined('_DOCTYPE_AIDE')) define('_DOCTYPE_AIDE',
1398 "<!DOCTYPE html PUBLIC '-//W3C//DTD HTML 4.01 Frameset//EN' 'http://www.w3.org/TR/1999/REC-html401-19991224/frameset.dtd'>");
1399
1400 // L'adresse de base du site ; on peut mettre '' si la racine est geree par
1401 // le script de l'espace public, alias index.php
1402 if (!defined('_SPIP_SCRIPT')) define('_SPIP_SCRIPT', 'spip.php');
1403 // argument page, personalisable en cas de conflit avec un autre script
1404 if (!defined('_SPIP_PAGE')) define('_SPIP_PAGE', 'page');
1405
1406 // le script de l'espace prive
1407 // Mettre a "index.php" si DirectoryIndex ne le fait pas ou pb connexes:
1408 // les anciens IIS n'acceptent pas les POST sur ecrire/ (#419)
1409 // meme pb sur thttpd cf. http://forum.spip.org/fr_184153.html
1410
1411 if (!defined('_SPIP_ECRIRE_SCRIPT')) define('_SPIP_ECRIRE_SCRIPT', // true ? #decommenter ici et commenter la
1412 preg_match(',IIS|thttpd,',$_SERVER['SERVER_SOFTWARE']) ?
1413 'index.php' : '');
1414
1415
1416 // Gestion AJAX sauf pour le mode oo (et en espace prive)
1417
1418 if (isset($GLOBALS['visiteur_session']['prefs'])AND !_DIR_RESTREINT) {
1419 $x = $GLOBALS['visiteur_session']['prefs'];
1420 if (!is_array($x)) $x = unserialize($x); // prive.php l'a fait
1421 if ($x['display'] == 4) {
1422 define('_SPIP_AJAX', -1);
1423 if (isset($_COOKIE['spip_accepte_ajax']))
1424 spip_setcookie('spip_accepte_ajax', -1, 0);
1425 }
1426 }
1427
1428 if (!defined('_SPIP_AJAX'))
1429 define('_SPIP_AJAX', ((!isset($_COOKIE['spip_accepte_ajax']))
1430 ? 1
1431 : (($_COOKIE['spip_accepte_ajax'] != -1) ? 1 : 0)));
1432
1433 // La requete est-elle en ajax ?
1434 define('_AJAX',
1435 (isset($_SERVER['HTTP_X_REQUESTED_WITH']) # ajax jQuery
1436 OR @$_REQUEST['var_ajax_redir'] # redirection 302 apres ajax jQuery
1437 OR @$_REQUEST['var_ajaxcharset'] # compat ascendante pour plugins
1438 )
1439 AND !@$_REQUEST['var_noajax'] # horrible exception, car c'est pas parce que la requete est ajax jquery qu'il faut tuer tous les formulaires ajax qu'elle contient
1440 );
1441
1442 # nombre de pixels maxi pour calcul de la vignette avec gd
1443 # au dela de 5500000 on considere que php n'est pas limite en memoire pour cette operation
1444 # les configurations limitees en memoire ont un seuil plutot vers 1MPixel
1445 if (!defined('_IMG_GD_MAX_PIXELS')) define('_IMG_GD_MAX_PIXELS', (isset($GLOBALS['meta']['max_taille_vignettes'])&&$GLOBALS['meta']['max_taille_vignettes']<5500000)?$GLOBALS['meta']['max_taille_vignettes']:0);
1446 if (!defined('_IMG_GD_QUALITE')) define('_IMG_GD_QUALITE', 85);
1447
1448 if (!defined('_MEMORY_LIMIT_MIN')) define('_MEMORY_LIMIT_MIN', 16);
1449 // si on est dans l'espace prive et si le besoin est superieur a 8Mo (qui est vraiment le standard)
1450 // on verifie que la memoire est suffisante pour le compactage css+js pour eviter la page blanche
1451 // il y aura d'autres problemes et l'utilisateur n'ira pas tres loin, mais ce sera plus comprehensible qu'une page blanche
1452 if (test_espace_prive() AND _MEMORY_LIMIT_MIN>8){
1453 if ($memory = trim(ini_get('memory_limit'))){
1454 $unit = strtolower(substr($memory,strlen($memory/1),1));
1455 switch($unit) {
1456 // Le modifieur 'G' est disponible depuis PHP 5.1.0
1457 case 'g': $memory *= 1024;
1458 case 'm': $memory *= 1024;
1459 case 'k': $memory *= 1024;
1460 }
1461 if ($memory<_MEMORY_LIMIT_MIN*1024*1024){
1462 ini_set('memory_limit',$m=_MEMORY_LIMIT_MIN.'M');
1463 if (trim(ini_get('memory_limit'))!=$m){
1464 define('_INTERDIRE_COMPACTE_HEAD_ECRIRE',true); // evite une page blanche car on ne saura pas calculer la css dans ce hit
1465 }
1466 }
1467 }
1468 else
1469 define('_INTERDIRE_COMPACTE_HEAD_ECRIRE',true); // evite une page blanche car on ne saura pas calculer la css dans ce hit
1470 }
1471 // Protocoles a normaliser dans les chaines de langues
1472 if (!defined('_PROTOCOLES_STD'))
1473 define('_PROTOCOLES_STD', 'http|https|ftp|mailto|webcal');
1474
1475 init_var_mode();
1476 }
1477
1478 // Reperer les variables d'URL qui conditionnent la perennite du cache, des urls
1479 // ou d'autres petit caches (trouver_table, css et js compactes ...)
1480 // http://doc.spip.org/@init_var_mode
1481 function init_var_mode(){
1482 static $done = false;
1483 if (!$done) {
1484 // On fixe $GLOBALS['var_mode']
1485 $GLOBALS['var_mode'] = false;
1486 $GLOBALS['var_preview'] = false;
1487 $GLOBALS['var_images'] = false;
1488 $GLOBALS['var_inclure'] = false;
1489 $GLOBALS['var_urls'] = false;
1490 if (isset($_GET['var_mode'])) {
1491 // tout le monde peut calcul/recalcul
1492 if ($_GET['var_mode'] == 'calcul'
1493 OR $_GET['var_mode'] == 'recalcul')
1494 $GLOBALS['var_mode'] = $_GET['var_mode'];
1495
1496 // preview, debug, blocs, urls et images necessitent une autorisation
1497 else if (in_array($_GET['var_mode'],array('preview','debug','inclure','urls','images'))) {
1498 include_spip('inc/autoriser');
1499 if (autoriser(
1500 ($_GET['var_mode'] == 'preview')
1501 ? 'previsualiser'
1502 : 'debug'
1503 )) {
1504 switch($_GET['var_mode']){
1505 case 'preview':
1506 // forcer le compilo et ignorer les caches existants
1507 $GLOBALS['var_mode'] = 'recalcul';
1508 // truquer les boucles
1509 $GLOBALS['var_preview'] = true;
1510 // et ne pas enregistrer de cache
1511 $GLOBALS['var_nocache'] = true;
1512 break;
1513 case 'inclure':
1514 // forcer le compilo et ignorer les caches existants
1515 $GLOBALS['var_mode'] = 'calcul';
1516 $GLOBALS['var_inclure'] = true;
1517 // et ne pas enregistrer de cache
1518 $GLOBALS['var_nocache'] = true;
1519 break;
1520 case 'urls':
1521 // forcer le compilo et ignorer les caches existants
1522 $GLOBALS['var_mode'] = 'calcul';
1523 $GLOBALS['var_urls'] = true;
1524 break;
1525 case 'images':
1526 // forcer le compilo et ignorer les caches existants
1527 $GLOBALS['var_mode'] = 'calcul';
1528 // indiquer qu'on doit recalculer les images
1529 $GLOBALS['var_images'] = true;
1530 break;
1531 case 'debug':
1532 $GLOBALS['var_mode'] = 'debug';
1533 // et ne pas enregistrer de cache
1534 $GLOBALS['var_nocache'] = true;
1535 break;
1536 default :
1537 $GLOBALS['var_mode'] = $_GET['var_mode'];
1538 break;
1539 }
1540 spip_log($GLOBALS['visiteur_session']['nom']
1541 . " ".$GLOBALS['var_mode']);
1542 }
1543 // pas autorise ?
1544 else {
1545 // si on n'est pas connecte on se redirige
1546 if (!$GLOBALS['visiteur_session']) {
1547 include_spip('inc/headers');
1548 redirige_par_entete(generer_url_public('login',
1549 'url='.rawurlencode(
1550 parametre_url(self(), 'var_mode', $_GET['var_mode'], '&')
1551 ), true));
1552 }
1553 // sinon tant pis
1554 }
1555 }
1556 }
1557 $done = true;
1558 }
1559 }
1560
1561 // Annuler les magic quotes \' sur GET POST COOKIE et GLOBALS ;
1562 // supprimer aussi les eventuels caracteres nuls %00, qui peuvent tromper
1563 // la commande is_readable('chemin/vers/fichier/interdit%00truc_normal')
1564 // http://doc.spip.org/@spip_desinfecte
1565 function spip_desinfecte(&$t,$deep = true) {
1566 static $magic_quotes;
1567 if (!isset($magic_quotes))
1568 $magic_quotes = @get_magic_quotes_gpc();
1569
1570 foreach ($t as $key => $val) {
1571 if (is_string($t[$key])) {
1572 if ($magic_quotes)
1573 $t[$key] = stripslashes($t[$key]);
1574 $t[$key] = str_replace(chr(0), '-', $t[$key]);
1575 }
1576 // traiter aussi les "texte_plus" de articles_edit
1577 else if ($deep AND is_array($t[$key]) AND $key!=='GLOBALS')
1578 spip_desinfecte($t[$key],$deep);
1579 }
1580 }
1581
1582 // retourne le statut du visiteur s'il s'annonce
1583
1584
1585 // http://doc.spip.org/@verifier_visiteur
1586 function verifier_visiteur() {
1587
1588 // Demarrer une session NON AUTHENTIFIEE si on donne son nom
1589 // dans un formulaire sans login (ex: #FORMULAIRE_FORUM)
1590 // Attention on separe bien session_nom et nom, pour eviter
1591 // les melanges entre donnees SQL et variables plus aleatoires
1592 $variables_session = array('session_nom', 'session_email');
1593 foreach($variables_session as $var) {
1594 if (_request($var) !== null) {
1595 $init = true;
1596 break;
1597 }
1598 }
1599 if (isset($init)) {
1600 @spip_initialisation_core(
1601 (_DIR_RACINE . _NOM_PERMANENTS_INACCESSIBLES),
1602 (_DIR_RACINE . _NOM_PERMANENTS_ACCESSIBLES),
1603 (_DIR_RACINE . _NOM_TEMPORAIRES_INACCESSIBLES),
1604 (_DIR_RACINE . _NOM_TEMPORAIRES_ACCESSIBLES)
1605 );
1606 #@spip_initialisation_suite();
1607 $session = charger_fonction('session', 'inc');
1608 $session();
1609 include_spip('inc/texte');
1610 foreach($variables_session as $var)
1611 if (($a = _request($var)) !== null)
1612 $GLOBALS['visiteur_session'][$var] = safehtml($a);
1613 if (!isset($GLOBALS['visiteur_session']['id_auteur']))
1614 $GLOBALS['visiteur_session']['id_auteur'] = 0;
1615 $session($GLOBALS['visiteur_session']);
1616 return 0;
1617 }
1618
1619 $h = (isset($_SERVER['PHP_AUTH_USER']) AND !$GLOBALS['ignore_auth_http']);
1620 if ($h OR isset($_COOKIE['spip_session']) OR isset($_COOKIE[$GLOBALS['cookie_prefix'].'_session'])) {
1621
1622 // Rq: pour que cette fonction marche depuis mes_options
1623 // il faut forcer l'init si ce n'est fait
1624 // mais on risque de perturber des plugins en initialisant trop tot
1625 // certaines constantes
1626 @spip_initialisation_core(
1627 (_DIR_RACINE . _NOM_PERMANENTS_INACCESSIBLES),
1628 (_DIR_RACINE . _NOM_PERMANENTS_ACCESSIBLES),
1629 (_DIR_RACINE . _NOM_TEMPORAIRES_INACCESSIBLES),
1630 (_DIR_RACINE . _NOM_TEMPORAIRES_ACCESSIBLES)
1631 );
1632 #@spip_initialisation_suite();
1633
1634 $session = charger_fonction('session', 'inc');
1635 if ($session()) {
1636 return $GLOBALS['visiteur_session']['statut'];
1637 }
1638 if ($h AND isset($_SERVER['PHP_AUTH_PW'])) {
1639 include_spip('inc/auth');
1640 $h = lire_php_auth($_SERVER['PHP_AUTH_USER'], $_SERVER['PHP_AUTH_PW']);
1641 }
1642 if ($h) {
1643 $GLOBALS['visiteur_session'] = $h;
1644 return $GLOBALS['visiteur_session']['statut'];
1645 }
1646 }
1647 // au moins son navigateur nous dit la langue preferee de cet inconnu
1648 include_spip('inc/lang');
1649 utiliser_langue_visiteur();
1650 return false;
1651 }
1652
1653 // selectionne la langue donnee en argument et memorise la courante
1654 // ou restaure l'ancienne si appel sans argument
1655 // On pourrait economiser l'empilement en cas de non changemnt
1656 // et lui faire retourner False pour prevenir l'appelant
1657 // Le noyau de Spip sait le faire, mais pour assurer la compatibilite
1658 // cette fonction retourne toujours non False
1659
1660 // http://doc.spip.org/@lang_select
1661 function lang_select ($lang=NULL) {
1662 static $pile_langues = array();
1663 include_spip('inc/lang');
1664 if ($lang === NULL)
1665 $lang = array_pop($pile_langues);
1666 else {
1667 array_push($pile_langues, $GLOBALS['spip_lang']);
1668 }
1669 if ($lang == $GLOBALS['spip_lang'])
1670 return $lang;
1671 changer_langue($lang);
1672 return $lang;
1673 }
1674
1675
1676 // Renvoie une chaine qui decrit la session courante pour savoir si on peut
1677 // utiliser un cache enregistre pour cette session.
1678 // Par convention cette chaine ne doit pas contenir de caracteres [^0-9A-Za-z]
1679 // Attention on ne peut *pas* inferer id_auteur a partir de la session, qui
1680 // est une chaine arbitraire
1681 // Cette chaine est courte (8 cars) pour pouvoir etre utilisee dans un nom
1682 // de fichier cache
1683 // http://doc.spip.org/@spip_session
1684 function spip_session($force = false) {
1685 static $session;
1686 if ($force OR !isset($session)) {
1687 $s = pipeline('definir_session',
1688 $GLOBALS['visiteur_session']
1689 ? serialize($GLOBALS['visiteur_session'])
1690 . '_' . @$_COOKIE['spip_session']
1691 : ''
1692 );
1693 $session = $s ? substr(md5($s), 0, 8) : '';
1694 }
1695 #spip_log('session: '.$session);
1696 return $session;
1697 }
1698
1699 //
1700 // Aide, aussi depuis l'espace prive a present.
1701 // Surchargeable mais pas d'ereur fatale si indisponible.
1702 //
1703
1704 // http://doc.spip.org/@aide
1705 function aide($aide='') {
1706 $aider = charger_fonction('aider', 'inc', true);
1707 return $aider ? $aider($aide) : '';
1708 }
1709
1710 // normalement il faudrait creer exec/info.php, mais pour mettre juste ca:
1711 // http://doc.spip.org/@exec_info_dist
1712 function exec_info_dist() {
1713 global $connect_statut;
1714 if ($connect_statut == '0minirezo')
1715 phpinfo();
1716 else
1717 echo "pas admin";
1718 }
1719
1720 function erreur_squelette($message='', $lieu='') {
1721 $debusquer = charger_fonction('debusquer', 'public');
1722 if (is_array($lieu)) {
1723 include_spip('public/compiler');
1724 $lieu = reconstruire_contexte_compil($lieu);
1725 }
1726 return $debusquer($message, $lieu);
1727 }
1728
1729 /**
1730 * La fonction de base de SPIP : un squelette + un contexte => une page.
1731 * $fond peut etre un nom de squelette, ou une liste de squelette au format array.
1732 * Dans ce dernier cas, les squelettes sont tous evalues et mis bout a bout
1733 * $options permet de selectionner les options suivantes :
1734 * trim => true (valeur par defaut) permet de ne rien renvoyer si le fond ne produit que des espaces ;
1735 * raw => true permet de recuperer la strucure $page complete avec entetes et invalideurs pour chaque $fond fourni.
1736 *
1737 * @param string/array $fond
1738 * @param array $contexte
1739 * @param array $options
1740 * @param string $connect
1741 * @return string/array
1742 */
1743 // http://doc.spip.org/@recuperer_fond
1744 function recuperer_fond($fond, $contexte=array(), $options = array(), $connect='') {
1745 include_spip('public/assembler');
1746 // assurer la compat avec l'ancienne syntaxe
1747 // (trim etait le 3eme argument, par defaut a true)
1748 if (!is_array($options)) $options = array('trim'=>$options);
1749 if (!isset($options['trim'])) $options['trim']=true;
1750
1751 if (isset($contexte['connect'])){
1752 $connect = ($connect ? $connect : $contexte['connect']);
1753 unset($contexte['connect']);
1754 }
1755
1756 if (isset($options['modele']))
1757 $contexte = creer_contexte_de_modele($contexte);
1758
1759 $texte = "";
1760 $pages = array();
1761 if (isset($contexte['fond'])
1762 // securite anti injection pour permettre aux plugins de faire
1763 // des interfaces avec simplement recuperer_fond($fond,$_GET);
1764 AND $contexte['fond']!==_request('fond'))
1765 $fond = $contexte['fond'];
1766
1767 $lang_select = '';
1768 if (!isset($options['etoile']) OR !$options['etoile']){
1769 // Si on a inclus sans fixer le critere de lang, on prend la langue courante
1770 if (!isset($contexte['lang']))
1771 $contexte['lang'] = $GLOBALS['spip_lang'];
1772
1773 if ($contexte['lang'] != $GLOBALS['meta']['langue_site']) {
1774 $lang_select = lang_select($contexte['lang']);
1775 }
1776 }
1777
1778 @$GLOBALS['_INC_PUBLIC']++;
1779
1780 foreach(is_array($fond) ? $fond : array($fond) as $f){
1781 $page = evaluer_fond($f, $contexte, $connect);
1782 if ($page === '') {
1783 $c = isset($options['compil']) ? $options['compil'] :'';
1784 $a = array('fichier'=>$fond.'.'._EXTENSION_SQUELETTES);
1785 $erreur = _T('info_erreur_squelette2', $a); // squelette introuvable
1786 erreur_squelette($erreur, $c);
1787 // eviter des erreurs strictes ensuite sur $page['cle'] en PHP >= 5.4
1788 $page = array('texte' => '', 'erreur' => $erreur);
1789 }
1790
1791 if (isset($options['ajax'])AND $options['ajax']){
1792 include_spip('inc/filtres');
1793 $page['texte'] = encoder_contexte_ajax(array_merge($contexte,array('fond'=>$f)),'',$page['texte']);
1794 }
1795
1796 $page = pipeline('recuperer_fond',array(
1797 'args'=>array('fond'=>$fond,'contexte'=>$contexte,'options'=>$options,'connect'=>$connect),
1798 'data'=>$page
1799 ));
1800 if (isset($options['raw']) AND $options['raw'])
1801 $pages[] = $page;
1802 else
1803 $texte .= $options['trim'] ? rtrim($page['texte']) : $page['texte'];
1804 }
1805
1806 $GLOBALS['_INC_PUBLIC']--;
1807
1808 if ($lang_select) lang_select();
1809 if (isset($options['raw']) AND $options['raw'])
1810 return is_array($fond)?$pages:reset($pages);
1811 else
1812 return $options['trim'] ? ltrim($texte) : $texte;
1813 }
1814
1815 function trouve_modele($nom)
1816 {
1817 return find_in_path( 'modeles/' . $nom.'.'. _EXTENSION_SQUELETTES);
1818 }
1819
1820 // Charger dynamiquement une extension php
1821 // http://doc.spip.org/@charger_php_extension
1822 function charger_php_extension($module) {
1823 if (extension_loaded($module)) {
1824 return true;
1825 } else {
1826 $charger_php_extension = charger_fonction('charger_php_extension','inc');
1827 return $charger_php_extension($module);
1828 }
1829 }
1830
1831
1832 /*
1833 * Bloc de compatibilite : quasiment tous les plugins utilisent ces fonctions
1834 * desormais depreciees ; plutot que d'obliger tout le monde a charger
1835 * vieilles_defs, on va assumer l'histoire de ces 3 fonctions ubiquitaires
1836 */
1837 // Fonction depreciee
1838 // http://doc.spip.org/@lire_meta
1839 function lire_meta($nom) {
1840 return $GLOBALS['meta'][$nom];
1841 }
1842
1843 // Fonction depreciee
1844 // http://doc.spip.org/@ecrire_metas
1845 function ecrire_metas() {}
1846
1847 // Fonction depreciee, cf. http://doc.spip.org/@sql_fetch
1848 // http://doc.spip.org/@spip_fetch_array
1849 function spip_fetch_array($r, $t=NULL) {
1850 if (!isset($t)) {
1851 if ($r) return sql_fetch($r);
1852 } else {
1853 if ($t=='SPIP_NUM') $t = MYSQL_NUM;
1854 if ($t=='SPIP_BOTH') $t = MYSQL_BOTH;
1855 if ($t=='SPIP_ASSOC') $t = MYSQL_ASSOC;
1856 spip_log("appel deprecie de spip_fetch_array(..., $t)", 'vieilles_defs');
1857 if ($r) return mysql_fetch_array($r, $t);
1858 }
1859 }
1860
1861 ?>