diff --git a/cas/cas-server/src/main/config/cas-server-application-dev.yml b/cas/cas-server/src/main/config/cas-server-application-dev.yml
index 033c8a6c7b5ad8966efd4cd3ad61896c6b5efe17..e8539df268a0d7729349433fa7598cbd447c83bb 100644
--- a/cas/cas-server/src/main/config/cas-server-application-dev.yml
+++ b/cas/cas-server/src/main/config/cas-server-application-dev.yml
@@ -147,8 +147,10 @@ server-identity :
   identityServerId: 1
 
 
-# Example to override theme colors and logo
+# Example to override theme colors, logo, favicon, platform name ...
 theme:
+#  vitamui-platform-name: VITAM-UI
+#  vitamui-favicon: /absolute/path/to/favicon.ico
 #  vitam-logo: /absolute/path/to/logo.png
 #  vitamui-logo-large: /absolute/path/to/logo.png
   primary: '#ff4a54'
diff --git a/cas/cas-server/src/main/java/fr/gouv/vitamui/cas/config/WebflowConfig.java b/cas/cas-server/src/main/java/fr/gouv/vitamui/cas/config/WebflowConfig.java
index 9ae67f5cfeb98ee7c6b553a5c9b2ffb6b70448f1..84bf672529f6a68bca5ee1c93c4329187a87e0af 100644
--- a/cas/cas-server/src/main/java/fr/gouv/vitamui/cas/config/WebflowConfig.java
+++ b/cas/cas-server/src/main/java/fr/gouv/vitamui/cas/config/WebflowConfig.java
@@ -36,18 +36,9 @@
  */
 package fr.gouv.vitamui.cas.config;
 
-import fr.gouv.vitamui.cas.pm.PmTransientSessionTicketExpirationPolicyBuilder;
-import fr.gouv.vitamui.cas.pm.ResetPasswordController;
-import fr.gouv.vitamui.cas.util.Utils;
-import fr.gouv.vitamui.cas.webflow.actions.GeneralTerminateSessionAction;
-import fr.gouv.vitamui.cas.provider.ProvidersService;
-import fr.gouv.vitamui.cas.webflow.actions.*;
-import fr.gouv.vitamui.cas.webflow.configurer.CustomLoginWebflowConfigurer;
-import fr.gouv.vitamui.iam.common.utils.IdentityProviderHelper;
-import fr.gouv.vitamui.iam.external.client.CasExternalRestClient;
-import lombok.val;
 import org.apereo.cas.CentralAuthenticationService;
 import org.apereo.cas.audit.AuditableExecution;
+import org.apereo.cas.authentication.AuthenticationEventExecutionPlan;
 import org.apereo.cas.authentication.AuthenticationServiceSelectionPlan;
 import org.apereo.cas.authentication.AuthenticationSystemSupport;
 import org.apereo.cas.authentication.adaptive.AdaptiveAuthenticationPolicy;
@@ -83,7 +74,11 @@ import org.springframework.boot.autoconfigure.thymeleaf.ThymeleafProperties;
 import org.springframework.cloud.context.config.annotation.RefreshScope;
 import org.springframework.context.ApplicationContext;
 import org.springframework.context.HierarchicalMessageSource;
-import org.springframework.context.annotation.*;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.DependsOn;
+import org.springframework.context.annotation.Lazy;
+import org.springframework.context.annotation.Scope;
 import org.springframework.core.Ordered;
 import org.springframework.core.annotation.Order;
 import org.springframework.webflow.config.FlowDefinitionRegistryBuilder;
@@ -92,6 +87,26 @@ import org.springframework.webflow.engine.builder.support.FlowBuilderServices;
 import org.springframework.webflow.execution.Action;
 import org.thymeleaf.spring5.SpringTemplateEngine;
 
+import fr.gouv.vitamui.cas.pm.PmTransientSessionTicketExpirationPolicyBuilder;
+import fr.gouv.vitamui.cas.pm.ResetPasswordController;
+import fr.gouv.vitamui.cas.provider.ProvidersService;
+import fr.gouv.vitamui.cas.util.Utils;
+import fr.gouv.vitamui.cas.webflow.actions.CheckMfaTokenAction;
+import fr.gouv.vitamui.cas.webflow.actions.CustomDelegatedClientAuthenticationAction;
+import fr.gouv.vitamui.cas.webflow.actions.CustomInitialFlowSetupAction;
+import fr.gouv.vitamui.cas.webflow.actions.CustomSendTokenAction;
+import fr.gouv.vitamui.cas.webflow.actions.CustomVerifyPasswordResetRequestAction;
+import fr.gouv.vitamui.cas.webflow.actions.DispatcherAction;
+import fr.gouv.vitamui.cas.webflow.actions.GeneralTerminateSessionAction;
+import fr.gouv.vitamui.cas.webflow.actions.I18NSendPasswordResetInstructionsAction;
+import fr.gouv.vitamui.cas.webflow.actions.NoOpAction;
+import fr.gouv.vitamui.cas.webflow.actions.SelectRedirectAction;
+import fr.gouv.vitamui.cas.webflow.actions.TriggerChangePasswordAction;
+import fr.gouv.vitamui.cas.webflow.configurer.CustomLoginWebflowConfigurer;
+import fr.gouv.vitamui.iam.common.utils.IdentityProviderHelper;
+import fr.gouv.vitamui.iam.external.client.CasExternalRestClient;
+import lombok.val;
+
 /**
  * Web(flow) customizations.
  *
@@ -116,6 +131,10 @@ public class WebflowConfig {
     @Qualifier("authenticationServiceSelectionPlan")
     private ObjectProvider<AuthenticationServiceSelectionPlan> authenticationRequestServiceSelectionStrategies;
 
+    @Autowired
+    @Qualifier("authenticationEventExecutionPlan")
+    private ObjectProvider<AuthenticationEventExecutionPlan> AuthenticationEventExecutionStrategies;
+
     @Autowired
     @Qualifier("communicationsManager")
     private CommunicationsManager communicationsManager;
@@ -228,6 +247,14 @@ public class WebflowConfig {
             surrogationSeparator, utils, delegatedClientDistributedSessionStore.getObject());
     }
 
+    @RefreshScope
+    @Bean
+    public Action initialFlowSetupAction() {
+        return new CustomInitialFlowSetupAction(CollectionUtils.wrap(argumentExtractor.getObject()), servicesManager.getObject(),
+                authenticationRequestServiceSelectionStrategies.getObject(), ticketGrantingTicketCookieGenerator.getObject(), warnCookieGenerator.getObject(),
+                casProperties, AuthenticationEventExecutionStrategies.getObject(), webflowSingleSignOnParticipationStrategy.getObject(), ticketRegistrySupport);
+    }
+
     @Bean
     public DefaultTransientSessionTicketFactory pmTicketFactory() {
         return new DefaultTransientSessionTicketFactory(new PmTransientSessionTicketExpirationPolicyBuilder(casProperties));
diff --git a/cas/cas-server/src/main/java/fr/gouv/vitamui/cas/pm/PmMessageToSend.java b/cas/cas-server/src/main/java/fr/gouv/vitamui/cas/pm/PmMessageToSend.java
index eb40a874e7c106695826722eed2a0fb6cb334b90..953a591002e7d197ce6cef676747e30c7b0121f1 100644
--- a/cas/cas-server/src/main/java/fr/gouv/vitamui/cas/pm/PmMessageToSend.java
+++ b/cas/cas-server/src/main/java/fr/gouv/vitamui/cas/pm/PmMessageToSend.java
@@ -74,16 +74,16 @@ public class PmMessageToSend {
     }
 
     public static PmMessageToSend buildMessage(final HierarchicalMessageSource messageSource, final String firstname,
-            final String lastname, final String ttlInMinutes, final String url, final Locale locale) {
+            final String lastname, final String ttlInMinutes, final String url, final String platformName, final Locale locale) {
         final String subject;
         final String text;
         if (ONE_DAY.equals(ttlInMinutes)) {
             subject = messageSource.getMessage(PM_ACCOUNTCREATION_SUBJECT_KEY, null, locale);
             text = messageSource.getMessage(PM_ACCOUNTCREATION_TEXT_KEY,
-                    new Object[] { firstname, lastname, "24", url }, locale);
+                    new Object[] { firstname, lastname, "24", url, platformName }, locale);
         } else {
             subject = messageSource.getMessage(PM_RESET_SUBJECT_KEY, null, locale);
-            text = messageSource.getMessage(PM_RESET_TEXT_KEY, new Object[] { firstname, lastname, ttlInMinutes, url },
+            text = messageSource.getMessage(PM_RESET_TEXT_KEY, new Object[] { firstname, lastname, ttlInMinutes, url, platformName},
                     locale);
         }
         return new PmMessageToSend(subject, text);
diff --git a/cas/cas-server/src/main/java/fr/gouv/vitamui/cas/pm/ResetPasswordController.java b/cas/cas-server/src/main/java/fr/gouv/vitamui/cas/pm/ResetPasswordController.java
index 80acc38d59ae24c1b677919b733d3e4757a5088d..d9d385e5b859dfc65d9041a64db80738b7fd17de 100644
--- a/cas/cas-server/src/main/java/fr/gouv/vitamui/cas/pm/ResetPasswordController.java
+++ b/cas/cas-server/src/main/java/fr/gouv/vitamui/cas/pm/ResetPasswordController.java
@@ -51,6 +51,7 @@ import org.apereo.cas.ticket.registry.TicketRegistry;
 import org.apereo.cas.util.CollectionUtils;
 import org.apereo.cas.util.io.CommunicationsManager;
 import org.apereo.cas.web.flow.CasWebflowConfigurer;
+import org.springframework.beans.factory.annotation.Value;
 import org.springframework.context.HierarchicalMessageSource;
 import org.springframework.web.bind.annotation.GetMapping;
 import org.springframework.web.bind.annotation.RequestMapping;
@@ -89,6 +90,9 @@ public class ResetPasswordController {
 
     private final DefaultTransientSessionTicketFactory pmTicketFactory;
 
+    @Value("${theme.vitamui-platform-name:VITAM-UI}")
+    private String vitamuiPlatformName;
+
     @GetMapping("/resetPassword")
     public boolean resetPassword(@RequestParam(value = "username", defaultValue = "") final String username,
                                  @RequestParam(value = "firstname", defaultValue = "") final String firstname,
@@ -122,7 +126,7 @@ public class ResetPasswordController {
         request.setAttribute(PmTransientSessionTicketExpirationPolicyBuilder.PM_EXPIRATION_IN_MINUTES_ATTRIBUTE, expMinutes);
 
         final String url = buildPasswordResetUrl(usernameLower, casProperties);
-        final PmMessageToSend messageToSend = PmMessageToSend.buildMessage(messageSource, firstname, lastname, ttl, url, new Locale(language));
+        final PmMessageToSend messageToSend = PmMessageToSend.buildMessage(messageSource, firstname, lastname, ttl, url, vitamuiPlatformName, new Locale(language));
 
         LOGGER.debug("Generated password reset URL [{}] for: {} ({}); Link is only active for the next [{}] minute(s)", utils.sanitizePasswordResetUrl(url),
             email, messageToSend.getSubject(), expMinutes);
diff --git a/cas/cas-server/src/main/java/fr/gouv/vitamui/cas/util/Constants.java b/cas/cas-server/src/main/java/fr/gouv/vitamui/cas/util/Constants.java
index ce080b43addcb7844f5506be782d8844eaf56af1..a925d0b79c5ad3c2991b25ff3fb63196945a2391 100644
--- a/cas/cas-server/src/main/java/fr/gouv/vitamui/cas/util/Constants.java
+++ b/cas/cas-server/src/main/java/fr/gouv/vitamui/cas/util/Constants.java
@@ -55,4 +55,7 @@ public abstract class Constants {
 
     public static final String VITAM_LOGO = "vitamLogo";
 
-    public static final String VITAM_UI_LARGE_LOGO = "vitamuiLargeLogo";}
+    public static final String VITAM_UI_LARGE_LOGO = "vitamuiLargeLogo";
+
+    public static final String VITAM_UI_FAVICON = "vitamuiFavicon";
+}
diff --git a/cas/cas-server/src/main/java/fr/gouv/vitamui/cas/webflow/actions/CustomInitialFlowSetupAction.java b/cas/cas-server/src/main/java/fr/gouv/vitamui/cas/webflow/actions/CustomInitialFlowSetupAction.java
new file mode 100644
index 0000000000000000000000000000000000000000..b3408842d52dbaaecb40e0f9ab81b1f259fe3ccd
--- /dev/null
+++ b/cas/cas-server/src/main/java/fr/gouv/vitamui/cas/webflow/actions/CustomInitialFlowSetupAction.java
@@ -0,0 +1,135 @@
+/**
+* Copyright French Prime minister Office/SGMAP/DINSIC/Vitam Program (2019-2020)
+* and the signatories of the "VITAM - Accord du Contributeur" agreement.
+*
+* contact@programmevitam.fr
+*
+* This software is a computer program whose purpose is to implement
+* implement a digital archiving front-office system for the secure and
+* efficient high volumetry VITAM solution.
+*
+* This software is governed by the CeCILL-C license under French law and
+* abiding by the rules of distribution of free software. You can use,
+* modify and/ or redistribute the software under the terms of the CeCILL-C
+* license as circulated by CEA, CNRS and INRIA at the following URL
+* "http://www.cecill.info".
+*
+* As a counterpart to the access to the source code and rights to copy,
+* modify and redistribute granted by the license, users are provided only
+* with a limited warranty and the software's author, the holder of the
+* economic rights, and the successive licensors have only limited
+* liability.
+*
+* In this respect, the user's attention is drawn to the risks associated
+* with loading, using, modifying and/or developing or reproducing the
+* software by the user in light of its specific status of free software,
+* that may mean that it is complicated to manipulate, and that also
+* therefore means that it is reserved for developers and experienced
+* professionals having in-depth computer knowledge. Users are therefore
+* encouraged to load and test the software's suitability as regards their
+* requirements in conditions enabling the security of their systems and/or
+* data to be ensured and, more generally, to use and operate it in the
+* same conditions as regards security.
+*
+* The fact that you are presently reading this means that you have had
+* knowledge of the CeCILL-C license and that you accept its terms.
+*/
+package fr.gouv.vitamui.cas.webflow.actions;
+
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.List;
+
+import javax.xml.bind.DatatypeConverter;
+
+import org.apereo.cas.authentication.AuthenticationEventExecutionPlan;
+import org.apereo.cas.authentication.AuthenticationServiceSelectionPlan;
+import org.apereo.cas.configuration.CasConfigurationProperties;
+import org.apereo.cas.services.ServicesManager;
+import org.apereo.cas.ticket.registry.TicketRegistrySupport;
+import org.apereo.cas.web.cookie.CasCookieBuilder;
+import org.apereo.cas.web.flow.SingleSignOnParticipationStrategy;
+import org.apereo.cas.web.flow.login.InitialFlowSetupAction;
+import org.apereo.cas.web.support.ArgumentExtractor;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.webflow.core.collection.MutableAttributeMap;
+import org.springframework.webflow.execution.Event;
+import org.springframework.webflow.execution.RequestContext;
+
+import fr.gouv.vitamui.cas.util.Constants;
+import fr.gouv.vitamui.commons.api.logger.VitamUILogger;
+import fr.gouv.vitamui.commons.api.logger.VitamUILoggerFactory;
+
+/**
+* Custom initial flow action to retrieve pre-filled inputs.
+*
+*
+*/
+public class CustomInitialFlowSetupAction extends InitialFlowSetupAction {
+
+    private static final VitamUILogger LOGGER = VitamUILoggerFactory.getInstance(CustomInitialFlowSetupAction.class);
+
+    @Value("${theme.vitam-logo:#{null}}")
+    private String vitamLogoPath;
+
+    @Value("${theme.vitamui-logo-large:#{null}}")
+    private String vitamuiLargeLogoPath;
+
+    @Value("${theme.vitamui-favicon:#{null}}")
+    private String vitamuiFaviconPath;
+
+    public CustomInitialFlowSetupAction(final List<ArgumentExtractor> argumentExtractors, final ServicesManager servicesManager,
+            final AuthenticationServiceSelectionPlan authenticationRequestServiceSelectionStrategies,
+            final CasCookieBuilder ticketGrantingTicketCookieGenerator, final CasCookieBuilder warnCookieGenerator,
+            final CasConfigurationProperties casProperties, final AuthenticationEventExecutionPlan authenticationEventExecutionPlan,
+            final SingleSignOnParticipationStrategy renewalStrategy, final TicketRegistrySupport ticketRegistrySupport) {
+        super(argumentExtractors, servicesManager, authenticationRequestServiceSelectionStrategies, ticketGrantingTicketCookieGenerator, warnCookieGenerator,
+                casProperties, authenticationEventExecutionPlan, renewalStrategy, ticketRegistrySupport);
+    }
+
+    @Override
+    public Event doExecute(final RequestContext context) {
+
+        final MutableAttributeMap<Object> flowScope = context.getFlowScope();
+
+        if (vitamLogoPath != null) {
+            try {
+                final Path logoFile = Paths.get(vitamLogoPath);
+                final String logo = DatatypeConverter.printBase64Binary(Files.readAllBytes(logoFile));
+                flowScope.put(Constants.VITAM_LOGO, logo);
+            }
+            catch (final IOException e) {
+                LOGGER.warn("Can't find vitam logo");
+                e.printStackTrace();
+            }
+        }
+        if (vitamuiLargeLogoPath != null) {
+            try {
+                final Path logoFile = Paths.get(vitamuiLargeLogoPath);
+                final String logo = DatatypeConverter.printBase64Binary(Files.readAllBytes(logoFile));
+                flowScope.put(Constants.VITAM_UI_LARGE_LOGO, logo);
+            }
+            catch (final IOException e) {
+                LOGGER.warn("Can't find vitam ui large logo");
+                e.printStackTrace();
+            }
+        }
+
+        if (vitamuiFaviconPath != null) {
+            try {
+                final Path faviconFile = Paths.get(vitamuiFaviconPath);
+                final String favicon = DatatypeConverter.printBase64Binary(Files.readAllBytes(faviconFile));
+                flowScope.put(Constants.VITAM_UI_FAVICON, favicon);
+            }
+            catch (final IOException e) {
+                LOGGER.warn("Can't find vitam ui favicon");
+                e.printStackTrace();
+            }
+        }
+
+        return super.doExecute(context);
+    }
+
+}
diff --git a/cas/cas-server/src/main/java/fr/gouv/vitamui/cas/webflow/actions/GeneralTerminateSessionAction.java b/cas/cas-server/src/main/java/fr/gouv/vitamui/cas/webflow/actions/GeneralTerminateSessionAction.java
index 9803b129cba3ac37824318314eaf228b69ab0b06..1bca83650a70a54e1fb219f2da9541b9c0b0608a 100644
--- a/cas/cas-server/src/main/java/fr/gouv/vitamui/cas/webflow/actions/GeneralTerminateSessionAction.java
+++ b/cas/cas-server/src/main/java/fr/gouv/vitamui/cas/webflow/actions/GeneralTerminateSessionAction.java
@@ -36,6 +36,7 @@
  */
 package fr.gouv.vitamui.cas.webflow.actions;
 
+import fr.gouv.vitamui.cas.util.Constants;
 import fr.gouv.vitamui.cas.util.Utils;
 import fr.gouv.vitamui.commons.api.logger.VitamUILogger;
 import fr.gouv.vitamui.commons.api.logger.VitamUILoggerFactory;
@@ -68,11 +69,19 @@ import org.apereo.cas.web.flow.logout.FrontChannelLogoutAction;
 import org.apereo.cas.web.flow.logout.TerminateSessionAction;
 import org.apereo.cas.web.support.WebUtils;
 import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.webflow.core.collection.MutableAttributeMap;
 import org.springframework.webflow.execution.Event;
 import org.springframework.webflow.execution.RequestContext;
 
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
+import javax.xml.bind.DatatypeConverter;
+
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
 import java.util.*;
 
 import static fr.gouv.vitamui.commons.api.CommonConstants.*;
