diff --git a/ecrire/inc_texte.php3 b/ecrire/inc_texte.php3
index d025828b85df1fce3648c8d7375e383da41c3874..3cc4d918499b8c22ce8bd2b64486ecbcb84bfbf0 100644
--- a/ecrire/inc_texte.php3
+++ b/ecrire/inc_texte.php3
@@ -120,6 +120,8 @@ define ('__regexp_echappe',
 		. "<(poesie|poetry)>((.*?))<\/(poesie|poetry)>" #poesie
 		. ")/si");
 
+define ('__regexp_img_echappe', "<(IMG|DOC|EMB)([0-9]+)(\|([^\>]*))?".">");
+
 function echappe_html($letexte, $source='SOURCEPROPRE', $no_transform=false) {
 	$debut = '';
 	$suite = $letexte;
@@ -187,7 +189,7 @@ function echappe_html($letexte, $source='SOURCEPROPRE', $no_transform=false) {
 	//
 	// Reperages d'images et de documents utilisateur 
 	// (insertion dans echappe_retour pour faciliter les doublons)
-	while (eregi("<(IMG|DOC|EMB)([0-9]+)(\|([^\>]*))?".">", $letexte, $match)) {
+	while (eregi(__regexp_img_echappe, $letexte, $match)) {
 		$num_echap++;
 
 		$letout = quotemeta($match[0]);
@@ -238,6 +240,18 @@ function echappe_retour($letexte, $les_echap, $source='') {
   return $debut . $letexte;
 }
 
+
+// fonction en cas de texte extrait d'un serveur distant:
+// on ne sait pas (encore) rappatrier les documents joints
+
+function supprime_img($letexte) {
+	$message = _L('indisponible');
+	while (eregi(__regexp_img_echappe, $letexte, $match)) {
+	  $letexte = ereg_replace($match[0], $message, $letexte);
+	}
+	return $letexte;
+}
+
 # il y a 3 couples de fonctions homonymes au prefixe _doublons pres
 # pour éviter à tous les appels de se trimbaler ce qui concerne les squelettes
 
diff --git a/inc-balises.php3 b/inc-balises.php3
index 01f424a198654c0bbbe09bdf6a8f64c81dd53cb5..42f22fcf599dcece7bf5f685a3fbe6ab09664b84 100644
--- a/inc-balises.php3
+++ b/inc-balises.php3
@@ -54,7 +54,6 @@ function champs_traitements ($p) {
 	);
 	$ps = $traitements[$p->nom_champ];
 	if (!$ps) return $p->code;
-
 	if ($p->documents)
 	  {$ps = str_replace('traiter_raccourcis(', 
 			     'traiter_raccourcis_doublon($doublons,',
@@ -62,7 +61,14 @@ function champs_traitements ($p) {
 					 'typo_doublon($doublons,',
 					 $ps));
 	  }
-	return str_replace('%s', $p->code, $ps);				
+	// on supprime les <IMGnnn> tant qu'on ne rapatrie pas
+	// les documents distants joints..
+	// il faudrait aussi corriger les raccourcis d'URL locales
+	return str_replace('%s',
+			   (!$p->boucles[$p->id_boucle]->sql_serveur ?
+			    $p->code :
+			    ('supprime_img(' . $p->code . ')')),
+			   $ps);				
 }
 
 //
@@ -356,6 +362,7 @@ function balise_EXPOSER_dist($p) {
 // Inserer directement un document dans le squelette
 //
 function balise_EMBED_DOCUMENT_dist($p) {
+	balise_distante_interdite($p);
 	$_id_document = champ_sql('id_document',$p);
 	$p->code = "calcule_embed_document(intval($_id_document), '" .
 	texte_script($p->fonctions ? join($p->fonctions, "|") : "") .
@@ -406,12 +413,14 @@ echo menu_langues(\"var_lang_ecrire\", \$menu_lang);
 // Formulaires de login
 //
 function balise_LOGIN_PRIVE_dist($p) {
+	balise_distante_interdite($p);
 	$p->code = '("<"."?php include(\'inc-login.php3\'); login(\'\', \'prive\'); ?".">")'; 
 	$p->statut = 'php';
 	return $p;
 }
 
 function balise_LOGIN_PUBLIC_dist($p) {
+	balise_distante_interdite($p);
 	if ($nom = $p->fonctions[0])
 	$lacible = "new Link('".$nom."')";
 	else
@@ -695,7 +704,7 @@ function balise_FORMULAIRE_RECHERCHE_dist($p) {
 // Formulaire d'inscription comme redacteur (dans inc-formulaires.php3)
 //
 function balise_FORMULAIRE_INSCRIPTION_dist($p) {
-
+	balise_distante_interdite($p);
 	$p->code = '((lire_meta("accepter_inscriptions") != "oui") ? "" :
 		("<"."?php include_local(\'inc-formulaires.php3\'); lang_select(\'".$GLOBALS[\'spip_lang\']."\'); echo formulaire_inscription(\"redac\"); lang_dselect(); ?".">"))';
 
@@ -707,6 +716,7 @@ function balise_FORMULAIRE_INSCRIPTION_dist($p) {
 // Formulaire ecrire auteur
 //
 function balise_FORMULAIRE_ECRIRE_AUTEUR_dist($p) {
+	balise_distante_interdite($p);
 	$_id_auteur = champ_sql('id_auteur', $p);
 	$_mail_auteur = champ_sql('email', $p);
 
@@ -721,6 +731,7 @@ function balise_FORMULAIRE_ECRIRE_AUTEUR_dist($p) {
 // Formulaire signature de petition
 //
 function balise_FORMULAIRE_SIGNATURE_dist($p) {
+	balise_distante_interdite($p);
 	$_id_article = champ_sql('id_article', $p);
 	$nom = $p->id_boucle;
 	$code = "sql_petitions(" .
@@ -746,6 +757,7 @@ echo formulaire_signature(".' .
 
 // Formulaire d'inscription de site dans l'annuaire
 function balise_FORMULAIRE_SITE_dist($p) {
+	balise_distante_interdite($p);
 	$_id_rubrique = champ_sql('id_rubrique', $p);
 
 	$p->code = '((lire_meta("proposer_sites") != 2) ? "":
@@ -755,6 +767,18 @@ function balise_FORMULAIRE_SITE_dist($p) {
 	return $p;
 }
 
+// il faudrait traiter le formulaire en local 
+// tout en appelant le serveur SQL distant.
+// En attendant, refuser une authentification sur qqch qui n'a rien à voir.
+
+function balise_distante_interdite($p) {
+	$nom = $p->id_boucle;
+	if ($p->boucles[$nom]->sql_serveur) {
+		include_local("inc-admin.php3");
+		erreur_squelette($p->nom_champ ._L(" distant interdit"), $nom);
+		exit;
+	}
+}
 
 
 //
@@ -766,6 +790,7 @@ function balise_FORMULAIRE_ADMIN_dist($p) {
 	return $p;
 }
 
+
 function balise_HTTP_dist($p) {
 	if (is_array($p->fonctions)) {
 		foreach($p->fonctions as $nom) {
diff --git a/inc-calcul-outils.php3 b/inc-calcul-outils.php3
index c7e855c445a05021a7ebc43b20e299756d21cf30..966a5e01640ba2be47963942010ea2072235964c 100644
--- a/inc-calcul-outils.php3
+++ b/inc-calcul-outils.php3
@@ -186,9 +186,10 @@ function calcul_exposer ($id, $type, $reference) {
 			if ($element == 'id_secteur') $element = 'id_rubrique';
 			if (ereg("id_(article|breve|rubrique|syndic)", $element, $regs)) {
 				$exposer[$element][$id_element] = true;
-				list ($id_rubrique) = spip_abstract_fetch(spip_abstract_select(array(id_rubrique), 
-											       array(table_objet($regs[1])),
-											       array("$element=$id_element")));
+				list ($id_rubrique) = spip_abstract_fetsel(
+array('id_rubrique'), 
+array(table_objet($regs[1])),
+array("$element=$id_element"));
 				$hierarchie = substr(calculer_hierarchie($id_rubrique), 2);
 				foreach (split(',',$hierarchie) as $id_rubrique)
 					$exposer['id_rubrique'][$id_rubrique] = true;
@@ -263,17 +264,17 @@ function sql_profondeur($id)
 
 function sql_parent($id_rubrique)
 {
-  $row = spip_abstract_fetch(spip_abstract_select(array(id_parent), 
-						  array(rubriques), 
-						  array("id_rubrique='$id_rubrique'")));
+  $row = spip_abstract_fetsel(array(id_parent), 
+			      array('rubriques'), 
+			      array("id_rubrique='$id_rubrique'"));
   return $row['id_parent'];
 }
 
 function sql_rubrique($id_article)
 {
-  $row = spip_abstract_fetch(spip_abstract_select(array(id_rubrique),
-						  array(articles),
-						  array("id_article='$id_article'")));
+  $row = spip_abstract_fetsel(array('id_rubrique'),
+			      array('articles'),
+			      array("id_article='$id_article'"));
   return $row['id_rubrique'];
 }
 
@@ -290,7 +291,7 @@ function sql_auteurs($id_article, $table, $id_boucle, $serveur='')
 					     '','','','',1, 
 					     $table, $id_boucle, $serveur);
 
-      while($row_auteur = spip_abstract_fetch($result_auteurs)) {
+      while($row_auteur = spip_abstract_fetch($result_auteurs, $serveur)) {
 	$nom_auteur = typo($row_auteur["nom"]);
 	$email_auteur = $row_auteur["email"];
 	if ($email_auteur) {
@@ -305,21 +306,21 @@ function sql_auteurs($id_article, $table, $id_boucle, $serveur='')
 }
 
 function sql_petitions($id_article, $table, $id_boucle, $serveur='') {
-  return spip_abstract_fetch(spip_abstract_select(array('id_article', 'email_unique', 'site_obli', 'site_unique', 'message', 'texte'),
-						  array('petitions'),
-						  array("id_article=".intval($id_article)),
-						  '','','','',1, 
-						  $table, $id_boucle, $serveur));
+  return spip_abstract_fetsel(array('id_article', 'email_unique', 'site_obli', 'site_unique', 'message', 'texte'),
+			      array('petitions'),
+			      array("id_article=".intval($id_article)),
+			      '','','','',1, 
+			      $table, $id_boucle, $serveur);
 }
 
 # retourne le chapeau d'un article, et seulement s'il est publie
 
 function sql_chapo($id_article)
 {
-  return spip_abstract_fetch(spip_abstract_select(array(chapo),
+  return spip_abstract_fetsel(array('chapo'),
 			      array('articles'),
 			      array("id_article='$id_article'",
-				    "statut='publie'")));
+				    "statut='publie'"));
 }
 
 // Calcul de la rubrique associee a la requete
@@ -328,18 +329,18 @@ function sql_chapo($id_article)
 function sql_rubrique_fond($contexte, $lang) {
 
 	if ($id = intval($contexte['id_rubrique'])) {
-	  $row = spip_abstract_fetch(spip_abstract_select(array('lang'),
-							  array('rubriques'),
-							  array("id_rubrique='$id'")));
+	  $row = spip_abstract_fetsel(array('lang'),
+				      array('rubriques'),
+				      array("id_rubrique='$id'"));
 		if ($row['lang'])
 			$lang = $row['lang'];
 		return array ($id, $lang);
 	}
 
 	if ($id  = intval($contexte['id_breve'])) {
-	  $row = spip_abstract_fetch(spip_abstract_select(array('id_rubrique', 'lang'),
-							  array(breves), 
-							  array("id_breve='$id'")));
+	  $row = spip_abstract_fetsel(array('id_rubrique', 'lang'),
+				      array('breves'), 
+				      array("id_breve='$id'"));
 		$id_rubrique_fond = $row['id_rubrique'];
 		if ($row['lang'])
 			$lang = $row['lang'];
@@ -347,22 +348,22 @@ function sql_rubrique_fond($contexte, $lang) {
 	}
 
 	if ($id = intval($contexte['id_syndic'])) {
-	  $row = spip_abstract_fetch(spip_abstract_select(array(id_rubrique),
-							  array(syndic),
-							  array("id_syndic='$id'")));
+	  $row = spip_abstract_fetsel(array('id_rubrique'),
+				      array('syndic'),
+				      array("id_syndic='$id'"));
 		$id_rubrique_fond = $row['id_rubrique'];
-		$row = spip_abstract_fetch(spip_abstract_select(array(lang),
-								array(rubriques),
-								array("id_rubrique='$id_rubrique_fond'")));
+		$row = spip_abstract_fetsel(array('lang'),
+					    array('rubriques'),
+					    array("id_rubrique='$id_rubrique_fond'"));
 		if ($row['lang'])
 			$lang = $row['lang'];
 		return array($id_rubrique_fond, $lang);
 	}
 
 	if ($id = intval($contexte['id_article'])) {
-	  $row = spip_abstract_fetch(spip_abstract_select(array('id_rubrique', 'lang'),
-							  array('articles'),
-							  array("id_article='$id'")));
+	  $row = spip_abstract_fetsel(array('id_rubrique', 'lang'),
+				      array('articles'),
+				      array("id_article='$id'"));
 		$id_rubrique_fond = $row['id_rubrique'];
 		if ($row['lang'])
 			$lang = $row['lang'];
@@ -370,6 +371,4 @@ function sql_rubrique_fond($contexte, $lang) {
 	}
 }
 
-
-
 ?>
\ No newline at end of file
diff --git a/inc-calcul.php3 b/inc-calcul.php3
index 01ca64387ff979ce8102b0f7ab619061913eaf08..2789bf96d17b4448dfe7ee7ee76716dd9bb32eb4 100644
--- a/inc-calcul.php3
+++ b/inc-calcul.php3
@@ -386,4 +386,17 @@ function spip_abstract_free($res, $serveur='')
   $f = serveur_defini('spip_' . $serveur . '_free', $serveur);
   return $f($res);
 }
+
+# une composition tellement fréquente...
+
+function spip_abstract_fetsel(
+	$select = array(), $from = array(), $where = '',
+	$groupby = '', $orderby = '', $limit = '',
+	$sousrequete = '', $cpt = '',
+	$table = '', $id = '', $serveur='') {
+	return spip_abstract_fetch(spip_abstract_select(
+$select, $from, $where,	$groupby, $orderby, $limit,
+$sousrequete, $cpt, $table, $id, $serveur),
+				   $serveur);
+}
 ?>
diff --git a/inc-compilo-index.php3 b/inc-compilo-index.php3
index 2978e78ce02631c6a85aec55bd9ffaa75299d5ce..4cfb6867bf9297aad962006c0e2f6a1f34441fb5 100644
--- a/inc-compilo-index.php3
+++ b/inc-compilo-index.php3
@@ -74,6 +74,10 @@ class Champ {
 	var $document;   // pour embed et <img dans les textes
 }
 
+global $tables_des_serveurs_sql, $tables_principales;
+
+$tables_des_serveurs_sql = array('localhost' => &$tables_principales);
+
 // index_pile retourne la position dans la pile du champ SQL $nom_champ 
 // en prenant la boucle la plus proche du sommet de pile (indique par $idb).
 // Si on ne trouve rien, on considere que ca doit provenir du contexte 
@@ -83,7 +87,7 @@ class Champ {
 // afin de construire un requete SQL minimale (plutot qu'un brutal 'SELECT *')
 
 function index_pile($idb, $nom_champ, &$boucles, $explicite='') {
-	global $exceptions_des_tables, $table_des_tables, $tables_principales;
+  global $exceptions_des_tables, $table_des_tables, $tables_des_serveurs_sql;
 
 	$i = 0;
 	
@@ -100,16 +104,19 @@ function index_pile($idb, $nom_champ, &$boucles, $explicite='') {
 	while ($idb!== '') {
 #		spip_log("Cherche: $nom_champ '$idb' '$c'");
 		$r = $boucles[$idb]->type_requete;
-		// indirection (pour les rares cas ou le nom de la table est /= du type)
-		$t = $table_des_tables[$r];
-		if (!$t)
-			$t = $r; // pour les tables non Spip
+		$s = $boucles[$idb]->sql_serveur;
+		if (!$s) 
+		  { $s = 'localhost';
+    // indirection (pour les rares cas ou le nom de la table!=type)
+		    $t = $table_des_tables[$r];
+		  }
+		if (!$t) $t = $r; // pour les tables non Spip
 		// $t est le nom PHP de cette table 
 		#spip_log("Go: idb='$idb' r='$r' c='$c' nom='$nom_champ'");
-		$desc = $tables_principales[$t];
+		$desc = $tables_des_serveurs_sql[$s][$t];
 		if (!$desc) {
 			include_local("inc-admin.php3");
-			erreur_squelette(_L("Table SQL \"$r\" absente de \$tables_principales dans inc_serialbase"), "'$idb'");
+			erreur_squelette(_L("Table SQL \"$r\" inconnue"), "'$idb'");
 		}
 		$excep = $exceptions_des_tables[$r][$c];
 		if ($excep) {