diff --git a/.gitattributes b/.gitattributes
index 8311e28c9227b5e96eb8f5d9d59a014e247c7841..d4ceecfe8542aeb44c4408e2ea27298bfebe437a 100644
--- a/.gitattributes
+++ b/.gitattributes
@@ -214,6 +214,7 @@ dist/inc-petition.html -text
 dist/inc-pied.html -text
 dist/inc-rss-item.html -text
 dist/inc-rubriques.html -text
+dist/javascript/async_upload.js -text
 dist/javascript/jquery-1.0.2-forms.js -text
 dist/javascript/jquery-1.0.2-forms.pack.js -text
 dist/modeles/article_mots.html -text
@@ -383,6 +384,7 @@ ecrire/exec/delete_all.php -text
 ecrire/exec/demande_mise_a_jour.php -text
 ecrire/exec/discuter.php -text
 ecrire/exec/documenter.php -text
+ecrire/exec/documents_colonne.php -text
 ecrire/exec/documents_liste.php -text
 ecrire/exec/editer_auteurs.php -text
 ecrire/exec/editer_mot.php -text
diff --git a/dist/javascript/async_upload.js b/dist/javascript/async_upload.js
new file mode 100644
index 0000000000000000000000000000000000000000..e8f3e13c936e4f36a8708d8c7d74eb41a3cf366a
--- /dev/null
+++ b/dist/javascript/async_upload.js
@@ -0,0 +1,63 @@
+// JavaScript Document
+jQuery.async_upload_count = 0;
+jQuery.fn.async_upload = function(add_function) {
+  return this.submit(function(){
+    return do_async_upload(this);
+  });
+  
+  function do_async_upload(form) {
+    jQuery.async_upload_count++;
+    var num = jQuery.async_upload_count;
+    var jForm = $(form);
+    var par = $(jForm).parent();
+    $("div.upload_message",par)
+    .remove();
+    if(!form.async_init) {
+      form.async_init = true
+      jForm
+      .attr("target","upload_frame"+num)
+      .append("<input type='hidden' name='iframe' value='iframe'>")
+      .find("input[@name='redirect']")
+        .val("")
+      .end();
+    }
+  
+    if (!form.jFrame) {
+      form.jFrame = $("<iframe id='upload_frame"+num+"' name='upload_frame"+num+"' frameborder='0' marginwidth='0' marginheight='0' scrolling='no' style='position:absolute;display:none' onload='this.iframeload("+num+")'></iframe>")
+      .appendTo("body");
+    }
+    
+    //IE apparently do not write anything in an iframe onload event handler 
+    form.jFrame[0].iframeload = function(num) {
+        //remove the previous message
+        $("div.upload_message",par).remove();
+        var res = $(".upload_answer",this.contentDocument || document.frames(this.name).document.body);
+        //possible classes 
+        //upload_document_added
+        if(res.is(".upload_document_added")) {
+          return add_function(res,jForm);
+        }
+        //upload_error
+        if(res.is(".upload_error")) {
+          var msg = $("<div class='upload_message'>")
+          .append(res.html())
+          jForm.after(msg[0]);
+          return true;
+        } 
+        //upload_zip_list
+        if(res.is(".upload_zip_list")) {
+          var zip_form = $("<div class='upload_message'>").append(res.html());
+          zip_form
+          .find("form")
+            .attr("target","upload_frame"+num)
+            .append("<input type='hidden' name='iframe' value='iframe'>")
+          .end();
+          jForm.after(zip_form[0]);
+          return true;  
+        }
+    };
+    
+    jForm.before($("<div class='upload_message' style='height:1%'>").append(ajax_image_searching)[0]);
+    return true;
+  }
+}
diff --git a/ecrire/action/iconifier.php b/ecrire/action/iconifier.php
index c4b38c9d63fb9f1b7c03e761ee4676c61ab03cbd..50b0f11830b316cd617df2ce5f9a5ff4300230e6 100644
--- a/ecrire/action/iconifier.php
+++ b/ecrire/action/iconifier.php
@@ -19,6 +19,7 @@ function action_iconifier_dist()
 	$var_f = charger_fonction('controler_action_auteur', 'inc');
 	$var_f();
 	$arg = _request('arg');
+  $iframe_redirect = _request('iframe_redirect');
 
 	$arg = rawurldecode($arg);
 	if (!preg_match(',^\d*(\D)(.*)$,',$arg, $r))
@@ -26,6 +27,11 @@ function action_iconifier_dist()
 	elseif ($r[1] == '+')
 		action_spip_image_ajouter_dist($r[2]);
 	else	action_spip_image_effacer_dist($r[2]);
+	
+	if(_request("iframe") == 'iframe') {
+		$redirect = urldecode($iframe_redirect)."&iframe=iframe";
+		redirige_par_entete(urldecode($redirect));
+	}
 }
 
 // http://doc.spip.org/@action_spip_image_effacer_dist
diff --git a/ecrire/action/joindre.php b/ecrire/action/joindre.php
index 1ec972d01a6100dc0dd0683659c8edad84f9da62..d83341e554b08d5b1113e86cdd8dc7d036138bd0 100644
--- a/ecrire/action/joindre.php
+++ b/ecrire/action/joindre.php
@@ -32,7 +32,8 @@ function action_joindre_dist()
 	$var_f();
 
 	$redirect = _request('redirect');
