Skip to content
Extraits de code Groupes Projets
utils.php 95,6 ko
Newer Older
marcimat's avatar
marcimat a validé
 *
 *  - `0` si un job est à traiter
 *  - `null` si la queue n'est pas encore initialisée
function queue_sleep_time_to_next_job($force = null) {
	static $queue_next_job_time = -1;
		$queue_next_job_time = $force;
		if (!defined('_JQ_NEXT_JOB_TIME_FILENAME')) {
			define('_JQ_NEXT_JOB_TIME_FILENAME', _DIR_TMP . "job_queue_next.txt");
		}
		// utiliser un cache memoire si dispo
		if (function_exists("cache_get") and defined('_MEMOIZE_MEMORY') and _MEMOIZE_MEMORY) {
			$queue_next_job_time = cache_get(_JQ_NEXT_JOB_TIME_FILENAME);
			if (lire_fichier(_JQ_NEXT_JOB_TIME_FILENAME, $contenu)) {
				$queue_next_job_time = intval($contenu);
		$_SERVER['REQUEST_TIME'] = time();
	return $queue_next_job_time - $_SERVER['REQUEST_TIME'];
marcimat's avatar
marcimat a validé
/**
 * Transformation XML des `&` en `&`
 * 
 * @pipeline post_typo
 * @param string $u
 * @return string
 */
function quote_amp($u) {
	return preg_replace(
Fil's avatar
Fil a validé
		"/&(?![a-z]{0,4}\w{2,3};|#x?[0-9a-f]{2,6};)/i",

/**
 * Produit une balise `<script>` valide
 *
 * @example
 *     ```
 *     echo http_script('alert("ok");');
 *     echo http_script('','js/jquery.js');
 *     ```
 * @param string $script
 *     Code source du script
 * @param string $src
 *     Permet de faire appel à un fichier javascript distant
 * @param string $noscript
 *     Contenu de la balise  `<noscript>`
 * @return string
 *     Balise HTML `<script>` et son contenu
function http_script($script, $src = '', $noscript = '') {
	static $done = array();
		$done[$src] = true;
		$src = find_in_path($src, _JAVASCRIPT);
		$script = ("/*<![CDATA[*/\n" .
			preg_replace(',</([^>]*)>,', '<\/\1>', $script) .
			"/*]]>*/");
	}
	if ($noscript) {
		$noscript = "<noscript>\n\t$noscript\n</noscript>\n";
		? "<script type='text/javascript'$src>$script</script>$noscript"
		: '';

/**
 * Sécurise du texte à écrire dans du PHP ou du Javascript.
 * Transforme n'importe quel texte en une chaîne utilisable
 * en PHP ou Javascript en toute sécurité, à l'intérieur d'apostrophes
 * simples (`'` uniquement ; pas `"`)
 *
 * Utile particulièrement en filtre dans un squelettes
 * pour écrire un contenu dans une variable JS ou PHP.
 *
 * Échappe les apostrophes (') du contenu transmis.
 *
 * @link http://www.spip.net/4281
 * @example
 *     PHP dans un squelette
 *     ```
 *     $x = '[(#TEXTE|texte_script)]';
 *     ```
 *
 *     JS dans un squelette (transmettre une chaîne de langue)
 *     ```
 *     $x = '<:afficher_calendrier|texte_script:>';
 *     ```
 *
 * @filtre
 * @param string $texte
 *     Texte à échapper
 * @return string
 *     Texte échappé
function texte_script($texte) {
	return str_replace('\'', '\\\'', str_replace('\\', '\\\\', $texte));
}


/**
 * 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 :
			_DIR_RACINE . ':' .
			_DIR_RACINE . 'squelettes-dist/:' .
			_DIR_RACINE . 'prive/:' .
Fil's avatar
Fil a validé
		// Ajouter squelettes/
		if (@is_dir(_DIR_RACINE . 'squelettes')) {
			$path = _DIR_RACINE . 'squelettes/:' . $path;
		}
Fil's avatar
Fil a validé
		foreach (explode(':', $path) as $dir) {
Fil's avatar
Fil a validé
				$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));
		if (reset($path_base) == _DIR_RACINE . 'squelettes/') {
		}
		$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);
			}
		}
		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
	}
	static $themes = null;
cerdic's avatar
cerdic a validé
		// si pas encore definie
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 = $GLOBALS['visiteur_session']['prefs'];
cerdic's avatar
cerdic a validé
			$prefs = unserialize($GLOBALS['visiteur_session']['prefs']);
cerdic's avatar
cerdic a validé
		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.
	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)) {
	// 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) {
		list($icone, $fonction) = $icone_renommer($icone, "");
		if (file_exists($icone)) {
cerdic's avatar
cerdic a validé
			return $icone;
cerdic's avatar
cerdic a validé
	}
//
// 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.
 *
 * @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) {
	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;
			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é
	if ($a !== false) {
		$dirname .= substr($file, 0, ++$a);
		$file = substr($file, $a);
	foreach (creer_chemin() as $dir) {
		if (!isset($dirs[$a = $dir . $dirname])) {
			$dirs[$a] = (is_dir(_ROOT_CWD . $a) || !$a);
		}
cerdic's avatar
cerdic a validé
			if (file_exists(_ROOT_CWD . ($a .= $file))) {
cerdic's avatar
cerdic a validé
					include_once _ROOT_CWD . $a;
					$inc[$dirname][$file] = $inc[''][$dirname . $file] = true;
				}
					// si le chemin n'a pas encore ete charge, ne pas lever le flag, ne pas cacher
				return $GLOBALS['path_files'][$GLOBALS['path_sig']][$dirname][$file] = $GLOBALS['path_files'][$GLOBALS['path_sig']][''][$dirname . $file] = $a;
esj's avatar
esj a validé
		}
		spip_log("include_spip $dirname$file non trouve");
			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é

		// si le chemin n'a pas encore ete charge, ne pas lever le flag, ne pas cacher
		if (is_null($GLOBALS['path_files'])) {
			return false;
		}
	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é
	$GLOBALS['path_files'] = array();
	spip_unlink(_CACHE_CHEMIN);
}
	// charger le path des plugins
		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)) {
cerdic's avatar
cerdic a validé
	}
cerdic's avatar
cerdic a validé
	if (defined('_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();
	// cas borderline si dans mes_options on appelle redirige_par_entete qui utilise _T et charge un fichier de langue
	// on a pas encore inclus flock.php
	if (!function_exists('preg_files')) {
		include_once _ROOT_RESTREINT . 'inc/flock.php';
	}

	foreach (creer_chemin() as $d) {
			$liste = preg_files($f, $pattern, $maxfiles - count($liste_fichiers), $recurs === true ? array() : $recurs);
				$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
					$liste_fichiers[$nom] = $chemin;
marcimat's avatar
marcimat a validé
/**
 * Prédicat sur les scripts de ecrire qui n'authentifient pas par cookie
 * @param string $nom
 * @return bool
 */
function autoriser_sans_cookie($nom) {
	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 (!$entite) {
			return '';
		}
		if (!function_exists('generer_url_ecrire_objet')) {
			include_spip('inc/urls');
		}
		$res = generer_url_ecrire_objet($entite, $id, $args, $ancre, false);
		if ($type === null) {
			$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

		// mais d'abord il faut tester le cas des urls sur une
		// base distante
		if (is_string($public)

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

	// Sinon c'est un raccourci ou compat SPIP < 2
	if (!function_exists($f = 'generer_url_' . $entite)) {
	if ($f) {
		$url = $f($id, $args, $ancre);
			$url .= strstr($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);
	}

// http://code.spip.net/@urls_connect_dist
function urls_connect_dist($i, &$entite, $args = '', $ancre = '', $public = null) {
	include_spip('base/connect_sql');
	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)) {
		for ($i = 0; $i < strlen($url); $i++) {
			if (ord($a = $url[$i]) > 127) {
// 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é
	}

/**
 * Tester qu'une variable d'environnement est active
 * Sur certains serveurs, la valeur 'Off' tient lieu de false dans certaines
 * variables d'environnement comme $_SERVER[HTTPS] ou ini_get(register_globals)
 *
 * @param string|bool $truc
 *     La valeur de la variable d'environnement
 * @return bool
 *     true si la valeur est considérée active ; false sinon.
function test_valeur_serveur($truc) {
	return (strtolower($truc) !== 'off');

//
// Fonctions de fabrication des URL des scripts de Spip
//
amemo's avatar
amemo a validé
 * Calcule l'url de base du site
 *
 * Calcule l'URL de base du site, en priorité sans se fier à la méta (adresse_site) qui
 * peut être fausse (sites avec plusieurs noms d’hôtes, déplacements, erreurs).
 * En dernier recours, lorsqu'on ne trouve rien, on utilise adresse_site comme fallback.
amemo's avatar
amemo a validé
 * @note
 *     La globale `$profondeur_url` doit être initialisée de manière à
 *     indiquer le nombre de sous-répertoires de l'url courante par rapport à la
 *     racine de SPIP : par exemple, sur ecrire/ elle vaut 1, sur sedna/ 1, et à
 *     la racine 0. Sur url/perso/ elle vaut 2
amemo's avatar
amemo a validé
 *    - si non renseignée : retourne l'url pour la profondeur $GLOBALS['profondeur_url']
 *    - si int : indique que l'on veut l'url pour la profondeur indiquée
 *    - si bool : retourne le tableau static complet
 *    - si array : réinitialise le tableau static complet avec la valeur fournie
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($_SERVER["SCRIPT_URI"])
		and substr($_SERVER["SCRIPT_URI"], 0, 5) == 'https'
	) {
		$http = 'https';
	} elseif (
		isset($_SERVER['HTTPS'])
		and test_valeur_serveur($_SERVER['HTTPS'])
	) {
		$http = 'https';
	}

	// note : HTTP_HOST contient le :port si necessaire
	$host = $_SERVER['HTTP_HOST'];
	// si on n'a pas trouvé d'hôte du tout, en dernier recours on utilise adresse_site comme fallback
	if (is_null($host) and isset($GLOBALS['meta']['adresse_site'])) {
		$host = $GLOBALS['meta']['adresse_site'];
		if ($scheme = parse_url($host, PHP_URL_SCHEME)) {
			$http = $scheme;
			$host = str_replace("{$scheme}://", '', $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 (isset($_SERVER['REQUEST_URI'])) {
			$GLOBALS['REQUEST_URI'] = $_SERVER['REQUEST_URI'];
		} else {
			$GLOBALS['REQUEST_URI'] = $_SERVER['PHP_SELF'];
			if ($_SERVER['QUERY_STRING']
			) {
				$GLOBALS['REQUEST_URI'] .= '?' . $_SERVER['QUERY_STRING'];
			}
cerdic's avatar
cerdic a validé
		}
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);
	# supprimer la chaine de GET
	list($myself) = explode('?', $myself);
	// vieux mode HTTP qui envoie après le nom de la methode l'URL compléte
	// protocole, "://", nom du serveur avant le path dans _SERVER["REQUEST_URI"]
	if (strpos($myself,'://') !== false) {
		$myself = explode('://',$myself);
		array_shift($myself);
		$myself = implode('://',$myself);
		$myself = explode('/',$myself);
		array_shift($myself);
		$myself = implode('/',$myself);
	}
	$url = join('/', array_slice(explode('/', $myself), 0, -1 - $prof)) . '/';

	$url = $http . '://' . rtrim($host, '/') . '/' . ltrim($url, '/');
Fil's avatar
Fil a validé

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;
	} else {
		if (!is_string($rel)) {
			$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);
		$args = "?exec=$script" . (!$args ? '' : "&$args");
	} elseif ($args) {
		$args = "?$args";
	}
	if ($ancre) {
		$args .= "#$ancre";
	}

	return $rel . ($no_entities ? $args : str_replace('&', '&amp;', $args));
marcimat's avatar
marcimat a validé
/**
 * Permet d'ajouter lien vers une page privée à un paramètre d'url (déprécié)
 *
 *     ```
 *     // deprecié
 *     $h = generer_url_ecrire('article', "id_article=$id_article&redirect=" . generer_url_retour('articles'));
 *     // utiliser
 *     $h = generer_url_ecrire('article');
 *     $h = parametre_url($h, 'id_article', $id_article);
 *     $h = parametre_url($h, 'redirect', generer_url_ecrire('articles'));
 *     ```
 *
 * @deprecated Utiliser parametre_url() et generer_url_ecrire()
 * @see parametre_url()
 * @see generer_url_ecrire()
 *
 * @param string $script
 * @param string $args
 * @return string
 */
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
function get_spip_script($default = '') {
	# cas define('_SPIP_SCRIPT', '');
Fil's avatar
Fil a validé
		return _SPIP_SCRIPT;
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();
	}
	if ($script) {
		$action = parametre_url($action, _SPIP_PAGE, $script, '&');