Merge branch 'master' into bootstrap-ui

# Conflicts:
#	.gitignore
#	app/pom.xml
#	app/src/main/resources/struts.xml
#	pom.xml
diff --git a/.gitignore b/.gitignore
index b7b9c8e..cf97e96 100644
--- a/.gitignore
+++ b/.gitignore
@@ -10,6 +10,11 @@
 *.iml
 *.iws
 
+# NetBeans
+/nb-configuration.xml
+/app/nb-configuration.xml
+/app/nbactions.xml
+
 # Mac
 .DS_Store
 
@@ -22,4 +27,5 @@
 tomcat-base
 deployment/docker-compose/postgresql-data
 deployment/docker-compose/roller-data
-deployment/data
+assembly-release/release.sh
+it-selenium/overlays/
diff --git a/app/pom.xml b/app/pom.xml
index dae2f54..bb04250 100644
--- a/app/pom.xml
+++ b/app/pom.xml
@@ -33,20 +33,20 @@
     <packaging>war</packaging>
 
     <properties>
-        <servlet.version>3.0.1</servlet.version>
+        <servlet.version>4.0.1</servlet.version>
         <jsp-api.version>2.2</jsp-api.version>
         <java-activation.version>1.2.0</java-activation.version>
         <java-mail.version>1.4.7</java-mail.version>
         <jstl.version>1.2</jstl.version>
 
-        <angular.version>1.2.29</angular.version>
-        <ant.version>1.10.1</ant.version>
+        <angular.version>1.7.8</angular.version>
+        <ant.version>1.10.5</ant.version>
         <commons-validator.version>1.6</commons-validator.version>
         <commons-beanutils.version>1.9.3</commons-beanutils.version>
         <commons-httpclient.version>3.1</commons-httpclient.version>
-        <commons-codec.version>1.10</commons-codec.version>
-        <eclipse-link.version>2.7.3</eclipse-link.version>
-        <guice.version>4.2.1</guice.version>
+        <commons-codec.version>1.12</commons-codec.version>
+        <eclipse-link.version>2.7.4</eclipse-link.version>
+        <guice.version>4.2.2</guice.version>
         <log4j.version>1.2.17</log4j.version>
         <log4j2.version>2.10.0</log4j2.version>
         <lucene.version>4.10.4</lucene.version>
@@ -54,11 +54,11 @@
         <maven-war.version>3.1.0</maven-war.version>
         <maven-surefire.version>2.17</maven-surefire.version>
         <maven-antrun.version>1.0b3</maven-antrun.version>
-        <rome.version>1.7.4</rome.version>
-        <slf4j.version>1.7.25</slf4j.version>
+        <rome.version>1.12.0</rome.version>
+        <slf4j.version>1.7.26</slf4j.version>
         <spring.version>4.1.4.RELEASE</spring.version>
         <spring.security.version>3.2.5.RELEASE</spring.security.version>
-        <struts.version>2.5.17</struts.version>
+        <struts.version>2.5.20</struts.version>
         <velocity.version>1.7</velocity.version>
         <webjars.version>1.5</webjars.version>
         <ws-commons-util.version>1.0.2</ws-commons-util.version>
@@ -119,20 +119,8 @@
          -->
         <dependency>
             <groupId>org.eclipse.persistence</groupId>
-            <artifactId>eclipselink</artifactId>
+            <artifactId>org.eclipse.persistence.jpa</artifactId>
             <version>${eclipse-link.version}</version>
-            <exclusions>
-                <exclusion>
-                    <groupId>org.eclipse.persistence</groupId>
-                    <artifactId>javax.persistence</artifactId>
-                </exclusion>
-            </exclusions>
-        </dependency>
-
-        <dependency>
-            <groupId>org.eclipse.persistence</groupId>
-            <artifactId>javax.persistence</artifactId>
-            <version>2.1.1</version>
         </dependency>
 
         <!-- Alternative testing with Hibernate (used by default with JBoss)
@@ -184,13 +172,30 @@
                 </exclusion>
             </exclusions>
         </dependency>
-
+        
         <dependency>
             <groupId>commons-collections</groupId>
             <artifactId>commons-collections</artifactId>
             <version>3.2.2</version>
         </dependency>
-
+        
+        <!-- explicitly adding newest asm lib to improve compatibility with latest JDKs -->
+        <dependency>
+            <groupId>org.ow2.asm</groupId>
+            <artifactId>asm</artifactId>
+            <version>7.1</version>
+        </dependency>
+        <dependency>
+            <groupId>org.ow2.asm</groupId>
+            <artifactId>asm-commons</artifactId>
+            <version>7.1</version>
+        </dependency>
+        <dependency>
+            <groupId>org.ow2.asm</groupId>
+            <artifactId>asm-tree</artifactId>
+            <version>7.1</version>
+        </dependency>
+        
         <dependency>
             <groupId>org.apache.struts</groupId>
             <artifactId>struts2-core</artifactId>
@@ -666,7 +671,7 @@
 
             <plugin>
                 <artifactId>maven-antrun-plugin</artifactId>
-                <version>1.7</version>
+                <version>1.8</version>
                 <dependencies>
                     <dependency>
                         <groupId>ant-contrib</groupId>
diff --git a/app/src/main/java/org/apache/roller/weblogger/ui/core/RollerContext.java b/app/src/main/java/org/apache/roller/weblogger/ui/core/RollerContext.java
index ec0d0c8..1acc7f4 100644
--- a/app/src/main/java/org/apache/roller/weblogger/ui/core/RollerContext.java
+++ b/app/src/main/java/org/apache/roller/weblogger/ui/core/RollerContext.java
@@ -234,10 +234,6 @@
         ApplicationContext ctx =
                 WebApplicationContextUtils.getRequiredWebApplicationContext(context);
 
-        /*String[] beanNames = ctx.getBeanDefinitionNames();
-        for (String name : beanNames)
-            System.out.println(name);*/
-
         String rememberMe = WebloggerConfig.getProperty("rememberme.enabled");
         boolean rememberMeEnabled = Boolean.valueOf(rememberMe);
 
