Skip to content
Extraits de code Groupes Projets
utils.php 89,3 ko
Newer Older

/**
 * Gestion des chemins (ou path) de recherche de fichiers par SPIP
 *
amemo's avatar
amemo a validé
 * Empile de nouveaux chemins (à la suite de ceux déjà présents, mais avant
 * le répertoire `squelettes` ou les dossiers squelettes), si un répertoire
 * (ou liste de répertoires séparés par `:`) lui est passé en paramètre.
 *
 * Ainsi, si l'argument est de la forme `dir1:dir2:dir3`, ces 3 chemins sont placés
amemo's avatar
amemo a validé
 * en tête du path, dans cet ordre (hormis `squelettes` & la globale
 * `$dossier_squelette` si définie qui resteront devant)
 * Retourne dans tous les cas la liste des chemins.
 *
 * @note
 *     Cette fonction est appelée à plusieurs endroits et crée une liste
 *     de chemins finale à peu près de la sorte :
 *     - dossiers squelettes (si globale précisée)
 *     - squelettes/
 *     - plugins (en fonction de leurs dépendances) : ceux qui dépendent
 *       d'un plugin sont devant eux (ils peuvent surcharger leurs fichiers)
 *     - racine du site
 *     - squelettes-dist/
 *     - prive/
 *     - ecrire/
 * @param string $dir_path
 *     - Répertoire(s) à empiler au path
 *     - '' provoque un recalcul des chemins.
 * @return array
 *     Liste des chemins, par ordre de priorité.
**/
function _chemin($dir_path=NULL){
	static $path_base = NULL;
	static $path_full = NULL;
	if ($path_base==NULL){
Fil's avatar
Fil a validé
		// Chemin standard depuis l'espace public
		$path = defined('_SPIP_PATH') ? _SPIP_PATH :
Fil's avatar
Fil a validé
			_DIR_RACINE.':'.
cerdic's avatar
cerdic a validé
			_DIR_RACINE.'squelettes-dist/:'.
Fil's avatar
Fil a validé
		// Ajouter squelettes/
Fil's avatar
Fil a validé
		if (@is_dir(_DIR_RACINE.'squelettes'))
			$path = _DIR_RACINE.'squelettes/:' . $path;
Fil's avatar
Fil a validé
		foreach (explode(':', $path) as $dir) {
			if (strlen($dir) AND substr($dir,-1) != '/')
				$dir .= "/";
			$path_base[] = $dir;
		}
		$path_full = $path_base;
		// Et le(s) dossier(s) des squelettes nommes
		if (strlen($GLOBALS['dossier_squelettes']))
			foreach (array_reverse(explode(':', $GLOBALS['dossier_squelettes'])) as $d)
				array_unshift($path_full, ($d[0] == '/' ? '' : _DIR_RACINE) . $d . '/');
		$GLOBALS['path_sig'] = md5(serialize($path_full));
cerdic's avatar
cerdic a validé
	if ($dir_path===NULL) return $path_full;

	if (strlen($dir_path)){
		$tete = "";
		if (reset($path_base)==_DIR_RACINE.'squelettes/')
			$tete = array_shift($path_base);
		$dirs = array_reverse(explode(':',$dir_path));
		foreach($dirs as $dir_path){
				#if ($dir_path{0}!='/')
				#	$dir_path = $dir_path;
				if (substr($dir_path,-1) != '/')
					$dir_path .= "/";
				if (!in_array($dir_path,$path_base))
					array_unshift($path_base,$dir_path);
Fil's avatar
Fil a validé
		}
		if (strlen($tete))
			array_unshift($path_base,$tete);
Fil's avatar
Fil a validé
	}
	$path_full = $path_base;
	// Et le(s) dossier(s) des squelettes nommes
	if (strlen($GLOBALS['dossier_squelettes']))
		foreach (array_reverse(explode(':', $GLOBALS['dossier_squelettes'])) as $d)
marcimat's avatar
marcimat a validé
			array_unshift($path_full, ((isset($d[0]) and $d[0] == '/') ? '' : _DIR_RACINE) . $d . '/');
	$GLOBALS['path_sig'] = md5(serialize($path_full));
/**
 * Retourne la liste des chemins connus de SPIP, dans l'ordre de priorité
 *
 * Recalcule la liste si le nom ou liste de dossier squelettes a changé.
 *
 * @uses _chemin()
 * @return array Liste de chemins
**/
function creer_chemin() {
	$path_a = _chemin();
	static $c = '';
	// on calcule le chemin si le dossier skel a change
	if ($c != $GLOBALS['dossier_squelettes']) {
		// assurer le non plantage lors de la montee de version :
		$c = $GLOBALS['dossier_squelettes'];
		$path_a = _chemin(''); // forcer un recalcul du chemin
	}
function lister_themes_prives(){
	static $themes = null;
	if (is_null($themes)){
cerdic's avatar
cerdic a validé
		// si pas encore definie
		if (!defined('_SPIP_THEME_PRIVE'))
denisb's avatar
denisb a validé
			define('_SPIP_THEME_PRIVE', 'spip');
		$themes = array(_SPIP_THEME_PRIVE);
		// lors d'une installation neuve, prefs n'est pas definie.
		if (isset($GLOBALS['visiteur_session']['prefs'])) {
			$prefs = isset($GLOBALS['visiteur_session']['prefs']);
		} else {
			$prefs = array();
		}
cerdic's avatar
cerdic a validé
		if (is_string($prefs))
			$prefs = unserialize($GLOBALS['visiteur_session']['prefs']);
		if (
			((isset($prefs['theme']) AND $theme = $prefs['theme'])
			OR (isset($GLOBALS['theme_prive_defaut']) AND $theme = $GLOBALS['theme_prive_defaut']))
			AND $theme != _SPIP_THEME_PRIVE)
			array_unshift($themes,$theme); // placer le theme choisi en tete
cerdic's avatar
cerdic a validé
	}
	return $themes;
cerdic's avatar
cerdic a validé
}

function find_in_theme($file, $subdir='', $include=false){
	static $themefiles=array();
	if (isset($themefiles["$subdir$file"])) return $themefiles["$subdir$file"];
	$themes = lister_themes_prives();
	foreach($themes as $theme){
		if ($f = find_in_path($file,"prive/themes/$theme/$subdir",$include))
			return $themefiles["$subdir$file"] = $f;
cerdic's avatar
cerdic a validé
	}
	spip_log("$file introuvable dans le theme prive ".reset($themes),'theme');
	return $themefiles["$subdir$file"] = "";
cerdic's avatar
cerdic a validé
}
marcimat's avatar
marcimat a validé

/**
 * Cherche une image dans les dossiers d'images
 *
 * Cherche en priorité dans les thèmes d'image (prive/themes/X/images)
 * et si la fonction n'en trouve pas, gère le renommage des icones (ex: 'supprimer' => 'del')
 * de facon temporaire le temps de la migration, et cherche de nouveau.
 *
 * Si l'image n'est toujours pas trouvée, on la cherche dans les chemins,
 * dans le répertoire défini par la constante `_NOM_IMG_PACK`
marcimat's avatar
marcimat a validé
 *
 * @see find_in_theme()
 * @see inc_icone_renommer_dist()
marcimat's avatar
marcimat a validé
 * @param string $icone
 *     Nom de l'icone cherchée
 * @return string
 *     Chemin complet de l'icone depuis la racine si l'icone est trouée,
 *     sinon chaîne vide.
**/
cerdic's avatar
cerdic a validé
function chemin_image($icone){
	static $icone_renommer;
	// gerer le cas d'un double appel en evitant de refaire le travail inutilement
	if (strpos($icone,"/")!==false AND file_exists($icone)) return $icone;
	// si c'est un nom d'image complet (article-24.png) essayer de le renvoyer direct
	if (preg_match(',[.](png|gif|jpg)$,',$icone) AND $f = find_in_theme("images/$icone"))
	// sinon passer par le module de renommage
	if (is_null($icone_renommer))
		$icone_renommer = charger_fonction('icone_renommer','inc',true);
	if ($icone_renommer){
cerdic's avatar
cerdic a validé
		list($icone,$fonction) = $icone_renommer($icone,"");
		if (file_exists($icone))
			return $icone;
	}
	return find_in_path ($icone, _NOM_IMG_PACK);
//
// chercher un fichier $file dans le SPIP_PATH
// si on donne un sous-repertoire en 2e arg optionnel, il FAUT le / final
// si 3e arg vrai, on inclut si ce n'est fait.
$GLOBALS['path_sig'] = '';
cerdic's avatar
cerdic a validé
$GLOBALS['path_files'] = null;
Fil's avatar
Fil a validé

/**
 * Recherche un fichier dans les chemins de SPIP (squelettes, plugins, core)
 *
 * Retournera le premier fichier trouvé (ayant la plus haute priorité donc),
 * suivant l'ordre des chemins connus de SPIP.
 *
marcimat's avatar
marcimat a validé
 * @see charger_fonction()
 * @uses creer_chemin() Pour la liste des chemins.
 * @example
 *     ```
 *     $f = find_in_path('css/perso.css');
 *     $f = find_in_path('perso.css', 'css');
 *     ```
 * @param string $file
 *     Fichier recherché
 * @param string $dirname
 *     Répertoire éventuel de recherche (est aussi extrait automatiquement de $file)
 * @param bool|string $include
 *     - false : ne fait rien de plus
 *     - true : inclut le fichier (include_once)
 *     - 'require' : idem, mais tue le script avec une erreur si le fichier n'est pas trouvé.
 * @return string|bool
 *     - string : chemin du fichier trouvé
 *     - false : fichier introuvable
**/
function find_in_path ($file, $dirname='', $include=false) {
cerdic's avatar
cerdic a validé
	static $dirs=array();
	static $inc = array(); # cf http://trac.rezo.net/trac/spip/changeset/14743
	static $c = '';

	// on calcule le chemin si le dossier skel a change
	if ($c != $GLOBALS['dossier_squelettes']){
		// assurer le non plantage lors de la montee de version :
		$c = $GLOBALS['dossier_squelettes'];
		creer_chemin(); // forcer un recalcul du chemin et la mise a jour de path_sig
	}

	if (isset($GLOBALS['path_files'][$GLOBALS['path_sig']][$dirname][$file])) {
		if (!$GLOBALS['path_files'][$GLOBALS['path_sig']][$dirname][$file])
cerdic's avatar
cerdic a validé
			return false;
		if ($include AND !isset($inc[$dirname][$file])) {
			include_once _ROOT_CWD . $GLOBALS['path_files'][$GLOBALS['path_sig']][$dirname][$file];
cerdic's avatar
cerdic a validé
			$inc[$dirname][$file] = $inc[''][$dirname . $file] = true;
		}
		return $GLOBALS['path_files'][$GLOBALS['path_sig']][$dirname][$file];
esj's avatar
esj a validé
	$a = strrpos($file,'/');
	if ($a !== false) {
		$dirname .= substr($file, 0, ++$a);
		$file = substr($file, $a);
	foreach(creer_chemin() as $dir) {
		if (!isset($dirs[$a = $dir . $dirname]))
cerdic's avatar
cerdic a validé
			$dirs[$a] = (is_dir(_ROOT_CWD . $a) || !$a) ;
cerdic's avatar
cerdic a validé
			if (file_exists(_ROOT_CWD . ($a .= $file))) {
				if ($include AND !isset($inc[$dirname][$file])) {
cerdic's avatar
cerdic a validé
					include_once _ROOT_CWD . $a;
					$inc[$dirname][$file] = $inc[''][$dirname . $file] = true;
				}
				if (!defined('_SAUVER_CHEMIN')){
					// si le chemin n'a pas encore ete charge, ne pas lever le flag, ne pas cacher
					if (is_null($GLOBALS['path_files'])) return $a;
					define('_SAUVER_CHEMIN', true);
				}
				return $GLOBALS['path_files'][$GLOBALS['path_sig']][$dirname][$file] = $GLOBALS['path_files'][$GLOBALS['path_sig']][''][$dirname . $file] = $a;
esj's avatar
esj a validé
		}

	if ($include){
		spip_log("include_spip $dirname$file non trouve");
		if ($include==='required'){
			echo '<pre>',
			"<strong>Erreur Fatale</strong><br />";
			if (function_exists('debug_print_backtrace'))
				echo debug_print_backtrace();
			echo '</pre>';
			die("Erreur interne: ne peut inclure $dirname$file");
		}
	}
cerdic's avatar
cerdic a validé

	if (!defined('_SAUVER_CHEMIN'))
		define('_SAUVER_CHEMIN',true);
	return $GLOBALS['path_files'][$GLOBALS['path_sig']][$dirname][$file] = $GLOBALS['path_files'][$GLOBALS['path_sig']][''][$dirname . $file] = false;
cerdic's avatar
cerdic a validé
}

cerdic's avatar
cerdic a validé
function clear_path_cache(){
	$GLOBALS['path_files'] = array();
	spip_unlink(_CACHE_CHEMIN);
}
cerdic's avatar
cerdic a validé
function load_path_cache(){
	// charger le path des plugins
	if (@is_readable(_CACHE_PLUGINS_PATH)){
		include_once(_CACHE_PLUGINS_PATH);
	}
cerdic's avatar
cerdic a validé
	$GLOBALS['path_files'] = array();
	// si le visiteur est admin,
	// on ne recharge pas le cache pour forcer sa mise a jour
cerdic's avatar
cerdic a validé
		// la session n'est pas encore chargee a ce moment, on ne peut donc pas s'y fier
		//AND (!isset($GLOBALS['visiteur_session']['statut']) OR $GLOBALS['visiteur_session']['statut']!='0minirezo')
cerdic's avatar
cerdic a validé
		// utiliser le cookie est un pis aller qui marche 'en general'
		// on blinde par un second test au moment de la lecture de la session
		// !isset($_COOKIE[$GLOBALS['cookie_prefix'].'_admin'])
cerdic's avatar
cerdic a validé
		// et en ignorant ce cache en cas de recalcul explicite
		// on essaye de lire directement sans verrou pour aller plus vite
		if ($contenu = spip_file_get_contents(_CACHE_CHEMIN)){
			// mais si semble corrompu on relit avec un verrou
			if (!$GLOBALS['path_files']=unserialize($contenu)){
				lire_fichier(_CACHE_CHEMIN,$contenu);
				if (!$GLOBALS['path_files']=unserialize($contenu))
					$GLOBALS['path_files'] = array();
			}
		}
cerdic's avatar
cerdic a validé
	}
cerdic's avatar
cerdic a validé
function save_path_cache(){
	if (defined('_SAUVER_CHEMIN')
		AND _SAUVER_CHEMIN)
		ecrire_fichier(_CACHE_CHEMIN,serialize($GLOBALS['path_files']));
}


cerdic's avatar
cerdic a validé
/**
 * Trouve tous les fichiers du path correspondants à un pattern
 * Pour un nom de fichier donné, ne retourne que le premier qui sera trouvé
 * par un `find_in_path()`
cerdic's avatar
cerdic a validé
 *
 * @api
marcimat's avatar
marcimat a validé
 * @uses creer_chemin()
 * @uses preg_files()
cerdic's avatar
cerdic a validé
 * @param string $dir
 * @param string $pattern
 * @param bool $recurs
 * @return array
 */
function find_all_in_path($dir,$pattern, $recurs=false){
	$liste_fichiers=array();
	$maxfiles = 10000;
	foreach (creer_chemin() as $d) {
		$f = $d.$dir;
		if (@is_dir($f)){
			$liste = preg_files($f,$pattern,$maxfiles-count($liste_fichiers),$recurs===true?array():$recurs);
			foreach($liste as $chemin){
				$nom = basename($chemin);
				// ne prendre que les fichiers pas deja trouves
				// car find_in_path prend le premier qu'il trouve,
				// les autres sont donc masques
				if (!isset($liste_fichiers[$nom]))
					$liste_fichiers[$nom] = $chemin;
			}
		}
// predicat sur les scripts de ecrire qui n'authentifient pas par cookie

// http://code.spip.net/@autoriser_sans_cookie
cerdic's avatar
cerdic a validé
  static $autsanscookie = array('install', 'base_repair');
  $nom = preg_replace('/.php[3]?$/', '', basename($nom));
  return in_array($nom, $autsanscookie);
}

 * Fonction codant et décodant les URLs des objets SQL mis en page par SPIP
 * @api
 * @param string $id
 *   numero de la cle primaire si nombre, URL a decoder si pas numerique
 * @param string $entite
 *   surnom de la table SQL (donne acces au nom de cle primaire)
 * @param string $args
 *   query_string a placer apres cle=$id&....
 * @param string $ancre
 *   ancre a mettre a la fin de l'URL a produire
 * @param bool|string $public
 *   produire l'URL publique ou privee (par defaut: selon espace)
 *   si string : serveur de base de donnee (nom du connect)
 * @param string $type
 *   fichier dans le repertoire ecrire/urls determinant l'apparence
 * @return string|array
 *   url codee ou fonction de decodage
 *   array : derogatoire, la fonction d'url retourne (objet,id_objet) utilises par nettoyer_raccourcis_typo() pour generer un lien titre
 *           (cas des raccourcis personalises [->spip20] : il faut implementer une fonction generer_url_spip et une fonction generer_url_ecrire_spip)
 */
function generer_url_entite($id='', $entite='', $args='', $ancre='', $public=NULL, $type=NULL)
	if ($public === NULL) $public = !test_espace_prive();
cerdic's avatar
cerdic a validé
	$entite = objet_type($entite); // cas particulier d'appels sur objet/id_objet...
		if (!function_exists('generer_url_ecrire_objet'))
			include_spip('inc/urls');
		$res = generer_url_ecrire_objet($entite,$id, $args, $ancre, false);
                        $type = (isset($GLOBALS['type_urls'])) 
                        ?  $GLOBALS['type_urls'] // pour surcharge via fichier d'options
                        :  ((isset($GLOBALS['meta']['type_urls'])) // sinon la config url_etendues
			    ? ($GLOBALS['meta']['type_urls']) : "page") ; // sinon type "page" par défaut

		$f = charger_fonction($type, 'urls', true);
		// se rabattre sur les urls page si les urls perso non dispo
		if (!$f) $f = charger_fonction('page', 'urls', true);

		// si $entite='', on veut la fonction de passage URL ==> id
		// sinon on veut effectuer le passage id ==> URL
		if (!$entite) return $f;

		// mais d'abord il faut tester le cas des urls sur une
		// base distante
		if (is_string($public)
		AND $g = charger_fonction('connect', 'urls', true))
			$f = $g;

		$res = $f(intval($id), $entite, $args, $ancre, $public);

	if ($res) return $res;
	// Sinon c'est un raccourci ou compat SPIP < 2
	if (!function_exists($f = 'generer_url_' . $entite)) {
		if (!function_exists($f .= '_dist')) $f = '';
	if ($f) {
		$url = $f($id, $args, $ancre);
		if (strlen($args))
			$url .= strstr($url, '?')
				? '&amp;'.$args
				: '?'.$args;
		return $url;
	}
	// On a ete gentil mais la ....
	spip_log("generer_url_entite: entite $entite ($f) inconnue $type $public");
function generer_url_ecrire_entite_edit($id, $entite, $args='', $ancre=''){
	$exec = objet_info($entite,'url_edit');
	$url = generer_url_ecrire($exec,$args);
	if (intval($id))
		$url = parametre_url($url,id_table_objet($entite),$id);
	else
		$url = parametre_url($url,'new','oui');
	if ($ancre)
		$url = ancre_url($url,$ancre);
	return $url;
}

// http://code.spip.net/@urls_connect_dist
function urls_connect_dist($i, &$entite, $args='', $ancre='', $public=null) {
	include_spip('base/connect_sql');
	$id_type = id_table_objet($entite,$public);
	return _DIR_RACINE . get_spip_script('./')
	  . "?"._SPIP_PAGE."=$entite&$id_type=$i&connect=$public"
	  . (!$args ? '' : "&$args")
	  . (!$ancre ? '' : "#$ancre");
}


/**
 * Transformer les caractères utf8 d'une URL (farsi par exemple) selon la RFC 1738
 *
 * @param string $url
 * @return string
 */
function urlencode_1738($url) {
	if (preg_match(',[^\x00-\x7E],sS', $url)){
		$uri = '';
		for ($i=0; $i < strlen($url); $i++) {
			if (ord($a = $url[$i]) > 127)
				$a = rawurlencode($a);
			$uri .= $a;
		}
		$url = $uri;
// http://code.spip.net/@generer_url_entite_absolue
function generer_url_entite_absolue($id='', $entite='', $args='', $ancre='', $connect=NULL)
{
	if (!$connect) $connect = true;
	$h = generer_url_entite($id, $entite, $args, $ancre, $connect);
esj's avatar
esj a validé
	if (!preg_match(',^\w+:,', $h)) {
		include_spip('inc/filtres_mini');
		$h = url_absolue($h);
esj's avatar
esj a validé
	}
// Sur certains serveurs, la valeur 'Off' tient lieu de false dans certaines
// variables d'environnement comme $_SERVER[HTTPS] ou ini_get(register_globals)
// http://code.spip.net/@test_valeur_serveur
function test_valeur_serveur($truc) {
	if (!$truc) return false;
	return (strtolower($truc) !== 'off');

//
// Fonctions de fabrication des URL des scripts de Spip
//
/**
 * l'URL de base du site, sans se fier a meta(adresse_site) qui
 * peut etre fausse (sites a plusieurs noms d'hotes, deplacements, erreurs)
 * Note : la globale $profondeur_url doit etre initialisee de maniere a
 * indiquer le nombre de sous-repertoires de l'url courante par rapport a la
 * racine de SPIP : par exemple, sur ecrire/ elle vaut 1, sur sedna/ 1, et a
 * la racine 0. Sur url/perso/ elle vaut 2
 * http://code.spip.net/@url_de_base
 *
 * @param int|boo|array $profondeur
 *    si non renseignee : retourne l'url pour la profondeur $GLOBALS['profondeur_url']
 *    si int : indique que l'on veut l'url pour la prondeur indiquee
 *    si bool : retourne le tableau static complet
 *    si array : reinitialise le tableau static complet avec la valeur fournie
 * @return string|array
 */
function url_de_base($profondeur=null) {
Fil's avatar
Fil a validé
	static $url = array();
	if (is_array($profondeur)) return $url = $profondeur;
	if ($profondeur===false) return $url;

	if (is_null($profondeur)) $profondeur = $GLOBALS['profondeur_url'];
	if (isset($url[$profondeur]))
		return $url[$profondeur];
		(isset($_SERVER["SCRIPT_URI"]) AND
			substr($_SERVER["SCRIPT_URI"],0,5) == 'https')
		OR (isset($_SERVER['HTTPS']) AND
		    test_valeur_serveur($_SERVER['HTTPS']))
	) ? 'https' : 'http';
	if (isset($_SERVER['HTTP_X_FORWARDED_HOST'])){
		$host = strtr($_SERVER['HTTP_X_FORWARDED_HOST'], "<>?\"' \r\n", '________');
	}
	else {
		# note : HTTP_HOST contient le :port si necessaire
		$host = $_SERVER['HTTP_HOST'];
		if (isset($_SERVER['SERVER_PORT'])
			AND $port=$_SERVER['SERVER_PORT']
			AND strpos($host,":")==false){
			if (!defined('_PORT_HTTP_STANDARD')) define('_PORT_HTTP_STANDARD','80');
			if (!defined('_PORT_HTTPS_STANDARD')) define('_PORT_HTTPS_STANDARD','443');
			if ($http=="http" AND !in_array($port,explode(',',_PORT_HTTP_STANDARD))) $host.=":$port";
			if ($http=="https" AND !in_array($port,explode(',',_PORT_HTTPS_STANDARD))) $host.=":$port";
		}
cerdic's avatar
cerdic a validé
	if (!$GLOBALS['REQUEST_URI']){
		if (isset($_SERVER['REQUEST_URI'])) {
			$GLOBALS['REQUEST_URI'] = $_SERVER['REQUEST_URI'];
		} else {
			$GLOBALS['REQUEST_URI'] = $_SERVER['PHP_SELF'];
			if ($_SERVER['QUERY_STRING']
			AND !strpos($_SERVER['REQUEST_URI'], '?'))
				$GLOBALS['REQUEST_URI'] .= '?'.$_SERVER['QUERY_STRING'];
		}
Fil's avatar
Fil a validé
	}
	$url[$profondeur] = url_de_($http,$host,$GLOBALS['REQUEST_URI'],$profondeur);
}
/**
 * fonction testable de construction d'une url appelee par url_de_base()
 * @param string $http
 * @param string $host
 * @param string $request
 * @param int $prof
 * @return string
 */
function url_de_($http,$host,$request,$prof=0){
	$prof = max($prof,0);

	$myself = ltrim($request,'/');
Fil's avatar
Fil a validé
	# supprimer la chaine de GET
	list($myself) = explode('?', $myself);
	$url = join('/', array_slice(explode('/', $myself), 0, -1-$prof)).'/';
Fil's avatar
Fil a validé

	$url = $http.'://'.rtrim($host,'/').'/'.ltrim($url,'/');
	return $url;
esj's avatar
esj a validé
// Pour une redirection, la liste des arguments doit etre separee par "&"
// Pour du code XHTML, ca doit etre &amp;
// Bravo au W3C qui n'a pas ete capable de nous eviter ca
// faute de separer proprement langage et meta-langage
// Attention, X?y=z et "X/?y=z" sont completement differents!
// http://httpd.apache.org/docs/2.0/mod/mod_dir.html
/**
 * Crée une URL vers un script de l'espace privé
 *
 * @example
 *     ```
 *     generer_url_ecrire('admin_plugin')
 *     ```
 * @param string $script
 *     Nom de la page privée (xx dans exec=xx)
 * @param string $args
 *     Arguments à transmettre, tel que `arg1=yy&arg2=zz`
 * @param bool $no_entities
 *     Si false : transforme les `&` en `&amp;`
 * @param bool|string $rel
 *     URL relative ?
 *
 *     - false : l’URL sera complète et contiendra l’URL du site
 *     - true : l’URL sera relavive.
 *     - string : on transmet l'url à la fonction
 * @return string URL
**/
function generer_url_ecrire($script='', $args="", $no_entities=false, $rel=false) {
		$rel = url_de_base() . _DIR_RESTREINT_ABS . _SPIP_ECRIRE_SCRIPT;
		$rel = _DIR_RESTREINT ? _DIR_RESTREINT :
			('./'  . _SPIP_ECRIRE_SCRIPT);
Fil's avatar
Fil a validé

marcimat's avatar
marcimat a validé
	list($script, $ancre) = array_pad(explode('#', $script), 2, null);
	if ($script AND ($script<>'accueil' OR $rel))
		$args = "?exec=$script" . (!$args ? '' : "&$args");
	elseif ($args)
		$args ="?$args";
	if ($ancre) $args .= "#$ancre";
	return $rel . ($no_entities ? $args : str_replace('&', '&amp;', $args));
// http://code.spip.net/@generer_url_retour
function generer_url_retour($script, $args="")
{
	return rawurlencode(generer_url_ecrire($script, $args, true, true));
}

Fil's avatar
Fil a validé
//
// Adresse des scripts publics (a passer dans inc-urls...)
//

/**
 * Retourne le nom du fichier d'exécution de SPIP
 *
 * @see _SPIP_SCRIPT
 * @note
 *   Detecter le fichier de base, a la racine, comme etant spip.php ou ''
 *   dans le cas de '', un $default = './' peut servir (comme dans urls/page.php)
 * @param string $default
 *     Script par défaut
 * @return string
 *     Nom du fichier (constante _SPIP_SCRIPT), sinon nom par défaut
**/
Fil's avatar
Fil a validé
function get_spip_script($default='') {
	# cas define('_SPIP_SCRIPT', '');
Fil's avatar
Fil a validé
	if (_SPIP_SCRIPT)
		return _SPIP_SCRIPT;
Fil's avatar
Fil a validé
	else
Fil's avatar
Fil a validé
		return $default;
}

/**
 * Crée une URL vers une page publique de SPIP
 *
 * @example
 *     ```
 *     generer_url_public("rubrique","id_rubrique=$id_rubrique")
 *     ```
 * @param string $script
 *     Nom de la page
 * @param string|array $args
 *     Arguments à transmettre a l'URL,
 *      soit sous la forme d'un string tel que `arg1=yy&arg2=zz`
 *      soit sous la forme d'un array tel que array( `arg1` => `yy`, `arg2` => `zz` )
 * @param bool $no_entities
 *     Si false : transforme les `&` en `&amp;`
 * @param bool $rel
 *     URL relative ?
 *
 *     - false : l’URL sera complète et contiendra l’URL du site
 *     - true : l’URL sera relavive.
 * @param string $action
 *     - Fichier d'exécution public (spip.php par défaut)
 * @return string URL
function generer_url_public($script='', $args="", $no_entities=false, $rel=true, $action='') {
Fil's avatar
Fil a validé
	// si le script est une action (spip_pass, spip_inscription),
esj's avatar
esj a validé
	// standardiser vers la nouvelle API
	if (!$action) $action = get_spip_script();
Fil's avatar
Fil a validé
	if ($script)
		$action = parametre_url($action, _SPIP_PAGE, $script, '&');
	if ($args) {
		if (is_array($args)) {
			$r = '';
			foreach($args as $k => $v) $r .= '&' . $k . '=' . $v;
			$args = substr($r,1);
		}
Fil's avatar
Fil a validé
		$action .=
			(strpos($action, '?') !== false ? '&' : '?') . $args;
Fil's avatar
Fil a validé
	if (!$no_entities)
		$action = quote_amp($action);
	// ne pas generer une url avec /./?page= en cas d'url absolue et de _SPIP_SCRIPT vide
	return ($rel ? _DIR_RACINE . $action : rtrim(url_de_base(),'/') . preg_replace(",^/[.]/,","/","/$action"));
// http://code.spip.net/@generer_url_prive
function generer_url_prive($script, $args="", $no_entities=false) {

	return generer_url_public($script, $args, $no_entities, false, _DIR_RESTREINT_ABS .  'prive.php');
// Pour les formulaires en methode POST,
// mettre le nom du script a la fois en input-hidden et dans le champ action:
// 1) on peut ainsi memoriser le signet comme si c'etait un GET
// 2) ca suit http://en.wikipedia.org/wiki/Representational_State_Transfer

/**
 * Retourne un formulaire (POST par défaut) vers un script exec
 * de l’interface privée
 *
 * @param string $script
 *     Nom de la page exec
 * @param string $corps
 *     Contenu du formulaire
 * @param string $atts
 *     Si présent, remplace les arguments par défaut (method=post) par ceux indiqués
 * @param string $submit
 *     Si indiqué, un bouton de soumission est créé avec texte sa valeur.
 * @return string
 *     Code HTML du formulaire
**/
function generer_form_ecrire($script, $corps, $atts='', $submit='') {
	$script1 = explode('&', $script);
	$script1 = reset($script1);
	. ($script ? generer_url_ecrire($script) : '')
	. "' "
	. ($atts ? $atts : " method='post'")
	.  "><div>\n"
	. "<input type='hidden' name='exec' value='$script1' />"
	     ("<div style='text-align: $spip_lang_right'><input class='fondo' type='submit' value=\"".entites_html($submit)."\" /></div>"))
 * Générer un formulaire pour lancer une action vers $script
 *
 * Attention, JS/Ajax n'aime pas le melange de param GET/POST
 * On n'applique pas la recommandation ci-dessus pour les scripts publics
 * qui ne sont pas destines a etre mis en signets
 * http://code.spip.net/@generer_form_action
 *
 * @param string $script
 * @param string $corps
 * @param string $atts
 * @param bool $public
 * @return string
 */
function generer_form_action($script, $corps, $atts='', $public=false) {
	// si l'on est dans l'espace prive, on garde dans l'url
	// l'exec a l'origine de l'action, qui permet de savoir si il est necessaire
	// ou non de proceder a l'authentification (cas typique de l'install par exemple)
kent1's avatar
kent1 a validé
	$h = (_DIR_RACINE AND !$public)
	? generer_url_ecrire(_request('exec'))
	: generer_url_public();

	return "\n<form action='" .
	  $h .
	  "'" .
	  $atts .
	  ">\n" .
	  "<div>" .
  	  "\n<input type='hidden' name='action' value='$script' />" .
	  $corps .
	  "</div></form>";
}

amemo's avatar
amemo a validé
/**
 * Créer une URL
 *
amemo's avatar
amemo a validé
 *     Nom du script à exécuter
 * @param  string|array $args
 *     Arguments à transmettre a l'URL, soit sous la forme d'un string
 *     tel que `arg1=yy&arg2=zz` soit sous la forme d'un array tel que
amemo's avatar
amemo a validé
 *    `array( arg1 => yy, arg2 => zz )`
amemo's avatar
amemo a validé
 *     Si false : transforme les & en &amp;
 * @param boolean $public
 *     URL relative ? false : l’URL sera complète et contiendra l’URL du site.
amemo's avatar
amemo a validé
 *     true : l’URL sera relative.
 * @return string
 *     URL
 */
function generer_url_action($script, $args="", $no_entities=false , $public = false) {
	// si l'on est dans l'espace prive, on garde dans l'url
	// l'exec a l'origine de l'action, qui permet de savoir si il est necessaire
	// ou non de proceder a l'authentification (cas typique de l'install par exemple)
	$url = (_DIR_RACINE  AND !$public)
	  ? generer_url_ecrire(_request('exec'))
	  :  generer_url_public('','',false,false);
	$url = parametre_url($url,'action',$script);
	if ($args) $url .= quote_amp('&'.$args);
kent1's avatar
kent1 a validé

	if ($no_entities) $url = str_replace('&amp;','&',$url);
	return $url;
cerdic's avatar
cerdic a validé
/**
marcimat's avatar
marcimat a validé
 * Fonction d'initialisation groupée pour compatibilité ascendante
cerdic's avatar
cerdic a validé
 *
marcimat's avatar
marcimat a validé
 * @param string $pi Répertoire permanent inaccessible
 * @param string $pa Répertoire permanent accessible
 * @param string $ti Répertoire temporaire inaccessible
 * @param string $ta Répertoire temporaire accessible
cerdic's avatar
cerdic a validé
 */
function spip_initialisation($pi=NULL, $pa=NULL, $ti=NULL, $ta=NULL) {
	spip_initialisation_core($pi,$pa,$ti,$ta);
	spip_initialisation_suite();
}

cerdic's avatar
cerdic a validé
/**
marcimat's avatar
marcimat a validé
 * Fonction d'initialisation, appellée dans inc_version ou mes_options
marcimat's avatar
marcimat a validé
 * Elle définit les répertoires et fichiers non partageables
 * et indique dans $test_dirs ceux devant être accessibles en écriture
 * mais ne touche pas à cette variable si elle est déjà définie
 * afin que mes_options.php puisse en spécifier d'autres.
marcimat's avatar
marcimat a validé
 * Elle définit ensuite les noms des fichiers et les droits.
 * Puis simule un register_global=on sécurisé.
cerdic's avatar
cerdic a validé
 *
marcimat's avatar
marcimat a validé
 * @param string $pi Répertoire permanent inaccessible
 * @param string $pa Répertoire permanent accessible
 * @param string $ti Répertoire temporaire inaccessible
 * @param string $ta Répertoire temporaire accessible
cerdic's avatar
cerdic a validé
 */
cerdic's avatar
cerdic a validé
function spip_initialisation_core($pi=NULL, $pa=NULL, $ti=NULL, $ta=NULL) {
	static $too_late = 0;
	if ($too_late++) return;
	// Declaration des repertoires

	// le nom du repertoire plugins/ activables/desactivables
	if (!defined('_DIR_PLUGINS')) define('_DIR_PLUGINS', _DIR_RACINE . "plugins/");

	// le nom du repertoire des extensions/ permanentes du core, toujours actives
	if (!defined('_DIR_PLUGINS_DIST')) define('_DIR_PLUGINS_DIST', _DIR_RACINE . "plugins-dist/");
kent1's avatar
kent1 a validé

	// le nom du repertoire des librairies
	if (!defined('_DIR_LIB')) define('_DIR_LIB', _DIR_RACINE . "lib/");
	if (!defined('_DIR_IMG')) define('_DIR_IMG', $pa);
	if (!defined('_DIR_LOGOS')) define('_DIR_LOGOS', $pa);
	if (!defined('_DIR_IMG_ICONES')) define('_DIR_IMG_ICONES', _DIR_LOGOS . "icones/");
	if (!defined('_DIR_DUMP')) define('_DIR_DUMP', $ti . "dump/");
	if (!defined('_DIR_SESSIONS')) define('_DIR_SESSIONS', $ti . "sessions/");
	if (!defined('_DIR_TRANSFERT')) define('_DIR_TRANSFERT', $ti . "upload/");
	if (!defined('_DIR_CACHE')) define('_DIR_CACHE', $ti . "cache/");
	if (!defined('_DIR_CACHE_XML')) define('_DIR_CACHE_XML', _DIR_CACHE . "xml/");
	if (!defined('_DIR_SKELS')) define('_DIR_SKELS',  _DIR_CACHE . "skel/");
	if (!defined('_DIR_AIDE')) define('_DIR_AIDE',  _DIR_CACHE . "aide/");
	if (!defined('_DIR_TMP')) define('_DIR_TMP', $ti);
	if (!defined('_DIR_VAR')) define('_DIR_VAR', $ta);
	if (!defined('_DIR_ETC')) define('_DIR_ETC', $pi);
	if (!defined('_DIR_CONNECT')) define('_DIR_CONNECT', $pi);
	if (!defined('_DIR_CHMOD')) define('_DIR_CHMOD', $pi);

	if (!isset($GLOBALS['test_dirs']))
	  // Pas $pi car il est bon de le mettre hors ecriture apres intstall
	  // il sera rajoute automatiquement si besoin a l'etape 2 de l'install
		$GLOBALS['test_dirs'] =  array($pa, $ti, $ta);
	if (!defined('_CACHE_PLUGINS_PATH')) define('_CACHE_PLUGINS_PATH', _DIR_CACHE . "charger_plugins_chemins.php");
	if (!defined('_CACHE_PLUGINS_OPT')) define('_CACHE_PLUGINS_OPT', _DIR_CACHE . "charger_plugins_options.php");
	if (!defined('_CACHE_PLUGINS_FCT')) define('_CACHE_PLUGINS_FCT', _DIR_CACHE . "charger_plugins_fonctions.php");
	if (!defined('_CACHE_PIPELINES')) define('_CACHE_PIPELINES',  _DIR_CACHE."charger_pipelines.php");
	if (!defined('_CACHE_CHEMIN')) define('_CACHE_CHEMIN',  _DIR_CACHE."chemin.txt");

	# attention .php obligatoire pour ecrire_fichier_securise
	if (!defined('_FILE_META')) define('_FILE_META', $ti . 'meta_cache.php');
	if (!defined('_DIR_LOG')) define('_DIR_LOG', _DIR_TMP . 'log/');
	if (!defined('_FILE_LOG')) define('_FILE_LOG', 'spip');
	if (!defined('_FILE_LOG_SUFFIX')) define('_FILE_LOG_SUFFIX', '.log');
	// Le fichier de connexion a la base de donnees
	// tient compte des anciennes versions (inc_connect...)
	if (!defined('_FILE_CONNECT_INS')) define('_FILE_CONNECT_INS', 'connect');
	if (!defined('_FILE_CONNECT')) define('_FILE_CONNECT',
		(@is_readable($f = _DIR_CONNECT . _FILE_CONNECT_INS . '.php') ? $f
	:	(@is_readable($f = _DIR_RESTREINT . 'inc_connect.php') ? $f
	// Le fichier de reglages des droits
	if (!defined('_FILE_CHMOD_INS')) define('_FILE_CHMOD_INS', 'chmod');
	if (!defined('_FILE_CHMOD')) define('_FILE_CHMOD',
		(@is_readable($f = _DIR_CHMOD . _FILE_CHMOD_INS . '.php') ? $f
	if (!defined('_FILE_LDAP')) define('_FILE_LDAP', 'ldap.php');
	if (!defined('_FILE_TMP_SUFFIX')) define('_FILE_TMP_SUFFIX', '.tmp.php');
	if (!defined('_FILE_CONNECT_TMP')) define('_FILE_CONNECT_TMP', _DIR_CONNECT . _FILE_CONNECT_INS . _FILE_TMP_SUFFIX);
	if (!defined('_FILE_CHMOD_TMP')) define('_FILE_CHMOD_TMP', _DIR_CHMOD . _FILE_CHMOD_INS . _FILE_TMP_SUFFIX);
	// Definition des droits d'acces en ecriture
	if (!defined('_SPIP_CHMOD') AND _FILE_CHMOD)
		include_once _FILE_CHMOD;

	// Se mefier des fichiers mal remplis!
	if (!defined('_SPIP_CHMOD')) define('_SPIP_CHMOD', 0777);
kent1's avatar
kent1 a validé

	if (!defined('_DEFAULT_CHARSET')) {
		/** Le charset par défaut lors de l'installation */
		define('_DEFAULT_CHARSET', 'utf-8');
	}
	if (!defined('_ROOT_PLUGINS')) define('_ROOT_PLUGINS', _ROOT_RACINE . "plugins/");
	if (!defined('_ROOT_PLUGINS_DIST')) define('_ROOT_PLUGINS_DIST', _ROOT_RACINE . "plugins-dist/");
	if (!defined('_ROOT_PLUGINS_SUPPL') && defined('_DIR_PLUGINS_SUPPL') && _DIR_PLUGINS_SUPPL) define('_ROOT_PLUGINS_SUPPL', _ROOT_RACINE . str_replace(_DIR_RACINE,'',_DIR_PLUGINS_SUPPL));
cerdic's avatar
cerdic a validé

	if (!defined('_MAX_LOG')) define('_MAX_LOG', 100);
cerdic's avatar
cerdic a validé
	// Sommes-nous dans l'empire du Mal ?
	// (ou sous le signe du Pingouin, ascendant GNU ?)
	if (isset($_SERVER['SERVER_SOFTWARE']) AND strpos($_SERVER['SERVER_SOFTWARE'], '(Win') !== false){
		if (!defined('_OS_SERVEUR')) define('_OS_SERVEUR', 'windows');
		if (!defined('_SPIP_LOCK_MODE')) define('_SPIP_LOCK_MODE',1); // utiliser le flock php
cerdic's avatar
cerdic a validé
	}
	else {
		if (!defined('_OS_SERVEUR')) define('_OS_SERVEUR', '');
		if (!defined('_SPIP_LOCK_MODE')) define('_SPIP_LOCK_MODE',1); // utiliser le flock php
		#if (!defined('_SPIP_LOCK_MODE')) define('_SPIP_LOCK_MODE',2); // utiliser le nfslock de spip mais link() est tres souvent interdite
cerdic's avatar
cerdic a validé
	}
kent1's avatar
kent1 a validé

	// Langue par defaut
	if (!defined('_LANGUE_PAR_DEFAUT')) define('_LANGUE_PAR_DEFAUT','fr');

cerdic's avatar
cerdic a validé
	//
	// Module de lecture/ecriture/suppression de fichiers utilisant flock()
	// (non surchargeable en l'etat ; attention si on utilise include_spip()
	// pour le rendre surchargeable, on va provoquer un reecriture
	// systematique du noyau ou une baisse de perfs => a etudier)
	include_once _ROOT_RESTREINT . 'inc/flock.php';
cerdic's avatar
cerdic a validé

	// charger tout de suite le path et son cache
cerdic's avatar
cerdic a validé
	load_path_cache();

cerdic's avatar
cerdic a validé
	// *********** traiter les variables ************

	//
	// Securite
	//

	// Ne pas se faire manger par un bug php qui accepte ?GLOBALS[truc]=toto
	if (isset($_REQUEST['GLOBALS'])) die();
	// nettoyer les magic quotes \' et les caracteres nuls %00
	spip_desinfecte($_GET);
	spip_desinfecte($_POST);
	spip_desinfecte($_COOKIE);
	spip_desinfecte($_REQUEST);

	// Par ailleurs on ne veut pas de magic_quotes au cours de l'execution
	if(version_compare(PHP_VERSION, '5.3.0', '<')){
		set_magic_quotes_runtime(0);
	}
cerdic's avatar
cerdic a validé

	// Si les variables sont passees en global par le serveur,
	// il faut faire quelques verifications de base
	$avertir_register_globals = false;
cerdic's avatar
cerdic a validé
	if (test_valeur_serveur(@ini_get('register_globals'))) {
		// ne pas desinfecter les globales en profondeur car elle contient aussi les