-	if (!preg_match(',^(\d+)\D(\d+)\D(\w+)/(\w+)$,',_request('arg'),$r)) {
+	$iframe_redirect = _request('iframe_redirect');
+	if (!preg_match(',^(-?\d+)\D(\d+)\D(\w+)/(\w+)$,',_request('arg'),$r)) {
 	  spip_log("action_joindre_dist incompris: " . _request('arg'));
 	  redirige_par_entete(urldecode($redirect));
 	}
@@ -54,7 +55,7 @@ function action_joindre_dist()
 
      if (function_exists($sousaction))
        $type_image = $sousaction($path, $mode, $type, $id, $id_document, 
-				 $hash, $redirect, $documents_actifs);
+				 $hash, $redirect, $documents_actifs, $iframe_redirect);
 
      else spip_log("spip_action: sousaction inconnue $sousaction");
 
@@ -78,6 +79,11 @@ function action_joindre_dist()
 	include_spip('inc/rubriques');
 	calculer_rubriques();
      }
+
+	if(_request("iframe") == 'iframe') {
+		$redirect = urldecode($iframe_redirect)."&show_docs=".join(',',$documents_actifs)."&iframe=iframe";
+	}
+
 	redirige_par_entete($redirect);
      ## redirection a supprimer si on veut poster dans l'espace prive directement (UPLOAD_DIRECT)
 }
@@ -86,19 +92,19 @@ function action_joindre_dist()
 // Cas d'un document distant reference sur internet
 
 // http://doc.spip.org/@spip_action_joindre2
-function spip_action_joindre2($path, $mode, $type, $id, $id_document,$hash, $redirect, &$actifs)
+function spip_action_joindre2($path, $mode, $type, $id, $id_document,$hash, $redirect, &$actifs, $iframe_redirect)
 {
 	return examiner_les_fichiers(array(
 				   array('name' => basename($path),
 					 'tmp_name' => $path)
 				   ), 'distant', $type, $id, $id_document,
-			     $hash, $redirect, $actifs);
+			     $hash, $redirect, $actifs, $iframe_redirect);
 }
 
 // Cas d'un fichier transmis
 
 // http://doc.spip.org/@spip_action_joindre1
-function spip_action_joindre1($path, $mode, $type, $id, $id_document,$hash, $redirect, &$actifs)
+function spip_action_joindre1($path, $mode, $type, $id, $id_document,$hash, $redirect, &$actifs, $iframe_redirect)
 {
 	$files = array();
 	if (is_array($path))
@@ -108,13 +114,13 @@ function spip_action_joindre1($path, $mode, $type, $id, $id_document,$hash, $red
 	}
 
 	return examiner_les_fichiers($files, $mode, $type, $id, $id_document,
-			     $hash, $redirect, $actifs);
+			     $hash, $redirect, $actifs, $iframe_redirect);
 } 
 
 // copie de tout ou partie du repertoire upload
 
 // http://doc.spip.org/@spip_action_joindre3
-function spip_action_joindre3($path, $mode, $type, $id, $id_document,$hash, $redirect, &$actifs)
+function spip_action_joindre3($path, $mode, $type, $id, $id_document,$hash, $redirect, &$actifs, $iframe_redirect)
 {
 	if (!$path || strstr($path, '..')) return;
 	    
@@ -137,7 +143,7 @@ function spip_action_joindre3($path, $mode, $type, $id, $id_document,$hash, $red
 	  }
 	}
 
-	return examiner_les_fichiers($files, $mode, $type, $id, $id_document, $hash, $redirect, $actifs);
+	return examiner_les_fichiers($files, $mode, $type, $id, $id_document, $hash, $redirect, $actifs, $iframe_redirect);
 }
 
 //  Zip avec confirmation "tel quel"