@@ -246,7 +242,8 @@
         context.setAttribute("rememberMeEnabled", rememberMe);
 
         if (!rememberMeEnabled) {
-            ProviderManager provider = (ProviderManager) ctx.getBean("_authenticationManager");
+            ProviderManager provider =
+                (ProviderManager) ctx.getBean("org.springframework.security.authenticationManager");
             for (AuthenticationProvider authProvider : provider.getProviders()) {
                 if (authProvider instanceof RememberMeAuthenticationProvider) {
                     provider.getProviders().remove(authProvider);
@@ -282,31 +279,6 @@
                     (LoginUrlAuthenticationEntryPoint) ctx.getBean("_formLoginEntryPoint");
             entryPoint.setForceHttps(true);
         }
-   
-        /*
-        if (WebloggerConfig.getBooleanProperty("schemeenforcement.enabled")) {
-            
-            ChannelProcessingFilter procfilter =
-                    (ChannelProcessingFilter)ctx.getBean("channelProcessingFilter");
-            ConfigAttributeDefinition secureDef = new ConfigAttributeDefinition();
-            secureDef.addConfigAttribute(new SecurityConfig("REQUIRES_SECURE_CHANNEL"));
-            ConfigAttributeDefinition insecureDef = new ConfigAttributeDefinition();
-            insecureDef.addConfigAttribute(new SecurityConfig("REQUIRES_INSECURE_CHANNEL"));
-            PathBasedFilterInvocationDefinitionMap defmap =
-                    (PathBasedFilterInvocationDefinitionMap)procfilter.getFilterInvocationDefinitionSource();
-            
-            // add HTTPS URL path patterns to Spring Security config
-            String httpsUrlsProp = WebloggerConfig.getProperty("schemeenforcement.https.urls");
-            if (httpsUrlsProp != null) {
-                String[] httpsUrls = StringUtils.stripAll(StringUtils.split(httpsUrlsProp, ",") );
-                for (int i=0; i<httpsUrls.length; i++) {
-                    defmap.addSecureUrl(httpsUrls[i], secureDef);
-                }
-            }
-            // all other action URLs are non-HTTPS
-            defmap.addSecureUrl("/**<!-- need to remove this when uncommenting -->/*.do*", insecureDef);
-        }
-        */
     }
 
 
diff --git a/app/src/main/java/org/apache/roller/weblogger/ui/core/filters/SchemeEnforcementFilter.java b/app/src/main/java/org/apache/roller/weblogger/ui/core/filters/SchemeEnforcementFilter.java
deleted file mode 100644
index 0b0b394..0000000
--- a/app/src/main/java/org/apache/roller/weblogger/ui/core/filters/SchemeEnforcementFilter.java
+++ /dev/null
@@ -1,210 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- *  contributor license agreements.  The ASF licenses this file to You
- * under the Apache License, Version 2.0 (the "License"); you may not
- * use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.  For additional information regarding
- * copyright in this work, please see the NOTICE file in the top level
- * directory of this distribution.
- */
-/*
- * SchemeEnforcementFilter.java
- *
- * Created on September 16, 2005, 3:17 PM
- */
-
-package org.apache.roller.weblogger.ui.core.filters;
-
-import java.io.IOException;
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.Set;
-
-import javax.servlet.Filter;
-import javax.servlet.FilterChain;
-import javax.servlet.FilterConfig;
-import javax.servlet.ServletException;
-import javax.servlet.ServletRequest;
-import javax.servlet.ServletResponse;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-
-import org.apache.commons.lang3.StringUtils;
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.apache.roller.weblogger.config.WebloggerConfig;
-
-/**
- * The SchemeEnforcementFilter is provided for Roller sites that enable secure
- * logins and want to ensure that login urls are used only under https.
- *
- * @author Allen Gilliland
- * @web.filter name="SchemeEnforcementFilter"
- */
-public class SchemeEnforcementFilter implements Filter {
-
-    private static Log log = LogFactory.getLog(SchemeEnforcementFilter.class);
-
-    private boolean schemeEnforcementEnabled = false;
-    private boolean secureLoginEnabled = false;
-    private int httpPort = 80;
-    private int httpsPort = 443;
-
-    private Set<String> allowedUrls = new HashSet<String>();
-    private Set<String> ignored = new HashSet<String>();
-
-    /**
-     * Process filter.
-     * <p/>
-     * We'll take the incoming request and first determine if this is a secure
-     * request. If the request is secure then we'll see if it matches one of the
-     * allowed secure urls, if not then we will redirect back out of https.
-     */
-    public void doFilter(ServletRequest request, ServletResponse response,
-                         FilterChain chain) throws IOException, ServletException {
-
-        if (this.schemeEnforcementEnabled && this.secureLoginEnabled) {
-
-            HttpServletRequest req = (HttpServletRequest) request;
-            HttpServletResponse res = (HttpServletResponse) response;
-
-            if (log.isDebugEnabled()) {
-                log.debug("checking path = " + req.getServletPath());
-            }
-
-            if (!request.isSecure()
-                    && allowedUrls.contains(req.getServletPath())) {
-
-                // http insecure request that should be over https
-                String redirect = "https://" + req.getServerName();
-
-                if (this.httpsPort != 443) {
-                    redirect += ":" + this.httpsPort;
-                }
-
-                redirect += req.getRequestURI();
-
-                if (req.getQueryString() != null) {
-                    redirect += "?" + req.getQueryString();
-                }
-
-                if (log.isDebugEnabled()) {
-                    log.debug("Redirecting to " + redirect);
-                }
-
-                res.sendRedirect(redirect);
-                return;
-
-            } else if (request.isSecure()
-                    && !isIgnoredURL(req.getServletPath())
-                    && !allowedUrls.contains(req.getServletPath())) {
-
-                // https secure request that should be over http
-                String redirect = "http://" + req.getServerName();
-
-                if (this.httpPort != 80) {
-                    redirect += ":" + this.httpPort;
-                }
-
-                redirect += req.getRequestURI();
-
-                if (req.getQueryString() != null) {
-                    redirect += "?" + req.getQueryString();
-                }
-
-                if (log.isDebugEnabled()) {
-                    log.debug("Redirecting to " + redirect);
-                }
-
-                res.sendRedirect(redirect);
-                return;
-            }
-        }
-
-        chain.doFilter(request, response);
-    }
-
-    /**
-     * Checks if the url is to be ignored.
-     *
-     * @param theUrl the the url
-     * @return true, if the url is to be ignored.
-     */
-    private boolean isIgnoredURL(String theUrl) {
-
-        int i = theUrl.lastIndexOf('.');
-
-        return i <= 0 || i == theUrl.length()-1 || ignored.contains(theUrl.substring(i + 1));
-
-    }
-
-    /**
-     * @see javax.servlet.Filter#destroy()
-     */
-    public void destroy() {
-    }
-
-    /**
-     * Filter init.
-     * <p/>
-     * We are just collecting init properties which we'll use for each request.
-     */
-    public void init(FilterConfig filterConfig) {
-
-        // determine if we are doing scheme enforcement
-        this.schemeEnforcementEnabled = WebloggerConfig
-                .getBooleanProperty("schemeenforcement.enabled");
-        this.secureLoginEnabled = WebloggerConfig
-                .getBooleanProperty("securelogin.enabled");
-
-        if (this.schemeEnforcementEnabled && this.secureLoginEnabled) {
-            // gather some more properties
-            String http_port = WebloggerConfig
-                    .getProperty("securelogin.http.port");
-            String https_port = WebloggerConfig
-                    .getProperty("securelogin.https.port");
-
-            try {
-                this.httpPort = Integer.parseInt(http_port);
-                this.httpsPort = Integer.parseInt(https_port);
-            } catch (NumberFormatException nfe) {
-                // ignored ... guess we'll have to use the defaults
-                log.warn("error with secure login ports", nfe);
-            }
-
-            // finally, construct our list of allowable https urls and ignored
-            // resources
-            String cfgs = WebloggerConfig
-                    .getProperty("schemeenforcement.https.urls");
-            String[] cfgsArray = cfgs.split(",");
-            Collections.addAll(this.allowedUrls, cfgsArray);
-
-            cfgs = WebloggerConfig
-                    .getProperty("schemeenforcement.https.ignored");
-            cfgsArray = StringUtils.stripAll(StringUtils.split(cfgs, ","));
-            Collections.addAll(this.ignored, cfgsArray);
-
-            // some logging for the curious
-            log.info("Scheme enforcement = enabled");
-            if (log.isDebugEnabled()) {
-                log.debug("allowed urls are:");
-                for (String allowedUrl : allowedUrls) {
-                    log.debug(allowedUrl);
-                }
-                log.debug("ignored extensions are:");
-                for (String ignore : ignored) {
-                    log.debug(ignore);
-                }
-            }
-        }
-    }
-
-}
diff --git a/app/src/main/java/org/apache/roller/weblogger/ui/core/security/RollerRememberMeAuthenticationProvider.java b/app/src/main/java/org/apache/roller/weblogger/ui/core/security/RollerRememberMeAuthenticationProvider.java
new file mode 100644
index 0000000..a847abc
--- /dev/null
+++ b/app/src/main/java/org/apache/roller/weblogger/ui/core/security/RollerRememberMeAuthenticationProvider.java
@@ -0,0 +1,47 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  The ASF licenses this file to You
+ * under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.  For additional information regarding
+ * copyright in this work, please see the NOTICE file in the top level
+ * directory of this distribution.
+ */
+
+package org.apache.roller.weblogger.ui.core.security;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.roller.weblogger.config.WebloggerConfig;
+import org.springframework.security.authentication.RememberMeAuthenticationProvider;
+
+
+public class RollerRememberMeAuthenticationProvider extends RememberMeAuthenticationProvider {
+    private static final Log log = LogFactory.getLog(RollerRememberMeServices.class);
+
+
+    public RollerRememberMeAuthenticationProvider() {
+        log.debug("initializing: RollerRememberMeAuthenticationProvider");
+
+        String key = WebloggerConfig.getProperty("rememberme.key", "springRocks");
+
+        if ("springRocks".equals(key)) {
+            throw new RuntimeException(
+                "If remember-me is to be enabled, rememberme.key must be specified in the roller " +
+                "properties file. Make sure it is a secret and make sure it is NOT be springRocks");
+        }
+        setKey(key);
+
+        log.debug("initialized: RollerRememberMeAuthenticationProvider with key: " + getKey());
+    }
+}
+
+
diff --git a/app/src/main/java/org/apache/roller/weblogger/ui/core/security/RollerRememberMeServices.java b/app/src/main/java/org/apache/roller/weblogger/ui/core/security/RollerRememberMeServices.java
new file mode 100644
index 0000000..608d752
--- /dev/null
+++ b/app/src/main/java/org/apache/roller/weblogger/ui/core/security/RollerRememberMeServices.java
@@ -0,0 +1,78 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  The ASF licenses this file to You
+ * under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.  For additional information regarding
+ * copyright in this work, please see the NOTICE file in the top level
+ * directory of this distribution.
+ */
+
+package org.apache.roller.weblogger.ui.core.security;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.roller.weblogger.config.AuthMethod;
+import org.apache.roller.weblogger.config.WebloggerConfig;
+import org.springframework.security.crypto.codec.Hex;
+import org.springframework.security.web.authentication.rememberme.TokenBasedRememberMeServices;
+
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+
+
+public class RollerRememberMeServices extends TokenBasedRememberMeServices {
+    private static final Log log = LogFactory.getLog(RollerRememberMeServices.class);
+
+
+    public RollerRememberMeServices() {
+        log.debug("initializing: RollerRememberMeServices");
+
+        String key = WebloggerConfig.getProperty("rememberme.key", "springRocks");
+
+        if ("springRocks".equals(key)) {
+            throw new RuntimeException(
+                "If remember-me is to be enabled, rememberme.key must be specified in the roller " +
+                    "properties file. Make sure it is a secret and make sure it is NOT be springRocks");
+        }
+        setKey(key);
+
+        log.debug("initialized: RollerRememberMeServices with key: " + getKey());
+    }
+
+    /**
+     * Calculates the digital signature to be put in the cookie. Default value is
+     * MD5 ("username:tokenExpiryTime:password:key")
+     *
+     * If LDAP is enabled then a configurable dummy password is used in the calculation.
+     */
+    protected String makeTokenSignature(long tokenExpiryTime, String username, String password) {
+
+        boolean usingLDAP = WebloggerConfig.getAuthMethod() == AuthMethod.LDAP;
+        if (usingLDAP) {
+            log.debug("LDAP is enabled; using dummy password in remember me signature.");
+
+            // for LDAP we don't store its password in the roller_users table,
+            // just an string indicating external auth method being used.
+            password = WebloggerConfig.getProperty("users.passwords.externalAuthValue","<externalAuth>");
+        }
+
+        String data = username + ":" + tokenExpiryTime + ":" + password + ":" + getKey();
+        MessageDigest digest;
+        try {
+            digest = MessageDigest.getInstance("MD5");
+        } catch (NoSuchAlgorithmException e) {
+            throw new IllegalStateException("No MD5 algorithm available!");
+        }
+
+        return new String(Hex.encode(digest.digest(data.getBytes())));
+    }
+}
diff --git a/app/src/main/java/org/apache/roller/weblogger/ui/rendering/plugins/comments/MathCommentAuthenticator.java b/app/src/main/java/org/apache/roller/weblogger/ui/rendering/plugins/comments/MathCommentAuthenticator.java
index 33a2d5d..8f37859 100644
--- a/app/src/main/java/org/apache/roller/weblogger/ui/rendering/plugins/comments/MathCommentAuthenticator.java
+++ b/app/src/main/java/org/apache/roller/weblogger/ui/rendering/plugins/comments/MathCommentAuthenticator.java
@@ -37,7 +37,7 @@
     
     public String getHtml(HttpServletRequest request) {
         
-        String answer = "";
+        int answer = 0;
         
         HttpSession session = request.getSession(true);
         if (session.getAttribute("mathAnswer") == null) {
@@ -51,10 +51,12 @@
             session.setAttribute("mathAnswer", sum);
         } else {
             // preserve user's answer
-            answer = request.getParameter("answer");
-            answer = (answer == null) ? "" : answer;
+            String answerString = request.getParameter("answer");
+            try {
+                answer = Integer.parseInt(answerString);
+            } catch (Throwable intentionallyIgnored) {}
         }
-        
+
         // pull existing values out of session
         Integer value1o = (Integer)request.getSession().getAttribute("mathValue1");
         Integer value2o = (Integer)request.getSession().getAttribute("mathValue2");
diff --git a/app/src/main/resources/org/apache/roller/weblogger/config/roller.properties b/app/src/main/resources/org/apache/roller/weblogger/config/roller.properties
index 9ea2484..258f99d 100644
--- a/app/src/main/resources/org/apache/roller/weblogger/config/roller.properties
+++ b/app/src/main/resources/org/apache/roller/weblogger/config/roller.properties
@@ -604,8 +604,10 @@
 # True to enable history in Atom feeds with next/prev links
 site.newsfeeds.history.enabled=false
 
-# Some folks consider remember-me type functionality to be a security
-rememberme.enabled=true
+# Some folks consider remember-me type functionality to be a security risk
+# If you enable remember me you MUST define a unique secret key that is not 'springRocks'
+rememberme.enabled=false
+rememberme.key=
 
 # You might want to disable GZIP if your app server already supports it
 compression.gzipResponse.enabled=true
diff --git a/app/src/main/resources/sql/400-to-500-migration.vm b/app/src/main/resources/sql/400-to-500-migration.vm
index 98e1e44..8ff0fca 100644
--- a/app/src/main/resources/sql/400-to-500-migration.vm
+++ b/app/src/main/resources/sql/400-to-500-migration.vm
@@ -87,7 +87,6 @@
     username       varchar(48)
 );
 create index oc_username_idx  on roller_oauthconsumer( username$!db.INDEXSIZE );
-create index oc_consumerkey_idx  on roller_oauthconsumer( consumerkey$!db.INDEXSIZE );
 
 -- each record is an OAuth accessor, always tied to just one user
 create table roller_oauthaccessor (
diff --git a/app/src/main/resources/sql/createdb.vm b/app/src/main/resources/sql/createdb.vm
index 5e6092e..b870a3c 100644
--- a/app/src/main/resources/sql/createdb.vm
+++ b/app/src/main/resources/sql/createdb.vm
@@ -508,4 +508,3 @@
 -- oauth indexes
 
 create index oc_username_idx  on roller_oauthconsumer( username$!db.INDEXSIZE );
-create index oc_consumerkey_idx  on roller_oauthconsumer( consumerkey$!db.INDEXSIZE );
diff --git a/app/src/main/resources/struts.xml b/app/src/main/resources/struts.xml
index 6a530d2..a345b20 100644
--- a/app/src/main/resources/struts.xml
+++ b/app/src/main/resources/struts.xml
@@ -2,18 +2,18 @@
 <!--
         Licensed to the Apache Software Foundation (ASF) under one or more
         contributor license agreements.  The ASF licenses this file to You
-        under the Apache License, Version 2.0 (the "License"); you may not
+        under the Apache License,Version 2.0 (the "License"); you may not
         use this file except in compliance with the License.
         You may obtain a copy of the License at
 
         http://www.apache.org/licenses/LICENSE-2.0
 
-        Unless required by applicable law or agreed to in writing, software
+        Unless required by applicable law or agreed to in writing,software
         distributed under the License is distributed on an "AS IS" BASIS,
-        WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+        WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,either express or implied.
         See the License for the specific language governing permissions and
         limitations under the License.  For additional information regarding
-        copyright in this work, please see the NOTICE file in the top level
+        copyright in this work,please see the NOTICE file in the top level
         directory of this distribution.
 -->
 <!DOCTYPE struts PUBLIC
@@ -75,7 +75,7 @@
                     <param name="excludeMethods">cancel</param>
                 </interceptor-ref>
                 
-                <!-- validation interceptors, MUST come after our custom interceptors -->
+                <!-- validation interceptors,MUST come after our custom interceptors -->
                 <interceptor-ref name="validation">
                     <param name="excludeMethods">input,back,cancel,browse</param>
                 </interceptor-ref>
@@ -112,7 +112,7 @@
                 class="org.apache.roller.weblogger.ui.struts2.core.Setup">
             <result name="success" type="tiles">.Setup</result>
             <result name="home" type="redirectAction">home</result>
-            <allowed-methods>activate, execute, save</allowed-methods>
+            <allowed-methods>activate,execute,save</allowed-methods>
         </action>
                         
         <action name="login"
@@ -126,7 +126,7 @@
             <result name="input" type="tiles">.Register</result>
             <result name="disabled" type="tiles">.GenericError</result>
             <result name="success" type="tiles">.Welcome</result>
-            <allowed-methods>activate, execute, save</allowed-methods>
+            <allowed-methods>activate,execute,save</allowed-methods>
         </action>
         
         <action name="profile"
@@ -134,7 +134,7 @@
             <result name="input" type="tiles">.Profile</result>
             <result name="cancel" type="redirectAction">menu</result>
             <result name="success" type="tiles">.MainMenu</result>
-            <allowed-methods>execute, save</allowed-methods>
+            <allowed-methods>execute,save</allowed-methods>
         </action>
 
         <action name="oauthKeys"
@@ -154,13 +154,13 @@
             <result name="input" type="tiles">.CreateWeblog</result>
             <result name="disabled" type="tiles">.GenericError</result>
             <result name="success" type="chain">menu</result>
-            <allowed-methods>cancel, execute, save</allowed-methods>
+            <allowed-methods>cancel,execute,save</allowed-methods>
         </action>
         
         <action name="menu"
                 class="org.apache.roller.weblogger.ui.struts2.core.MainMenu">
             <result type="tiles">.MainMenu</result>
-            <allowed-methods>accept, decline, execute</allowed-methods>
+            <allowed-methods>accept,decline,execute</allowed-methods>
         </action>
 
     </package>
@@ -169,6 +169,14 @@
     <!-- Weblogger install/bootstrap actions -->
     <package name="weblogger-install" namespace="/roller-ui/install" extends="weblogger" >
 
+        <global-allowed-methods>
+            execute,
+            create,
+            update,
+            upgrade,
+            bootstrap
+        </global-allowed-methods>
+
         <action name="install"
                 class="org.apache.roller.weblogger.ui.struts2.core.Install">
             <result name="database_error" type="tiles">.DatabaseError</result>
@@ -179,7 +187,7 @@
                 <param name="actionName">home</param>
                 <param name="namespace">/roller-ui</param>
             </result>
-            <allowed-methods>execute, create, upgrade, bootstrap</allowed-methods>
+            <allowed-methods>execute,create,upgrade,bootstrap</allowed-methods>
         </action>
             
     </package>
@@ -192,7 +200,7 @@
                 class="org.apache.roller.weblogger.ui.struts2.admin.GlobalConfig">
             <result name="success" type="tiles">.GlobalConfig</result>
             <result name="error" type="tiles">.GlobalConfig</result>
-            <allowed-methods>execute, save</allowed-methods>
+            <allowed-methods>execute,save</allowed-methods>
         </action>
                
         <action name="userAdmin"
@@ -204,7 +212,7 @@
                 <param name="actionName">modifyUser</param>
                 <param name="bean.userName">${bean.userName}</param>
             </result>
-            <allowed-methods>edit, execute</allowed-methods>
+            <allowed-methods>edit,execute</allowed-methods>
         </action>
         
         <action name="createUser"
@@ -216,7 +224,7 @@
                 <param name="actionName">modifyUser!firstSave</param>
                 <param name="bean.id">${bean.id}</param>
             </result>
-            <allowed-methods>execute, firstSave, save</allowed-methods>
+            <allowed-methods>execute,firstSave,save</allowed-methods>
         </action>
 
         <action name="modifyUser"
@@ -228,20 +236,20 @@
             <result name="cancel" type="redirectAction">
                 <param name="actionName">userAdmin</param>
             </result>
-            <allowed-methods>execute, firstSave, save</allowed-methods>
+            <allowed-methods>execute,firstSave,save</allowed-methods>
         </action>
         
         <action name="globalCommentManagement"
                 class="org.apache.roller.weblogger.ui.struts2.admin.GlobalCommentManagement">
             <result name="list" type="tiles">.GlobalCommentManagement</result>
-            <allowed-methods>execute, delete, query, update</allowed-methods>
+            <allowed-methods>execute,delete,query,update</allowed-methods>
         </action>
         
         <action name="commonPingTargets"
                 class="org.apache.roller.weblogger.ui.struts2.admin.PingTargets">
             <result name="list" type="tiles">.PingTargets</result>
             <result name="confirm" type="tiles">.PingTargetConfirm</result>
-            <allowed-methods>delete, deleteConfirm, disable, enable, execute</allowed-methods>
+            <allowed-methods>delete,deleteConfirm,disable,enable,execute</allowed-methods>
         </action>
         
         <action name="commonPingTargetAdd"
@@ -266,25 +274,25 @@
         <action name="cacheInfo"
                 class="org.apache.roller.weblogger.ui.struts2.admin.CacheInfo">
             <result name="success" type="tiles">.CacheInfo</result>
-            <allowed-methods>execute, clear</allowed-methods>
+            <allowed-methods>execute,clear</allowed-methods>
         </action>
 
         <action name="planetConfig"
                 class="org.apache.roller.weblogger.planet.ui.PlanetConfig">
             <result name="input" type="tiles">.PlanetConfig</result>
-            <allowed-methods>execute, save</allowed-methods>
+            <allowed-methods>execute,save</allowed-methods>
         </action>
         
         <action name="planetGroupSubs"
                 class="org.apache.roller.weblogger.planet.ui.PlanetGroupSubs">
             <result name="list" type="tiles">.PlanetGroupSubs</result>
-            <allowed-methods>execute, deleteSubscription, saveGroup, saveSubscription</allowed-methods>
+            <allowed-methods>execute,deleteSubscription,saveGroup,saveSubscription</allowed-methods>
         </action>
         
         <action name="planetGroups"
                 class="org.apache.roller.weblogger.planet.ui.PlanetGroups">
             <result name="list" type="tiles">.PlanetGroups</result>
-            <allowed-methods>delete, execute</allowed-methods>
+            <allowed-methods>delete,execute</allowed-methods>
         </action>
     </package>
     
@@ -301,14 +309,14 @@
                 <param name="actionName">mediaFileView</param>
                 <param name="weblog">${weblog}</param>
             </result>
-            <allowed-methods>execute, save</allowed-methods>
+            <allowed-methods>execute,save</allowed-methods>
         </action>
 
         <action name="mediaFileEdit"
                 class="org.apache.roller.weblogger.ui.struts2.editor.MediaFileEdit">
             <result name="input" type="tiles">.MediaFileEdit</result>
             <result name="success" type="tiles">.MediaFileEditSuccess</result>
-            <allowed-methods>execute, save</allowed-methods>
+            <allowed-methods>execute,save</allowed-methods>
         </action>
 
         <action name="mediaFileAddExternalInclude"
@@ -316,7 +324,7 @@
             <result name="input" type="tiles">.MediaFileAddExternalInclude</result>
             <result name="success" type="tiles">.MediaFileAddExternalInclude</result>
             <result name="error" type="tiles">.MediaFileAddExternalInclude</result>
-            <allowed-methods>execute, save</allowed-methods>
+            <allowed-methods>execute,save</allowed-methods>
         </action>
 
 	    <action name="mediaFileView"
@@ -359,7 +367,7 @@
                 <param name="weblog">${weblog}</param>
                 <param name="bean.id">${bean.id}</param>
             </result>
-            <allowed-methods>execute, firstSave, publish, saveDraft, trackback</allowed-methods>
+            <allowed-methods>execute,firstSave,publish,saveDraft,trackback</allowed-methods>
         </action>
 
         <action name="entryEdit"
@@ -371,7 +379,7 @@
                 <param name="actionName">menu</param>
                 <param name="namespace">/roller-ui</param>
             </result>
-            <allowed-methods>execute, firstSave, publish, saveDraft, trackback</allowed-methods>
+            <allowed-methods>execute,firstSave,publish,saveDraft,trackback</allowed-methods>
         </action>
         
         <action name="entryRemove"
@@ -383,11 +391,11 @@
                 <param name="namespace">/roller-ui</param>
             </result>
             <result name="success" type="chain">entryAdd</result>
-            <allowed-methods>execute, remove</allowed-methods>
+            <allowed-methods>execute,remove</allowed-methods>
         </action>
 
-        <!-- Below activated by Entries.jsp and EntryRemove.jsp, kept separate from
-        entryRemove above as return pages are different, both in the confirm delete
+        <!-- Below activated by Entries.jsp and EntryRemove.jsp,kept separate from
+        entryRemove above as return pages are different,both in the confirm delete
         and cancel delete scenarios.
 
         Note the different actionName parameters.  The actionName is used to determine
@@ -405,7 +413,7 @@
                 <param name="namespace">/roller-ui</param>
             </result>
           <result name="success" type="chain">entries</result>
-            <allowed-methods>execute, remove</allowed-methods>
+            <allowed-methods>execute,remove</allowed-methods>
         </action>
 
         <action name="entries"
@@ -417,13 +425,13 @@
         <action name="comments"
                 class="org.apache.roller.weblogger.ui.struts2.editor.Comments">
             <result name="list" type="tiles">.Comments</result>
-            <allowed-methods>delete, execute, query, update</allowed-methods>
+            <allowed-methods>delete,execute,query,update</allowed-methods>
         </action>
 
         <action name="categories"
                 class="org.apache.roller.weblogger.ui.struts2.editor.Categories">
             <result name="list" type="tiles">.Categories</result>
-            <allowed-methods>execute, move</allowed-methods>
+            <allowed-methods>execute,move</allowed-methods>
         </action>
 
         <action name="categoryAdd"
@@ -433,7 +441,7 @@
             <result name="input" type="tiles">.CategoryEdit</result>
             <result name="success" type="chain">categories</result>
             <result name="error" type="chain">categories</result>
-            <allowed-methods>execute, save</allowed-methods>
+            <allowed-methods>execute,save</allowed-methods>
         </action>
 
         <action name="categoryEdit"
@@ -446,7 +454,7 @@
                 <param name="actionName">categories</param>
                 <param name="weblog">${weblog}</param>
             </result>
-            <allowed-methods>execute, save</allowed-methods>
+            <allowed-methods>execute,save</allowed-methods>
         </action>
 
         <action name="categoryRemove"
@@ -457,13 +465,13 @@
                 <param name="weblog">${weblog}</param>
             </result>
             <result name="success" type="chain">categories</result>
-            <allowed-methods>execute, remove</allowed-methods>
+            <allowed-methods>execute,remove</allowed-methods>
         </action>
 
         <action name="bookmarks"
                 class="org.apache.roller.weblogger.ui.struts2.editor.Bookmarks">
             <result name="list" type="tiles">.Bookmarks</result>
-            <allowed-methods>delete, deleteFolder, execute, folderCreated, move, view</allowed-methods>
+            <allowed-methods>delete,deleteFolder,execute,folderCreated,move,view</allowed-methods>
         </action>
 
         <action name="bookmarkAdd"
@@ -473,7 +481,7 @@
             <result name="input" type="tiles">.BookmarkEdit</result>
             <result name="success" type="chain">bookmarks</result>
             <result name="error" type="chain">bookmarks</result>
-            <allowed-methods>execute, save</allowed-methods>
+            <allowed-methods>execute,save</allowed-methods>
         </action>
 
         <action name="bookmarkEdit"
@@ -488,14 +496,14 @@
                 <param name="folderId">${folderId}</param>
             </result>
             <result name="error" type="chain">bookmarkEdit</result>
-            <allowed-methods>execute, save</allowed-methods>
+            <allowed-methods>execute,save</allowed-methods>
         </action>
 
         <action name="bookmarksImport"
                 class="org.apache.roller.weblogger.ui.struts2.editor.BookmarksImport">
             <result name="input" type="tiles">.BookmarksImport</result>
             <result name="success" type="chain">bookmarks</result>
-            <allowed-methods>execute, save</allowed-methods>
+            <allowed-methods>execute,save</allowed-methods>
         </action>
 
         <action name="folderAdd"
@@ -510,7 +518,7 @@
                 <param name="folderId">${folderId}</param>
             </result>
             <result name="error" type="chain">bookmarks</result>
-            <allowed-methods>execute, save</allowed-methods>
+            <allowed-methods>execute,save</allowed-methods>
         </action>
 
         <action name="folderEdit"
@@ -525,13 +533,13 @@
                 <param name="folderId">${folderId}</param>
             </result>
             <result name="error" type="chain">bookmarks</result>
-            <allowed-methods>execute, save</allowed-methods>
+            <allowed-methods>execute,save</allowed-methods>
         </action>
 
         <action name="weblogConfig"
                 class="org.apache.roller.weblogger.ui.struts2.editor.WeblogConfig">
             <result name="input" type="tiles">.WeblogConfig</result>
-            <allowed-methods>execute, save</allowed-methods>
+            <allowed-methods>execute,save</allowed-methods>
         </action>
         
         <action name="weblogRemove"
@@ -541,19 +549,19 @@
                 <param name="actionName">menu</param>
                 <param name="namespace">/roller-ui</param>
             </result>
-            <allowed-methods>execute, remove</allowed-methods>
+            <allowed-methods>execute,remove</allowed-methods>
         </action>
         
         <action name="themeEdit"
                 class="org.apache.roller.weblogger.ui.struts2.editor.ThemeEdit">
             <result name="input" type="tiles">.ThemeEdit</result>
-            <allowed-methods>execute, save</allowed-methods>
+            <allowed-methods>execute,save</allowed-methods>
         </action>
         
         <action name="stylesheetEdit"
                 class="org.apache.roller.weblogger.ui.struts2.editor.StylesheetEdit">
             <result name="input" type="tiles">.StylesheetEdit</result>
-            <allowed-methods>copyStylesheet, delete, execute, revert, save </allowed-methods>
+            <allowed-methods>copyStylesheet,delete,execute,revert,save</allowed-methods>
         </action>
         
         <action name="templates"
@@ -566,13 +574,13 @@
                 class="org.apache.roller.weblogger.ui.struts2.editor.TemplateEdit">
             <result name="list" type="chain">templates</result>
             <result name="input" type="tiles">.TemplateEdit</result>
-            <allowed-methods>execute, save</allowed-methods>
+            <allowed-methods>execute,save</allowed-methods>
         </action>
 
         <action name="members"
                 class="org.apache.roller.weblogger.ui.struts2.editor.Members">
             <result name="list" type="tiles">.Members</result>
-            <allowed-methods>execute, save</allowed-methods>
+            <allowed-methods>execute,save</allowed-methods>
         </action>
         
         <action name="invite"
@@ -584,7 +592,7 @@
                 <param name="actionName">members</param>
                 <param name="weblog">${weblog}</param>
             </result>
-            <allowed-methods>execute, save</allowed-methods>
+            <allowed-methods>execute,save</allowed-methods>
         </action>
 
         <action name="memberResign"
@@ -598,19 +606,19 @@
                 <param name="actionName">menu</param>
                 <param name="namespace">/roller-ui</param>
             </result>
-            <allowed-methods>execute, resign</allowed-methods>
+            <allowed-methods>execute,resign</allowed-methods>
         </action>
 
         <action name="pings"
                 class="org.apache.roller.weblogger.ui.struts2.editor.Pings">
             <result name="list" type="tiles">.Pings</result>
-            <allowed-methods>disable, enable, execute, pingNow</allowed-methods>
+            <allowed-methods>disable,enable,execute,pingNow</allowed-methods>
         </action>
 
         <action name="maintenance"
                 class="org.apache.roller.weblogger.ui.struts2.editor.Maintenance">
             <result name="success" type="tiles">.Maintenance</result>
-            <allowed-methods>execute, flushCache, reset</allowed-methods>
+            <allowed-methods>execute,flushCache,reset</allowed-methods>
         </action>
 
     </package>
@@ -625,7 +633,7 @@
             <result name="input" type="tiles">.MediaFileAddInclude</result>
             <result name="success" type="tiles">.MediaFileAddSuccessInclude</result>
             <result name="error" type="tiles">.MediaFileAddInclude</result>
-            <allowed-methods>execute, save</allowed-methods>
+            <allowed-methods>execute,save</allowed-methods>
         </action>
 
 	    <action name="mediaFileImageChooser"
@@ -634,7 +642,7 @@
             <result name="input" type="tiles">.MediaFileImageChooser</result>
             <result name="error" type="tiles">.MediaFileImageChooser</result>
             <result name="success" type="tiles">.MediaFileImageChooser</result>
-            <allowed-methods>execute, save</allowed-methods>
+            <allowed-methods>execute,save</allowed-methods>
         </action>
 
     </package>
diff --git a/app/src/main/webapp/WEB-INF/security.xml b/app/src/main/webapp/WEB-INF/security.xml
index 73094b0..d3e8fa3 100644
--- a/app/src/main/webapp/WEB-INF/security.xml
+++ b/app/src/main/webapp/WEB-INF/security.xml
@@ -41,7 +41,7 @@
                     authentication-failure-url="/roller-ui/login.rol?error=true"
                     login-processing-url="/roller_j_security_check"/>
 
-        <remember-me user-service-ref="rollerUserService"
+        <remember-me services-ref="rollerRememberMeServices"
                      key="715F2448-3176-11DD-ABC6-9CD955D89593"/>
 
         <custom-filter ref="openidAuthenticationProcessingFilter" position="OPENID_FILTER"/>
@@ -63,19 +63,28 @@
     <!-- Read users from Roller API -->
     <authentication-manager alias='rollerAuthenticationManager'>
         <authentication-provider ref="rememberMeAuthenticationProvider"/>
+
         <!-- Uncomment one of the three below, based on whether database, LDAP, or
              OpenID authentication is desired. -->
         <authentication-provider user-service-ref="rollerUserService"/>
-        <!--authentication-provider ref="ldapAuthProvider"/>
-        <authentication-provider ref="openIDAuthProvider"/-->
+        <!--
+        <authentication-provider ref="ldapAuthProvider" />
+        <authentication-provider ref="openIDAuthProvider"/>
+        -->
     </authentication-manager>
 
     <beans:bean id="rollerUserService"
                 class="org.apache.roller.weblogger.ui.core.security.RollerUserDetailsService"/>
 
+    <beans:bean id="rollerRememberMeServices"
+                class="org.apache.roller.weblogger.ui.core.security.RollerRememberMeServices">
+        <beans:property name="key" value="ignored"/>
+        <beans:property name="userDetailsService" ref="rollerUserService"/>
+    </beans:bean>
+
     <beans:bean id="rememberMeAuthenticationProvider"
-                class="org.springframework.security.authentication.RememberMeAuthenticationProvider">
-        <beans:property name="key" value="springRocks"/>
+                class="org.apache.roller.weblogger.ui.core.security.RollerRememberMeAuthenticationProvider">
+        <beans:property name="key" value="ignored"/>
     </beans:bean>
 
     <beans:bean id = "openIDAuthProvider" class="org.springframework.security.openid.OpenIDAuthenticationProvider">
@@ -113,10 +122,10 @@
         </beans:property>
     </beans:bean>
 
-    <!-- Uncomment & customize below beans if using LDAP -->
-    <!--beans:bean id="contextSource" class="org.springframework.security.ldap.DefaultSpringSecurityContextSource">
-        <beans:constructor-arg value="ldap://localhost:10389/dc=example,dc=com" />
-        <beans:property name="userDn" value="uid=admin,ou=system" />
+    <!-- Uncomment & customize below beans if using LDAP
+    <beans:bean id="contextSource" class="org.springframework.security.ldap.DefaultSpringSecurityContextSource">
+        <beans:constructor-arg value="ldap://localhost:389/dc=example,dc=com" />
+        <beans:property name="userDn" value="uid=admin" />
         <beans:property name="password" value="secret" />
     </beans:bean>
 
@@ -142,6 +151,7 @@
         <beans:constructor-arg index="1" value="(uid={0})" />
         <beans:constructor-arg index="2" ref="contextSource" />
         <beans:property name="searchSubtree" value="true" />
-    </beans:bean-->
-
+    </beans:bean>
+    -->
+    
 </beans:beans>
diff --git a/app/src/main/webapp/WEB-INF/web.xml b/app/src/main/webapp/WEB-INF/web.xml
index 2783697..3ccd730 100644
--- a/app/src/main/webapp/WEB-INF/web.xml
+++ b/app/src/main/webapp/WEB-INF/web.xml
@@ -56,11 +56,6 @@
     </filter>
 
     <filter>
-        <filter-name>SchemeEnforcementFilter</filter-name>
-        <filter-class>org.apache.roller.weblogger.ui.core.filters.SchemeEnforcementFilter</filter-class>
-    </filter>
-
-    <filter>
         <filter-name>CharEncodingFilter</filter-name>
         <filter-class>org.apache.roller.weblogger.ui.core.filters.CharEncodingFilter</filter-class>
     </filter>
@@ -104,13 +99,6 @@
         <dispatcher>FORWARD</dispatcher>
     </filter-mapping>
 
-    <!-- Scheme enforcement.  Only here until we get Spring Security scheme enforcement working -->
-    <filter-mapping>
-        <filter-name>SchemeEnforcementFilter</filter-name>
-        <url-pattern>/*</url-pattern>
-        <dispatcher>REQUEST</dispatcher>
-    </filter-mapping>
-
     <!-- Spring Security filters - controls secure access to different parts of Roller -->
     <filter-mapping>
         <filter-name>securityFilter</filter-name>
diff --git a/pom.xml b/pom.xml
index 9670bc0..9373820 100644
--- a/pom.xml
+++ b/pom.xml
@@ -80,7 +80,7 @@
                 <plugin>
                     <groupId>org.eclipse.jetty</groupId>
                     <artifactId>jetty-maven-plugin</artifactId>
-                    <version>9.4.11.v20180605</version>
+                    <version>9.4.17.v20190418</version>
                 </plugin>
                 <plugin>
                     <groupId>com.btmatthews.maven.plugins.inmemdb</groupId>
@@ -93,7 +93,7 @@
                 </plugin>
             </plugins>
         </pluginManagement>
-     </build>
+    </build>
 
     <dependencyManagement>
         <dependencies>