diff --git a/VERSIONS_WIP/58112 b/VERSIONS_WIP/58112
new file mode 100644
index 0000000000000000000000000000000000000000..29526cff2dfcdd290c910e0e58d1bc903c9ba93b
--- /dev/null
+++ b/VERSIONS_WIP/58112
@@ -0,0 +1 @@
+ - ticket #58112 : ajout de la variable FORCE_HTTPS pour forcer le navigateur à rediriger sur la version HTTPS du portail
\ No newline at end of file
diff --git a/library/Class/AdminVar.php b/library/Class/AdminVar.php
index 10b2a52bb58c1ef16445c4750aca7d8e40e679b0..11ba04017f30f1ffcc0e22c8828da58ab2169f0a 100644
--- a/library/Class/AdminVar.php
+++ b/library/Class/AdminVar.php
@@ -97,133 +97,20 @@ class Class_AdminVarLoader extends Storm_Model_Loader {
 
     return $this->all_vars=
       [
-       'avis' => [
-                  'AVIS_MAX_SAISIE' => Class_AdminVar_Meta::newDefault($this->_('Nombre de caractères maximum autorisé à saisir dans les avis.')),
-                  'AVIS_MIN_SAISIE' => Class_AdminVar_Meta::newDefault($this->_('Nombre de caractères minimum autorisé à saisir dans les avis.')),
-                  'BLOG_MAX_NB_CARAC' => Class_AdminVar_Meta::newDefault($this->_('Nombre de caractères maximum à afficher dans le bloc critiques.'))],
-       'modo' => [                     'MODO_AVIS' => Class_AdminVar_Meta::newOnOff($this->_('Modération des avis des lecteurs.<br /> Désactivé : affichage sans attente de validation<br /> Activé : affichage seulement après validation.')),
-                  'MODO_AVIS_BIBLIO' => Class_AdminVar_Meta::newOnOff($this->_('Modération des avis des bibliothécaires.<br />  Désactivé: affichage sans attente de validation<br /> Activé: affichage seulement après validation')),
-                  'AVIS_BIB_SEULEMENT' => Class_AdminVar_Meta::newOnOff($this->_('Désactivé: les lecteurs peuvent donner leur avis. <br /> Activé: seuls les bibliothécaires peuvent donner leur avis')),
-                  'MODO_BLOG' => Class_AdminVar_Meta::newOnOff($this->_('Désactivé: ne requiert pas d\'identification pour saisir des  commentaires. <br /> Activé: requiert l\'identification pour saisir des commentaires.')),
-                  'MAX_DAY_INVALID_MEMBRE' => Class_AdminVar_Meta::newDefault($this->_('Nombre de jours de validité des nouvelles inscriptions sur le site')),
-       ],
-
-       'stat' => [  'JS_STAT' => Class_AdminVar_Meta::newRawText($this->_('Javascript code for statistics')),
-                  'PIWIK_AUTH_TOKEN' => Class_AdminVar_Meta::newDefault($this->_('PIWIK authentication token for widgets'))],
-
-       'global' => [
-                    'NB_AFFICH_AVIS_PAR_AUTEUR'  => Class_AdminVar_Meta::newDefault($this->_('Nombre d\'avis maximum à afficher par utilisateur.')),
-                    'CLEF_GOOGLE_MAP' => Class_AdminVar_Meta::newDefault($this->_('Clef d\'activation pour le plan d\'accès google map. <a target="_blank" href="http://code.google.com/apis/maps/signup.html">Obtenir la clé google map</a>')),
-                    'REGISTER_OK' => Class_AdminVar_Meta::newEncodedData($this->_('Texte visible par l\'internaute après son inscription.')),
-                    'RESA_CONDITION' => Class_AdminVar_Meta::newEncodedData($this->_('Texte visible après l\'envoi d\'e-mail de demande de réservation.')),
-                    'SITE_OK' => Class_AdminVar_Meta::newOnOff($this->_('Désactiver pour passer le site en maintenance')),
-                    'ID_BIBLIOSURF' => Class_AdminVar_Meta::newDefault($this->_('Nom de la bibliothèque chez bibliosurf (en minuscules)'))->bePrivate(),
-                    'ID_READ_SPEAKER' => Class_AdminVar_Meta::newDefault($this->_('Numéro de client Read Speaker <a target="_blank" href="http://webreader.readspeaker.com">http://webreader.readspeaker.com</a>')),
-                    'BLUGA_API_KEY' => Class_AdminVar_Meta::newDefault($this->_('Clé API Bluga Webthumb <a target="_blank" href="http://webthumb.bluga.net/home">http://webthumb.bluga.net/home</a>')),
-                    'AIDE_FICHE_ABONNE' => Class_AdminVar_Meta::newDefault($this->_('Texte d\'aide affiché dans la fiche abonné')),
-                    'INTERDIRE_ENREG_UTIL' => Class_AdminVar_Meta::newOnOff($this->_('Supprime l\'affichage du lien d\'enregistrement dans les différents formulaires de connexion et interdit l\'enregistrement d\'utilisateurs')),
-                    'LANGUES' => Class_AdminVar_Meta::newMultiInput($this->_('Liste des codes langue utilisées en plus du français séparées par des ;. Exemple: en;ro;es')),
-                    'CACHE_ACTIF' => Class_AdminVar_Meta::newOnOff(implode('<br/>',
-                                                                           ['Activer le cache des boîtes (meilleure performance mais mise à jour toutes les ' . CACHE_LIFETIME / 60 . 'mn)',
-                                                                            '<a href="' . Class_Url::baseUrl() . '/admin/index/clearcache" >Vider le cache</a>']))->bePrivate(),
-                    'CACHE_DATE' => Class_AdminVar_Meta::newDefault($this->_('Date du dernier vidage manuel du cache'))->bePrivate(),
-
-                    'FORMATIONS' => Class_AdminVar_Meta::newOnOff($this->_('Activer ou désactiver le module formation'))->bePrivate(),
-
-                    'BABELTHEQUE_JS' => Class_AdminVar_Meta::newDefault($this->_('URL du javascript Babelthèque à insérer dans l\'OPAC'))->bePrivate(),
-                    'MULTIMEDIA_KEY' => Class_AdminVar_Meta::newDefault($this->_('Clé publique pour le cryptage des données AFI-Multimédia')),
-
-                    'WEBKIOSK_KEY' => Class_AdminVar_Meta::newDefault($this->_('Clé publique pour le cryptage des données Aesis Webkiosk'))->bePrivate(),
-                    'WEBKIOSK_RESERVATION_URL' => Class_AdminVar_Meta::newDefault($this->_('URL d\'accès à l\'interface de réservation des postes Aesis Webkiosk'))->bePrivate(),
-
-                    'MENU_BOITE' => Class_AdminVar_Meta::newOnOff($this->_('Activation des boîtes dans les menus')),
-                    'INTERDIRE_MODIF_FICHE_ABONNE' => Class_AdminVar_Meta::newOnOff($this->_('Interdire la modification de la fiche abonne')),
-                    'ROOT_URL_ECOUTE' => Class_AdminVar_Meta::newDefault('URL de base à rajouter aux données unimarc pour la lecture des morceaux'),
-                    'URL_TYPO3' => Class_AdminVar_Meta::newDefault($this->_('Url d\'import d\'un agenda TYPO3'))->bePrivate(),
-                    'CHAMPS_FICHE_UTILISATEUR' => Class_AdminVar_Meta::newMultiInput($this->_('Liste des champs que l\'utilisateur peux modifier. <br/>Ex: nom;prenom;pseudo;adresse;<br/>code_postal;ville;mail;is_contact_mail;<br/>telephone;is_contact_telephone;')),
-                    'FACETTE_PCDM4_LIBELLE' => Class_AdminVar_Meta::newDefault($this->_('Libellé pour la PCDM4')),
-                    'FACETTE_DEWEY_LIBELLE' => Class_AdminVar_Meta::newDefault($this->_('Libellé pour la Dewey')),
-                    'FACETTE_TYPE_DOC_LIBELLE' => Class_AdminVar_Meta::newDefault('Libellé de la facette type de document'),
-                    'FACETTE_LANGUE_LIBELLE' => Class_AdminVar_Meta::newDefault('Libellé de la facette langue'),
-                    'FACETTE_GENRE_LIBELLE' => Class_AdminVar_Meta::newDefault('Libelle de la facette genre'),
-                    'FACETTE_SITE_LIBELLE' => Class_AdminVar_Meta::newDefault('Libellé de la facette site'),
-                    'FACETTE_SECTION_LIBELLE' => Class_AdminVar_Meta::newDefault('Libellé de la facette section'),
-                    'FACETTE_BIBLIOTHEQUE_LIBELLE' => Class_AdminVar_Meta::newDefault('Libellé de la facette bibliothèque'),
-                    'FACETTE_AUTEUR_LIBELLE' => Class_AdminVar_Meta::newDefault('Libellé de la facette auteur'),
-                    'FACETTE_INTERET_LIBELLE' => Class_AdminVar_Meta::newDefault('Libellé de la facette centres d\'intérêt'),
-                    'FACETTE_MATIERE_LIBELLE' => Class_AdminVar_Meta::newDefault('Libellé de la facette matière'),
-                    'FACETTE_TAG_LIBELLE' => Class_AdminVar_Meta::newDefault('Libellé de la facette tag'),
-                    'UNLEASHED_FACETS' => Class_AdminVar_Meta::newMultiInput($this->_('Liste des codes des facettes qui ne sont pas limitées à l\'affichage dans le résultat de recherche<br/>Exemple : T => Type de doc, Y => Annexe, B => Bibliothèque, ... (Voir <a href="' . BOKEH_REMOTE_FILES . 'blob/' . BOKEH_VERSION . '/library/Class/Codification.php#L24">la liste complète</a>)')),
-                    'BOITE_PANIER_AUTO' => Class_AdminVar_Meta::newOnOff($this->_('Ajouter automatiquement une boîte panier dans la division flottante')),
-                    'EXTRA_SKIN_PATH' => Class_AdminVar_Meta::newDefault($this->_('Chemin vers les skins personnalisées, relatif à %s', Class_Profil_Skin::EXTRA_PATH)),
-                    'ENABLE_COLLABORATIVE_BROWSING' => Class_AdminVar_Meta::newOnOff($this->_('Activation de la navigation collaborative')),
-                    'KOHA_MULTI_SITES' => Class_AdminVar_Meta::newOnOff($this->_('WS KOHA : Reservation d\'exemplaires pour les multi sites')),
-
-                    'TEXT_REPLACEMENTS' => Class_AdminVar_Meta::newRawText($this->_('Remplacement de textes à la volée. <br/>Ex:<br/>Panier;Sélection<br/>Vous avez %%d paniers;Vous avez %%d sélections')),
-                    'URL_COSMOGRAMME' => Class_AdminVar_Meta::newDefault('')->bePrivate(),
-                    'PACK_MOBILE' => Class_AdminVar_Meta::newOnOff($this->_('Activation des fonctions avancées du téléphone'))->bePrivate(),
-                    'CNIL_CONSENT_ENABLE' => Class_AdminVar_Meta::newOnOff('Affiche la demande de consentement avant l\'insertion de cookies ou autres traceurs'),
-                    'BUID' => Class_AdminVar_Meta::newRawText($this->_('Identifiant unique (attention: la modification de cette variable impactera les outils de suivi de cette installation)'))->bePrivate(),
-                    'STATUS_REPORT_PUSH_URL' => Class_AdminVar_Meta::newRawText($this->_('URL destinataire du rapport d\'état du système (0 pour désactiver)'), ['value' => 'http://pola.afi-sa.net/smile.php'])->bePrivate(),
-                    'STATUS_REPORT_TAGS' => Class_AdminVar_Meta::newMultiInput($this->_('Liste des tags à ajouter au rapport d\'état du système'))->bePrivate()],
-
-       'cosmogramme' => [
-                         'DATE_LAST_FULL_INTEGRATION_USERS' => Class_AdminVar_Meta::newDefault($this->_('Date du dernier import total des abonnés (modifié par cosmogramme)')),
-                         'INTEGRATIONS_TOO_LONG_ALERT_THRESHOLD' => Class_AdminVar_Meta::newDefault($this->_('Seuil d\'alerte en heures pour détecter que les traitements d\'intégration prennent trop de temps. Par défaut: 2', ['value' => 2]))
-       ],
-
-       'catalogue' => [
-                       'OAI_SERVER' => Class_AdminVar_Meta::newOnOff($this->_('Activation du serveur OAI: permet le moissonnage des domaines par d\'autres logiciels via OAI'))],
-       'newsletter' => [
-                        'NEWSLETTER_ID_PROFIL' => Class_AdminVar_Meta::newCombo($this->_('Profil de la page de désinscription<br/>Par défaut : page d\'accueil du portail'),
-                                                                                ['options' => ['selectOptions' => $this->_getProfilsOptions()],
-                                                                                 'renderer' => $this->_getProfilRenderer()]),
-                        'NEWSLETTER_UNSUBSCRIBE_TEXT' => Class_AdminVar_Meta::newDefault($this->_('Texte de désinscription version texte<br/>Le lien est inséré à la place de {{URL}}<br/>Par défaut : Lien pour se désinscrire de cette lettre d\'information : {{URL}}'),
-                                                                                         ['value' => $this->_('Lien pour se désinscrire de cette lettre d\'information : {{URL}}')]),
-                        'NEWSLETTER_UNSUBSCRIBE_HTML' => Class_AdminVar_Meta::newDefault($this->_('Texte de désinscription version HTML<br/>Le lien de désinscription est appliqué sur tout ce texte<br/>Par défaut : Je ne veux plus recevoir cette lettre d\'information'),
-                                                                                         ['value' => $this->_('Je ne veux plus recevoir cette lettre d\'information')])
-       ],
-       'cms' => ['ARTICLES_LIST_MODE' => Class_AdminVar_Meta::newOnOff($this->_('Le gestionnaire de contenu affiche les articles sous forme de liste paginée au lieu de d\'une arborescence. Cet affichage est adapté lorsque le nombre d\'article devient trop important')),
-                 'LIMIT_MULTIPLE_SELECTION' => Class_AdminVar_Meta::newDefault($this->_('Nombre maximum d\'articles  en sélection multiple'), ['value' => 200]),
-
-                 'CMS_FORMULAIRES' => Class_AdminVar_Meta::newOnOff($this->_('Activation des formulaires')),
-
-                 'WORKFLOW' => Class_AdminVar_Meta::newDefault(implode('<br/>',
-                                                                       ['Activer ou désactiver la gestion des validations des articles',
-                                                                        'Vide ou 0 = Désactivé, 1 = Activé avec les statuts par défaut, JSON = Activé avec des statuts de validation supplémentaire',
-                                                                        'Exemple JSON :',
-                                                                        '[{"id":10, "label":"À valider niveau 2"}, {"id":11, "label":"À valider niveau 3"}]',
-                                                                        'Les identifiants 1 à 5 sont réservés']),
-                                                               ['validate' => 'ZendAfi_Validate_WorkflowVar',
-                                                                'after_save' => 'setWorkflowPermissions']),
-                 'WORKFLOW_TEXT_MAIL_ARTICLE_PENDING' => Class_AdminVar_Meta::newDefault($this->_('Contenu de l\'email de notification d\'article en attente de validation. Termes substitués: TITRE_ARTICLE, URL_ARTICLE, AUTHOR_ARTICLE, SAVED_BY_ARTICLE, STATUS_ARTICLE, NEXT_STATUS_ARTICLE')),
-                 'WORKFLOW_TEXT_MAIL_ARTICLE_REFUSED' => Class_AdminVar_Meta::newDefault($this->_('Contenu de l\'email de notification de refus d\'un article à valider. Termes substitués: TITRE_ARTICLE, URL_ARTICLE, AUTHOR_ARTICLE, SAVED_BY_ARTICLE')),
-                 'WORKFLOW_TEXT_MAIL_ARTICLE_VALIDATED' => Class_AdminVar_Meta::newDefault($this->_('Contenu de l\'email de notification de validation d\'un article. Termes substitués: TITRE_ARTICLE, URL_ARTICLE, AUTHOR_ARTICLE, SAVED_BY_ARTICLE')),
-
-       ],
+       'avis' => $this->_getCommentVars(),
+       'modo' => $this->_getModerationVars(),
+       'stat' => $this->_getStatVars(),
+       'global' => $this->_getGlobalVars(),
+       'cosmogramme' => $this->_getCosmogrammeVars(),
+       'catalogue' => $this->_getOAIVars(),
+       'newsletter' => $this->_getNewsletterVars(),
+       'cms' => $this->_getCmsVars(),
        'album' => $this->_getAlbumVars(),
-       'users' => ['NDAYS_EXPIRY_NOTICE' => Class_AdminVar_Meta::newDefault($this->_('Prévenir l\'utilisateur xx jour(s) avant l\'expiration de son abonnement (par défaut 30 jours).'), ['value' => 30]),
-                   'DISABLE_SUGGESTIONS' => Class_AdminVar_Meta::newOnOff($this->_('Désactivation des suggestions d\'achats'))->bePrivate(),
-                   'ENABLE_BOOKMARKABLE_LIBRARIES' => Class_AdminVar_Meta::newOnOff($this->_('Les utilisateurs peuvent sélectionner des bibliothèques favorites pour leurs recherche'), ['value' => 1])],
-       'redmine' => ['REDMINE_SERVER_URL' => Class_Adminvar_Meta::newDefault($this->_('Url du serveur redmine'))->bePrivate(),
-                     'REDMINE_PROXY_URL' => Class_Adminvar_Meta::newDefault($this->_('Url du proxy Redmine'))->bePrivate(),
-                     'REDMINE_PROJECT_ID' => Class_Adminvar_Meta::newDefault($this->_('Identifiant du project Redmine'))->bePrivate()],
-       'lesocial' => ['LESOCIAL_URL' => Class_Adminvar_Meta::newDefault($this->_('Url du connecteur Le Social'))->bePrivate(),
-                      'LESOCIAL_ID' => Class_Adminvar_Meta::newDefault($this->_('Id du connecteur Le Social'))->bePrivate()],
-       'static_map' => ['STATIC_MAP' => Class_AdminVar_Meta::newCombo($this->_('API utilisée pour les cartes statiques'),
-                                                                      ['options' => ['selectOptions' => ['label' => $this->_('API'),
-                                                                                                         'value' => Class_Map::GOOGLE_API,
-                                                                                                         'multioptions' => (new Class_Map())->getAPIs()]]])->bePrivate()],
-       'search' => ['SEARCH_PAGINATE_POSITION' => Class_AdminVar_Meta::newCombo($this->_('Position de la pagination en résultat de recherche'),
-                                                                                ['options' => ['selectOptions' => ['label' => $this->_('Position'),
-                                                                                                                   'multioptions' => ['BOTTOM' => 'en bas', 'TOP' => 'en haut', 'BOTH' => 'en haut et en bas']]]]),
-                    'EXTENDED_SEARCH' => Class_AdminVar_Meta::newOnOff($this->_('Etendre automatiquement le résultat de recherche en rajoutant des "OU" entre les mots saisis'), ['value' => 1]),
-                    'AFFICHER_DISPONIBILITE_SUR_RECHERCHE' => Class_AdminVar_Meta::newOnOff($this->_('Activation de la disponibilite dans le resultat de recherche au survol de la couverture du document, calculé en temps réel.')),
-                    'AFFICHER_DISPONIBILITE_SUR_RECHERCHE_MODE_FACETTE' => Class_AdminVar_Meta::newOnOff($this->_('Activation de la disponibilite dans le resultat de recherche. Calculé grâce à la facette "En rayon".')),
-                    'SEARCH_ALSO_IN' => Class_AdminVar_Meta::newMultiInput($this->_('Liste des sites de recherche élargie (la chaine \'%s\' dans l\'url sera remplacée par le terme de recherche)'),
-                                                                           [ 'options' => ['fields' => [['name' => 'site_label', 'label' => $this->_('Nom du site')],
-                                                                                                        ['name' => 'site_url', 'label' => $this->_('Url de recherche')] ]]]),
-                    'NOM_DOMAINE' => Class_AdminVar_Meta::newDefault($this->_('Nom de domaine principal de l\'OPAC, ex: monopac.macommune.fr')),]
+       'users' => $this->_getUsersVars(),
+       'redmine' => $this->_getRedmineVars(),
+       'lesocial' => $this->_getLeSocialVars(),
+       'static_map' => $this->_getStaticMapVars(),
+       'search' => $this->_getSearchVars()
        ];
   }
 
