diff --git a/VERSIONS b/VERSIONS
index 60c9b5d29efa90a2372154d457cef4469a660a87..e8b8f994db9e06d6a642baa6a1195c07c9cf64f8 100644
--- a/VERSIONS
+++ b/VERSIONS
@@ -1,13 +1,33 @@
+03/11/2015 - v7.3.23
+
+ - ticket #30552 : Nanook: affectation de l'abonné à la bonne bibliothèque à la création temps réel. Nécessite Nanook 3.0
+ 
+ - ticket #31887 : L'extension de recherche peut prendre en charge Gallica
+ 
+ - ticket #31425 : Patch sql de suppression des pseudos notices orphelines
+ 
+ - ticket #29373 : Module sitothèque : correction de la sauvegarde du paramètre "groupement par catégorie"
+ 
+ - ticket #31237 : Correction de l'affichage de la langue dans un détail notice
+ 
+ - ticket #28103 : Correction de l'exécution des batchs qui empêchait le moissonage des vignettes d'album 1dtouch
+
+ - ticket #32225 : Enrichissement Premiere: adaptation au changement du site
+
+ - ticket #32112 : Connection de l'explorateur de fichiers avec l'authentification Bokeh
+
+
+
 28/10/2015 - v7.3.22
 
  - ticket #31941 : Correction compatibilité explorateur de fichier / hébergement mutualisé sans sous-répertoire
- 
+
  - ticket #27768 : Affichage en mode liste des articles, correctif des problèmes suivant : 
-  * le filtre ne descend pas dans les sous-catégories 
+  * le filtre ne descend pas dans les sous-catégories
   * la pagination ne fonctionne pas après une recherche
   * la recherche ne se fait que dans le portail
 
- - ticket #30552 : 
+ - ticket #30552 :
     - La longueur maxi d'un pseudo passe a 100 caractères
     - correction du bug : lors de la mise a jour du pseudo l'abonné se retrouve en invite
 
@@ -20,7 +40,7 @@
 26/10/2015 - v7.3.20
 
  - ticket #31732 : correction des popups multiples en cliquant sur les vignettes de notices dans certains navigateurs
-  
+
  - correction affichage des avis dans la boite avis.
 
 
