diff --git a/formulaire_forum-dist.html b/formulaire_forum-dist.html
index 9e2d21a122573acd56081cbc474e65952d276e51..c067b96eabcf580240ef8daa8d7c56a797aafaf1 100644
--- a/formulaire_forum-dist.html
+++ b/formulaire_forum-dist.html
@@ -1,57 +1,57 @@
-<form action='[(#HTTP_VARS{url})]' method='post' name='formulaire'>
+<form action="[(#HTTP_VARS{url})]" method="post" name="formulaire">
 
-<input type='hidden' name='ajout_forum' value="oui" />
-<input type='hidden' name='alea' value="[(#HTTP_VARS{alea})]" />
-<input type='hidden' name='hash' value="[(#HTTP_VARS{hash})]" />
-<input type='hidden' name='retour' value="[(#HTTP_VARS{retour})]" />
+<input type="hidden" name="ajout_forum" value="oui" />
+[<input type="hidden" name="alea" value="(#HTTP_VARS{alea})" />]
+[<input type="hidden" name="hash" value="(#HTTP_VARS{hash})" />]
+[<input type="hidden" name="retour" value="(#HTTP_VARS{retour})" />]
 
 [<p>(#HTTP_VARS*{modere})</p>]
 
 [(#HTTP_VARS*{afficher_texte_hidden})]
 [(#HTTP_VARS*{afficher_texte_input})
 	[(#HTTP_VARS*{previsu})
-		<fieldset class='spip_encadrer'>
+		<fieldset class="spip_encadrer">
 		<legend><b><:forum_titre:></b></legend>
-		<label><input type='text' name='titre' 
-			[value="(#HTTP_VARS{titre})" ]class='forml' size='40' />
+		<label><input type="text" name="titre" 
+			[value="(#HTTP_VARS{titre})" ]class="forml" size="40" />
 		</label>
 		</fieldset>
 		<br />
-		<fieldset class='spip_encadrer'>
+		<fieldset class="spip_encadrer">
 		<legend><b><:forum_texte:></b></legend>
 		<p><:info_creation_paragraphe:></p>
 		[(#HTTP_VARS{texte}|barre_forum)]
 		</fieldset>
 		<br />
 		[<p>(#HTTP_VARS*{table})</p>]
-		<fieldset class='spip_encadrer'>
+		<fieldset class="spip_encadrer">
 			<legend><:forum_lien_hyper:></legend>
 			<p><:forum_page_url:></p>
 			<p><label><:forum_titre:>
-				<input type='text' name='nom_site_forum' class='forml' size='40'
+				<input type="text" name="nom_site_forum" class="forml" size="40"
 					value="[(#HTTP_VARS{nom_site_forum})]" />
 			</label></p>
 			<p><label><:forum_url:>
-			<input type='text' name='url_site' class='forml' size='40'
+			<input type="text" name="url_site" class="forml" size="40"
 				value="[(#HTTP_VARS{url_site})]" />
 			</label></p>
 		</fieldset>
 		<br />
-		<fieldset class='spip_encadrer'>
+		<fieldset class="spip_encadrer">
 			<legend><:forum_qui_etes_vous:></legend>
 			<p><label><:forum_votre_nom:>
-				<input type='text' name='auteur' value="[(#HTTP_VARS{auteur})]"
-					class='forml' size='40' [(#HTTP_VARS{disabled})] />
+				<input type="text" name="auteur" value="[(#HTTP_VARS{auteur})]"
+					class="forml" size="40" [(#HTTP_VARS{disabled})] />
 			</label></p>
 			<p><label><:forum_votre_email:>
-				<input type='text' name='email_auteur'
+				<input type="text" name="email_auteur"
 				value="[(#HTTP_VARS{email_auteur})]"
-				class='forml' size='40' [(#HTTP_VARS{disabled})] />
+				class="forml" size="40" [(#HTTP_VARS{disabled})] />
 			</label></p>
 		</fieldset>
 		<br />
-		<div align='right'><input type='submit' value="<:forum_voir_avant:>"
-		class='spip_bouton'></div>
+		<div align="#LANG_RIGHT"><input type="submit" value="<:forum_voir_avant:>"
+		class="spip_bouton"></div>
 	]
 ]
 </form>
diff --git a/forum.php3 b/forum.php3
index 94d184831e4e29fe0b263bd57788eab67d68bf4b..a9fe0f862e2c26224a1b36c1fdebf40728320f64 100644
--- a/forum.php3
+++ b/forum.php3
@@ -1,4 +1,5 @@
 <?php
+
 $fond = "forum";
 $delais = 3600;
 
@@ -6,7 +7,7 @@ $delais = 3600;
 // @ http://www.spip.net/fr_article1825.html
 //
 // 1. seuls les mots-cles du groupe de mots numero 1 doivent s'afficher
-// $afficher_groupe = array(9);
+// $afficher_groupe = array(1);
 //
 // 2. faire des forums uniquement pour affecter des mots-cles
 // $afficher_texte = "non";
diff --git a/inc-balises.php3 b/inc-balises.php3
index b122b86307d9b4bbe32a9436ba0ce0aef0895751..e45ded6043d7bf1c1027601d5a9e4a023ae3c6ed 100644
--- a/inc-balises.php3
+++ b/inc-balises.php3
@@ -605,13 +605,14 @@ function balise_EXTRA_dist ($p) {
 
 function balise_PARAMETRES_FORUM_dist($p) {
 	include_local('inc-formulaire_forum.php3');
-	$_accepter_forum = champ_sql('accepter_forum', $p);
+	$_id_article = champ_sql('id_article', $p);
 	$p->code = '
-	// refus des forums ?
-	('.$_accepter_forum.'=="non" OR
-	(lire_meta("forums_publics") == "non" AND !ereg("^(pos|pri|abo)", '.$_accepter_forum.')))
-	? "" : // sinon:
-	';
+		// refus des forums ?
+		(sql_accepter_forum('.$_id_article.')=="non" OR
+		(lire_meta("forums_publics") == "non"
+		AND sql_accepter_forum('.$_id_article.') == ""))
+		? "" : // sinon:
+		';
 
 	switch ($p->type_requete) {
 		case 'articles':
diff --git a/inc-calcul-outils.php3 b/inc-calcul-outils.php3
index b49676faaa6aec16d93fed1fa6628175b901bc02..ada0ba9ea5f06cf59634ce8eed9e569d3de389b3 100644
--- a/inc-calcul-outils.php3
+++ b/inc-calcul-outils.php3
@@ -353,12 +353,28 @@ function sql_petitions($id_article, $table, $id_boucle, $serveur, &$Cache) {
 # retourne le chapeau d'un article, et seulement s'il est publie
 
 function sql_chapo($id_article) {
+	if ($id_article)
 	return spip_abstract_fetsel(array('chapo'),
 		array('articles'),
 		array("id_article=".intval($id_article),
 		"statut='publie'"));
 }
 
+# retourne le champ 'accepter_forum' d'un article
+function sql_accepter_forum($id_article) {
+	static $cache = array();
+
+	if (!$id_article) return;
+
+	if (!isset($cache[$id_article]))
+		$cache[$id_article] = spip_abstract_fetsel(array('accepter_forum'),
+			array('articles'),
+			array("id_article=".intval($id_article)));
+
+	return $cache[$id_article];
+}
+
+
 // Calcul de la rubrique associee a la requete
 // (selection de squelette specifique par id_rubrique & lang)
 
diff --git a/inc-formulaire_forum.php3 b/inc-formulaire_forum.php3
index d4e12e41848efd566d166aea7c5b7050533085e8..6f484d7afdbf35e9349c9279b6c2ef6baf4c3eb2 100644
--- a/inc-formulaire_forum.php3
+++ b/inc-formulaire_forum.php3
@@ -21,21 +21,21 @@ else
 /* GESTION DU FORMULAIRE FORUM */
 /*******************************/
 global $balise_FORMULAIRE_FORUM_collecte;
-$balise_FORMULAIRE_FORUM_collecte = array('id_rubrique', 'id_forum', 'id_article', 'id_breve', 'id_syndic');
+$balise_FORMULAIRE_FORUM_collecte = array('id_rubrique', 'id_forum', 'id_article', 'id_breve', 'id_syndic', 'alea', 'hash');
 
-function balise_FORMULAIRE_FORUM_stat($args, $filtres)
-{
-  list ($idr, $idf, $ida, $idb, $ids) = $args;
-
-  // recuperer les donnees du forum auquel on repond, false = forum interdit
-  if (!$r = sql_recherche_donnees_forum ($idr, $idf, $ida, $idb, $ids))
-    return '';
-  list($titre, $table, $forums_publics) = $r;
-  return 
-    array($titre, $table, $forums_publics, $idr, $idf, $ida, $idb, $ids);
+function balise_FORMULAIRE_FORUM_stat($args, $filtres) {
+	list ($idr, $idf, $ida, $idb, $ids, $alea, $hash) = $args;
+
+	// recuperer les donnees du forum auquel on repond, false = forum interdit
+	if (!$r = sql_recherche_donnees_forum ($idr, $idf, $ida, $idb, $ids))
+		return '';
+
+	list($titre, $table, $forums_publics) = $r;
+	return
+		array($titre, $table, $forums_publics, $idr, $idf, $ida, $idb, $ids, $alea, $hash);
 }
 
-function balise_FORMULAIRE_FORUM_dyn($titre, $table, $forums_publics, $id_rubrique, $id_forum, $id_article, $id_breve, $id_syndic) {
+function balise_FORMULAIRE_FORUM_dyn($titre, $table, $forums_publics, $id_rubrique, $id_forum, $id_article, $id_breve, $id_syndic, $alea, $hash) {
 
 	global $REMOTE_ADDR, $id_message, $afficher_texte, $spip_forum_user;
 
@@ -146,17 +146,39 @@ function balise_FORMULAIRE_FORUM_dyn($titre, $table, $forums_publics, $id_rubriq
 		}
 	}
 
-	// Generation d'une valeur de securite pour validation
-	$seed = (double) (microtime() + 1) * time() * 1000000;
-	@mt_srand($seed);
-	$alea = @mt_rand();
-	if (!$alea) {srand($seed);$alea = rand();}
-	$forum_id_rubrique = intval($id_rubrique);
-	$forum_id_forum = intval($id_forum);
-	$forum_id_article = intval($id_article);
-	$forum_id_breve = intval($id_breve);
-	$forum_id_syndic = intval($id_syndic);
-	$hash = calculer_action_auteur("ajout_forum $forum_id_rubrique $forum_id_forum $forum_id_article $forum_id_breve $forum_id_syndic $alea");
+	$id_rubrique = intval($id_rubrique);
+	$id_forum = intval($id_forum);
+	$id_article = intval($id_article);
+	$id_breve = intval($id_breve);
+	$id_syndic = intval($id_syndic);
+
+	// Une securite qui nous protege contre :
+	// - les doubles validations de forums (derapages humains ou des brouteurs)
+	// - les abus visant à mettre des forums malgre nous sur un article (??)
+	// On installe un fichier temporaire dans _DIR_SESSIONS (et pas _DIR_CACHE
+	// afin de ne pas bugguer quand on vide le cache)
+	// Le lock est leve au moment de l'insertion en base (inc-messforum.php3)
+	if ($GLOBALS['HTTP_POST_VARS']['ajout_forum']) {
+
+		$alea = preg_replace('/[^0-9]/', '', $alea);
+		if(!$alea OR !@file_exists(_DIR_SESSIONS."forum_$alea.lck")) {
+			while (
+				# astuce : mt_rand pour autoriser les hits simultanes
+				$alea = time() + @mt_rand()
+				AND @file_exists($f = _DIR_SESSIONS."forum_$alea.lck")) {};
+			@touch ($f);
+			@chmod ($f,0666);
+		}
+
+		# et maintenant on purge les locks de forums ouverts depuis > 4 h
+		if ($dh = @opendir(_DIR_SESSIONS))
+			while (($file = @readdir($dh)) !== false)
+				if (preg_match('/^forum_([0-9]+)\.lck$/', $file)
+				AND (time()-@filemtime(_DIR_SESSIONS.$file) > 4*3600))
+					@unlink(_DIR_SESSIONS.$file);
+
+		$hash = calculer_action_auteur("ajout_forum $id_rubrique $id_forum $id_article $id_breve $id_syndic $alea");
+	}
 
 	// Faut-il ajouter des propositions de mots-cles
 	if ((lire_meta("mots_cles_forums") == "oui") && ($table != 'forum'))
diff --git a/inc-messforum.php3 b/inc-messforum.php3
index bbb7f818810b052b1484ad4a5d00e11bbfc6f371..8df714c24d2eb9708336e75654fef8adc3596654 100644
--- a/inc-messforum.php3
+++ b/inc-messforum.php3
@@ -108,32 +108,38 @@ if ((strlen($texte) + strlen($titre) + strlen($nom_site_forum) + strlen($url_sit
 if (strlen($confirmer) > 0
 OR ($afficher_texte=='non' AND $ajouter_mot)) {
 
-	// verifier droit (pour interdire de hack-poster sur des forums fermes ?)
+	// prevoir le redirect
+	$redirect = $retour_forum;
+
+	// Verifier hash securite
 	include_ecrire("inc_admin.php3");
-	if (!(verifier_action_auteur("ajout_forum $id_rubrique".
+	if (!verifier_action_auteur("ajout_forum $id_rubrique".
 	" $id_forum $id_article $id_breve".
-	" $id_syndic $alea", $hash))) {
-		header("Status: 404");
-		exit;
-	}
+	" $id_syndic $alea", $hash))
+		return; 	# echec silencieux du POST
+
+	// verifier fichier lock
+	$alea = preg_replace('/[^0-9]/', '', $alea);
+	if (!file_exists($f = _DIR_SESSIONS."forum_$alea.lck"))
+		return; # echec silencieux du POST
+	unlink($f);
 
 	// Entrer le message dans la base
-	$id_message = spip_abstract_insert('forum', 
-	"(date_heure)",
-	"(NOW())");
+	$id_message = spip_abstract_insert('forum', '(date_heure)', '(NOW())');
 
 	$statut =
 		($forums_publics == 'non') ? 'off' :
 		(($forums_publics == 'pri') ? 'prop' :
 		'publie');
 
-	if ($id_forum > 0)
-		$id_thread = $id_forum;
+	if ($id_forum)
+		list($id_thread) = spip_fetch_array(spip_query(
+		"SELECT id_thread FROM spip_forum WHERE id_forum = $id_forum"));
 	else
 		$id_thread = $id_message; # id_thread oblige INSERT puis UPDATE.
 
 	spip_query("UPDATE spip_forum SET id_parent = $id_forum,
-	id_rubrique =$id_rubrique,
+	id_rubrique = $id_rubrique,
 	id_article = $id_article,
 	id_breve = $id_breve,
 	id_syndic = $id_syndic,
@@ -183,8 +189,6 @@ OR ($afficher_texte=='non' AND $ajouter_mot)) {
 				$id_syndic) . "'");
 	}
 
-	$redirect = $retour_forum;
-
 }
 
 ?>