diff --git a/config.json b/config.json
index 27f950c8976c887efdafe22c4897bfdd9842a5c3..f73dbeb76e63b26c833c24eeff1c57d05758b465 100644
--- a/config.json
+++ b/config.json
@@ -1,21 +1,21 @@
 {
+	"connexion": {
+		"dn": "uid=quentin.chevalier,ou=eleves,dc=frankiz,dc=net",
+		"passwd": "Ie42fds'eaJm1"
+	},
 	"ldap": {
 		"server": "ldap://frankiz.eleves.polytechnique.fr:389",
 		"searchBase": "ou=eleves,dc=frankiz,dc=net",
 		"searchFilter": "(uid={{username}})"
 	},
-	"ldap_data_gl": {
-		"searchBase": "ou=groups,dc=frankiz,dc=net",
-		"searchFilter":"(restrictedMemberUid=${id})"
-	},
-	"ldap_data_ml": {
-		"searchBase": "ou=eleves,dc=frankiz,dc=net",
-		"searchFilter": "(brMemberOf=${id})"
-	},
-	"ldap_data_tol": {
-		"searchBase": "ou=eleves,dc=frankiz,dc=net",
-		"searchFilterAttributes": ["givenName", "sn", "brPromo","telephoneNumber","mail","brRoom","brIP","brMemberOf","brMemberOf","brMemberOf","brMemberOf","brMemberOf","brMemberOf"],
-		"searchAttributes": ["jpegPhoto","givenName", "sn", "brBirthdate", "brPromo","telephoneNumber","mail","brRoom","brIP"]
-	},
+	"dn_groups":"ou=groups,dc=frankiz,dc=net",
+	"dn_users": "ou=eleves,dc=frankiz,dc=net",
+	"filter_lm":"(brMemberOf=${id})",
+	"filter_al":"(brMemberOf=${id})",
+	"filter_lg":"(restrictedMemberUid=${id})",
+	"filter_st": "(uid=${id})",
+	"attributes_id": ["uid"],
+	"attributes_all": ["jpegPhoto","givenName", "sn", "brBirthdate", "brPromo","telephoneNumber","mail","brRoom","brIP"],
+	"search_attributes_tol": ["givenName", "sn", "displayName", "country", "brMemberOf", "brPromo", "brMemberOf", "brMemberOf", "brMemberOf", "telephoneNumber","mail","brRoom","brIP"],
 	"sessionSecret":"change this"
 }
\ No newline at end of file
diff --git a/src/ldap/ldap_data.js b/src/ldap/ldap_data.js
index 9a93f2dc203c022304c49b32f0e9bfcb13497c51..6abfba2df89c3e5932dae37d19f9aebd491f18f3 100644
--- a/src/ldap/ldap_data.js
+++ b/src/ldap/ldap_data.js
@@ -1,16 +1,16 @@
 /**
- * @file Ce fichier gère les requêtes LDAP de type données ; liste des groupe d'un individu="", liste des membres d'un groupe... A ne pas confondre avec ldap_auth qui lui gère l'authentification.
+ * @file Ce fichier gère les requêtes LDAP de type données ; liste des groupe d'un individu, liste des membres d'un groupe... A ne pas confondre avec ldap_auth qui lui gère l'authentification. Il est à lire conjointement avec config.json qui détaille les pats et champs spécifique à un LDAP.
  * @author hawkspar
-*/
+ */
 
-/* Ne pas hésiter à repasser en synthaxe ES5... Plus simple pour tester en solo avec node directement
+/* Ne pas hésiter à repasser en synthaxe ES5... Plus simple pour tester en solo avec node directement */
 import ldap  from 'ldapjs';
 import fs from 'fs';
-import ldapEscape from 'ldap-escape'; */
+import ldapEscape from 'ldap-escape';
 
-var ldap = require('ldapjs');
+/*var ldap = require('ldapjs');
 var fs = require('fs');
-var ldapEscape = require('ldap-escape');
+var ldapEscape = require('ldap-escape');*/
 
 // Important ; permet de vérifier que l'utilisateur reste connecté.
 var ensureLoggedin =  require('connect-ensure-login').ensureLoggedIn;
