diff --git a/.gitattributes b/.gitattributes
index 50e66a54c8b71ef71422841e24ea13c2a494d3a1..c2ee70b7ff80d07b3069311deb92513162eeb106 100644
--- a/.gitattributes
+++ b/.gitattributes
@@ -574,6 +574,7 @@ ecrire/inc/plonger.php -text
 ecrire/inc/plugin.php -text
 ecrire/inc/popularites.php -text
 ecrire/inc/premiers_pas.php -text
+ecrire/inc/rechercher.php -text
 ecrire/inc/referencer_traduction.php -text
 ecrire/inc/regler_moderation.php -text
 ecrire/inc/safehtml.php -text
diff --git a/ecrire/exec/recherche.php b/ecrire/exec/recherche.php
index 0821628b8aef33125cd2cda9f24c46cd4eb248e0..e75f93278e03bc9d9cb1b2b8f483b9fd2a9c675f 100644
--- a/ecrire/exec/recherche.php
+++ b/ecrire/exec/recherche.php
@@ -15,125 +15,120 @@ if (!defined("_ECRIRE_INC_VERSION")) return;
 include_spip('inc/presentation');
 include_spip('inc/sites_voir');
 
+
 // http://doc.spip.org/@exec_recherche_dist
-function exec_recherche_dist()
-{
+function exec_recherche_dist() {
 	$recherche = _request('recherche');
-
 	$recherche_aff = entites_html($recherche);
 
 	$commencer_page = charger_fonction('commencer_page', 'inc');
 	echo $commencer_page(_T('titre_page_recherche', array('recherche' => $recherche_aff)));
- 
-	debut_gauche();
 
-	if ($recherche) {
-	  $onfocus = "this.value='" . addslashes($recherche) . "';";
-	} else {
-	  $recherche_aff = _T('info_rechercher');
-	  $onfocus = "this.value='';";
+	if (strlen($recherche)) {
+		include_spip('inc/rechercher');
+		include_spip('base/abstract_sql');
+
+		// Si on demande /xxx/ on passe en REGEXP
+		if (preg_match(',^/(.*)/$,', $recherche, $r))
+			$results = recherche_en_base($r[1], NULL, 'REGEXP');
+		// sinon LIKE, plus simple et rapide
+		else
+			$results = recherche_en_base($recherche);
+
+		$modifier = false;
+		foreach ($results as $table => $r) {
+			foreach ($r as $id => $x) {
+				if (!autoriser('voir', $table, $id)) {
+					unset($r[$id]);
+				} else {
+					$modifier |= autoriser('modifier', $table, $id);
+				}
+			}
+			if (!$r)
+				unset($results[$table]);
+			else
+				$results[$table] = $r;
+		}
 	}
-	echo "<form method='get' style='margin: 0px;' action='" . generer_url_ecrire("recherche","") . "'><div>";
-	echo "<input type='hidden' name='exec' value='recherche' />";
-	echo '<input type="text" size="10" value="'.$recherche_aff.'" name="recherche" class="spip_recherche" accesskey="r" onfocus="'.$onfocus . '" />';
-	echo "</div></form>";
 
-	debut_droite();
-
-	if (strlen($recherche) > 0) {
-
-	echo "<span class='verdana1'><b>"._T('info_resultat_recherche')."</b></span><br />";
-	echo "<span class='ligne_foncee verdana1 spip_large'><b>$recherche_aff</b></span>";
+	debut_gauche();
 
-	$query_articles['FROM'] = 'spip_articles AS articles';
-	$query_breves['FROM'] = 'spip_breves';
-	$query_rubriques['FROM'] = 'spip_rubriques';
-	$query_sites['FROM'] = 'spip_syndic';
-	$testnum = preg_match(",^[0-9]+$,", $recherche);
+	if (!strlen($recherche)) {
+		$recherche_aff = _T('info_rechercher');
+		$onfocus = " onfocus=\"this.value='';\"";
+	}
 
-	// Eviter les symboles '%', caracteres SQL speciaux
+	// TODO: aide expliquant qu'on peut utiliser REGEXP en entrant /xxx/
 
-	$where = split("[[:space:]]+", $recherche);
-	if ($where) {
-		foreach ($where as $k => $v) 
-		  $where[$k] = "'%" . substr(str_replace("%","\%", _q($v)),1,-1) . "%'";
-		$where = ($testnum ? "OR " : '') .
-		  ("(titre LIKE " . join(" AND titre LIKE ", $where) . ")");
-	}
+	echo "<form method='get' style='margin: 0px;' action='" . generer_url_ecrire("recherche","") . "'><div>";
+	echo "<input type='hidden' name='exec' value='recherche' />";
+	echo '<input type="text" size="10" value="'.$recherche_aff.'" name="recherche" class="spip_recherche" accesskey="r"' . $onfocus . ' />';
 
-	$query_articles['WHERE']= ($testnum ? "(articles.id_article = $recherche)" :'') . $where;
-	$query_breves['WHERE']= ($testnum ? "(id_breve = $recherche)" : '') . $where;
-	$query_rubriques['WHERE']= ($testnum ? "(id_rubrique = $recherche)" : '') . $where;
-	$query_sites['WHERE']= ($testnum ? "(id_syndic = $recherche)" : '') . preg_replace("/titre LIKE/", "nom_site LIKE",$where);
-
-	$query_articles['ORDER BY']= "date_modif DESC";
-	$query_breves['ORDER BY']= "maj DESC";
-	$query_rubriques['ORDER BY']= "maj DESC";
-	$query_sites['ORDER BY']= "maj DESC";
-	
-	$activer_moteur = ($GLOBALS['meta']['activer_moteur'] == 'oui');
-
-	if ($activer_moteur) {	// texte integral
-		include_spip('inc/indexation');
-		list($hash_recherche,) = requete_hash(str_replace("%","\%",$recherche));
-		$query_articles_int = requete_txt_integral('spip_articles', $hash_recherche);
-		$query_breves_int = requete_txt_integral('spip_breves', $hash_recherche);
-		$query_rubriques_int = requete_txt_integral('spip_rubriques', $hash_recherche);
-		$query_sites_int = requete_txt_integral('spip_syndic', $hash_recherche);
-		$query_auteurs_int = requete_txt_integral('spip_auteurs', $hash_recherche);
+/*
+	// Si on est autorise a modifier, proposer le choix de REMPLACER
+	// Il faudra aussi pouvoir indiquer sur quels elements on veut effectuer le remplacement...
+	if ($modifier) {
+	echo '<br /><input type="text" size="10" value="'.entites_html(_request('remplacer')).'" name="remplacer" class="spip_recherche" />';
 	}
-	
-	$nba = afficher_articles (_T('info_articles_trouves'), $query_articles);
-	echo $nba;
+*/
+	echo "</div></form>";
 
-	if ($activer_moteur) {
-		if ($nba) 
-			$query_articles_int['WHERE'] .= " AND NOT (" . $query_articles['WHERE'] . ")";
+	debut_droite();
 
-		$nba1 = afficher_articles (_T('info_articles_trouves_dans_texte'), $query_articles_int);
-		echo $nba1;
-	}
-	
-	$nbb = afficher_breves ('<b>' . _T('info_breves_touvees') . '</b>', $query_breves, true);
-	echo $nbb;
-	if ($activer_moteur) {
-		if ($nbb) {
-			$query_breves_int["WHERE"].= " AND NOT (" . $query_breves['WHERE'] . ")";
+	if ($results) {
+		echo "<span class='verdana1'><b>"._T('info_resultat_recherche')."</b></span><br />";
+		echo "<span class='ligne_foncee verdana1 spip_large'><b>$recherche_aff</b></span>";
+
+		foreach($results as $table => $r) {
+			switch ($table) {
+			case 'article':
+				$fn = 'afficher_articles';
+				$titre = _T('info_articles_trouves');
+				$order = 'date DESC';
+				break;
+			case 'breve':
+				$fn = 'afficher_breves';
+				$titre = _T('info_breves_touvees');
+				$order = 'date_heure DESC';
+				break;
+			case 'rubrique':
+				$fn = 'afficher_rubriques';
+				$titre = _T('info_rubriques_trouvees');
+				$order = 'date DESC';
+				break;
+			case 'site':
+				$fn = 'afficher_sites';
+				$titre = _T('info_sites_trouves');
+				$order = 'date DESC';
+				break;
+			case 'auteur':
+				$fn = 'afficher_auteurs';
+				$titre = _T('info_auteurs_trouves');
+				$order = 'nom';
+				break;
+			}
+
+			echo $a = $fn($titre,
+				array(
+					// gasp: la requete spip_articles exige AS articles...
+					'FROM' => 'spip_'.table_objet($table).' AS '.$table.'s',
+					'WHERE' => id_table_objet($table)
+						.' IN ('.join(',',array_keys($r)).')',
+					'ORDER BY' => $order
+				)
+			);
 		}
-		$nbb1 = afficher_breves ('<b>' . _T('info_breves_touvees_dans_texte') . '</b>', $query_breves_int, true);
-		echo $nbb1;
-	}
 
-	$nbr = afficher_rubriques ('<b>' . _T('info_rubriques_trouvees') . '</b>', $query_rubriques);
-	echo $nbr;
-	if ($activer_moteur) {
-		if ($nbr) {
-			$query_rubriques_int["WHERE"].= " AND NOT (" . $query_rubriques['WHERE'] . ")";
-		}
-		$nbr1 = afficher_rubriques ('<b>' . _T('info_rubriques_trouvees_dans_texte') . '</b>', $query_rubriques_int);
-		echo $nbr1;
 	}
-	
-	$nbt = afficher_auteurs (_T('info_auteurs_trouves'), $query_auteurs_int);
-	
-	$nbs = afficher_sites ('<b>' . _T('info_sites_trouves') . '</b>', $query_sites);
-	echo $nbs;
-	if ($activer_moteur) {
-		if ($nbs) {
-			$query_sites_int["WHERE"].=  " AND NOT (" . $query_sites['WHERE'] . ")";
-		}
-		$nbs1 = afficher_sites ('<b>' . _T('info_sites_trouves_dans_texte') . '</b>', $query_sites_int);
-		echo $nbs1;
-	}
-	
-	if (!$nba AND !$nba1 AND !$nbb AND !$nbb1 AND !$nbr AND !$nbr1 AND !$nbt AND !$nbs AND !$nbs1) {
-		echo "<p class='verdana1'>"._T('avis_aucun_resultat')."</p>";
-	}
-	}
-echo fin_gauche(), fin_page();
+	else
+		if (strlen($recherche))
+			echo "<p class='verdana1'>"._T('avis_aucun_resultat')."</p>";
+
+	echo fin_gauche(), fin_page();
 }
 
 
+// old style, devrait etre dans inc/presentation
 // http://doc.spip.org/@afficher_auteurs
 function afficher_auteurs ($titre_table, $requete) {
 
@@ -184,6 +179,6 @@ function afficher_auteurs ($titre_table, $requete) {
 	echo "</table>";
 	fin_cadre_relief();
 
-	return $cpt;
 }
+
 ?>
diff --git a/ecrire/inc/rechercher.php b/ecrire/inc/rechercher.php
new file mode 100644
index 0000000000000000000000000000000000000000..b7bc8712e915eae8eedc8c7cb026b3f9d1128a6a
--- /dev/null
+++ b/ecrire/inc/rechercher.php
@@ -0,0 +1,98 @@
+<?php
+
+/***************************************************************************\
+ *  SPIP, Systeme de publication pour l'internet                           *
+ *                                                                         *
+ *  Copyright (c) 2001-2007                                                *
+ *  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;
+
+
+// Donne la liste des champs/tables ou l'on sait chercher/remplacer
+function liste_des_champs() {
+	return
+	array(
+		'article' => array(
+			'surtitre', 'titre', 'soustitre', 'chapo', 'texte', 'ps', 'nom_site', 'url_site'
+		),
+		'breve' => array(
+			'titre', 'texte', 'lien_titre', 'lien_url'
+		),
+		'rubrique' => array(
+			'titre', 'descriptif', 'texte'
+		),
+		'site' => array(
+			'nom_site', 'url_site', 'descriptif'
+		),
+		'auteur' => array(
+			'nom', 'bio', 'email', 'nom_site', 'url_site', 'login'
+		)
+	);
+}
+
+
+// Effectue une recherche sur toutes les tables de la base de donnees
+function recherche_en_base($recherche='', $tables=NULL) {
+	if (!is_array($tables))
+		$tables = liste_des_champs();
+
+	$results = array();
+
+	if (!strlen($recherche))
+		return array();
+
+	// Si la chaine est inactive, on va utiliser LIKE pour aller plus vite
+	if (preg_quote($recherche) == $recherche) {
+		$methode = 'LIKE';
+		$q = _q(
+			"%"
+			. str_replace(array('%','_'), array('\%', '\_'), $recherche)
+			. "%"
+		);
+	} else {
+		$methode == 'REGEXP';
+		$q = _q($recherche);
+	}
+
+	foreach ($tables as $table => $champs) {
+		$a = array();
+		$_id_table = id_table_objet($table);
+
+		// Recherche par identifiant
+		if (preg_match(',^[0-9]+$,', $recherche))
+			$a[] = $_id_table.' = '.$recherche;
+
+		// Recherche fulltext
+		foreach ($champs as $champ)
+			$a[] = $champ.' '.$methode.' '.$q;
+		$s = spip_query(
+			'SELECT '.$_id_table.','
+			.join(',', $champs)
+			.' FROM spip_'.table_objet($table)
+			.' WHERE ('
+			. join (' OR ', $a)
+			. ")");
+		while ($t = spip_fetch_array($s)) {
+			$results[$table][$t[$_id_table]] = $t;
+		}
+	}
+
+	return $results;
+}
+
+
+// Effectue une recherche sur toutes les tables de la base de donnees
+function remplace_en_base($recherche='', $remplace=NULL, $tables=NULL, $callback=NULL) {
+	if (!is_array($tables))
+		$tables = liste_des_champs();
+
+}
+
+
+?>