diff --git a/application/modules/admin/controllers/AccueilController.php b/application/modules/admin/controllers/AccueilController.php
index 4106298f732675b7c0b020f55dc843ca0be21819..0219df7f483368585348d7f511e91bdcec7572b7 100644
--- a/application/modules/admin/controllers/AccueilController.php
+++ b/application/modules/admin/controllers/AccueilController.php
@@ -19,499 +19,499 @@
  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301  USA
  */
 class Admin_AccueilController extends Zend_Controller_Action {
-	private $id_profil;										// Profil a modifier
-	private $config;											// Qui a appelé la config : "admin" ou "accueil"
-	private $id_module;										// Identifiant unique du module a traiter
-	private $type_module;									// Identifiant du module à traiter
+  private $id_profil;                   // Profil a modifier
+  private $config;                      // Qui a appelé la config : "admin" ou "accueil"
+  private $id_module;                   // Identifiant unique du module a traiter
+  private $type_module;                 // Identifiant du module à traiter
 
-	/** @var Class_Systeme_ModulesAccueil */
-	private $_systemeModulesAccueil;
+  /** @var Class_Systeme_ModulesAccueil */
+  private $_systemeModulesAccueil;
 
 
-	public function preDispatch() {
-		parent::preDispatch();
+  public function preDispatch() {
+    parent::preDispatch();
 
-		// Changer le layout
-		$viewRenderer = $this->getHelper('ViewRenderer');
-	 	$viewRenderer->setLayoutScript('subModal.phtml');
+    // Changer le layout
+    $viewRenderer = $this->getHelper('ViewRenderer');
+    $viewRenderer->setLayoutScript('subModal.phtml');
 
-		// Recup des parametres
-		$this->id_module = $this->_request->getParam("id_module");
-		$this->id_profil = $this->_request->getParam("id_profil");
-		$this->config = $this->_request->getParam("config");
+    // Recup des parametres
+    $this->id_module = $this->_request->getParam("id_module");
+    $this->id_profil = $this->_request->getParam("id_profil");
+    $this->config = $this->_request->getParam("config");
 
-		// On initalise les proprietes
-		if (!$this->profil = Class_Profil::find($this->id_profil)) {
-			$this->profil = Class_Profil::getCurrentProfil();
-			$this->id_profil = $this->profil->getId();
-		}
+    // On initalise les proprietes
+    if (!$this->profil = Class_Profil::find($this->id_profil)) {
+      $this->profil = Class_Profil::getCurrentProfil();
+      $this->id_profil = $this->profil->getId();
+    }
 
-		$this->type_module = $this->_getParam('type_module');
+    $this->type_module = $this->_getParam('type_module');
 
-		$user = Class_Users::getIdentity();
+    $user = Class_Users::getIdentity();
 
-		if ((!$user->isAdminBib() && !$user->hasRightConfigFront())
-				|| ($user->isAdminBib() && ($user->getIdSite() !== $this->profil->getIdSite()))) {
-			 $this->_redirect('admin/index');
-			 return;
-		}
+    if ((!$user->isAdminBib() && !$user->hasRightConfigFront())
+        || ($user->isAdminBib() && ($user->getIdSite() !== $this->profil->getIdSite()))) {
+      $this->_redirect('admin/index');
+      return;
+    }
 
-		$this->preferences = ($this->config == 'admin')
-			? $this->_extractProperties()
-			: $this->profil->getOrCreateConfigAccueil($this->id_module, $this->type_module);
+    $this->preferences = ($this->config == 'admin')
+      ? $this->_extractProperties()
+      : $this->profil->getOrCreateConfigAccueil($this->id_module, $this->type_module);
 
-		$boite = isset($this->preferences["boite"]) ? $this->preferences["boite"] : '';
-		$this->view->preferences = $this->preferences;
-		$this->view->url = $this->_request->getRequestUri();
+    $boite = isset($this->preferences["boite"]) ? $this->preferences["boite"] : '';
+    $this->view->preferences = $this->preferences;
+    $this->view->url = $this->_request->getRequestUri();
 
-		$this->view->combo_templates = ZendAfi_View_Helper_Accueil_Base::getComboTemplates($boite, $this->profil);
-		$this->view->id_profil = $this->profil->getId();
-		$this->view->profil = $this->profil;
-		$this->view->id_bib = $this->profil->getIdSite();
+    $this->view->combo_templates = ZendAfi_View_Helper_Accueil_Base::getComboTemplates($boite, $this->profil);
+    $this->view->id_profil = $this->profil->getId();
+    $this->view->profil = $this->profil;
+    $this->view->id_bib = $this->profil->getIdSite();
 
-		$this->_systemeModulesAccueil = new Class_Systeme_ModulesAccueil();
+    $this->_systemeModulesAccueil = new Class_Systeme_ModulesAccueil();
 
-		Zend_Layout::startMvc([]);
-	}
+    Zend_Layout::startMvc([]);
+  }
 
 
-	public function addBlockAction() {
-		if ($this->_request->isPost()) {
-			$post = $this->_request->getPost();
-			$new_id = $this->profil->createNewModuleAccueilId();
-			$division = $this->_getParam('division');
-			$parent_id = $this->_getParam('id_module');
+  public function addBlockAction() {
+    if ($this->_request->isPost()) {
+      $post = $this->_request->getPost();
+      $new_id = $this->profil->createNewModuleAccueilId();
+      $division = $this->_getParam('division');
+      $parent_id = $this->_getParam('id_module');
+      $config = ['type_module' => $post['module_type'],
+                 'preferences' => Class_Systeme_ModulesAccueil::getValeursParDefaut($post['module_type']),
+                 'division' => $division];
 
-			$config = ['type_module' => $post['module_type'],
-								 'preferences' => Class_Systeme_ModulesAccueil::getValeursParDefaut($post['module_type']),
-								 'division' => $division];
+      $config['preferences']['titre'] = $post['titre'];
+      $config['preferences']['boite'] = $post['boite'];
 
-			$config['preferences']['titre'] = $post['titre'];
-			$config['preferences']['boite'] = $post['boite'];
+      $parent_position = $this->profil->getModulePositionInDiv($parent_id, $division);
 
-			$parent_position = $this->profil->getModulePositionInDiv($parent_id, $division);
+      $this->profil->updateModuleConfigAccueil($new_id, $config);
+      $my_position = $this->profil->getModulePositionInDiv($new_id, $division);
+      $this->profil
+        ->moveModuleOldDivPosNewDivPos($division, $my_position,
+                                       $division, $parent_position + 1)
+        ->save();
 
-			$this->profil->updateModuleConfigAccueil($new_id, $config);
-			$my_position = $this->profil->getModulePositionInDiv($new_id, $division);
-			$this->profil
-				->moveModuleOldDivPosNewDivPos($division, $my_position,
-																			 $division, $parent_position + 1)
-				->save();
+      $this->view->reload = 'SITE';
+      $viewRenderer = $this->getHelper('ViewRenderer');
+      $viewRenderer->renderScript('accueil/_retour.phtml');
+    }
+  }
 
-			$this->view->reload = 'SITE';
-			$viewRenderer = $this->getHelper('ViewRenderer');
-			$viewRenderer->renderScript('accueil/_retour.phtml');
-		}
-	}
 
+  public function deleteBlockAction() {
+    $this->profil
+      ->removeBoiteFromDiv($this->_getParam('id_module'),
+                           $this->_getParam('division'))
+      ->save();
 
-	public function deleteBlockAction() {
-		$this->profil
-			->removeBoiteFromDiv($this->_getParam('id_module'),
-													 $this->_getParam('division'))
-			->save();
+    $this->_redirect($this->view->url(['id_profil' => $this->profil->getId()],
+                                      null, true),
+                     ['prependBase' => false]);
+  }
 
-		$this->_redirect($this->view->url(['id_profil' => $this->profil->getId()],
-																			null, true),
-										 ['prependBase' => false]);
-	}
 
+  public function calendrierAction()  {
+    $this->_simpleAction('CALENDAR');
+  }
 
-	public function calendrierAction()	{
-		$this->_simpleAction('CALENDAR');
-	}
 
+  public function menuverticalAction()  {
+    $this->_simpleAction('MENU_VERTICAL');
+  }
 
-	public function menuverticalAction()	{
-		$this->_simpleAction('MENU_VERTICAL');
-	}
 
+  public function rechguideeAction() {
+    $this->_simpleAction('RECH_GUIDEE');
+  }
 
-	public function rechguideeAction() {
-		$this->_simpleAction('RECH_GUIDEE');
-	}
 
+  public function rechsimpleAction() {
+    $this->view->getHelper('ComboProfils')
+               ->setTagId('profil_redirect')
+               ->setTagName('profil_redirect')
+               ->addEmptyOption();
 
-	public function rechsimpleAction() {
-		$this->view->getHelper('ComboProfils')
-			->setTagId('profil_redirect')
-			->setTagName('profil_redirect')
-			->addEmptyOption();
+    $this->_simpleAction('RECH_SIMPLE');
+  }
 
-		$this->_simpleAction('RECH_SIMPLE');
-	}
 
+  public function cartezonesAction() {
+    $this->_simpleAction('CARTE_ZONES');
+  }
 
-	public function cartezonesAction() {
-		$this->_simpleAction('CARTE_ZONES');
-	}
 
+  public function preprocessSitoCategories() {
+    if ((int)$this->_getParam('type_aff',0)!=3)
+      return;
 
-	public function preprocessSitoCategories() {
-		if ((int)$this->_getParam('type_aff',0)!=3)
-			return;
+    if ($categories=explode('-',$this->_getParam('id_categorie')))
+      $this->_request->setPost('id_categorie',$categories[0]);
 
-		if ($categories=explode('-',$this->_getParam('id_categorie')))
-			$this->_request->setPost('id_categorie',$categories[0]);
+  }
+  public function sitothequeAction() {
+    $this->preprocessSitoCategories();
+    if ($this->_request->getPost('type_aff') == ZendAfi_View_Helper_Accueil_Sito::DISPLAY_HIERARCHY)
+      $this->_request->setPost('group_by_categorie','0');
+    $this->_simpleAction('SITO');
+  }
 
-	}
-	public function sitothequeAction() {
-		$this->preprocessSitoCategories();
-		$this->_request->setPost('group_by_categorie','0');
-		$this->_simpleAction('SITO');
-	}
 
-
-	public function domainBrowserAction() {
-		$this->view->module_settings = $this->profil
-			->getModuleAccueilConfig($this->id_module, 'DOMAIN_BROWSER')['preferences'];
-		$this->_simpleAction('DOMAIN_BROWSER');
-	}
+  public function domainBrowserAction() {
+    $this->view->module_settings = $this->profil
+      ->getModuleAccueilConfig($this->id_module, 'DOMAIN_BROWSER')['preferences'];
+    $this->_simpleAction('DOMAIN_BROWSER');
+  }
 
 
-	public function formationsWidgetAction() {
-		$this->view->module_settings = $this->profil
-			->getModuleAccueilConfig($this->id_module, 'FORMATIONS_WIDGET')['preferences'];
-		$this->_simpleAction('FORMATIONS_WIDGET');
-	}
+  public function formationsWidgetAction() {
+    $this->view->module_settings = $this->profil
+      ->getModuleAccueilConfig($this->id_module, 'FORMATIONS_WIDGET')['preferences'];
+    $this->_simpleAction('FORMATIONS_WIDGET');
+  }
 
 
-	public function newsAction() {
-		if (1 == $this->_getParam('styles_reload')) {
-			$this->view->preferences = $this->_request->getPost();
-			return;
-		}
+  public function newsAction() {
+    if (1 == $this->_getParam('styles_reload')) {
+      $this->view->preferences = $this->_request->getPost();
+      return;
+    }
 
-		$this->_simpleAction('NEWS');
-	}
+    $this->_simpleAction('NEWS');
+  }
 
 
-	public function rssAction() {
-		$this->_simpleAction('RSS');
-	}
+  public function rssAction() {
+    $this->_simpleAction('RSS');
+  }
 
 
-	public function langueAction() {
-		$this->_simpleAction('LANGUE');
-	}
+  public function langueAction() {
+    $this->_simpleAction('LANGUE');
+  }
 
 
-	public function loginAction() {
-		$this->_simpleAction('LOGIN');
-	}
+  public function loginAction() {
+    $this->_simpleAction('LOGIN');
+  }
 
 
-	public function libraryAction() {
+  public function libraryAction() {
     $this->view->module_settings = $this->profil
-			->getModuleAccueilConfig($this->id_module, 'LIBRARY')['preferences'];
-		$this->_simpleAction('LIBRARY');
-	}
-
-
-	public function compteursAction() {
-		$this->_simpleAction('COMPTEURS');
-	}
-
-	public function pretsAction() {
-		$this->_simpleAction('PRETS');
-	}
-
-	public function historiqueRecherchesAction() {
-		$this->_simpleAction('HISTORIQUE_RECHERCHES');
-	}
-
-	public function reservationsAction() {
-		$this->_simpleAction('RESERVATIONS');
-	}
-
-	public function multimediaAction() {
-		$this->_simpleAction('MULTIMEDIA');
-	}
-
-	public function newslettersAction() {
-		$this->_simpleAction('NEWSLETTERS');
-	}
-
-	public function panierAction() {
-		$this->_simpleAction('PANIER');
-	}
-
-
-	public function bibliothequeNumeriqueAction() {
-		if (1 == $this->_getParam('styles_reload')) {
-			$this->view->preferences = $this->_request->getPost();
-		} else {
-			$this->_simpleAction('BIB_NUMERIQUE');
-		}
-
-		$this->view->categories = Class_AlbumCategorie::getLoader()->getCollections();
-		$moduleBibNumerique = $this->_systemeModulesAccueil->getModuleByCode('BIB_NUMERIQUE');
-		$this->view->displayModes = $moduleBibNumerique->getDisplayModes();
-		$this->view->orderModes = $moduleBibNumerique->getOrderModes();
-
-		$this->view->albums = Class_AlbumCategorie::getLoader()->findAlbumsRecursively();
-	}
-
-
-	public function tagsAction() {
-		// Retour du formulaire
-		if ($this->_request->isPost()) {
-			$enreg = $this->_request->getPost();
-			$enreg['nombre'] = (int)$this->_getParam('nombre', 10);
-			$enreg['limite'] = (int)$this->_getParam('limite', 1000);
-			$enreg['type_tags'] = $enreg['type_tags_codes'];
-			$this->_updateEtRetour($enreg, 'TAGS');
-		} else {
-			$this->view->catalogues = Class_Catalogue::getCataloguesForCombo();
-		}
-	}
-
-
-	public function critiquesAction() {
-		if ($this->_request->isPost()) 	{
-			$enreg = $this->_request->getPost();
-			if ($enreg["id_panier"]) {
-				$user = ZendAfi_Auth::getInstance()->getIdentity();
-				$enreg["id_catalogue"] = 0;
-				$enreg["id_user"] = $user->ID_USER;
-
-			} else {
-				$enreg["id_user"] = 0;
-			}
-
-			$this->_updateEtRetour($enreg, 'CRITIQUES');
-		}
-
-		$this->view->catalogues = Class_Catalogue::getCataloguesForCombo();
-		$this->view->paniers = Class_PanierNotice::getPaniersForCombo();
-	}
-
-
-	public function catalogueAction() {
-		if ($this->_request->isPost()) {
-			extract($_POST);
-			$nb_requete = intval($nb_requete);
-			if (!$nb_requete)
-				$nb_requete = 200;
-
-			$nb_aff = intval($nb_aff);
-			if (!$nb_aff)
-				$nb_aff = 10;
-
-			if ($ordre == "1")
-				$nb_requete = $nb_aff; // si ordre strict on ne lit pas plus de notices qu'on en affiche
-
-			$enreg["message"] = $message;
-			$enreg["notices"] = $notices;
-			$enreg["format"] = $format;
-			$enreg["ordre"] = $ordre;
-			$enreg["type_doc"] = $type_doc;
-			$enreg["section"] = $section;
-			$enreg["genre"] = $genre;
-			$enreg["dewey"] = $dewey;
-			$enreg["pcdm4"] = $pcdm4;
-			$enreg["matiere"] = $matiere;
-			$enreg["nb_requete"] = $nb_requete;
-			$enreg["nb_aff"] = $nb_aff;
-
-			$this->_updateEtRetour($enreg, 'CATALOGUE');
-		}
-	}
-
-
-	public function kiosqueAction() {
-		if ($this->_request->isPost()) {
-			if (1 == $this->_getParam('styles_reload')) {
-				$this->view->preferences = $this->_request->getPost();
-			} else {
+      ->getModuleAccueilConfig($this->id_module, 'LIBRARY')['preferences'];
+    $this->_simpleAction('LIBRARY');
+  }
+
+
+  public function compteursAction() {
+    $this->_simpleAction('COMPTEURS');
+  }
+
+  public function pretsAction() {
+    $this->_simpleAction('PRETS');
+  }
+
+  public function historiqueRecherchesAction() {
+    $this->_simpleAction('HISTORIQUE_RECHERCHES');
+  }
+
+  public function reservationsAction() {
+    $this->_simpleAction('RESERVATIONS');
+  }
+
+  public function multimediaAction() {
+    $this->_simpleAction('MULTIMEDIA');
+  }
+
+  public function newslettersAction() {
+    $this->_simpleAction('NEWSLETTERS');
+  }
+
+  public function panierAction() {
+    $this->_simpleAction('PANIER');
+  }
+
+
+  public function bibliothequeNumeriqueAction() {
+    if (1 == $this->_getParam('styles_reload')) {
+      $this->view->preferences = $this->_request->getPost();
+    } else {
+      $this->_simpleAction('BIB_NUMERIQUE');
+    }
+
+    $this->view->categories = Class_AlbumCategorie::getLoader()->getCollections();
+    $moduleBibNumerique = $this->_systemeModulesAccueil->getModuleByCode('BIB_NUMERIQUE');
+    $this->view->displayModes = $moduleBibNumerique->getDisplayModes();
+    $this->view->orderModes = $moduleBibNumerique->getOrderModes();
+
+    $this->view->albums = Class_AlbumCategorie::getLoader()->findAlbumsRecursively();
+  }
+
+
+  public function tagsAction() {
+    // Retour du formulaire
+    if ($this->_request->isPost()) {
+      $enreg = $this->_request->getPost();
+      $enreg['nombre'] = (int)$this->_getParam('nombre', 10);
+      $enreg['limite'] = (int)$this->_getParam('limite', 1000);
+      $enreg['type_tags'] = $enreg['type_tags_codes'];
+      $this->_updateEtRetour($enreg, 'TAGS');
+    } else {
+      $this->view->catalogues = Class_Catalogue::getCataloguesForCombo();
+    }
+  }
+
+
+  public function critiquesAction() {
+    if ($this->_request->isPost())  {
+      $enreg = $this->_request->getPost();
+      if ($enreg["id_panier"]) {
+        $user = ZendAfi_Auth::getInstance()->getIdentity();
+        $enreg["id_catalogue"] = 0;
+        $enreg["id_user"] = $user->ID_USER;
+
+      } else {
+        $enreg["id_user"] = 0;
+      }
+
+      $this->_updateEtRetour($enreg, 'CRITIQUES');
+    }
+
+    $this->view->catalogues = Class_Catalogue::getCataloguesForCombo();
+    $this->view->paniers = Class_PanierNotice::getPaniersForCombo();
+  }
+
+
+  public function catalogueAction() {
+    if ($this->_request->isPost()) {
+      extract($_POST);
+      $nb_requete = intval($nb_requete);
+      if (!$nb_requete)
+        $nb_requete = 200;
+
+      $nb_aff = intval($nb_aff);
+      if (!$nb_aff)
+        $nb_aff = 10;
+
+      if ($ordre == "1")
+        $nb_requete = $nb_aff; // si ordre strict on ne lit pas plus de notices qu'on en affiche
+
+      $enreg["message"] = $message;
+      $enreg["notices"] = $notices;
+      $enreg["format"] = $format;
+      $enreg["ordre"] = $ordre;
+      $enreg["type_doc"] = $type_doc;
+      $enreg["section"] = $section;
+      $enreg["genre"] = $genre;
+      $enreg["dewey"] = $dewey;
+      $enreg["pcdm4"] = $pcdm4;
+      $enreg["matiere"] = $matiere;
+      $enreg["nb_requete"] = $nb_requete;
+      $enreg["nb_aff"] = $nb_aff;
+
+      $this->_updateEtRetour($enreg, 'CATALOGUE');
+    }
+  }
+
+
+  public function kiosqueAction() {
+    if ($this->_request->isPost()) {
+      if (1 == $this->_getParam('styles_reload')) {
+        $this->view->preferences = $this->_request->getPost();
+      } else {
         if ($this->isAFlashStyleSelected())
           $_POST['profil_redirect'] = '';
-				$this->_updateConfig('KIOSQUE');
-			}
-		}
+        $this->_updateConfig('KIOSQUE');
+      }
+    }
 
-		$this->view->styles_liste = $this->_getStylesListes();
-		$this->view->flash_selected = $this->isAFlashStyleSelected();
-		$this->view->catalogues = Class_Catalogue::getCataloguesForCombo();
-		$this->view->paniers = Class_PanierNotice::getPaniersForCombo();
-	}
+    $this->view->styles_liste = $this->_getStylesListes();
+    $this->view->flash_selected = $this->isAFlashStyleSelected();
+    $this->view->catalogues = Class_Catalogue::getCataloguesForCombo();
+    $this->view->paniers = Class_PanierNotice::getPaniersForCombo();
+  }
 
-	public function premierChapitreAction() {
-		$this->view->paniers = Class_PanierNotice::getPaniersForCombo();
-		$this->_simpleAction('PREMIER-CHAPITRE');
-	}
+  public function premierChapitreAction() {
+    $this->view->paniers = Class_PanierNotice::getPaniersForCombo();
+    $this->_simpleAction('PREMIER-CHAPITRE');
+  }
 
 
-	protected function isAFlashStyleSelected() {
+  protected function isAFlashStyleSelected() {
     return Class_Systeme_ModulesAccueil::moduleByCode('KIOSQUE')
       ->isAFlashStyle($this->_getParam('style_liste',
                                        $this->view->preferences['style_liste']));
-	}
+  }
 
 
-	protected function _unsetStyleReload(&$enreg) {
-		if (array_key_exists('styles_reload', $enreg)) {
-			unset($enreg["styles_reload"]);
-		}
-	}
+  protected function _unsetStyleReload(&$enreg) {
+    if (array_key_exists('styles_reload', $enreg)) {
+      unset($enreg["styles_reload"]);
+    }
+  }
 
 
-	protected function _setTypeDAnalyse(&$enreg) {
-		$enreg = isset($enreg['nb_notices']) ? $enreg : array_merge($enreg,['nb_notices' => 1]) ;
+  protected function _setTypeDAnalyse(&$enreg) {
+    $enreg = isset($enreg['nb_notices']) ? $enreg : array_merge($enreg,['nb_notices' => 1]) ;
 
-		$enreg['nb_notices'] = (1 < (int)$enreg['nb_notices']) ?
-			(int)$enreg["nb_notices"]
-			: 1;
+    $enreg['nb_notices'] = (1 < (int)$enreg['nb_notices']) ?
+      (int)$enreg["nb_notices"]
+      : 1;
 
-		$enreg = isset($enreg['nb_analyse']) ? $enreg : array_merge($enreg,['nb_analyse' => 10]) ;
+    $enreg = isset($enreg['nb_analyse']) ? $enreg : array_merge($enreg,['nb_analyse' => 10]) ;
 
-		$enreg['nb_analyse'] = (int)$enreg['nb_analyse'];
-		if ($enreg['nb_analyse'] < $enreg['nb_notices'])
-			$enreg['nb_analyse'] = $enreg['nb_notices'] + 10;
-	}
+    $enreg['nb_analyse'] = (int)$enreg['nb_analyse'];
+    if ($enreg['nb_analyse'] < $enreg['nb_notices'])
+      $enreg['nb_analyse'] = $enreg['nb_notices'] + 10;
+  }
 
 
-	protected function _setPanierOrDomaine(&$enreg) {
-		if ($enreg['id_panier'] > 0)
-			$enreg['id_catalogue'] = 0;
-		if ($enreg['id_catalogue'] > 0)
-			$enreg['id_panier'] = 0;
-	}
+  protected function _setPanierOrDomaine(&$enreg) {
+    if ($enreg['id_panier'] > 0)
+      $enreg['id_catalogue'] = 0;
+    if ($enreg['id_catalogue'] > 0)
+      $enreg['id_panier'] = 0;
+  }
 
 
-	protected function _updateConfig($type) {
-			$enreg = $this->_request->getPost();
-			$this->_unsetStyleReload($enreg);
-			$this->_setTypeDAnalyse($enreg);
-			$this->_setPanierOrDomaine($enreg);
-			$this->_updateEtRetour($enreg, $type);
-	}
+  protected function _updateConfig($type) {
+    $enreg = $this->_request->getPost();
+    $this->_unsetStyleReload($enreg);
+    $this->_setTypeDAnalyse($enreg);
+    $this->_setPanierOrDomaine($enreg);
+    $this->_updateEtRetour($enreg, $type);
+  }
 
 
-	public function kiosqueChangeSelectionAction() {
-		$this->getHelper('ViewRenderer')->setNoRender();
+  public function kiosqueChangeSelectionAction() {
+    $this->getHelper('ViewRenderer')->setNoRender();
 
-		$module_config = $this->profil
-			->getModuleAccueilConfig($this->id_module, 'KIOSQUE');
-		$selected_elementId = explode('-', $this->_request->getPost('domaine_panier'));
+    $module_config = $this->profil
+      ->getModuleAccueilConfig($this->id_module, 'KIOSQUE');
+    $selected_elementId = explode('-', $this->_request->getPost('domaine_panier'));
 
-		if($selected_elementId[0] == 'p') {
-			$module_config['preferences']['id_catalogue'] = 0;
-			$module_config['preferences']['id_panier'] = $selected_elementId[1];
-		} else if ($selected_elementId[0] == 'c') {
-			$module_config['preferences']['id_panier'] = 0;
-			$module_config['preferences']['id_catalogue'] = $selected_elementId[1];
-		} else {
-			$module_config['preferences']['id_catalogue'] = 0;
-			$module_config['preferences']['id_panier'] = 0;
-		}
+    if($selected_elementId[0] == 'p') {
+      $module_config['preferences']['id_catalogue'] = 0;
+      $module_config['preferences']['id_panier'] = $selected_elementId[1];
+    } else if ($selected_elementId[0] == 'c') {
+      $module_config['preferences']['id_panier'] = 0;
+      $module_config['preferences']['id_catalogue'] = $selected_elementId[1];
+    } else {
+      $module_config['preferences']['id_catalogue'] = 0;
+      $module_config['preferences']['id_panier'] = 0;
+    }
 
-		$this->profil
-			->updateModuleConfigAccueil($this->id_module, $module_config)
-			->save();
+    $this->profil
+      ->updateModuleConfigAccueil($this->id_module, $module_config)
+      ->save();
 
-		$this->_redirect($this->_request->getServer('HTTP_REFERER'));
-	}
+    $this->_redirect($this->_request->getServer('HTTP_REFERER'));
+  }
 
 
-	public function conteneur2colonnesAction()	{
-		if ($this->_request->isPost()) {
-			$enreg = $this->_request->getPost();
+  public function conteneur2colonnesAction()  {
+    if ($this->_request->isPost()) {
+      $enreg = $this->_request->getPost();
 
-			$this->preferences = array_merge($this->preferences, $enreg);
-			foreach(['gauche', 'droite'] as $colonne)
-				$enreg['col_' . $colonne .'_module_id'] =	$this->createModuleFor($colonne);
+      $this->preferences = array_merge($this->preferences, $enreg);
+      foreach(['gauche', 'droite'] as $colonne)
+        $enreg['col_' . $colonne .'_module_id'] = $this->createModuleFor($colonne);
 
-			return $this->_updateEtRetour($enreg, 'CONTENEUR_DEUX_COLONNES');
-		}
+      return $this->_updateEtRetour($enreg, 'CONTENEUR_DEUX_COLONNES');
+    }
 
-		$modules_accueil = Class_Systeme_ModulesAccueil::getModules();
-		$modules = [];
-		foreach ($modules_accueil as $key => $module)
-			$modules[$key] = $module->getLibelle();
+    $modules_accueil = Class_Systeme_ModulesAccueil::getModules();
+    $modules = [];
+    foreach ($modules_accueil as $key => $module)
+      $modules[$key] = $module->getLibelle();
 
-		$this->view->modules = $modules;
-	}
+    $this->view->modules = $modules;
+  }
 
 
-	protected function createModuleFor($colonne) {
-		return Class_Systeme_ModulesAccueil_ConteneurDeuxColonnes::createModuleForCol($colonne,
-																																									$this->preferences,
-																																									$this->id_module);
+  protected function createModuleFor($colonne) {
+    return Class_Systeme_ModulesAccueil_ConteneurDeuxColonnes::createModuleForCol($colonne,
+                                                                                  $this->preferences,
+                                                                                  $this->id_module);
 
-	}
+  }
 
 
-	private function _simpleAction($type) {
-		// pour combo des annexes
-		$this->view->ya_annexes = fetchAll("select count(*) from codif_annexe where invisible=0 order by libelle");
-		if ($this->_request->isPost())
-			$this->_updateEtRetour($this->_request->getPost(), $type);
-	}
+  private function _simpleAction($type) {
+    // pour combo des annexes
+    $this->view->ya_annexes = fetchAll("select count(*) from codif_annexe where invisible=0 order by libelle");
+    if ($this->_request->isPost())
+      $this->_updateEtRetour($this->_request->getPost(), $type);
+  }
 
 
-	/**
-	 * @param array $datas
-	 * @return string
-	 */
-	private function _compactProperties($datas) {
-		$properties = array();
-		foreach ($datas as $k => $v) {
-			$properties[] = $k . '=' . $v;
-		}
-
-		return implode('/', $properties);
-	}
+  /**
+   * @param array $datas
+   * @return string
+   */
+  private function _compactProperties($datas) {
+    $properties = array();
+    foreach ($datas as $k => $v) {
+      $properties[] = $k . '=' . $v;
+    }
+
+    return implode('/', $properties);
+  }
 
 
-	/** @return array */
-	private function _extractProperties() {
-		if (null != ($props = $this->_getParam("proprietes"))) {
-			$props = explode('/', $props);
-			foreach ($props as $prop) {
-				$pos = strpos($prop, '=');
-				$clef = substr($prop, 0, $pos);
-				$valeur = substr($prop, ($pos + 1));
-				$properties[$clef] = $valeur;
-			}
-		}	else {
-			$cls = new Class_Systeme_ModulesAccueil();
-			$properties = $cls->getValeursParDefaut($this->type_module);
-		}
-
-		return $properties;
-	}
-
-
-	/**
-	 * @param array $data
-	 */
-	protected function _updateEtRetour($data, $type) {
-		$enreg = [];
-		foreach ($data as $clef => $valeur)
-			$enreg[$clef] = addslashes($valeur);
-
-		if ($this->config == "admin") {
-			$this->view->id_module = $this->id_module;
-			$this->view->properties = $this->_compactProperties($enreg);
-		} else {
-
-			$module_config = $this->profil->getModuleAccueilConfig($this->id_module, $type);
-			$module_config['preferences'] = array_merge($module_config['preferences'], $enreg);
-
-			$this->profil
-				->updateModuleConfigAccueil($this->id_module, $module_config)
-				->save();
-			$this->view->reload = 'SITE';
-		}
-
-		$viewRenderer = $this->getHelper('ViewRenderer');
-		$viewRenderer->renderScript('accueil/_retour.phtml');
-	}
+  /** @return array */
+  private function _extractProperties() {
+    if (null != ($props = $this->_getParam("proprietes"))) {
+      $props = explode('/', $props);
+      foreach ($props as $prop) {
+        $pos = strpos($prop, '=');
+        $clef = substr($prop, 0, $pos);
+        $valeur = substr($prop, ($pos + 1));
+        $properties[$clef] = $valeur;
+      }
+    } else {
+      $cls = new Class_Systeme_ModulesAccueil();
+      $properties = $cls->getValeursParDefaut($this->type_module);
+    }
+
+    return $properties;
+  }
+
+
+  /**
+   * @param array $data
+   */
+  protected function _updateEtRetour($data, $type) {
+    $enreg = [];
+    foreach ($data as $clef => $valeur)
+      $enreg[$clef] = addslashes($valeur);
+
+    if ($this->config == "admin") {
+      $this->view->id_module = $this->id_module;
+      $this->view->properties = $this->_compactProperties($enreg);
+    } else {
+
+      $module_config = $this->profil->getModuleAccueilConfig($this->id_module, $type);
+      $module_config['preferences'] = array_merge($module_config['preferences'], $enreg);
+
+      $this->profil
+        ->updateModuleConfigAccueil($this->id_module, $module_config)
+        ->save();
+      $this->view->reload = 'SITE';
+    }
+
+    $viewRenderer = $this->getHelper('ViewRenderer');
+    $viewRenderer->renderScript('accueil/_retour.phtml');
+  }
 
 
-	protected function _getStylesListes() {
+  protected function _getStylesListes() {
     return Class_Systeme_ModulesAccueil::moduleByCode('KIOSQUE')
       ->getStylesListes();
-	}
+  }
 }