@@ -155,7 +161,7 @@ function spip_action_joindre5($path, $mode, $type, $id, $id_document,$hash, $red
 // Zip a deballer.
 
 // http://doc.spip.org/@spip_action_joindre6
-function spip_action_joindre6($path, $mode, $type, $id, $id_document,$hash, $redirect, &$actifs)
+function spip_action_joindre6($path, $mode, $type, $id, $id_document,$hash, $redirect, &$actifs, $iframe_redirect)
 {
 	$x = joindre_deballes($path, $mode, $type, $id, $id_document,$hash, $redirect, $actifs);
 	//  suppression de l'archive en zip
@@ -165,14 +171,13 @@ function spip_action_joindre6($path, $mode, $type, $id, $id_document,$hash, $red
 
 // Zip avec les 2 options a la fois
 
-// http://doc.spip.org/@spip_action_joindre4
-function spip_action_joindre4($path, $mode, $type, $id, $id_document,$hash, $redirect, &$actifs)
+function spip_action_joindre4($path, $mode, $type, $id, $id_document,$hash, $redirect, &$actifs, $iframe_redirect)
 {
 	joindre_deballes($path, $mode, $type, $id, $id_document,$hash, $redirect, $actifs);
 	return spip_action_joindre5($path, $mode, $type, $id, $id_document,$hash, $redirect, $actifs);
 }
 
-// http://doc.spip.org/@joindre_deballes
+// http://doc.spip.org/@spip_action_joindre6
 function joindre_deballes($path, $mode, $type, $id, $id_document,$hash, $redirect, &$actifs)
 {
 	    define('_tmp_dir', creer_repertoire_documents($hash));
diff --git a/ecrire/exec/articles.php b/ecrire/exec/articles.php
index dcaa5e3d7b64592b8ca2fefb2e2932417edbd65e..5a8ea70c9d83466af7b3689c28ae0f6e5cdf18da 100644
--- a/ecrire/exec/articles.php
+++ b/ecrire/exec/articles.php
@@ -109,7 +109,7 @@ function articles_affiche($id_article, $row, $cherche_auteur, $ids, $cherche_mot
 
 	.	boite_info_articles($id_article, $statut_article, $visites, $id_version)
 
-	.	(!$iconifier ? '' : $iconifier('id_article', $id_article,'articles'))
+	.	(!$iconifier ? '' : $iconifier('id_article', $id_article,'articles','iconifier'))
 
 	.	boites_de_config_articles($id_article, $flag_editable)
 	.	boite_article_virtuel($id_article, $virtuel, $flag_editable) 
@@ -175,23 +175,42 @@ function articles_documents($flag_editable, $type, $id)
 		$f = charger_fonction('joindre', 'inc');
 
 		$res = debut_cadre_relief("image-24.gif", true, "", _T('titre_joindre_document'))
-		. $f('articles', "id_article=$id", $id, _T('info_telecharger_ordinateur'), 'document', 'article')
+		. $f('articles', "id_article=$id", $id, _T('info_telecharger_ordinateur'), 'document', 'article','',0,generer_url_ecrire("documenter","id_article=$id&type=$type",true))
 		. fin_cadre_relief(true);
 
 	// eviter le formulaire upload qui se promene sur la page
 	// a cause des position:relative incompris de MSIE
 
-		if ($align = ($GLOBALS['browser_name'] !== "MSIE")) {
+    $align = "";
+		if ($GLOBALS['browser_name']!='MSIE') {
 			$res = "\n<table width='50%' cellpadding='0' cellspacing='0' border='0'>\n<tr><td style='text-align: $spip_lang_left;'>\n$res</td></tr></table>";
 			$align = " align='right'";
 		}
 		$res = "\n<div$align>$res</div>";
-	} else $res ='';
+    $res .= "<script src='"._DIR_JAVASCRIPT."async_upload.js' type='text/javascript'></script>\n";
+    $res .= <<<EOF
+    <script type='text/javascript'>
+    $(".form_upload").async_upload(function(res){
+      res.find(">div").each(function(){
+        var cont = $("#"+this.id);
+        var self = $(this);
+        if(!cont.size()) {
+          cont = $(this.id.search(/--/)!=-1 ? "#portfolio":"#documents")
+          .append(self.clone().get());
+        }
+        verifForm(cont.html(self.html()));
+      });
+      return true;             
+    })
+    </script>
+EOF;
+		
+	} else $res = '';
 
 	$f = charger_fonction('documenter', 'inc');
 
-	return $f($id, 'article', 'portfolio', $flag_editable)
-	. $f($id, 'article', 'documents', $flag_editable)
+	return "<div id='portfolio'>" . $f($id, 'article', 'portfolio', $flag_editable) . "</div>"
+	. "<div id='documents'>" . $f($id, 'article', 'documents', $flag_editable) . "</div>"
 	. $res;
 }
 
diff --git a/ecrire/exec/articles_edit.php b/ecrire/exec/articles_edit.php
index 1d7aa5024581876ca4c21621a34555968e7f4e06..cd9172754272cfdb4507408de6cba9595f3a8f5f 100644
--- a/ecrire/exec/articles_edit.php
+++ b/ecrire/exec/articles_edit.php
@@ -63,13 +63,23 @@ function exec_articles_edit_dist()
 	// Pave "documents associes a l'article"
 
 	if (!$new){
-
 		# affichage sur le cote des pieces jointes, en reperant les inserees
 		# note : traiter_modeles($texte, true) repere les doublons
 		# aussi efficacement que propre(), mais beaucoup plus rapidement
 		traiter_modeles(join('',$row), true);
-		afficher_documents_colonne($id_article, 'article', true);
+		echo afficher_documents_colonne($id_article, 'article', true);
+	} else {
+		# ICI GROS HACK
+		# -------------
+		# on est en new ; si on veut ajouter un document, on ne pourra
+		# pas l'accrocher a l'article (puisqu'il n'a pas d'id_article)...
+		# on indique donc un id_article farfelu (0-id_auteur) qu'on ramassera
+		# le moment venu, c'est-à-dire lors de la creation de l'article
+		# dans editer_article.
+		echo afficher_documents_colonne(
+			0-$GLOBALS['auteur_session']['id_auteur'], 'article', true);
 	}
+
 	echo pipeline('affiche_gauche',array('args'=>array('exec'=>'articles_edit','id_article'=>$id_article),'data'=>''));
 	creer_colonne_droite();
 	echo pipeline('affiche_droite',array('args'=>array('exec'=>'articles_edit','id_article'=>$id_article),'data'=>''));
diff --git a/ecrire/exec/documenter.php b/ecrire/exec/documenter.php
index 5fa1c7fac63dc5367258614798bc28690f6d8d96..88a9fb1bc567e9599f0336dff6894fb0c9860aab 100644
--- a/ecrire/exec/documenter.php
+++ b/ecrire/exec/documenter.php
@@ -20,7 +20,7 @@ function exec_documenter_dist()
 {
 	$type = _request("type");
 	$script = _request("script"); // generalisation a tester
-	$album = !_request("s") ? 'documents' :  'portfolio'; 
+  $album = !_request("s") ? 'documents' :  'portfolio'; 
 	$id = intval(_request(($type == 'article') ? 'id_article' : 'id_rubrique'));
 	$id_auteur = $GLOBALS['auteur_session']['id_auteur'];
 	$statut = $GLOBALS['auteur_session']['statut'];
@@ -48,6 +48,11 @@ function exec_documenter_dist()
 	}
 
 	$documenter = charger_fonction('documenter', 'inc');
-	ajax_retour($documenter($id, $type, $album, 'ajax', '', $script));
+	if(_request("iframe")=="iframe") { 
+	 $res = $documenter($id, $type, "portfolio", 'ajax', '', $script).
+	        $documenter($id, $type, "documents", 'ajax', '', $script);
+	 echo "<div class='upload_answer upload_document_added'>".$res."</div>";
+	}	else 
+	 ajax_retour($documenter($id, $type, $album, 'ajax', '', $script));
 }
 ?>
diff --git a/ecrire/exec/documents_colonne.php b/ecrire/exec/documents_colonne.php
new file mode 100644
index 0000000000000000000000000000000000000000..83170223e07f984aca2281c3b2d92558422f5f6a
--- /dev/null
+++ b/ecrire/exec/documents_colonne.php
@@ -0,0 +1,44 @@
+<?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 exec_documents_colonne_dist()
+{
+	global $id, $type, $show_docs;
+	$id = intval($id);
+
+	if (!($type == 'article' 
+		? acces_article($id)
+		: acces_rubrique($id))) {
+		spip_log("Tentative d'intrusion de " . $GLOBALS['auteur_session']['nom'] . " dans " . $GLOBALS['exec']);
+		include_spip('inc/minipres');
+		minipres(_T('info_acces_interdit'));
+	}
+
+	include_spip("inc/documents");
+	include_spip("inc/presentation");
+
+	// TODO: return au lieu de echo
+	$documents = explode(",",$show_docs);
+	$script = $type."s_edit";
+	$res = "";
+	foreach($documents as $doc) {
+    $res .= afficher_case_document($doc, $id, $script, $type, $deplier = false);
+  }
+  
+  echo "<div class='upload_answer upload_document_added'>".
+	$res.
+	"</div>";
+}
+
+?>
diff --git a/ecrire/exec/iconifier.php b/ecrire/exec/iconifier.php
index 17c131236f072f8b7186b7359e1d92879fd898e0..e18a522626425453e7e7a44b57bc32920820e117 100644
--- a/ecrire/exec/iconifier.php
+++ b/ecrire/exec/iconifier.php
@@ -23,7 +23,7 @@ function exec_iconifier_dist()
 	$script = _request("script");
 	$type = _request("type");
 	$id = intval(_request($type));
-
+  
 	if (!preg_match('/^\w+$/', "$type$script"))
 		die(_T('info_acces_interdit'));
 
@@ -48,6 +48,14 @@ function exec_iconifier_dist()
 	}
 
 	$iconifier = charger_fonction('iconifier', 'inc');
-	ajax_retour($iconifier($type, $id, $script));
+	
+	$ret = $iconifier($type, $id, $script,"iconifier");
+	
+	if(_request("iframe")=="iframe") {
+    $ret = "<div class='upload_answer upload_document_added'>$ret</div>";
+    echo $ret;
+    die;
+  }
+  ajax_retour($ret);
 }
 ?>