@@ -106,6 +115,15 @@ public class GeneralTerminateSessionAction extends TerminateSessionAction {
     @Autowired
     private FrontChannelLogoutAction frontChannelLogoutAction;
 
+    @Value("${theme.vitam-logo:#{null}}")
+    private String vitamLogoPath;
+
+    @Value("${theme.vitamui-logo-large:#{null}}")
+    private String vitamuiLargeLogoPath;
+
+    @Value("${theme.vitamui-favicon:#{null}}")
+    private String vitamuiFaviconPath;
+
     public GeneralTerminateSessionAction(final CentralAuthenticationService centralAuthenticationService,
                                          final CasCookieBuilder ticketGrantingTicketCookieGenerator,
                                          final CasCookieBuilder warnCookieGenerator,
@@ -173,6 +191,42 @@ public class GeneralTerminateSessionAction extends TerminateSessionAction {
             frontChannelLogoutAction.doExecute(context);
         }
 
+        final MutableAttributeMap<Object> flowScope = context.getFlowScope();
+        if (vitamLogoPath != null) {
+            try {
+                final Path logoFile = Paths.get(vitamLogoPath);
+                final String logo = DatatypeConverter.printBase64Binary(Files.readAllBytes(logoFile));
+                flowScope.put(Constants.VITAM_LOGO, logo);
+            }
+            catch (final IOException e) {
+                LOGGER.warn("Can't find vitam logo");
+                e.printStackTrace();
+            }
+        }
+        if (vitamuiLargeLogoPath != null) {
+            try {
+                final Path logoFile = Paths.get(vitamuiLargeLogoPath);
+                final String logo = DatatypeConverter.printBase64Binary(Files.readAllBytes(logoFile));
+                flowScope.put(Constants.VITAM_UI_LARGE_LOGO, logo);
+            }
+            catch (final IOException e) {
+                LOGGER.warn("Can't find vitam ui large logo");
+                e.printStackTrace();
+            }
+        }
+
+        if (vitamuiFaviconPath != null) {
+            try {
+                final Path faviconFile = Paths.get(vitamuiFaviconPath);
+                final String favicon = DatatypeConverter.printBase64Binary(Files.readAllBytes(faviconFile));
+                flowScope.put(Constants.VITAM_UI_FAVICON, favicon);
+            }
+            catch (final IOException e) {
+                LOGGER.warn("Can't find vitam ui favicon");
+                e.printStackTrace();
+            }
+        }
+
         return event;
     }
 
diff --git a/cas/cas-server/src/main/java/fr/gouv/vitamui/cas/webflow/actions/I18NSendPasswordResetInstructionsAction.java b/cas/cas-server/src/main/java/fr/gouv/vitamui/cas/webflow/actions/I18NSendPasswordResetInstructionsAction.java
index 89b321bbe6c9c775dd147d9c5a3b1892d23d4f24..26392dc6ff797ce406494bc082f7914e79cbc401 100644
--- a/cas/cas-server/src/main/java/fr/gouv/vitamui/cas/webflow/actions/I18NSendPasswordResetInstructionsAction.java
+++ b/cas/cas-server/src/main/java/fr/gouv/vitamui/cas/webflow/actions/I18NSendPasswordResetInstructionsAction.java
@@ -36,14 +36,6 @@
  */
 package fr.gouv.vitamui.cas.webflow.actions;
 
-import fr.gouv.vitamui.cas.pm.PmMessageToSend;
-import fr.gouv.vitamui.cas.pm.PmTransientSessionTicketExpirationPolicyBuilder;
-import fr.gouv.vitamui.cas.provider.ProvidersService;
-import fr.gouv.vitamui.cas.util.Utils;
-import fr.gouv.vitamui.commons.api.logger.VitamUILogger;
-import fr.gouv.vitamui.commons.api.logger.VitamUILoggerFactory;
-import fr.gouv.vitamui.iam.common.utils.IdentityProviderHelper;
-import lombok.val;
 import org.apache.commons.lang3.StringUtils;
 import org.apereo.cas.authentication.credential.UsernamePasswordCredential;
 import org.apereo.cas.configuration.CasConfigurationProperties;
@@ -53,12 +45,22 @@ import org.apereo.cas.ticket.TicketFactory;
 import org.apereo.cas.ticket.registry.TicketRegistry;
 import org.apereo.cas.util.io.CommunicationsManager;
 import org.apereo.cas.web.support.WebUtils;
+import org.springframework.beans.factory.annotation.Value;
 import org.springframework.context.HierarchicalMessageSource;
 import org.springframework.context.i18n.LocaleContextHolder;
 import org.springframework.webflow.core.collection.MutableAttributeMap;
 import org.springframework.webflow.execution.Event;
 import org.springframework.webflow.execution.RequestContext;
 
+import fr.gouv.vitamui.cas.pm.PmMessageToSend;
+import fr.gouv.vitamui.cas.pm.PmTransientSessionTicketExpirationPolicyBuilder;
+import fr.gouv.vitamui.cas.provider.ProvidersService;
+import fr.gouv.vitamui.cas.util.Utils;
+import fr.gouv.vitamui.commons.api.logger.VitamUILogger;
+import fr.gouv.vitamui.commons.api.logger.VitamUILoggerFactory;
+import fr.gouv.vitamui.iam.common.utils.IdentityProviderHelper;
+import lombok.val;
+
 /**
  * Send reset password emails with i18n messages.
  *
@@ -66,8 +68,7 @@ import org.springframework.webflow.execution.RequestContext;
  */
 public class I18NSendPasswordResetInstructionsAction extends SendPasswordResetInstructionsAction {
 
-    private static final VitamUILogger LOGGER = VitamUILoggerFactory
-            .getInstance(I18NSendPasswordResetInstructionsAction.class);
+    private static final VitamUILogger LOGGER = VitamUILoggerFactory.getInstance(I18NSendPasswordResetInstructionsAction.class);
 
     private final CasConfigurationProperties casProperties;
 
@@ -83,6 +84,9 @@ public class I18NSendPasswordResetInstructionsAction extends SendPasswordResetIn
 
     private final Utils utils;
 
+    @Value("${theme.vitamui-platform-name:VITAM-UI}")
+    private String vitamuiPlatformName;
+
     public I18NSendPasswordResetInstructionsAction(final CasConfigurationProperties casProperties,
                                                    final CommunicationsManager communicationsManager,
                                                    final PasswordManagementService passwordManagementService,
@@ -141,8 +145,8 @@ public class I18NSendPasswordResetInstructionsAction extends SendPasswordResetIn
         val url = buildPasswordResetUrl(username, passwordManagementService, casProperties, service);
         if (StringUtils.isNotBlank(url)) {
             val pm = casProperties.getAuthn().getPm();
-            LOGGER.debug("Generated password reset URL [{}]; Link is only active for the next [{}] minute(s)",
-                utils.sanitizePasswordResetUrl(url), pm.getReset().getExpirationMinutes());
+            LOGGER.debug("Generated password reset URL [{}]; Link is only active for the next [{}] minute(s)", utils.sanitizePasswordResetUrl(url),
+                    pm.getReset().getExpirationMinutes());
             if (sendPasswordResetEmailToAccount(email, url)) {
                 return success();
             }
@@ -155,9 +159,9 @@ public class I18NSendPasswordResetInstructionsAction extends SendPasswordResetIn
 
     @Override
     protected boolean sendPasswordResetEmailToAccount(final String to, final String url) {
-        final PmMessageToSend messageToSend = PmMessageToSend.buildMessage(messageSource, "", "", "10", url,
+        final PmMessageToSend messageToSend = PmMessageToSend.buildMessage(messageSource, "", "", "10", url, vitamuiPlatformName,
                 LocaleContextHolder.getLocale());
-        return utils.htmlEmail(messageToSend.getText(), casProperties.getAuthn().getPm().getReset().getMail().getFrom(),
-                messageToSend.getSubject(), to, null, null);
+        return utils.htmlEmail(messageToSend.getText(), casProperties.getAuthn().getPm().getReset().getMail().getFrom(), messageToSend.getSubject(), to, null,
+                null);
     }
 }
diff --git a/cas/cas-server/src/main/resources/application.properties b/cas/cas-server/src/main/resources/application.properties
index 2e68c5b1f149d2a54ee8f8512aebefd21537610c..ca7fdb1bc483f51c13dbc233ef1e1d52a4cee134 100644
--- a/cas/cas-server/src/main/resources/application.properties
+++ b/cas/cas-server/src/main/resources/application.properties
@@ -182,6 +182,7 @@ cas.view.cas2.v3ForwardCompatible=true
 # theme.vitam-logo=/path/to/vitam-logo/vitam-logo.png
 # theme.vitamui-logo-large=/path/to/vitam-logo/vitamui-logo-large.png
 
+theme.vitamui-platform-name=VITAM-UI
 theme.primary=#702382
 theme.secondary=#7FA1D4
 
diff --git a/cas/cas-server/src/main/resources/overriden_messages.properties b/cas/cas-server/src/main/resources/overriden_messages.properties
index 422cbc13eeeab269d7584f0cb29745738695f07b..2118f9a9c9ecc2951f02171666dc051419212fba 100644
--- a/cas/cas-server/src/main/resources/overriden_messages.properties
+++ b/cas/cas-server/src/main/resources/overriden_messages.properties
@@ -4,23 +4,23 @@ screen.accountlocked.message=Please wait before trying again
 authenticationFailure.AccountLockedException=Your account has been locked for the next 20 minutes, please wait before trying again
 
 cas.authn.pm.reset.subject=Password creation
-cas.authn.pm.reset.text=<html><body>Hello.<br /><br />Here is the link that will allow you to create a new password on VitamUI: <a href="{3}">click here</a>.<br />This one is valid for the next {2} minutes.<br /><br />Have a good day.</body></html>
+cas.authn.pm.reset.text=<html><body>Hello.<br /><br />Here is the link that will allow you to create a new password on {4}: <a href="{3}">click here</a>.<br />This one is valid for the next {2} minutes.<br /><br />Have a good day.</body></html>
 cas.authn.pm.accountcreation.subject=Password creation
-cas.authn.pm.accountcreation.text=<html><body>Hello {0} {1}.<br /><br />Here is the link that will allow you to create a new password on VitamUI: <a href="{3}">click here</a>.<br />This one is valid for the next {2} hours.<br /><br />Have a good day.</body></html>
+cas.authn.pm.accountcreation.text=<html><body>Hello {0} {1}.<br /><br />Here is the link that will allow you to create a new password on {0}: <a href="{3}">click here</a>.<br />This one is valid for the next {2} hours.<br /><br />Have a good day.</body></html>
 
 screen.welcome.label.surrogate=Surrogate:
 screen.welcome.label.superuser=Super user:
 
-screen.service.error.header=Application Not Authorized to Use VITAMUI
+screen.service.error.header=Application Not Authorized to Use {0}
 service.not.authorized.missing.attr=You are not authorized to access the application as your account \
-is missing privileges required by the VITAMUI server to authenticate into this service. Please notify your support desk.
-screen.service.error.message=The application you attempted to authenticate to is not authorized to use VITAMUI. \
-  Contact your VITAMUI administrator to learn how you might register and integrate your application with VITAMUI.
-screen.service.empty.error.message=Contact your VITAMUI administrator to learn how you might register and integrate your application with VITAMUI.
+is missing privileges required by the {0} server to authenticate into this service. Please notify your support desk.
+screen.service.error.message=The application you attempted to authenticate to is not authorized. \
+  Contact your administrator to learn how you might register and integrate your application.
+screen.service.empty.error.message=Contact your administrator to learn how you might register and integrate your application.
 
 screen.logout.header=Logout
-screen.logout.success=You have successfully logged out of VITAMUI. You may <a href="login">log in</a> again.
-screen.logout.fc.success=You have successfully logged out of VITAMUI. You may <a href="login">log in</a> again.
+screen.logout.success=You have successfully logged out of {0}. You may <a href="login">log in</a> again.
+screen.logout.fc.success=You have successfully logged out of {0}. You may <a href="login">log in</a> again.
 screen.logout.security=For security reasons, exit your web browser.
 
 screen.pac4j.unauthz.message=You are not authorized to access the application.
@@ -35,9 +35,9 @@ screen.pm.success.header=Password Change
 pm.validationFailure.alreadyUsed=You cannot set again one of your three latest passwords
 
 # Unavailable
-screen.unavailable.header=VITAMUI Error
+screen.unavailable.header={0} Error
 screen.unavailable.heading=An error occurred while processing your request.
-screen.unavailable.message=Contact your VITAMUI administrator.
+screen.unavailable.message=Contact your {0} administrator.
 
 screen.accountbadconfiguration.heading=Your account is not properly configured.
-screen.accountbadconfiguration.message=Contact your VITAMUI administrator.
+screen.accountbadconfiguration.message=Contact your {0} administrator.
diff --git a/cas/cas-server/src/main/resources/overriden_messages_de.properties b/cas/cas-server/src/main/resources/overriden_messages_de.properties
index 734a09d47c3e1ec145d9175ef3c74bd57887ad32..e82309437646e5d4752a6fd700267ef62efa9166 100644
--- a/cas/cas-server/src/main/resources/overriden_messages_de.properties
+++ b/cas/cas-server/src/main/resources/overriden_messages_de.properties
@@ -11,12 +11,12 @@ cas.authn.pm.accountcreation.text=Hallo {0} {1}.\n\nHier ist der Link, mit dem S
 screen.welcome.label.surrogate=�bergegangenen :
 screen.welcome.label.superuser=Superbenutzer :
 
-screen.service.error.header=Anwendung darf VITAMUI nicht verwenden
+screen.service.error.header=Anwendung darf {0} nicht verwenden
 service.not.authorized.missing.attr=Sie sind nicht berechtigt, auf diese Anwendung zuzugreifen, da Ihr Konto nicht �ber die Berechtigungen verf�gt, \
-die der VITAMUI-Anbieter f�r den Zugriff auf diesen Dienst ben�tigt. Bitte kontaktieren Sie Ihren Support.
-screen.service.error.message=Die Anwendung, f�r die Sie eine Authentifizierung versucht haben, darf VITAMUI nicht verwenden. \
-  <br>Wenden Sie sich an Ihren VITAMUI-Administrator, um zu erfahren, wie Sie Ihre Anwendung bei VITAMUI registrieren und integrieren.
-screen.service.empty.error.message=Wenden Sie sich an Ihren VITAMUI-Administrator, um zu erfahren, wie Sie Ihre Anwendung bei VITAMUI registrieren und integrieren.
+die der {0}-Anbieter f�r den Zugriff auf diesen Dienst ben�tigt. Bitte kontaktieren Sie Ihren Support.
+screen.service.error.message=Die Anwendung, f�r die Sie eine Authentifizierung versucht haben. \
+  <br>Wenden Sie sich an Ihren Administrator, um zu erfahren, wie Sie Ihre Anwendung registrieren und integrieren.
+screen.service.empty.error.message=Wenden Sie sich an Ihren Administrator, um zu erfahren, wie Sie Ihre Anwendung registrieren und integrieren.
 
 screen.logout.header=austragen
 screen.logout.success=Sie haben sich ausgeloggt. Sie k�nnen sich <a href="login">erneut</a> anmelden.
@@ -36,6 +36,6 @@ screen.pm.init.security.four=Beide Passwörter müssen übereinstimmen
 screen.pm.success.header=�nderung des Passwortes
 
 # Unavailable
-screen.unavailable.header=VITAMUI-Fehler
+screen.unavailable.header={0}-Fehler
 screen.unavailable.heading=Bei der Bearbeitung Ihrer Anfrage ist ein Fehler aufgetreten.
-screen.unavailable.message=Wenden Sie sich an Ihren VITAMUI-Administrator.
+screen.unavailable.message=Wenden Sie sich an Ihren {0}-Administrator.
diff --git a/cas/cas-server/src/main/resources/overriden_messages_fr.properties b/cas/cas-server/src/main/resources/overriden_messages_fr.properties
index 05ca4a0a6e751c9606b8ea39a55a01aa8bde96dd..9744b82c6b8ad6f530fc1154b86d4d1d91d399bb 100644
--- a/cas/cas-server/src/main/resources/overriden_messages_fr.properties
+++ b/cas/cas-server/src/main/resources/overriden_messages_fr.properties
@@ -4,19 +4,19 @@ screen.accountlocked.message=Veuillez patienter avant de réessayer
 authenticationFailure.AccountLockedException=Votre compte est bloqué pour les 20 prochaines minutes, veuillez patienter avant de réessayer
 
 cas.authn.pm.reset.subject=Création de mot de passe
-cas.authn.pm.reset.text=<html><body>Bonjour.<br/><br/>Voici le lien qui vous permettra de vous créer un nouveau mot de passe sur VitamUI : <a href="{3}">cliquez ici</a>.<br/>Celui-ci est valable pour les prochaines {2} minutes.<br/><br/>Bonne journée.</body></html>
+cas.authn.pm.reset.text=<html><body>Bonjour.<br/><br/>Voici le lien qui vous permettra de vous créer un nouveau mot de passe sur {4} : <a href="{3}">cliquez ici</a>.<br/>Celui-ci est valable pour les prochaines {2} minutes.<br/><br/>Bonne journée.</body></html>
 cas.authn.pm.accountcreation.subject=Création de mot de passe
-cas.authn.pm.accountcreation.text=<html><body>Bonjour {0} {1}.<br/><br/>Voici le lien qui vous permettra de vous créer un nouveau mot de passe sur VitamUI : <a href="{3}">cliquez ici</a>.<br/>Celui-ci est valable pour les prochaines {2} heures.<br/><br/>Bonne journée.</body></html>
+cas.authn.pm.accountcreation.text=<html><body>Bonjour {0} {1}.<br/><br/>Voici le lien qui vous permettra de vous créer un nouveau mot de passe sur {4} : <a href="{3}">cliquez ici</a>.<br/>Celui-ci est valable pour les prochaines {2} heures.<br/><br/>Bonne journée.</body></html>
 
 screen.welcome.label.surrogate=Subrogé :
 screen.welcome.label.superuser=Super utilisateur :
 
-screen.service.error.header=Application non autorisée à utiliser VITAMUI
+screen.service.error.header=Application non autorisée à utiliser {0}
 service.not.authorized.missing.attr=Vous n'êtes pas autorisé à accéder à cette application car votre compte \
-n'a pas les privilèges requis par le seveur VITAMUI pour accéder à ce service. Merci de contacter votre support.
-screen.service.error.message=L'application pour laquelle vous avez tenté de vous authentifier n'est pas autorisée à utiliser VITAMUI. \
-  <br>Contactez votre administrateur VITAMUI pour savoir comment enregistrer et intégrer votre application à VITAMUI.
-screen.service.empty.error.message=Contactez votre administrateur VITAMUI pour savoir comment enregistrer et intégrer votre application à VITAMUI.
+n'a pas les privilèges requis par le seeveur {0} pour accéder à ce service. Merci de contacter votre support.
+screen.service.error.message=L' application pour laquelle vous avez tenté de vous authentifier n'est pas autorisée. \
+  <br>Contactez votre administrateur pour savoir comment enregistrer et intégrer votre application.
+screen.service.empty.error.message=Contactez votre administrateur pour savoir comment enregistrer et intégrer votre application.
 
 screen.logout.header=Déconnexion
 screen.logout.success=Vous vous êtes déconnecté(e). Vous pouvez vous <a href="login">connecter</a> à nouveau.
@@ -57,11 +57,11 @@ screen.mfa.sms.expired.resend=Envoyer un nouveau code au {0}
 authenticationFailure.AuthenticationException=Le code OTP est erroné
 
 # Unavailable
-screen.unavailable.header=Erreur VITAMUI
+screen.unavailable.header=Erreur {0}
 screen.unavailable.heading=Une erreur est survenue lors du traitement de votre requête.
-screen.unavailable.message=Contactez votre administrateur VITAMUI.
+screen.unavailable.message=Contactez votre administrateur {0}.
 
 screen.accountbadconfiguration.heading=Votre compte a un problème de configuration.
-screen.accountbadconfiguration.message=Contactez votre administrateur VITAMUI.
+screen.accountbadconfiguration.message=Contactez votre administrateur {0}.
 
 screen.pm.reset.message=Le lien n'est plus valide.
diff --git a/cas/cas-server/src/main/resources/static/js/attrresolution.js b/cas/cas-server/src/main/resources/static/js/attrresolution.js
deleted file mode 100644
index e500ff3fc11e1545019fd5b793315fc3e8c8e674..0000000000000000000000000000000000000000
--- a/cas/cas-server/src/main/resources/static/js/attrresolution.js
+++ /dev/null
@@ -1,116 +0,0 @@
-var table;
-
-$(document).ready(function () {
-    $('#fmrel').on('submit', function (e) {
-        e.preventDefault();
-        var username = $('#username').val();
-        var password = $('#password').val();
-        var service = $('#service').val();
-
-        releaseAttributes(username, password, service);
-    });
-
-
-    $('#fm1').on('submit', function (e) {
-        e.preventDefault();
-        var uid = $('#uid').val();
-        table = $('#attributesTable').DataTable();
-        table.clear().draw();
-
-        var status = $('#status');
-
-        if (uid !== null && uid !== '') {
-            resolveAttributes(uid);
-            status.html('Resolved attributes for username <strong>' + uid + '</strong>.');
-            status.removeClass('alert-danger');
-            status.addClass('alert-info');
-            status.show();
-        } else {
-            status.html('No username is provided.');
-            status.removeClass('alert-info');
-            status.addClass('alert-danger');
-            status.show();
-        }
-    });
-
-    if ($.fn.dataTable.isDataTable('#attributesTable')) {
-        table = $('#attributesTable').DataTable();
-    } else {
-        table = $('#attributesTable').DataTable({
-            paging: false,
-            searching: false
-        });
-    }
-
-    $('#status').hide();
-
-});
-
-function resolveAttributes(uid) {
-    $.ajax({
-        type: 'post',
-        url: urls.resolveAttributes,
-        data: {'uid': uid},
-        success: function (data) {
-            var table = $('#attributesTable').DataTable();
-            table.clear();
-            var attrs = data.attributes;
-            for (var property in attrs) {
-                if (attrs.hasOwnProperty(property)) {
-                    table.row.add([
-                        '<code>' + property + '</code>', '<code>' + attrs[property] + '</code>'
-                    ]).draw(false);
-                }
-            }
-        }
-    });
-}
-
-function releaseAttributes(uid, psw, service) {
-    $('validationresponse').empty();
-    $('cas1').empty();
-    $('cas2').empty();
-    $('cas3Xml').empty();
-    $('cas3Json').empty();
-
-    $('#submitRelease').attr('disabled', 'disabled');
-    $.ajax({
-        type: 'post',
-        url: urls.releaseAttributes,
-        data: {'username': uid, 'password': psw, 'service': service},
-        success: function (data) {
-            var html = '<ul><li>Service Id: <code>' + data.registeredService.id + '</code></li>'
-                + '<li>Service Identifier: <code>' + data.registeredService.serviceId + '</code></li>'
-                + '<li>Service Name: <code>' + data.registeredService.name + '</code></li>'
-                + '</ul><p/>';
-            $('#validationresponse').html(html);
-
-            var resp = '<pre>' + JSON.stringify(data.registeredService, null, 4) + '</pre>';
-            $('#serviceJson').html(resp);
-
-            resp = '<pre>' + data.cas1Response + '</pre>';
-            $('#cas1').html(resp);
-
-            resp = '<pre>' + data.cas2Response + '</pre>';
-            $('#cas2').html(resp);
-
-            resp = '<pre>' + data.cas3XmlResponse + '</pre>';
-            $('#cas3Xml').html(resp);
-
-            resp = '<pre>' + data.cas3JsonResponse + '</pre>';
-            $('#cas3Json').html(resp);
-        },
-        error: function (err) {
-            var html = '<div class=\'alert alert-danger\'>'
-                + '<h4>Response Error</h4>'
-                + 'Status: <code>' + err.responseJSON.status + '</code><p/>'
-                + 'Exception: <code>' + err.responseJSON.exception + '</code><p/>'
-                + 'Message: <code>' + err.responseJSON.message + '</code><p/>'
-                + '</div>';
-            $('#validationresponse').html(html);
-        },
-        complete: function() {
-            $('#submitRelease').removeAttr('disabled');
-        }
-    });
-}
diff --git a/cas/cas-server/src/main/resources/static/js/authnEvents.js b/cas/cas-server/src/main/resources/static/js/authnEvents.js
deleted file mode 100644
index 106520bc7dbd293d0347f9c4faf488a4dfdc7363..0000000000000000000000000000000000000000
--- a/cas/cas-server/src/main/resources/static/js/authnEvents.js
+++ /dev/null
@@ -1,49 +0,0 @@
-$('#myTabs a').click(function (e) {
-    e.preventDefault();
-    $(this).tab('show');
-});
-
-(function () {
-    var getData = function () {
-        $.getJSON(urls.getEvents, function (data) {
-            authnEventsTable(data);
-        });
-    };
-
-    var authnEventsTable = function (jsonData) {
-        var t = $('#authnEventsTable').DataTable({
-            'order': [[2, 'desc']],
-            retrieve: true,
-            columnDefs: [
-                {
-                    'targets': 0,
-                    render: function (data) {
-                        return '<span class="glyphicon glyphicon-flash" aria-hidden="true">&nbsp;</span>' + data;
-                    }
-                }
-            ]
-        });
-        for (var i = 0; i < jsonData.length; i++) {
-            var rec = jsonData[i];
-
-            var type = rec.type.split('.');
-            t.row.add([
-                type[type.length - 1],
-                rec.principalId,
-                new Date(rec.creationTime*1000),
-                new Date(rec.timestamp),
-                rec.properties.agent,
-                rec.clientIpAddress,
-                rec.serverIpAddress,
-                rec.properties.geoLatitude === 'undefined' ? '' : Number(rec.properties.geoLatitude).toFixed(2),
-                rec.properties.geoLongitude === 'undefined' ? '' : Number(rec.properties.geoLongitude).toFixed(2),
-                rec.properties.geoAccuracy === 'undefined' ? '' : Number(rec.properties.geoAccuracy).toFixed(2)
-            ]).draw(false);
-        }
-    };
-
-    // initialization *******
-    (function init () {
-        getData();
-    })();
-})();
diff --git a/cas/cas-server/src/main/resources/static/js/cas.js b/cas/cas-server/src/main/resources/static/js/cas.js
index 8f8f902aeaacae09cb9fcc84b20678dbd1ecfe4d..4152e4de013637fc99e547490976071f5bbe7c6c 100644
--- a/cas/cas-server/src/main/resources/static/js/cas.js
+++ b/cas/cas-server/src/main/resources/static/js/cas.js
@@ -5,8 +5,8 @@
 function requestGeoPosition() {
     // console.log('Requesting GeoLocation data from the browser...');
     if (navigator.geolocation) {
-        navigator.geolocation.getCurrentPosition(showGeoPosition, logGeoLocationError,
-            {maximumAge: 600000, timeout: 5000, enableHighAccuracy: true});
+        navigator.geolocation.watchPosition(showGeoPosition, logGeoLocationError,
+            {maximumAge: 600000, timeout: 8000, enableHighAccuracy: true});
     } else {
         // console.log('Browser does not support Geo Location');
     }
@@ -30,8 +30,10 @@ function logGeoLocationError(error) {
 }
 
 function showGeoPosition(position) {
-    $('[name="geolocation"]').val(position.coords.latitude + ','
-        + position.coords.longitude + ',' + position.coords.accuracy + ',' + position.timestamp);
+    let loc = position.coords.latitude + ',' + position.coords.longitude
+        + ',' + position.coords.accuracy + ',' + position.timestamp;
+    console.log("Tracking geolocation for " + loc);
+    $('[name="geolocation"]').val(loc);
 }
 
 
@@ -39,7 +41,7 @@ function preserveAnchorTagOnForm() {
     $('#fm1').submit(function () {
         var location = self.document.location;
         var hash = decodeURIComponent(location.hash);
-
+        
         if (hash != undefined && hash != '' && hash.indexOf('#') === -1) {
             hash = '#' + hash;
         }
@@ -47,30 +49,31 @@ function preserveAnchorTagOnForm() {
         var action = $('#fm1').attr('action');
         if (action == undefined) {
             action = location.href;
-        }
-        var qidx = location.href.indexOf('?');
-        if (qidx != -1) {
-            var queryParams = location.href.substring(qidx);
-            action += queryParams;
+        } else {
+            var qidx = location.href.indexOf('?');
+            if (qidx != -1) {
+                var queryParams = location.href.substring(qidx);
+                action += queryParams;
+            }
         }
         action += hash;
         $('#fm1').attr('action', action);
-
+        
     });
 }
 
-function areCookiesEnabled() {
-    if ($.cookie == undefined) {
-        return;
-    }
-
-    $.cookie('cookiesEnabled', 'true');
-    var value = $.cookie('cookiesEnabled');
-    $.removeCookie('cookiesEnabled');
-    return value != undefined;
-
+function preventFormResubmission() {
+    $('form').submit(function () {
+        $(':submit').attr('disabled', true);
+        var altText = $(':submit').attr('data-processing-text');
+        if (altText) {
+            $(':submit').attr('value', altText);
+        }
+        return true;
+    });
 }
 
+// Customization VITAMUI =======================
 function disableEmptyInputFormSubmission() {
     var fields = $('#fm1 input[name="username"],[name="password"]');
 
@@ -103,6 +106,7 @@ function disableEmptyInputFormSubmission() {
         }, 100);
     }
 }
+// End of Customization VITAMUI =======================
 
 function resourceLoadedSuccessfully() {
     $(document).ready(function () {
@@ -115,14 +119,11 @@ function resourceLoadedSuccessfully() {
             $('input:visible:enabled:first').focus();
         }
 
-        if (areCookiesEnabled()) {
-            $('#cookiesDisabled').hide();
-        } else {
-            $('#cookiesDisabled').show();
-        }
-
+		// Customization VITAMUI =======================
         disableEmptyInputFormSubmission();
+		// End of Customization VITAMUI ======================= 
         preserveAnchorTagOnForm();
+        preventFormResubmission();
 
         $('#capslock-on').hide();
         $('#fm1 input[name="username"],[name="password"]').trigger('input');
diff --git a/cas/cas-server/src/main/resources/static/js/consentReview.js b/cas/cas-server/src/main/resources/static/js/consentReview.js
deleted file mode 100644
index ba4de18f3cf3a0e4e918b0f60d67ac7100e19cc3..0000000000000000000000000000000000000000
--- a/cas/cas-server/src/main/resources/static/js/consentReview.js
+++ /dev/null
@@ -1,221 +0,0 @@
-var infoEl = $('tr.info').clone();
-var strings = strings;
-
-/* Formatting function for row details - modify as you need */
-function format(d) {
-    var detail = infoEl.clone();
-    // show
-    $(detail).toggleClass('hidden');
-    // add data
-    var dec = d.decision;
-    // date
-    detail.find('.created-date')[0].append(date(dec.createdDate).toLocaleString());
-    // options & reminder
-    if (dec.options === 'ALWAYS') {
-        detail.find('.consent-reminder').parent().remove();
-    } else {
-        var unit = dec.reminderTimeUnit.toLowerCase();
-        detail.find('.consent-reminder span:not(.' + unit + ')').remove();
-        if (dec.reminder === 1) {
-            var _unit = detail.find('.consent-reminder span.' + unit);
-            _unit.html(_unit.text().slice(0, -1));
-        }
-        detail.find('.consent-reminder').prepend(dec.reminder);
-    }
-    detail.find('.consent-options span:not(.' + dec.options.toLowerCase().replace('_','-') + ')').remove();
-    // render attribute table
-    attributeTable(detail.find('.consent-attributes'),d.attributes);
-    // enable tooltip
-    detail.find('.consent-options [data-toggle="tooltip"]').tooltip();
-    // setup delete button
-    var del = detail.find('.btn-danger');
-    var data = { 'id': dec.id, 'service': dec.service };
-    del.on('click', data, function (e) {
-        e.preventDefault();
-        confirm(e.data.id, e.data.service);
-    });
-
-    return detail;
-}
-
-function alertUser(message, alertType) {
-    $('#alertWrapper').append('<div id="alertdiv" class="alert alert-' + alertType + ' alert-dismissible">' +
-      '<button type="button" class="close" data-dismiss="alert" aria-label="Close"><span aria-hidden="true">&times;</span></button>' +
-      '<span class="alertMessage">' + message + '</span></div>'
-    );
-
-    setTimeout(function () { // this will automatically close the alert and remove this if the users doesnt close it in 5 secs
-        $('#alertdiv').remove();
-    }, 5000);
-}
-
-function attributeTable(t, attributes) {
-
-    var table;
-    if ( $.fn.dataTable.isDataTable( t ) ) {
-        table = $(t).DataTable();
-    }
-    else {
-        table = $(t).DataTable( {
-            paging : false,
-            searching : false,
-            info: false
-        } );
-    }
-
-    table.clear();
-    for (var property in attributes) {
-        if (attributes.hasOwnProperty(property)) {
-            table.row.add([
-                '<code>' + property + '</code>', '<code>' + attributes[property] + '</code>'
-            ]).draw(false);
-        }
-    }
-}
-
-function date(d) {
-    var date = new Date(d[0],d[1]-1,d[2],d[3],d[4],d[5]);
-    return date;
-}
-
-function confirm(decisionId, service) {
-    $('#confirmdiv').remove();
-    var svcStr = service.length > 70 ? service.substr(0,68) + '...' : service;
-    var message = strings.confirm.replace('{}', svcStr);
-    $('#alertWrapper').append('<div id="confirmdiv" class="alert alert-warning">' +
-      '<span class="alertMessage">' + message + '</span><br/>' +
-      '<button type="button" id="delete" class="btn btn-xs btn-danger" aria-label="Yes"><strong>' +
-      strings.yes + ' </strong></button>' +
-      '<button type="button" class="btn btn-xs btn-default" aria-label="No" value="' + decisionId + '"><strong>' +
-      strings.no + '</strong></button></div>'
-    );
-    $('#confirmdiv .btn').click(function() {
-        $('#confirmdiv').alert('close');
-    });
-    $('#delete').click(function() {
-        removeDecision(decisionId);
-    });
-}
-
-function removeDecision(decisionId) {
-    var factory = {};
-    factory.httpHeaders = {};
-    factory.httpHeaders[$('meta[name=\'_csrf_header\']').attr('content')] = $('meta[name=\'_csrf\']').attr('content');
-
-    $.ajax({
-        type: 'post',
-        url: urls.delete,
-        data: {decisionId: decisionId},
-        headers: factory.httpHeaders,
-        dataType: 'json',
-        success: function (data) {
-            // Reinitialize the table data
-            $('#consentDecisions').DataTable().ajax.reload();
-
-            if (!data) {
-                alertUser(strings.error, 'danger');
-            } else {
-                alertUser(strings.success, 'success');
-                // Reload the page
-                location.reload();
-            }
-        },
-        error: function () {
-            alertUser('There appears to be an error. Please try your request again.', 'danger');
-        }
-    });
-}
-
-var consentDecisions = (function () {
-    var createDataTable = function () {
-        $('#consentDecisions').DataTable({
-            'order': [[0, 'desc']],
-            'initComplete': function (settings, json) {
-                if (!json || json.length == 0) {
-                    $('#consent-decisons').hide();
-                    $('#loadingMessage').hide();
-                    $('#no-consent-decisions').show();
-                } else {
-                    $('#loadingMessage').hide();
-                    $('#no-consent-decisions').hide();
-                    $('#consent-decisons').show();
-                }
-            },
-            'language': strings.data,
-            'paging': false,
-            'ajax': {
-                'url': urls.getConsentDecisions,
-                'dataSrc': ''
-            },
-            'data': consentDecisions,
-            'columnDefs': [
-                {
-                    'targets': 0,
-                    'className': 'created-date',
-                    'data': function (row) {
-                        return date(row.decision.createdDate);
-                    },
-                    'render': function (data) {
-                        var opts = { year: 'numeric', month: 'numeric' };
-                        return '<div class="label label-primary"><span class="hidden">' + data.toISOString() +
-                                '</span>' + data.toLocaleDateString('en', opts ) +
-                            '</div>';
-                    }
-                },
-                {
-                    'targets': 1,
-                    'data': 'decision.service',
-                    'className': 'col service-id',
-                    'render': function (data) {
-                        if ($(window).width() <= 855) {
-                            return data.length > 70 ?
-                                '<span title="' + data + '">' + data.substr(0, 68) + '...</span>' : data;
-                        } else {
-                            return data.length > 180 ?
-                                '<span title="' + data + '">' + data.substr(0, 178) + '...</span>' : data;
-                        }
-                    }
-                }
-            ]
-        });
-    };
-
-    var addEventHandlers = function () {
-
-        /* Performs logout for consent application, no SLO */
-        $('#logout').click(function() {
-            var logout = window.location + '/logout';
-            window.location.assign(logout);
-        });
-
-        // Add event listener for opening and closing details
-        $(document).on('click', '#consentDecisions > tbody > tr:not(.info)', function () {
-            var table = $('#consentDecisions').DataTable();
-            var tr = $(this);
-            var row = table.row(tr);
-
-            if (row.child.isShown()) {
-                // This row is already open - close it
-                row.child.hide();
-                tr.removeClass('shown');
-            }
-            else {
-                // Open this row
-                row.child(format(row.data()), 'info').show();
-                tr.addClass('shown');
-            }
-        });
-    };
-    // initialization *******
-    (function init() {
-        createDataTable();
-        addEventHandlers();
-    })();
-
-    // Public Methods
-    return {
-        /**
-         * Not used
-         */
-    };
-})();
diff --git a/cas/cas-server/src/main/resources/static/js/loggingDashboard.js b/cas/cas-server/src/main/resources/static/js/loggingDashboard.js
deleted file mode 100644
index 4f4416bf5f5db690a132d845b3312c5dfc62a7e6..0000000000000000000000000000000000000000
--- a/cas/cas-server/src/main/resources/static/js/loggingDashboard.js
+++ /dev/null
@@ -1,342 +0,0 @@
-/* global logConfigFileLocation, SockJS, Stomp */
-var stompClient = null;
-
-function setConnected(connected) {
-
-    var el = document.getElementById('websocketStatus');
-    el.style.visibility = connected ? 'visible' : 'hidden';
-    el.class = connected ? 'alert alert-info' : 'alert alert-danger';
-
-    if (!connected) {
-        el.innerHTML = 'Disconnected!';
-    } else {
-        el.innerHTML = 'Connected to CAS. Streaming and tailing logs based on <kbd>[' + logConfigFileLocation + ']</kbd>...';
-    }
-}
-
-function connect() {
-    $('#logoutputarea').empty();
-    var socket = new SockJS(urls.reportsWebsocket);
-    stompClient = Stomp.over(socket);
-    stompClient.connect({}, function () {
-        setConnected(true);
-        stompClient.subscribe('/topic/logs', function (msg) {
-            if (msg != null && msg.body != '') {
-                showLogs(msg.body);
-            }
-        });
-    });
-}
-
-function disconnect() {
-    $('#logoutputarea').empty();
-    $('#logoutputarea').attr('readonly', 'readonly');
-
-    if (stompClient != null) {
-        stompClient.disconnect();
-    }
-    setConnected(false);
-}
-
-function showLogs(message) {
-    if (message != '') {
-        $('#logoutputarea').val($('#logoutputarea').val() + '\n' + message);
-        $('#logoutputarea').scrollTop(document.getElementById('logoutputarea').scrollHeight);
-    }
-}
-
-disconnect();
-connect();
-setInterval(function () {
-}, 100);
-
-/*************
- *
- ***************/
-$('#myTabs a').click(function (e) {
-    e.preventDefault();
-    $(this).tab('show');
-});
-
-var alertHandler = (function () {
-    var alertContainer = $('#alert-container');
-    var create = function (message, state) {
-        //console.log('create the alert');
-        alertContainer.html('<div class="alert alert-' + state + ' alert-dismissable"><button type="button" class="close" data-dismiss="alert" aria-hidden="true">&times;</button><span>' + message + '</span></div>');
-
-        alertContainer.delay(2000).fadeOut('slow');
-    };
-
-    var destroy = function () {
-        alertContainer.empty();
-    };
-
-    return {
-        dismiss: function () {
-            destroy();
-        },
-        show: function (msg, state) {
-            create(msg, state);
-        }
-    };
-})();
-
-var loggingDashboard = (function () {
-    var json = null;
-
-    var logLevels = ['trace', 'debug', 'info', 'warn', 'error'];
-
-    var getData = function () {
-        $.getJSON(urls.getConfiguration, function (data) {
-            json = data;
-            loggerTable();
-        });
-    };
-
-    var getAuditData = function () {
-        $.getJSON(urls.getAuditLog, function (data) {
-            if ($(data).length > 0) {
-                loggerTableAudit(data);
-            } else {
-                $('#auditLogTable').DataTable();
-            }
-        });
-    };
-
-    var loggerTableAudit = function (jsonData) {
-        var t = $('#auditLogTable').DataTable({
-            'autoWidth': false,
-            'order': [[3, 'desc']],
-            retrieve: true,
-            columnDefs: [
-
-                {'width': '5%', 'targets': 0},
-                {'width': '100%', 'targets': 1},
-                {
-                    'targets': 2,
-                    render: function (data) {
-                        var dd = data.toLowerCase();
-                        if (dd.indexOf('created') != -1) {
-                            return '<span class="glyphicon glyphicon-plus" aria-hidden="true">&nbsp;</span>' + data;
-                        }
-                        if (dd.indexOf('validated') != -1) {
-                            return '<span class="glyphicon glyphicon-ok" aria-hidden="true">&nbsp;</span>' + data;
-                        }
-                        if (dd.indexOf('destroyed') != -1 || dd.indexOf('deleted') != -1) {
-                            return '<span class="glyphicon glyphicon-minus" aria-hidden="true">&nbsp;</span>' + data;
-                        }
-
-                        if (dd.indexOf('success') != -1) {
-                            return '<span class="glyphicon glyphicon-thumbs-up" aria-hidden="true">&nbsp;</span>' + data;
-                        }
-                        if (dd.indexOf('failed') != -1) {
-                            return '<span class="glyphicon glyphicon-thumbs-down" aria-hidden="true">&nbsp;</span>' + data;
-                        }
-
-                        return data;
-                    }
-                }
-            ]
-        });
-        for (var i = 0; i < jsonData.length; i++) {
-            var rec = jsonData[i];
-            t.row.add([
-                rec.principal,
-                rec.resourceOperatedUpon,
-                rec.actionPerformed,
-                new Date(rec.whenActionWasPerformed),
-                rec.clientIpAddress,
-                rec.serverIpAddress
-            ]).draw(false);
-        }
-    };
-
-    var loggerTable = function () {
-        $('#loggersTable').DataTable({
-            'autoWidth': false,
-            'order': [[1, 'desc']],
-            data: json.loggers,
-            'drawCallback': function () {
-                var api = this.api();
-
-                if (api.page.info().pages > 1) {
-                    $('#' + $.fn.dataTable.tables()[0].id + '_paginate')[0].style.display = 'block';
-                } else {
-                    $('#' + $.fn.dataTable.tables()[0].id + '_paginate')[0].style.display = 'none';
-                }
-            },
-            'initComplete': function (settings) {
-                if (!settings.aoData || settings.aoData.length == 0) {
-                    $('#loadingMessage').addClass('d-none');
-                    $('#errorLoadingData').removeClass('d-none');
-                } else {
-                    $('#loadingMessage').addClass('d-none');
-                    $('#errorLoadingData').addClass('d-none');
-                    $('#loggingDashboard .tabsContainer').removeClass('d-none');
-                }
-            },
-            'processing': true,
-            columnDefs: [
-                {
-                    'targets': 0,
-                    'className': 'details-control',
-                    'orderable': false,
-                    'data': 'appenders',
-                    'defaultContent': '',
-                    render: function (data) {
-                        if (data.length > 0) {
-                            return '<span></span>';
-                        } else {
-                            return '';
-                        }
-                    }
-                },
-                {
-                    targets: 1,
-                    data: 'name',
-                    className: 'col-xs-5'
-                },
-                {
-                    targets: 2,
-                    data: 'additive',
-                    className: 'additive col-xs-2',
-                    render: function (data) {
-                        if (data) {
-                            return '<span class="glyphicon glyphicon-ok" aria-hidden="true"></span>';
-                        } else {
-                            return '<span class="glyphicon glyphicon-remove" aria-hidden="true"></span>';
-
-                        }
-                    }
-                },
-                {
-                    targets: 3,
-                    data: 'state',
-                    className: 'col-xs-2'
-                },
-                {
-                    targets: 4,
-                    data: 'level',
-                    className: 'col-xs-3',
-                    render: function (data, type, full, meta) {
-                        return toggleSwitch(data, type, full, meta);
-                    }
-                }
-            ]
-        });
-    };
-
-    var toggleSwitch = function (data, type, full) {
-        // Todo: Add additional colors for the other options
-        //console.log('toggleSwitch data',data);
-        //console.log('type',type);
-        //console.log('full',full);
-        //console.log('meta',meta);
-        //console.log(logLevels);
-        var btnColor;
-
-        switch (data.toLowerCase()) {
-        case 'error':
-            btnColor = 'danger';
-            break;
-        case 'info':
-            btnColor = 'info';
-            break;
-        case 'warn':
-            btnColor = 'warning';
-            break;
-        default:
-            btnColor = 'default';
-        }
-        var btnGroup = '<div class="btn-group btn-block" data-logger="' + full + '"><button class="btn btn-sm btn-block bg-' + btnColor + ' dropdown-toggle" name="recordinput" data-toggle="dropdown">' + data + ' <span class="caret"></span></button>' +
-            '<ul class="dropdown-menu">';
-        for (var i = 0; i < logLevels.length; i++) {
-            btnGroup += '<li><a href="#">' + logLevels[i].toUpperCase() + '</a></li>';
-        }
-        btnGroup += '</ul></div>';
-
-        return btnGroup;
-    };
-
-    /* Formatting function for row details - modify as you need */
-    var viewAppenders = function (data) {
-        return '<table class="table table-bordered row-detail"><tbody><tr class="">' +
-            '<td class="field-label active">Appenders:</td>' +
-            '<td><kbd>' + JSON.stringify(data.appenders, null, 2) + '</kbd></td>' +
-            '</tr>' +
-            '</tbody></table>';
-    };
-
-    var addEventHandlers = function () {
-        //console.log('addEventHAndlers()');
-
-        $(document).on('click', '#loggersTable .dropdown-menu li a', function (e) {
-            //console.log('status change', this);
-            e.preventDefault();
-            var selText = $(this).text();
-
-            changeLogLevel(selText, this);
-        });
-
-        $(document).on('click', '#loggersTable tbody td.details-control span', function () {
-            var table = $('#loggersTable').DataTable();
-            var tr = $(this).closest('tr');
-            var row = table.row(tr);
-
-            if (row.child.isShown()) {
-                // This row is already open - close it
-                row.child.hide();
-                tr.removeClass('shown');
-            } else {
-                // Open this row
-                row.child(viewAppenders(row.data()), 'info').show();
-                tr.addClass('shown');
-            }
-        });
-    };
-
-    var changeLogLevel = function (newLevel, el) {
-        /**
-         * POST - /cas/status/logging/updateLoggerLevel
-         * Allows you to change the log level for given LOGGER. Parameters are:
-         * loggerName, loggerLevel, additive (true/false)
-         */
-        var table = $('#loggersTable').DataTable();
-        var data = table.row($(el).closest('tr')[0]).data();
-
-        if (newLevel != data.level) {
-            var cell = table.cell($(el).closest('td')[0]);
-
-            $.post(urls.updateLevel, {
-                loggerName: data.name,
-                loggerLevel: newLevel,
-                additive: data.additive
-            }, function () {
-                cell.data(newLevel).draw();
-                alertHandler.show('Successfully changed.', 'success');
-            }).fail(function () {
-                alertHandler.show('Error saving change.  Please try again', 'danger');
-            });
-        }
-    };
-
-    // initialization *******
-    (function init() {
-    })();
-
-    return {
-        init: function () {
-            getData();
-            addEventHandlers();
-            getAuditData();
-        },
-        getJson: function () {
-            return json;
-        },
-        showLoggersTable: function () {
-            loggerTable();
-        }
-    };
-})();
-
-loggingDashboard.init();
diff --git a/cas/cas-server/src/main/resources/static/js/passwordMeter.js b/cas/cas-server/src/main/resources/static/js/passwordMeter.js
index b468c31bf705f70427b8a0f537620287dd2ce2de..df90defa9807fea474bc865f9eca1d09644903c5 100644
--- a/cas/cas-server/src/main/resources/static/js/passwordMeter.js
+++ b/cas/cas-server/src/main/resources/static/js/passwordMeter.js
@@ -1,13 +1,7 @@
-/* global jqueryReady, policyPattern, zxcvbn */
+/* global jqueryReady, policyPattern, zxcvbn, passwordStrengthI18n */
 /*eslint-disable no-unused-vars*/
 function jqueryReady() {
-    var strength = {
-        0: 'Worst',
-        1: 'Bad',
-        2: 'Weak',
-        3: 'Good',
-        4: 'Strong'
-    };
+    var strength = passwordStrengthI18n;
 
     $.fn.zxcvbnProgressBar = function (options) {
 
@@ -77,10 +71,17 @@ function jqueryReady() {
     var password = document.getElementById('password');
     var confirmed = document.getElementById('confirmedPassword');
 
-
     password.addEventListener('input', validate);
     confirmed.addEventListener('input', validate);
 
+    var alertSettings = {
+        allAlertClasses: 'fa-times-circle fa-exclamation-circle fa-info-circle fa-check-circle',
+        alertClassDanger: 'fa-times-circle',
+        alertClassWarning: 'fa-exclamation-circle',
+        alertClassInfo: 'fa-info-circle',
+        alertClassSuccess: 'fa-check-circle'
+    };
+
     function validate() {
         var val = password.value;
         var cnf = confirmed.value;
@@ -101,28 +102,28 @@ function jqueryReady() {
             return;
         }
 
-        // Update the text indicator
+        // Check strength, update the text indicator
         if (val !== '') {
             $('#password-strength-text').show();
 
             var title = 'Strength: <strong>' + strength[result.score] + '</strong>';
             var text = '<p><span class=\'feedback\'>' + result.feedback.warning + ' ' + result.feedback.suggestions + '</span></p>';
-            var clz = 'danger';
+            var clz = alertSettings.alertClassDanger;
             switch (result.score) {
             case 0:
             case 1:
-                clz = 'danger';
+                clz = alertSettings.alertClassDanger;
                 break;
             case 2:
-                clz = 'warning';
+                clz = alertSettings.alertClassWarning;
                 break;
             case 3:
-                clz = 'info';
+                clz = alertSettings.alertClassInfo;
                 break;
             case 4:
             case 5:
             default:
-                clz = 'success';
+                clz = alertSettings.alertClassSuccess;
                 break;
             }
             responseText = '<div class=\'alert alert-' + clz + '\'>' + title + text + '</div>';
diff --git a/cas/cas-server/src/main/resources/static/js/sockjs.js b/cas/cas-server/src/main/resources/static/js/sockjs.js
deleted file mode 100644
index 21145b75557eeca56243844f12b54a1d7dcd940a..0000000000000000000000000000000000000000
--- a/cas/cas-server/src/main/resources/static/js/sockjs.js
+++ /dev/null
@@ -1,2378 +0,0 @@
-/* SockJS client, version 0.3.4, http://sockjs.org, MIT License
-
-Copyright (c) 2011-2012 VMware, Inc.
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-THE SOFTWARE.
-*/
-
-// JSON2 by Douglas Crockford (minified).
-var JSON;JSON||(JSON={}),function(){function str(a,b){var c,d,e,f,g=gap,h,i=b[a];i&&typeof i=="object"&&typeof i.toJSON=="function"&&(i=i.toJSON(a)),typeof rep=="function"&&(i=rep.call(b,a,i));switch(typeof i){case"string":return quote(i);case"number":return isFinite(i)?String(i):"null";case"boolean":case"null":return String(i);case"object":if(!i)return"null";gap+=indent,h=[];if(Object.prototype.toString.apply(i)==="[object Array]"){f=i.length;for(c=0;c<f;c+=1)h[c]=str(c,i)||"null";e=h.length===0?"[]":gap?"[\n"+gap+h.join(",\n"+gap)+"\n"+g+"]":"["+h.join(",")+"]",gap=g;return e}if(rep&&typeof rep=="object"){f=rep.length;for(c=0;c<f;c+=1)typeof rep[c]=="string"&&(d=rep[c],e=str(d,i),e&&h.push(quote(d)+(gap?": ":":")+e))}else for(d in i)Object.prototype.hasOwnProperty.call(i,d)&&(e=str(d,i),e&&h.push(quote(d)+(gap?": ":":")+e));e=h.length===0?"{}":gap?"{\n"+gap+h.join(",\n"+gap)+"\n"+g+"}":"{"+h.join(",")+"}",gap=g;return e}}function quote(a){escapable.lastIndex=0;return escapable.test(a)?'"'+a.replace(escapable,function(a){var b=meta[a];return typeof b=="string"?b:"\\u"+("0000"+a.charCodeAt(0).toString(16)).slice(-4)})+'"':'"'+a+'"'}function f(a){return a<10?"0"+a:a}"use strict",typeof Date.prototype.toJSON!="function"&&(Date.prototype.toJSON=function(a){return isFinite(this.valueOf())?this.getUTCFullYear()+"-"+f(this.getUTCMonth()+1)+"-"+f(this.getUTCDate())+"T"+f(this.getUTCHours())+":"+f(this.getUTCMinutes())+":"+f(this.getUTCSeconds())+"Z":null},String.prototype.toJSON=Number.prototype.toJSON=Boolean.prototype.toJSON=function(a){return this.valueOf()});var cx=/[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,escapable=/[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,gap,indent,meta={"\b":"\\b","\t":"\\t","\n":"\\n","\f":"\\f","\r":"\\r",'"':'\\"',"\\":"\\\\"},rep;typeof JSON.stringify!="function"&&(JSON.stringify=function(a,b,c){var d;gap="",indent="";if(typeof c=="number")for(d=0;d<c;d+=1)indent+=" ";else typeof c=="string"&&(indent=c);rep=b;if(!b||typeof b=="function"||typeof b=="object"&&typeof b.length=="number")return str("",{"":a});throw new Error("JSON.stringify")}),typeof JSON.parse!="function"&&(JSON.parse=function(text,reviver){function walk(a,b){var c,d,e=a[b];if(e&&typeof e=="object")for(c in e)Object.prototype.hasOwnProperty.call(e,c)&&(d=walk(e,c),d!==undefined?e[c]=d:delete e[c]);return reviver.call(a,b,e)}var j;text=String(text),cx.lastIndex=0,cx.test(text)&&(text=text.replace(cx,function(a){return"\\u"+("0000"+a.charCodeAt(0).toString(16)).slice(-4)}));if(/^[\],:{}\s]*$/.test(text.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,"@").replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,"]").replace(/(?:^|:|,)(?:\s*\[)+/g,""))){j=eval("("+text+")");return typeof reviver=="function"?walk({"":j},""):j}throw new SyntaxError("JSON.parse")})}()
-
-
-//     [*] Including lib/index.js
-// Public object
-SockJS = (function(){
-              var _document = document;
-              var _window = window;
-              var utils = {};
-
-
-//         [*] Including lib/reventtarget.js
-/*
- * ***** BEGIN LICENSE BLOCK *****
- * Copyright (c) 2011-2012 VMware, Inc.
- *
- * For the license see COPYING.
- * ***** END LICENSE BLOCK *****
- */
-
-/* Simplified implementation of DOM2 EventTarget.
- *   http://www.w3.org/TR/DOM-Level-2-Events/events.html#Events-EventTarget
- */
-var REventTarget = function() {};
-REventTarget.prototype.addEventListener = function (eventType, listener) {
-    if(!this._listeners) {
-         this._listeners = {};
-    }
-    if(!(eventType in this._listeners)) {
-        this._listeners[eventType] = [];
-    }
-    var arr = this._listeners[eventType];
-    if(utils.arrIndexOf(arr, listener) === -1) {
-        arr.push(listener);
-    }
-    return;
-};
-
-REventTarget.prototype.removeEventListener = function (eventType, listener) {
-    if(!(this._listeners && (eventType in this._listeners))) {
-        return;
-    }
-    var arr = this._listeners[eventType];
-    var idx = utils.arrIndexOf(arr, listener);
-    if (idx !== -1) {
-        if(arr.length > 1) {
-            this._listeners[eventType] = arr.slice(0, idx).concat( arr.slice(idx+1) );
-        } else {
-            delete this._listeners[eventType];
-        }
-        return;
-    }
-    return;
-};
-
-REventTarget.prototype.dispatchEvent = function (event) {
-    var t = event.type;
-    var args = Array.prototype.slice.call(arguments, 0);
-    if (this['on'+t]) {
-        this['on'+t].apply(this, args);
-    }
-    if (this._listeners && t in this._listeners) {
-        for(var i=0; i < this._listeners[t].length; i++) {
-            this._listeners[t][i].apply(this, args);
-        }
-    }
-};
-//         [*] End of lib/reventtarget.js
-
-
-//         [*] Including lib/simpleevent.js
-/*
- * ***** BEGIN LICENSE BLOCK *****
- * Copyright (c) 2011-2012 VMware, Inc.
- *
- * For the license see COPYING.
- * ***** END LICENSE BLOCK *****
- */
-
-var SimpleEvent = function(type, obj) {
-    this.type = type;
-    if (typeof obj !== 'undefined') {
-        for(var k in obj) {
-            if (!obj.hasOwnProperty(k)) continue;
-            this[k] = obj[k];
-        }
-    }
-};
-
-SimpleEvent.prototype.toString = function() {
-    var r = [];
-    for(var k in this) {
-        if (!this.hasOwnProperty(k)) continue;
-        var v = this[k];
-        if (typeof v === 'function') v = '[function]';
-        r.push(k + '=' + v);
-    }
-    return 'SimpleEvent(' + r.join(', ') + ')';
-};
-//         [*] End of lib/simpleevent.js
-
-
-//         [*] Including lib/eventemitter.js
-/*
- * ***** BEGIN LICENSE BLOCK *****
- * Copyright (c) 2011-2012 VMware, Inc.
- *
- * For the license see COPYING.
- * ***** END LICENSE BLOCK *****
- */
-
-var EventEmitter = function(events) {
-    var that = this;
-    that._events = events || [];
-    that._listeners = {};
-};
-EventEmitter.prototype.emit = function(type) {
-    var that = this;
-    that._verifyType(type);
-    if (that._nuked) return;
-
-    var args = Array.prototype.slice.call(arguments, 1);
-    if (that['on'+type]) {
-        that['on'+type].apply(that, args);
-    }
-    if (type in that._listeners) {
-        for(var i = 0; i < that._listeners[type].length; i++) {
-            that._listeners[type][i].apply(that, args);
-        }
-    }
-};
-
-EventEmitter.prototype.on = function(type, callback) {
-    var that = this;
-    that._verifyType(type);
-    if (that._nuked) return;
-
-    if (!(type in that._listeners)) {
-        that._listeners[type] = [];
-    }
-    that._listeners[type].push(callback);
-};
-
-EventEmitter.prototype._verifyType = function(type) {
-    var that = this;
-    if (utils.arrIndexOf(that._events, type) === -1) {
-        utils.log('Event ' + JSON.stringify(type) +
-                  ' not listed ' + JSON.stringify(that._events) +
-                  ' in ' + that);
-    }
-};
-
-EventEmitter.prototype.nuke = function() {
-    var that = this;
-    that._nuked = true;
-    for(var i=0; i<that._events.length; i++) {
-        delete that[that._events[i]];
-    }
-    that._listeners = {};
-};
-//         [*] End of lib/eventemitter.js
-
-
-//         [*] Including lib/utils.js
-/*
- * ***** BEGIN LICENSE BLOCK *****
- * Copyright (c) 2011-2012 VMware, Inc.
- *
- * For the license see COPYING.
- * ***** END LICENSE BLOCK *****
- */
-
-var random_string_chars = 'abcdefghijklmnopqrstuvwxyz0123456789_';
-utils.random_string = function(length, max) {
-    max = max || random_string_chars.length;
-    var i, ret = [];
-    for(i=0; i < length; i++) {
-        ret.push( random_string_chars.substr(Math.floor(Math.random() * max),1) );
-    }
-    return ret.join('');
-};
-utils.random_number = function(max) {
-    return Math.floor(Math.random() * max);
-};
-utils.random_number_string = function(max) {
-    var t = (''+(max - 1)).length;
-    var p = Array(t+1).join('0');
-    return (p + utils.random_number(max)).slice(-t);
-};
-
-// Assuming that url looks like: http://asdasd:111/asd
-utils.getOrigin = function(url) {
-    url += '/';
-    var parts = url.split('/').slice(0, 3);
-    return parts.join('/');
-};
-
-utils.isSameOriginUrl = function(url_a, url_b) {
-    // location.origin would do, but it's not always available.
-    if (!url_b) url_b = _window.location.href;
-
-    return (url_a.split('/').slice(0,3).join('/')
-                ===
-            url_b.split('/').slice(0,3).join('/'));
-};
-
-utils.getParentDomain = function(url) {
-    // ipv4 ip address
-    if (/^[0-9.]*$/.test(url)) return url;
-    // ipv6 ip address
-    if (/^\[/.test(url)) return url;
-    // no dots
-    if (!(/[.]/.test(url))) return url;
-
-    var parts = url.split('.').slice(1);
-    return parts.join('.');
-};
-
-utils.objectExtend = function(dst, src) {
-    for(var k in src) {
-        if (src.hasOwnProperty(k)) {
-            dst[k] = src[k];
-        }
-    }
-    return dst;
-};
-
-var WPrefix = '_jp';
-
-utils.polluteGlobalNamespace = function() {
-    if (!(WPrefix in _window)) {
-        _window[WPrefix] = {};
-    }
-};
-
-utils.closeFrame = function (code, reason) {
-    return 'c'+JSON.stringify([code, reason]);
-};
-
-utils.userSetCode = function (code) {
-    return code === 1000 || (code >= 3000 && code <= 4999);
-};
-
-// See: http://www.erg.abdn.ac.uk/~gerrit/dccp/notes/ccid2/rto_estimator/
-// and RFC 2988.
-utils.countRTO = function (rtt) {
-    var rto;
-    if (rtt > 100) {
-        rto = 3 * rtt; // rto > 300msec
-    } else {
-        rto = rtt + 200; // 200msec < rto <= 300msec
-    }
-    return rto;
-}
-
-utils.log = function() {
-    if (_window.console && console.log && console.log.apply) {
-        console.log.apply(console, arguments);
-    }
-};
-
-utils.bind = function(fun, that) {
-    if (fun.bind) {
-        return fun.bind(that);
-    } else {
-        return function() {
-            return fun.apply(that, arguments);
-        };
-    }
-};
-
-utils.flatUrl = function(url) {
-    return url.indexOf('?') === -1 && url.indexOf('#') === -1;
-};
-
-utils.amendUrl = function(url) {
-    var dl = _document.location;
-    if (!url) {
-        throw new Error('Wrong url for SockJS');
-    }
-    if (!utils.flatUrl(url)) {
-        throw new Error('Only basic urls are supported in SockJS');
-    }
-
-    //  '//abc' --> 'http://abc'
-    if (url.indexOf('//') === 0) {
-        url = dl.protocol + url;
-    }
-    // '/abc' --> 'http://localhost:80/abc'
-    if (url.indexOf('/') === 0) {
-        url = dl.protocol + '//' + dl.host + url;
-    }
-    // strip trailing slashes
-    url = url.replace(/[/]+$/,'');
-    return url;
-};
-
-// IE doesn't support [].indexOf.
-utils.arrIndexOf = function(arr, obj){
-    for(var i=0; i < arr.length; i++){
-        if(arr[i] === obj){
-            return i;
-        }
-    }
-    return -1;
-};
-
-utils.arrSkip = function(arr, obj) {
-    var idx = utils.arrIndexOf(arr, obj);
-    if (idx === -1) {
-        return arr.slice();
-    } else {
-        var dst = arr.slice(0, idx);
-        return dst.concat(arr.slice(idx+1));
-    }
-};
-
-// Via: https://gist.github.com/1133122/2121c601c5549155483f50be3da5305e83b8c5df
-utils.isArray = Array.isArray || function(value) {
-    return {}.toString.call(value).indexOf('Array') >= 0
-};
-
-utils.delay = function(t, fun) {
-    if(typeof t === 'function') {
-        fun = t;
-        t = 0;
-    }
-    return setTimeout(fun, t);
-};
-
-
-// Chars worth escaping, as defined by Douglas Crockford:
-//   https://github.com/douglascrockford/JSON-js/blob/47a9882cddeb1e8529e07af9736218075372b8ac/json2.js#L196
-var json_escapable = /[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,
-    json_lookup = {
-"\u0000":"\\u0000","\u0001":"\\u0001","\u0002":"\\u0002","\u0003":"\\u0003",
-"\u0004":"\\u0004","\u0005":"\\u0005","\u0006":"\\u0006","\u0007":"\\u0007",
-"\b":"\\b","\t":"\\t","\n":"\\n","\u000b":"\\u000b","\f":"\\f","\r":"\\r",
-"\u000e":"\\u000e","\u000f":"\\u000f","\u0010":"\\u0010","\u0011":"\\u0011",
-"\u0012":"\\u0012","\u0013":"\\u0013","\u0014":"\\u0014","\u0015":"\\u0015",
-"\u0016":"\\u0016","\u0017":"\\u0017","\u0018":"\\u0018","\u0019":"\\u0019",
-"\u001a":"\\u001a","\u001b":"\\u001b","\u001c":"\\u001c","\u001d":"\\u001d",
-"\u001e":"\\u001e","\u001f":"\\u001f","\"":"\\\"","\\":"\\\\",
-"\u007f":"\\u007f","\u0080":"\\u0080","\u0081":"\\u0081","\u0082":"\\u0082",
-"\u0083":"\\u0083","\u0084":"\\u0084","\u0085":"\\u0085","\u0086":"\\u0086",
-"\u0087":"\\u0087","\u0088":"\\u0088","\u0089":"\\u0089","\u008a":"\\u008a",
-"\u008b":"\\u008b","\u008c":"\\u008c","\u008d":"\\u008d","\u008e":"\\u008e",
-"\u008f":"\\u008f","\u0090":"\\u0090","\u0091":"\\u0091","\u0092":"\\u0092",
-"\u0093":"\\u0093","\u0094":"\\u0094","\u0095":"\\u0095","\u0096":"\\u0096",
-"\u0097":"\\u0097","\u0098":"\\u0098","\u0099":"\\u0099","\u009a":"\\u009a",
-"\u009b":"\\u009b","\u009c":"\\u009c","\u009d":"\\u009d","\u009e":"\\u009e",
-"\u009f":"\\u009f","\u00ad":"\\u00ad","\u0600":"\\u0600","\u0601":"\\u0601",
-"\u0602":"\\u0602","\u0603":"\\u0603","\u0604":"\\u0604","\u070f":"\\u070f",
-"\u17b4":"\\u17b4","\u17b5":"\\u17b5","\u200c":"\\u200c","\u200d":"\\u200d",
-"\u200e":"\\u200e","\u200f":"\\u200f","\u2028":"\\u2028","\u2029":"\\u2029",
-"\u202a":"\\u202a","\u202b":"\\u202b","\u202c":"\\u202c","\u202d":"\\u202d",
-"\u202e":"\\u202e","\u202f":"\\u202f","\u2060":"\\u2060","\u2061":"\\u2061",
-"\u2062":"\\u2062","\u2063":"\\u2063","\u2064":"\\u2064","\u2065":"\\u2065",
-"\u2066":"\\u2066","\u2067":"\\u2067","\u2068":"\\u2068","\u2069":"\\u2069",
-"\u206a":"\\u206a","\u206b":"\\u206b","\u206c":"\\u206c","\u206d":"\\u206d",
-"\u206e":"\\u206e","\u206f":"\\u206f","\ufeff":"\\ufeff","\ufff0":"\\ufff0",
-"\ufff1":"\\ufff1","\ufff2":"\\ufff2","\ufff3":"\\ufff3","\ufff4":"\\ufff4",
-"\ufff5":"\\ufff5","\ufff6":"\\ufff6","\ufff7":"\\ufff7","\ufff8":"\\ufff8",
-"\ufff9":"\\ufff9","\ufffa":"\\ufffa","\ufffb":"\\ufffb","\ufffc":"\\ufffc",
-"\ufffd":"\\ufffd","\ufffe":"\\ufffe","\uffff":"\\uffff"};
-
-// Some extra characters that Chrome gets wrong, and substitutes with
-// something else on the wire.
-var extra_escapable = /[\x00-\x1f\ud800-\udfff\ufffe\uffff\u0300-\u0333\u033d-\u0346\u034a-\u034c\u0350-\u0352\u0357-\u0358\u035c-\u0362\u0374\u037e\u0387\u0591-\u05af\u05c4\u0610-\u0617\u0653-\u0654\u0657-\u065b\u065d-\u065e\u06df-\u06e2\u06eb-\u06ec\u0730\u0732-\u0733\u0735-\u0736\u073a\u073d\u073f-\u0741\u0743\u0745\u0747\u07eb-\u07f1\u0951\u0958-\u095f\u09dc-\u09dd\u09df\u0a33\u0a36\u0a59-\u0a5b\u0a5e\u0b5c-\u0b5d\u0e38-\u0e39\u0f43\u0f4d\u0f52\u0f57\u0f5c\u0f69\u0f72-\u0f76\u0f78\u0f80-\u0f83\u0f93\u0f9d\u0fa2\u0fa7\u0fac\u0fb9\u1939-\u193a\u1a17\u1b6b\u1cda-\u1cdb\u1dc0-\u1dcf\u1dfc\u1dfe\u1f71\u1f73\u1f75\u1f77\u1f79\u1f7b\u1f7d\u1fbb\u1fbe\u1fc9\u1fcb\u1fd3\u1fdb\u1fe3\u1feb\u1fee-\u1fef\u1ff9\u1ffb\u1ffd\u2000-\u2001\u20d0-\u20d1\u20d4-\u20d7\u20e7-\u20e9\u2126\u212a-\u212b\u2329-\u232a\u2adc\u302b-\u302c\uaab2-\uaab3\uf900-\ufa0d\ufa10\ufa12\ufa15-\ufa1e\ufa20\ufa22\ufa25-\ufa26\ufa2a-\ufa2d\ufa30-\ufa6d\ufa70-\ufad9\ufb1d\ufb1f\ufb2a-\ufb36\ufb38-\ufb3c\ufb3e\ufb40-\ufb41\ufb43-\ufb44\ufb46-\ufb4e\ufff0-\uffff]/g,
-    extra_lookup;
-
-// JSON Quote string. Use native implementation when possible.
-var JSONQuote = (JSON && JSON.stringify) || function(string) {
-    json_escapable.lastIndex = 0;
-    if (json_escapable.test(string)) {
-        string = string.replace(json_escapable, function(a) {
-            return json_lookup[a];
-        });
-    }
-    return '"' + string + '"';
-};
-
-// This may be quite slow, so let's delay until user actually uses bad
-// characters.
-var unroll_lookup = function(escapable) {
-    var i;
-    var unrolled = {}
-    var c = []
-    for(i=0; i<65536; i++) {
-        c.push( String.fromCharCode(i) );
-    }
-    escapable.lastIndex = 0;
-    c.join('').replace(escapable, function (a) {
-        unrolled[ a ] = '\\u' + ('0000' + a.charCodeAt(0).toString(16)).slice(-4);
-        return '';
-    });
-    escapable.lastIndex = 0;
-    return unrolled;
-};
-
-// Quote string, also taking care of unicode characters that browsers
-// often break. Especially, take care of unicode surrogates:
-//    http://en.wikipedia.org/wiki/Mapping_of_Unicode_characters#Surrogates
-utils.quote = function(string) {
-    var quoted = JSONQuote(string);
-
-    // In most cases this should be very fast and good enough.
-    extra_escapable.lastIndex = 0;
-    if(!extra_escapable.test(quoted)) {
-        return quoted;
-    }
-
-    if(!extra_lookup) extra_lookup = unroll_lookup(extra_escapable);
-
-    return quoted.replace(extra_escapable, function(a) {
-        return extra_lookup[a];
-    });
-}
-
-var _all_protocols = ['websocket',
-                      'xdr-streaming',
-                      'xhr-streaming',
-                      'iframe-eventsource',
-                      'iframe-htmlfile',
-                      'xdr-polling',
-                      'xhr-polling',
-                      'iframe-xhr-polling',
-                      'jsonp-polling'];
-
-utils.probeProtocols = function() {
-    var probed = {};
-    for(var i=0; i<_all_protocols.length; i++) {
-        var protocol = _all_protocols[i];
-        // User can have a typo in protocol name.
-        probed[protocol] = SockJS[protocol] &&
-                           SockJS[protocol].enabled();
-    }
-    return probed;
-};
-
-utils.detectProtocols = function(probed, protocols_whitelist, info) {
-    var pe = {},
-        protocols = [];
-    if (!protocols_whitelist) protocols_whitelist = _all_protocols;
-    for(var i=0; i<protocols_whitelist.length; i++) {
-        var protocol = protocols_whitelist[i];
-        pe[protocol] = probed[protocol];
-    }
-    var maybe_push = function(protos) {
-        var proto = protos.shift();
-        if (pe[proto]) {
-            protocols.push(proto);
-        } else {
-            if (protos.length > 0) {
-                maybe_push(protos);
-            }
-        }
-    }
-
-    // 1. Websocket
-    if (info.websocket !== false) {
-        maybe_push(['websocket']);
-    }
-
-    // 2. Streaming
-    if (pe['xhr-streaming'] && !info.null_origin) {
-        protocols.push('xhr-streaming');
-    } else {
-        if (pe['xdr-streaming'] && !info.cookie_needed && !info.null_origin) {
-            protocols.push('xdr-streaming');
-        } else {
-            maybe_push(['iframe-eventsource',
-                        'iframe-htmlfile']);
-        }
-    }
-
-    // 3. Polling
-    if (pe['xhr-polling'] && !info.null_origin) {
-        protocols.push('xhr-polling');
-    } else {
-        if (pe['xdr-polling'] && !info.cookie_needed && !info.null_origin) {
-            protocols.push('xdr-polling');
-        } else {
-            maybe_push(['iframe-xhr-polling',
-                        'jsonp-polling']);
-        }
-    }
-    return protocols;
-}
-//         [*] End of lib/utils.js
-
-
-//         [*] Including lib/dom.js
-/*
- * ***** BEGIN LICENSE BLOCK *****
- * Copyright (c) 2011-2012 VMware, Inc.
- *
- * For the license see COPYING.
- * ***** END LICENSE BLOCK *****
- */
-
-// May be used by htmlfile jsonp and transports.
-var MPrefix = '_sockjs_global';
-utils.createHook = function() {
-    var window_id = 'a' + utils.random_string(8);
-    if (!(MPrefix in _window)) {
-        var map = {};
-        _window[MPrefix] = function(window_id) {
-            if (!(window_id in map)) {
-                map[window_id] = {
-                    id: window_id,
-                    del: function() {delete map[window_id];}
-                };
-            }
-            return map[window_id];
-        }
-    }
-    return _window[MPrefix](window_id);
-};
-
-
-
-utils.attachMessage = function(listener) {
-    utils.attachEvent('message', listener);
-};
-utils.attachEvent = function(event, listener) {
-    if (typeof _window.addEventListener !== 'undefined') {
-        _window.addEventListener(event, listener, false);
-    } else {
-        // IE quirks.
-        // According to: http://stevesouders.com/misc/test-postmessage.php
-        // the message gets delivered only to 'document', not 'window'.
-        _document.attachEvent("on" + event, listener);
-        // I get 'window' for ie8.
-        _window.attachEvent("on" + event, listener);
-    }
-};
-
-utils.detachMessage = function(listener) {
-    utils.detachEvent('message', listener);
-};
-utils.detachEvent = function(event, listener) {
-    if (typeof _window.addEventListener !== 'undefined') {
-        _window.removeEventListener(event, listener, false);
-    } else {
-        _document.detachEvent("on" + event, listener);
-        _window.detachEvent("on" + event, listener);
-    }
-};
-
-
-var on_unload = {};
-// Things registered after beforeunload are to be called immediately.
-var after_unload = false;
-
-var trigger_unload_callbacks = function() {
-    for(var ref in on_unload) {
-        on_unload[ref]();
-        delete on_unload[ref];
-    };
-};
-
-var unload_triggered = function() {
-    if(after_unload) return;
-    after_unload = true;
-    trigger_unload_callbacks();
-};
-
-// 'unload' alone is not reliable in opera within an iframe, but we
-// can't use `beforeunload` as IE fires it on javascript: links.
-utils.attachEvent('unload', unload_triggered);
-
-utils.unload_add = function(listener) {
-    var ref = utils.random_string(8);
-    on_unload[ref] = listener;
-    if (after_unload) {
-        utils.delay(trigger_unload_callbacks);
-    }
-    return ref;
-};
-utils.unload_del = function(ref) {
-    if (ref in on_unload)
-        delete on_unload[ref];
-};
-
-
-utils.createIframe = function (iframe_url, error_callback) {
-    var iframe = _document.createElement('iframe');
-    var tref, unload_ref;
-    var unattach = function() {
-        clearTimeout(tref);
-        // Explorer had problems with that.
-        try {iframe.onload = null;} catch (x) {}
-        iframe.onerror = null;
-    };
-    var cleanup = function() {
-        if (iframe) {
-            unattach();
-            // This timeout makes chrome fire onbeforeunload event
-            // within iframe. Without the timeout it goes straight to
-            // onunload.
-            setTimeout(function() {
-                if(iframe) {
-                    iframe.parentNode.removeChild(iframe);
-                }
-                iframe = null;
-            }, 0);
-            utils.unload_del(unload_ref);
-        }
-    };
-    var onerror = function(r) {
-        if (iframe) {
-            cleanup();
-            error_callback(r);
-        }
-    };
-    var post = function(msg, origin) {
-        try {
-            // When the iframe is not loaded, IE raises an exception
-            // on 'contentWindow'.
-            if (iframe && iframe.contentWindow) {
-                iframe.contentWindow.postMessage(msg, origin);
-            }
-        } catch (x) {};
-    };
-
-    iframe.src = iframe_url;
-    iframe.style.display = 'none';
-    iframe.style.position = 'absolute';
-    iframe.onerror = function(){onerror('onerror');};
-    iframe.onload = function() {
-        // `onload` is triggered before scripts on the iframe are
-        // executed. Give it few seconds to actually load stuff.
-        clearTimeout(tref);
-        tref = setTimeout(function(){onerror('onload timeout');}, 2000);
-    };
-    _document.body.appendChild(iframe);
-    tref = setTimeout(function(){onerror('timeout');}, 15000);
-    unload_ref = utils.unload_add(cleanup);
-    return {
-        post: post,
-        cleanup: cleanup,
-        loaded: unattach
-    };
-};
-
-utils.createHtmlfile = function (iframe_url, error_callback) {
-    var doc = new ActiveXObject('htmlfile');
-    var tref, unload_ref;
-    var iframe;
-    var unattach = function() {
-        clearTimeout(tref);
-    };
-    var cleanup = function() {
-        if (doc) {
-            unattach();
-            utils.unload_del(unload_ref);
-            iframe.parentNode.removeChild(iframe);
-            iframe = doc = null;
-            CollectGarbage();
-        }
-    };
-    var onerror = function(r)  {
-        if (doc) {
-            cleanup();
-            error_callback(r);
-        }
-    };
-    var post = function(msg, origin) {
-        try {
-            // When the iframe is not loaded, IE raises an exception
-            // on 'contentWindow'.
-            if (iframe && iframe.contentWindow) {
-                iframe.contentWindow.postMessage(msg, origin);
-            }
-        } catch (x) {};
-    };
-
-    doc.open();
-    doc.write('<html><s' + 'cript>' +
-              'document.domain="' + document.domain + '";' +
-              '</s' + 'cript></html>');
-    doc.close();
-    doc.parentWindow[WPrefix] = _window[WPrefix];
-    var c = doc.createElement('div');
-    doc.body.appendChild(c);
-    iframe = doc.createElement('iframe');
-    c.appendChild(iframe);
-    iframe.src = iframe_url;
-    tref = setTimeout(function(){onerror('timeout');}, 15000);
-    unload_ref = utils.unload_add(cleanup);
-    return {
-        post: post,
-        cleanup: cleanup,
-        loaded: unattach
-    };
-};
-//         [*] End of lib/dom.js
-
-
-//         [*] Including lib/dom2.js
-/*
- * ***** BEGIN LICENSE BLOCK *****
- * Copyright (c) 2011-2012 VMware, Inc.
- *
- * For the license see COPYING.
- * ***** END LICENSE BLOCK *****
- */
-
-var AbstractXHRObject = function(){};
-AbstractXHRObject.prototype = new EventEmitter(['chunk', 'finish']);
-
-AbstractXHRObject.prototype._start = function(method, url, payload, opts) {
-    var that = this;
-
-    try {
-        that.xhr = new XMLHttpRequest();
-    } catch(x) {};
-
-    if (!that.xhr) {
-        try {
-            that.xhr = new _window.ActiveXObject('Microsoft.XMLHTTP');
-        } catch(x) {};
-    }
-    if (_window.ActiveXObject || _window.XDomainRequest) {
-        // IE8 caches even POSTs
-        url += ((url.indexOf('?') === -1) ? '?' : '&') + 't='+(+new Date);
-    }
-
-    // Explorer tends to keep connection open, even after the
-    // tab gets closed: http://bugs.jquery.com/ticket/5280
-    that.unload_ref = utils.unload_add(function(){that._cleanup(true);});
-    try {
-        that.xhr.open(method, url, true);
-    } catch(e) {
-        // IE raises an exception on wrong port.
-        that.emit('finish', 0, '');
-        that._cleanup();
-        return;
-    };
-
-    if (!opts || !opts.no_credentials) {
-        // Mozilla docs says https://developer.mozilla.org/en/XMLHttpRequest :
-        // "This never affects same-site requests."
-        that.xhr.withCredentials = 'true';
-    }
-    if (opts && opts.headers) {
-        for(var key in opts.headers) {
-            that.xhr.setRequestHeader(key, opts.headers[key]);
-        }
-    }
-
-    that.xhr.onreadystatechange = function() {
-        if (that.xhr) {
-            var x = that.xhr;
-            switch (x.readyState) {
-            case 3:
-                // IE doesn't like peeking into responseText or status
-                // on Microsoft.XMLHTTP and readystate=3
-                try {
-                    var status = x.status;
-                    var text = x.responseText;
-                } catch (x) {};
-                // IE returns 1223 for 204: http://bugs.jquery.com/ticket/1450
-                if (status === 1223) status = 204;
-
-                // IE does return readystate == 3 for 404 answers.
-                if (text && text.length > 0) {
-                    that.emit('chunk', status, text);
-                }
-                break;
-            case 4:
-                var status = x.status;
-                // IE returns 1223 for 204: http://bugs.jquery.com/ticket/1450
-                if (status === 1223) status = 204;
-
-                that.emit('finish', status, x.responseText);
-                that._cleanup(false);
-                break;
-            }
-        }
-    };
-    that.xhr.send(payload);
-};
-
-AbstractXHRObject.prototype._cleanup = function(abort) {
-    var that = this;
-    if (!that.xhr) return;
-    utils.unload_del(that.unload_ref);
-
-    // IE needs this field to be a function
-    that.xhr.onreadystatechange = function(){};
-
-    if (abort) {
-        try {
-            that.xhr.abort();
-        } catch(x) {};
-    }
-    that.unload_ref = that.xhr = null;
-};
-
-AbstractXHRObject.prototype.close = function() {
-    var that = this;
-    that.nuke();
-    that._cleanup(true);
-};
-
-var XHRCorsObject = utils.XHRCorsObject = function() {
-    var that = this, args = arguments;
-    utils.delay(function(){that._start.apply(that, args);});
-};
-XHRCorsObject.prototype = new AbstractXHRObject();
-
-var XHRLocalObject = utils.XHRLocalObject = function(method, url, payload) {
-    var that = this;
-    utils.delay(function(){
-        that._start(method, url, payload, {
-            no_credentials: true
-        });
-    });
-};
-XHRLocalObject.prototype = new AbstractXHRObject();
-
-
-
-// References:
-//   http://ajaxian.com/archives/100-line-ajax-wrapper
-//   http://msdn.microsoft.com/en-us/library/cc288060(v=VS.85).aspx
-var XDRObject = utils.XDRObject = function(method, url, payload) {
-    var that = this;
-    utils.delay(function(){that._start(method, url, payload);});
-};
-XDRObject.prototype = new EventEmitter(['chunk', 'finish']);
-XDRObject.prototype._start = function(method, url, payload) {
-    var that = this;
-    var xdr = new XDomainRequest();
-    // IE caches even POSTs
-    url += ((url.indexOf('?') === -1) ? '?' : '&') + 't='+(+new Date);
-
-    var onerror = xdr.ontimeout = xdr.onerror = function() {
-        that.emit('finish', 0, '');
-        that._cleanup(false);
-    };
-    xdr.onprogress = function() {
-        that.emit('chunk', 200, xdr.responseText);
-    };
-    xdr.onload = function() {
-        that.emit('finish', 200, xdr.responseText);
-        that._cleanup(false);
-    };
-    that.xdr = xdr;
-    that.unload_ref = utils.unload_add(function(){that._cleanup(true);});
-    try {
-        // Fails with AccessDenied if port number is bogus
-        that.xdr.open(method, url);
-        that.xdr.send(payload);
-    } catch(x) {
-        onerror();
-    }
-};
-
-XDRObject.prototype._cleanup = function(abort) {
-    var that = this;
-    if (!that.xdr) return;
-    utils.unload_del(that.unload_ref);
-
-    that.xdr.ontimeout = that.xdr.onerror = that.xdr.onprogress =
-        that.xdr.onload = null;
-    if (abort) {
-        try {
-            that.xdr.abort();
-        } catch(x) {};
-    }
-    that.unload_ref = that.xdr = null;
-};
-
-XDRObject.prototype.close = function() {
-    var that = this;
-    that.nuke();
-    that._cleanup(true);
-};
-
-// 1. Is natively via XHR
-// 2. Is natively via XDR
-// 3. Nope, but postMessage is there so it should work via the Iframe.
-// 4. Nope, sorry.
-utils.isXHRCorsCapable = function() {
-    if (_window.XMLHttpRequest && 'withCredentials' in new XMLHttpRequest()) {
-        return 1;
-    }
-    // XDomainRequest doesn't work if page is served from file://
-    if (_window.XDomainRequest && _document.domain) {
-        return 2;
-    }
-    if (IframeTransport.enabled()) {
-        return 3;
-    }
-    return 4;
-};
-//         [*] End of lib/dom2.js
-
-
-//         [*] Including lib/sockjs.js
-/*
- * ***** BEGIN LICENSE BLOCK *****
- * Copyright (c) 2011-2012 VMware, Inc.
- *
- * For the license see COPYING.
- * ***** END LICENSE BLOCK *****
- */
-
-var SockJS = function(url, dep_protocols_whitelist, options) {
-    if (this === _window) {
-        // makes `new` optional
-        return new SockJS(url, dep_protocols_whitelist, options);
-    }
-
-    var that = this, protocols_whitelist;
-    that._options = {devel: false, debug: false, protocols_whitelist: [],
-                     info: undefined, rtt: undefined};
-    if (options) {
-        utils.objectExtend(that._options, options);
-    }
-    that._base_url = utils.amendUrl(url);
-    that._server = that._options.server || utils.random_number_string(1000);
-    if (that._options.protocols_whitelist &&
-        that._options.protocols_whitelist.length) {
-        protocols_whitelist = that._options.protocols_whitelist;
-    } else {
-        // Deprecated API
-        if (typeof dep_protocols_whitelist === 'string' &&
-            dep_protocols_whitelist.length > 0) {
-            protocols_whitelist = [dep_protocols_whitelist];
-        } else if (utils.isArray(dep_protocols_whitelist)) {
-            protocols_whitelist = dep_protocols_whitelist
-        } else {
-            protocols_whitelist = null;
-        }
-        if (protocols_whitelist) {
-            that._debug('Deprecated API: Use "protocols_whitelist" option ' +
-                        'instead of supplying protocol list as a second ' +
-                        'parameter to SockJS constructor.');
-        }
-    }
-    that._protocols = [];
-    that.protocol = null;
-    that.readyState = SockJS.CONNECTING;
-    that._ir = createInfoReceiver(that._base_url);
-    that._ir.onfinish = function(info, rtt) {
-        that._ir = null;
-        if (info) {
-            if (that._options.info) {
-                // Override if user supplies the option
-                info = utils.objectExtend(info, that._options.info);
-            }
-            if (that._options.rtt) {
-                rtt = that._options.rtt;
-            }
-            that._applyInfo(info, rtt, protocols_whitelist);
-            that._didClose();
-        } else {
-            that._didClose(1002, 'Can\'t connect to server', true);
-        }
-    };
-};
-// Inheritance
-SockJS.prototype = new REventTarget();
-
-SockJS.version = "0.3.4";
-
-SockJS.CONNECTING = 0;
-SockJS.OPEN = 1;
-SockJS.CLOSING = 2;
-SockJS.CLOSED = 3;
-
-SockJS.prototype._debug = function() {
-    if (this._options.debug)
-        utils.log.apply(utils, arguments);
-};
-
-SockJS.prototype._dispatchOpen = function() {
-    var that = this;
-    if (that.readyState === SockJS.CONNECTING) {
-        if (that._transport_tref) {
-            clearTimeout(that._transport_tref);
-            that._transport_tref = null;
-        }
-        that.readyState = SockJS.OPEN;
-        that.dispatchEvent(new SimpleEvent("open"));
-    } else {
-        // The server might have been restarted, and lost track of our
-        // connection.
-        that._didClose(1006, "Server lost session");
-    }
-};
-
-SockJS.prototype._dispatchMessage = function(data) {
-    var that = this;
-    if (that.readyState !== SockJS.OPEN)
-            return;
-    that.dispatchEvent(new SimpleEvent("message", {data: data}));
-};
-
-SockJS.prototype._dispatchHeartbeat = function(data) {
-    var that = this;
-    if (that.readyState !== SockJS.OPEN)
-        return;
-    that.dispatchEvent(new SimpleEvent('heartbeat', {}));
-};
-
-SockJS.prototype._didClose = function(code, reason, force) {
-    var that = this;
-    if (that.readyState !== SockJS.CONNECTING &&
-        that.readyState !== SockJS.OPEN &&
-        that.readyState !== SockJS.CLOSING)
-            throw new Error('INVALID_STATE_ERR');
-    if (that._ir) {
-        that._ir.nuke();
-        that._ir = null;
-    }
-
-    if (that._transport) {
-        that._transport.doCleanup();
-        that._transport = null;
-    }
-
-    var close_event = new SimpleEvent("close", {
-        code: code,
-        reason: reason,
-        wasClean: utils.userSetCode(code)});
-
-    if (!utils.userSetCode(code) &&
-        that.readyState === SockJS.CONNECTING && !force) {
-        if (that._try_next_protocol(close_event)) {
-            return;
-        }
-        close_event = new SimpleEvent("close", {code: 2000,
-                                                reason: "All transports failed",
-                                                wasClean: false,
-                                                last_event: close_event});
-    }
-    that.readyState = SockJS.CLOSED;
-
-    utils.delay(function() {
-                   that.dispatchEvent(close_event);
-                });
-};
-
-SockJS.prototype._didMessage = function(data) {
-    var that = this;
-    var type = data.slice(0, 1);
-    switch(type) {
-    case 'o':
-        that._dispatchOpen();
-        break;
-    case 'a':
-        var payload = JSON.parse(data.slice(1) || '[]');
-        for(var i=0; i < payload.length; i++){
-            that._dispatchMessage(payload[i]);
-        }
-        break;
-    case 'm':
-        var payload = JSON.parse(data.slice(1) || 'null');
-        that._dispatchMessage(payload);
-        break;
-    case 'c':
-        var payload = JSON.parse(data.slice(1) || '[]');
-        that._didClose(payload[0], payload[1]);
-        break;
-    case 'h':
-        that._dispatchHeartbeat();
-        break;
-    }
-};
-
-SockJS.prototype._try_next_protocol = function(close_event) {
-    var that = this;
-    if (that.protocol) {
-        that._debug('Closed transport:', that.protocol, ''+close_event);
-        that.protocol = null;
-    }
-    if (that._transport_tref) {
-        clearTimeout(that._transport_tref);
-        that._transport_tref = null;
-    }
-
-    while(1) {
-        var protocol = that.protocol = that._protocols.shift();
-        if (!protocol) {
-            return false;
-        }
-        // Some protocols require access to `body`, what if were in
-        // the `head`?
-        if (SockJS[protocol] &&
-            SockJS[protocol].need_body === true &&
-            (!_document.body ||
-             (typeof _document.readyState !== 'undefined'
-              && _document.readyState !== 'complete'))) {
-            that._protocols.unshift(protocol);
-            that.protocol = 'waiting-for-load';
-            utils.attachEvent('load', function(){
-                that._try_next_protocol();
-            });
-            return true;
-        }
-
-        if (!SockJS[protocol] ||
-              !SockJS[protocol].enabled(that._options)) {
-            that._debug('Skipping transport:', protocol);
-        } else {
-            var roundTrips = SockJS[protocol].roundTrips || 1;
-            var to = ((that._options.rto || 0) * roundTrips) || 5000;
-            that._transport_tref = utils.delay(to, function() {
-                if (that.readyState === SockJS.CONNECTING) {
-                    // I can't understand how it is possible to run
-                    // this timer, when the state is CLOSED, but
-                    // apparently in IE everythin is possible.
-                    that._didClose(2007, "Transport timeouted");
-                }
-            });
-
-            var connid = utils.random_string(8);
-            var trans_url = that._base_url + '/' + that._server + '/' + connid;
-            that._debug('Opening transport:', protocol, ' url:'+trans_url,
-                        ' RTO:'+that._options.rto);
-            that._transport = new SockJS[protocol](that, trans_url,
-                                                   that._base_url);
-            return true;
-        }
-    }
-};
-
-SockJS.prototype.close = function(code, reason) {
-    var that = this;
-    if (code && !utils.userSetCode(code))
-        throw new Error("INVALID_ACCESS_ERR");
-    if(that.readyState !== SockJS.CONNECTING &&
-       that.readyState !== SockJS.OPEN) {
-        return false;
-    }
-    that.readyState = SockJS.CLOSING;
-    that._didClose(code || 1000, reason || "Normal closure");
-    return true;
-};
-
-SockJS.prototype.send = function(data) {
-    var that = this;
-    if (that.readyState === SockJS.CONNECTING)
-        throw new Error('INVALID_STATE_ERR');
-    if (that.readyState === SockJS.OPEN) {
-        that._transport.doSend(utils.quote('' + data));
-    }
-    return true;
-};
-
-SockJS.prototype._applyInfo = function(info, rtt, protocols_whitelist) {
-    var that = this;
-    that._options.info = info;
-    that._options.rtt = rtt;
-    that._options.rto = utils.countRTO(rtt);
-    that._options.info.null_origin = !_document.domain;
-    var probed = utils.probeProtocols();
-    that._protocols = utils.detectProtocols(probed, protocols_whitelist, info);
-};
-//         [*] End of lib/sockjs.js
-
-
-//         [*] Including lib/trans-websocket.js
-/*
- * ***** BEGIN LICENSE BLOCK *****
- * Copyright (c) 2011-2012 VMware, Inc.
- *
- * For the license see COPYING.
- * ***** END LICENSE BLOCK *****
- */
-
-var WebSocketTransport = SockJS.websocket = function(ri, trans_url) {
-    var that = this;
-    var url = trans_url + '/websocket';
-    if (url.slice(0, 5) === 'https') {
-        url = 'wss' + url.slice(5);
-    } else {
-        url = 'ws' + url.slice(4);
-    }
-    that.ri = ri;
-    that.url = url;
-    var Constructor = _window.WebSocket || _window.MozWebSocket;
-
-    that.ws = new Constructor(that.url);
-    that.ws.onmessage = function(e) {
-        that.ri._didMessage(e.data);
-    };
-    // Firefox has an interesting bug. If a websocket connection is
-    // created after onunload, it stays alive even when user
-    // navigates away from the page. In such situation let's lie -
-    // let's not open the ws connection at all. See:
-    // https://github.com/sockjs/sockjs-client/issues/28
-    // https://bugzilla.mozilla.org/show_bug.cgi?id=696085
-    that.unload_ref = utils.unload_add(function(){that.ws.close()});
-    that.ws.onclose = function() {
-        that.ri._didMessage(utils.closeFrame(1006, "WebSocket connection broken"));
-    };
-};
-
-WebSocketTransport.prototype.doSend = function(data) {
-    this.ws.send('[' + data + ']');
-};
-
-WebSocketTransport.prototype.doCleanup = function() {
-    var that = this;
-    var ws = that.ws;
-    if (ws) {
-        ws.onmessage = ws.onclose = null;
-        ws.close();
-        utils.unload_del(that.unload_ref);
-        that.unload_ref = that.ri = that.ws = null;
-    }
-};
-
-WebSocketTransport.enabled = function() {
-    return !!(_window.WebSocket || _window.MozWebSocket);
-};
-
-// In theory, ws should require 1 round trip. But in chrome, this is
-// not very stable over SSL. Most likely a ws connection requires a
-// separate SSL connection, in which case 2 round trips are an
-// absolute minumum.
-WebSocketTransport.roundTrips = 2;
-//         [*] End of lib/trans-websocket.js
-
-
-//         [*] Including lib/trans-sender.js
-/*
- * ***** BEGIN LICENSE BLOCK *****
- * Copyright (c) 2011-2012 VMware, Inc.
- *
- * For the license see COPYING.
- * ***** END LICENSE BLOCK *****
- */
-
-var BufferedSender = function() {};
-BufferedSender.prototype.send_constructor = function(sender) {
-    var that = this;
-    that.send_buffer = [];
-    that.sender = sender;
-};
-BufferedSender.prototype.doSend = function(message) {
-    var that = this;
-    that.send_buffer.push(message);
-    if (!that.send_stop) {
-        that.send_schedule();
-    }
-};
-
-// For polling transports in a situation when in the message callback,
-// new message is being send. If the sending connection was started
-// before receiving one, it is possible to saturate the network and
-// timeout due to the lack of receiving socket. To avoid that we delay
-// sending messages by some small time, in order to let receiving
-// connection be started beforehand. This is only a halfmeasure and
-// does not fix the big problem, but it does make the tests go more
-// stable on slow networks.
-BufferedSender.prototype.send_schedule_wait = function() {
-    var that = this;
-    var tref;
-    that.send_stop = function() {
-        that.send_stop = null;
-        clearTimeout(tref);
-    };
-    tref = utils.delay(25, function() {
-        that.send_stop = null;
-        that.send_schedule();
-    });
-};
-
-BufferedSender.prototype.send_schedule = function() {
-    var that = this;
-    if (that.send_buffer.length > 0) {
-        var payload = '[' + that.send_buffer.join(',') + ']';
-        that.send_stop = that.sender(that.trans_url, payload, function(success, abort_reason) {
-            that.send_stop = null;
-            if (success === false) {
-                that.ri._didClose(1006, 'Sending error ' + abort_reason);
-            } else {
-                that.send_schedule_wait();
-            }
-        });
-        that.send_buffer = [];
-    }
-};
-
-BufferedSender.prototype.send_destructor = function() {
-    var that = this;
-    if (that._send_stop) {
-        that._send_stop();
-    }
-    that._send_stop = null;
-};
-
-var jsonPGenericSender = function(url, payload, callback) {
-    var that = this;
-
-    if (!('_send_form' in that)) {
-        var form = that._send_form = _document.createElement('form');
-        var area = that._send_area = _document.createElement('textarea');
-        area.name = 'd';
-        form.style.display = 'none';
-        form.style.position = 'absolute';
-        form.method = 'POST';
-        form.enctype = 'application/x-www-form-urlencoded';
-        form.acceptCharset = "UTF-8";
-        form.appendChild(area);
-        _document.body.appendChild(form);
-    }
-    var form = that._send_form;
-    var area = that._send_area;
-    var id = 'a' + utils.random_string(8);
-    form.target = id;
-    form.action = url + '/jsonp_send?i=' + id;
-
-    var iframe;
-    try {
-        // ie6 dynamic iframes with target="" support (thanks Chris Lambacher)
-        iframe = _document.createElement('<iframe name="'+ id +'">');
-    } catch(x) {
-        iframe = _document.createElement('iframe');
-        iframe.name = id;
-    }
-    iframe.id = id;
-    form.appendChild(iframe);
-    iframe.style.display = 'none';
-
-    try {
-        area.value = payload;
-    } catch(e) {
-        utils.log('Your browser is seriously broken. Go home! ' + e.message);
-    }
-    form.submit();
-
-    var completed = function(e) {
-        if (!iframe.onerror) return;
-        iframe.onreadystatechange = iframe.onerror = iframe.onload = null;
-        // Opera mini doesn't like if we GC iframe
-        // immediately, thus this timeout.
-        utils.delay(500, function() {
-                       iframe.parentNode.removeChild(iframe);
-                       iframe = null;
-                   });
-        area.value = '';
-        // It is not possible to detect if the iframe succeeded or
-        // failed to submit our form.
-        callback(true);
-    };
-    iframe.onerror = iframe.onload = completed;
-    iframe.onreadystatechange = function(e) {
-        if (iframe.readyState == 'complete') completed();
-    };
-    return completed;
-};
-
-var createAjaxSender = function(AjaxObject) {
-    return function(url, payload, callback) {
-        var xo = new AjaxObject('POST', url + '/xhr_send', payload);
-        xo.onfinish = function(status, text) {
-            callback(status === 200 || status === 204,
-                     'http status ' + status);
-        };
-        return function(abort_reason) {
-            callback(false, abort_reason);
-        };
-    };
-};
-//         [*] End of lib/trans-sender.js
-
-
-//         [*] Including lib/trans-jsonp-receiver.js
-/*
- * ***** BEGIN LICENSE BLOCK *****
- * Copyright (c) 2011-2012 VMware, Inc.
- *
- * For the license see COPYING.
- * ***** END LICENSE BLOCK *****
- */
-
-// Parts derived from Socket.io:
-//    https://github.com/LearnBoost/socket.io/blob/0.6.17/lib/socket.io/transports/jsonp-polling.js
-// and jQuery-JSONP:
-//    https://code.google.com/p/jquery-jsonp/source/browse/trunk/core/jquery.jsonp.js
-var jsonPGenericReceiver = function(url, callback) {
-    var tref;
-    var script = _document.createElement('script');
-    var script2;  // Opera synchronous load trick.
-    var close_script = function(frame) {
-        if (script2) {
-            script2.parentNode.removeChild(script2);
-            script2 = null;
-        }
-        if (script) {
-            clearTimeout(tref);
-            // Unfortunately, you can't really abort script loading of
-            // the script.
-            script.parentNode.removeChild(script);
-            script.onreadystatechange = script.onerror =
-                script.onload = script.onclick = null;
-            script = null;
-            callback(frame);
-            callback = null;
-        }
-    };
-
-    // IE9 fires 'error' event after orsc or before, in random order.
-    var loaded_okay = false;
-    var error_timer = null;
-
-    script.id = 'a' + utils.random_string(8);
-    script.src = url;
-    script.type = 'text/javascript';
-    script.charset = 'UTF-8';
-    script.onerror = function(e) {
-        if (!error_timer) {
-            // Delay firing close_script.
-            error_timer = setTimeout(function() {
-                if (!loaded_okay) {
-                    close_script(utils.closeFrame(
-                        1006,
-                        "JSONP script loaded abnormally (onerror)"));
-                }
-            }, 1000);
-        }
-    };
-    script.onload = function(e) {
-        close_script(utils.closeFrame(1006, "JSONP script loaded abnormally (onload)"));
-    };
-
-    script.onreadystatechange = function(e) {
-        if (/loaded|closed/.test(script.readyState)) {
-            if (script && script.htmlFor && script.onclick) {
-                loaded_okay = true;
-                try {
-                    // In IE, actually execute the script.
-                    script.onclick();
-                } catch (x) {}
-            }
-            if (script) {
-                close_script(utils.closeFrame(1006, "JSONP script loaded abnormally (onreadystatechange)"));
-            }
-        }
-    };
-    // IE: event/htmlFor/onclick trick.
-    // One can't rely on proper order for onreadystatechange. In order to
-    // make sure, set a 'htmlFor' and 'event' properties, so that
-    // script code will be installed as 'onclick' handler for the
-    // script object. Later, onreadystatechange, manually execute this
-    // code. FF and Chrome doesn't work with 'event' and 'htmlFor'
-    // set. For reference see:
-    //   http://jaubourg.net/2010/07/loading-script-as-onclick-handler-of.html
-    // Also, read on that about script ordering:
-    //   http://wiki.whatwg.org/wiki/Dynamic_Script_Execution_Order
-    if (typeof script.async === 'undefined' && _document.attachEvent) {
-        // According to mozilla docs, in recent browsers script.async defaults
-        // to 'true', so we may use it to detect a good browser:
-        // https://developer.mozilla.org/en/HTML/Element/script
-        if (!/opera/i.test(navigator.userAgent)) {
-            // Naively assume we're in IE
-            try {
-                script.htmlFor = script.id;
-                script.event = "onclick";
-            } catch (x) {}
-            script.async = true;
-        } else {
-            // Opera, second sync script hack
-            script2 = _document.createElement('script');
-            script2.text = "try{var a = document.getElementById('"+script.id+"'); if(a)a.onerror();}catch(x){};";
-            script.async = script2.async = false;
-        }
-    }
-    if (typeof script.async !== 'undefined') {
-        script.async = true;
-    }
-
-    // Fallback mostly for Konqueror - stupid timer, 35 seconds shall be plenty.
-    tref = setTimeout(function() {
-                          close_script(utils.closeFrame(1006, "JSONP script loaded abnormally (timeout)"));
-                      }, 35000);
-
-    var head = _document.getElementsByTagName('head')[0];
-    head.insertBefore(script, head.firstChild);
-    if (script2) {
-        head.insertBefore(script2, head.firstChild);
-    }
-    return close_script;
-};
-//         [*] End of lib/trans-jsonp-receiver.js
-
-
-//         [*] Including lib/trans-jsonp-polling.js
-/*
- * ***** BEGIN LICENSE BLOCK *****
- * Copyright (c) 2011-2012 VMware, Inc.
- *
- * For the license see COPYING.
- * ***** END LICENSE BLOCK *****
- */
-
-// The simplest and most robust transport, using the well-know cross
-// domain hack - JSONP. This transport is quite inefficient - one
-// mssage could use up to one http request. But at least it works almost
-// everywhere.
-// Known limitations:
-//   o you will get a spinning cursor
-//   o for Konqueror a dumb timer is needed to detect errors
-
-
-var JsonPTransport = SockJS['jsonp-polling'] = function(ri, trans_url) {
-    utils.polluteGlobalNamespace();
-    var that = this;
-    that.ri = ri;
-    that.trans_url = trans_url;
-    that.send_constructor(jsonPGenericSender);
-    that._schedule_recv();
-};
-
-// Inheritnace
-JsonPTransport.prototype = new BufferedSender();
-
-JsonPTransport.prototype._schedule_recv = function() {
-    var that = this;
-    var callback = function(data) {
-        that._recv_stop = null;
-        if (data) {
-            // no data - heartbeat;
-            if (!that._is_closing) {
-                that.ri._didMessage(data);
-            }
-        }
-        // The message can be a close message, and change is_closing state.
-        if (!that._is_closing) {
-            that._schedule_recv();
-        }
-    };
-    that._recv_stop = jsonPReceiverWrapper(that.trans_url + '/jsonp',
-                                           jsonPGenericReceiver, callback);
-};
-
-JsonPTransport.enabled = function() {
-    return true;
-};
-
-JsonPTransport.need_body = true;
-
-
-JsonPTransport.prototype.doCleanup = function() {
-    var that = this;
-    that._is_closing = true;
-    if (that._recv_stop) {
-        that._recv_stop();
-    }
-    that.ri = that._recv_stop = null;
-    that.send_destructor();
-};
-
-
-// Abstract away code that handles global namespace pollution.
-var jsonPReceiverWrapper = function(url, constructReceiver, user_callback) {
-    var id = 'a' + utils.random_string(6);
-    var url_id = url + '?c=' + escape(WPrefix + '.' + id);
-
-    // Unfortunately it is not possible to abort loading of the
-    // script. We need to keep track of frake close frames.
-    var aborting = 0;
-
-    // Callback will be called exactly once.
-    var callback = function(frame) {
-        switch(aborting) {
-        case 0:
-            // Normal behaviour - delete hook _and_ emit message.
-            delete _window[WPrefix][id];
-            user_callback(frame);
-            break;
-        case 1:
-            // Fake close frame - emit but don't delete hook.
-            user_callback(frame);
-            aborting = 2;
-            break;
-        case 2:
-            // Got frame after connection was closed, delete hook, don't emit.
-            delete _window[WPrefix][id];
-            break;
-        }
-    };
-
-    var close_script = constructReceiver(url_id, callback);
-    _window[WPrefix][id] = close_script;
-    var stop = function() {
-        if (_window[WPrefix][id]) {
-            aborting = 1;
-            _window[WPrefix][id](utils.closeFrame(1000, "JSONP user aborted read"));
-        }
-    };
-    return stop;
-};
-//         [*] End of lib/trans-jsonp-polling.js
-
-
-//         [*] Including lib/trans-xhr.js
-/*
- * ***** BEGIN LICENSE BLOCK *****
- * Copyright (c) 2011-2012 VMware, Inc.
- *
- * For the license see COPYING.
- * ***** END LICENSE BLOCK *****
- */
-
-var AjaxBasedTransport = function() {};
-AjaxBasedTransport.prototype = new BufferedSender();
-
-AjaxBasedTransport.prototype.run = function(ri, trans_url,
-                                            url_suffix, Receiver, AjaxObject) {
-    var that = this;
-    that.ri = ri;
-    that.trans_url = trans_url;
-    that.send_constructor(createAjaxSender(AjaxObject));
-    that.poll = new Polling(ri, Receiver,
-                            trans_url + url_suffix, AjaxObject);
-};
-
-AjaxBasedTransport.prototype.doCleanup = function() {
-    var that = this;
-    if (that.poll) {
-        that.poll.abort();
-        that.poll = null;
-    }
-};
-
-// xhr-streaming
-var XhrStreamingTransport = SockJS['xhr-streaming'] = function(ri, trans_url) {
-    this.run(ri, trans_url, '/xhr_streaming', XhrReceiver, utils.XHRCorsObject);
-};
-
-XhrStreamingTransport.prototype = new AjaxBasedTransport();
-
-XhrStreamingTransport.enabled = function() {
-    // Support for CORS Ajax aka Ajax2? Opera 12 claims CORS but
-    // doesn't do streaming.
-    return (_window.XMLHttpRequest &&
-            'withCredentials' in new XMLHttpRequest() &&
-            (!/opera/i.test(navigator.userAgent)));
-};
-XhrStreamingTransport.roundTrips = 2; // preflight, ajax
-
-// Safari gets confused when a streaming ajax request is started
-// before onload. This causes the load indicator to spin indefinetely.
-XhrStreamingTransport.need_body = true;
-
-
-// According to:
-//   http://stackoverflow.com/questions/1641507/detect-browser-support-for-cross-domain-xmlhttprequests
-//   http://hacks.mozilla.org/2009/07/cross-site-xmlhttprequest-with-cors/
-
-
-// xdr-streaming
-var XdrStreamingTransport = SockJS['xdr-streaming'] = function(ri, trans_url) {
-    this.run(ri, trans_url, '/xhr_streaming', XhrReceiver, utils.XDRObject);
-};
-
-XdrStreamingTransport.prototype = new AjaxBasedTransport();
-
-XdrStreamingTransport.enabled = function() {
-    return !!_window.XDomainRequest;
-};
-XdrStreamingTransport.roundTrips = 2; // preflight, ajax
-
-
-
-// xhr-polling
-var XhrPollingTransport = SockJS['xhr-polling'] = function(ri, trans_url) {
-    this.run(ri, trans_url, '/xhr', XhrReceiver, utils.XHRCorsObject);
-};
-
-XhrPollingTransport.prototype = new AjaxBasedTransport();
-
-XhrPollingTransport.enabled = XhrStreamingTransport.enabled;
-XhrPollingTransport.roundTrips = 2; // preflight, ajax
-
-
-// xdr-polling
-var XdrPollingTransport = SockJS['xdr-polling'] = function(ri, trans_url) {
-    this.run(ri, trans_url, '/xhr', XhrReceiver, utils.XDRObject);
-};
-
-XdrPollingTransport.prototype = new AjaxBasedTransport();
-
-XdrPollingTransport.enabled = XdrStreamingTransport.enabled;
-XdrPollingTransport.roundTrips = 2; // preflight, ajax
-//         [*] End of lib/trans-xhr.js
-
-
-//         [*] Including lib/trans-iframe.js
-/*
- * ***** BEGIN LICENSE BLOCK *****
- * Copyright (c) 2011-2012 VMware, Inc.
- *
- * For the license see COPYING.
- * ***** END LICENSE BLOCK *****
- */
-
-// Few cool transports do work only for same-origin. In order to make
-// them working cross-domain we shall use iframe, served form the
-// remote domain. New browsers, have capabilities to communicate with
-// cross domain iframe, using postMessage(). In IE it was implemented
-// from IE 8+, but of course, IE got some details wrong:
-//    http://msdn.microsoft.com/en-us/library/cc197015(v=VS.85).aspx
-//    http://stevesouders.com/misc/test-postmessage.php
-
-var IframeTransport = function() {};
-
-IframeTransport.prototype.i_constructor = function(ri, trans_url, base_url) {
-    var that = this;
-    that.ri = ri;
-    that.origin = utils.getOrigin(base_url);
-    that.base_url = base_url;
-    that.trans_url = trans_url;
-
-    var iframe_url = base_url + '/iframe.html';
-    if (that.ri._options.devel) {
-        iframe_url += '?t=' + (+new Date);
-    }
-    that.window_id = utils.random_string(8);
-    iframe_url += '#' + that.window_id;
-
-    that.iframeObj = utils.createIframe(iframe_url, function(r) {
-                                            that.ri._didClose(1006, "Unable to load an iframe (" + r + ")");
-                                        });
-
-    that.onmessage_cb = utils.bind(that.onmessage, that);
-    utils.attachMessage(that.onmessage_cb);
-};
-
-IframeTransport.prototype.doCleanup = function() {
-    var that = this;
-    if (that.iframeObj) {
-        utils.detachMessage(that.onmessage_cb);
-        try {
-            // When the iframe is not loaded, IE raises an exception
-            // on 'contentWindow'.
-            if (that.iframeObj.iframe.contentWindow) {
-                that.postMessage('c');
-            }
-        } catch (x) {}
-        that.iframeObj.cleanup();
-        that.iframeObj = null;
-        that.onmessage_cb = that.iframeObj = null;
-    }
-};
-
-IframeTransport.prototype.onmessage = function(e) {
-    var that = this;
-    if (e.origin !== that.origin) return;
-    var window_id = e.data.slice(0, 8);
-    var type = e.data.slice(8, 9);
-    var data = e.data.slice(9);
-
-    if (window_id !== that.window_id) return;
-
-    switch(type) {
-    case 's':
-        that.iframeObj.loaded();
-        that.postMessage('s', JSON.stringify([SockJS.version, that.protocol, that.trans_url, that.base_url]));
-        break;
-    case 't':
-        that.ri._didMessage(data);
-        break;
-    }
-};
-
-IframeTransport.prototype.postMessage = function(type, data) {
-    var that = this;
-    that.iframeObj.post(that.window_id + type + (data || ''), that.origin);
-};
-
-IframeTransport.prototype.doSend = function (message) {
-    this.postMessage('m', message);
-};
-
-IframeTransport.enabled = function() {
-    // postMessage misbehaves in konqueror 4.6.5 - the messages are delivered with
-    // huge delay, or not at all.
-    var konqueror = navigator && navigator.userAgent && navigator.userAgent.indexOf('Konqueror') !== -1;
-    return ((typeof _window.postMessage === 'function' ||
-            typeof _window.postMessage === 'object') && (!konqueror));
-};
-//         [*] End of lib/trans-iframe.js
-
-
-//         [*] Including lib/trans-iframe-within.js
-/*
- * ***** BEGIN LICENSE BLOCK *****
- * Copyright (c) 2011-2012 VMware, Inc.
- *
- * For the license see COPYING.
- * ***** END LICENSE BLOCK *****
- */
-
-var curr_window_id;
-
-var postMessage = function (type, data) {
-    if(parent !== _window) {
-        parent.postMessage(curr_window_id + type + (data || ''), '*');
-    } else {
-        utils.log("Can't postMessage, no parent window.", type, data);
-    }
-};
-
-var FacadeJS = function() {};
-FacadeJS.prototype._didClose = function (code, reason) {
-    postMessage('t', utils.closeFrame(code, reason));
-};
-FacadeJS.prototype._didMessage = function (frame) {
-    postMessage('t', frame);
-};
-FacadeJS.prototype._doSend = function (data) {
-    this._transport.doSend(data);
-};
-FacadeJS.prototype._doCleanup = function () {
-    this._transport.doCleanup();
-};
-
-utils.parent_origin = undefined;
-
-SockJS.bootstrap_iframe = function() {
-    var facade;
-    curr_window_id = _document.location.hash.slice(1);
-    var onMessage = function(e) {
-        if(e.source !== parent) return;
-        if(typeof utils.parent_origin === 'undefined')
-            utils.parent_origin = e.origin;
-        if (e.origin !== utils.parent_origin) return;
-
-        var window_id = e.data.slice(0, 8);
-        var type = e.data.slice(8, 9);
-        var data = e.data.slice(9);
-        if (window_id !== curr_window_id) return;
-        switch(type) {
-        case 's':
-            var p = JSON.parse(data);
-            var version = p[0];
-            var protocol = p[1];
-            var trans_url = p[2];
-            var base_url = p[3];
-            if (version !== SockJS.version) {
-                utils.log("Incompatibile SockJS! Main site uses:" +
-                          " \"" + version + "\", the iframe:" +
-                          " \"" + SockJS.version + "\".");
-            }
-            if (!utils.flatUrl(trans_url) || !utils.flatUrl(base_url)) {
-                utils.log("Only basic urls are supported in SockJS");
-                return;
-            }
-
-            if (!utils.isSameOriginUrl(trans_url) ||
-                !utils.isSameOriginUrl(base_url)) {
-                utils.log("Can't connect to different domain from within an " +
-                          "iframe. (" + JSON.stringify([_window.location.href, trans_url, base_url]) +
-                          ")");
-                return;
-            }
-            facade = new FacadeJS();
-            facade._transport = new FacadeJS[protocol](facade, trans_url, base_url);
-            break;
-        case 'm':
-            facade._doSend(data);
-            break;
-        case 'c':
-            if (facade)
-                facade._doCleanup();
-            facade = null;
-            break;
-        }
-    };
-
-    // alert('test ticker');
-    // facade = new FacadeJS();
-    // facade._transport = new FacadeJS['w-iframe-xhr-polling'](facade, 'http://host.com:9999/ticker/12/basd');
-
-    utils.attachMessage(onMessage);
-
-    // Start
-    postMessage('s');
-};
-//         [*] End of lib/trans-iframe-within.js
-
-
-//         [*] Including lib/info.js
-/*
- * ***** BEGIN LICENSE BLOCK *****
- * Copyright (c) 2011-2012 VMware, Inc.
- *
- * For the license see COPYING.
- * ***** END LICENSE BLOCK *****
- */
-
-var InfoReceiver = function(base_url, AjaxObject) {
-    var that = this;
-    utils.delay(function(){that.doXhr(base_url, AjaxObject);});
-};
-
-InfoReceiver.prototype = new EventEmitter(['finish']);
-
-InfoReceiver.prototype.doXhr = function(base_url, AjaxObject) {
-    var that = this;
-    var t0 = (new Date()).getTime();
-    var xo = new AjaxObject('GET', base_url + '/info');
-
-    var tref = utils.delay(8000,
-                           function(){xo.ontimeout();});
-
-    xo.onfinish = function(status, text) {
-        clearTimeout(tref);
-        tref = null;
-        if (status === 200) {
-            var rtt = (new Date()).getTime() - t0;
-            var info = JSON.parse(text);
-            if (typeof info !== 'object') info = {};
-            that.emit('finish', info, rtt);
-        } else {
-            that.emit('finish');
-        }
-    };
-    xo.ontimeout = function() {
-        xo.close();
-        that.emit('finish');
-    };
-};
-
-var InfoReceiverIframe = function(base_url) {
-    var that = this;
-    var go = function() {
-        var ifr = new IframeTransport();
-        ifr.protocol = 'w-iframe-info-receiver';
-        var fun = function(r) {
-            if (typeof r === 'string' && r.substr(0,1) === 'm') {
-                var d = JSON.parse(r.substr(1));
-                var info = d[0], rtt = d[1];
-                that.emit('finish', info, rtt);
-            } else {
-                that.emit('finish');
-            }
-            ifr.doCleanup();
-            ifr = null;
-        };
-        var mock_ri = {
-            _options: {},
-            _didClose: fun,
-            _didMessage: fun
-        };
-        ifr.i_constructor(mock_ri, base_url, base_url);
-    }
-    if(!_document.body) {
-        utils.attachEvent('load', go);
-    } else {
-        go();
-    }
-};
-InfoReceiverIframe.prototype = new EventEmitter(['finish']);
-
-
-var InfoReceiverFake = function() {
-    // It may not be possible to do cross domain AJAX to get the info
-    // data, for example for IE7. But we want to run JSONP, so let's
-    // fake the response, with rtt=2s (rto=6s).
-    var that = this;
-    utils.delay(function() {
-        that.emit('finish', {}, 2000);
-    });
-};
-InfoReceiverFake.prototype = new EventEmitter(['finish']);
-
-var createInfoReceiver = function(base_url) {
-    if (utils.isSameOriginUrl(base_url)) {
-        // If, for some reason, we have SockJS locally - there's no
-        // need to start up the complex machinery. Just use ajax.
-        return new InfoReceiver(base_url, utils.XHRLocalObject);
-    }
-    switch (utils.isXHRCorsCapable()) {
-    case 1:
-        // XHRLocalObject -> no_credentials=true
-        return new InfoReceiver(base_url, utils.XHRLocalObject);
-    case 2:
-        return new InfoReceiver(base_url, utils.XDRObject);
-    case 3:
-        // Opera
-        return new InfoReceiverIframe(base_url);
-    default:
-        // IE 7
-        return new InfoReceiverFake();
-    };
-};
-
-
-var WInfoReceiverIframe = FacadeJS['w-iframe-info-receiver'] = function(ri, _trans_url, base_url) {
-    var ir = new InfoReceiver(base_url, utils.XHRLocalObject);
-    ir.onfinish = function(info, rtt) {
-        ri._didMessage('m'+JSON.stringify([info, rtt]));
-        ri._didClose();
-    }
-};
-WInfoReceiverIframe.prototype.doCleanup = function() {};
-//         [*] End of lib/info.js
-
-
-//         [*] Including lib/trans-iframe-eventsource.js
-/*
- * ***** BEGIN LICENSE BLOCK *****
- * Copyright (c) 2011-2012 VMware, Inc.
- *
- * For the license see COPYING.
- * ***** END LICENSE BLOCK *****
- */
-
-var EventSourceIframeTransport = SockJS['iframe-eventsource'] = function () {
-    var that = this;
-    that.protocol = 'w-iframe-eventsource';
-    that.i_constructor.apply(that, arguments);
-};
-
-EventSourceIframeTransport.prototype = new IframeTransport();
-
-EventSourceIframeTransport.enabled = function () {
-    return ('EventSource' in _window) && IframeTransport.enabled();
-};
-
-EventSourceIframeTransport.need_body = true;
-EventSourceIframeTransport.roundTrips = 3; // html, javascript, eventsource
-
-
-// w-iframe-eventsource
-var EventSourceTransport = FacadeJS['w-iframe-eventsource'] = function(ri, trans_url) {
-    this.run(ri, trans_url, '/eventsource', EventSourceReceiver, utils.XHRLocalObject);
-}
-EventSourceTransport.prototype = new AjaxBasedTransport();
-//         [*] End of lib/trans-iframe-eventsource.js
-
-
-//         [*] Including lib/trans-iframe-xhr-polling.js
-/*
- * ***** BEGIN LICENSE BLOCK *****
- * Copyright (c) 2011-2012 VMware, Inc.
- *
- * For the license see COPYING.
- * ***** END LICENSE BLOCK *****
- */
-
-var XhrPollingIframeTransport = SockJS['iframe-xhr-polling'] = function () {
-    var that = this;
-    that.protocol = 'w-iframe-xhr-polling';
-    that.i_constructor.apply(that, arguments);
-};
-
-XhrPollingIframeTransport.prototype = new IframeTransport();
-
-XhrPollingIframeTransport.enabled = function () {
-    return _window.XMLHttpRequest && IframeTransport.enabled();
-};
-
-XhrPollingIframeTransport.need_body = true;
-XhrPollingIframeTransport.roundTrips = 3; // html, javascript, xhr
-
-
-// w-iframe-xhr-polling
-var XhrPollingITransport = FacadeJS['w-iframe-xhr-polling'] = function(ri, trans_url) {
-    this.run(ri, trans_url, '/xhr', XhrReceiver, utils.XHRLocalObject);
-};
-
-XhrPollingITransport.prototype = new AjaxBasedTransport();
-//         [*] End of lib/trans-iframe-xhr-polling.js
-
-
-//         [*] Including lib/trans-iframe-htmlfile.js
-/*
- * ***** BEGIN LICENSE BLOCK *****
- * Copyright (c) 2011-2012 VMware, Inc.
- *
- * For the license see COPYING.
- * ***** END LICENSE BLOCK *****
- */
-
-// This transport generally works in any browser, but will cause a
-// spinning cursor to appear in any browser other than IE.
-// We may test this transport in all browsers - why not, but in
-// production it should be only run in IE.
-
-var HtmlFileIframeTransport = SockJS['iframe-htmlfile'] = function () {
-    var that = this;
-    that.protocol = 'w-iframe-htmlfile';
-    that.i_constructor.apply(that, arguments);
-};
-
-// Inheritance.
-HtmlFileIframeTransport.prototype = new IframeTransport();
-
-HtmlFileIframeTransport.enabled = function() {
-    return IframeTransport.enabled();
-};
-
-HtmlFileIframeTransport.need_body = true;
-HtmlFileIframeTransport.roundTrips = 3; // html, javascript, htmlfile
-
-
-// w-iframe-htmlfile
-var HtmlFileTransport = FacadeJS['w-iframe-htmlfile'] = function(ri, trans_url) {
-    this.run(ri, trans_url, '/htmlfile', HtmlfileReceiver, utils.XHRLocalObject);
-};
-HtmlFileTransport.prototype = new AjaxBasedTransport();
-//         [*] End of lib/trans-iframe-htmlfile.js
-
-
-//         [*] Including lib/trans-polling.js
-/*
- * ***** BEGIN LICENSE BLOCK *****
- * Copyright (c) 2011-2012 VMware, Inc.
- *
- * For the license see COPYING.
- * ***** END LICENSE BLOCK *****
- */
-
-var Polling = function(ri, Receiver, recv_url, AjaxObject) {
-    var that = this;
-    that.ri = ri;
-    that.Receiver = Receiver;
-    that.recv_url = recv_url;
-    that.AjaxObject = AjaxObject;
-    that._scheduleRecv();
-};
-
-Polling.prototype._scheduleRecv = function() {
-    var that = this;
-    var poll = that.poll = new that.Receiver(that.recv_url, that.AjaxObject);
-    var msg_counter = 0;
-    poll.onmessage = function(e) {
-        msg_counter += 1;
-        that.ri._didMessage(e.data);
-    };
-    poll.onclose = function(e) {
-        that.poll = poll = poll.onmessage = poll.onclose = null;
-        if (!that.poll_is_closing) {
-            if (e.reason === 'permanent') {
-                that.ri._didClose(1006, 'Polling error (' + e.reason + ')');
-            } else {
-                that._scheduleRecv();
-            }
-        }
-    };
-};
-
-Polling.prototype.abort = function() {
-    var that = this;
-    that.poll_is_closing = true;
-    if (that.poll) {
-        that.poll.abort();
-    }
-};
-//         [*] End of lib/trans-polling.js
-
-
-//         [*] Including lib/trans-receiver-eventsource.js
-/*
- * ***** BEGIN LICENSE BLOCK *****
- * Copyright (c) 2011-2012 VMware, Inc.
- *
- * For the license see COPYING.
- * ***** END LICENSE BLOCK *****
- */
-
-var EventSourceReceiver = function(url) {
-    var that = this;
-    var es = new EventSource(url);
-    es.onmessage = function(e) {
-        that.dispatchEvent(new SimpleEvent('message',
-                                           {'data': unescape(e.data)}));
-    };
-    that.es_close = es.onerror = function(e, abort_reason) {
-        // ES on reconnection has readyState = 0 or 1.
-        // on network error it's CLOSED = 2
-        var reason = abort_reason ? 'user' :
-            (es.readyState !== 2 ? 'network' : 'permanent');
-        that.es_close = es.onmessage = es.onerror = null;
-        // EventSource reconnects automatically.
-        es.close();
-        es = null;
-        // Safari and chrome < 15 crash if we close window before
-        // waiting for ES cleanup. See:
-        //   https://code.google.com/p/chromium/issues/detail?id=89155
-        utils.delay(200, function() {
-                        that.dispatchEvent(new SimpleEvent('close', {reason: reason}));
-                    });
-    };
-};
-
-EventSourceReceiver.prototype = new REventTarget();
-
-EventSourceReceiver.prototype.abort = function() {
-    var that = this;
-    if (that.es_close) {
-        that.es_close({}, true);
-    }
-};
-//         [*] End of lib/trans-receiver-eventsource.js
-
-
-//         [*] Including lib/trans-receiver-htmlfile.js
-/*
- * ***** BEGIN LICENSE BLOCK *****
- * Copyright (c) 2011-2012 VMware, Inc.
- *
- * For the license see COPYING.
- * ***** END LICENSE BLOCK *****
- */
-
-var _is_ie_htmlfile_capable;
-var isIeHtmlfileCapable = function() {
-    if (_is_ie_htmlfile_capable === undefined) {
-        if ('ActiveXObject' in _window) {
-            try {
-                _is_ie_htmlfile_capable = !!new ActiveXObject('htmlfile');
-            } catch (x) {}
-        } else {
-            _is_ie_htmlfile_capable = false;
-        }
-    }
-    return _is_ie_htmlfile_capable;
-};
-
-
-var HtmlfileReceiver = function(url) {
-    var that = this;
-    utils.polluteGlobalNamespace();
-
-    that.id = 'a' + utils.random_string(6, 26);
-    url += ((url.indexOf('?') === -1) ? '?' : '&') +
-        'c=' + escape(WPrefix + '.' + that.id);
-
-    var constructor = isIeHtmlfileCapable() ?
-        utils.createHtmlfile : utils.createIframe;
-
-    var iframeObj;
-    _window[WPrefix][that.id] = {
-        start: function () {
-            iframeObj.loaded();
-        },
-        message: function (data) {
-            that.dispatchEvent(new SimpleEvent('message', {'data': data}));
-        },
-        stop: function () {
-            that.iframe_close({}, 'network');
-        }
-    };
-    that.iframe_close = function(e, abort_reason) {
-        iframeObj.cleanup();
-        that.iframe_close = iframeObj = null;
-        delete _window[WPrefix][that.id];
-        that.dispatchEvent(new SimpleEvent('close', {reason: abort_reason}));
-    };
-    iframeObj = constructor(url, function(e) {
-                                that.iframe_close({}, 'permanent');
-                            });
-};
-
-HtmlfileReceiver.prototype = new REventTarget();
-
-HtmlfileReceiver.prototype.abort = function() {
-    var that = this;
-    if (that.iframe_close) {
-        that.iframe_close({}, 'user');
-    }
-};
-//         [*] End of lib/trans-receiver-htmlfile.js
-
-
-//         [*] Including lib/trans-receiver-xhr.js
-/*
- * ***** BEGIN LICENSE BLOCK *****
- * Copyright (c) 2011-2012 VMware, Inc.
- *
- * For the license see COPYING.
- * ***** END LICENSE BLOCK *****
- */
-
-var XhrReceiver = function(url, AjaxObject) {
-    var that = this;
-    var buf_pos = 0;
-
-    that.xo = new AjaxObject('POST', url, null);
-    that.xo.onchunk = function(status, text) {
-        if (status !== 200) return;
-        while (1) {
-            var buf = text.slice(buf_pos);
-            var p = buf.indexOf('\n');
-            if (p === -1) break;
-            buf_pos += p+1;
-            var msg = buf.slice(0, p);
-            that.dispatchEvent(new SimpleEvent('message', {data: msg}));
-        }
-    };
-    that.xo.onfinish = function(status, text) {
-        that.xo.onchunk(status, text);
-        that.xo = null;
-        var reason = status === 200 ? 'network' : 'permanent';
-        that.dispatchEvent(new SimpleEvent('close', {reason: reason}));
-    }
-};
-
-XhrReceiver.prototype = new REventTarget();
-
-XhrReceiver.prototype.abort = function() {
-    var that = this;
-    if (that.xo) {
-        that.xo.close();
-        that.dispatchEvent(new SimpleEvent('close', {reason: 'user'}));
-        that.xo = null;
-    }
-};
-//         [*] End of lib/trans-receiver-xhr.js
-
-
-//         [*] Including lib/test-hooks.js
-/*
- * ***** BEGIN LICENSE BLOCK *****
- * Copyright (c) 2011-2012 VMware, Inc.
- *
- * For the license see COPYING.
- * ***** END LICENSE BLOCK *****
- */
-
-// For testing
-SockJS.getUtils = function(){
-    return utils;
-};
-
-SockJS.getIframeTransport = function(){
-    return IframeTransport;
-};
-//         [*] End of lib/test-hooks.js
-
-                  return SockJS;
-          })();
-if ('_sockjs_onload' in window) setTimeout(_sockjs_onload, 1);
-
-// AMD compliance
-if (typeof define === 'function' && define.amd) {
-    define('sockjs', [], function(){return SockJS;});
-}
-//     [*] End of lib/index.js
-
-// [*] End of lib/all.js
diff --git a/cas/cas-server/src/main/resources/static/js/ssosessions.js b/cas/cas-server/src/main/resources/static/js/ssosessions.js
deleted file mode 100644
index 84224b28d49817c4bd3cc5371cbe7c2876d23f83..0000000000000000000000000000000000000000
--- a/cas/cas-server/src/main/resources/static/js/ssosessions.js
+++ /dev/null
@@ -1,351 +0,0 @@
-/*eslint-disable no-unused-vars*/
-String.prototype.padLeft = function (length, character) {
-    return new Array(length - this.length + 1).join(character || ' ') + this;
-};
-
-Date.prototype.toFormattedString = function () {
-    return [String(this.getMonth() + 1).padLeft(2, '0'),
-        String(this.getDate()).padLeft(2, '0'),
-        String(this.getFullYear()).substr(2, 2)].join('/') + ' ' +
-          [String(this.getHours()).padLeft(2, '0'),
-              String(this.getMinutes()).padLeft(2, '0')].join(':');
-};
-
-function principalAttributes(obj) {
-    var output = '<table class="table table-condensed principal_attributes"><tbody>';
-    for (var key in obj) {
-        if (obj.hasOwnProperty(key)) {
-            if (Array.isArray(obj[key])) {
-                output = output.concat('<tr><td class="field-label active">' + key + '</td><td>' + obj[key].toString() + '</td></tr>');
-            } else {
-                output = output.concat('<tr><td class="field-label active">' + key + '</td><td>' + obj[key] + '</td></tr>');
-            }
-        }
-    }
-    output = output.concat('</tbody></table>');
-
-    return output;
-}
-
-function authenticatedServices(obj) {
-    var output = '';
-    for (var key in obj) {
-        if (obj.hasOwnProperty(key)) {
-            output = output.concat('<h5>' + key + '</h5><table class="table table-condensed principal_attributes"><tbody>');
-            for (var foo in obj[key]) {
-                if (obj[key].hasOwnProperty(foo)) {
-                    if (Array.isArray(obj[key][foo])) {
-                        output = output.concat('<tr><td class="field-label active">' + foo + ':</td><td>' + obj[key][foo].toString() + '</td></tr>');
-                    } else {
-                        output = output.concat('<tr><td class="field-label active">' + foo + ':</td><td>' + obj[key][foo] + '</td></tr>');
-                    }
-                }
-            }
-            output = output.concat('</tbody></table>');
-        }
-    }
-    return output;
-}
-
-/* Formatting function for row details - modify as you need */
-function format(d) {
-    return '<table class="table table-bordered row-detail">' +
-      '<tbody>' +
-      '<tr class="hidden-md hidden-lg">' +
-      '<td class="field-label active">Access Date:</td>' +
-      '<td>' + d.authentication_date_formatted + '</td>' +
-      '</tr>' +
-      '<tr class="hidden-md hidden-lg">' +
-      '<td class="field-label active">Usage Count:</td>' +
-      '<td>' + d.number_of_uses + '</td>' +
-      '</tr>' +
-      '<tr>' +
-      '<td class="field-label active">Ticket Granting Ticket:</td>' +
-      '<td>' + d.ticket_granting_ticket + '</td>' +
-      '</tr>' +
-      '<tr>' +
-      '<td class="field-label active">Principal Attributes:</td>' +
-      '<td>' +
-      principalAttributes(d.principal_attributes) +
-      '</td>' +
-      '</tr>' +
-      '<tr>' +
-      '<td class="field-label active">Authenticated Services:</td>' +
-      '<td>' +
-      authenticatedServices(d.authenticated_services) +
-      '</td>' +
-      '</tr>' +
-      '<tr>' +
-      '<td class="field-label active">Ticket Granting Service:</td>' +
-      '<td></td>' +
-      '</tr>' +
-      '</tbody></table>';
-
-}
-
-function updateAdminPanels(data) {
-    //$('#totalUsers').text(data.totalPrincipals);
-    $('#totalUsers').text(data.activeSsoSessions.length);
-    $('#totalUsageSessions').text(sum(data.activeSsoSessions, 'number_of_uses'));
-    //$('#totalProxied').text(data.totalTicketGrantingTickets);
-    $('#totalTGTs').text(data.totalTicketGrantingTickets);
-    //$('#totalTGTs').text( sum(data.activeSsoSessions, 'is_proxied' ) );
-}
-
-function sum(obj, prop) {
-    var sum = 0;
-    for (var el in obj) {
-        if (obj.hasOwnProperty(el)) {
-            sum += ( typeof obj[el][prop] == 'boolean' ) ? +obj[el][prop] : obj[el][prop];
-        }
-    }
-    return sum;
-}
-
-/*
- function showError(msg) {
- $('#msg').removeClass();
- $('#msg').addClass('errors');
- $('#msg').text(msg);
- $('#msg').show();
- }
- */
-
-/*
- function showInfo(msg) {
- $('#msg').removeClass();
- $('#msg').addClass('info');
- $('#msg').text(msg);
- $('#msg').show();
- }
- */
-
-function alertUser(message, alertType) {
-    $('#alertWrapper').append('<div id="alertdiv" class="alert alert-' + alertType + ' alert-dismissible">' +
-      '<button type="button" class="close" data-dismiss="alert" aria-label="Close"><span aria-hidden="true">&times;</span></button>' +
-      '<span class="alertMessage">' + message + '</span></div>'
-    );
-
-    setTimeout(function () { // this will automatically close the alert and remove this if the users doesnt close it in 5 secs
-        $('#alertdiv').remove();
-    }, 5000);
-}
-
-function removeSession(ticketId) {
-    var factory = {};
-    factory.httpHeaders = {};
-    factory.messages = {};
-    factory.httpHeaders[$('meta[name=\'_csrf_header\']').attr('content')] = $('meta[name=\'_csrf\']').attr('content');
-
-    factory.ticketId = ticketId;
-
-
-    if (ticketId && (ticketId == 'ALL' || ticketId == 'PROXIED' || ticketId == 'DIRECT' )) {
-        factory.url = urls.destroy.all;
-        factory.data = {type: ticketId};
-        factory.messages.success = 'Removed <strong>' + ticketId + '</strong> tickets successfully.';
-        factory.messages.error = 'Could not remove <strong>' + ticketId + '</strong> tickets.';
-    } else {
-        factory.url = urls.destroy.single;
-        factory.data = {ticketGrantingTicket: factory.ticketId};
-        factory.messages.success = 'Ticket is removed successfully.';
-        factory.messages.error = 'Ticket is not removed successfully.';
-    }
-
-    $.ajax({
-        type: 'post',
-        url: factory.url,
-        //data: { ticketGrantingTicket: factory.ticketId, type: 'ALL' },
-        data: factory.data,
-        headers: factory.httpHeaders,
-        dataType: 'json',
-        success: function (data) {
-            // Reinitialize the table data
-            $('#ssoSessions').DataTable().ajax.reload();
-
-            if (data.status != 200) {
-                alertUser(factory.messages.error, 'danger');
-            } else {
-                alertUser(factory.messages.success, 'success');
-                // Reload the page
-                location.reload();
-            }
-        },
-        error: function () {
-            alertUser('There appears to be an error. Please try your request again.', 'danger');
-        }
-    });
-}
-
-var ssoSessions = (function () {
-    var createDataTable = function () {
-        $('#ssoSessions').DataTable({
-            'order': [[3, 'desc']],
-            'initComplete': function (settings, json) {
-                if (!json || json.activeSsoSessions.length == 0) {
-                    $('#loadingMessage').hide();
-                    $('#no-cas-sessions').show();
-                } else {
-                    updateAdminPanels(json);
-
-                    $('#loadingMessage').hide();
-                    $('#no-cas-sessions').hide();
-                    $('#cas-sessions').show();
-                }
-            },
-            'language': {
-                //"infoEmpty": "No active sessions were found",
-                'emptyTable': 'No sessions found',
-                'zeroRecords': 'No matching sessions found'
-            },
-            'processing': true,
-            'ajax': {
-                'url': urls.getSessions,
-                'dataSrc': 'activeSsoSessions'
-            },
-
-            columnDefs: [
-                {
-                    'targets': 0,
-                    'className': 'details-control',
-                    'orderable': false,
-                    'data': null,
-                    'defaultContent': ''
-                },
-                {
-                    'targets': 1,
-                    'data': 'is_proxied',
-                    'className': 'col-xs-2 col-md-1',
-                    'render': function (data) {
-                        if (data === true) {
-                            return '<span class="label label-primary">Proxy</span>';
-                        } else {
-                            return ' ';
-                        }
-                    }
-                },
-                {
-                    'targets': 2,
-                    'data': 'authenticated_principal',
-                    'className': 'col-xs-4 col-md-2',
-                    'render': function (data, type) {
-                        return type === 'display' && data.length > 20 ?
-                            '<span title="' + data + '">' + data.substr(0, 18) + '...</span>' :
-                            data;
-                    }
-                },
-                {
-                    'targets': 3,
-                    'data': 'ticket_granting_ticket',
-                    'className': 'hidden-xs hidden-sm col-md-4',
-                    'render': function (data, type) {
-                        return type === 'display' && data.length > 20 ?
-                            '<span title="' + data + '">' + data.substr(0, 40) + '...</span>' :
-                            data;
-                    }
-                },
-                {
-                    'targets': 4,
-                    'data': 'authentication_date_formatted',
-                    'className': 'col-xs-4 col-sm-4 col-md-2'
-                },
-                {
-                    'targets': 5,
-                    'data': 'number_of_uses',
-                    'className': 'hidden-xs hidden-sm visible-md-* col-md-2'
-                },
-                {
-                    'targets': 6,
-                    'data': 'ticket_granting_ticket',
-                    'className': 'col-xs-2 col-sm-2 col-md-1',
-                    'render': function (data) {
-                        return '<button class="btn btn-xs btn-block btn-danger" type="button" value="' + data + '">Destroy</button>';
-                    },
-                    'orderable': false
-                },
-            ]
-        });
-    };
-
-    var addEventHandlers = function () {
-
-        /**
-         * The Bulk remove button
-         */
-        $('#removeAllSessionsButton').on('click', function (e) {
-            e.preventDefault();
-            removeSession(this.value);
-        });
-
-        /**
-         * Individual removal button
-         */
-        $(document).on('click', '#ssoSessions tbody tr td:last-child button.btn-danger', function (e) {
-            e.preventDefault();
-            removeSession(this.value);
-        });
-
-        /**
-         * The filter buttons
-         */
-        $('#filterButtons .btn').click(function () {
-
-            var filter = $(this).data('filter');
-            var table = $('#ssoSessions').DataTable();
-            var filterRegex;
-            var deleteValue;
-            var btnText;
-
-            // Create Filter RegEx:
-            if (filter == 'proxied') {
-                filterRegex = '^Proxy$';
-                deleteValue = 'PROXIED';
-                btnText = 'Remove <span class="badge">xx</span> Proxied Sessions';
-            } else if (filter == 'non-proxied') {
-                filterRegex = '^ $';
-                deleteValue = 'DIRECT';
-                btnText = 'Remove <span class="badge">xx</span> Non-Proxied Sessions';
-            } else {
-                filterRegex = '';
-                deleteValue = 'ALL';
-                btnText = 'Remove All Sessions';
-            }
-
-            var searchTerm = table.column(1).search(filterRegex, true, false).draw();
-
-            $('#removeAllSessionsButton').val(deleteValue).html(btnText.replace('xx', searchTerm.page.info().recordsDisplay));
-        });
-
-
-        // Add event listener for opening and closing details
-        $(document).on('click', '#ssoSessions tbody td.details-control', function () {
-            var table = $('#ssoSessions').DataTable();
-            var tr = $(this).closest('tr');
-            var row = table.row(tr);
-
-            if (row.child.isShown()) {
-                // This row is already open - close it
-                row.child.hide();
-                tr.removeClass('shown');
-            }
-            else {
-                // Open this row
-                row.child(format(row.data()), 'info').show();
-                tr.addClass('shown');
-            }
-        });
-    };
-
-    // initialization *******
-    (function init() {
-        addEventHandlers();
-        createDataTable();
-    })();
-
-    // Public Methods
-    return {
-        /**
-         * Not used
-         */
-    };
-})();
diff --git a/cas/cas-server/src/main/resources/static/js/statisticsview.js b/cas/cas-server/src/main/resources/static/js/statisticsview.js
deleted file mode 100644
index e493211fe661ce0ca6a0fa94118941d32054e088..0000000000000000000000000000000000000000
--- a/cas/cas-server/src/main/resources/static/js/statisticsview.js
+++ /dev/null
@@ -1,208 +0,0 @@
-/* global d3 */
-/*eslint-disable no-unused-vars*/
-var Gauge = function (wrapper, percent, options) {
-    if (!wrapper || !percent) {
-        //console.error('wrapper and percentage are required.  Please check your code.');
-        return;
-    }
-
-    var label = (!options.label) ? '' : options.label;
-
-    var textClass = options.textClass || 'progress-meter';
-
-    var width = options.width || 200,
-        height = options.height || 200,
-        twoPi = 2 * Math.PI,
-        progress = 0,
-        total = 100,
-        formatPercent = d3.format('.0%');
-
-    var colorScale = d3.scaleLinear()
-        .domain([0, 0.40, 0.50, 1])
-        .range(['green', 'green', 'goldenrod', 'red']);
-
-    var arc = d3.arc()
-        .startAngle(0)
-        .innerRadius(width * 0.4)
-        .outerRadius(width * 0.5)
-        ;
-
-    var svg = d3.select(wrapper).append('svg')
-        .attr('width', width)
-        .attr('height', height)
-
-        .attr('fill', '#2E7AF9')
-        .append('g')
-        .attr('transform', 'translate(' + width / 2 + ',' + height / 2 + ')');
-
-    var meter = svg.append('g')
-        .attr('class', textClass);
-
-    meter.append('path')
-        .attr('class', 'background')
-        .attr('d', arc.endAngle(twoPi));
-
-    var foreground = meter.append('path')
-        .attr('class', 'foreground');
-
-    var text = meter.append('text')
-        .attr('text-anchor', 'middle');
-
-    var text2 = meter.append('text')
-        .attr('y', height * 0.15)
-        .attr('text-anchor', 'middle')
-        .attr('class', 'text2');
-
-    text2.text(label);
-
-    var animate = function (percentage) {
-        var i = d3.interpolate(progress, percentage);
-
-        foreground.transition().duration(2000)
-            .tween('progress', function () {
-
-                return function (t) {
-                    progress = i(t);
-
-                    foreground.style('fill', colorScale(progress));
-                    foreground.attr('d', arc.endAngle(twoPi * progress));
-                    text.text(formatPercent(progress));
-                };
-            });
-    };
-
-    // init
-    (function () {
-        setTimeout(function () {
-            animate(percent);
-        }, 500);
-    })();
-
-    return {
-        update: function (newPercent) {
-            animate(newPercent);
-        }
-    };
-};
-
-
-function upTime(countTo, el) {
-    var wrapper = document.getElementById('card-uptime');
-    var element = document.getElementById(el);
-    var difference = new Date(countTo*1000);
-
-    var days = Math.floor(difference / (60 * 60 * 1000 * 24) * 1);
-    var hours = Math.floor((difference % (60 * 60 * 1000 * 24)) / (60 * 60 * 1000) * 1);
-    var mins = Math.floor(((difference % (60 * 60 * 1000 * 24)) % (60 * 60 * 1000)) / (60 * 1000) * 1);
-    var secs = Math.floor((((difference % (60 * 60 * 1000 * 24)) % (60 * 60 * 1000)) % (60 * 1000)) / 1000 * 1);
-
-    clearTimeout(upTime.to);
-
-    if (isNaN(days) || isNaN(hours) || isNaN(mins) || isNaN(secs) ) {
-        wrapper.style.display = 'none';
-    } else {
-        days = (days == 1) ? days + ' day ' : days + ' days ';
-        hours = (hours == 1) ? hours + ' hour ' : hours + ' hours ';
-        mins = (mins == 1) ? mins + ' minute ' : mins + ' minutes ';
-        secs = (secs == 1) ? secs + ' second ' : secs + ' seconds';
-
-        var timeString = '<span class="upTime">' + days + hours + mins + secs + '</span>';
-        element.innerHTML = timeString;
-        wrapper.style.display = 'block';
-
-        upTime.to = setTimeout(function() {
-            countTo = countTo + 1;
-            upTime(countTo, el);
-        },1000);
-
-    }
-}
-
-var analytics = document.getElementById('expiredSts');
-
-var casStatistics = function (urls, messages) {
-    var timers = {
-        memory: 5000,
-        availability: 15000,
-        tickets: 5000
-    };
-
-    var memoryGauage;
-
-    var getRemoteJSON = function(url) {
-        return $.getJSON( url);
-    };
-
-    var tickets = function() {
-        var data = getRemoteJSON(urls.tickets);
-        data.done(function( data ) {
-            updateElementValue( 'unexpiredTgts', data.unexpiredTgts );
-            updateElementValue( 'unexpiredSts', data.unexpiredSts );
-            updateElementValue( 'expiredTgts', data.expiredTgts );
-            updateElementValue( 'expiredSts', data.expiredSts );
-            setTimeout( tickets, timers.tickets );
-        });
-    };
-
-    var updateElementValue = function(el, val) {
-        $( '#' + el ).text( val );
-    };
-
-    var memory = function() {
-        var data = getRemoteJSON(urls.memory);
-        data.done(function( data ) {
-            updateElementValue('freeMemory', data.freeMemory.toFixed(2));
-            // updateElementValue('totalMemory', data.totalMemory);
-            // updateElementValue('maxMemory', data.maxMemory);
-            // updateElementValue('availableProcessors', data.availableProcessors);
-
-            var memCalc = (data.totalMemory / data.maxMemory).toFixed(2);
-
-            if ( !memoryGauage ) {
-                memoryGauage = new Gauge('#maxMemoryGauge', memCalc, {width: 200, height: 200,
-                    label: messages.memoryGaugeTitle,
-                    textClass: 'runtimeStatistics'});
-            } else {
-                memoryGauage.update( memCalc );
-            }
-
-            setTimeout( memory, timers.memory );
-        });
-
-    };
-    var availability = function() {
-        var data = getRemoteJSON(urls.availability);
-        data.done(function( data ) {
-            updateElementValue('upTime', data.upTime);
-            setTimeout( availability, timers.availability );
-        });
-    };
-
-    // initialization *******
-    ( function init () {
-        $('#loading, .statisticsView').toggle();
-        tickets();
-        memory();
-        // availability();
-    })();
-
-    // Public Methods
-    return {
-        getTickets: function() {
-            return tickets();
-        },
-        getMemory: function() {
-            return memory();
-        },
-        getAvailability: function() {
-            return availability();
-        },
-        updateGauge: function(val){
-            if (memoryGauage) {
-                memoryGauage.update( val );
-            } else {
-                return 'unable to update';
-            }
-        }
-    };
-};
diff --git a/cas/cas-server/src/main/resources/static/js/stomp.js b/cas/cas-server/src/main/resources/static/js/stomp.js
deleted file mode 100644
index 26a8163630de213591f347663286fdeaa1092b90..0000000000000000000000000000000000000000
--- a/cas/cas-server/src/main/resources/static/js/stomp.js
+++ /dev/null
@@ -1,474 +0,0 @@
-// Generated by CoffeeScript 1.7.1
-
-/*
-   Stomp Over WebSocket http://www.jmesnil.net/stomp-websocket/doc/ | Apache License V2.0
-
-   Copyright (C) 2010-2013 [Jeff Mesnil](http://jmesnil.net/)
-   Copyright (C) 2012 [FuseSource, Inc.](http://fusesource.com)
- */
-
-(function() {
-  var Byte, Client, Frame, Stomp,
-    __hasProp = {}.hasOwnProperty,
-    __slice = [].slice;
-
-  Byte = {
-    LF: '\x0A',
-    NULL: '\x00'
-  };
-
-  Frame = (function() {
-    var unmarshallSingle;
-
-    function Frame(command, headers, body) {
-      this.command = command;
-      this.headers = headers != null ? headers : {};
-      this.body = body != null ? body : '';
-    }
-
-    Frame.prototype.toString = function() {
-      var lines, name, value, _ref;
-      lines = [this.command];
-      _ref = this.headers;
-      for (name in _ref) {
-        if (!__hasProp.call(_ref, name)) continue;
-        value = _ref[name];
-        lines.push("" + name + ":" + value);
-      }
-      if (this.body) {
-        lines.push("content-length:" + (Frame.sizeOfUTF8(this.body)));
-      }
-      lines.push(Byte.LF + this.body);
-      return lines.join(Byte.LF);
-    };
-
-    Frame.sizeOfUTF8 = function(s) {
-      if (s) {
-        return encodeURI(s).split(/%..|./).length - 1;
-      } else {
-        return 0;
-      }
-    };
-
-    unmarshallSingle = function(data) {
-      var body, chr, command, divider, headerLines, headers, i, idx, len, line, start, trim, _i, _j, _len, _ref, _ref1;
-      divider = data.search(RegExp("" + Byte.LF + Byte.LF));
-      headerLines = data.substring(0, divider).split(Byte.LF);
-      command = headerLines.shift();
-      headers = {};
-      trim = function(str) {
-        return str.replace(/^\s+|\s+$/g, '');
-      };
-      _ref = headerLines.reverse();
-      for (_i = 0, _len = _ref.length; _i < _len; _i++) {
-        line = _ref[_i];
-        idx = line.indexOf(':');
-        headers[trim(line.substring(0, idx))] = trim(line.substring(idx + 1));
-      }
-      body = '';
-      start = divider + 2;
-      if (headers['content-length']) {
-        len = parseInt(headers['content-length']);
-        body = ('' + data).substring(start, start + len);
-      } else {
-        chr = null;
-        for (i = _j = start, _ref1 = data.length; start <= _ref1 ? _j < _ref1 : _j > _ref1; i = start <= _ref1 ? ++_j : --_j) {
-          chr = data.charAt(i);
-          if (chr === Byte.NULL) {
-            break;
-          }
-          body += chr;
-        }
-      }
-      return new Frame(command, headers, body);
-    };
-
-    Frame.unmarshall = function(datas) {
-      var data;
-      return (function() {
-        var _i, _len, _ref, _results;
-        _ref = datas.split(RegExp("" + Byte.NULL + Byte.LF + "*"));
-        _results = [];
-        for (_i = 0, _len = _ref.length; _i < _len; _i++) {
-          data = _ref[_i];
-          if ((data != null ? data.length : void 0) > 0) {
-            _results.push(unmarshallSingle(data));
-          }
-        }
-        return _results;
-      })();
-    };
-
-    Frame.marshall = function(command, headers, body) {
-      var frame;
-      frame = new Frame(command, headers, body);
-      return frame.toString() + Byte.NULL;
-    };
-
-    return Frame;
-
-  })();
-
-  Client = (function() {
-    var now;
-
-    function Client(ws) {
-      this.ws = ws;
-      this.ws.binaryType = "arraybuffer";
-      this.counter = 0;
-      this.connected = false;
-      this.heartbeat = {
-        outgoing: 10000,
-        incoming: 10000
-      };
-      this.maxWebSocketFrameSize = 16 * 1024;
-      this.subscriptions = {};
-    }
-
-    Client.prototype.debug = function(message) {
-      void 0;
-    };
-
-    now = function() {
-      return Date.now || new Date().valueOf;
-    };
-
-    Client.prototype._transmit = function(command, headers, body) {
-      var out;
-      out = Frame.marshall(command, headers, body);
-      if (typeof this.debug === "function") {
-        this.debug(">>> " + out);
-      }
-      while (true) {
-        if (out.length > this.maxWebSocketFrameSize) {
-          this.ws.send(out.substring(0, this.maxWebSocketFrameSize));
-          out = out.substring(this.maxWebSocketFrameSize);
-          if (typeof this.debug === "function") {
-            this.debug("remaining = " + out.length);
-          }
-        } else {
-          return this.ws.send(out);
-        }
-      }
-    };
-
-    Client.prototype._setupHeartbeat = function(headers) {
-      var serverIncoming, serverOutgoing, ttl, v, _ref, _ref1;
-      if ((_ref = headers.version) !== Stomp.VERSIONS.V1_1 && _ref !== Stomp.VERSIONS.V1_2) {
-        return;
-      }
-      _ref1 = (function() {
-        var _i, _len, _ref1, _results;
-        _ref1 = headers['heart-beat'].split(",");
-        _results = [];
-        for (_i = 0, _len = _ref1.length; _i < _len; _i++) {
-          v = _ref1[_i];
-          _results.push(parseInt(v));
-        }
-        return _results;
-      })(), serverOutgoing = _ref1[0], serverIncoming = _ref1[1];
-      if (!(this.heartbeat.outgoing === 0 || serverIncoming === 0)) {
-        ttl = Math.max(this.heartbeat.outgoing, serverIncoming);
-        if (typeof this.debug === "function") {
-          this.debug("send PING every " + ttl + "ms");
-        }
-        this.pinger = Stomp.setInterval(ttl, (function(_this) {
-          return function() {
-            _this.ws.send(Byte.LF);
-            return typeof _this.debug === "function" ? _this.debug(">>> PING") : void 0;
-          };
-        })(this));
-      }
-      if (!(this.heartbeat.incoming === 0 || serverOutgoing === 0)) {
-        ttl = Math.max(this.heartbeat.incoming, serverOutgoing);
-        if (typeof this.debug === "function") {
-          this.debug("check PONG every " + ttl + "ms");
-        }
-        return this.ponger = Stomp.setInterval(ttl, (function(_this) {
-          return function() {
-            var delta;
-            delta = now() - _this.serverActivity;
-            if (delta > ttl * 2) {
-              if (typeof _this.debug === "function") {
-                _this.debug("did not receive server activity for the last " + delta + "ms");
-              }
-              return _this.ws.close();
-            }
-          };
-        })(this));
-      }
-    };
-
-    Client.prototype._parseConnect = function() {
-      var args, connectCallback, errorCallback, headers;
-      args = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
-      headers = {};
-      switch (args.length) {
-        case 2:
-          headers = args[0], connectCallback = args[1];
-          break;
-        case 3:
-          if (args[1] instanceof Function) {
-            headers = args[0], connectCallback = args[1], errorCallback = args[2];
-          } else {
-            headers.login = args[0], headers.passcode = args[1], connectCallback = args[2];
-          }
-          break;
-        case 4:
-          headers.login = args[0], headers.passcode = args[1], connectCallback = args[2], errorCallback = args[3];
-          break;
-        default:
-          headers.login = args[0], headers.passcode = args[1], connectCallback = args[2], errorCallback = args[3], headers.host = args[4];
-      }
-      return [headers, connectCallback, errorCallback];
-    };
-
-    Client.prototype.connect = function() {
-      var args, errorCallback, headers, out;
-      args = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
-      out = this._parseConnect.apply(this, args);
-      headers = out[0], this.connectCallback = out[1], errorCallback = out[2];
-      if (typeof this.debug === "function") {
-        this.debug("Opening Web Socket...");
-      }
-      this.ws.onmessage = (function(_this) {
-        return function(evt) {
-          var arr, c, client, data, frame, messageID, onreceive, subscription, _i, _len, _ref, _results;
-          data = typeof ArrayBuffer !== 'undefined' && evt.data instanceof ArrayBuffer ? (arr = new Uint8Array(evt.data), typeof _this.debug === "function" ? _this.debug("--- got data length: " + arr.length) : void 0, ((function() {
-            var _i, _len, _results;
-            _results = [];
-            for (_i = 0, _len = arr.length; _i < _len; _i++) {
-              c = arr[_i];
-              _results.push(String.fromCharCode(c));
-            }
-            return _results;
-          })()).join('')) : evt.data;
-          _this.serverActivity = now();
-          if (data === Byte.LF) {
-            if (typeof _this.debug === "function") {
-              _this.debug("<<< PONG");
-            }
-            return;
-          }
-          if (typeof _this.debug === "function") {
-            _this.debug("<<< " + data);
-          }
-          _ref = Frame.unmarshall(data);
-          _results = [];
-          for (_i = 0, _len = _ref.length; _i < _len; _i++) {
-            frame = _ref[_i];
-            switch (frame.command) {
-              case "CONNECTED":
-                if (typeof _this.debug === "function") {
-                  _this.debug("connected to server " + frame.headers.server);
-                }
-                _this.connected = true;
-                _this._setupHeartbeat(frame.headers);
-                _results.push(typeof _this.connectCallback === "function" ? _this.connectCallback(frame) : void 0);
-                break;
-              case "MESSAGE":
-                subscription = frame.headers.subscription;
-                onreceive = _this.subscriptions[subscription] || _this.onreceive;
-                if (onreceive) {
-                  client = _this;
-                  messageID = frame.headers["message-id"];
-                  frame.ack = function(headers) {
-                    if (headers == null) {
-                      headers = {};
-                    }
-                    return client.ack(messageID, subscription, headers);
-                  };
-                  frame.nack = function(headers) {
-                    if (headers == null) {
-                      headers = {};
-                    }
-                    return client.nack(messageID, subscription, headers);
-                  };
-                  _results.push(onreceive(frame));
-                } else {
-                  _results.push(typeof _this.debug === "function" ? _this.debug("Unhandled received MESSAGE: " + frame) : void 0);
-                }
-                break;
-              case "RECEIPT":
-                _results.push(typeof _this.onreceipt === "function" ? _this.onreceipt(frame) : void 0);
-                break;
-              case "ERROR":
-                _results.push(typeof errorCallback === "function" ? errorCallback(frame) : void 0);
-                break;
-              default:
-                _results.push(typeof _this.debug === "function" ? _this.debug("Unhandled frame: " + frame) : void 0);
-            }
-          }
-          return _results;
-        };
-      })(this);
-      this.ws.onclose = (function(_this) {
-        return function() {
-          var msg;
-          msg = "Whoops! Lost connection to " + _this.ws.url;
-          if (typeof _this.debug === "function") {
-            _this.debug(msg);
-          }
-          _this._cleanUp();
-          return typeof errorCallback === "function" ? errorCallback(msg) : void 0;
-        };
-      })(this);
-      return this.ws.onopen = (function(_this) {
-        return function() {
-          if (typeof _this.debug === "function") {
-            _this.debug('Web Socket Opened...');
-          }
-          headers["accept-version"] = Stomp.VERSIONS.supportedVersions();
-          headers["heart-beat"] = [_this.heartbeat.outgoing, _this.heartbeat.incoming].join(',');
-          return _this._transmit("CONNECT", headers);
-        };
-      })(this);
-    };
-
-    Client.prototype.disconnect = function(disconnectCallback) {
-      this._transmit("DISCONNECT");
-      this.ws.onclose = null;
-      this.ws.close();
-      this._cleanUp();
-      return typeof disconnectCallback === "function" ? disconnectCallback() : void 0;
-    };
-
-    Client.prototype._cleanUp = function() {
-      this.connected = false;
-      if (this.pinger) {
-        Stomp.clearInterval(this.pinger);
-      }
-      if (this.ponger) {
-        return Stomp.clearInterval(this.ponger);
-      }
-    };
-
-    Client.prototype.send = function(destination, headers, body) {
-      if (headers == null) {
-        headers = {};
-      }
-      if (body == null) {
-        body = '';
-      }
-      headers.destination = destination;
-      return this._transmit("SEND", headers, body);
-    };
-
-    Client.prototype.subscribe = function(destination, callback, headers) {
-      var client;
-      if (headers == null) {
-        headers = {};
-      }
-      if (!headers.id) {
-        headers.id = "sub-" + this.counter++;
-      }
-      headers.destination = destination;
-      this.subscriptions[headers.id] = callback;
-      this._transmit("SUBSCRIBE", headers);
-      client = this;
-      return {
-        id: headers.id,
-        unsubscribe: function() {
-          return client.unsubscribe(headers.id);
-        }
-      };
-    };
-
-    Client.prototype.unsubscribe = function(id) {
-      delete this.subscriptions[id];
-      return this._transmit("UNSUBSCRIBE", {
-        id: id
-      });
-    };
-
-    Client.prototype.begin = function(transaction) {
-      var client, txid;
-      txid = transaction || "tx-" + this.counter++;
-      this._transmit("BEGIN", {
-        transaction: txid
-      });
-      client = this;
-      return {
-        id: txid,
-        commit: function() {
-          return client.commit(txid);
-        },
-        abort: function() {
-          return client.abort(txid);
-        }
-      };
-    };
-
-    Client.prototype.commit = function(transaction) {
-      return this._transmit("COMMIT", {
-        transaction: transaction
-      });
-    };
-
-    Client.prototype.abort = function(transaction) {
-      return this._transmit("ABORT", {
-        transaction: transaction
-      });
-    };
-
-    Client.prototype.ack = function(messageID, subscription, headers) {
-      if (headers == null) {
-        headers = {};
-      }
-      headers["message-id"] = messageID;
-      headers.subscription = subscription;
-      return this._transmit("ACK", headers);
-    };
-
-    Client.prototype.nack = function(messageID, subscription, headers) {
-      if (headers == null) {
-        headers = {};
-      }
-      headers["message-id"] = messageID;
-      headers.subscription = subscription;
-      return this._transmit("NACK", headers);
-    };
-
-    return Client;
-
-  })();
-
-  Stomp = {
-    VERSIONS: {
-      V1_0: '1.0',
-      V1_1: '1.1',
-      V1_2: '1.2',
-      supportedVersions: function() {
-        return '1.1,1.0';
-      }
-    },
-    client: function(url, protocols) {
-      var klass, ws;
-      if (protocols == null) {
-        protocols = ['v10.stomp', 'v11.stomp'];
-      }
-      klass = Stomp.WebSocketClass || WebSocket;
-      ws = new klass(url, protocols);
-      return new Client(ws);
-    },
-    over: function(ws) {
-      return new Client(ws);
-    },
-    Frame: Frame
-  };
-
-  if (typeof window !== "undefined" && window !== null) {
-    Stomp.setInterval = function(interval, f) {
-      return window.setInterval(f, interval);
-    };
-    Stomp.clearInterval = function(id) {
-      return window.clearInterval(id);
-    };
-    window.Stomp = Stomp;
-  } else if (typeof exports !== "undefined" && exports !== null) {
-    exports.Stomp = Stomp;
-  } else {
-    self.Stomp = Stomp;
-  }
-
-}).call(this);
diff --git a/cas/cas-server/src/main/resources/static/js/trustedDevices.js b/cas/cas-server/src/main/resources/static/js/trustedDevices.js
deleted file mode 100644
index 7fdbdc94c9c0d7602fc3240a6cedfec15b8c8699..0000000000000000000000000000000000000000
--- a/cas/cas-server/src/main/resources/static/js/trustedDevices.js
+++ /dev/null
@@ -1,59 +0,0 @@
-/*eslint-disable no-unused-vars*/
-$('#myTabs a').click(function (e) {
-    e.preventDefault();
-    $(this).tab('show');
-});
-
-var revokeDevice = function (key) {
-    $.ajax({
-        type: 'post',
-        url: urls.revokeRecord,
-        data: {'key': key},
-        success: function () {
-            var table = $('#trustedDevicesTable').DataTable();
-            table
-                .rows($('#' + key).parents('tr'))
-                .remove()
-                .draw();
-        },
-        error: function () {
-            //console.log('Could not remove record');
-        }
-    });
-};
-
-var trustedDevices = (function () {
-    var getData = function () {
-        $.getJSON(urls.getRecords, function (data) {
-            trustedDevicesTable(data);
-        });
-    };
-
-    var trustedDevicesTable = function (jsonData) {
-        var t = $('#trustedDevicesTable').DataTable({
-            'order': [[2, 'desc']],
-            columnDefs: [
-                {'width': '20%', 'targets': 0},
-                {'width': '10%', 'targets': 1},
-                {'width': '60%', 'targets': 2},
-                {'width': '10%', 'targets': 3},
-                {'width': '30%', 'targets': 4}
-            ]
-        });
-        for (var i = 0; i < jsonData.length; i++) {
-            var rec = jsonData[i];
-            t.row.add([
-                rec.name,
-                rec.principal,
-                new Date(rec.date),
-                rec.geography,
-                '<button id=\'' + rec.key + '\' class=\'btn btn-sm btn-danger\' type=\'button\' value=\'ALL\' onclick=\'revokeDevice("' + rec.key + '")\'>Revoke</button>'
-            ]).draw(false);
-        }
-    };
-
-    // initialization *******
-    (function init() {
-        getData();
-    })();
-})();
diff --git a/cas/cas-server/src/main/resources/static/js/viewConfig.js b/cas/cas-server/src/main/resources/static/js/viewConfig.js
deleted file mode 100644
index ad69c9bcbd52a82621d7c9e080479d4aec6ee9cf..0000000000000000000000000000000000000000
--- a/cas/cas-server/src/main/resources/static/js/viewConfig.js
+++ /dev/null
@@ -1,157 +0,0 @@
-/* globals $, urls, updateEnabled */
-(function () {
-    var origData;
-
-    var setupButtonClickOnRefreshedProperties = function () {
-        $('#formRefreshCAS button').on('click', function (e) {
-            e.preventDefault();
-
-            // Show the refreshModal
-            var myModal = $('#refreshModal').modal({
-                keyboard: false,
-                backdrop: 'static'
-            });
-
-            var primaryButton = myModal.find('.modal-footer button.btn-primary');
-
-            // Disable the primary button
-            primaryButton.prop('disabled', true).text('Refreshing...');
-
-            $.post(e.target.parentNode.action, function (data) {
-                if (data.length !== 0) {
-                    $('#refreshModal-label').text('Refreshed Properties');
-                    myModal.find('.modal-content .modal-body').html(
-                        '<pre>' + data + '</pre>' +
-            '<p>Click &quot;OK&quot; to reload page.</p>'
-                    );
-                } else {
-                    myModal.find('.modal-header .modal-title').text('Properties Refreshed');
-                    myModal.find('.modal-content .modal-body').html(
-                        '<p>Click &quot;OK&quot; to reload page.</p>'
-                    );
-                }
-            })
-                .done(function () {
-                    primaryButton.prop('disabled', false).text('Reload page').on('click', function (e) {
-                        e.preventDefault();
-                        window.location.reload();
-                    });
-                })
-                .fail(function (jqXHR) {
-                    $('#refreshModal-label').text('Problem With Refreshing Properties');
-                    myModal.find('.modal-content .modal-body').html(
-                        '<div class="alert alert-warning"><strong>Status: ' + jqXHR.status + '</strong><p/>Unable to refresh the properties. Please try again.</div>'
-                    );
-                    primaryButton.prop('disabled', false).text('OK').on('click', function (e) {
-                        e.preventDefault();
-                        myModal.modal('hide');
-                    });
-                });
-        });
-    };
-
-    var createDataTable = function () {
-        $('#viewConfigsTable').DataTable({
-            'autoWidth': false,
-            'initComplete': function (settings, json) {
-                if (!json) {
-                    $('#loadingMessage').hide();
-                    $('#viewConfigError').show();
-                    $('#view-configuration').hide();
-                } else {
-                    $('#loadingMessage').hide();
-                    $('#viewConfigError').hide();
-                    $('#view-configuration').show();
-                }
-            },
-            'drawCallback': function () {
-                var api = this.api();
-                if (api.page.info().pages > 1) {
-                    $('#' + $.fn.dataTable.tables()[0].id + '_paginate')[0].style.display = 'block';
-                } else {
-                    $('#' + $.fn.dataTable.tables()[0].id + '_paginate')[0].style.display = 'none';
-                }
-
-                if (updateEnabled) {
-                    editTable();
-                }
-            },
-            'processing': true,
-            'ajax': {
-                'url': urls.getConfiguration,
-                'dataSrc': function (json) {
-                    var returnData = [];
-                    for (var item in json) {
-                        returnData.push({
-                            'key': '<code>' + item + '</code>',
-                            'value': '' + json[item] + ''
-                        });
-                    }
-                    return returnData;
-                }
-            },
-            'columns': [
-                {'data': 'key', 'className': 'col-xs-6 key'},
-                {'data': 'value', 'className': 'col-xs-6 value'}
-            ],
-            'pageLength': 50
-        });
-    };
-
-    var getRowData = function (row) {
-        var tds = row.find('td');
-        var tmp = {};
-        $.each(tds, function (i) {
-            if (i % 2 === 0) {
-                tmp.key = $(this).text();
-            } else {
-                tmp.value = $(this).text();
-            }
-        });
-        return tmp;
-    };
-
-    var editTable = function () {
-        $('#viewConfigsTable').editableTableWidget({editor: $('<textarea>')});
-
-        $('#viewConfigsTable td').on('focus', function () {
-            origData = getRowData($(this).closest('tr'));
-        });
-
-        $('#viewConfigsTable tr').on('change', function () {
-            var newChanges = getRowData($(this));
-
-            var data = {old: origData, new: newChanges};
-            $.ajax({url: urls.updateConfiguration, data: JSON.stringify(data), type: 'POST', contentType: 'application/json'})
-                .fail(function () {
-                    var result = 'Failed to save settings.';
-                    $('#alertWrapper').addClass('alert-warning');
-                    $('#alertWrapper').removeClass('alert-success');
-
-                    $('#alertWrapper').text(result);
-                    $('#alertWrapper').show();
-                })
-                .success(function () {
-                    var result = 'Saved settings successfully.';
-                    $('#alertWrapper').removeClass('alert-warning');
-                    $('#alertWrapper').addClass('alert-success');
-
-                    $('#resultText').text(result);
-                    $('#alertWrapper').show();
-                });
-        });
-    };
-
-    // initialization *******
-    (function init () {
-        createDataTable();
-        setupButtonClickOnRefreshedProperties();
-    })();
-
-    // Public Methods
-    return {
-    /**
-     * Not used
-     */
-    };
-})();
diff --git a/cas/cas-server/src/main/resources/static/js/viewConfigMetadata.js b/cas/cas-server/src/main/resources/static/js/viewConfigMetadata.js
deleted file mode 100644
index 75734824aa8487af4af65f010d4f89a9538c39ec..0000000000000000000000000000000000000000
--- a/cas/cas-server/src/main/resources/static/js/viewConfigMetadata.js
+++ /dev/null
@@ -1,136 +0,0 @@
-$('.ui.search').search({
-    type: 'message',
-    searchDelay: 500,
-    silent: true,
-    apiSettings: {
-        silent: true,
-        cache: false,
-        url: urls.search,
-        onResponse: function (casResp) {
-            var response = {
-                results: {}
-            };
-
-            for (var key in casResp) {
-                if (casResp.hasOwnProperty(key)) {
-                    var prop = casResp[key];
-                    var group = prop.group;
-
-                    if (response.results[group] === undefined) {
-                        response.results[group] = {
-                            name: group,
-                            results: []
-                        };
-                    }
-                    response.results[group].results.push({
-                        title: prop.id,
-                        description: prop.description,
-                        defaultValue: prop.defaultValue,
-                        type: prop.type,
-                        deprecated: prop.deprecated,
-                        requiredProperty: prop.requiredProperty,
-                        requiredModule: prop.requiredModule,
-                        requiredModuleAutomated: prop.requiredModuleAutomated
-                    });
-                }
-            }
-
-            return response;
-        },
-    },
-    minCharacters: 3,
-    templates: {
-        message: function (response, type) {
-            var html = '';
-            $('#accordion').empty();
-
-            if (type === 'empty') {
-                html += '<h3><i class=\'fa fa-search\' />&nbsp;<strong>No Results</strong></h3>';
-                html += '<div class=\'alert alert-warning\'>';
-                html += '<i class=\'fa fa-exclamation-circle\'/>&nbsp;';
-                html += 'No search results could be found based on the provided query.';
-                html += '</div>';
-            }
-
-            for (var group in response.results) {
-                var modules = new Set();
-
-                html += '<h2><i class=\'fa fa-users\' />&nbsp;<strong>Group: </strong>' + group + '</h2>';
-                var props = response.results[group].results;
-
-                html += '<div>';
-
-                for (var i = 0; i < props.length; i++) {
-                    html += '<p>';
-                    var prop = props[i];
-                    html += '<i class=\'fa fa-cogs\'/>&nbsp;';
-                    html += 'Property: <code>' + prop.title + '=' + prop.defaultValue + '</code><br/>';
-                    if (prop.deprecated) {
-                        html += '<p/><div class=\'alert alert-warning\'>';
-                        html += '<i class=\'fa fa-exclamation-circle\'/>&nbsp;';
-                        html += 'This property is deprecated and will be removed in future CAS versions.';
-                        html += '</div>';
-                    }
-                    if (prop.requiredProperty) {
-                        html += '<p/><div class=\'alert alert-success\'>';
-                        html += '<i class=\'fa fa-check-square\'/>&nbsp;';
-                        html += 'This property is required.';
-                        html += '</div>';
-                    }
-
-                    html += '<i class=\'fab fa-codepen\' />&nbsp;Type: <code>' + prop.type + '</code><br/>';
-                    if (prop.description != null) {
-                        html += '<p>' + prop.description + '</p>';
-                    }
-
-                    if (prop.requiredModule != null) {
-                        modules.add(prop.requiredModule);
-                    }
-                    html += '<hr>';
-                }
-
-                if (modules.size > 0) {
-                    html += '<div>';
-                    html += '<p><i class=\'fa fa-gear\' />&nbsp;Required Modules</p>';
-                    html += '<ul class=\'nav nav-pills\'>';
-                    html += '<li class=\'active\'><a  href=\'#1\' data-toggle=\'tab\'>Maven</a></li>';
-                    html += '<li><a href=\'#2\' data-toggle=\'tab\'>Gradle</a></li>';
-                    html += '</ul>';
-
-                    for (let moduleString of modules) {
-                        html += '<div class=\'tab-content\'>';
-
-                        var moduleArr = moduleString.split('|');
-                        var module = moduleArr[0];
-
-                        var maven = '&lt;dependency&gt;\n';
-                        maven += '\t&lt;groupId&gt;org.apereo.cas&lt;/groupId&gt;\n';
-                        maven += '\t&lt;artifactId&gt;' + module + '&lt;/artifactId&gt;\n';
-                        maven += '\t&lt;cas.version&gt;${cas.version}&lt;/cas.version&gt;\n';
-                        maven += '&lt;/dependency&gt;\n';
-                        html += '<div class=\'tab-pane active\' id=\'1\'><pre>' + maven + '</pre></div>';
-
-                        var gradle = 'compile \'org.apereo.cas:' + module + ':${project.\'cas.version\'}\'\n';
-                        html += '<div class=\'tab-pane\' id=\'2\'><pre>' + gradle + '</pre></div>';
-
-                        html += '</div>';
-                    }
-
-                    html += '</div>';
-                }
-
-                html += '</div>';
-            }
-
-            html += '</div>';
-
-
-            $('#accordion').html(html);
-            $('#accordion').accordion({
-                heightStyle: 'content'
-            });
-            $('#accordion').accordion('refresh');
-            return '';
-        }
-    }
-});
diff --git a/cas/cas-server/src/main/resources/templates/casAccountBadConfigurationView.html b/cas/cas-server/src/main/resources/templates/casAccountBadConfigurationView.html
index 124cdb1dadd760a77031ebd58044c0aa38c56bb6..7d4fa0572f240aa0c9b88b85ddceaedcdcaeff56 100644
--- a/cas/cas-server/src/main/resources/templates/casAccountBadConfigurationView.html
+++ b/cas/cas-server/src/main/resources/templates/casAccountBadConfigurationView.html
@@ -9,7 +9,7 @@
 <div layout:fragment="content">
     <div>
         <h2 th:utext="#{screen.accountbadconfiguration.heading}">This account has not properly configured.</h2>
-        <p th:utext="#{screen.accountbadconfiguration.message}">Please contact the system administrator to regain access.</p>
+        <p th:utext="#{screen.accountbadconfiguration.message(${@environment.getProperty('theme.vitamui-platform-name')})}">Please contact the system administrator to regain access.</p>
     </div>
 </div>
 </body>
diff --git a/cas/cas-server/src/main/resources/templates/casAccountDisabledView.html b/cas/cas-server/src/main/resources/templates/casAccountDisabledView.html
index 72a8edafd1014db8cba24fdf50323ba239aa3dd6..2f9486abc873b7a656f48371d3e6d0ca6c0d7ee7 100644
--- a/cas/cas-server/src/main/resources/templates/casAccountDisabledView.html
+++ b/cas/cas-server/src/main/resources/templates/casAccountDisabledView.html
@@ -2,6 +2,9 @@
 <html xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout" layout:decorate="~{layout}">
 
 <head>
+    <meta http-equiv="X-UA-Compatible" content="IE=edge"/>
+    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"/>
+
     <title th:text="#{screen.accountdisabled.heading}">CAS Account Disabled View</title>
 </head>
 
diff --git a/cas/cas-server/src/main/resources/templates/casAccountLockedView.html b/cas/cas-server/src/main/resources/templates/casAccountLockedView.html
index 9486ed2dd25ab7660c62293d7c4da4661de070bb..0d0ca2dead98f92d2018bfbde54d48c6957249a6 100644
--- a/cas/cas-server/src/main/resources/templates/casAccountLockedView.html
+++ b/cas/cas-server/src/main/resources/templates/casAccountLockedView.html
@@ -2,6 +2,9 @@
 <html xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout" layout:decorate="~{layout}">
 
 <head>
+    <meta http-equiv="X-UA-Compatible" content="IE=edge"/>
+    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"/>
+
     <title th:text="#{screen.accountlocked.heading}">Account Locked View</title>
 </head>
 
diff --git a/cas/cas-server/src/main/resources/templates/casAuthenticationBlockedView.html b/cas/cas-server/src/main/resources/templates/casAuthenticationBlockedView.html
index d404f14607f8331cf1a0855db48d512b780bf2ac..0af1e852ada1c3bdc8e0871571fa7486ed5736a3 100644
--- a/cas/cas-server/src/main/resources/templates/casAuthenticationBlockedView.html
+++ b/cas/cas-server/src/main/resources/templates/casAuthenticationBlockedView.html
@@ -2,6 +2,9 @@
 <html xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout" layout:decorate="~{layout}">
 
 <head>
+    <meta http-equiv="X-UA-Compatible" content="IE=edge"/>
+    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"/>
+
     <title th:text="#{screen.authnblocked.heading}">Authentication Blocked View</title>
 </head>
 
diff --git a/cas/cas-server/src/main/resources/templates/casExpiredPassView.html b/cas/cas-server/src/main/resources/templates/casExpiredPassView.html
index 548411171ce3e06339b3a1d3c36705f4f4d5ee27..c01887ff283fd37db9a5621d2bf3d0d5f2046236 100644
--- a/cas/cas-server/src/main/resources/templates/casExpiredPassView.html
+++ b/cas/cas-server/src/main/resources/templates/casExpiredPassView.html
@@ -2,7 +2,11 @@
 <html xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout" layout:decorate="~{layout}">
 
 <head>
+    <meta http-equiv="X-UA-Compatible" content="IE=edge"/>
+    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"/>
+
     <title th:text="#{screen.expiredpass.heading}">CAS Expired Password View</title>
+    <script type="text/javascript" th:src="@{#{webjars.zxcvbn.js}}"></script>
     <script type="text/javascript" th:src="@{/js/passwordMeter.js}"></script>
 </head>
 
diff --git a/cas/cas-server/src/main/resources/templates/casGenericSuccessView.html b/cas/cas-server/src/main/resources/templates/casGenericSuccessView.html
index dbdb3ed9c2b8314156df1e7846645319d9148cca..1b852bc3e4546ef7f977c09bd0a54f807662f4c8 100644
--- a/cas/cas-server/src/main/resources/templates/casGenericSuccessView.html
+++ b/cas/cas-server/src/main/resources/templates/casGenericSuccessView.html
@@ -4,42 +4,20 @@
 <head>
     <meta http-equiv="X-UA-Compatible" content="IE=edge"/>
     <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"/>
-    <meta charset="UTF-8"/>
-    <title>Vitam-UI</title>
 
-    <meta http-equiv="refresh" th:attr="content=${'1; url=' + portalUrl}" />
-    <meta name="viewport" content="width=device-width, initial-scale=1">
+	<meta charset="UTF-8"/>
+    <title th:text="${@environment.getProperty('theme.vitamui-platform-name')}">VITAM-UI</title>
 
-    <link rel="icon" th:href="@{/images/favicon.ico}" type="image/x-icon"/>
+    <meta http-equiv="refresh" th:attr="content=${'1; url=' + portalUrl}" />
+    
+    <link rel="icon" type="image/x-icon" th:href="${vitamuiFavicon} ? 'data:image/png;base64,' + ${vitamuiFavicon} : @{/images/favicon.ico}"/>
 
     <link th:href="@{/css/cas.css}" rel="stylesheet"/>
 
-    <script type="text/javascript" th:src="@{#{webjars.zxcvbn.js}}"></script>
     <script type="text/javascript" th:src="@{#{webjars.jquerymin.js}}"></script>
     <script type="text/javascript" th:src="@{#{webjars.jqueryui.js}}"></script>
-    <script type="text/javascript" th:src="@{#{webjars.jquerycookie.js}}"></script>
     <script src="//www.google.com/recaptcha/api.js" async defer th:if="${recaptchaSiteKey}"></script>
-    <script th:src="@{#{webjars.bootstrapmin.js}}"></script>
-
-    <script th:inline="javascript">
-        /*<![CDATA[*/
-
-        var trackGeoLocation = /*[[${trackGeoLocation}]]*/ === "true";
-
-        var googleAnalyticsTrackingId = /*[[${googleAnalyticsTrackingId}]]*/;
-
-        if (googleAnalyticsTrackingId != null && googleAnalyticsTrackingId != '') {
-            (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
-                        (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
-                    m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
-            })(window, document, 'script', 'https://www.google-analytics.com/analytics.js', 'ga');
-
-            ga('create', googleAnalyticsTrackingId, 'auto');
-            ga('send', 'pageview');
-        }
 
-        /*]]>*/
-    </script>
 </head>
 <body class="login bg-portal" th:styleappend="${@environment.getProperty('theme.body.style')}">
     <div class="background bg-success"></div>
diff --git a/cas/cas-server/src/main/resources/templates/casLoginView.html b/cas/cas-server/src/main/resources/templates/casLoginView.html
index e23e3dab187b9d24852c4317b42807b94f450b5b..55f43b88b40185f211bf0f1bf61ee94d8bb4d83c 100644
--- a/cas/cas-server/src/main/resources/templates/casLoginView.html
+++ b/cas/cas-server/src/main/resources/templates/casLoginView.html
@@ -5,38 +5,14 @@
     <meta http-equiv="X-UA-Compatible" content="IE=edge"/>
     <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"/>
     <meta charset="UTF-8"/>
-    <title>Vitam-UI</title>
+    <title th:text="${@environment.getProperty('theme.vitamui-platform-name')}">VITAM-UI</title>
 
-    <meta name="viewport" content="width=device-width, initial-scale=1">
-    <link rel="icon" type="image/x-icon" th:href="@{/images/favicon.ico}">
+    <link rel="icon" type="image/x-icon" th:href="${vitamuiFavicon} ? 'data:image/png;base64,' + ${vitamuiFavicon} : @{/images/favicon.ico}">
     <link th:href="@{/css/cas.css}" rel="stylesheet"/>
 
-    <script type="text/javascript" th:src="@{#{webjars.zxcvbn.js}}"></script>
     <script type="text/javascript" th:src="@{#{webjars.jquerymin.js}}"></script>
     <script type="text/javascript" th:src="@{#{webjars.jqueryui.js}}"></script>
-    <script type="text/javascript" th:src="@{#{webjars.jquerycookie.js}}"></script>
     <script src="//www.google.com/recaptcha/api.js" async defer th:if="${recaptchaSiteKey}"></script>
-    <script th:src="@{#{webjars.bootstrapmin.js}}"></script>
-
-    <script th:inline="javascript">
-        /*<![CDATA[*/
-
-        var trackGeoLocation = /*[[${trackGeoLocation}]]*/ === "true";
-
-        var googleAnalyticsTrackingId = /*[[${googleAnalyticsTrackingId}]]*/;
-
-        if (googleAnalyticsTrackingId != null && googleAnalyticsTrackingId != '') {
-            (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
-                        (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
-                    m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
-            })(window, document, 'script', 'https://www.google-analytics.com/analytics.js', 'ga');
-
-            ga('create', googleAnalyticsTrackingId, 'auto');
-            ga('send', 'pageview');
-        }
-
-        /*]]>*/
-    </script>
 </head>
 <body th:styleappend="${@environment.getProperty('theme.body.style')}">
 
diff --git a/cas/cas-server/src/main/resources/templates/casLogoutView.html b/cas/cas-server/src/main/resources/templates/casLogoutView.html
index 7a7f82eee1f3eac0d19dd29273e47f73d79c2372..d1468f00cca103795be3befbd8654539c4d0adc1 100644
--- a/cas/cas-server/src/main/resources/templates/casLogoutView.html
+++ b/cas/cas-server/src/main/resources/templates/casLogoutView.html
@@ -5,38 +5,14 @@
     <meta http-equiv="X-UA-Compatible" content="IE=edge"/>
     <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"/>
     <meta charset="UTF-8"/>
-    <title>Vitam-UI</title>
+    <title th:text="${@environment.getProperty('theme.vitamui-platform-name')}">VITAM-UI</title>
 
-    <meta name="viewport" content="width=device-width, initial-scale=1">
-    <link rel="icon" type="image/x-icon" th:href="@{/images/favicon.ico}">
+    <link rel="icon" type="image/x-icon" th:href="${vitamuiFavicon} ? 'data:image/png;base64,' + ${vitamuiFavicon} : @{/images/favicon.ico}">
     <link th:href="@{/css/cas.css}" rel="stylesheet"/>
 
-    <script type="text/javascript" th:src="@{#{webjars.zxcvbn.js}}"></script>
     <script type="text/javascript" th:src="@{#{webjars.jquerymin.js}}"></script>
     <script type="text/javascript" th:src="@{#{webjars.jqueryui.js}}"></script>
-    <script type="text/javascript" th:src="@{#{webjars.jquerycookie.js}}"></script>
     <script src="//www.google.com/recaptcha/api.js" async defer th:if="${recaptchaSiteKey}"></script>
-    <script th:src="@{#{webjars.bootstrapmin.js}}"></script>
-
-    <script th:inline="javascript">
-        /*<![CDATA[*/
-
-        var trackGeoLocation = /*[[${trackGeoLocation}]]*/ === "true";
-
-        var googleAnalyticsTrackingId = /*[[${googleAnalyticsTrackingId}]]*/;
-
-        if (googleAnalyticsTrackingId != null && googleAnalyticsTrackingId != '') {
-            (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
-                        (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
-                    m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
-            })(window, document, 'script', 'https://www.google-analytics.com/analytics.js', 'ga');
-
-            ga('create', googleAnalyticsTrackingId, 'auto');
-            ga('send', 'pageview');
-        }
-
-        /*]]>*/
-    </script>
 </head>
 <body th:styleappend="${@environment.getProperty('theme.body.style')}">
 
diff --git a/cas/cas-server/src/main/resources/templates/casMustChangePassView.html b/cas/cas-server/src/main/resources/templates/casMustChangePassView.html
index 6391cb31f78c9c53231a0684e92b0a4cf9d3a6ea..b5341a328095f9100853d0447a4054cdcbf934f9 100644
--- a/cas/cas-server/src/main/resources/templates/casMustChangePassView.html
+++ b/cas/cas-server/src/main/resources/templates/casMustChangePassView.html
@@ -2,7 +2,11 @@
 <html xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout" layout:decorate="~{layout}">
 
 <head>
+    <meta http-equiv="X-UA-Compatible" content="IE=edge"/>
+    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"/>
+
     <title th:text="#{screen.mustchangepass.heading}"></title>
+    <script type="text/javascript" th:src="@{#{webjars.zxcvbn.js}}"></script>
     <script type="text/javascript" th:src="@{/js/passwordMeter.js}"></script>
 </head>
 
diff --git a/cas/cas-server/src/main/resources/templates/casPac4jStopWebflow.html b/cas/cas-server/src/main/resources/templates/casPac4jStopWebflow.html
index 8a22d98f5914259a7f6632bbb89f97d1db2fba36..3a3434b10a18c77b10fbed74eb1fe2aede48b2f1 100644
--- a/cas/cas-server/src/main/resources/templates/casPac4jStopWebflow.html
+++ b/cas/cas-server/src/main/resources/templates/casPac4jStopWebflow.html
@@ -2,6 +2,9 @@
 <html xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout" layout:decorate="~{layout}">
 
 <head>
+    <meta http-equiv="X-UA-Compatible" content="IE=edge"/>
+    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"/>
+
     <title th:text="#{screen.pac4j.unauthz.pagetitle}">Pac4j Stop Webflow View</title>
 </head>
 
diff --git a/cas/cas-server/src/main/resources/templates/casPasswordUpdateSuccessView.html b/cas/cas-server/src/main/resources/templates/casPasswordUpdateSuccessView.html
index c5b51c8ef6f3a53107368172c1b7da151317882d..eb56137c669b57fab1f294300868b81fdedf9afa 100644
--- a/cas/cas-server/src/main/resources/templates/casPasswordUpdateSuccessView.html
+++ b/cas/cas-server/src/main/resources/templates/casPasswordUpdateSuccessView.html
@@ -2,7 +2,10 @@
 <html xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout" layout:decorate="~{layout}">
 
 <head>
-	<title th:text="#{screen.success.header}">Password Update Success View</title>
+    <meta http-equiv="X-UA-Compatible" content="IE=edge"/>
+    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"/>
+
+    <title th:text="#{screen.success.header}">Password Update Success View</title>
 </head>
 
 <body id="cas" th:styleappend="${@environment.getProperty('theme.body.style')}">
diff --git a/cas/cas-server/src/main/resources/templates/casPropagateLogoutView.html b/cas/cas-server/src/main/resources/templates/casPropagateLogoutView.html
index 142ced3621cc91f5cedada72b75b55aad9cb9f0c..57614e19dbd93c7faf486f8d8a3ee74831bb8913 100644
--- a/cas/cas-server/src/main/resources/templates/casPropagateLogoutView.html
+++ b/cas/cas-server/src/main/resources/templates/casPropagateLogoutView.html
@@ -9,19 +9,14 @@
     <title th:text="#{screen.logout.header}">Propagate Logout View</title>
 
     <link rel="stylesheet" th:href="@{#{webjars.fontawesomemin.css}}"/>
-    <link type="text/css" rel="stylesheet" th:href="@{#{webjars.bootstrapmin.css}}"/>
-    <link type="text/css" rel="stylesheet" th:href="@{#{webjars.latomin.css}}"/>
 
     <link rel="stylesheet" th:href="@{/css/cas.css}"/>
 
-    <link rel="icon" th:href="@{/images/favicon.ico}" type="image/x-icon"/>
+    <link rel="icon" type="image/x-icon" th:href="${vitamuiFavicon} ? 'data:image/png;base64,' + ${vitamuiFavicon} : @{/images/favicon.ico}"/>
 
-    <script type="text/javascript" th:src="@{#{webjars.zxcvbn.js}}"></script>
     <script type="text/javascript" th:src="@{#{webjars.jquerymin.js}}"></script>
     <script type="text/javascript" th:src="@{#{webjars.jqueryui.js}}"></script>
-    <script type="text/javascript" th:src="@{#{webjars.jquerycookie.js}}"></script>
     <script src="//www.google.com/recaptcha/api.js" async defer th:if="${recaptchaSiteKey}"></script>
-    <script th:src="@{#{webjars.bootstrapmin.js}}"></script>
 
     <script th:inline="javascript">
         /*<![CDATA[*/
diff --git a/cas/cas-server/src/main/resources/templates/casPwdView.html b/cas/cas-server/src/main/resources/templates/casPwdView.html
index e65cf6f890aa8d6db0250fdb675bd0339382fd43..43b516ab0713aa3ca71b7f98cdbcaaf4dc68ccb9 100644
--- a/cas/cas-server/src/main/resources/templates/casPwdView.html
+++ b/cas/cas-server/src/main/resources/templates/casPwdView.html
@@ -5,38 +5,16 @@
     <meta http-equiv="X-UA-Compatible" content="IE=edge"/>
     <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"/>
     <meta charset="UTF-8"/>
-    <title>Vitam-UI</title>
+    <title th:text="${@environment.getProperty('theme.vitamui-platform-name')}">VITAM-UI</title>
 
     <meta name="viewport" content="width=device-width, initial-scale=1">
-    <link rel="icon" type="image/x-icon" th:href="@{/images/favicon.ico}">
+    <link rel="icon" type="image/x-icon" th:href="${vitamuiFavicon} ? 'data:image/png;base64,' + ${vitamuiFavicon} : @{/images/favicon.ico}"/>
     <link th:href="@{/css/cas.css}" rel="stylesheet"/>
 
     <script type="text/javascript" th:src="@{#{webjars.zxcvbn.js}}"></script>
     <script type="text/javascript" th:src="@{#{webjars.jquerymin.js}}"></script>
     <script type="text/javascript" th:src="@{#{webjars.jqueryui.js}}"></script>
-    <script type="text/javascript" th:src="@{#{webjars.jquerycookie.js}}"></script>
     <script src="//www.google.com/recaptcha/api.js" async defer th:if="${recaptchaSiteKey}"></script>
-    <script th:src="@{#{webjars.bootstrapmin.js}}"></script>
-
-    <script th:inline="javascript">
-        /*<![CDATA[*/
-
-        var trackGeoLocation = /*[[${trackGeoLocation}]]*/ === "true";
-
-        var googleAnalyticsTrackingId = /*[[${googleAnalyticsTrackingId}]]*/;
-
-        if (googleAnalyticsTrackingId != null && googleAnalyticsTrackingId != '') {
-            (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
-                        (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
-                    m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
-            })(window, document, 'script', 'https://www.google-analytics.com/analytics.js', 'ga');
-
-            ga('create', googleAnalyticsTrackingId, 'auto');
-            ga('send', 'pageview');
-        }
-
-        /*]]>*/
-    </script>
 </head>
 <body th:styleappend="${@environment.getProperty('theme.body.style')}">
 
diff --git a/cas/cas-server/src/main/resources/templates/casResetPasswordErrorView.html b/cas/cas-server/src/main/resources/templates/casResetPasswordErrorView.html
index 832b7b74de358d090383fda8274626f6d0520af0..10dffe5020fab27f34f4984668ba66fbb0483b50 100644
--- a/cas/cas-server/src/main/resources/templates/casResetPasswordErrorView.html
+++ b/cas/cas-server/src/main/resources/templates/casResetPasswordErrorView.html
@@ -2,6 +2,9 @@
 <html xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout" layout:decorate="~{layout}">
 
 <head>
+    <meta http-equiv="X-UA-Compatible" content="IE=edge"/>
+    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"/>
+
     <title th:text="#{screen.pm.reset.title}">Password Reset Error View</title>
 </head>
 
diff --git a/cas/cas-server/src/main/resources/templates/casResetPasswordSendInstructionsView.html b/cas/cas-server/src/main/resources/templates/casResetPasswordSendInstructionsView.html
index 0f425d5204788f78560474b3e4ed2ccb8f457f6d..2184720993500886d744e1f30c60777f28d55dce 100644
--- a/cas/cas-server/src/main/resources/templates/casResetPasswordSendInstructionsView.html
+++ b/cas/cas-server/src/main/resources/templates/casResetPasswordSendInstructionsView.html
@@ -2,6 +2,9 @@
 <html xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout" layout:decorate="~{layout}">
 
 <head>
+    <meta http-equiv="X-UA-Compatible" content="IE=edge"/>
+    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"/>
+
     <title th:text="#{screen.pm.reset.title}">Reset Password Send Instructions View</title>
 </head>
 
diff --git a/cas/cas-server/src/main/resources/templates/casResetPasswordSentInstructionsView.html b/cas/cas-server/src/main/resources/templates/casResetPasswordSentInstructionsView.html
index 5603d1a768725f5348c24ade0e24b236d83fc924..d07c589c49b9197bac93a336bc5ace799060de5f 100644
--- a/cas/cas-server/src/main/resources/templates/casResetPasswordSentInstructionsView.html
+++ b/cas/cas-server/src/main/resources/templates/casResetPasswordSentInstructionsView.html
@@ -2,6 +2,9 @@
 <html xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout" layout:decorate="~{layout}">
 
 <head>
+    <meta http-equiv="X-UA-Compatible" content="IE=edge"/>
+    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"/>
+
     <title th:text="#{screen.pm.reset.title}">Reset Password Sent Instructions View</title>
 </head>
 
diff --git a/cas/cas-server/src/main/resources/templates/casServiceErrorView.html b/cas/cas-server/src/main/resources/templates/casServiceErrorView.html
index 8ce0ad2ba669b6e56505879380aea23a136e78ea..a11504ffb9d4e11e3b4f6d5d2aebe6eb20a22649 100644
--- a/cas/cas-server/src/main/resources/templates/casServiceErrorView.html
+++ b/cas/cas-server/src/main/resources/templates/casServiceErrorView.html
@@ -2,13 +2,16 @@
 <html xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout" layout:decorate="~{layout}">
 
 <head>
-    <title th:text="#{screen.service.error.header}"></title>
+    <meta http-equiv="X-UA-Compatible" content="IE=edge"/>
+    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"/>
+
+    <title th:utext="#{screen.service.error.header(${@environment.getProperty('theme.vitamui-platform-name')})}"></title>
 </head>
 
 <body id="cas" th:styleappend="${@environment.getProperty('theme.body.style')}">
 <div layout:fragment="content">
     <div>
-        <h1 th:utext="#{screen.service.error.header}"/>
+        <h1 th:utext="#{screen.service.error.header(${@environment.getProperty('theme.vitamui-platform-name')})}"/>
         <p th:if="${rootCauseException != null and rootCauseException.code != null}"
            th:utext="#{${rootCauseException.code}}"/>
     </div>
diff --git a/cas/cas-server/src/main/resources/templates/casSimpleMfaLoginView.html b/cas/cas-server/src/main/resources/templates/casSimpleMfaLoginView.html
index d15015dd071d0e5fde281d0374e3f7860f50b8ff..3debe81812070b117ea34fe3dc8ede91319e8adf 100644
--- a/cas/cas-server/src/main/resources/templates/casSimpleMfaLoginView.html
+++ b/cas/cas-server/src/main/resources/templates/casSimpleMfaLoginView.html
@@ -2,7 +2,10 @@
 <html xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout" layout:decorate="~{layout}">
 
 <head>
-    <title th:text="#{screen.mfa.sms.login.pagetitle}"></title>
+    <meta http-equiv="X-UA-Compatible" content="IE=edge"/>
+    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"/>
+
+    <title th:text="#{cas.mfa.simple.pagetitle}"></title>
 </head>
 
 <body id="cas" th:styleappend="${@environment.getProperty('theme.body.style')}">
diff --git a/cas/cas-server/src/main/resources/templates/error.html b/cas/cas-server/src/main/resources/templates/error.html
index ab4e1ad4a194f5958574b1431fc9ed9d62712be1..41f1ae917986df93dc6580e44608b8fd63e9dce4 100644
--- a/cas/cas-server/src/main/resources/templates/error.html
+++ b/cas/cas-server/src/main/resources/templates/error.html
@@ -2,14 +2,17 @@
 <html xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout" layout:decorate="~{layout}">
 
 <head>
-    <title th:text="#{screen.unavailable.header}">VITAMUI Error</title>
+    <meta http-equiv="X-UA-Compatible" content="IE=edge"/>
+    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"/>
+
+    <title th:text="#{screen.unavailable.header(${@environment.getProperty('theme.vitamui-platform-name')})}">VITAMUI Error</title>
 </head>
 
 <body id="cas" th:styleappend="${@environment.getProperty('theme.body.style')}">
 <div layout:fragment="content">
     <div>
         <h2 th:utext="#{screen.unavailable.heading(${status},${error})}">VITAMUI is unable to process this request: "{0}:{1}"</h2>
-        <div th:utext="#{screen.unavailable.message}">screen.unavailable.message would go here</div>
+        <div th:utext="#{screen.unavailable.message(${@environment.getProperty('theme.vitamui-platform-name')})}">screen.unavailable.message would go here</div>
     </div>
 
 </div>
diff --git a/cas/cas-server/src/main/resources/templates/error/401.html b/cas/cas-server/src/main/resources/templates/error/401.html
index f68939a051eef12db83efe6c1097152a3cb30272..ec6e93f20732b0ca44e50cf56f7b4abb26de937e 100644
--- a/cas/cas-server/src/main/resources/templates/error/401.html
+++ b/cas/cas-server/src/main/resources/templates/error/401.html
@@ -2,8 +2,12 @@
 <html xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout" layout:decorate="~{layout}">
 
 <head>
-    <title th:text="#{screen.error.page.accessdenied}">Error - 401</title>
-    <link rel="stylesheet" th:href="@{#{webjars.fontawesome.css}}" />
+    <meta charset="UTF-8">
+    <meta http-equiv="X-UA-Compatible" content="IE=edge"/>
+    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"/>
+
+    <title th:text="#{screen.error.page.title.accessdenied}">Error - 401</title>
+
     <style>
         .prompt {
             font-family: Verdana, sans-serif;
diff --git a/cas/cas-server/src/main/resources/templates/error/403.html b/cas/cas-server/src/main/resources/templates/error/403.html
index aca83ba19a729d67a7adcb68d3c39684fb40275d..264a5a1486ef4d0e532fd78c8c802c86b35d7a9f 100644
--- a/cas/cas-server/src/main/resources/templates/error/403.html
+++ b/cas/cas-server/src/main/resources/templates/error/403.html
@@ -2,7 +2,11 @@
 <html xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout" layout:decorate="~{layout}">
 
 <head>
-    <title th:text="#{screen.error.page.accessdenied}">Error - Permission Denied</title>
+    <meta charset="UTF-8">
+    <meta http-equiv="X-UA-Compatible" content="IE=edge"/>
+    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"/>
+
+    <title th:text="#{screen.error.page.title.permissiondenied}">Error - Permission Denied</title>
     <link rel="stylesheet" th:href="@{#{webjars.fontawesome.css}}" />
     <style>
         .prompt {
diff --git a/cas/cas-server/src/main/resources/templates/error/404.html b/cas/cas-server/src/main/resources/templates/error/404.html
index 22e8bd20aa072d3d26246ff6fb213e7395171fae..1bc27fa92fa8b89f867ebefde44c34e764d7d295 100644
--- a/cas/cas-server/src/main/resources/templates/error/404.html
+++ b/cas/cas-server/src/main/resources/templates/error/404.html
@@ -2,7 +2,11 @@
 <html xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout" layout:decorate="~{layout}">
 
 <head>
-    <title th:text="#{screen.error.page.notfound}">Error Page Not Found</title>
+    <meta charset="UTF-8">
+    <meta http-equiv="X-UA-Compatible" content="IE=edge"/>
+    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"/>
+
+    <title th:text="#{screen.error.page.title.pagenotfound}">Error - Page Not Found</title>
 
     <style>
         <link rel="stylesheet" th:href="@{#{webjars.fontawesome.css}}" />
diff --git a/cas/cas-server/src/main/resources/templates/error/405.html b/cas/cas-server/src/main/resources/templates/error/405.html
index 89118b473d3ffb6bc51a8ba7016b614d265b3f33..1b2e5c27d680dad0c07190ff1033dc04bd111690 100644
--- a/cas/cas-server/src/main/resources/templates/error/405.html
+++ b/cas/cas-server/src/main/resources/templates/error/405.html
@@ -2,7 +2,11 @@
 <html xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout" layout:decorate="~{layout}">
 
 <head>
-    <title th:text="#{screen.error.page.requestunsupported}">Error - Unsupported Request</title>
+    <meta charset="UTF-8">
+    <meta http-equiv="X-UA-Compatible" content="IE=edge"/>
+    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"/>
+
+    <title th:text="#{screen.error.page.title.requestunsupported}">Error - Unsupported Request</title>
     <link rel="stylesheet" th:href="@{#{webjars.fontawesome.css}}" />
     <style>
         .prompt {
diff --git a/cas/cas-server/src/main/resources/templates/error/423.html b/cas/cas-server/src/main/resources/templates/error/423.html
index 556ca9b7b9b1f3eea7763fec6914842f36b16ba6..e5ee085afcd73e5c069c6da9a34b97ecbc54ba58 100644
--- a/cas/cas-server/src/main/resources/templates/error/423.html
+++ b/cas/cas-server/src/main/resources/templates/error/423.html
@@ -2,7 +2,11 @@
 <html xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout" layout:decorate="~{layout}">
 
 <head>
-    <title th:text="#{screen.error.page.accessdenied}">Error - Permission Denied</title>
+    <meta charset="UTF-8">
+    <meta http-equiv="X-UA-Compatible" content="IE=edge"/>
+    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"/>
+
+    <title th:text="#{screen.error.page.title.blocked}">Error - Permission Denied</title>
     <link rel="stylesheet" th:href="@{#{webjars.fontawesome.css}}" />
     <style>
         .prompt {
diff --git a/cas/cas-server/src/main/resources/templates/fragments/pwdupdateform.html b/cas/cas-server/src/main/resources/templates/fragments/pwdupdateform.html
index 6de31f4dbf5521262745fff93d92e8510ab0330b..9de6f6cadf0c5336bbeef38182c0cbab403f0ff5 100644
--- a/cas/cas-server/src/main/resources/templates/fragments/pwdupdateform.html
+++ b/cas/cas-server/src/main/resources/templates/fragments/pwdupdateform.html
@@ -2,6 +2,13 @@
     /*<![CDATA[*/
 
     var policyPattern = /*[[${policyPattern}]]*/;
+      var passwordStrengthI18n = {
+          0: /*[[#{screen.pm.password.strength.0}]]*/,
+          1: /*[[#{screen.pm.password.strength.1}]]*/,
+          2: /*[[#{screen.pm.password.strength.2}]]*/,
+          3: /*[[#{screen.pm.password.strength.3}]]*/,
+          4: /*[[#{screen.pm.password.strength.4}]]*/
+      };
 
     /*]]>*/
 </script>
diff --git a/cas/cas-server/src/main/resources/templates/fragments/scripts.html b/cas/cas-server/src/main/resources/templates/fragments/scripts.html
index 670b7dece499e7b47836dc2961bf93ed1f257726..5a764724cc99776872f18aa33dd9680be2de33d6 100644
--- a/cas/cas-server/src/main/resources/templates/fragments/scripts.html
+++ b/cas/cas-server/src/main/resources/templates/fragments/scripts.html
@@ -1,4 +1,8 @@
-<script th:src="@{#{webjars.headmin.js}}"></script>
+<script type="text/javascript" th:src="@{#{webjars.jqueryui.js}}"></script>
+<script src="//www.google.com/recaptcha/api.js" async defer th:if="${recaptchaSiteKey != null and recaptchaVersion=='v2'}"></script>
+<script th:src="${'//www.google.com/recaptcha/api.js?render=' + recaptchaSiteKey}" th:if="${recaptchaSiteKey != null and recaptchaVersion == 'v3'}"></script>
+
+<script type="text/javascript" th:src="@{#{webjars.headmin.js}}"></script>
 <script type="text/javascript" th:src="@{${#themes.code('cas.javascript.file')}}"></script>
 
 <script th:inline="javascript">
@@ -13,11 +17,6 @@ head.ready(document, function () {
 
 function loadjQueryUI() {
 	var jqueryUrl = /*[[@{#{webjars.jqueryui.js}}]]*/;
-	head.load(jqueryUrl, loadjQueryCookies);
-}
-
-function loadjQueryCookies() {
-	var jqueryUrl = /*[[@{#{webjars.jquerycookie.js}}]]*/;
 	head.load(jqueryUrl, notifyResourcesAreLoaded(resourceLoadedSuccessfully));
 }
 
@@ -28,4 +27,51 @@ function notifyResourcesAreLoaded(callback) {
 }
 </script>
 
+<script th:inline="javascript">
+    /*<![CDATA[*/
+
+    var trackGeoLocation = /*[[${trackGeoLocation}]]*/ === "true";
+
+    var googleAnalyticsTrackingId = /*[[${googleAnalyticsTrackingId}]]*/;
+
+    if (googleAnalyticsTrackingId != null && googleAnalyticsTrackingId != '') {
+        (function (i, s, o, g, r, a, m) {
+            i['GoogleAnalyticsObject'] = r;
+            i[r] = i[r] || function () {
+                (i[r].q = i[r].q || []).push(arguments)
+            }, i[r].l = 1 * new Date();
+            a = s.createElement(o),
+                m = s.getElementsByTagName(o)[0];
+            a.async = 1;
+            a.src = g;
+            m.parentNode.insertBefore(a, m)
+        })(window, document, 'script', 'https://www.google-analytics.com/analytics.js', 'ga');
+
+        ga('create', googleAnalyticsTrackingId, 'auto');
+        ga('send', 'pageview');
+    }
+
+    /*]]>*/
+</script>
+
+<span th:if="${recaptchaVersion=='v2'}" th:remove="tag">
+    <script type="text/javascript" th:if="${recaptchaSiteKey != null AND recaptchaInvisible != null AND recaptchaInvisible}" th:inline="javascript">
+        function onRecaptchaV2Submit(token) {
+            $('#fm1').submit();
+        }
+    </script>
+</span>
+
+<span th:if="${recaptchaVersion=='v3'}" th:remove="tag">
+    <script type="text/javascript" th:if="${recaptchaSiteKey != null}" th:inline="javascript">
+         grecaptcha.ready(function() {
+             grecaptcha.execute(/*[[${recaptchaSiteKey}]]*/, {action: 'login'})
+                 .then(function(token) {
+                    $("#g-recaptcha-token").val(token)
+                 });
+         });
+    </script>
+</span>
+
+
 
diff --git a/cas/cas-server/src/main/resources/templates/layout.html b/cas/cas-server/src/main/resources/templates/layout.html
index 5f759a0e14cf9918da58d66190377ef18c89bd45..897f1c3a2eba9ef0531b5928b605e65c06d8f2a1 100644
--- a/cas/cas-server/src/main/resources/templates/layout.html
+++ b/cas/cas-server/src/main/resources/templates/layout.html
@@ -7,38 +7,14 @@
 
     <title layout:title-pattern="$CONTENT_TITLE">VITAMUI</title>
 
-    <link rel="stylesheet" th:href="@{#{webjars.fontawesomemin.css}}"/>
+    <link rel="stylesheet" type="text/css" th:href="@{#{webjars.fontawesomemin.css}}"/>
 
-    <link rel="stylesheet" th:href="@{/css/cas.css}"/>
+    <!--/* Core CAS CSS */-->
+    <link rel="stylesheet" type="text/css" th:href="@{/css/cas.css}"/>
 
-    <link rel="icon" th:href="@{/images/favicon.ico}" type="image/x-icon"/>
+    <link rel="icon" type="image/x-icon" th:href="${vitamuiFavicon} ? 'data:image/png;base64,' + ${vitamuiFavicon} : @{/images/favicon.ico}"/>
 
-    <script type="text/javascript" th:src="@{#{webjars.zxcvbn.js}}"></script>
     <script type="text/javascript" th:src="@{#{webjars.jquerymin.js}}"></script>
-    <script type="text/javascript" th:src="@{#{webjars.jqueryui.js}}"></script>
-    <script type="text/javascript" th:src="@{#{webjars.jquerycookie.js}}"></script>
-    <script src="//www.google.com/recaptcha/api.js" async defer th:if="${recaptchaSiteKey}"></script>
-    <script th:src="@{#{webjars.bootstrapmin.js}}"></script>
-
-    <script th:inline="javascript">
-        /*<![CDATA[*/
-
-        var trackGeoLocation = /*[[${trackGeoLocation}]]*/ === "true";
-
-        var googleAnalyticsTrackingId = /*[[${googleAnalyticsTrackingId}]]*/;
-
-        if (googleAnalyticsTrackingId != null && googleAnalyticsTrackingId != '') {
-            (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
-                        (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
-                    m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
-            })(window, document, 'script', 'https://www.google-analytics.com/analytics.js', 'ga');
-
-            ga('create', googleAnalyticsTrackingId, 'auto');
-            ga('send', 'pageview');
-        }
-
-        /*]]>*/
-    </script>
 
 </head>
 
diff --git a/cas/cas-server/src/main/resources/templates/protocol/casGetResponseView.html b/cas/cas-server/src/main/resources/templates/protocol/casGetResponseView.html
index 922824f35f5147ed8f22b9cfc17d4b31a7077e77..dcf0b122f1150089f01487c48c8aa20256057234 100644
--- a/cas/cas-server/src/main/resources/templates/protocol/casGetResponseView.html
+++ b/cas/cas-server/src/main/resources/templates/protocol/casGetResponseView.html
@@ -5,12 +5,12 @@
     <meta http-equiv="X-UA-Compatible" content="IE=edge"/>
     <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"/>
     <meta charset="UTF-8"/>
-    <title>Vitam-UI</title>
+    <title>${@environment.getProperty('theme.vitamui-platform-name')}</title>
 
     <meta http-equiv="refresh" th:attr="content=${'1; url=' + url}" />
     <meta name="viewport" content="width=device-width, initial-scale=1">
 
-    <link rel="icon" th:href="@{/images/favicon.ico}" type="image/x-icon"/>
+    <link rel="icon" type="image/x-icon" th:href="${vitamuiFavicon} ? 'data:image/png;base64,' + ${vitamuiFavicon} : @{/images/favicon.ico}"/>
     <script type="text/javascript" th:src="@{#{webjars.jquerymin.js}}"></script>
     <link th:href="@{/css/cas.css}" rel="stylesheet"/>
 </head>
diff --git a/deployment/environments/group_vars/all/vitamui_vars.yml b/deployment/environments/group_vars/all/vitamui_vars.yml
index 82fc596a8f25c39c0bb97321f8a29ad9ee5fd270..70e6342489b4e6b73267f74c4c8f8ea61ab96b36 100755
--- a/deployment/environments/group_vars/all/vitamui_vars.yml
+++ b/deployment/environments/group_vars/all/vitamui_vars.yml
@@ -156,6 +156,11 @@ vitamui:
     secure: true
     jvm_log: false
     logging_level: "INFO"
+    theme:
+      vitamui_platform_name: VITAM-UI
+      vitamui_favicon: "{{ vitamui_defaults.folder.root_path }}/conf/assets/favicon.ico"
+      vitam_logo: "{{ vitamui_defaults.folder.root_path }}/conf/assets/logo.png"
+      vitamui_logo_large: "{{ vitamui_defaults.folder.root_path }}/conf/assets/logo-large.png"
     log:
       logback_max_file_size: "10MB"
       logback_max_history: 30
diff --git a/deployment/roles/vitamui/templates/cas-server/application.yml.j2 b/deployment/roles/vitamui/templates/cas-server/application.yml.j2
index cdcad26e78dbabe36a410eec7f0121f62f28d8c4..b81772d874a6dcf0f837ee34795e344728377c4d 100644
--- a/deployment/roles/vitamui/templates/cas-server/application.yml.j2
+++ b/deployment/roles/vitamui/templates/cas-server/application.yml.j2
@@ -171,10 +171,12 @@ server-identity:
   identityServerId: 1
 
 
-# Example to override theme colors and logo
+# Example to override theme colors, logo, favicon, platform name ...
 theme:
-#  vitam-logo: {{ vitamui_defaults.folder.root_path }}/conf/assets/logo.png
-#  vitamui-logo-large: {{ vitamui_defaults.folder.root_path }}/conf/assets/logo-large.png
+  vitamui-platform-name: {{ vitamui.cas_server.theme.vitamui_platform_name }}
+  vitamui-favicon: {{ vitamui.cas_server.theme.vitamui_favicon }}
+  vitam-logo: {{ vitamui.cas_server.theme.vitam_logo }}
+  vitamui-logo-large: {{ vitamui.cas_server.theme.vitamui_logo_large }}
   primary: '{{ vitamui_platform_informations.theme_colors.vitamui_primary }}'
   secondary: '{{ vitamui_platform_informations.theme_colors.vitamui_secondary }}'