@@ -19,94 +19,201 @@ var ensureLoggedin =  require('connect-ensure-login').ensureLoggedIn;
 let config = JSON.parse(fs.readFileSync('../../config.json', 'utf8'));
 
 // Connection au serveur LDAP avec des temps de timeout arbitraires
-var client = ldap.createClient({ url: config.ldap.server, timeout: 10000, idleTimeout: 10000});
+var client = ldap.createClient({ url: config.ldap.server});
 
 /**
- * @summary Fonction qui interroge le LDAP et retrouve les groupes dont un individu est membre.
- * @desc Cette fonction utilise une Promise pour être asynchrone ; elle renvoit la promesse d'une réponse puis traite la demande. Il faut l'appeler suivant un schéma listGroups(uid).then((res) => { truc avec res });. Aucun bind n'est nécessaire donc pas d'identifiant ou de mot de passe à passer. Cette fonction fait une demande au LDAP qu'elle filtre selon un schéma prédéfini dans config.json et à chaque résultat (event SearchEntry) le met dans une liste, et renvoit la liste à l'issue (event end).
- * @arg {int} uid - Identifiant de l'individu à interroger
- * @return {string} Liste des uid de groupes (noms flat des groupes) où l'id fourni est membre
+ * @summary Fonction qui interroge le LDAP selon un protocole bien précis et renvoit les valeurs trouvées.
+ * @desc Cette fonction utilise une Promise pour être asynchrone ; elle renvoit la promesse d'une réponse puis traite la demande avec ldapjs (voir [`Client API`](http://ldapjs.org/client.html) méthode search). Il faut l'appeler suivant un schéma requeteLDAP(dic).then((res) => { truc avec res });. Cette fonction fait une demande au LDAP qu'elle filtre selon un schéma prédéfini dans `dic` et à chaque résultat (event SearchEntry) le met dans une liste, et renvoit la liste à l'issue (event end).
+ * @arg {string} base - DN de l'emplacement de la requête
+ * @arg {string} filter - Filtre logique de la recherche (format RFC2254)
+ * @arg {{}} filter_dic - Dictionnaire qui associe les faux champs dans filter aux vraies valeurs pertinentes de la recherche
+ * @arg {string[]} attributes - Liste des attributs qui figureront dans le résultat final
+ * @return {string[]} Résultats de la recherche
  */