@@ -332,6 +219,183 @@ class Class_AdminVarLoader extends Storm_Model_Loader {
   }
 
 
+
+  protected function _getUsersVars() {
+    return ['NDAYS_EXPIRY_NOTICE' => Class_AdminVar_Meta::newDefault($this->_('Prévenir l\'utilisateur xx jour(s) avant l\'expiration de son abonnement (par défaut 30 jours).'), ['value' => 30]),
+            'DISABLE_SUGGESTIONS' => Class_AdminVar_Meta::newOnOff($this->_('Désactivation des suggestions d\'achats'))->bePrivate(),
+            'ENABLE_BOOKMARKABLE_LIBRARIES' => Class_AdminVar_Meta::newOnOff($this->_('Les utilisateurs peuvent sélectionner des bibliothèques favorites pour leurs recherche'), ['value' => 1])];
+  }
+
+
+  protected function _getRedmineVars() {
+    return ['REDMINE_SERVER_URL' => Class_Adminvar_Meta::newDefault($this->_('Url du serveur redmine'))->bePrivate(),
+            'REDMINE_PROXY_URL' => Class_Adminvar_Meta::newDefault($this->_('Url du proxy Redmine'))->bePrivate(),
+            'REDMINE_PROJECT_ID' => Class_Adminvar_Meta::newDefault($this->_('Identifiant du project Redmine'))->bePrivate()];
+  }
+
+
+  protected function _getSearchVars() {
+    return ['SEARCH_PAGINATE_POSITION' => Class_AdminVar_Meta::newCombo($this->_('Position de la pagination en résultat de recherche'),
+                                                                        ['options' => ['selectOptions' => ['label' => $this->_('Position'),
+                                                                                                           'multioptions' => ['BOTTOM' => 'en bas', 'TOP' => 'en haut', 'BOTH' => 'en haut et en bas']]]]),
+            'EXTENDED_SEARCH' => Class_AdminVar_Meta::newOnOff($this->_('Etendre automatiquement le résultat de recherche en rajoutant des "OU" entre les mots saisis'), ['value' => 1]),
+            'AFFICHER_DISPONIBILITE_SUR_RECHERCHE' => Class_AdminVar_Meta::newOnOff($this->_('Activation de la disponibilite dans le resultat de recherche au survol de la couverture du document, calculé en temps réel.')),
+            'AFFICHER_DISPONIBILITE_SUR_RECHERCHE_MODE_FACETTE' => Class_AdminVar_Meta::newOnOff($this->_('Activation de la disponibilite dans le resultat de recherche. Calculé grâce à la facette "En rayon".')),
+            'SEARCH_ALSO_IN' => Class_AdminVar_Meta::newMultiInput($this->_('Liste des sites de recherche élargie (la chaine \'%s\' dans l\'url sera remplacée par le terme de recherche)'),
+                                                                   [ 'options' => ['fields' => [['name' => 'site_label', 'label' => $this->_('Nom du site')],
+                                                                                                ['name' => 'site_url', 'label' => $this->_('Url de recherche')] ]]]),
+            'NOM_DOMAINE' => Class_AdminVar_Meta::newDefault($this->_('Nom de domaine principal de l\'OPAC, ex: monopac.macommune.fr')),];
+  }
+
+
+  protected function _getCmsVars() {
+    return ['ARTICLES_LIST_MODE' => Class_AdminVar_Meta::newOnOff($this->_('Le gestionnaire de contenu affiche les articles sous forme de liste paginée au lieu de d\'une arborescence. Cet affichage est adapté lorsque le nombre d\'article devient trop important')),
+            'LIMIT_MULTIPLE_SELECTION' => Class_AdminVar_Meta::newDefault($this->_('Nombre maximum d\'articles  en sélection multiple'), ['value' => 200]),
+
+            'CMS_FORMULAIRES' => Class_AdminVar_Meta::newOnOff($this->_('Activation des formulaires')),
+
+            'WORKFLOW' => Class_AdminVar_Meta::newDefault(implode('<br/>',
+                                                                  ['Activer ou désactiver la gestion des validations des articles',
+                                                                   'Vide ou 0 = Désactivé, 1 = Activé avec les statuts par défaut, JSON = Activé avec des statuts de validation supplémentaire',
+                                                                   'Exemple JSON :',
+                                                                   '[{"id":10, "label":"À valider niveau 2"}, {"id":11, "label":"À valider niveau 3"}]',
+                                                                   'Les identifiants 1 à 5 sont réservés']),
+                                                          ['validate' => 'ZendAfi_Validate_WorkflowVar',
+                                                           'after_save' => 'setWorkflowPermissions']),
+            'WORKFLOW_TEXT_MAIL_ARTICLE_PENDING' => Class_AdminVar_Meta::newDefault($this->_('Contenu de l\'email de notification d\'article en attente de validation. Termes substitués: TITRE_ARTICLE, URL_ARTICLE, AUTHOR_ARTICLE, SAVED_BY_ARTICLE, STATUS_ARTICLE, NEXT_STATUS_ARTICLE')),
+            'WORKFLOW_TEXT_MAIL_ARTICLE_REFUSED' => Class_AdminVar_Meta::newDefault($this->_('Contenu de l\'email de notification de refus d\'un article à valider. Termes substitués: TITRE_ARTICLE, URL_ARTICLE, AUTHOR_ARTICLE, SAVED_BY_ARTICLE')),
+            'WORKFLOW_TEXT_MAIL_ARTICLE_VALIDATED' => Class_AdminVar_Meta::newDefault($this->_('Contenu de l\'email de notification de validation d\'un article. Termes substitués: TITRE_ARTICLE, URL_ARTICLE, AUTHOR_ARTICLE, SAVED_BY_ARTICLE')),
+
+    ];
+  }
+
+
+  protected function _getNewsletterVars() {
+    return [
+            'NEWSLETTER_ID_PROFIL' => Class_AdminVar_Meta::newCombo($this->_('Profil de la page de désinscription<br/>Par défaut : page d\'accueil du portail'),
+                                                                    ['options' => ['selectOptions' => $this->_getProfilsOptions()],
+                                                                     'renderer' => $this->_getProfilRenderer()]),
+            'NEWSLETTER_UNSUBSCRIBE_TEXT' => Class_AdminVar_Meta::newDefault($this->_('Texte de désinscription version texte<br/>Le lien est inséré à la place de {{URL}}<br/>Par défaut : Lien pour se désinscrire de cette lettre d\'information : {{URL}}'),
+                                                                             ['value' => $this->_('Lien pour se désinscrire de cette lettre d\'information : {{URL}}')]),
+            'NEWSLETTER_UNSUBSCRIBE_HTML' => Class_AdminVar_Meta::newDefault($this->_('Texte de désinscription version HTML<br/>Le lien de désinscription est appliqué sur tout ce texte<br/>Par défaut : Je ne veux plus recevoir cette lettre d\'information'),
+                                                                             ['value' => $this->_('Je ne veux plus recevoir cette lettre d\'information')])
+    ];
+  }
+
+
+  protected function _getGlobalVars() {
+    return [
+            'FORCE_HTTPS' => Class_AdminVar_Meta::newDefault($this->_('Forcer l\'accès au site par le protocole HTTPS. Nécessite l\'installation et la configuration appropriée du serveur Web'))->bePrivate(),
+            'NB_AFFICH_AVIS_PAR_AUTEUR'  => Class_AdminVar_Meta::newDefault($this->_('Nombre d\'avis maximum à afficher par utilisateur.')),
+            'CLEF_GOOGLE_MAP' => Class_AdminVar_Meta::newDefault($this->_('Clef d\'activation pour le plan d\'accès google map. <a target="_blank" href="http://code.google.com/apis/maps/signup.html">Obtenir la clé google map</a>')),
+            'REGISTER_OK' => Class_AdminVar_Meta::newEncodedData($this->_('Texte visible par l\'internaute après son inscription.')),
+            'RESA_CONDITION' => Class_AdminVar_Meta::newEncodedData($this->_('Texte visible après l\'envoi d\'e-mail de demande de réservation.')),
+            'SITE_OK' => Class_AdminVar_Meta::newOnOff($this->_('Désactiver pour passer le site en maintenance')),
+            'ID_BIBLIOSURF' => Class_AdminVar_Meta::newDefault($this->_('Nom de la bibliothèque chez bibliosurf (en minuscules)'))->bePrivate(),
+            'ID_READ_SPEAKER' => Class_AdminVar_Meta::newDefault($this->_('Numéro de client Read Speaker <a target="_blank" href="http://webreader.readspeaker.com">http://webreader.readspeaker.com</a>')),
+            'BLUGA_API_KEY' => Class_AdminVar_Meta::newDefault($this->_('Clé API Bluga Webthumb <a target="_blank" href="http://webthumb.bluga.net/home">http://webthumb.bluga.net/home</a>')),
+            'AIDE_FICHE_ABONNE' => Class_AdminVar_Meta::newDefault($this->_('Texte d\'aide affiché dans la fiche abonné')),
+            'INTERDIRE_ENREG_UTIL' => Class_AdminVar_Meta::newOnOff($this->_('Supprime l\'affichage du lien d\'enregistrement dans les différents formulaires de connexion et interdit l\'enregistrement d\'utilisateurs')),
+            'LANGUES' => Class_AdminVar_Meta::newMultiInput($this->_('Liste des codes langue utilisées en plus du français séparées par des ;. Exemple: en;ro;es')),
+            'CACHE_ACTIF' => Class_AdminVar_Meta::newOnOff(implode('<br/>',
+                                                                   ['Activer le cache des boîtes (meilleure performance mais mise à jour toutes les ' . CACHE_LIFETIME / 60 . 'mn)',
+                                                                    '<a href="' . Class_Url::baseUrl() . '/admin/index/clearcache" >Vider le cache</a>']))->bePrivate(),
+            'CACHE_DATE' => Class_AdminVar_Meta::newDefault($this->_('Date du dernier vidage manuel du cache'))->bePrivate(),
+
+            'FORMATIONS' => Class_AdminVar_Meta::newOnOff($this->_('Activer ou désactiver le module formation'))->bePrivate(),
+
+            'BABELTHEQUE_JS' => Class_AdminVar_Meta::newDefault($this->_('URL du javascript Babelthèque à insérer dans l\'OPAC'))->bePrivate(),
+            'MULTIMEDIA_KEY' => Class_AdminVar_Meta::newDefault($this->_('Clé publique pour le cryptage des données AFI-Multimédia')),
+
+            'WEBKIOSK_KEY' => Class_AdminVar_Meta::newDefault($this->_('Clé publique pour le cryptage des données Aesis Webkiosk'))->bePrivate(),
+            'WEBKIOSK_RESERVATION_URL' => Class_AdminVar_Meta::newDefault($this->_('URL d\'accès à l\'interface de réservation des postes Aesis Webkiosk'))->bePrivate(),
+
+            'MENU_BOITE' => Class_AdminVar_Meta::newOnOff($this->_('Activation des boîtes dans les menus')),
+            'INTERDIRE_MODIF_FICHE_ABONNE' => Class_AdminVar_Meta::newOnOff($this->_('Interdire la modification de la fiche abonne')),
+            'ROOT_URL_ECOUTE' => Class_AdminVar_Meta::newDefault('URL de base à rajouter aux données unimarc pour la lecture des morceaux'),
+            'URL_TYPO3' => Class_AdminVar_Meta::newDefault($this->_('Url d\'import d\'un agenda TYPO3'))->bePrivate(),
+            'CHAMPS_FICHE_UTILISATEUR' => Class_AdminVar_Meta::newMultiInput($this->_('Liste des champs que l\'utilisateur peux modifier. <br/>Ex: nom;prenom;pseudo;adresse;<br/>code_postal;ville;mail;is_contact_mail;<br/>telephone;is_contact_telephone;')),
+            'FACETTE_PCDM4_LIBELLE' => Class_AdminVar_Meta::newDefault($this->_('Libellé pour la PCDM4')),
+            'FACETTE_DEWEY_LIBELLE' => Class_AdminVar_Meta::newDefault($this->_('Libellé pour la Dewey')),
+            'FACETTE_TYPE_DOC_LIBELLE' => Class_AdminVar_Meta::newDefault('Libellé de la facette type de document'),
+            'FACETTE_LANGUE_LIBELLE' => Class_AdminVar_Meta::newDefault('Libellé de la facette langue'),
+            'FACETTE_GENRE_LIBELLE' => Class_AdminVar_Meta::newDefault('Libelle de la facette genre'),
+            'FACETTE_SITE_LIBELLE' => Class_AdminVar_Meta::newDefault('Libellé de la facette site'),
+            'FACETTE_SECTION_LIBELLE' => Class_AdminVar_Meta::newDefault('Libellé de la facette section'),
+            'FACETTE_BIBLIOTHEQUE_LIBELLE' => Class_AdminVar_Meta::newDefault('Libellé de la facette bibliothèque'),
+            'FACETTE_AUTEUR_LIBELLE' => Class_AdminVar_Meta::newDefault('Libellé de la facette auteur'),
+            'FACETTE_INTERET_LIBELLE' => Class_AdminVar_Meta::newDefault('Libellé de la facette centres d\'intérêt'),
+            'FACETTE_MATIERE_LIBELLE' => Class_AdminVar_Meta::newDefault('Libellé de la facette matière'),
+            'FACETTE_TAG_LIBELLE' => Class_AdminVar_Meta::newDefault('Libellé de la facette tag'),
+            'UNLEASHED_FACETS' => Class_AdminVar_Meta::newMultiInput($this->_('Liste des codes des facettes qui ne sont pas limitées à l\'affichage dans le résultat de recherche<br/>Exemple : T => Type de doc, Y => Annexe, B => Bibliothèque, ... (Voir <a href="' . BOKEH_REMOTE_FILES . 'blob/' . BOKEH_VERSION . '/library/Class/Codification.php#L24">la liste complète</a>)')),
+            'BOITE_PANIER_AUTO' => Class_AdminVar_Meta::newOnOff($this->_('Ajouter automatiquement une boîte panier dans la division flottante')),
+            'EXTRA_SKIN_PATH' => Class_AdminVar_Meta::newDefault($this->_('Chemin vers les skins personnalisées, relatif à %s', Class_Profil_Skin::EXTRA_PATH)),
+            'ENABLE_COLLABORATIVE_BROWSING' => Class_AdminVar_Meta::newOnOff($this->_('Activation de la navigation collaborative')),
+            'KOHA_MULTI_SITES' => Class_AdminVar_Meta::newOnOff($this->_('WS KOHA : Reservation d\'exemplaires pour les multi sites')),
+
+            'TEXT_REPLACEMENTS' => Class_AdminVar_Meta::newRawText($this->_('Remplacement de textes à la volée. <br/>Ex:<br/>Panier;Sélection<br/>Vous avez %%d paniers;Vous avez %%d sélections')),
+            'URL_COSMOGRAMME' => Class_AdminVar_Meta::newDefault('')->bePrivate(),
+            'PACK_MOBILE' => Class_AdminVar_Meta::newOnOff($this->_('Activation des fonctions avancées du téléphone'))->bePrivate(),
+            'CNIL_CONSENT_ENABLE' => Class_AdminVar_Meta::newOnOff('Affiche la demande de consentement avant l\'insertion de cookies ou autres traceurs'),
+            'BUID' => Class_AdminVar_Meta::newRawText($this->_('Identifiant unique (attention: la modification de cette variable impactera les outils de suivi de cette installation)'))->bePrivate(),
+            'STATUS_REPORT_PUSH_URL' => Class_AdminVar_Meta::newRawText($this->_('URL destinataire du rapport d\'état du système (0 pour désactiver)'), ['value' => 'http://pola.afi-sa.net/smile.php'])->bePrivate(),
+            'STATUS_REPORT_TAGS' => Class_AdminVar_Meta::newMultiInput($this->_('Liste des tags à ajouter au rapport d\'état du système'))->bePrivate()];
+  }
+
+
+  protected function _getCommentVars() {
+    return [
+            'AVIS_MAX_SAISIE' => Class_AdminVar_Meta::newDefault($this->_('Nombre de caractères maximum autorisé à saisir dans les avis.')),
+            'AVIS_MIN_SAISIE' => Class_AdminVar_Meta::newDefault($this->_('Nombre de caractères minimum autorisé à saisir dans les avis.')),
+            'BLOG_MAX_NB_CARAC' => Class_AdminVar_Meta::newDefault($this->_('Nombre de caractères maximum à afficher dans le bloc critiques.'))];
+  }
+
+
+  protected function _getModerationVars() {
+    return [
+            'MODO_AVIS' => Class_AdminVar_Meta::newOnOff($this->_('Modération des avis des lecteurs.<br /> Désactivé : affichage sans attente de validation<br /> Activé : affichage seulement après validation.')),
+            'MODO_AVIS_BIBLIO' => Class_AdminVar_Meta::newOnOff($this->_('Modération des avis des bibliothécaires.<br />  Désactivé: affichage sans attente de validation<br /> Activé: affichage seulement après validation')),
+            'AVIS_BIB_SEULEMENT' => Class_AdminVar_Meta::newOnOff($this->_('Désactivé: les lecteurs peuvent donner leur avis. <br /> Activé: seuls les bibliothécaires peuvent donner leur avis')),
+            'MODO_BLOG' => Class_AdminVar_Meta::newOnOff($this->_('Désactivé: ne requiert pas d\'identification pour saisir des  commentaires. <br /> Activé: requiert l\'identification pour saisir des commentaires.')),
+            'MAX_DAY_INVALID_MEMBRE' => Class_AdminVar_Meta::newDefault($this->_('Nombre de jours de validité des nouvelles inscriptions sur le site')),
+    ];
+  }
+
+
+  protected function _getStatVars() {
+    return ['JS_STAT' => Class_AdminVar_Meta::newRawText($this->_('Javascript code for statistics')),
+            'PIWIK_AUTH_TOKEN' => Class_AdminVar_Meta::newDefault($this->_('PIWIK authentication token for widgets'))];
+  }
+
+
+  protected function _getCosmogrammeVars() {
+    return [
+            'DATE_LAST_FULL_INTEGRATION_USERS' => Class_AdminVar_Meta::newDefault($this->_('Date du dernier import total des abonnés (modifié par cosmogramme)')),
+            'INTEGRATIONS_TOO_LONG_ALERT_THRESHOLD' => Class_AdminVar_Meta::newDefault($this->_('Seuil d\'alerte en heures pour détecter que les traitements d\'intégration prennent trop de temps. Par défaut: 2', ['value' => 2]))
+    ];
+  }
+
+
+  protected function _getOAIVars() {
+    return [
+            'OAI_SERVER' => Class_AdminVar_Meta::newOnOff($this->_('Activation du serveur OAI: permet le moissonnage des domaines par d\'autres logiciels via OAI'))];
+  }
+
+
+  protected function _getLeSocialVars() {
+    return ['LESOCIAL_URL' => Class_Adminvar_Meta::newDefault($this->_('Url du connecteur Le Social'))->bePrivate(),
+            'LESOCIAL_ID' => Class_Adminvar_Meta::newDefault($this->_('Id du connecteur Le Social'))->bePrivate()];
+  }
+
+
+  protected function _getStaticMapVars() {
+    return ['STATIC_MAP' => Class_AdminVar_Meta::newCombo($this->_('API utilisée pour les cartes statiques'),
+                                                          ['options' => ['selectOptions' => ['label' => $this->_('API'),
+                                                                                             'value' => Class_Map::GOOGLE_API,
+                                                                                             'multioptions' => (new Class_Map())->getAPIs()]]])->bePrivate()];
+  }
+
+
   public function allVarsValues() {
     $values=[];
     foreach ($this->knownVars() as $key => $value) {
diff --git a/library/Class/AdminVar/ForceHTTPS.php b/library/Class/AdminVar/ForceHTTPS.php
new file mode 100644
index 0000000000000000000000000000000000000000..9d4889de3e70bc6b8404231948f56b3ab616be7b
--- /dev/null
+++ b/library/Class/AdminVar/ForceHTTPS.php
@@ -0,0 +1,28 @@
+<?php
+/**
+ * Copyright (c) 2012-2017, 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_AdminVar_ForceHTTPS {
+  public static function isEnabled() {
+    return '1' == Class_AdminVar::get('FORCE_HTTPS');
+  }
+}
+?>
\ No newline at end of file
diff --git a/library/Class/Url.php b/library/Class/Url.php
index d881737eaffadfaaaaa3946cf5a1c5cb462d676c..bf5c169891fbf67d89fdef67ad285eabedc4d4cd 100644
--- a/library/Class/Url.php
+++ b/library/Class/Url.php
@@ -84,6 +84,9 @@ class Class_Url {
 
 
   public static function getProtocol() {
+    if (Class_AdminVar_ForceHTTPS::isEnabled())
+      return 'https://';
+
     return 'http'
       . (!isset($_SERVER['HTTPS']) || !$_SERVER['HTTPS'] || $_SERVER['HTTPS'] == 'off'
          ? '' : 's')
diff --git a/library/ZendAfi/Controller/Dispatcher/Standard.php b/library/ZendAfi/Controller/Dispatcher/Standard.php
index f02ea5f60413d33e4172e41fc78ecbecd557650e..ccd9fb481c7e9201af0c3187ed30869a0a7529dd 100644
--- a/library/ZendAfi/Controller/Dispatcher/Standard.php
+++ b/library/ZendAfi/Controller/Dispatcher/Standard.php
@@ -20,20 +20,38 @@
  */
 class ZendAfi_Controller_Dispatcher_Standard extends Zend_Controller_Dispatcher_Standard {
   public function dispatch(Zend_Controller_Request_Abstract $request, Zend_Controller_Response_Abstract $response) {
+    if ($this->_isRedirectedToHTTPS($request, $response))
+      return;
+
     try {
       return parent::dispatch($request, $response);
     }
+
     catch (Zend_Controller_Dispatcher_Exception $e) {
-      $controller_name = $request->getControllerName();
+      $this->_tryRewritedUrlsOrThrowError($request, $e);
+    }
+  }
 
-      if ($library = Class_Bib::findFirstBy(['rewrite_url' => $controller_name]))
-        return $this->_dispatchToLibrary($library, $request, $response);
 
-      if ($profil = Class_Profil::findInControllerActionOf($request))
-        return $this->_dispatchToProfil($profil, $request, $response);
+  protected function _isRedirectedToHTTPS($request, $response) {
+    if (($_SERVER['HTTPS'] == 'on') || !Class_AdminVar::isModuleEnabled('FORCE_HTTPS'))
+      return false;
 
-      throw $e;
-    }
+    $response->setRedirect(Class_Url::absolute(), 301);
+    return true;
+  }
+
+
+  protected function _tryRewritedUrlsOrThrowError($request, $error) {
+    $controller_name = $request->getControllerName();
+
+    if ($library = Class_Bib::findFirstBy(['rewrite_url' => $controller_name]))
+      return $this->_dispatchToLibrary($library, $request, $response);
+
+    if ($profil = Class_Profil::findInControllerActionOf($request))
+      return $this->_dispatchToProfil($profil, $request, $response);
+
+    throw $error;
   }
 
 
diff --git a/library/startup.php b/library/startup.php
index 6f29cfc6a9db540284e7f58fcb1beac249d54c0c..078fb25e35dbe865bbe5f320d9a9530e8b8958df 100644
--- a/library/startup.php
+++ b/library/startup.php
@@ -61,7 +61,6 @@ class Bokeh_Engine {
   function warmUp() {
     require_once('Class/Url.php');
 
-    defineConstant('ROOT_URL', Class_Url::rootUrl());
     defineConstant('BASE_URL',  Class_Url::baseUrl());
 
     require_once "Zend/Loader.php";
@@ -77,6 +76,7 @@ class Bokeh_Engine {
 
     Class_AdminVar::findAll();
 
+    defineConstant('ROOT_URL', Class_Url::rootUrl());
     return $this->setupLanguage();
   }
 
diff --git a/tests/scenarios/Https/HttpsTest.php b/tests/scenarios/Https/HttpsTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..f1e5acea45af9f2ef48393cf67af14e5913fef27
--- /dev/null
+++ b/tests/scenarios/Https/HttpsTest.php
@@ -0,0 +1,79 @@
+<?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 Scenario_HttpsForceRedirectTest extends AbstractControllerTestCase {
+  protected
+    $_storm_default_to_volatile = true;
+
+
+  public function setUp() {
+    parent::setUp();
+
+
+    Class_AdminVar::set('FORCE_HTTPS', '1');
+
+    $this->fixture('Class_Article',
+                   ['id' => 3,
+                    'titre' => 'Redirection test',
+                    'contenu' => 'With FORCE_HTTPS on, should redirect to https'
+                   ]);
+  }
+
+
+  /** @test */
+  public function withHTTPSSchemeShouldRenderArticle() {
+    $_SERVER['HTTPS'] = 'on';
+    $this->dispatch('/cms/articleview/id/3', true);
+    $this->assertXPathContentContains('//h1', 'Redirection test');
+  }
+
+
+  /** @test */
+  public function withoutHTTPSchemeShouldRedirectToSameURIWithHTTPS() {
+    $_SERVER['HTTPS'] = 'off';
+
+    $this->dispatch('/cms/articleview/id/3', true);
+    $this->assertRedirectTo('https://localhost' . BASE_URL . '/cms/articleview/id/3');
+    return $this->response;
+  }
+
+
+  /**
+   * @depends withoutHTTPSchemeShouldRedirectToSameURIWithHTTPS
+   * @test
+   */
+  public function redirectCodeShouldBe301($response) {
+    $this->assertEquals(301, $response->getHttpResponseCode());
+  }
+
+
+  /** @test */
+  public function profileUrlsShouldIncludeHTTPSProtocol() {
+    $profil = $this->fixture('Class_Profil',
+                             ['id' => 2,
+                              'rewrite_url' => 'secure',
+                              'titre' => 'home'
+                             ]);
+    $this->assertEquals('https://localhost' . BASE_URL . '/secure',
+                        $profil->getUrl());
+  }
+}