diff --git a/VERSIONS_HOTLINE/37288 b/VERSIONS_HOTLINE/37288
new file mode 100644
index 0000000000000000000000000000000000000000..54f149ec3de32e0fc0a31e79ca1a074116394392
--- /dev/null
+++ b/VERSIONS_HOTLINE/37288
@@ -0,0 +1 @@
+ - ticket #37288 : Correction de la localisation des exemplaires
\ No newline at end of file
diff --git a/VERSIONS_HOTLINE/9366 b/VERSIONS_HOTLINE/9366
new file mode 100644
index 0000000000000000000000000000000000000000..619fb804b8e94b871cbe5c0c220d252228cbaf9f
--- /dev/null
+++ b/VERSIONS_HOTLINE/9366
@@ -0,0 +1 @@
+ - ticket #9366 : Correction du message d'indisponibilité
\ No newline at end of file
diff --git a/VERSIONS_WIP/35272 b/VERSIONS_WIP/35272
new file mode 100644
index 0000000000000000000000000000000000000000..e0f67a886c659cb22ec2a71d766b35d710776de3
--- /dev/null
+++ b/VERSIONS_WIP/35272
@@ -0,0 +1 @@
+ - ticket #35272 : Formulaire d'inscription : possibilité de paramétrer l'affichage des champs bibliothèque et numéro de carte
\ No newline at end of file
diff --git a/application/modules/admin/controllers/ModulesController.php b/application/modules/admin/controllers/ModulesController.php
index eea626f7e69f58bc3013fb25dc84e50956861690..2ba944397d49f310fbce2713f65a304c3b506054 100644
--- a/application/modules/admin/controllers/ModulesController.php
+++ b/application/modules/admin/controllers/ModulesController.php
@@ -44,8 +44,8 @@ class Admin_ModulesController extends ZendAfi_Controller_Action {
 
   public function preDispatch() {
     parent::preDispatch();
-    if ($this->_request->getActionName()!='kiosque-change-data' &&
-        $this->_request->getActionName()!='search-result')
+    if (!in_array($this->_request->getActionName(),
+                  ['kiosque-change-data', 'search-result', 'auth-register']))
       Zend_Layout::startMvc();
   }
 
@@ -97,10 +97,26 @@ class Admin_ModulesController extends ZendAfi_Controller_Action {
 
 
   public function authAction() {
+    if ('register' == $this->_getParam('action1'))
+      return $this->_forward('auth-register');
+
     return $this->_simpleAction('auth_'.$this->_getParam('action1'));
   }
 
 
+  public function authRegisterAction() {
+    $form = ZendAfi_Form_Configuration_AuthRegister::newConfigurationWith($this->preferences);
+    if ($this->_request->isPost() && $form->isValid($this->_request->getPost())) {
+      $datas = $form->getValues();
+      unset($datas['submit']);
+
+      return $this->updateEtRetour($datas);
+    }
+
+    $this->view->form = $form;
+  }
+
+
   public function cmsAction() {
     return $this->_simpleAction(($this->_getParam('action1') == 'articleviewbydate')
                                 ? 'cms_articleviewbydate' : 'cms_all');
diff --git a/application/modules/admin/views/scripts/modules/auth-register.phtml b/application/modules/admin/views/scripts/modules/auth-register.phtml
new file mode 100644
index 0000000000000000000000000000000000000000..a77ca805bea2b10e567e9f4184a61fd9b389811a
--- /dev/null
+++ b/application/modules/admin/views/scripts/modules/auth-register.phtml
@@ -0,0 +1,4 @@
+<center>
+  <h1><?php echo $this->_('Propriétés du module : %s', $this->titre_module); ?></h1>
+  <?php echo $this->renderForm($this->form); ?>
+</center>
diff --git a/application/modules/admin/views/scripts/modules/auth_register.phtml b/application/modules/admin/views/scripts/modules/auth_register.phtml
deleted file mode 100644
index bc4491adc28ae12683d0d1ea856bc5fcc05d3d19..0000000000000000000000000000000000000000
--- a/application/modules/admin/views/scripts/modules/auth_register.phtml
+++ /dev/null
@@ -1,26 +0,0 @@
-<?php echo $this->render('modules/_debut.phtml');?>
-      
-<br>
-<fieldset>
-  <legend>Préférences</legend>
-  <table cellspacing="2">
-
-    <tr>
-      <td class="droite">Titre &nbsp;</td>
-      <td class="gauche"><input type="text" name="titre" size="40" value="<?php print($this->preferences["titre"]); ?>"></td>
-    </tr>
-    <tr>
-      <td class="droite">Texte d'aide &nbsp;</td>
-      <td class="gauche"><textarea cols="70" rows="5" name="register_help"><?php print($this->preferences["register_help"]); ?></textarea></td>
-    </tr>
-    <tr>
-      <td class="droite">Texte de confirmation &nbsp;</td>
-      <td class="gauche"><textarea cols="70" rows="5" name="register_confirm"><?php print($this->preferences["register_confirm"]); ?></textarea></td>
-    </tr>
-    
-
-  </table>
-</fieldset>
-
-<?php echo $this->render('modules/_fin.phtml');?>
-
diff --git a/application/modules/opac/controllers/AuthController.php b/application/modules/opac/controllers/AuthController.php
index 64862e20875a6dc1ddb5781c73174eca6e3f8dd7..bbcd1e00fa68d78a64080384662628723278e4ad 100644
--- a/application/modules/opac/controllers/AuthController.php
+++ b/application/modules/opac/controllers/AuthController.php
@@ -205,60 +205,22 @@ class AuthController extends ZendAfi_Controller_Action {
 
 
   public function registerAction()  {
-    $this->view->preferences = Class_Profil::getCurrentProfil()->getCfgModulesPreferences('auth', 'register');
-    if (Class_AdminVar::get('INTERDIRE_ENREG_UTIL'))
+    if (Class_AdminVar::get('INTERDIRE_ENREG_UTIL')) {
       $this->_redirect('/');
+      return;
+    }
+
+    $this->view->preferences = Class_Profil::getCurrentProfil()->getCfgModulesPreferences('auth', 'register');
+
+    $this->view->form = new ZendAfi_Form_Register();
 
-    $this->view->form = ZendAfi_Form::newWithOptions(['action' => $this->view->url(['module'=>'opac',
-                                                                  'controller'=>'auth',
-                                                                  'action'=>'register'])])
-
-      ->addElement('text', 'login', ['label' => $this->view->_('Identifiant'),
-                                     'maxlength' => 20,
-                                     'required' => true,
-                                     'validators' => ['LoginExists']])
-
-      ->addElement('password', 'mdp', ['label' => $this->view->_('Mot de passe'),
-                                       'maxlength' => 15,
-                                       'required' => true])
-
-      ->addElement('password', 'mdp2', ['label' => $this->view->_('Confirmez votre mot de passe'),
-                                        'maxlength' => 15,
-                                        'required' => true,
-                                        'validators' => [new ZendAfi_Validate_PasswordEquals('mdp')]])
-
-      ->addElement('email', 'mail', ['label' => $this->view->_('E-mail'),
-                                     'maxlength' => 50,
-                                     'required' => true,
-                                     'validators' => ['MailExists']])
-
-      ->addElement('email', 'mail2', ['label' => $this->view->_('Confirmez votre e-mail'),
-                                      'maxlength' => 50,
-                                      'required' => true,
-                                      'validators' => [new ZendAfi_Validate_MailEquals('mail')]])
-
-      ->addDisplayGroup(['login', 'mdp', 'mdp2', 'mail', 'mail2'],
-                        'fields',
-                        ['legend' => ''])
-
-      ->addElement('captcha', 'captcha', array('captcha' => 'Image',
-                                               'label' => $this->view->_('Recopiez le code'),
-                                               'captchaOptions' => array('font' => PATH_FONTS.'/Vera.ttf',
-                                                                         'imgDir' => PATH_CAPTCHA,
-                                                                         'imgUrl' => URL_CAPTCHA)))
-      ->addDisplayGroup(['captcha'],
-                        'security',
-                        ['legend' => $this->view->_('Sécurité'),
-                         'required' => true])
-      ->addElement('submit','submit', ['label' => $this->view->_('Valider')]);
-
-
-    if ($this->_request->isPost() && $this->view->form->isValid($this->_request->getPost()))  {
-      // recup _post
+
+    if ($this->_request->isPost()
+        && $this->view->form->isValid($this->_request->getPost())) {
       $data = ZendAfi_Filters_Post::filterStatic($this->_request->getPost());
       $class_user = new Class_Users();
       $data['cle'] = md5($data['mail']);
-      $ret=$class_user->registerUser($data);
+      $ret = $class_user->registerUser($data);
 
       // Affichage des erreurs
       if(isset($ret["error"])) {
@@ -357,7 +319,6 @@ class AuthController extends ZendAfi_Controller_Action {
   }
 
 
-
   public function activeuserAction() {
     if (!$cle = $this->_request->getParam('c'))
       $this->_redirect('/');
diff --git a/application/modules/opac/views/scripts/index/sitedown.phtml b/application/modules/opac/views/scripts/index/sitedown.phtml
index 604c663041dfad71587637c88195f4f0841fcced..404033260a98274ba9f27aad8a82e07c3882b7ef 100644
--- a/application/modules/opac/views/scripts/index/sitedown.phtml
+++ b/application/modules/opac/views/scripts/index/sitedown.phtml
@@ -2,11 +2,11 @@
 <div style="margin-top:70px;margin-bottom:150px;">
   <h2 id="error">
     <p class="erreur">
-<?php 
+<?php
 
-print($this->traduire("L'accès au site est momentanément bloqué.<br><br> Veuillez essayez plus tard.")); 
+print($this->traduire("L'accès au site est momentanément bloqué.<br><br> Veuillez essayer plus tard."));
 ?>
     </p>
   </h2>
 </div>
-</center>
\ No newline at end of file
+</center>
diff --git a/cosmogramme/sql/patch/patch_287.php b/cosmogramme/sql/patch/patch_287.php
new file mode 100644
index 0000000000000000000000000000000000000000..58f6b24e70a9055e5e62d8e66bb7434ee35b1ed3
--- /dev/null
+++ b/cosmogramme/sql/patch/patch_287.php
@@ -0,0 +1,11 @@
+<?php
+$adapter = Zend_Db_Table::getDefaultAdapter();
+
+$column_adder = function($column) use ($adapter) {
+  try {
+    $adapter->query('ALTER TABLE bib_admin_users_non_valid ADD COLUMN ' . $column);
+  } catch(Exception $e) {}
+};
+
+$column_adder('id_site smallint(6) null');
+$column_adder('idabon varchar(20) null');
diff --git a/library/Class/Exemplaire.php b/library/Class/Exemplaire.php
index 618854ad9b72a58672fe5373b44d6e7bb08edb72..1486ef51fe4ac1c33ee7322542019af8292f6137 100644
--- a/library/Class/Exemplaire.php
+++ b/library/Class/Exemplaire.php
@@ -80,9 +80,9 @@ class Class_Exemplaire extends Storm_Model_Abstract {
 
 
   public function getBestCote() {
-    if($this->_sigb_exemplaire &&
-       ($sigb_cote = $this->_sigb_exemplaire->getCote()) &&
-       (strlen($sigb_cote) > strlen($this->getCote())))
+    if ($this->getSigbExemplaire() &&
+        ($sigb_cote = $this->getSigbExemplaire()->getCote()) &&
+        (strlen($sigb_cote) > strlen($this->getCote())))
       return $sigb_cote;
 
     return $this->getCote();
diff --git a/library/Class/Localisation.php b/library/Class/Localisation.php
index e6ef278ee1ece6f1d67815d466503dd3e4e875e8..7afe7020da660c1e22ad770f5355d5035c8ae756 100644
--- a/library/Class/Localisation.php
+++ b/library/Class/Localisation.php
@@ -232,12 +232,15 @@ class Class_Localisation extends Storm_Model_Abstract {
 
     $quality = count(array_intersect_assoc($matching_datas, $exemplaire_datas));
 
+    if ($quality < count($matching_datas) && $quality < (count($exemplaire_datas)))
+      return null;
+
     if( 0 > ($cote_quality = $this->coteMatchingQuality($exemplaire)))
       return null;
 
     $quality += $cote_quality;
 
-    return [$quality => $this];
+    return ($quality > 0) ? [$quality => $this] : null;
   }
 
 
diff --git a/library/Class/Profil.php b/library/Class/Profil.php
index f3c1562cd048b1d12f0c6b73cbaef48c008fdda3..974edf1d140ed2d92af6e35cbed5262b33d746af 100644
--- a/library/Class/Profil.php
+++ b/library/Class/Profil.php
@@ -921,6 +921,16 @@ class Class_Profil extends Storm_Model_Abstract {
   }
 
 
+  public function setCfgModulesPreferences($prefs, $controller, $action, $subaction = '') {
+    $prefs = array_merge($this->getCfgModulesPreferences($controller, $action, $subaction),
+                         $prefs);
+
+    $cfg_modules = $this->getCfgModulesAsArray();
+    $cfg_modules[$controller][$action.$subaction] = $prefs;
+    $this->setCfgModules($cfg_modules)->save();
+  }
+
+
   /**
    * @return string la liste des codes a afficher sur la notice dans
    * le résultat de recherche (ex: 'TANGE')
diff --git a/library/Class/Systeme/ModulesAppli.php b/library/Class/Systeme/ModulesAppli.php
index 6b69a569e464d9aabe7a56591883d1d45cacc7b1..c895e1c0bcb0b39a1e2df0618c2fb23e90ccf65a 100644
--- a/library/Class/Systeme/ModulesAppli.php
+++ b/library/Class/Systeme/ModulesAppli.php
@@ -67,8 +67,8 @@ class Class_Systeme_ModulesAppli extends Class_Systeme_ModulesAbstract {
                                              'popup_width' => 800,
                                              'popup_height' => 700],
                                  'register' => ['libelle' => 'Demande d\'inscription',
-                                                'popup_width' => 710,
-                                                'popup_height' => 290],
+                                                'popup_width' => 800,
+                                                'popup_height' => 700],
                                  'lostpass' => ['libelle' => 'Mot de passe oublié',
                                                 'popup_width' => 710,
                                                 'popup_height' => 290]],
@@ -280,35 +280,26 @@ class Class_Systeme_ModulesAppli extends Class_Systeme_ModulesAbstract {
    * @return int
    */
   private function getDefautAuth($action) {
-    $ret = array();
-
-    switch ((string)$action) {
-      case "login":
-        $ret=array_merge(['barre_nav'=>'Connexion'],
+    if ('login' == $action)
+      return array_merge(['barre_nav' => 'Connexion'],
                          (new Class_Systeme_ModulesAccueil_Login())->getDefaultValues());
-        break;
-      case "register":
-        $ret["barre_nav"] = "S'inscrire";           // Barre de nav
-        $ret["titre"] = "Demande d'inscription";        // Titre de la boite
-        $ret["register_help"] = "Remplissez les champs ci-dessous\n"
-          ."Un mail de confirmation vous sera envoyé.\n"
-          ."Vous devrez cliquer sur le lien pour confirmer la création de votre compte.";        // Texte d'aide
-        $ret["register_confirm"] = "Cher Internaute,<br />"
-          ."Merci pour votre inscription.<br />"
-          ."Pour vérifier l'adresse e-mail associée à votre compte, nous avons envoyé un courrier "
-          ."électronique à l'adresse indiquée. Pour activer votre compte, accédez à votre messagerie "
-          ."et cliquez sur le lien fourni dans le courrier de vérification.";
-        break;
-      case "lostpass":
-        $ret["barre_nav"] = "demande de mot de passe";     // Barre de nav
-        $ret["titre"] = "Mot de passe oublié";       // Titre de la boite
-        break;
-    }
 
-    return $ret;
+    if ('register' == $action)
+      return ['barre_nav' => 'S\'inscrire',
+              'titre' => 'Demande d\'inscription',
+              'register_help' => "Remplissez les champs ci-dessous\nUn mail de confirmation vous sera envoyé.\nVous devrez cliquer sur le lien pour confirmer la création de votre compte.",
+              'register_confirm' => "Cher Internaute,<br />Merci pour votre inscription.<br />Pour vérifier l'adresse e-mail associée à votre compte, nous avons envoyé un courrier électronique à l'adresse indiquée. Pour activer votre compte, accédez à votre messagerie et cliquez sur le lien fourni dans le courrier de vérification.",
+              'fields' => 'library:;card_number:', // nom_de_champs:[|optional|required]
+      ];
 
+    if ('lostpass' == $action)
+      return ['barre_nav' => 'demande de mot de passe',
+              'titre' => 'Mot de passe oublié'];
+
+    return [];
   }
 
+
   /**
    * @param type string
    * @return array
diff --git a/library/Class/Users.php b/library/Class/Users.php
index b954f9f4b962587cef4696a7c15eb634214254dd..4d89ce25f115178568617a8e465c9dabc3596aa4 100644
--- a/library/Class/Users.php
+++ b/library/Class/Users.php
@@ -994,13 +994,19 @@ class Class_Users extends Storm_Model_Abstract {
       return $ret;
     }
 
-    Class_UsersNonValid::newInstance(['login' => $login,
-                                      'password' => $mdp,
-                                      'mail' => $mail,
-                                      'cle' => $cle])->save();
+    $attribs = ['login' => $login,
+                'password' => $mdp,
+                'mail' => $mail,
+                'cle' => $cle];
 
-    $profil = Class_Profil::getCurrentProfil();
+    if (array_key_exists('id_site', $data))
+      $attribs['id_site'] = $data['id_site'];
+    if (array_key_exists('idabon', $data))
+      $attribs['idabon'] = $data['idabon'];
+
+    Class_UsersNonValid::newInstance($attribs)->save();
 
+    $profil = Class_Profil::getCurrentProfil();
 
     // Corps du mail
     $message_mail=[];
diff --git a/library/Class/UsersNonValid.php b/library/Class/UsersNonValid.php
index ba7185946f2b2da85b7f195b0aa9d6d5dec8cea3..3999c10ac669db2f3e1ffd5743da2ebe9b5c6885 100644
--- a/library/Class/UsersNonValid.php
+++ b/library/Class/UsersNonValid.php
@@ -67,12 +67,16 @@ class Class_UsersNonValid extends Storm_Model_Abstract {
 
   protected $_user;
 
+  protected $_default_attribute_values = ['id_site' => 0, 'idabon' => ''];
+
   public function activate() {
     $user = new Class_Users();
     if (!$user
         ->setLogin($this->getLogin())
         ->setMail($this->getMail())
         ->setPassword($this->getPassword())
+        ->setIdSite($this->getIdSite())
+        ->setIdabon($this->getIdabon())
         ->save())
       return false;
 
diff --git a/library/ZendAfi/Form/Configuration/AuthRegister.php b/library/ZendAfi/Form/Configuration/AuthRegister.php
new file mode 100644
index 0000000000000000000000000000000000000000..6b8c1771fbfc8d953def5c3fe06100fe7d449499
--- /dev/null
+++ b/library/ZendAfi/Form/Configuration/AuthRegister.php
@@ -0,0 +1,110 @@
+<?php
+/**
+ * Copyright (c) 2012-2014, 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 ZendAfi_Form_Configuration_AuthRegister extends ZendAfi_Form {
+
+  public static function newConfigurationWith($conf) {
+    $form = new static();
+    $form->populate($conf);
+    return $form;
+  }
+
+
+  public function init() {
+    parent::init();
+
+    $this
+      ->setAttrib('id', 'auth_register_conf')
+
+      ->addElement('select', 'boite',
+                   ['label' => $this->_('Style de boite'),
+                    'multiOptions' => (new Class_Profil_Templates(Class_Profil::getCurrentProfil()))->toArray()])
+
+      ->addElement('text', 'barre_nav', ['label' => $this->_('Texte du fil d\'ariane'),
+                                         'size' => 25,
+                                         'maxlength' => 30])
+
+      ->addDisplayGroup(['boite', 'barre_nav'], 'common', ['legend' => $this->_('Module')])
+
+      ->addElement('text', 'titre', ['label' => $this->_('Titre'),
+                                     'size' => 40])
+
+      ->addElement('textarea', 'register_help', ['label' => $this->_('Texte d\'aide'),
+                                                 'cols' => 70,
+                                                 'rows' => 5])
+
+      ->addElement('textarea', 'register_confirm', ['label' => $this->_('Texte de confirmation'),
+                                                    'cols' => 70,
+                                                    'rows' => 5])
+
+      ->addDisplayGroup(['titre', 'register_help', 'register_confirm'],
+                        'prefs',
+                        ['legend' => $this->_('Préférences')])
+
+      ->addElement('select', 'library',
+                   ['label' => $this->_('Bibliothèque d\'inscription'),
+                    'multiOptions' => $this->_optionalFieldOptions()])
+
+      ->addElement('select', 'card_number',
+                   ['label' => $this->_('N° de carte'),
+                    'multiOptions' => $this->_optionalFieldOptions()])
+
+      ->addDisplayGroup(['library', 'card_number'], 'options', ['legend' => $this->_('Champs optionnels')])
+
+      ->addElement('submit', 'submit', ['label' => $this->_('Valider'),
+                                        'class' => 'bouton'])
+
+      ->addDisplayGroup(['submit'], 'submit', ['legend' => ''])
+      ;
+  }
+
+
+  public function populate(array $datas) {
+    parent::populate($datas);
+    if (!array_key_exists('fields', $datas))
+      return $this;
+
+    foreach(explode(';', $datas['fields']) as $field) {
+      $parts = explode(':', $field);
+      if ($element = $this->getElement($parts[0]))
+        $element->setValue($parts[1]);
+    }
+
+    return $this;
+  }
+
+
+  protected function _optionalFieldOptions() {
+    return ['' => $this->_('Non affiché'),
+            'optional' => $this->_('Affiché et facultatif'),
+            'required' => $this->_('Affiché et obligatoire')];
+  }
+
+
+  public function getValues() {
+    $values = parent::getValues();
+    $values['fields'] = 'library:' . $values['library'] . ';card_number:' . $values['card_number'];
+    unset($values['library'], $values['card_number']);
+
+    return $values;
+  }
+}
\ No newline at end of file
diff --git a/library/ZendAfi/Form/Configuration/SearchResult.php b/library/ZendAfi/Form/Configuration/SearchResult.php
index 5a7839015e2193c074a403a54a1944df788b9c0d..df54207a61408ee52d1a1800d6f657c3b13d8b5b 100644
--- a/library/ZendAfi/Form/Configuration/SearchResult.php
+++ b/library/ZendAfi/Form/Configuration/SearchResult.php
@@ -240,7 +240,8 @@ class ZendAfi_Form_Configuration_SearchResult extends ZendAfi_Form {
 
       ->addElement('submit',
                    'submit',
-                   ['label' => $this->_('Valider')]);
+                   ['label' => $this->_('Valider'),
+                    'class' => 'bouton']);
   }
 
 
diff --git a/library/ZendAfi/Form/Register.php b/library/ZendAfi/Form/Register.php
new file mode 100644
index 0000000000000000000000000000000000000000..a731b7a270e0e86e75cd65594c707b5302956860
--- /dev/null
+++ b/library/ZendAfi/Form/Register.php
@@ -0,0 +1,198 @@
+<?php
+/**
+ * Copyright (c) 2012-2014, 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 ZendAfi_Form_Register extends ZendAfi_Form {
+  public function init() {
+    parent::init();
+
+    $this->_initCommons()
+         ->_initOptionals()
+         ->_initCaptcha();
+
+    $this->addElement('submit','submit', ['label' => $this->_('Valider')]);
+  }
+
+
+  protected function _initCommons() {
+    $this
+      ->addElement('text', 'login', ['label' => $this->_('Identifiant'),
+                                     'maxlength' => 20,
+                                     'required' => true,
+                                     'allowEmpty' => false,
+                                     'validators' => ['LoginExists']])
+
+      ->addElement('password', 'mdp', ['label' => $this->_('Mot de passe'),
+                                       'maxlength' => 15,
+                                       'required' => true,
+                                       'allowEmpty' => false,])
+
+      ->addElement('password', 'mdp2', ['label' => $this->_('Confirmez votre mot de passe'),
+                                        'maxlength' => 15,
+                                        'required' => true,
+                                        'allowEmpty' => false,
+                                        'validators' => [new ZendAfi_Validate_PasswordEquals('mdp')]])
+
+      ->addElement('email', 'mail', ['label' => $this->_('E-mail'),
+                                     'maxlength' => 50,
+                                     'required' => true,
+                                     'allowEmpty' => false,
+                                     'validators' => ['MailExists']])
+
+      ->addElement('email', 'mail2', ['label' => $this->_('Confirmez votre e-mail'),
+                                      'maxlength' => 50,
+                                      'required' => true,
+                                      'allowEmpty' => false,
+                                      'validators' => [new ZendAfi_Validate_MailEquals('mail')]])
+
+      ->addDisplayGroup(['login', 'mdp', 'mdp2', 'mail', 'mail2'],
+                        'fields',
+                        ['legend' => '']);
+
+    return $this;
+  }
+
+
+  protected function _initOptionals() {
+    (new ZendAfi_Form_RegisterOptionals())->addTo($this);
+    return $this;
+  }
+
+
+  protected function _initCaptcha() {
+    $this->addElement('captcha', 'captcha',
+                      ['captcha' => 'Image',
+                       'label' => $this->_('Recopiez le code'),
+                       'captchaOptions' => ['font' => PATH_FONTS.'/Vera.ttf',
+                                            'imgDir' => PATH_CAPTCHA,
+                                            'imgUrl' => URL_CAPTCHA]])
+
+         ->addDisplayGroup(['captcha'], 'security', ['legend' => $this->_('Sécurité')]);
+    return $this;
+  }
+}
+
+
+class ZendAfi_Form_RegisterOptionals {
+  protected
+    $_form,
+    $_added = [];
+
+  public function addTo($form) {
+    if (!$pref = Class_Profil::getCurrentProfil()->getModulePreference('auth', 'register', 'fields'))
+      return;
+
+    $this->_form = $form;
+
+    foreach(explode(';', $pref) as $field)
+      ZendAfi_Form_RegisterOptional::newWith($field)->addTo($this);
+
+    if ($this->_added)
+      $form->addDisplayGroup($this->_added, 'optionals', ['legend' => '']);
+  }
+
+
+  public function addElement($type, $id, $options) {
+    $this->_added[] = $id;
+    return $this->_form->addElement($type, $id, $options);
+  }
+}
+
+
+
+class ZendAfi_Form_RegisterOptional {
+  use Trait_Translator;
+
+  protected
+    $_type,
+    $_id,
+    $_visibility = '';
+
+  public static function newWith($field) {
+    if ((!$parts = explode(':', $field))
+        || 2 > count($parts)
+        || '' == $parts[1])
+      return new static();
+
+    $class_name = 'ZendAfi_Form_RegisterOptional'.ucfirst($parts[0]);
+    return new $class_name($parts[1]);
+  }
+
+
+  public function __construct($visibility='') {
+    $this->_visibility = $visibility;
+  }
+
+
+  public function addTo($parent) {
+    if ('' == $this->_visibility)
+      return;
+
+    $parent->addElement($this->_type, $this->_id, $this->_getOptions());
+  }
+
+
+  protected function _getOptions() {
+    $options = ['label' => $this->_getLabel()];
+    if ('required' == $this->_visibility) {
+      $options['required'] = true;
+      $options['allowEmpty'] = false;
+    }
+
+    return $options;
+  }
+
+
+  protected function _getLabel() {
+    return '';
+  }
+}
+
+
+
+class ZendAfi_Form_RegisterOptionalLibrary extends ZendAfi_Form_RegisterOptional {
+  protected
+    $_type = 'select',
+    $_id = 'id_site';
+
+  protected function _getLabel() {
+    return $this->_('Bibliothèque de rattachement');
+  }
+
+
+  protected function _getOptions() {
+    $options = parent::_getOptions();
+    $options['multiOptions'] = Class_Bib::findAllLabels();
+    return $options;
+  }
+}
+
+
+
+class ZendAfi_Form_RegisterOptionalCard_number extends ZendAfi_Form_RegisterOptional {
+  protected
+    $_type = 'text',
+    $_id = 'idabon';
+
+  protected function _getLabel() {
+    return $this->_('N° de carte');
+  }
+}
diff --git a/tests/application/modules/admin/controllers/ModulesControllerTest.php b/tests/application/modules/admin/controllers/ModulesControllerTest.php
index c5099f558407f5f80d5bf34a65a79345db9e6713..b3b8af39636ea50ba5b615f617a9b486935da864 100644
--- a/tests/application/modules/admin/controllers/ModulesControllerTest.php
+++ b/tests/application/modules/admin/controllers/ModulesControllerTest.php
@@ -374,30 +374,41 @@ class ModulesControllerRegisterConfigTest extends Admin_AbstractControllerTestCa
 
 
   /** @test */
-  public function modulesAuthRegisterInputBarreNavShouldContainsSInscrire() {
+  public function barreNavShouldContainsSInscrire() {
     $this->assertXPath('//input[@name="barre_nav"][@value="S\'inscrire"]');
   }
 
 
   /** @test */
-  public function modulesAuthRegisterInputTitreShouldContainsDemandeDinscription() {
+  public function titreShouldContainsDemandeDinscription() {
     $this->assertXPath('//input[@type="text"][@name="titre"][@value="Demande d\'inscription"]');
   }
 
 
   /** @test */
-  public function modulesAuthRegisterTextareaRegisterHelpShouldContainsDefautMessage() {
-
+  public function registerHelpShouldContainsDefautMessage() {
     $this->assertXPathContentContains('//textarea[@name="register_help"]',
                                       'mail de confirmation');
   }
 
 
   /** @test */
-  public function modulesAuthRegisterTextareaRegisterConfirmShouldContainsDefautMessage() {
+  public function registerConfirmShouldContainsDefautMessage() {
     $this->assertXPathContentContains('//textarea[@name="register_confirm"]',
                                       'Cher Internaute,');
   }
+
+
+  /** @test */
+  public function optionalLibraryShouldBePresent() {
+    $this->assertXPath('//select[@name="library"]');
+  }
+
+
+  /** @test */
+  public function optionalCardNumberShouldBePresent() {
+    $this->assertXPath('//select[@name="card_number"]');
+  }
 }
 
 
diff --git a/tests/application/modules/opac/controllers/AuthControllerTest.php b/tests/application/modules/opac/controllers/AuthControllerTest.php
index 647a72889def47cf6dcdc675dda447245eb2a0af..e9d27adfb46ac008cd6d7cdb3c3a2c5efb97a2f9 100644
--- a/tests/application/modules/opac/controllers/AuthControllerTest.php
+++ b/tests/application/modules/opac/controllers/AuthControllerTest.php
@@ -21,6 +21,8 @@
 require_once 'AbstractControllerTestCase.php';
 
 abstract class PortailWithOneLoginModuleTestCase extends AbstractControllerTestCase {
+  protected $_storm_default_to_volatile = true;
+
   public function setUp() {
     parent::setUp();
 
@@ -229,8 +231,6 @@ class AuthControllerNobodyLoggedActivateTest extends AuthControllerNobodyLoggedT
 
   public function setUp() {
     parent::setUp();
-    Class_UsersNonValid::beVolatile();
-    Class_Users::beVolatile();
     $this->fixture('Class_AdminVar', ['id' => 'USER_NON_VALIDATED',
                                       'valeur' => self::ERROR_MESSAGE]);
     $this->fixture('Class_AdminVar', ['id' => 'USER_VALIDATED',
@@ -1174,6 +1174,7 @@ class AuthControllerLoginActionWithDefaultPreferencesRenderTest extends AuthCont
 }
 
 class AuthControllerLostPasswordUnknownPostTest extends AbstractControllerTestCase{
+  protected $_storm_default_to_volatile = true;
 
   public function setUp() {
     parent::setUp();
@@ -1196,6 +1197,7 @@ class AuthControllerLostPasswordUnknownPostTest extends AbstractControllerTestCa
 }
 
 class AuthControllerLostPasswordNoMailPostTest extends AbstractControllerTestCase{
+  protected $_storm_default_to_volatile = true;
 
   public function setUp() {
     parent::setUp();
@@ -1255,13 +1257,13 @@ class AuthControllerNobodyLoggedAndRegistrationAllowedRegisterTest extends AuthC
 
 
   /** @test */
-  public function H1ShouldContainsDemandDInscription() {
+  public function h1ShouldContainsDemandDInscription() {
     $this->assertXPathContentContains('//h1', 'Demande d\'inscription');
   }
 
 
   /** @test */
-  public function ParagraphRegisterHelpShouldContainsMailDeConfirmation() {
+  public function paragraphRegisterHelpShouldContainsMailDeConfirmation() {
     $this->assertXPathContentContains('//p', 'mail de confirmation');
   }
 
@@ -1304,12 +1306,40 @@ class AuthControllerNobodyLoggedAndRegistrationAllowedRegisterTest extends AuthC
 
 
 
+class AuthControllerNobodyLoggedAndRegistrationAllowedWithOptionalFieldsRegisterTest
+  extends AuthControllerNobodyLoggedTestCase {
+
+  public function setUp() {
+    parent::setUp();
+    Class_AdminVar::newInstanceWithId('INTERDIRE_ENREG_UTIL', ['valeur' => 0]);
+
+    Class_Profil::getCurrentProfil()
+      ->setCfgModulesPreferences(['fields' => 'library:optional;card_number:required'],
+                                 'auth', 'register');
+
+    $this->dispatch('auth/register', true);
+  }
+
+
+  /** @test */
+  public function libraryShouldBeHereAndOptional() {
+    $this->assertXPath('//select[@name="id_site"]');
+    $this->assertXPath('//label[@for="id_site"][not(contains(@class, "required"))]');
+  }
+
+
+  /** @test */
+  public function cardNumberShouldBeHereAndRequired() {
+    $this->assertXPath('//input[@type="text"][@name="idabon"]');
+    $this->assertXPath('//label[@for="idabon"][contains(@class, "required")]');
+  }
+}
+
+
 
 class AuthControllerNobodyLoggedRegisterPostRightDatasTest extends AuthControllerNobodyLoggedTestCase {
   public function setUp() {
     parent::setUp();
-    Class_Users::beVolatile();
-    Class_UsersNonValid::beVolatile();
     ZendAfi_Form_Element_Captcha::beValid();
 
     $this->mock_transport = new MockMailTransport();
@@ -1396,7 +1426,9 @@ class AuthControllerNobodyLoggedRegisterPostRightDatasTest extends AuthControlle
                          'login' => 'mario',
                          'password' => 'secret',
                          'mail' => 'mario@afi-sa.fr',
-                         'cle' => md5('mario@afi-sa.fr')],
+                         'cle' => md5('mario@afi-sa.fr'),
+                         'id_site' => 0,
+                         'idabon' => ''],
                         $user->getRawAttributes());
   }
 }
@@ -1524,11 +1556,11 @@ class AuthControllerNobodyLoggedRegisterPostWrongDataTest extends AuthController
 
 
 class PortailWithOneLoginModuleTestAndLoggedUserCase extends AbstractControllerTestCase {
+  protected $_storm_default_to_volatile = true;
+
   public function setUp() {
     parent::setUp();
 
-    Class_IntBib::beVolatile();
-
     $cfg_accueil = ['modules' => [4 => ['division' => '4',
                                         'id_module' => 4,
                                         'type_module' => 'LOGIN',
@@ -1637,7 +1669,6 @@ class AuthControllerNobodyLoggedAndRegisterNewsletterWithWrongNewsletterTest ext
 
   public function setUp() {
     parent::setUp();
-    Class_Newsletter::beVolatile();
     $this->dispatch('/opac/auth/newsletter-register/id/1', true);
   }
 
@@ -1730,9 +1761,6 @@ class AuthControllerPostRegisterNewsletterDailyNewsTest extends AuthControllerNo
     Class_Profil::getCurrentProfil()
       ->setMailSite('tom@afi.fr');
 
-    Class_Users::beVolatile();
-    Class_UsersNonValid::beVolatile();
-
     $this->fixture('Class_Newsletter', ['id' => 5, 'titre' => 'Daily News']);
 
     $this->postDispatch('/opac/auth/newsletter-register/id/5', ['email' => 'iwanttobespamed@abo.com',
@@ -1834,8 +1862,6 @@ class AuthControllerPostRegisterNewsletterDailyNewsWithNonUniqueMailTest extends
                     'password' => 'pwd',
                     'mail' => 'imalreadyused@mail.com']);
 
-    Class_UsersNonValid::beVolatile();
-
     $this->fixture('Class_Newsletter',
                    ['id' => 5,
                     'titre' => 'Daily News']);
@@ -1866,8 +1892,6 @@ class AuthControllerPostRegisterNewsletterDailyNewsWithBadMailTest extends AuthC
   public function setUp() {
     parent::setUp();
 
-    Class_Users::beVolatile();
-    Class_UsersNonValid::beVolatile();
     $this->fixture('Class_Newsletter', ['id' => 5, 'titre' => 'Daily News']);
 
     $this->postDispatch('/opac/auth/newsletter-register/id/5', ['email' => 'bad_mail!',
@@ -1912,7 +1936,6 @@ class AuthControllerNewsletterActiveUserWithWrongParamsTest extends AuthControll
 
   /** @test */
   public function wrongNewsletterShouldRedirectedToIndex() {
-    Class_Newsletter::beVolatile();
     $this->dispatch('opac/auth/newsletter-active-user/c/4897sd8fsdf/id/1', true);
     $this->assertRedirectTo('/');
   }
@@ -1935,10 +1958,6 @@ class AuthControllerNewsletterActiveUserTest extends AuthControllerNoBodyLoggedT
   public function setUp() {
     parent::setUp();
 
-    Class_NewsletterSubscription::beVolatile();
-
-    Class_Users::beVolatile();
-
     $this->fixture('Class_Newsletter',[
                                        'id' => 1,
                                        'titre' => 'News of the month']);
@@ -1988,9 +2007,11 @@ class AuthControllerNewsletterActiveUserTest extends AuthControllerNoBodyLoggedT
 
 
 class AuthControllerTomLoggedRegisterNewsletterTestCase extends AbstractControllerTestCase {
+  protected $_storm_default_to_volatile = true;
+
   public function setUp() {
     parent::setUp();
-    Class_NewsletterSubscription::beVolatile();
+
     $this->fixture('Class_Newsletter',
                    ['id' => 5,
                     'titre' => 'Daily News']);
@@ -2057,7 +2078,6 @@ class AuthControllerNewsletterUnsubscribeWrongIdTest extends AuthControllerNobod
 
   public function setUp() {
     parent::setUp();
-    Class_Newsletter::beVolatile();
     $this->dispatch('auth/newsletter-unsubscribe/id/1', true);
   }
 
@@ -2078,6 +2098,7 @@ class AuthControllerNewsletterUnsubscribeWrongIdTest extends AuthControllerNobod
 
 
 class AuthControllerNewsletterUnsubscribeTest extends AbstractControllerTestCase {
+  protected $_storm_default_to_volatile = true;
 
   public function setUp() {
     parent::setUp();
@@ -2120,6 +2141,8 @@ class AuthControllerNewsletterUnsubscribeTest extends AbstractControllerTestCase
 
 
 class AuthControllerNewsletterRegisterSendMailWrongMailConfigurationTest extends AbstractControllerTestCase {
+  protected $_storm_default_to_volatile = true;
+
   public function setUp() {
     parent::setUp();
 
@@ -2133,9 +2156,6 @@ class AuthControllerNewsletterRegisterSendMailWrongMailConfigurationTest extends
     Class_Profil::getCurrentProfil()
       ->setMailSite('tom@afi.fr');
 
-    Class_Users::beVolatile();
-    Class_UsersNonValid::beVolatile();
-
     $this->fixture('Class_Newsletter', ['id' => 5, 'titre' => 'Daily News']);
 
     $this->postDispatch('/opac/auth/newsletter-register/id/5', ['email' => 'iwanttobespamed@abo.it',
@@ -2152,10 +2172,11 @@ class AuthControllerNewsletterRegisterSendMailWrongMailConfigurationTest extends
 
 
 class AuthControllerNewsletterRegisterWithAutoSubscribeNewsletterTest extends AbstractControllerTestCase {
+  protected $_storm_default_to_volatile = true;
+
   public function setUp() {
     parent::setUp();
-    Class_NewsletterSubscription::beVolatile();
-    Class_Users::beVolatile();
+
     $this->fixture('Class_UsersNonValid', [
                                            'id' => 1,
                                            'login' => 'future@i.am',
@@ -2194,5 +2215,4 @@ class AuthControllerNewsletterRegisterWithAutoSubscribeNewsletterTest extends Ab
   public function messageShouldBeAsExpected() {
     $this->assertXPathContentContains('//p', "Vous avez bien été abonné à la newsletter");
   }
-}
-?>
\ No newline at end of file
+}
\ No newline at end of file
diff --git a/tests/db/UpgradeDBTest.php b/tests/db/UpgradeDBTest.php
index 8dc1249b69353290bd6fd8d8c0427847bd68d157..ee5358183e16f6d9d170bb570d583ad7537e18ab 100644
--- a/tests/db/UpgradeDBTest.php
+++ b/tests/db/UpgradeDBTest.php
@@ -445,6 +445,25 @@ class UpgradeDB_286_Test extends UpgradeDBTestCase {
 }
 
 
+class UpgradeDB_287_Test extends UpgradeDBTestCase {
+  public function prepare() {
+    try {
+      $this->query('ALTER TABLE bib_admin_users_non_valid DROP id_site, DROP idabon');
+    } catch(Exception $e) {}
+  }
+
+  public function idSiteShouldExists() {
+    $this->assertColumn('bib_admin_users_non_valid', 'id_site');
+  }
+
+
+  /** @test */
+  public function idabonShouldExists() {
+    $this->assertColumn('bib_admin_users_non_valid', 'idabon');
+  }
+}
+
+
 
 class UpgradeDB_288_Test extends UpgradeDBTestCase {
   public function prepare() {
diff --git a/tests/library/Class/LocalisationTest.php b/tests/library/Class/LocalisationTest.php
index 261a037d12322a44e90be943fa87458183065585..ef9eabc9c23d3672d8d6cc66763464da9b81cbb6 100644
--- a/tests/library/Class/LocalisationTest.php
+++ b/tests/library/Class/LocalisationTest.php
@@ -87,6 +87,17 @@ class LocalisationTest extends Storm_Test_ModelTestCase {
                     'libelle' => 'CD Jazz',
                     'cote_debut' => 'CDJazz A',
                     'cote_fin' => 'CDJazz Z']);
+
+    $this->fixture('Class_Localisation',
+                   ['id' => 22,
+                    'id_bib' => 1,
+                    'annexe' => 1,
+                    'section' => 'J',
+                    'genre' => 'B',
+                    'libelle' => 'CD Jazz Broken',
+                    'cote_debut' => 'CDJazz A',
+                    'cote_fin' => 'CDJazz Z',
+                    'type_doc' => 2]);
   }