-function listGroups(uid) {
+function requeteLDAP(base, filter, filter_dic, attributes) {
     return new Promise(function(resolve, reject) {
-        var groupsList=[];
-        
-        client.search(config.ldap_data_gl.searchBase, {scope: "sub", attributes: "uid", filter: ldapEscape.filter(config.ldap_data_gl.searchFilter, {id: uid})}, function(err, res) {
+        // A terme mettre id du type qui se connecte (permet de pas avoir trop de demandes trop rapides)
+        client.bind(config.connexion.dn, config.connexion.passwd, (err, res) => {});
+
+        var vals=[];
+        // Interrogation LDAP selon configuration du dic
+        client.search(base, {
+            "scope": "sub",
+            "filter": ldapEscape.filter(filter, filter_dic),
+            "attributes": attributes
+        }, function(err, res) {
+            // Gestion erreur
             if (err) {
                 reject(err);
             } else {
-                res.on('searchEntry', function(entry) { groupsList.push(entry.object.uid); });
-                res.on('end', function(res) { resolve(groupsList); });
+                // Dès que la recherche renvoit une entrée, on stocke les attributs qui nous intéresse
+                res.on('searchEntry', function(entry) {
+                    attributes.forEach((element) => {
+                        eval("vals.push(entry.object."+element+")");
+                        console.log(vals);
+                    });
+                });
+                // Si la recherche est finie on se déconnecte et on renvoit la liste
+                res.on('end', function(res) {
+                    client.bind("", "", (err, res) => {});
+                    resolve(vals);
+                });
             }
         });
     });
 }
+
+/**
+ * @summary Fonction qui interroge le LDAP et retrouve les groupes dont un individu est membre.
+ * @desc Cette fonction utilise requeteLDAP avec un dictionnaire prédéfini dans config.json.
+ * @arg {int} uid - Identifiant de l'individu à interroger
+ * @return {string} Liste des uid de groupes (noms flat des groupes) où l'id fourni est membre
+ */
+function listGroups(uid) {
+    return new Promise(function(resolve, reject) {
+        resolve(requeteLDAP(config.dn_groups, config.filter_lg, { id : uid }, config.attributes_id));
+    });
+}
  
 /**
  * @summary Fonction qui interroge le LDAP et retrouve la liste des membres d'un groupe.
- * @desc Cette fonction utilise une Promise pour être asynchrone ; elle renvoit la promesse d'une réponse puis traite la demande. Il faut l'appeler suivant un schéma listMembers(uid).then((res) => { truc avec res });. Aucun bind n'est nécessaire donc pas d'identifiant ou de mot de passe à passer. Cette fonction fait une demande au LDAP qu'elle filtre selon un schéma prédéfini dans config.json et à chaque résultat (event SearchEntry) le met dans une liste, et renvoit la liste à l'issue (event end).
+ * @desc Cette fonction utilise requeteLDAP avec un dictionnaire prédéfini dans config.json.
  * @arg {int} gid - Identifiant du groupe à interroger
  * @return {string} Liste des uid des membres où l'id fournie est membre (noms flat des groupes)
  */
 function listMembers(gid) {
     return new Promise(function(resolve, reject) {
-        var membersList=[];
-        
-        client.search(config.ldap_data_ml.searchBase="", {scope: "sub", attributes: "uid", filter: ldapEscape.filter(config.ldap_data_ml.searchFilter, {id: gid})}, function(err, res) {
-            if (err) {
-                reject(err);
-            } else {
-                res.on('searchEntry', function(entry) { membersList.push(entry.object.uid); });
-                res.on('end', function(res) { resolve(membersList); });
+        resolve(requeteLDAP(config.dn_users, config.filter_lm, { id: gid }, config.attributes_id));
+    });
+}
+ 
+/**
+ * @summary Fonction qui interroge le LDAP et retrouve la liste des admins d'un groupe.
+ * @desc Cette fonction utilise requeteLDAP avec un dictionnaire prédéfini dans config.json.
+ * @arg {int} gid - Identifiant du groupe à interroger
+ * @return {string} Liste des uid des membres où l'id fournie est membre (noms flat des groupes)
+ */
+function listAdmins(gid) {
+    //TBC
+    return new Promise(function(resolve, reject) {
+        resolve(requeteLDAP(gid, config.ldap_data_al));
+    });
+}
+ 
+/**
+ * @summary Fonction qui interroge le LDAP au sujet d'un uid particulier et qui renvoit toutes ses infos.
+ * @arg {string} uid - Identifiants de l'utilisateur
+ * @return {string[]} Informations recueillies ; même quand dans TOL voir config.json.
+ */
+function rens(uid) {
+    return new Promise(function(resolve, reject) {
+        resolve(requeteLDAP(config.dn_users, config.filter_st, { id: uid }, config.attributes_all));
+    });
+}
+
+/**
+ * @summary Fonction qui interroge le LDAP et retrouve juste les uid des paxs validant les critères de recherche. Première étape vers vrai TOL (Trombino On Line).
+ * @desc Accepte des champs exacts ou incomplets mais pas approximatifs et ne gère pas l'auto-complete. Cette fonction utilise une Promise pour être asynchrone ; elle renvoit la promesse d'une réponse puis traite la demande. Il faut l'appeler suivant un schéma TOL(uid).then((res) => { truc avec res });. Aucun bind n'est nécessaire donc pas d'identifiant ou de mot de passe à passer. Cette fonction fait une demande au LDAP qu'elle filtre selon un schéma généré à la volée à partir de config.json et à chaque résultat (event SearchEntry) le met dans une liste, et renvoit la liste à l'issue (event end). MEF Timeout pour des recherches trop vagues.
+ * @arg {string} c0 - Prénom
+ * @arg {string} c1 - Nom
+ * @arg {string} c2 - Surnom
+ * @arg {string} c3 - Nationalité
+ * @arg {string} c4 - Ecole ou université d'origine
+ * @arg {string} c5 - Promotion
+ * @arg {string} c6 - Groupe
+ * @arg {string} c7 - Cours
+ * @arg {string} c8 - Sport pratiqué
+ * @arg {string} c9 - Numéro de téléphone
+ * @arg {string} c10 - Adresse courriel
+ * @arg {string} c11 - Adresse physique
+ * @arg {string} c12 - Adresse ip
+ * @return {string[]} uids des profils qui "match" les critères proposés.
+ */
+function idTOL(c0="", c1="", c2="", c3="", c4="", c5="", c6="", c7="", c8="", c9="", c10="", c11="", c12="") {
+    return new Promise(function(resolve, reject) {
+        var filter="";
+        var filter_dic={};
+        // Iteration pour chaque champ, alourdissement du filtre selon des trucs prédéfini dans config.json encore
+        config.search_attributes_tol.forEach((element, index, list) => {
+            if (eval("c"+index) != '') {                                 // Si il y a qque chose à chercher pour ce filtre
+                filter="(&"+filter+"(|("+element+"=${app_"+element+index+"})"+      // On cherche la valeur exacte
+                                   "(|("+element+"=*${app_"+element+index+"})"+     // La valeur finale avec des trucs avant ; wildcard *
+                                   "(|("+element+"=*${app_"+element+index+"}*)"+    // La valeur du milieu avec des trucs avant et après
+                                     "("+element+"=${app_"+element+index+"}*)))))"; // La valeur du début avec des trucs après
+                // Mise en relation de chaque valeur à la demande utilisateur dans un dico
+                filter_dic["app_"+element+index]=eval("c"+index);
             }
         });
+
+        // Appel requeteLDAP avec filtre de l'espace 
+        resolve(requeteLDAP(config.dn_users, filter, filter_dic, config.attributes_id));
     });
 }
  
 /**
- * @summary Fonction qui interroge le LDAP et retrouve les paxs validant les critères de recherche.
- * @desc Accepte des champs incomplets mais pas approximatifs et ne gère pas l'auto-complete. Cette fonction utilise une Promise pour être asynchrone ; elle renvoit la promesse d'une réponse puis traite la demande. Il faut l'appeler suivant un schéma TOL(uid).then((res) => { truc avec res });. Aucun bind n'est nécessaire donc pas d'identifiant ou de mot de passe à passer. Cette fonction fait une demande au LDAP qu'elle filtre selon un schéma généré à la volée à partir de config.json et à chaque résultat (event SearchEntry) le met dans une liste, et renvoit la liste à l'issue (event end).
+ * @summary Fonction qui interroge le LDAP et retrouve les paxs validant les critères de recherche. Bien mais vite inutilisable car demande trop au LDAP.
+ * @desc Accepte des champs incomplets mais pas approximatifs et ne gère pas l'auto-complete. Cette fonction utilise une Promise pour être asynchrone ; elle renvoit la promesse d'une réponse puis traite la demande. Il faut l'appeler suivant un schéma TOL(uid).then((res) => { truc avec res });. Aucun bind n'est nécessaire donc pas d'identifiant ou de mot de passe à passer. Cette fonction fait une demande au LDAP qu'elle filtre selon un schéma généré à la volée à partir de config.json et à chaque résultat (event SearchEntry) le met dans une liste, et renvoit la liste à l'issue (event end). MEF Timeout pour des recherches trop vagues.
  * @arg {string} c0 - Prénom
  * @arg {string} c1 - Nom
  * @arg {string} c2 - Surnom
  * @arg {string} c3 - Nationalité
  * @arg {string} c4 - Ecole ou université d'origine
- * @arg {int} c5 - Promotion
+ * @arg {string} c5 - Promotion
  * @arg {string} c6 - Groupe
  * @arg {string} c7 - Cours
  * @arg {string} c8 - Sport pratiqué
- * @arg {int} c9 - Numéro de téléphone
+ * @arg {string} c9 - Numéro de téléphone
  * @arg {string} c10 - Adresse courriel
  * @arg {string} c11 - Adresse physique
  * @arg {string} c12 - Adresse ip
- * @return {string[]} Informations recueillies ; plusieurs fois une liste sur le format ci-dessus pour tous les résultats correspondants plus une photo en byttestring et date de naissance.
+ * @arg {int}
+ * @return {string[]} Informations recueillies ; voir config.json.
  */
 function TOL(c0="", c1="", c2="", c3="", c4="", c5="", c6="", c7="", c8="", c9="", c10="", c11="", c12="") {
     return new Promise(function(resolve, reject) {
-        var candidatesList=[];
+        // Pas nécessaire mais bien
+        client.bind(config.connexion.dn, config.connexion.passwd, (err, res) => {});
 
         var filter="";
         var dic={};
-
+        // Iteration pour chaque champ, alourdissement du filtre selon des trucs prédéfini dans config.json encore
         config.ldap_data_tol.searchFilterAttributes.forEach((element, index, list) => {
-            if (eval("c"+index.toString()) != '') {
-                filter="(&"+filter+"(|("+element+"=*${app_"+element+index+"})"+
-                                "(|("+element+"=${app_"+element+index+"})"+
-                                "(|("+element+"=*${app_"+element+index+"}*)"+
-                                    "("+element+"=${app_"+element+index+"}*)))))";
+            if (eval("c"+index.toString()) != '') {                                 // Si il y a qque chose à chercher pour ce filtre
+                filter="(&"+filter+"(|("+element+"=${app_"+element+index+"})"+      // On cherche la valeur exacte
+                                   "(|("+element+"=*${app_"+element+index+"})"+     // La valeur finale avec des trucs avant ; wildcard *
+                                   "(|("+element+"=*${app_"+element+index+"}*)"+    // La valeur du milieu avec des trucs avant et après
+                                     "("+element+"=${app_"+element+index+"}*)))))"; // La valeur du début avec des trucs après
+                // Mise en relation de chaque valeur à la demande utilisateur dans un dico
                 dic["app_"+element+index]=eval("c"+index.toString());
             }
         });
+        // Debug
+        //console.log(filter);
+        //console.log(dic);
 
-        client.search(config.ldap_data_tol.searchBase, {scope: "sub", attributes: config.ldap_data_tol.searchAttributes, filter: ldapEscape.filter(filter, dic)}, function(err, res) {
+        var candidatesList=[];
+
+        // Interrogation LDAP et filtre de malade
+        client.search(config.ldap_data_tol.searchBase, { 
+            scope: "sub",
+            attributes: config.ldap_data_tol.searchAttributes,
+            filter: ldapEscape.filter(filter, dic)
+        },
+        function(err, res) {
+            // Gestion erreur
             if (err) {
                 reject(err);
             } else {
+                // Toujours gestion différenciée début et fin
                 res.on('searchEntry', function(entry) {
-                    for (var i=0; i<config.ldap_data_tol.searchAttributes.length; i++) {
-                        // Complicated, but hides searchAttributes
-                        eval("candidatesList.push(entry.object."+config.ldap_data_tol.searchAttributes[i]+")");
-                    }
+                    // De nouveau, iteration sur les valeurs recherchées et entrée dans la liste
+                    config.ldap_data_tol.searchAttributes.forEach((element) => {
+                        eval("candidatesList.push(entry.object."+element+")");
+                    });
+                });
+                res.on('page', function(result, cb) {
+                    resolve(candidatesList);
+                    console.log("page ends");
                 });
                 res.on('end', function(res) { resolve(candidatesList); });
             }
@@ -114,11 +221,13 @@ function TOL(c0="", c1="", c2="", c3="", c4="", c5="", c6="", c7="", c8="", c9="
     });
 }
 
-// Synthaxe d'utilisation
-//listGroups("quentin.louis").then((meList) => { console.log(meList); });
-TOL("","","","","","","faerix","","","","","","").then((meList) => { console.log(meList); });
+//listMembers("drakkes").then((meList) => { console.log(meList); });
+//listGroups("agopia.1999").then((grList) => { console.log(grList); });
+//rens("quentin.louis").then((profil) => { console.log(profil); });
+//idTOL("","","","","","","bda","","","","","","").then((caList) => { console.log(caList); });
+//TOL("","","","","","","faerix","","","","","","").then((caList) => { console.log(caList); });
 
-/* Partage pour le reste du monde ; même remarque synthaxe  
-export { listGroups, listMembers, TOL }; */
+/* Partage pour le reste du monde ; même remarque synthaxe que pour l'import */
+export { listGroups, listMembers, TOL };
 
-module.exports ={ listGroups, listMembers, TOL };
\ No newline at end of file
+/*module.exports ={ listGroups, listMembers, TOL };*/
\ No newline at end of file