diff --git a/.gitattributes b/.gitattributes
index 2997230f1781964cc43263f4bb9ddae2bc9dcf59..e10285bbb52117604543ade494be94bec85314d0 100644
--- a/.gitattributes
+++ b/.gitattributes
@@ -297,6 +297,8 @@ ecrire/plugins/get_infos.php -text
 ecrire/plugins/verifie_conformite.php -text
 ecrire/prive.php -text
 ecrire/public/aiguiller.php -text
+ecrire/public/creer_boucle_data.php -text
+ecrire/public/creer_boucle_enum.php -text
 ecrire/public/creer_boucle_pour.php -text
 ecrire/public/decompiler.php -text
 ecrire/public/format_html.php -text
diff --git a/ecrire/public/compiler.php b/ecrire/public/compiler.php
index e839b7c31b2c3723b821a350cbb09ecbd8805049..b97d623ae0196a017130aa158b81c62be3cc2c5e 100644
--- a/ecrire/public/compiler.php
+++ b/ecrire/public/compiler.php
@@ -242,21 +242,8 @@ function calculer_boucle_rec($id_boucle, &$boucles, $trace) {
 define('CODE_CORPS_BOUCLE', '%s
 	$t0 = "";
 	// REQUETE
-	$iter = new %s();
-	$iter->init( array(
-		"select"=>$select,
-		"from"=>$from,
-		"type"=>$type,
-		"where"=>$where,
-		"join"=>$join,
-		"groupby"=>$groupby,
-		"orderby"=>$orderby,
-		"limit"=>$limit,
-		"having"=>$having,
-		"table"=>$table,
-		"id"=>$id,
-		"connect"=>$connect
-		),
+	$iter = new %s(
+		%s,
 		array(%s)
 	);
 	if ($iter->ok) {
@@ -401,7 +388,46 @@ function calculer_boucle_nonrec($id_boucle, &$boucles, $trace) {
 	. calculer_requete_sql($boucles[$id_boucle]);
 
 	$contexte = memoriser_contexte_compil($boucle);
-	$a = sprintf(CODE_CORPS_BOUCLE, $init, $boucle->iterateur, $contexte, $nums, $init_lang, $corps, $fin_lang, $trace);
+
+	switch ($boucle->iterateur) {
+		case 'IterSQL':
+			$command = 'array(
+		"select"=>$select,
+		"from"=>$from,
+		"type"=>$type,
+		"where"=>$where,
+		"join"=>$join,
+		"groupby"=>$groupby,
+		"orderby"=>$orderby,
+		"limit"=>$limit,
+		"having"=>$having,
+		"table"=>$table,
+		"id"=>$id,
+		"connect"=>$connect
+		)';
+			break;
+
+		case 'IterPOUR':
+		case 'IterENUM':
+			$command = 'array("where" => $where, "source"=>$source, "sourcemode"=>$sourcemode, "limit" => $limit)';
+			break;
+
+		default:
+			$command = 'array()';
+			break;
+	}
+
+	$a = sprintf(CODE_CORPS_BOUCLE,
+		$init,
+		$boucle->iterateur,
+		$command,
+		$contexte,
+		$nums,
+		$init_lang,
+		$corps,
+		$fin_lang,
+		$trace
+	);
 
 #	var_dump($a);exit;
 	return $a;
diff --git a/ecrire/public/creer_boucle_data.php b/ecrire/public/creer_boucle_data.php
new file mode 100644
index 0000000000000000000000000000000000000000..28dcd84df8634469291fc1d4aa91af714f4d27d7
--- /dev/null
+++ b/ecrire/public/creer_boucle_data.php
@@ -0,0 +1,27 @@
+<?php
+
+/***************************************************************************\
+ *  SPIP, Systeme de publication pour l'internet                           *
+ *                                                                         *
+ *  Copyright (c) 2001-2010                                                *
+ *  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.   *
+\***************************************************************************/
+
+//
+// creer une boucle sur un iterateur DATA
+// annonce au compilo les "champs" disponibles
+//
+function public_creer_boucle_DATA_dist($b) {
+	$b->iterateur = 'IterPOUR'; # designe la classe d'iterateur
+	$b->show = array(
+		'field' => array(
+			'cle' => 'STRING',
+			'valeur' => 'STRING',
+		)
+	);
+	return $b;
+}
+
diff --git a/ecrire/public/creer_boucle_enum.php b/ecrire/public/creer_boucle_enum.php
new file mode 100644
index 0000000000000000000000000000000000000000..b970d04562be5e95014c6440a39898afd39934a4
--- /dev/null
+++ b/ecrire/public/creer_boucle_enum.php
@@ -0,0 +1,26 @@
+<?php
+
+/***************************************************************************\
+ *  SPIP, Systeme de publication pour l'internet                           *
+ *                                                                         *
+ *  Copyright (c) 2001-2010                                                *
+ *  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.   *
+\***************************************************************************/
+
+//
+// creer une boucle sur un iterateur ENUM
+// annonce au compilo les "champs" disponibles
+//
+function public_creer_boucle_ENUM_dist($b) {
+	$b->iterateur = 'IterENUM'; # designe la classe d'iterateur
+	$b->show = array(
+		'field' => array(
+			'valeur' => 'STRING',
+		)
+	);
+	return $b;
+}
+
diff --git a/ecrire/public/creer_boucle_pour.php b/ecrire/public/creer_boucle_pour.php
index cd5a55966328cb6d3132aea6a987dffe03041658..141112006d23510e7191a266d0f8905342ab19f3 100644
--- a/ecrire/public/creer_boucle_pour.php
+++ b/ecrire/public/creer_boucle_pour.php
@@ -12,7 +12,7 @@
 
 //
 // creer une boucle sur un iterateur POUR
-// definir les "champs" existants pour le compilo
+// annonce au compilo les "champs" disponibles
 //
 function public_creer_boucle_POUR_dist($b) {
 	$b->iterateur = 'IterPOUR'; # designe la classe d'iterateur
diff --git a/ecrire/public/criteres.php b/ecrire/public/criteres.php
index c0265cf7a6612353e8f4e71d3d48266c71cbb3e5..4d10729e1aebebaa1a9bc2fcb63f51f962d8a30e 100644
--- a/ecrire/public/criteres.php
+++ b/ecrire/public/criteres.php
@@ -1380,4 +1380,14 @@ function calculer_param_date($date_compare, $date_orig) {
 	$date_orig .
 	")))";
 }
+
+function critere_datasource($idb, &$boucles, $crit) {
+	$boucle = &$boucles[$idb];
+	$boucle->hash .= '
+	$source = '.calculer_liste($crit->param[0], array(), $boucles, $boucles[$idb]->id_parent).';
+	$sourcemode = '.calculer_liste($crit->param[1], array(), $boucles, $boucles[$idb]->id_parent).';';
+	$boucle->where['sourcemode'] = '$sourcemode';
+	$boucle->where['source'] = '$source';
+}
+
 ?>
diff --git a/ecrire/public/iterateur.php b/ecrire/public/iterateur.php
index 2ce263bc1973cc4d46e5139c282523cede54579c..70444e5a1f0c8030bad2d4ce4128a0e0dbd3a130 100644
--- a/ecrire/public/iterateur.php
+++ b/ecrire/public/iterateur.php
@@ -24,15 +24,12 @@ class Iter {
 
 	private $result = false;
 
-	public function Iter() {
-		$this->type = '??';
-	}
-
 	/*
 	 * array command: les commandes d'initialisation
 	 * array info: les infos sur le squelette
 	 */
-	public function init($command, $info=array()) {
+	public function Iter($command, $info=array()) {
+		$this->type = '??';
 		$this->command = $command;
 		$this->info = $info;
 	}
@@ -60,7 +57,7 @@ class IterSQL extends Iter {
 	 * array command: les commandes d'initialisation
 	 * array info: les infos sur le squelette
 	 */
-	public function init($command, $info=array()) {
+	public function IterSQL($command, $info=array()) {
 		$this->type='SQL';
 		$this->command = $command;
 		$this->info = $info;
@@ -86,6 +83,85 @@ class IterSQL extends Iter {
 	}
 }
 
+class IterENUM extends Iter {
+	var $ok = true;
+	var $type;
+	var $command;
+	var $info;
+
+	var $n = 0;
+	var $max = 1000000;
+
+	var $filtre = array();
+
+	private $result = false;
+
+	/*
+	 * array command: les commandes d'initialisation
+	 * array info: les infos sur le squelette
+	 */
+	public function IterENUM($command, $info=array()) {
+		$this->type='ENUM';
+		$this->command = $command;
+		$this->info = $info;
+
+		if (is_array($this->command['where']))
+		foreach ($this->command['where'] as $k => $com) {
+			switch($com[1]) {
+				case 'valeur':
+					unset($op);
+					if ($com[0] == 'REGEXP')
+						$this->filtre[] = 'preg_match("/". '.str_replace('\"', '"', $com[2]).'."/", $'.$com[1].')';
+					else if ($com[0] == '=')
+						$op = '==';
+					else if (in_array($com[0], array('<','<=', '>', '>=')))
+						$op = $com[0];
+
+					if ($op)
+						$this->filtre[] = '$'.$com[1].$op.str_replace('\"', '"', $com[2]);
+
+					break;
+			}
+
+		}
+
+		// critere {2,7}
+		if ($this->command['limit']) {
+			$limit = explode(',',$this->command['limit']);
+			$this->n = $limit[0];
+			$this->max = $limit[0]+$limit[1]-1;
+		}
+
+
+		// Appliquer les filtres sur (valeur)
+		if ($this->filtre) {
+			$this->filtre = create_function('$valeur', $b = 'return ('.join(') AND (', $this->filtre).');');
+		}
+
+	}
+	public function seek($n=0, $continue=null) {
+		$this->n = $n;
+		return true;
+	}
+	public function next() {
+		if ($f = $this->filtre) {
+			while (
+			$this->n < $this->max
+			AND !$f($a = $this->n++)){};
+		} else
+			$a = $this->n++;
+
+		if ($this->n <= 1+$this->max)
+			return array('valeur' => $a);
+	}
+	public function free(){
+	}
+	public function count() {
+		return $this->max;
+	}
+}
+
+
 class IterPOUR extends Iter {
 	var $ok = false;
 	var $type;
@@ -101,13 +177,53 @@ class IterPOUR extends Iter {
 	 * array command: les commandes d'initialisation
 	 * array info: les infos sur le squelette
 	 */
-	public function init($command, $info=array()) {
+	public function IterPOUR($command, $info=array()) {
 		$this->type='POUR';
 		$this->command = $command;
 		$this->info = $info;
 
 		// les commandes connues pour l'iterateur POUR
 		// sont : tableau=#ARRAY ; cle=...; valeur=...
+		// source URL
+		if (isset($this->command['source'])) {
+			if (preg_match(',^http://,', $this->command['source'])) {
+				include_spip('inc/distant');
+				$u = recuperer_page($this->command['source']);
+			} else
+				$u = spip_file_get_contents($this->command['source']);
+
+			// si c'est du RSS
+			if (isset($this->command['sourcemode'])) {
+				switch ($this->command['sourcemode']) {
+					case 'rss':
+						include_spip('inc/syndic');
+						if (is_array($rss = analyser_backend($u))) {
+							$this->tableau = $rss;
+							$this->ok = true;
+						}
+						break;
+					case 'json':
+						if (is_array($json = json_decode($u))) {
+							$this->tableau = $json;
+							$this->ok = true;
+						}
+						break;
+					case 'yaml':
+						include_spip('inc/yaml');
+						if (is_array($yaml = yaml_decode($u))) {
+							$this->tableau = $yaml;
+							$this->ok = true;
+						}
+						break;
+					case 'csv':
+						# decodage csv a peaufiner :-)
+						foreach(explode("\n",$u) as $ligne)
+							$this->tableau[] = explode(',', $ligne);
+						$this->ok = true;
+				}
+			}
+		}
+
 		if (is_array($this->command['where']))
 		foreach ($this->command['where'] as $k => $com) {
 			switch($com[1]) {