diff --git a/application/modules/admin/views/scripts/batch/index.phtml b/application/modules/admin/views/scripts/batch/index.phtml
index f3785319ebe0aec694b01a7ef53cebc8f4c1048a..3073302f02165f8ff63ee81112d44f91d860ce86 100644
--- a/application/modules/admin/views/scripts/batch/index.phtml
+++ b/application/modules/admin/views/scripts/batch/index.phtml
@@ -7,7 +7,7 @@ echo $this->bouton('id=add',
                    );
 
 echo $this->tagModelTable(
-  $this->batchs, 
+  $this->batchs,
   [$this->_('Libelle'), $this->_('Dernière exécution')],
   ['Libelle', 'last_run'],
   [
@@ -16,12 +16,13 @@ echo $this->tagModelTable(
       if ('MOISSONNAGE_CYBERLIBRIS' == $batch->getType())
         return '';
 
-      $action = (in_array($batch->getType(), 
-                   ['AUTOCOMPLETE_RECORD_TITLE', 'AUTOCOMPLETE_RECORD_AUTHOR'])) ?
-        'run-ajax' : 'run';
-      return $this->tagAnchor(['action' => $action, 'id' => $batch->getId()], 
+      $action = (in_array($batch->getType(),
+                          ['AUTOCOMPLETE_RECORD_TITLE',
+                           'AUTOCOMPLETE_RECORD_AUTHOR',
+                           'INDEX_RESSOURCES_NUMERIQUES'])) ?
+                'run-ajax' : 'run';
+      return $this->tagAnchor(['action' => $action, 'id' => $batch->getId()],
                               $this->boutonIco('type=test', 'bulle=Lancer'));
     }],
   'batchs');
-                          
 ?>
diff --git a/ckeditor/core_five_filemanager/connectors/php/filemanager.config.php b/ckeditor/core_five_filemanager/connectors/php/filemanager.config.php
index 2bc7a5bdffa9ae68819afacf4b8f02d583f75936..3f6b28cd96927a1dca7b32b196c178463f96ff30 100644
--- a/ckeditor/core_five_filemanager/connectors/php/filemanager.config.php
+++ b/ckeditor/core_five_filemanager/connectors/php/filemanager.config.php
@@ -19,9 +19,18 @@
  *	@return boolean true is access granted, false if no access
  */
 function auth() {
-  // You can insert your own code over here to check if the user is authorized.
-  // If you use a session variable, you've got to start the session first (session_start())
-  return true;
+  $base_path = __DIR__ . '/../../../../'; // :)
+  require_once($base_path . 'cosmogramme/php/classes/classe_cosmopaths.php');
+
+  CosmoPaths::setDirName('ckeditor');
+  $cosmo_path = new CosmoPaths();
+
+  define('BASE_URL', $cosmo_path->getBaseUrl());
+  define('USERFILESPATH', $cosmo_path->getUserfilesPath());
+
+  require_once($base_path . 'cosmogramme/storm_init.php');
+  setupSession();
+  return (new Class_FileManager())->isAuthorized($_GET['path']);
 }
 
 
diff --git a/ckeditor/core_five_filemanager/connectors/php/filemanager.php b/ckeditor/core_five_filemanager/connectors/php/filemanager.php
index efe4f4b5ca4c816e7876cfa9607d2e5851f7436e..66712a927c9dccc5cf2929e6f45ac24f55726e33 100644
--- a/ckeditor/core_five_filemanager/connectors/php/filemanager.php
+++ b/ckeditor/core_five_filemanager/connectors/php/filemanager.php
@@ -18,23 +18,6 @@ header('Content-type: application/json');
  */
 
 
-/**
- * Fast fix for afi-opac context
- * @author Patrick Barroca
- * @param string $path
- */
-function opacTraversalProtect ($path) {
-  $path = (string)$path;
-  $parts = explode('/', $path);
-  array_shift($parts);
-
-  if (in_array('..', $parts)
-      || 2 > count($parts)
-      || !in_array('userfiles', $parts))
-    exit();
-}
-
-
 require_once('./inc/filemanager.inc.php');
 require_once('filemanager.config.php');
 require_once('filemanager.class.php');
@@ -62,19 +45,16 @@ if(!isset($_GET)) {
     switch($_GET['mode']) {
 
       default:
-				opacTraversalProtect($_GET['path']);
         $fm->error($fm->lang('MODE_ERROR'));
         break;
 
       case 'getinfo':
-				opacTraversalProtect($_GET['path']);
         if($fm->getvar('path')) {
           $response = $fm->getinfo();
         }
         break;
 
       case 'getfolder':
-				opacTraversalProtect($_GET['path']);
         if($fm->getvar('path')) {
           $response = $fm->getfolder();
         }
@@ -88,21 +68,18 @@ if(!isset($_GET)) {
         break;
 
       case 'delete':
-				opacTraversalProtect($_GET['path']);
         if($fm->getvar('path')) {
           $response = $fm->delete();
         }
         break;
 
       case 'addfolder':
-				opacTraversalProtect($_GET['path']);
         if($fm->getvar('path') && $fm->getvar('name')) {
           $response = $fm->addfolder();
         }
         break;
 
       case 'download':
-				opacTraversalProtect($_GET['path']);
         if($fm->getvar('path')) {
           $fm->download();
         }
@@ -125,7 +102,6 @@ if(!isset($_GET)) {
 
       case 'add':
         if($fm->postvar('currentpath')) {
-					opacTraversalProtect($_POST['currentpath']);
           $response = $fm->add();
         }
         break;
diff --git a/cosmogramme/php/_init.php b/cosmogramme/php/_init.php
index 6bf6f9b5653243208920ab0509930fc31376d559..7c36ad9fabd761ccdfaec66108ced749a8a9f80d 100644
--- a/cosmogramme/php/_init.php
+++ b/cosmogramme/php/_init.php
@@ -1,8 +1,7 @@
 <?php
 error_reporting(E_ERROR | E_PARSE);
 
-
-define("PATCH_LEVEL","276");
+define("PATCH_LEVEL","277");
 
 define("APPLI","cosmogramme");
 define("COSMOPATH", "/var/www/html/vhosts/opac2/www/htdocs");
diff --git a/cosmogramme/php/classes/classe_cosmopaths.php b/cosmogramme/php/classes/classe_cosmopaths.php
index 7c39f13342e47a38641a545914394fd3c5ea4cc8..a8f5fd18580f06e4a4698afdc101b2902db58882 100644
--- a/cosmogramme/php/classes/classe_cosmopaths.php
+++ b/cosmogramme/php/classes/classe_cosmopaths.php
@@ -20,88 +20,93 @@
  */
 
 class CosmoPaths {
-	const COSMO_DIR_NAME = 'cosmogramme';
+  protected static $_dir_name = 'cosmogramme';
+  protected $_filesystem;
 
-	protected $_filesystem;
 
-	public function getBasePath() {
-		$parts = array_filter(explode('/', $this->getFilePath()));
-		while ((count($parts)>0) && (end($parts) !== self::COSMO_DIR_NAME))
-			array_pop($parts);
-		array_pop($parts);
-		return ($this->isWindowsPath() ? '' : '/')  . implode('/', $parts) . '/';
-	}
+  public static function setDirName($name) {
+    static::$_dir_name = $name;
+  }
 
 
-	public function isWindowsPath() {
-		return strtoupper(substr(PHP_OS, 0, 3)) === 'WIN';
-	}
+  public function getBasePath() {
+    $parts = array_filter(explode('/', $this->getFilePath()));
+    while ((count($parts)>0) && (end($parts) !== static::$_dir_name))
+      array_pop($parts);
+    array_pop($parts);
+    return ($this->isWindowsPath() ? '' : '/')  . implode('/', $parts) . '/';
+  }
 
 
-	public function setFileSystem($filesystem) {
-		$this->_filesystem = $filesystem;
-	}
+  public function isWindowsPath() {
+    return strtoupper(substr(PHP_OS, 0, 3)) === 'WIN';
+  }
 
 
-	public function getFilesystem() {
-		require_once(realpath(dirname(__FILE__)).'/../../../library/Class/Testing/FileSystem.php');
-		return null == $this->_filesystem
-			? new Class_Testing_FileSystem()
-			: $this->_filesystem;
-	}
+  public function setFileSystem($filesystem) {
+    $this->_filesystem = $filesystem;
+  }
 
 
-	public function getConfigPath() {
-		return $this->getBasePath() . self::COSMO_DIR_NAME . '/config.php';
-	}
+  public function getFilesystem() {
+    require_once(realpath(dirname(__FILE__)).'/../../../library/Class/Testing/FileSystem.php');
+    return null == $this->_filesystem
+      ? new Class_Testing_FileSystem()
+      : $this->_filesystem;
+  }
 
 
-	public function getBokehConfigPath() {
-		return $this->getBasePath() . 'config.ini';
-	}
+  public function getConfigPath() {
+    return $this->getBasePath() . static::$_dir_name . '/config.php';
+  }
 
 
-	public function getBaseUrl() {
-		if (!isset($_SERVER['SCRIPT_NAME']))
-			return '/' . $this->getSite() . '/';
+  public function getBokehConfigPath() {
+    return $this->getBasePath() . 'config.ini';
+  }
 
-		$parts = array_filter(explode('/', $_SERVER['SCRIPT_NAME']));
-		while ((count($parts)>0) && (end($parts) !== self::COSMO_DIR_NAME))
-			array_pop($parts);
-		array_pop($parts);
-		return $parts
-			? '/' . implode('/', $parts) . '/'
-			: '/';
-	}
 
+  public function getBaseUrl() {
+    if (!isset($_SERVER['SCRIPT_NAME']))
+      return '/' . $this->getSite();
 
-	public function getCosmoBaseUrl() {
-		return $this->getBaseUrl() . self::COSMO_DIR_NAME . '/';
-	}
+    $parts = array_filter(explode('/', $_SERVER['SCRIPT_NAME']));
+    while ((count($parts)>0) && (end($parts) !== static::$_dir_name))
+      array_pop($parts);
+    array_pop($parts);
+    return $parts
+      ? '/' . implode('/', $parts)
+      : '';
+  }
 
 
-	public function getUserfilesPath() {
-		return $this->getBasePath() . 'userfiles';
-	}
+  public function getCosmoBaseUrl() {
+    return $this->getBaseUrl() . '/' . static::$_dir_name . '/';
+  }
 
 
-	public function getSite() {
-		$parts = array_filter(explode('/', $this->getBasePath()));
-		return array_pop($parts);
-	}
+  public function getUserfilesPath() {
+    return $this->getBasePath() . 'userfiles';
+  }
 
 
-	protected function getFilePath() {
-		if (isset($_SERVER['SCRIPT_FILENAME'])
-				&& false !== strpos($_SERVER['SCRIPT_FILENAME'], self::COSMO_DIR_NAME))
-			return $_SERVER['SCRIPT_FILENAME'];
+  public function getSite() {
+    $parts = array_filter(explode('/', $this->getBasePath()));
+    return array_pop($parts);
+  }
 
-		$current_path = $this->getFileSystem()->getcwd();
-		if (false !== strpos($current_path, self::COSMO_DIR_NAME))
-			return $current_path;
 
-		return realpath(dirname(__FILE__));
-	}
+  protected function getFilePath() {
+    if (isset($_SERVER['SCRIPT_FILENAME'])
+        && false !== strpos($_SERVER['SCRIPT_FILENAME'], static::$_dir_name))
+      return $_SERVER['SCRIPT_FILENAME'];
+
+    $current_path = $this->getFileSystem()->getcwd();
+    if (false !== strpos($current_path, static::$_dir_name))
+      return $current_path;
+
+    return realpath(dirname(__FILE__));
+  }
 }
 
 ?>
\ No newline at end of file
diff --git a/cosmogramme/sql/patch/patch_277.php b/cosmogramme/sql/patch/patch_277.php
new file mode 100644
index 0000000000000000000000000000000000000000..419c9b69f50dd8d52b3d0cec3e3dd01652cf46a1
--- /dev/null
+++ b/cosmogramme/sql/patch/patch_277.php
@@ -0,0 +1,31 @@
+<?php
+
+$adapter = Zend_Db_Table_Abstract::getDefaultAdapter();
+$types = [Class_TypeDoc::SITE => 'getSite',
+          Class_TypeDoc::ARTICLE => 'getArticle'];
+
+foreach($types as $type => $parent_getter) {
+  $ids = $adapter->query('select id_notice from notices where type_doc=' . $type)
+                 ->fetchAll();
+
+  if (!$ids)
+    return;
+
+  $ids = array_chunk($ids, 500, true);
+
+  foreach($ids as $page) {
+    foreach($page as $data) {
+      if (!$record = Class_Notice::find((int)$data['id_notice']))
+        continue; // Record does not exists
+
+      if (call_user_func([$record, $parent_getter]))
+        continue; // Record is not an orphan
+
+      $record->delete();
+    }
+
+    Storm_Model_Abstract::unsetLoaders();
+    Storm_Model_Loader::resetCache();
+    gc_collect_cycles();
+  }
+}
\ No newline at end of file
diff --git a/cosmogramme/tests/php/classes/CosmoPathsTest.php b/cosmogramme/tests/php/classes/CosmoPathsTest.php
index 9fb8b34b9b0a573a1268d1e3637863775703f51a..23a6549103de12ce577f3a93e09322fb931e0b5c 100644
--- a/cosmogramme/tests/php/classes/CosmoPathsTest.php
+++ b/cosmogramme/tests/php/classes/CosmoPathsTest.php
@@ -42,7 +42,7 @@ abstract class CosmoPathsTestCase extends PHPUnit_Framework_TestCase {
 
 	/** @test */
 	public function baseUrlShouldBeBokehDotFr() {
-		$this->assertEquals('/bokeh.fr/', $this->_cosmo_paths->getBaseUrl());
+		$this->assertEquals('/bokeh.fr', $this->_cosmo_paths->getBaseUrl());
 	}
 
 
@@ -113,7 +113,13 @@ class CosmoPathsFromHttpRequestInASubdirTest extends PHPUnit_Framework_TestCase
 
 	/** @test */
 	public function baseUrlShouldBeProjectsBokeh() {
-		$this->assertEquals('/projects/bokeh/', $this->_cosmo_paths->getBaseUrl());
+		$this->assertEquals('/projects/bokeh', $this->_cosmo_paths->getBaseUrl());
+	}
+
+
+	/** @test */
+	public function cosmogrammeBaseUrlShouldBeProjectsBokehCosmogramme() {
+		$this->assertEquals('/projects/bokeh/cosmogramme/', $this->_cosmo_paths->getCosmoBaseUrl());
 	}
 
 
@@ -171,7 +177,7 @@ class CosmoPathsFromHttpRequestAtRootTest extends PHPUnit_Framework_TestCase {
 
 	/** @test */
 	public function baseUrlShouldBeEmpty() {
-		$this->assertEquals('/', $this->_cosmo_paths->getBaseUrl());
+		$this->assertEquals('', $this->_cosmo_paths->getBaseUrl());
 	}
 
 
diff --git a/includes.php b/includes.php
index 6f619f1a16252dd94e068f9a6f61ee4079322f0c..700f31add111ce256d5ca9deb18c3985fbeec4ea 100644
--- a/includes.php
+++ b/includes.php
@@ -19,7 +19,8 @@
  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301  USA
  */
 $base_path = realpath(dirname(__FILE__));
-set_include_path($base_path . '/library' . PATH_SEPARATOR .
+set_include_path($base_path . PATH_SEPARATOR .
+                 $base_path . '/library' . PATH_SEPARATOR .
 								 $base_path . '/library/storm/src' . PATH_SEPARATOR .
 								 $base_path . '/library/storm/zf/library' . PATH_SEPARATOR .
 								 get_include_path());
diff --git a/library/Class/AdminVar.php b/library/Class/AdminVar.php
index c406e8229fede6c5e631e80083692e3193d4b6de..0899a65c3e3b13cad42f24c558271700be64f2ca 100644
--- a/library/Class/AdminVar.php
+++ b/library/Class/AdminVar.php
@@ -717,7 +717,7 @@ class Class_AdminVar extends Storm_Model_Abstract {
 
 
   public function getValeur() {
-    return stripslashes($this->_get('valeur'));
+    return $this->_get('valeur');
   }
 
 
diff --git a/library/Class/Batch/IndexRessourcesNumeriques.php b/library/Class/Batch/IndexRessourcesNumeriques.php
index 77a0b1aa4647afa32cf36ab04f2d0aedaf6acc9b..dd30d9e7448d8a2b4c9f1b9f94eb88367e3a2bb8 100644
--- a/library/Class/Batch/IndexRessourcesNumeriques.php
+++ b/library/Class/Batch/IndexRessourcesNumeriques.php
@@ -7,9 +7,10 @@ class Class_Batch_IndexRessourcesNumeriques extends Class_Batch_Abstract {
     return $this->_("Indexer les ressources numériques");
   }
 
+
   public function run() {
     $current_page = -1;
-    do  {
+    do {
       $albums = Class_Album::findAllBy(['limitPage' => [$current_page += 1,
                                                         100]]);
       foreach ($albums as $album)
@@ -24,6 +25,32 @@ class Class_Batch_IndexRessourcesNumeriques extends Class_Batch_Abstract {
     (new Storm_Cache())->clean();
   }
 
+
+  public function runStep($params) {
+    $response = new stdClass;
+    if (empty($params) || !isset($params['done'])) {
+      $response->done = 0;
+      $response->total= 0;
+      return $response;
+    }
+
+    $done = $params['done'];
+    $page_size = 100;
+    $page = ($done / $page_size) + 1;
+    $response->total = Class_Album::count();
+
+    $models = Class_Album::findAllBy(['limitPage' => [$page, $page_size]]);
+    foreach($models as $models)
+      $models->index();
+
+    $response->done = ($response->total > $done + $page_size) ?
+      $done + $page_size :
+      $done + count($models);
+
+    return $response;
+  }
+
+
   public function isEnabled() {
     $types = Class_Batch::getRessourcesNumeriqueTypes();
     foreach ($types as $instance) {
diff --git a/library/Class/Cosmogramme/Integration/PhaseBatchs.php b/library/Class/Cosmogramme/Integration/PhaseBatchs.php
index 887bd37f63b384eac29d3d8c4b7d6c5652c77372..8bb8714e42e16a16365b50f96011055f5cc2e77e 100644
--- a/library/Class/Cosmogramme/Integration/PhaseBatchs.php
+++ b/library/Class/Cosmogramme/Integration/PhaseBatchs.php
@@ -38,15 +38,25 @@ class Class_Cosmogramme_Integration_PhaseBatchs
       return;
     }
 
-    $batchs = Class_Batch::findAllBy(['order' => 'id']);
-    foreach($batchs as $batch) {
+    foreach(Class_Batch::findAllBy(['order' => 'id']) as $batch) {
       if ($this->_getData('pointeur_reprise') > $batch->getId())
         continue;
-      $this->_runOne($batch);
+
+      $this->_resetHttpClient()
+           ->_runOne($batch);
     }
   }
 
 
+  protected function _resetHttpClient() {
+    if (!$client = Zend_Registry::get('httpClient'))
+      return $this;
+
+    $client->setAuth(null);
+    return $this;
+  }
+
+
   protected function _runOne($batch) {
     $this->_log->ecrire('<span class="vert">' . $batch->getLibelle().':');
     $this->_setData('pointeur_reprise', $batch->getId());
diff --git a/library/Class/FileManager.php b/library/Class/FileManager.php
new file mode 100644
index 0000000000000000000000000000000000000000..bdc26e83d14201a09fee035ebdb7ee030718402a
--- /dev/null
+++ b/library/Class/FileManager.php
@@ -0,0 +1,31 @@
+<?php
+/**
+ * Copyright (c) 2012, Agence Française Informatique (AFI). All rights reserved.
+ *
+ * BOKEH is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE as published by
+ * the Free Software Foundation.
+ *
+ * There are special exceptions to the terms and conditions of the AGPL as it
+ * is applied to this software (see README file).
+ *
+ * BOKEH is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU AFFERO GENERAL PUBLIC LICENSE for more details.
+ *
+ * You should have received a copy of the GNU AFFERO GENERAL PUBLIC LICENSE
+ * along with BOKEH; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301  USA
+ */
+
+class Class_FileManager {
+  public function isAuthorized($path) {
+    return Class_Users::isCurrentUserCanAccesBackend()
+      && false !== strpos($path, USERFILESURL)
+      && false === strpos($path, '..');
+  }
+}
+
+
+?>
\ No newline at end of file
diff --git a/library/Class/Notice.php b/library/Class/Notice.php
index bd76d4bc4351c23e774891f0b44ea747eaf2ecee..6b2449a6635e1fb3de52ca61bb5243bc6f3d2601 100644
--- a/library/Class/Notice.php
+++ b/library/Class/Notice.php
@@ -686,6 +686,7 @@ class Class_Notice extends Storm_Model_Abstract {
       case Class_Codification::CODE_URL: return  $this->getUrls();
       case Class_Codification::CODE_ANNEE: return  $this->getAnnee();
       case Class_Codification::CODE_PRIX: return  $this->getPrix();
+      case Class_CodifLangue::CODE_FACETTE: return  $this->getLangues();
       case Class_Codification::CODE_IDENTIFIANT: return  (new Class_Isbn($this->getIsbnOrEan()))->getAll()['isbn10'];
       case Class_Codification::CODE_NOUVEAUTE: return $this->isNouveaute() ? $this->_('Oui'): $this->_('Non');
     }
diff --git a/library/Class/WebService/OAI.php b/library/Class/WebService/OAI.php
index 9abb3b4b3aa648511da2ad82a2ffb76763a4a7f2..ad3cfced020f303aaba93e6623529c025065acdb 100644
--- a/library/Class/WebService/OAI.php
+++ b/library/Class/WebService/OAI.php
@@ -41,8 +41,10 @@ class Class_WebService_OAI extends Class_WebService_Abstract {
   protected $web_client;
   protected $numeric_resource_class = 'Class_WebService_BibNumerique_Numilog_LivreNumerique';
   protected $_listRecordsResumptionToken;
-  protected $metadata_prefix='oai_dc';
+  protected $metadata_prefix = 'oai_dc';
   protected $_first_page = 1;
+  protected $_logger;
+
   const ListSets = 'ListSets';
   const ListRecords = 'ListRecords';
 
@@ -96,7 +98,23 @@ class Class_WebService_OAI extends Class_WebService_Abstract {
     $parameters = array_merge(['verb' => $verb],
                               $parameters);
     $url = $this->oai_handler.'?'.http_build_query($parameters);
-    return $this->getContent($url);
+    $response = $this->getContent($url);
+    $this->_log($url, $response);
+
+    return $response;
+  }
+
+
+  protected function _log($url, $response) {
+    if (!$this->_logger)
+      return;
+    $this->_logger->log($url, $response);
+  }
+
+
+  public function setLogger($logger) {
+    $this->_logger = $logger;
+    return $this;
   }
 
 
diff --git a/library/Class/WebService/Premiere.php b/library/Class/WebService/Premiere.php
index f1d97a2877aade968da2be8bd8b10421f6972b38..9bbca85d110cbb54bed6565d2d45ec3ec29fca64 100644
--- a/library/Class/WebService/Premiere.php
+++ b/library/Class/WebService/Premiere.php
@@ -63,7 +63,7 @@ class Class_WebService_Premiere {
     }
 
     // Recherche du bon bloc
-    $start = '<div class="rSnippet" itemprop="description" content="';
+    $start = '<div class="field-item even" property="content:encoded">';
     if (!$pos = strPos($data, $start))
       return '';
     $pos = $pos + strlen($start);
diff --git a/library/Class/WebService/SIGB/Emprunteur.php b/library/Class/WebService/SIGB/Emprunteur.php
index f33aebe27698160a77fe186f0152e676131e7c20..f2186806d636857a999d410f6a26995efdd3aa78 100644
--- a/library/Class/WebService/SIGB/Emprunteur.php
+++ b/library/Class/WebService/SIGB/Emprunteur.php
@@ -713,6 +713,9 @@ class Class_WebService_SIGB_Emprunteur {
 
     if ($this->_id)
       $user->setIdSigb($this->_id);
+
+    if (($annexe = $this->getLibrary())  &&  ($bib = $annexe->getBib()))
+      $user->setBib($bib);
   }
 
 
diff --git a/library/Class/WebService/SIGB/Nanook/PatronInfoReader.php b/library/Class/WebService/SIGB/Nanook/PatronInfoReader.php
index 06e0aab3fde30d9e648a71a751e826dd32a8829a..49af883364194fa5c7f78750c46763dfb80c8292 100644
--- a/library/Class/WebService/SIGB/Nanook/PatronInfoReader.php
+++ b/library/Class/WebService/SIGB/Nanook/PatronInfoReader.php
@@ -224,5 +224,10 @@ class Class_WebService_SIGB_Nanook_PatronInfoReader extends Class_WebService_SIG
   public function getSuggestions() {
     return $this->_suggests;
   }
+
+
+  public function endSiteId($data) {
+    $this->getEmprunteur()->setLibraryCode($data);
+  }
 }
 ?>
\ No newline at end of file
diff --git a/library/startup.php b/library/startup.php
index eb6a6c96dc593c0629d2455f64cd2265e31dacab..a5536b5522c201a5a286f9b5f9da5edb25f37fab 100644
--- a/library/startup.php
+++ b/library/startup.php
@@ -38,7 +38,7 @@ function setupOpac() {
   require_once('requires.php');
 
   $cfg = loadConfig();
-  setupSession($cfg);
+  setupSession();
   setupDatabase($cfg);
   Class_AdminVar::findAll();
   setupLanguage();
@@ -64,7 +64,7 @@ function defineConstant($name, $value) {
 
 function setupConstants() {
   defineConstant('BOKEH_MAJOR_VERSION','7.3');
-  defineConstant('BOKEH_RELEASE_NUMBER', BOKEH_MAJOR_VERSION . '.22');
+  defineConstant('BOKEH_RELEASE_NUMBER', BOKEH_MAJOR_VERSION . '.23');
 
   defineConstant('BOKEH_REMOTE_FILES', 'http://git.afi-sa.fr/afi/opacce/');
 
@@ -166,7 +166,7 @@ function setupCache($cfg) {
 }
 
 
-function setupSession($cfg) {
+function setupSession() {
   // Start Session
   $session = new Zend_Session_Namespace(md5(BASE_URL));
   if (!isset($session->initialized))
diff --git a/tests/application/modules/admin/controllers/AccueilControllerTest.php b/tests/application/modules/admin/controllers/AccueilControllerTest.php
index 1478e833a80312147f614646c9e73aaa58b00d03..9f34c4c254556614bbf842dcc4dc1e61af0aafce 100644
--- a/tests/application/modules/admin/controllers/AccueilControllerTest.php
+++ b/tests/application/modules/admin/controllers/AccueilControllerTest.php
@@ -237,6 +237,7 @@ class AccueilControllerConfigSitothequePostTest extends Admin_AbstractController
 
   }
 
+
   /** @test */
   public function selectHierachicalDisplayShouldForceGroupByCategoryToFalse() {
     $this->postDispatch('/admin/accueil/sitotheque?config=accueil&id_profil=1&type_module=SITO&id_module=25',
@@ -249,8 +250,24 @@ class AccueilControllerConfigSitothequePostTest extends Admin_AbstractController
 
 
     $this->assertEquals('0', Class_Profil::find(1)->getModuleAccueilConfig(25,'SITO')['preferences']['group_by_categorie']);
+  }
+
+
+  /** @test */
+  public function selectDisplayShouldNotForceGroupByCategoryToFalse() {
+    $this->postDispatch('/admin/accueil/sitotheque?config=accueil&id_profil=1&type_module=SITO&id_module=25',
+                        [
+                         'type_aff' => 1,
+                         'nb_aff' => 2,
+                         'group_by_categorie' => true,
+                         'id_categorie' => '12-17'
+                        ]);
+
 
+    $this->assertEquals(true, Class_Profil::find(1)->getModuleAccueilConfig(25,'SITO')['preferences']['group_by_categorie']);
   }
+
+
   /** @test */
   public function selectHierachicalDisplayWithEmptyCategoriesShouldSaveOnlyFirstCategory() {
     $this->postDispatch('/admin/accueil/sitotheque?config=accueil&id_profil=1&type_module=SITO&id_module=25',
@@ -264,9 +281,11 @@ class AccueilControllerConfigSitothequePostTest extends Admin_AbstractController
     $this->assertEquals('',Class_Profil::find(1)->getModuleAccueilConfig(25,'SITO')['preferences']['id_categorie']);
 
   }
+}
+
+
 
 
-}
 class AccueilControllerConfigSitothequeDefaultsTest extends Admin_AbstractControllerTestCase {
   public function setUp() {
     parent::setUp();
diff --git a/tests/application/modules/admin/controllers/AdminIndexControllerTest.php b/tests/application/modules/admin/controllers/AdminIndexControllerTest.php
index abe9116d9b6eb7485cd7900a503f50378c02de3f..e4e5b415c647190e45e3e9484a28227b5e0a0453 100644
--- a/tests/application/modules/admin/controllers/AdminIndexControllerTest.php
+++ b/tests/application/modules/admin/controllers/AdminIndexControllerTest.php
@@ -836,7 +836,7 @@ class AdminIndexControllerAdminVarEditSearchAlsoInPostTest
 
   /** @test */
   public function varShouldContainsUrl() {
-    $this->assertContains('http://jumelles.fr/?q=%s',
-                          Class_AdminVar::find('SEARCH_ALSO_IN')->getValeur());
+    $this->assertEquals('http://jumelles.fr/?q=%s',
+                        json_decode(Class_AdminVar::find('SEARCH_ALSO_IN')->getValeur())->site_url[0]);
   }
 }
diff --git a/tests/application/modules/admin/controllers/SystemeControllerWebServicesTest.php b/tests/application/modules/admin/controllers/SystemeControllerWebServicesTest.php
index b6e6e60a06eb6c42c44081b39bf2d1818fede43e..d4ba3f492981a777b29468280f35697f31348c12 100644
--- a/tests/application/modules/admin/controllers/SystemeControllerWebServicesTest.php
+++ b/tests/application/modules/admin/controllers/SystemeControllerWebServicesTest.php
@@ -18,8 +18,6 @@
  * along with BOKEH; if not, write to the Free Software
  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301  USA
  */
-require_once 'AdminAbstractControllerTestCase.php';
-
 class SystemeControllerWebServicesIndexActionTest extends Admin_AbstractControllerTestCase {
   public function setUp() {
     parent::setUp();
@@ -64,6 +62,7 @@ class SystemeControllerWebServicesActionTest extends Admin_AbstractControllerTes
    */
   public function webServicePremiereGetResumeShouldWork() {
     $this->dispatch('/admin/systeme/webservices/id_service/Premiere/id_fonction/1', true);
+
     $this->assertXPathContentContains('//pre[@class="resultat"]',
                                       'Jake Sully est un ancien marine', $this->_response->getBody());
   }
diff --git a/tests/application/modules/opac/controllers/NoticeAjaxControllerTest.php b/tests/application/modules/opac/controllers/NoticeAjaxControllerTest.php
index 71713966f8dec1e6cbdfe54f38a902e3574410ac..4ddcb1d302c4e0d7eaf9e29fc20204e51a09c2c8 100644
--- a/tests/application/modules/opac/controllers/NoticeAjaxControllerTest.php
+++ b/tests/application/modules/opac/controllers/NoticeAjaxControllerTest.php
@@ -60,7 +60,8 @@ class NoticeAjaxControllerNonRegressionTest extends AbstractControllerTestCase {
 
 
 
-class NoticeAjaxControllerNoticeWithGamUrlTestCase extends AbstractControllerTestCase {
+
+class NoticeAjaxControllerDetailNoticeWithGamUrlTestCase extends AbstractControllerTestCase {
   protected $_wesley;
 
 
@@ -91,21 +92,34 @@ class NoticeAjaxControllerNoticeWithGamUrlTestCase extends AbstractControllerTes
 
     $this->fixture('Class_CosmoVar', ['id' => 'types_docs',
                                       'liste' => "1:cd\r\n200:non identifié\r\n201:livres\r\n202:bd"]);
+    $this->dispatch('/opac/noticeajax/detail/id_notice/1', true);
   }
 
 
   /** @test */
   public function withNoticeFoundResponseShouldContainsLienInternet() {
-    $this->dispatch('/opac/noticeajax/detail/id_notice/1', true);
     $this->assertXPathContentContains('//a', 'http://www.gamannecy.com//upload/albums/201202/0602527840871_thumb.jpg', $this->_response->getBody());
   }
-}
 
 
+  /** @test */
+  public function ddForYearShouldContains() {
+    $this->assertXPathContentContains('//dd[preceding-sibling::dt[contains(text(),"Ann")]]',
+                                      '2000');
+  }
 
-class NoticeAjaxControllerNoticeWithCustomLinks extends AbstractControllerTestCase {
+
+  /** @test */
+  public function ddForLanguageShouldContainsAnglais() {
+    $this->assertXPathContentContains('//dd[preceding-sibling::dt[contains(text(),"Langue(s)")]]',
+                                      'anglais');
+  }
+}
 
 
+
+
+class NoticeAjaxControllerNoticeWithCustomLinks extends AbstractControllerTestCase {
   public function setUp() {
     parent::setUp();
 
diff --git a/tests/application/modules/opac/controllers/RechercheControllerSearchExtensionTest.php b/tests/application/modules/opac/controllers/RechercheControllerSearchExtensionTest.php
index 73425ea2d2352fa88789eadfc75f2b4bf117849c..2d82cfd57e19c780984b92a996ab7309f7784154 100644
--- a/tests/application/modules/opac/controllers/RechercheControllerSearchExtensionTest.php
+++ b/tests/application/modules/opac/controllers/RechercheControllerSearchExtensionTest.php
@@ -111,10 +111,12 @@ class RechercheControllerSearchExtensionEnabledTest
   protected function _extensionSites() {
     return ['site_label' => ['Jumel',
                              'Incomplete',
-                             'Trouvons.org',],
+                             'Trouvons.org',
+                             'Gallica'],
             'site_url' => ['http://www.jumel39.fr/rechercher?search_api_views_fulltext=%s',
                            '',
-                           'http://trouvons.org/#q=%s']];
+                           'http://trouvons.org/#q=%s',
+                           'http://gallica.bnf.fr/services/engine/search/sru?operation=searchRetrieve&version=1.2&query=(gallica all "%s")']];
   }
 
 
@@ -142,6 +144,13 @@ class RechercheControllerSearchExtensionEnabledTest
     $this->assertXPathContentContains('//a[contains(@href, "#q=sport")]',
                                       'Trouvons.org');
   }
+
+
+  /** @test */
+  public function gallicaLinkShouldBeRendered() {
+    $this->assertXPathContentContains('//a[contains(@href, "gallica all ")]',
+                                      'Gallica');
+  }
 }
 
 
diff --git a/tests/db/UpgradeDBTest.php b/tests/db/UpgradeDBTest.php
index 77195bf2d0dd0415b32b4f4e9c845ebfb3799c14..adb49124462df6ffc8ec3659d9818ba7774d5c9a 100644
--- a/tests/db/UpgradeDBTest.php
+++ b/tests/db/UpgradeDBTest.php
@@ -28,10 +28,9 @@ abstract class UpgradeDBTestCase extends PHPUnit_Framework_TestCase {
 
   public function setUp() {
     if (!self::$_upgrade_done) {
-
-    $this->_movePatchLevelTo(self::BACK_PATCH_LEVEL);
-    $this->_runAllPrepares();
-    self::$_upgrade_done = true;
+      $this->_movePatchLevelTo(self::BACK_PATCH_LEVEL);
+      $this->_runAllPrepares();
+      self::$_upgrade_done = true;
     }
 
     (new Class_Migration_ScriptPatchs())->runTo($this->_getPatchLevel());
@@ -43,6 +42,11 @@ abstract class UpgradeDBTestCase extends PHPUnit_Framework_TestCase {
   }
 
 
+  public function lastInsertId() {
+    return Zend_Db_Table::getDefaultAdapter()->lastInsertId();
+  }
+
+
   public function _movePatchLevelTo($patch_level) {
     $this->query('update variables set valeur=' . $patch_level . ' where clef="patch_level"');
     $this->query('delete from patch_hash');
@@ -77,7 +81,6 @@ abstract class UpgradeDBTestCase extends PHPUnit_Framework_TestCase {
 
 
 
-
 class UpgradeDB_263_Test extends UpgradeDBTestCase {
   public function prepare() {
     $this->query('delete from permission where code="CATEGORY"');
@@ -98,6 +101,31 @@ class UpgradeDB_263_Test extends UpgradeDBTestCase {
 
 
 
+class UpgradeDB_268_Test extends UpgradeDBTestCase {
+  protected static $user_backup;
+
+  public function prepare() {
+    static::$user_backup = $this->query('select id_user, pseudo from bib_admin_users order by id_user limit 1')->fetch();
+  }
+
+
+  public function tearDown() {
+    $this->query('update bib_admin_users set pseudo="' . static::$user_backup['pseudo'] . '" where id_user=' . static::$user_backup['id_user']);
+  }
+
+
+  /** @test */
+  public function userPseudoCanBeHundredCharsLong() {
+    $hundred_chars_pseudo = str_pad('pseudo', 100, 'o', STR_PAD_BOTH);
+
+    $this->query('update bib_admin_users set pseudo="' . $hundred_chars_pseudo . '" where id_user=' . static::$user_backup['id_user']);
+
+    $this->assertEquals($hundred_chars_pseudo,
+                        $this->query('select pseudo from bib_admin_users where id_user=' . static::$user_backup['id_user'])->fetch()['pseudo']);
+  }
+}
+
+
 
 class UpgradeDB_274_Test extends UpgradeDBTestCase {
   public function prepare() {
@@ -115,29 +143,34 @@ class UpgradeDB_274_Test extends UpgradeDBTestCase {
 
 
 
-
-class UpgradeDB_268_Test extends UpgradeDBTestCase {
-  protected static $user_backup;
+class UpgradeDB_277_Test extends UpgradeDBTestCase {
+  protected static $_inserted_records = [];
 
   public function prepare() {
-    static::$user_backup = $this->query('select id_user, pseudo from bib_admin_users order by id_user limit 1')->fetch();
+    // insert orphan sito and article
+    $this->_prepareRecordOfType(Class_TypeDoc::SITE)
+         ->_prepareRecordOfType(Class_TypeDoc::ARTICLE);
   }
 
 
-  public function tearDown() {
-    $this->query('update bib_admin_users set pseudo="' . static::$user_backup['pseudo'] . '" where id_user=' . static::$user_backup['id_user']);
+  protected function _prepareRecordOfType($type) {
+    $this->query('insert into notices (type_doc) values (' . $type . ')');
+    static::$_inserted_records[] = $id = $this->lastInsertId();
+
+    $this->query('insert into exemplaires '
+                 .'(id_notice, id_bib, section, emplacement, zone995, id_int_bib) values '
+                 .'(' . $id . ', 1, "", "", "", 1)');
+
+    return $this;
   }
 
 
   /** @test */
-  public function userPseudoCanBeHundredCharsLong() {
-    $hundred_chars_pseudo = str_pad('pseudo', 100, 'o', STR_PAD_BOTH);
+  public function shouldHaveDeletedOrphanedRecordsAndItems() {
+    $query = 'select * from notices where id_notice in (' . implode(', ', static::$_inserted_records) .')';
+    $this->assertEmpty($this->query($query)->fetchAll());
 
-    $this->query('update bib_admin_users set pseudo="' . $hundred_chars_pseudo . '" where id_user=' . static::$user_backup['id_user']);
-
-    $this->assertEquals($hundred_chars_pseudo,
-                        $this->query('select pseudo from bib_admin_users where id_user=' . static::$user_backup['id_user'])->fetch()['pseudo']);
+    $query = 'select * from exemplaires where id_notice in (' . implode(', ', static::$_inserted_records) .')';
+    $this->assertEmpty($this->query($query)->fetchAll());
   }
-}
-
-?>
\ No newline at end of file
+}
\ No newline at end of file
diff --git a/tests/fixtures/GetPatronInfoFrancoisMorel.xml b/tests/fixtures/GetPatronInfoFrancoisMorel.xml
index 60de13e6f1ce0501bcf21835191117cec8577a17..fc7620a1de16106ef0285725c9ab429530f1eb4b 100644
--- a/tests/fixtures/GetPatronInfoFrancoisMorel.xml
+++ b/tests/fixtures/GetPatronInfoFrancoisMorel.xml
@@ -1,3 +1,3 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <GetPatronInfo><patronId>5352</patronId><barcode>7942236</barcode><lastName>MOREL</lastName><firstName>François</firstName><displayOrder>1</displayOrder><birthDate>1970-01-01</birthDate><phoneNumber>XX XX XX XX XX</phoneNumber><town>Amityville</town><zipcode>0666</zipcode><address>12&#29;6 Elm Street
-</address><endDate>2015-03-19</endDate><mail></mail><loans><loan><bibId>186567</bibId><itemId>72958</itemId><title>Le garçon qui voulait devenir un être humain</title><author>Jorn Riel</author><locationLabel>Médiathèque </locationLabel><loanDate>2014-06-25</loanDate><dueDate>2014-07-25</dueDate></loan><loan><bibId>186564</bibId><itemId>72955</itemId><title>Le garçon qui voulait devenir un être humain</title><author>Jorn Riel</author><locationLabel>Médiathèque </locationLabel><loanDate>2014-06-25</loanDate><dueDate>2014-07-25</dueDate></loan><loan><bibId>279034</bibId><itemId>111089</itemId><title>La vieille qui voulait tuer le bon Dieu</title><author>Nadine Monfils</author><locationLabel>Médiathèque </locationLabel><loanDate>2014-07-04</loanDate><dueDate>2014-08-03</dueDate></loan><loan><bibId>273559</bibId><itemId>111718</itemId><title>Un fleuve de fumée</title><author>Amitav Ghosh</author><locationLabel>Médiathèque </locationLabel><loanDate>2014-07-04</loanDate><dueDate>2014-08-03</dueDate></loan><loan><bibId>198354</bibId><itemId>83017</itemId><title>Demoiselles des Lumières</title><author>Jean Diwo</author><locationLabel>Médiathèque </locationLabel><loanDate>2014-07-04</loanDate><dueDate>2014-08-03</dueDate></loan><loan><bibId>230310</bibId><itemId>91620</itemId><title>Le naufrage</title><author>Eric Roussel</author><locationLabel>Médiathèque </locationLabel><loanDate>2014-07-04</loanDate><dueDate>2014-08-03</dueDate></loan></loans><holds><hold><bibId>280792</bibId><itemId>112771</itemId><title>Le livre du roi</title><author>Arnaldur Indriòason</author><locationLabel>Médiathèque </locationLabel><priority>1</priority><available>0</available><availabilityDate>11/08/2014</availabilityDate></hold><hold><bibId>152968</bibId><itemId>42029</itemId><title>L'énigme de Ravejouls</title><author>Alain Gandy</author><locationLabel>Médiathèque </locationLabel><priority>1</priority><available>0</available><availabilityDate>24/07/2014</availabilityDate></hold></holds><suggests/></GetPatronInfo>
+</address><endDate>2015-03-19</endDate><mail></mail><siteId>8</siteId><loans><loan><bibId>186567</bibId><itemId>72958</itemId><title>Le garçon qui voulait devenir un être humain</title><author>Jorn Riel</author><locationLabel>Médiathèque </locationLabel><loanDate>2014-06-25</loanDate><dueDate>2014-07-25</dueDate></loan><loan><bibId>186564</bibId><itemId>72955</itemId><title>Le garçon qui voulait devenir un être humain</title><author>Jorn Riel</author><locationLabel>Médiathèque </locationLabel><loanDate>2014-06-25</loanDate><dueDate>2014-07-25</dueDate></loan><loan><bibId>279034</bibId><itemId>111089</itemId><title>La vieille qui voulait tuer le bon Dieu</title><author>Nadine Monfils</author><locationLabel>Médiathèque </locationLabel><loanDate>2014-07-04</loanDate><dueDate>2014-08-03</dueDate></loan><loan><bibId>273559</bibId><itemId>111718</itemId><title>Un fleuve de fumée</title><author>Amitav Ghosh</author><locationLabel>Médiathèque </locationLabel><loanDate>2014-07-04</loanDate><dueDate>2014-08-03</dueDate></loan><loan><bibId>198354</bibId><itemId>83017</itemId><title>Demoiselles des Lumières</title><author>Jean Diwo</author><locationLabel>Médiathèque </locationLabel><loanDate>2014-07-04</loanDate><dueDate>2014-08-03</dueDate></loan><loan><bibId>230310</bibId><itemId>91620</itemId><title>Le naufrage</title><author>Eric Roussel</author><locationLabel>Médiathèque </locationLabel><loanDate>2014-07-04</loanDate><dueDate>2014-08-03</dueDate></loan></loans><holds><hold><bibId>280792</bibId><itemId>112771</itemId><title>Le livre du roi</title><author>Arnaldur Indriòason</author><locationLabel>Médiathèque </locationLabel><priority>1</priority><available>0</available><availabilityDate>11/08/2014</availabilityDate></hold><hold><bibId>152968</bibId><itemId>42029</itemId><title>L'énigme de Ravejouls</title><author>Alain Gandy</author><locationLabel>Médiathèque </locationLabel><priority>1</priority><available>0</available><availabilityDate>24/07/2014</availabilityDate></hold></holds><suggests/></GetPatronInfo>
diff --git a/tests/library/Class/AdminVarTest.php b/tests/library/Class/AdminVarTest.php
index ddbceaeda930a1cdd47121610058b274a54055ba..824bfdf2cac372a7aee8d5ff531c3a149161d749 100644
--- a/tests/library/Class/AdminVarTest.php
+++ b/tests/library/Class/AdminVarTest.php
@@ -83,17 +83,6 @@ class AdminVarTestGet extends AdminVarTestCase {
   }
 
 
-  /** @test */
-  public function getVarShouldStripSlashes() {
-    $this->fixture('Class_AdminVar',
-                   ['id' => 'JS_STAT',
-                    'valeur' => addslashes('<script type="text/javascript">\'test\'')]);
-
-    $this->assertEquals('<script type="text/javascript">\'test\'',
-                        Class_AdminVar::get('JS_STAT'));
-  }
-
-
   /** @test */
   public function unleashFacetDescriptionShouldContainsLinkToRemoteFiles() {
     $this->fixture('Class_AdminVar',
diff --git a/tests/library/Class/Cosmogramme/Integration/PhaseBatchsTest.php b/tests/library/Class/Cosmogramme/Integration/PhaseBatchsTest.php
index 6463d52559add4dea8474ff323d98402a87c235a..5814fa6d1156f02f1424f07a956701aa77417724 100644
--- a/tests/library/Class/Cosmogramme/Integration/PhaseBatchsTest.php
+++ b/tests/library/Class/Cosmogramme/Integration/PhaseBatchsTest.php
@@ -21,7 +21,7 @@
 
 
 abstract class PhaseBatchsTestCase extends Class_Cosmogramme_Integration_PhaseTestCase {
-  protected $_batch;
+  protected $_batch, $_registry_http_client, $_mock_http_client;
 
   protected function _prepareFixtures() {
     $this->fixture('Class_Batch',
@@ -41,8 +41,20 @@ abstract class PhaseBatchsTestCase extends Class_Cosmogramme_Integration_PhaseTe
 
   public function setUp() {
     parent::setUp();
+
+    $this->_registry_http_client = Zend_Registry::get('httpClient');
+    $this->_mock_http_client = $this->mock();
+    $this->_mock_http_client->whenCalled('setAuth')->answers($this->_mock_http_client);
+    Zend_Registry::set('httpClient', $this->_mock_http_client);
+
     $this->_buildPhase('Batchs')->run();
   }
+
+
+  public function tearDown() {
+    Zend_Registry::set('httpClient', $this->_registry_http_client);
+    parent::tearDown();
+  }
 }
 
 
@@ -102,6 +114,16 @@ class PhaseBatchsCronRunTest extends PhaseBatchsTestCase {
   public function shouldDisplayElapsedTime() {
     $this->assertLogContains('Temps de traitement');
   }
+
+
+  /**
+   * @test
+   * @see http://forge.afi-sa.fr/issues/28103
+   */
+  public function httpAuthShouldHaveBeenReset() {
+    $this->assertTrue($this->_mock_http_client
+                      ->methodHasBeenCalled('setAuth'));
+  }
 }
 
 
diff --git a/tests/library/Class/FileManagerTest.php b/tests/library/Class/FileManagerTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..7be30a02b468ca625de417e8d8794ccc8da01b43
--- /dev/null
+++ b/tests/library/Class/FileManagerTest.php
@@ -0,0 +1,96 @@
+<?php
+/**
+ * Copyright (c) 2012, Agence Française Informatique (AFI). All rights reserved.
+ *
+ * BOKEH is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE as published by
+ * the Free Software Foundation.
+ *
+ * There are special exceptions to the terms and conditions of the AGPL as it
+ * is applied to this software (see README file).
+ *
+ * BOKEH is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU AFFERO GENERAL PUBLIC LICENSE for more details.
+ *
+ * You should have received a copy of the GNU AFFERO GENERAL PUBLIC LICENSE
+ * along with BOKEH; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301  USA
+ */
+
+class FileManagerTest extends ModelTestCase {
+  protected
+    $_filemanager,
+    $_admin;
+
+  public function setUp() {
+    parent::setUp();
+    $this->_filemanager = new Class_FileManager();
+    $this->_admin = $this->fixture('Class_Users',
+                                   ['id' => 2,
+                                    'login' => 'admin',
+                                    'password' => 'admin']);
+    $this->_admin->beModoBib()->save();
+
+
+    $this->_guest = $this->fixture('Class_Users',
+                                   ['id' => 3,
+                                    'login' => 'guest',
+                                    'password' => 'guest']);
+    $this->_guest->beInvite()->save();
+
+  }
+
+  /** @test */
+  public function withoutAuthenticationUserfilesShouldNotBeAuthorized() {
+    $this->assertFalse($this->_filemanager->isAuthorized(USERFILESURL . 'images/bokeh.png'));
+  }
+
+
+  /** @test */
+  public function asModoBibUserfilesShouldBeAuthorized() {
+    ZendAfi_Auth::getInstance()->logUser($this->_admin);
+    $this->assertTrue($this->_filemanager->isAuthorized(USERFILESURL . 'images/bokeh.png'));
+  }
+
+
+  /** @test */
+  public function asGuestUserfilesShouldNotBeAuthorized() {
+    ZendAfi_Auth::getInstance()->logUser($this->_guest);
+    $this->assertFalse($this->_filemanager->isAuthorized(USERFILESURL . 'images/bokeh.png'));
+  }
+}
+
+
+
+
+class FileManagerAsAdminTest extends ModelTestCase {
+  protected $_filemanager;
+
+  public function setUp() {
+    parent::setUp();
+    $this->_filemanager = new Class_FileManager();
+
+    $this->_admin = $this->fixture('Class_Users',
+                                   ['id' => 2,
+                                    'login' => 'admin',
+                                    'password' => 'admin']);
+    $this->_admin->beAdminPortail()->save();
+    ZendAfi_Auth::getInstance()->logUser($this->_admin);
+  }
+
+
+  /** @test */
+  public function rootShouldNotBeAuthorized() {
+    $this->assertFalse($this->_filemanager->isAuthorized('/'));
+  }
+
+
+  /** @test */
+  public function upperDirectoryShouldNotBeAuthorized() {
+    $this->assertFalse($this->_filemanager->isAuthorized(USERFILESURL . '../'));
+  }
+}
+
+?>
\ No newline at end of file
diff --git a/tests/library/Class/UsersTest.php b/tests/library/Class/UsersTest.php
index 7b9548810a4c4cd9a038b25e6b47dac3aca76983..2fb44f14322f2e61c0b2dc7742ff55df53c6d50f 100644
--- a/tests/library/Class/UsersTest.php
+++ b/tests/library/Class/UsersTest.php
@@ -19,9 +19,6 @@
  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301  USA
  */
 
-require_once 'Class/Newsletter.php';
-require_once 'ModelTestCase.php';
-
 class UserFixtures {
   public static function miles() {
     return array('ID_USER' => 1,
diff --git a/tests/library/Class/WebService/SIGB/NanookTest.php b/tests/library/Class/WebService/SIGB/NanookTest.php
index b957ded7b7f2338e2d63db62b83ac5af3defa27e..ced2ee8c3b32b6d8620582b1189ba84f6c7536d2 100644
--- a/tests/library/Class/WebService/SIGB/NanookTest.php
+++ b/tests/library/Class/WebService/SIGB/NanookTest.php
@@ -78,11 +78,23 @@ abstract class NanookTestCase extends Storm_Test_ModelTestCase {
       ->setServerRoot('http://localhost:8080/afi_Nanook/ilsdi/')
       ->setWebClient($this->_mock_web_client);
 
+    $this->fixture('Class_Bib',
+                   ['id' => 3,
+                    'libelle' => 'Cran-Gévrier']);
+
     $this->fixture('Class_CodifAnnexe' , ['id' => 3,
                                           'libelle' => 'Annexe Cran-Gevrier',
                                           'id_bib' => 3,
                                           'code' => 10]);
 
+    $this->fixture('Class_Bib',
+                   ['id' => 5,
+                    'libelle' => 'Seynod']);
+
+    $this->fixture('Class_CodifAnnexe' , ['id' => 4,
+                                          'libelle' => 'Annexe Seynod',
+                                          'id_bib' => 5,
+                                          'code' => 8]);
   }
 }
 
@@ -182,6 +194,7 @@ class NanookHtmlResponseErrorTest extends NanookServiceErrorTestCase {
     $this->assertEmpty($this->_emprunteur->getEmprunts());
   }
 
+
   /** @test */
   public function validShouldBeFalse() {
     $this->assertFalse($this->_emprunteur->isValid());
@@ -408,7 +421,8 @@ class NanookGetEmprunteurChristelDelpeyrouxTest extends NanookTestCase {
 
     $this->_chrystel = Class_Users::newInstance(['id_sigb' => 1,
                                                  'login' => 8765,
-                                                 'password' => 2002]);
+                                                 'password' => 2002,
+                                                 'id_site' => 3]);
     $this->_emprunteur = $this->_service->getEmprunteur($this->_chrystel);
     $this->_emprunteur->updateUser($this->_chrystel);
 
@@ -508,6 +522,12 @@ class NanookGetEmprunteurChristelDelpeyrouxTest extends NanookTestCase {
   }
 
 
+  /** @test */
+  public function userBibShouldStayCranGevrier() {
+    $this->assertEquals('Cran-Gévrier', $this->_chrystel->getLibelleBib());
+  }
+
+
   /** @test */
   public function nbEmpruntsShouldBeThree() {
     $this->assertEquals(3, $this->_emprunteur->getNbEmprunts());
@@ -698,6 +718,9 @@ class NanookGetEmprunteurChristelDelpeyrouxTest extends NanookTestCase {
   }
 }
 
+
+
+
 class NanookGetEmprunteurFrancoisMorelTest extends NanookTestCase {
   /** @var Class_WebService_SIGB_Emprunteur */
   protected $_emprunteur;
@@ -716,8 +739,8 @@ class NanookGetEmprunteurFrancoisMorelTest extends NanookTestCase {
       ->answers(NanookFixtures::xmlGetPatronInfoFrancoisMorel());
 
     $this->_user = Class_Users::newInstance(['id_sigb' => 5352,
-                                                 'login' => 7942236,
-                                                 'password' => 1900]);
+                                             'login' => 7942236,
+                                             'password' => 1900]);
     $this->_emprunteur = $this->_service->getEmprunteur($this->_user);
     $this->_emprunteur->updateUser($this->_user);
 
@@ -726,15 +749,30 @@ class NanookGetEmprunteurFrancoisMorelTest extends NanookTestCase {
       ->answers(null);
   }
 
+
   /** @test */
   public function getEmpruntsShouldReturnsAllLoans() {
     $loans = $this->_emprunteur->getEmprunts();
     $this->assertEquals(6, count($loans));
   }
+
+
+
+  /** @test */
+  public function emprunteurLibraryLabelShouldBeAnnexeSeynod() {
+    $this->assertEquals('Annexe Seynod', $this->_emprunteur->getLibraryLabel());
+  }
+
+
+  /** @test */
+  public function userBibShouldBeSeynod() {
+    $this->assertEquals('Seynod', $this->_user->getBib()->getLibelle());
+  }
 }
 
 
 
+
 class NanookGetEmprunteurWithErrorTest extends NanookTestCase {
   /** @test */
   public function emprunteurShouldBeEmpty() {