diff --git a/.gitattributes b/.gitattributes
index bd2ac63c368c84dbb00da398c4c31d0b84f77ea7..9e9a7182a919bca3da58b8dc139c7bf620cf3149 100644
--- a/.gitattributes
+++ b/.gitattributes
@@ -336,7 +336,6 @@ ecrire/img_pack/xml.gif -text
 ecrire/inc_agenda.php -text
 ecrire/inc_ajax.php -text
 ecrire/inc_auteur_voir.php -text
-ecrire/inc_barre.php -text
 ecrire/inc_boutons.php -text
 ecrire/inc_cookie.php -text
 ecrire/inc_distant.php -text
diff --git a/ecrire/exec_naviguer.php b/ecrire/exec_naviguer.php
index 4db4ad745b26a2728d0640b3697cab398d12f02a..432196249aa8c249add627e5454691d7fa499181 100644
--- a/ecrire/exec_naviguer.php
+++ b/ecrire/exec_naviguer.php
@@ -258,7 +258,8 @@ if ($id_rubrique>0 AND $GLOBALS['meta']['multi_rubriques'] == 'oui' AND ($GLOBAL
 
 	echo debut_block_invisible('languesrubrique');
 	echo "<div class='verdana2' align='center'>";
-	echo menu_langues('changer_lang', $langue_rubrique, '', $langue_parent, new Link(generer_url_ecrire("naviguer","action=coloniser&id_rubrique=$id_rubrique")));
+	echo menu_langues('changer_lang', $langue_rubrique, '', $langue_parent,
+		parametre_url(self(),'action','coloniser'));
 	echo "</div>\n";
 	echo fin_block();
 
diff --git a/ecrire/inc_barre.php b/ecrire/inc_barre.php
deleted file mode 100755
index a244932746fd6adf4752e31657a5b25347409720..0000000000000000000000000000000000000000
--- a/ecrire/inc_barre.php
+++ /dev/null
@@ -1,28 +0,0 @@
-<?php
-
-/***************************************************************************\
- *  SPIP, Systeme de publication pour l'internet                           *
- *                                                                         *
- *  Copyright (c) 2001-2006                                                *
- *  Arnaud Martin, Antoine Pitrou, Philippe Riviere, Emmanuel Saint-James  *
- *                                                                         *
- *  Ce programme est un logiciel libre distribue sous licence GNU/GPL.     *
- *  Pour plus de details voir le fichier COPYING.txt ou l'aide en ligne.   *
-\***************************************************************************/
-
-if (!defined("_ECRIRE_INC_VERSION")) return;
-
-function afficher_barre($champ, $forum=false) {
-	global $barre_typo;
-	tester_variable("barre_typo", "spip");
-	if($barre_typo != '' AND file_exists(_DIR_RESTREINT."inc_barre_$barre_typo.php" )) {
-		include_ecrire("inc_barre_$barre_typo");
-		$f = "afficher_barre_$barre_typo";
-		if(function_exists($f)) {
-			return $f($champ, $forum);
-		}
-	}
-	return "";
-}
-
-?>
diff --git a/ecrire/inc_invalideur.php b/ecrire/inc_invalideur.php
index a4dcaabd0a73cdf48c2e8fb613893e828d4c6805..cf70e6493aafe9b7eaa4cdc6055bc6a47f5eb415 100644
--- a/ecrire/inc_invalideur.php
+++ b/ecrire/inc_invalideur.php
@@ -32,34 +32,39 @@ function ajouter_invalideur($type, $valeur, $code) {
 //
 // Calcul des pages : noter dans la base les liens d'invalidation
 //
-function maj_invalideurs ($fichier, $invalideurs, $delais) {
-	$fichier = addslashes($fichier); #parano
-	if ($fichier == '') return;	// ne pas noter les POST et les delais=0
-	spip_query("DELETE FROM spip_caches WHERE fichier='$fichier'");
-
-	// invalidation des forums (l'invalideur est : 'id_forum/a23')
-	insere_invalideur($invalideurs['id_forum'], 'id_forum', $fichier);
-
-	// invalidation des petitions et autres
-	// (l'invalideur est par exemple : 'varia/petition')
-	insere_invalideur($invalideurs['varia'], 'varia', $fichier);
-
-	// invalidation du reste - experimental a activer dans mes_options
-	if ($GLOBALS['invalider_caches']) {
-		insere_invalideur($invalideurs['id_article'],'id_article', $fichier);
-		insere_invalideur($invalideurs['id_breve'], 'id_breve', $fichier);
-		insere_invalideur($invalideurs['id_rubrique'],'id_rubrique', $fichier);
-		insere_invalideur($invalideurs['id_syndic'],'id_syndic', $fichier);
-	}
+function maj_invalideurs ($fichier, &$page, $duree) {
+	// ne pas noter les POST et les delais=0
+	if ($fichier == '') return;
+
+	// Supprimer les anciens invalideurs
+	$f = str_replace('.gz', '', $fichier);
+	spip_query("DELETE FROM spip_caches WHERE fichier='$f' OR fichier='$f.gz'");
+
+	// Creer un invalideur 't' nous informant de la date d'expiration
+	// et de la taille du fichier cache
+	# Note : on ajoute 3600s pour eviter toute concurrence
+	# entre un invalideur et un appel public de page
+	$bedtime = time() + $duree + 3600;
+	$taille = @filesize(_DIR_CACHE . $fichier);
+	spip_query("INSERT IGNORE INTO spip_caches (fichier,id,type,taille)
+	VALUES ('".addslashes($fichier)."','$bedtime','t','$taille')");
+
+	// invalidations
+	insere_invalideur($page['invalideurs'], $fichier);
 }
 
-function insere_invalideur($a, $type, $fichier) {
-	if (is_array($a)) {
-		$values = array();
-		foreach($a as $k => $v)
-			$values[] = "('$fichier', '$type/$k')";
-		spip_query ("INSERT IGNORE INTO spip_caches
-			(fichier, id) VALUES " . join(", ", $values));
+// pour les forums l'invalideur est : 'id_forum/a23'
+// pour les petitions et autres, l'invalideur est par exemple :
+// 'varia/pet60'
+function insere_invalideur($inval, $fichier) {
+	foreach ($inval as $type => $a) {
+		if (is_array($a)) {
+			$values = array();
+			foreach($a as $k => $v)
+				$values[] = "('$fichier', '$type/$k')";
+			spip_query ("INSERT IGNORE INTO spip_caches
+				(fichier, id) VALUES " . join(", ", $values));
+		}
 	}
 }
 
diff --git a/ecrire/inc_lang.php b/ecrire/inc_lang.php
index 6383320a4641fd312c4cf0fa39fdda485cecea87..bfa72f0c692ecaa319486b9535f69074e4168825 100644
--- a/ecrire/inc_lang.php
+++ b/ecrire/inc_lang.php
@@ -243,33 +243,28 @@ function menu_langues($nom_select = 'var_lang', $default = '', $texte = '', $her
 
 	if (!$couleur_foncee) $couleur_foncee = '#044476';
 
-	if (!$lien) $lien = $GLOBALS['clean_link'];
+	if (!$lien)
+		$lien = self();
 
 	if ($nom_select == 'changer_lang') {
+		$lien = parametre_url($lien, 'changer_lang', '');
+		$lien = parametre_url($lien, 'url', '');
 		$cible = '';
-		if (is_object($lien)) {
-			$lien->delvar('changer_lang');
-			$lien->delvar('url');
-			$lien = $lien->getUrl();
-		    }
 	} else {
-		$args = "";
-		if (!_DIR_RESTREINT) {
-			$cible = _DIR_RESTREINT_ABS . 
-			  (is_object($lien) ? $lien->getUrl() : $lien);
+		if (_DIR_RESTREINT) {
+			$cible = $lien;
+		} else {
+			$cible = _DIR_RESTREINT_ABS . $lien;
 			if (_FILE_CONNECT) {
-			  include_ecrire('inc_session');
-			  $args = "id_auteur=$connect_id_auteur&valeur=".calculer_action_auteur('var_lang_ecrire', $connect_id_auteur);
+				include_ecrire('inc_session');
+				$args = "id_auteur=$connect_id_auteur&valeur=".calculer_action_auteur('var_lang_ecrire', $connect_id_auteur);
 			}
-
-		} else {
-			$cible = $lien->getUrl();
 		}
-		$lien = generer_url_public("spip_cookie", $args);
+		$lien = generer_url_action('cookie', $args);
 	}
 
 	return "<form action='$lien' method='post' style='margin:0px; padding:0px;'>"
-	  . (!$cible ? '' : "<input type='hidden' name='url' value='".quote_amp($cible)."' />")
+	  . (!$cible ? '' : "<input type='hidden' name='url' value='$cible' />")
 	  . $texte
 	  . "<select name='$nom_select' "
 	  . (_DIR_RESTREINT ?
@@ -279,7 +274,7 @@ function menu_langues($nom_select = 'var_lang', $default = '', $texte = '', $her
 	       . "; max-height: 24px; border: 1px solid white; color: white; width: 100px;'") :
 	      "class='fondl'"))
 	  . "\nonchange=\"document.location.href='"
-	  . $lien . (!$cible ? "" : ((strpos($lien,'?') ? '&amp;' : '?') . 'url=' . urlencode($cible)))
+	  . parametre_url($lien, 'url', str_replace('&amp;', '&', $cible))
 	  ."&amp;$nom_select='+this.options[this.selectedIndex].value\">\n"
 	  . $ret
 	  . "</select>\n"
@@ -298,13 +293,16 @@ function liste_options_langues($nom_select, $default='', $herit='') {
 	if (count($langues) <= 1) return '';
 	$ret = '';
 	sort($langues);
-	while (list(, $l) = each ($langues)) {
+	foreach ($langues as $l) {
 		$selected = ($l == $default) ? ' selected=\'selected\'' : '';
 		if ($l == $herit) {
 			$ret .= "<option class='maj-debut' style='font-weight: bold;' value='herit'$selected>"
 				.traduire_nom_langue($herit)." ("._T('info_multi_herit').")</option>\n";
 		}
-		else $ret .= "<option class='maj-debut' value='$l'$selected>".traduire_nom_langue($l)."</option>\n";
+		## ici ce serait bien de pouvoir choisir entre "langue par defaut"
+		## et "langue heritee"
+		else
+			$ret .= "<option class='maj-debut' value='$l'$selected>".traduire_nom_langue($l)."</option>\n";
 	}
 	return $ret;
 }
diff --git a/ecrire/inc_session.php b/ecrire/inc_session.php
index f7674632bc44ca6dd79f1bc0e812dd1846e00ac3..b274397813ac05731960c7caaad1d4a73911d519 100644
--- a/ecrire/inc_session.php
+++ b/ecrire/inc_session.php
@@ -27,8 +27,7 @@ $GLOBALS['auteur_session'] = '';
 // On verifie l'IP et le nom du navigateur
 //
 function hash_env() {
-	global $_SERVER;
-	return md5($_SERVER['REMOTE_ADDR'] . $_SERVER['HTTP_USER_AGENT']);
+	return md5($GLOBALS['ip'] . $_SERVER['HTTP_USER_AGENT']);
 }
 
 
diff --git a/ecrire/inc_texte.php b/ecrire/inc_texte.php
index d91f6cee797058da309d3e242540e7e3a6cece2e..e96a0d3aa164692d72e82d66bc4dfed0366478e0 100644
--- a/ecrire/inc_texte.php
+++ b/ecrire/inc_texte.php
@@ -16,20 +16,7 @@ if (!defined("_ECRIRE_INC_VERSION")) return;
 
 include_ecrire ("inc_filtres");
 
-//
-// Initialisation de quelques variables globales
-// (on peut les modifier globalement dans mes_fonctions,
-//  OU individuellement pour chaque type de page dans article, rubrique, etc.
-// cf doc...)
-//
-function tester_variable($nom_var, $val){
-	if (!isset($GLOBALS[$nom_var])) {
-		$GLOBALS[$nom_var] = $val;
-		return false;
-	}
-	return true;
-}
-
+// Verifier les variables de personnalisation
 tester_variable('debut_intertitre', "\n<h3 class=\"spip\">");
 tester_variable('fin_intertitre', "</h3>\n");
 tester_variable('ligne_horizontale', "\n<hr class=\"spip\" />\n");
@@ -42,19 +29,35 @@ tester_variable('compt_note', 0);
 tester_variable('nombre_surligne', 4);
 tester_variable('url_glossaire_externe', "http://@lang@.wikipedia.org/wiki/");
 
+// on initialise la puce ici car il serait couteux de faire le find_in_path()
+// a chaque hit, alors qu'on n'a besoin de cette valeur que lors du calcul
+function definir_puce() {
+	static $les_puces = array();
+
+	// Attention au sens, qui n'est pas defini de la meme facon dans
+	// l'espace prive (spip_lang est la langue de l'interface, lang_dir
+	// celle du texte) et public (spip_lang est la langue du texte)
+	include_ecrire('inc_lang');
+	$dir = _DIR_RESTREINT ?
+		lang_dir($GLOBALS['spip_lang']) : $GLOBALS['lang_dir'];
+	$p = ($dir == 'rtl') ? 'puce_rtl' : 'puce';
+
+	if (!isset($les_puces[$p])) {
+		tester_variable($p, 'AUTO');
+		if ($GLOBALS[$p] == 'AUTO') {
+			$img = find_in_path($p.'.gif', _DIR_IMG_PACK);
+			list(,,,$size) = @getimagesize($img);
+			$img = '<img src="'.$img.'" '
+				.$size.' alt="-" border="0" />';
+		} else
+			$img = $GLOBALS[$p];
+
+		$les_puces[$p] = $img;
+	}
 
-// On ne prend la $puce_rtl par defaut que si $puce n'a pas ete redefinie
-
-//if (!tester_variable('puce', "<li class='spip_puce' style='list-style-image: url(puce.gif)'>")) {
-$puce = _DIR_RESTREINT ?
-	find_in_path('puce.gif'): _DIR_IMG_PACK.'puce.gif';
-$puce_rtl = _DIR_RESTREINT ?
-	find_in_path('puce_rtl.gif'): _DIR_IMG_PACK.'puce_rtl.gif';
-if (!tester_variable('puce', "<img class='spip_puce' src='$puce' alt='-' />&nbsp;")) {
-	tester_variable('puce_rtl', "<img class='spip_puce' src='$puce_rtl' alt='-' />&nbsp;");
+	return $les_puces[$p];
 }
 
-
 //
 // Diverses fonctions essentielles
 //
@@ -929,16 +932,6 @@ function traiter_raccourcis($letexte) {
 		}
 	}
 
-	// Puce
-	if (!$lang_dir) {
-		include_ecrire('inc_lang');
-		$lang_dir = lang_dir($GLOBALS['spip_lang']);
-	}
-	if ($lang_dir == 'rtl' AND $GLOBALS['puce_rtl'])
-		$puce = $GLOBALS['puce_rtl'];
-	else
-		$puce = $GLOBALS['puce'];
-
 	// Harmoniser les retours chariot
 	$letexte = preg_replace(",\r\n?,", "\n", $letexte);
 
@@ -1084,6 +1077,10 @@ function traiter_raccourcis($letexte) {
 	if (ereg("\n-[*#]", $letexte))
 		$letexte = traiter_listes($letexte);
 
+	// Puce
+	if (strpos($letexte, "\n- ") !== false)
+		$puce = definir_puce();
+
 	// autres raccourcis
 	$cherche1 = array(
 		/* 0 */ 	"/\n(----+|____+)/",
diff --git a/ecrire/inc_utils.php b/ecrire/inc_utils.php
index c1015ed731a56c922688f9f76beb5666f39ea256..19d3f412daa9b5cda5589ea38f64a6a65aafc2f4 100644
--- a/ecrire/inc_utils.php
+++ b/ecrire/inc_utils.php
@@ -145,13 +145,13 @@ function spip_log($message, $logname='spip') {
 	if ($compteur++ > 100) return;
 
 	$pid = '(pid '.@getmypid().')';
-	if (!$ip = $GLOBALS['REMOTE_ADDR']) $ip = '-';
 
-	$message = date("M d H:i:s")." $ip $pid "
+	$message = date("M d H:i:s").' '.$GLOBALS['ip'].' '.$pid.' '
 		.preg_replace("/\n*$/", "\n", $message);
 
 	$logfile = _DIR_SESSIONS . $logname . '.log';
-	if (@file_exists($logfile) && (@filesize($logfile) > 10*1024)) {
+	if (@file_exists($logfile)
+	AND (!$s = @filesize($logfile) OR $s > 10*1024)) {
 		$rotate = true;
 		$message .= "[-- rotate --]\n";
 	}
@@ -284,16 +284,19 @@ function self($root = false) {
 	if (!$root)
 		$url = preg_replace(',^[^?]*/,', '', $url);
 
-	// ajouter le cas echeant les variables _POST
+	// ajouter le cas echeant les variables _POST['id_...']
 	foreach ($_POST as $v => $c)
 		if (substr($v,0,3) == 'id_')
 			$url = parametre_url($url, $v, $c, '&');
 
 	// supprimer les variables sans interet
-	if (!_DIR_RESTREINT)
-		preg_replace (',[?&]('
-		.'lang|set_options|set_couleur|set_disp|set_ecran|show_docs'
-		.')=[^&]*,i', '', $url);
+	if (!_DIR_RESTREINT) {
+		$url = preg_replace (',([?&])('
+		.'lang|set_options|set_couleur|set_disp|set_ecran|show_docs|'
+		.'changer_lang|var_lang|action)=[^&]*,i', '\1', $url);
+		$url = preg_replace(',([?&])[&]+,', '\1', $url);
+		$url = preg_replace(',[&]$,', '\1', $url);
+	}
 
 	// eviter les hacks
 	$url = htmlspecialchars($url);
@@ -773,7 +776,7 @@ function generer_url_action($script, $args="", $no_entities=false) {
 
 
 // Dirty hack contre le register_globals a 'Off' (PHP 4.1.x)
-// A remplacer (un jour!) par une gestion propre des variables admissibles ;-)
+// A remplacer (bientot ?) par une gestion propre des variables admissibles ;-)
 // Attention pour compatibilite max $_GET n'est pas superglobale
 // NB: c'est une fonction de maniere a ne pas pourrir $GLOBALS
 function spip_register_globals() {
@@ -785,13 +788,7 @@ function spip_register_globals() {
 
 		# ecrire/inc_auth
 		'REMOTE_USER',
-		'PHP_AUTH_USER', 'PHP_AUTH_PW',
-
-		# ecrire/inc_texte
-		'debut_intertitre', 'fin_intertitre', 'ligne_horizontale',
-		'ouvre_ref', 'ferme_ref', 'ouvre_note', 'ferme_note',
-		'les_notes', 'compt_note', 'nombre_surligne',
-		'url_glossaire_externe', 'puce', 'puce_rtl'
+		'PHP_AUTH_USER', 'PHP_AUTH_PW'
 	);
 
 	// Liste des variables (contexte) dont on refuse qu'elles soient cookie
@@ -810,40 +807,22 @@ function spip_register_globals() {
 	if (@ini_get('register_globals')) {
 		foreach ($refuse_gpc as $var) {
 			if (isset($GLOBALS[$var])) {
-				foreach (array('_GET', '_POST', '_COOKIE') as $_table) {
-					if (
-					// demande par le client
-					isset ($GLOBALS[$_table][$var])
-					// et pas modifie par les fichiers d'appel
-					AND $GLOBALS[$_table][$var] == $GLOBALS[$var]
-					) // On ne sait pas si c'est un hack
-					{
-						# REMOTE_USER ou fond, c'est grave ;
-						# pour le reste (cookie 'lang', par exemple), simplement
-						# interdire la mise en cache de la page produite
-						switch ($var) {
-							case 'REMOTE_USER':
-							case 'fond':
-								die ("$var interdite");
-								break;
-							default:
-								define ('spip_interdire_cache', true);
-						}
-					}
-				}
+				if (
+				// demande par le client
+				isset ($_REQUEST[$var])
+				// et pas modifie par les fichiers d'appel
+				AND $GLOBALS[$_table][$var] == $GLOBALS[$var]
+				) // Alors on ne sait pas si c'est un hack
+					die ("$var interdite");
 			}
 		}
 		foreach ($refuse_c as $var) {
 			if (isset($GLOBALS[$var])) {
-				foreach (array('_COOKIE') as $_table) {
-					if (
-					// demande par le client
-					isset ($GLOBALS[$_table][$var])
-					// et pas modifie par les fichiers d'appel
-					AND $GLOBALS[$_table][$var] == $GLOBALS[$var]
-					)
-						define ('spip_interdire_cache', true);
-				}
+				if (
+				isset ($_COOKIE[$var])
+				AND $_COOKIE[$var] == $GLOBALS[$var]
+				)
+					define ('spip_interdire_cache', true);
 			}
 		}
 	}
@@ -863,6 +842,19 @@ function spip_register_globals() {
 	}
 }
 
+//
+// Gerer les variables de personnalisation, qui peuvent provenir
+// des fichiers d'appel, en verifiant qu'elles n'ont pas ete passees
+// par le visiteur (sinon, pas de cache)
+//
+function tester_variable($var, $val){
+	if (!isset($GLOBALS[$var])) {
+		$GLOBALS[$var] = $val;
+		return false;
+	}
+	if (isset($_REQUEST[$var]) AND $_REQUEST[$var] == $GLOBALS[$var])
+		die ("$var interdite");
+}
 
 // Annuler les magic quotes \' sur GET POST COOKIE et GLOBALS ;
 // supprimer aussi les eventuels caracteres nuls %00, qui peuvent tromper
diff --git a/ecrire/inc_version.php b/ecrire/inc_version.php
index 1e25fe2b22dbc1b8df6f16dcf1b2fbab68578004..ea7dfad84c21e6517d751bccaa82c648698780c2 100644
--- a/ecrire/inc_version.php
+++ b/ecrire/inc_version.php
@@ -66,6 +66,18 @@ $auto_compress = true;
 // 'standard': article.php3?id_article=123
 $type_urls = 'page';
 
+
+//
+// On note le numero IP du client dans la variable $ip
+//
+($ip = @$_SERVER['HTTP_X_FORWARDED_FOR']) OR $ip = @$_SERVER['REMOTE_ADDR'];
+
+// Pour renforcer la privacy, decommentez la ligne ci-dessous : SPIP ne pourra
+// alors conserver aucun numero IP, ni temporairement lors des visites (pour
+// gerer les statistiques ou dans spip.log), ni dans les forums (responsabilite)
+# $ip = substr(md5($ip),0,16);
+
+
 // creation des vignettes avec image magick en ligne de commande : mettre
 // le chemin complet '/bin/convert' (Linux) ou '/sw/bin/convert' (fink/Mac OS X)
 // Note : preferer GD2 ou le module php imagick s'ils sont disponibles
@@ -102,10 +114,10 @@ $ignore_auth_http = false;
 $ignore_remote_user = true; # methode obsolete et risquee
 
 // Faut-il "invalider" les caches quand on depublie ou modifie un article ?
-// (experimental)
-# NB: cette option ne concerne que articles,breves,rubriques et site
-# car les forums et petitions sont toujours invalidants.
-$invalider_caches = false;
+# NB: cette option ne concerne pas les forums et petitions qui sont toujours
+# invalidants. (fonctionnalite experimentale : decommenter ci-dessous)
+#$invalider_caches = 'id_article,id_breve,id_rubrique,id_syndic';
+$invalider_caches = '';
 
 // Quota : la variable $quota_cache, si elle est > 0, indique la taille
 // totale maximale desiree des fichiers contenus dans le CACHE/ ;
@@ -132,13 +144,13 @@ $traiter_math = 'tex';
 // Controler les dates des item dans les flux RSS ?
 $controler_dates_rss = true;
 
-
 //
-// Plugins
+// Pipelines & plugins
 //
-// (plus tard on fera une interface graphique qui les liste et permet de
-// les activer un par un, dans tel ordre, etc)
 # les pipeline standards (traitements derivables aka points d'entree)
+# ils seront compiles par la suite
+# note: un pipeline non reference se compile aussi, mais uniquement
+# lorsqu'il est rencontre
 $spip_pipeline = array(
 	'pre_typo' => '|extraire_multi',
 	'post_typo' => '|quote_amp',
diff --git a/ecrire/public-cache.php b/ecrire/public-cache.php
index 2dd4b545af15b421c2a3f6f598d4cd1682fd30b6..f107a61dfcf422012120e0c7d97e49ebf5d693ef 100644
--- a/ecrire/public-cache.php
+++ b/ecrire/public-cache.php
@@ -50,9 +50,15 @@ function generer_nom_fichier_cache($contexte, $fond) {
 	include_ecrire('inc_acces');
 	verifier_htaccess(_DIR_CACHE);
 
-	$gzip = $GLOBALS['flag_gz'] ? '.gz' : '';
+	return $subdir.$fichier_cache;
+}
 
-	return $subdir.$fichier_cache.$gzip;
+// Faut-il compresser ce cache ? A partir de 16ko ca vaut le coup
+function cache_gz($page) {
+	if ($GLOBALS['flag_gz'] AND strlen($page['texte']) > 16*1024)
+		return '.gz';
+	else
+		return '';
 }
 
 //
@@ -145,6 +151,7 @@ function cache_valide_autodetermine($chemin_cache, $page, $date) {
 	return cache_valide($chemin_cache, $contenu, $date);
 }
 
+
 // retourne le nom du fichier cache, 
 // et affecte le param use_cache avec un nombre N:
 // < 0 s'il faut calculer la page sans la mettre en cache
@@ -162,13 +169,16 @@ function determiner_cache(&$use_cache, $contexte, $fond) {
 		$use_cache = -1;
 		return array('','',0);
 	}
-	
+
 	$chemin_cache = generer_nom_fichier_cache($contexte, $fond);
+	if ($GLOBALS['flag_gz'] AND @file_exists($chemin_cache.'.gz'))
+		$chemin_cache .= '.gz';
 
-	// cas sans jamais de calcul pour raison interne
+	// HEAD : cas sans jamais de calcul pour raisons de performance
 	if ($_SERVER['REQUEST_METHOD'] == 'HEAD') {
 		$use_cache = 0;
-		return array($chemin_cache, @filemtime(_DIR_CACHE . $chemin_cache), 0);
+		return array($chemin_cache, array(),
+			@filemtime(_DIR_CACHE . $chemin_cache));
 	}
 
 	// Faut-il effacer des pages invalidees (en particulier ce cache-ci) ?
@@ -194,10 +204,9 @@ function determiner_cache(&$use_cache, $contexte, $fond) {
 	if (!$use_cache AND $ok) return array($chemin_cache, $page, $time);
 
 	// Si pas valide mais pas de connexion a la base, le garder quand meme
-
 	if (!$GLOBALS['db_ok']) {
 		if (file_exists(_DIR_CACHE . $chemin_cache))
-  			$use_cache = 0 ;
+			$use_cache = 0 ;
 		else {
 			spip_log("Erreur base de donnees, impossible utiliser $chemin_cache");
 			include_ecrire('inc_minipres');
@@ -208,9 +217,9 @@ function determiner_cache(&$use_cache, $contexte, $fond) {
 	return array((($use_cache < 0) ? "" : $chemin_cache), $page, $time);
 }
 
-// Passage par reference juste par souci d'economie
-
-function creer_cache(&$page, $chemin_cache, $duree) {
+// Creer le fichier cache
+# Passage par reference de $page par souci d'economie
+function creer_cache(&$page, &$chemin_cache, $duree) {
 	// Entrer dans la base les invalideurs calcules par le compilateur
 	// (et supprimer les anciens)
 
@@ -219,30 +228,29 @@ function creer_cache(&$page, $chemin_cache, $duree) {
 	if (strlen($t = $page['entetes']['X-Spip-Cache']))
 		$duree = intval($t);
 
-	include_ecrire('inc_invalideur');
-	maj_invalideurs($chemin_cache, $page['invalideurs'], $duree);
-
 	// Enregistrer le fichier cache qui contient
 	// 1) la carte d'identite de la page (ses "globals", genre id_article=7)
 	// 2) son contenu
 	$page['signal']['process_ins'] = $page['process_ins'];
 	$page['signal']['entetes'] = $page['entetes'];
-	$r = ecrire_fichier(_DIR_CACHE . $chemin_cache,
+
+	// Normaliser le chemin et supprimer l'eventuelle contrepartie -gz du cache
+	$chemin_cache = str_replace('.gz', '', $chemin_cache);
+	$gz = cache_gz($page);
+	supprimer_fichier(_DIR_CACHE . $chemin_cache . ($gz ? '' : '.gz'));
+
+	// l'enregistrer, compresse ou non...
+	$chemin_cache .= $gz;
+	ecrire_fichier(_DIR_CACHE . $chemin_cache,
 		"<!-- "
 		. str_replace("\n", " ", serialize($page['signal']))
 		. " -->\n"
 		. $page['texte']);
 
-	// Nouveau cache : creer un invalideur 't' fixant la date
-	// d'expiration et la taille du fichier
-	if ($r) {
-			// Ici on ajoute 3600s pour eviter toute concurrence
-			// entre un invalideur et un appel public de page
-		$bedtime = time() + $duree + 3600;
-		$taille = @filesize(_DIR_CACHE . $chemin_cache);
-		$fichier = addslashes($chemin_cache);
-		spip_query("INSERT IGNORE INTO spip_caches (fichier,id,type,taille) VALUES ('$fichier','$bedtime','t','$taille')");
-	}
+	// Inserer ses invalideurs
+	include_ecrire('inc_invalideur');
+	maj_invalideurs($chemin_cache, $page, $duree);
+
 }
 
 function restaurer_meta_donnees ($contenu) {
diff --git a/ecrire/public-calcul.php b/ecrire/public-calcul.php
index 9f3ea494ea54d7a7a43f6dcebaaa33116cb89539..4eef4bac37bda5d17529dc522225c8463569c93f 100644
--- a/ecrire/public-calcul.php
+++ b/ecrire/public-calcul.php
@@ -107,7 +107,6 @@ function charger_squelette ($squelette) {
 			include_ecrire("inc_debug_sql");
 			debug_dumpfile ($skel_code, $nom, 'code');
 		}
-#		spip_log($skel_code);
 		eval('?'.'>'.$skel_code);
 		if (function_exists($nom)) {
 			ecrire_fichier ($phpfile, $skel_code);
@@ -163,8 +162,9 @@ function cherche_page ($cache, $contexte, $fond)  {
 			$page = $fonc(array('cache' => $cache), array($contexte));
 			spip_log("calcul ("
 				.spip_timer('calcul page')
-				.") ".trim("[$skel] $cache")
-				." - ".strlen($page['texte']).' octets'
+				.") [$skel] ".
+				($cache ? $cache.cache_gz($page).' ' : '')
+				.'- '.strlen($page['texte']).' octets'
 			);
 		}
 
diff --git a/ecrire/public-compilo.php b/ecrire/public-compilo.php
index ff317165d7d04ac044e7bf5972e6d5f33528242e..6940fe205d48c633077a0ce7175f769f3e1db8a7 100644
--- a/ecrire/public-compilo.php
+++ b/ecrire/public-compilo.php
@@ -125,9 +125,10 @@ function calculer_boucle_nonrec($id_boucle, &$boucles) {
 		if (\$Numrows['$id_boucle']['compteur_boucle']-1 >= \$debut_boucle
 		AND \$Numrows['$id_boucle']['compteur_boucle']-1 <= \$fin_boucle) {";
 	
-	// Calculer les invalideurs si c'est une boucle non constante
-
-	if ($primary && !$constant)
+	// Calculer les invalideurs si c'est une boucle non constante et si on
+	// souhaite invalider ces elements
+	if (!$constant AND $primary AND ($primary == 'id_forum'
+	OR in_array($primary, explode(',', $GLOBALS['invalider_caches']))))
 		$corps .= "\n\t\t\$Cache['$primary'][intval(" .
 		  (($primary != 'id_forum')  ? 
 		   index_pile($id_boucle, $primary, $boucles) :
diff --git a/ecrire/public-global.php b/ecrire/public-global.php
index 3ca6f4fa2b13b2355fe783a5775ed38297b2ca8a..8b12c0d6601921113f581dfb01c52a5009495b28 100644
--- a/ecrire/public-global.php
+++ b/ecrire/public-global.php
@@ -59,7 +59,7 @@ function calcule_header_et_page ($fond) {
 		else {
 			$link = new Link();
 			$link->addvar('var_mode', 'debug');
-			redirige_par_entete(generer_url_public('login'), 'url='.urlencode($link->getUrl()));
+			redirige_par_entete(generer_url_public('login'), 'url='.urlencode($link->getUrl()), true);
 			exit;
 		}
 	}
diff --git a/ecrire/public-messforum.php b/ecrire/public-messforum.php
index 20460efb2763cd24bed9ff75b3d6f57678854bc6..135718f70fee5f42f9c0d763175524332884f416 100644
--- a/ecrire/public-messforum.php
+++ b/ecrire/public-messforum.php
@@ -119,7 +119,7 @@ function mots_du_forum($ajouter_mot, $id_message)
 }
 
 function enregistre_forum() {
-	global $REMOTE_ADDR, $auteur_session,
+	global $auteur_session,
 		$afficher_texte, $ajouter_mot, $alea, $hash,
 		$auteur, $confirmer_forum, $email_auteur, $id_auteur,
 		$nom_site_forum, $retour_forum, $texte, $titre, $url_site,
@@ -210,7 +210,7 @@ function enregistre_forum() {
 	url_site = '".addslashes(corriger_caracteres($url_site))."',
 	auteur = '".addslashes(corriger_caracteres($auteur))."',
 	email_auteur = '".addslashes(corriger_caracteres($email_auteur))."',
-	ip = '$REMOTE_ADDR',
+	ip = '".addslashes($ip)."',
 	statut = '$statut'
 	WHERE id_forum = $id_message
 	");
diff --git a/ecrire/public-stats.php b/ecrire/public-stats.php
index 76cfb7939a9d38f13904f2a55da54be90c55dfe0..0abe4d797c812925495f198bc9ec698435b5413d 100644
--- a/ecrire/public-stats.php
+++ b/ecrire/public-stats.php
@@ -15,8 +15,6 @@
 if (!defined("_ECRIRE_INC_VERSION")) return;
 
 function ecrire_stats() {
-	global $_SERVER;
-	global $id_article, $id_breve, $id_rubrique;
 
 	// Rejet des robots (qui sont pourtant des humains comme les autres)
 	if (preg_match(
@@ -31,23 +29,17 @@ function ecrire_stats() {
 		return;
 
 	// Identification de l'element
-	if ($log_id_num = intval($id_rubrique))
+	if ($log_id_num = intval(_request('id_rubrique')))
 		$log_type = "rubrique";
-	else if ($log_id_num = intval($id_article))
+	else if ($log_id_num = intval(_request('id_article')))
 		$log_type = "article";
-	else if ($log_id_num = intval($id_breve))
+	else if ($log_id_num = intval(_request('id_breve')))
 		$log_type = "breve";
 	else
 		$log_type = "autre";
 
-	// Identification du client ("unique")
-	if ($_SERVER['HTTP_X_FORWARDED_FOR']) {
-		$client_ip = $_SERVER['HTTP_X_FORWARDED_FOR'];
-	} else {
-		$client_ip = $_SERVER['REMOTE_ADDR'];
-	}
 	$client_id = substr(md5(
-		$client_ip . $_SERVER['HTTP_USER_AGENT']
+		$GLOBALS['ip'] . $_SERVER['HTTP_USER_AGENT']
 		. $_SERVER['HTTP_ACCEPT'] . $_SERVER['HTTP_ACCEPT_LANGUAGE']
 		. $_SERVER['HTTP_ACCEPT_ENCODING']
 	), 0,10);
diff --git a/formulaires/inc-formulaire_ecrire_auteur.php3 b/formulaires/inc-formulaire_ecrire_auteur.php3
index a3c0bb1af23b7d0d425de6613327d1e9e9e521ca..d4b03b8747ed38a837ca13429e1991b8b3a26bff 100644
--- a/formulaires/inc-formulaire_ecrire_auteur.php3
+++ b/formulaires/inc-formulaire_ecrire_auteur.php3
@@ -72,7 +72,7 @@ function balise_FORMULAIRE_ECRIRE_AUTEUR_dyn($id_auteur, $id_article, $mail) {
 		$texte .= "\n\n-- "._T('envoi_via_le_site')." ".supprimer_tags(extraire_multi($GLOBALS['meta']['nom_site']))." (".$GLOBALS['meta']['adresse_site']."/) --\n";
 		include_ecrire("inc_mail");
 		envoyer_mail($mail, $sujet, $texte, $adres,
-				"X-Originating-IP: ".$GLOBALS['REMOTE_ADDR']);
+				"X-Originating-IP: ".$GLOBALS['ip']);
 		return _T('form_prop_message_envoye');
 	}