diff --git a/ecrire/inc/documenter.php b/ecrire/inc/documenter.php
index e4f5da900a2367cb3ea59704c21fbb280870870e..81f2682053045268c9d5fde062a8e7949795fa5e 100644
--- a/ecrire/inc/documenter.php
+++ b/ecrire/inc/documenter.php
@@ -94,8 +94,7 @@ function inc_documenter_dist(
 
 	$s = ($ancre =='documents' ? '': '-');
 	if (is_int($doc)) {
-		$head = "\n<div id='$ancre'>&nbsp;</div>"
-		. "\n<div style='background-color: $couleur; padding: 4px; color: black; -moz-border-radius-topleft: 5px; -moz-border-radius-topright: 5px;' class='verdana2'>\n<b>".majuscules(_T("info_$ancre"))."</b></div>";
+		$head = "\n<div style='background-color: $couleur; padding: 4px; color: black; -moz-border-radius-topleft: 5px; -moz-border-radius-topright: 5px;' class='verdana2'>\n<b>".majuscules(_T("info_$ancre"))."</b></div>";
 
 		if (count($documents) > 3) {
 			$head .= "<div style='background-color: #dddddd; padding: 4px; color: black; text-align: right' class='arial1'>"
diff --git a/ecrire/inc/documents.php b/ecrire/inc/documents.php
index 71c9e1a01536469541d64a4ba9b13df760b649f7..40f5332e522c33fe330a688137d5ce3809badc63 100644
--- a/ecrire/inc/documents.php
+++ b/ecrire/inc/documents.php
@@ -120,14 +120,14 @@ function afficher_documents_colonne($id, $type="article", $flag_modif = true) {
 	$script = $type.'s_edit';
 
 	/// Ajouter nouvelle image
-	echo "<a name='images'></a>\n";
+	$ret .= "<a name='images'></a>\n";
 	$titre_cadre = _T('bouton_ajouter_image').aide("ins_img");
 
 	$joindre = charger_fonction('joindre', 'inc');
-	debut_cadre_relief("image-24.gif", false, "creer.gif", $titre_cadre);
-	echo $joindre($script, "id_$type=$id", $id, _T('info_telecharger'),'vignette',$type);
+	$ret .= debut_cadre_relief("image-24.gif", true, "creer.gif", $titre_cadre);
+	$ret .= $joindre($script, "id_$type=$id", $id, _T('info_telecharger'),'vignette',$type,'',0,generer_url_ecrire("documents_colonne","id=$id&type=$type",true));
 
-	fin_cadre_relief();
+	$ret .= fin_cadre_relief(true);
 
 	//// Documents associes
 	$res = spip_query("SELECT docs.id_document FROM spip_documents AS docs, spip_documents_".$type."s AS l WHERE l.id_".$type."=$id AND l.id_document=docs.id_document AND docs.mode='document' ORDER BY docs.id_document");
@@ -148,31 +148,68 @@ function afficher_documents_colonne($id, $type="article", $flag_modif = true) {
 	//// Images sans documents
 	$images_liees = spip_query("SELECT docs.id_document FROM spip_documents AS docs, spip_documents_".$type."s AS l "."WHERE l.id_".$type."=$id AND l.id_document=docs.id_document ".$docs_exclus."AND docs.mode='vignette' ORDER BY docs.id_document");
 
-	echo "\n<p />";
+	$ret .= "\n<p></p><div id='liste_images'>";
 	while ($doc = spip_fetch_array($images_liees)) {
 		$id_document = $doc['id_document'];
 		$deplier = $id_document_actif==$id_document;
-		afficher_case_document($id_document, $id, $script, $type, $deplier);
+		$ret .= afficher_case_document($id_document, $id, $script, $type, $deplier);
 	}
 
 	/// Ajouter nouveau document
-	echo "<p>&nbsp;</p>\n<a name='documents'></a>\n<a name='portfolio'></a>\n";
+	$ret .= "</div><p>&nbsp;</p>\n<a name='documents'></a>\n<a name='portfolio'></a>\n";
 	if ($type == "article") {
 		if ($GLOBALS['meta']["documents_article"] != 'non') {
 			$titre_cadre = _T('bouton_ajouter_document').aide("ins_doc");
-			debut_cadre_enfonce("doc-24.gif", false, "creer.gif", $titre_cadre);
-			echo $joindre($script, "id_$type=$id", $id, _T('info_telecharger_ordinateur'), 'document',$type);
-			fin_cadre_enfonce();
+			$ret .= debut_cadre_enfonce("doc-24.gif", true, "creer.gif", $titre_cadre);
+			$ret .= $joindre($script, "id_$type=$id", $id, _T('info_telecharger_ordinateur'), 'document',$type,'',0,generer_url_ecrire("documents_colonne","id=$id&type=$type",true));
+			$ret .= fin_cadre_enfonce(true);
 		}
 
 		// Afficher les documents lies
-		echo "<p />\n";
+		$ret .= "<p></p><div id='liste_documents'>\n";
 
-		foreach($documents_lies as $id_document) {
-			$deplier = $id_document_actif==$id_document;
-			afficher_case_document($id_document, $id, $script, $type, $deplier);
+		foreach($documents_lies as $doc) {
+			$ret .= afficher_case_document($doc, $id, $script, $type, $id_doc_actif == $doc);
 		}
+		$ret .= "</div>";
 	}
+  
+  $ret .= "<script src='"._DIR_JAVASCRIPT."async_upload.js' type='text/javascript'></script>\n";
+  $ret .= <<<EOF
+    <script type='text/javascript'>
+    $(".form_upload").async_upload(function(res,jForm){
+      var cont;
+      //add a class to new documents
+      res.
+      find(">div[@class]")
+        .addClass("documents_added")
+        .css("display","none")
+      .end();
+      if (jForm.find("input[@name='arg']").val().search("vignette")!=-1)
+        cont = $("#liste_images");
+      else
+        cont = $("#liste_documents");
+      cont
+      .prepend(res.html());
+      //find added documents, remove label and show them nicely
+      //set overflow to visible to completely show the overlay icon
+      cont.
+      find("div.documents_added")
+        .removeClass("documents_added")
+        .show("slow",function(){
+            var anim = $(this).css({"height":"","overflow":""});
+            //bug explorer-opera-safari
+            if(!jQuery.browser.mozilla) anim.width(this.orig.width-2);
+            $(anim).find("img[@onclick]").get(0).onclick();
+        })
+        .overflow("");
+      verifForm(cont);
+      return true;
+    })
+    </script>
+EOF;
+    
+	return $ret;
 }
 
 //
@@ -240,7 +277,7 @@ function afficher_case_document($id_document, $id, $script, $type, $deplier=fals
 	//
 	// Afficher un document
 	//
-
+	$ret = "";
 	if ($mode == 'document') {
 		if ($options == "avancees") {
 			# 'extension', a ajouter dans la base quand on supprimera spip_types_documents
@@ -256,53 +293,53 @@ function afficher_case_document($id_document, $id, $script, $type, $deplier=fals
 					break;
 			}
 
-		echo "<a id='document$id_document' name='document$id_document'></a>\n";
-		debut_cadre_enfonce("doc-24.gif", false, "", lignes_longues(typo($cadre),30));
+		$ret .= "<a id='document$id_document' name='document$id_document'></a>\n";
+		$ret .= debut_cadre_enfonce("doc-24.gif", true, "", lignes_longues(typo($cadre),30));
 
 		//
 		// Affichage de la vignette
 		//
-		echo "\n<div align='center'>";
-		echo document_et_vignette($document, $url, true); 
-		echo '</div>';
-		echo "\n<div class='verdana1' style='text-align: center; color: black;'>\n";
-		echo ($type_titre ? $type_titre : 
+		$ret .= "\n<div align='center'>";
+		$ret .= document_et_vignette($document, $url, true); 
+		$ret .= '</div>';
+		$ret .= "\n<div class='verdana1' style='text-align: center; color: black;'>\n";
+		$ret .= ($type_titre ? $type_titre : 
 		      ( _T('info_document').' '.majuscules($type_extension)));
-		echo "</div>";
+		$ret .= "</div>";
 
 		// Affichage du raccourci <doc...> correspondant
 		if (!$doublon) {
-			echo "\n<div style='padding:2px; font-size: 10px; font-family: arial,helvetica,sans-serif'>";
+			$ret .= "\n<div style='padding:2px; font-size: 10px; font-family: arial,helvetica,sans-serif'>";
 			if ($options == "avancees" AND ($type_inclus == "embed" OR $type_inclus == "image") AND $largeur > 0 AND $hauteur > 0) {
-				echo "<b>"._T('info_inclusion_vignette')."</b><br />";
+				$ret .= "<b>"._T('info_inclusion_vignette')."</b><br />";
 			}
-			echo "<div style='color: 333333'>"
+			$ret .= "<div style='color: 333333'>"
 			. affiche_raccourci_doc('doc', $id_document, 'left')
 			. affiche_raccourci_doc('doc', $id_document, 'center')
 			. affiche_raccourci_doc('doc', $id_document, 'right')
 			. "</div>\n";
-			echo "</div>";
+			$ret .= "</div>";
 
 			if ($options == "avancees" AND ($type_inclus == "embed" OR $type_inclus == "image") AND $largeur > 0 AND $hauteur > 0) {
-				echo "<div style='padding:2px; font-size: 10px; font-family: arial,helvetica,sans-serif'>";
-				echo "<b>"._T('info_inclusion_directe')."</b><br />";
-				echo "<div style='color: 333333'>"
+				$ret .= "<div style='padding:2px; font-size: 10px; font-family: arial,helvetica,sans-serif'>";
+				$ret .= "<b>"._T('info_inclusion_directe')."</b><br />";
+				$ret .= "<div style='color: 333333'>"
 				. affiche_raccourci_doc('emb', $id_document, 'left')
 				. affiche_raccourci_doc('emb', $id_document, 'center')
 				. affiche_raccourci_doc('emb', $id_document, 'right')
 				. "</div>\n";
-				echo "</div></div>";
+				$ret .= "</div>";
 			}
 		} else {
-			echo "<div style='padding:2px;'><font size='1' face='arial,helvetica,sans-serif'>",
-			  affiche_raccourci_doc('doc', $id_document, ''),
+			$ret .= "<div style='padding:2px;'><font size='1' face='arial,helvetica,sans-serif'>".
+			  affiche_raccourci_doc('doc', $id_document, '').
 			  "</font></div>";
 		}
 
 		$f = charger_fonction('legender', 'inc');
-		echo $f($id_document, $document, $script, $type, $id, "document$id_document", $deplier);
+		$ret .= $f($id_document, $document, $script, $type, $id, "document$id_document", $deplier);
 
-		fin_cadre_enfonce();
+		$ret .= fin_cadre_enfonce(true);
 		}
 	}
 
@@ -311,7 +348,7 @@ function afficher_case_document($id_document, $id, $script, $type, $deplier=fals
 	//
 	else if ($mode == 'vignette') {
 	
-		debut_cadre_relief("image-24.gif", false, "", lignes_longues(typo($cadre),30));
+		$ret .= debut_cadre_relief("image-24.gif", true, "", lignes_longues(typo($cadre),30));
 
 		//
 		// Preparer le raccourci a afficher sous la vignette ou sous l'apercu
@@ -328,7 +365,7 @@ function afficher_case_document($id_document, $id, $script, $type, $deplier=fals
 				. affiche_raccourci_doc($doc, $id_document, 'center')
 				. affiche_raccourci_doc($doc, $id_document, 'right');
 		} else {
-			$raccourci_doc .= affiche_raccourci_doc($doc, $id_document, '');;
+			$raccourci_doc .= affiche_raccourci_doc($doc, $id_document, '');
 		}
 		$raccourci_doc .= "</font></div>\n";
 
@@ -336,21 +373,22 @@ function afficher_case_document($id_document, $id, $script, $type, $deplier=fals
 		// Afficher un apercu (pour les images)
 		//
 		if ($type_inclus == 'image') {
-			echo "<div style='text-align: center; padding: 2px;'>\n";
-			echo document_et_vignette($document, $url, true);
-			echo "</div>\n";
+			$ret .= "<div style='text-align: center; padding: 2px;'>\n";
+			$ret .= document_et_vignette($document, $url, true);
+			$ret .= "</div>\n";
 			if (!$doublon)
-				echo $raccourci_doc;
+				$ret .= $raccourci_doc;
 		}
 
 		if ($doublon)
-			echo $raccourci_doc;
+			$ret .= $raccourci_doc;
 
 		$f = charger_fonction('legender', 'inc');
-		echo $f($id_document, $document, $script, $type, $id, "document$id_document", $deplier);
+		$ret .= $f($id_document, $document, $script, $type, $id, "document$id_document");
 		
-		fin_cadre_relief();
+		$ret .= fin_cadre_relief(true);
 	}
+	return $ret;
 }
 
 ?>
diff --git a/ecrire/inc/getdocument.php b/ecrire/inc/getdocument.php
index e2efe044b986f590a42ef66a2308f0acbb884fef..dfb04793f26aabcbdfaac51cd4c607124a899417 100644
--- a/ecrire/inc/getdocument.php
+++ b/ecrire/inc/getdocument.php
@@ -132,6 +132,11 @@ function check_upload_error($error, $msg='') {
 
 	spip_log ("erreur upload $error");
 
+  if(_request("iframe")=="iframe") {
+    echo "<div class='upload_answer upload_error'>$msg</div>";
+    exit;
+  }
+  
 	minipres($msg, '<form action="' .
 		rawurldecode($GLOBALS['redirect']).
 		'" method="post"><div align="'.  #ici method='post' permet d'aller au bon endroit, alors qu'en GET on perd les variables... mais c'est un hack sale.
@@ -145,13 +150,15 @@ function check_upload_error($error, $msg='') {
 // depuis qu'on est sortis de spip_image.php, apparemment).
 function erreur_upload_trop_gros() {
 	include_spip('inc/filtres');
-	minipres(_T('pass_erreur'),
-		"<p>"
+	
+	$msg = 		"<p>"
 		.taille_en_octets($_SERVER["CONTENT_LENGTH"])
 		.'<br />'
 		._T('upload_limit',
 		array('max' => ini_get('upload_max_filesize')))
-		."</p>");
+		."</p>";
+	
+  minipres(_T('pass_erreur'),"<div class='upload_answer upload_error'>".$msg."</div>");
 	exit;
 }
 
@@ -488,7 +495,7 @@ function traite_svg($file)
 //
 
 // http://doc.spip.org/@examiner_les_fichiers
-function examiner_les_fichiers($files, $mode, $type, $id, $id_document, $hash, $redirect, &$actifs)
+function examiner_les_fichiers($files, $mode, $type, $id, $id_document, $hash, $redirect, &$actifs, $iframe_redirect)
 {
 	if (function_exists('gzopen') 
 	AND !($mode == 'distant')
@@ -512,7 +519,7 @@ function examiner_les_fichiers($files, $mode, $type, $id, $id_document, $hash, $
 			if ($archive) {
 			  $valables = verifier_compactes($archive);
 			  if ($valables) {
-			    liste_archive_jointe($valables, $mode, $type, $id, $id_document, $hash, $redirect, $zip);
+			    liste_archive_jointe($valables, $mode, $type, $id, $id_document, $hash, $redirect, $zip, $iframe_redirect);
 			    exit;
 			  }
 			}
@@ -529,8 +536,7 @@ function examiner_les_fichiers($files, $mode, $type, $id, $id_document, $hash, $
 // Afficher un formulaire de choix: decompacter et/ou garder tel quel.
 // Passer ca en squelette un de ces jours.
 
-// http://doc.spip.org/@liste_archive_jointe
-function liste_archive_jointe($valables, $mode, $type, $id, $id_document, $hash, $redirect, $zip)
+function liste_archive_jointe($valables, $mode, $type, $id, $id_document, $hash, $redirect, $zip, $iframe_redirect)
 {
 	$arg = (intval($id) .'/' .intval($id_document) . "/$mode/$type");
 	$texte =
@@ -550,11 +556,25 @@ function liste_archive_jointe($valables, $mode, $type, $id, $id_document, $hash,
 		"<div style='text-align: right;'><input class='fondo' style='font-size: 9px;' type='submit' value='".
 		_T('bouton_valider').
 		  "'></div>";
-	$action = (construire_upload($texte, array(
+	echo "<p>build form $iframe_redirect</p>";
+  $action = construire_upload($texte, array(
 					 'redirect' => $redirect,
+					 'iframe_redirect' => $iframe_redirect,
 					 'hash' => $hash,
 					 'chemin' => $zip,
-					 'arg' => $arg)));
+					 'arg' => $arg));
+	
+	if(_request("iframe")=="iframe") {
+    echo "<div class='upload_answer upload_zip_list'><p>" .
+		_T('upload_fichier_zip_texte') .
+	  "</p><p>" .
+		_T('upload_fichier_zip_texte2') .
+	  "</p>" .
+	  $action.
+	  "</div>";
+    exit;
+  }
+  				 
 	minipres(_T('upload_fichier_zip'),
 	  "<p>" .
 		_T('upload_fichier_zip_texte') .
diff --git a/ecrire/inc/iconifier.php b/ecrire/inc/iconifier.php
index 566d17c275081822b706c4280856d8203a5feb8d..e3a18f83df126c254fdbc42bf4de90109a3bd815 100644
--- a/ecrire/inc/iconifier.php
+++ b/ecrire/inc/iconifier.php
@@ -15,14 +15,22 @@ if (!defined("_ECRIRE_INC_VERSION")) return;
 include_spip('inc/actions');
 
 // http://doc.spip.org/@inc_iconifier_dist
-function inc_iconifier_dist($id_objet, $id,  $script) {
+function inc_iconifier_dist($id_objet, $id,  $script, $iframe_script='') {
 
 	$texteon = $GLOBALS['logo_libelles'][($id OR $id_objet != 'id_rubrique') ? $id_objet : 'id_racine'];
 
 	$logo_f = charger_fonction('chercher_logo', 'inc');
 	
+	// Add the redirect url when uploading via iframe
+
+  $iframe = "";
+  if($iframe_script) {
+    $iframe_script = generer_url_ecrire($iframe_script,"type=$id_objet&$id_objet=$id&script=$script",true);
+    $iframe = "<input type='hidden' name='iframe_redirect' value='".rawurlencode($iframe_script)."' />\n";
+  }
+	
 	if (!$logo = $logo_f($id, $id_objet, 'on')) {
-		$masque = indiquer_logo($texteon, $id_objet, 'on', $id, $script);
+		$masque = indiquer_logo($texteon, $id_objet, 'on', $id, $script, $iframe);
 		$res = block_parfois_visible('on', "<b>$texteon</b>", $masque);
 	} else {
 		list($img, $clic) = decrire_logo($id_objet,'on',$id, 170, 170, $logo, $texteon, $script);
@@ -40,7 +48,7 @@ function inc_iconifier_dist($id_objet, $id,  $script) {
 
 			$res .= "<center>$masque</center>";
 		} else {
-		  $masque = indiquer_logo($texteoff, $id_objet, 'off', $id, $script);
+		  $masque = indiquer_logo($texteoff, $id_objet, 'off', $id, $script, $iframe);
 		  $res .= block_parfois_visible('off', "<b>$texteoff</b>", $masque);
 		}
 	}
@@ -51,7 +59,27 @@ function inc_iconifier_dist($id_objet, $id,  $script) {
 	. "</div>"
 	. fin_cadre_relief(true);
 
-	return ajax_action_greffe("iconifier-$id", $res);
+  $js = "";
+  if(_request("exec")!="iconifier") {
+      $js .= "<script src='"._DIR_JAVASCRIPT."async_upload.js' type='text/javascript'></script>\n";
+  		$js .= <<<EOF
+      <script type='text/javascript'>
+      $(".form_upload_icon").async_upload(upload_complete);
+      function upload_complete(res) {
+        res.find(">div").each(function(){
+          var cont = $("#"+this.id);
+          verifForm(cont.html($(this).html()));
+          cont.find("img[@onclick]").each(function(){this.onclick();})
+          $(".form_upload_icon").async_upload(upload_complete);
+        });
+        return true;                     
+      }
+      </script>
+EOF;
+    }
+
+  	return ajax_action_greffe("iconifier-$id", $res).$js;
+
 }
 
 global $logo_libelles;
@@ -66,7 +94,7 @@ $logo_libelles = array(
 		       );
 
 // http://doc.spip.org/@indiquer_logo
-function indiquer_logo($titre, $id_objet, $mode, $id, $script) {
+function indiquer_logo($titre, $id_objet, $mode, $id, $script, $iframe_script) {
 
 	global $formats_logos;
 	$dir_ftp = determine_upload();
@@ -110,8 +138,8 @@ function indiquer_logo($titre, $id_objet, $mode, $id, $script) {
 		return generer_action_auteur('iconifier',
 			"$id+$type$mode$id",
 			generer_url_ecrire($script, "$id_objet=$id", true), 
-			$afficher,
-			" method='post' enctype='multipart/form-data'");
+			$iframe_script.$afficher,
+			" method='post' enctype='multipart/form-data' class='form_upload_icon'");
 }
 
 // http://doc.spip.org/@decrire_logo
@@ -121,7 +149,7 @@ function decrire_logo($id_objet, $mode, $id, $width, $height, $img, $titre="", $
 
 	$res = ratio_image($fid, $nom, $format, $width, $height, "alt=''");
 	if ($res)
-	    $res = "<a href='" .	$fid . "'>$res</a>";
+	    $res = "<div><a href='" .	$fid . "'>$res</a></div>";
 	else
 	    $res = "<img src='$fid' width='$width' height='$height' alt=\"" . htmlentities($titre) . '" />';
 	if ($taille = @getimagesize($fid))
@@ -131,7 +159,7 @@ function decrire_logo($id_objet, $mode, $id, $width, $height, $img, $titre="", $
 			"<font size='1'>" .
 		     $taille .
 		     "\n<br />[" .
-		     ajax_action_auteur("iconifier", "$id-$nom.$format", $script, "$id_objet=$id&type=$id_objet", array(_T('lien_supprimer'))) .
+		     ajax_action_auteur("iconifier", "$id-$nom.$format", $script, "$id_objet=$id&type=$id_objet", array(_T('lien_supprimer')),'',"function(r,noeud) {noeud.innerHTML = r; \$('.form_upload_icon',noeud).async_upload(upload_complete);}") .
 		     "]</font>");
 }
 ?>
diff --git a/ecrire/inc/joindre.php b/ecrire/inc/joindre.php
index 095491bbf1a467f97f7031412a40c68d837544ef..4f531768e06e8a416a9b0e575e2e4372da5deff5 100644
--- a/ecrire/inc/joindre.php
+++ b/ecrire/inc/joindre.php
@@ -20,7 +20,7 @@ include_spip('base/abstract_sql');
 //
 
 // http://doc.spip.org/@inc_joindre_dist
-function inc_joindre_dist($script, $args, $id=0, $intitule='', $mode='', $type='', $ancre='', $id_document=0) {
+function inc_joindre_dist($script, $args, $id=0, $intitule='', $mode='', $type='', $ancre='', $id_document=0,$iframe_script='') {
 	global $spip_lang_right;
 	$vignette_de_doc = ($mode == 'vignette' AND $id_document>0);
 	$distant = ($mode == 'document' AND $type);
@@ -37,6 +37,12 @@ function inc_joindre_dist($script, $args, $id=0, $intitule='', $mode='', $type='
 		else
 			$dir_ftp = '';
 	}
+  
+  // Add the redirect url when uploading via iframe
+
+  $iframe = "";
+  if($iframe_script)
+    $iframe = "<input type='hidden' name='iframe_redirect' value='".rawurlencode($iframe_script)."' />\n";
 
 	// Un menu depliant si on a une possibilite supplementaire
 
@@ -76,8 +82,8 @@ function inc_joindre_dist($script, $args, $id=0, $intitule='', $mode='', $type='
 	return generer_action_auteur('joindre',
 		(intval($id) .'/' .intval($id_document) . "/$mode/$type"),
 		generer_url_ecrire($script, $args, true),
-		"$debut$intitule$res$dir_ftp$distant$fin",
-		" method='post' enctype='multipart/form-data'");
+		"$iframe$debut$intitule$res$dir_ftp$distant$fin",
+		" method='post' enctype='multipart/form-data' style='border: 0px; margin: 0px;' class='form_upload'");
 }
 
 
diff --git a/ecrire/inc/layer.php b/ecrire/inc/layer.php
index 0bd3daef6af19d43fae35c23f8a7ad0f8a0d908e..0a83527cc0523bff4b9a3887d9c960a5f60523ac 100644
--- a/ecrire/inc/layer.php
+++ b/ecrire/inc/layer.php
@@ -17,7 +17,7 @@ $numero_block = array();
 
 $compteur_block = 0;
 
-if (_request('var_ajaxcharset'))
+if (_request('var_ajaxcharset') || _request("iframe")=="iframe")
 $compteur_block = rand(1,2500)*500;	// astuce idiote pour que les blocs ahah n'aient pas les memes numeros de triangle que la page principale (sinon le triangle d'un bloc importe par ahah agit sur un autre triangle... vivement jquery...).
 
 // http://doc.spip.org/@block_parfois_visible
@@ -246,6 +246,10 @@ onclick='storeCaret(this);'
 onkeyup='storeCaret(this);'
 ondblclick='storeCaret(this);'");
 
+	// Hack pour forcer largeur des formo/forml sous Mozilla >= 1.7
+	// meme principe que le behavior win_width.htc pour MSIE
+$GLOBALS['browser_verifForm'] = (eregi("mozilla", $GLOBALS["browser_name"]) AND $GLOBALS["browser_rev"] >= 1.7) ?  "verifForm();" : "";
+
 // http://doc.spip.org/@http_script
 function http_script($script, $src='', $noscript='') {
 	return '<script type="text/javascript"'