Просмотр исходного кода

Merge remote-tracking branch 'origin/master' into angular-html-editor

jalbr74 7 лет назад
Родитель
Сommit
7eb31efa46

+ 23 - 25
server/pom.xml

@@ -92,7 +92,7 @@
             <plugin>
             <plugin>
                 <groupId>com.github.spotbugs</groupId>
                 <groupId>com.github.spotbugs</groupId>
                 <artifactId>spotbugs-maven-plugin</artifactId>
                 <artifactId>spotbugs-maven-plugin</artifactId>
-                <version>3.1.0-RC8</version>
+                <version>3.1.1</version>
                 <dependencies>
                 <dependencies>
                     <dependency>
                     <dependency>
                         <groupId>com.github.spotbugs</groupId>
                         <groupId>com.github.spotbugs</groupId>
@@ -327,32 +327,25 @@
                 </executions>
                 </executions>
             </plugin>
             </plugin>
             <plugin>
             <plugin>
+                <!-- verifies jsp pages compile, but does not include the compiled versions in the WAR -->
                 <groupId>io.leonard.maven.plugins</groupId>
                 <groupId>io.leonard.maven.plugins</groupId>
                 <artifactId>jspc-maven-plugin</artifactId>
                 <artifactId>jspc-maven-plugin</artifactId>
                 <version>2.4.2</version>
                 <version>2.4.2</version>
-            </plugin>
-            <plugin>
-                <artifactId>maven-clean-plugin</artifactId>
-                <version>3.0.0</version>
                 <executions>
                 <executions>
                     <execution>
                     <execution>
-                        <id>remove-compiled-jsps</id>
-                        <phase>prepare-package</phase>
                         <goals>
                         <goals>
-                            <goal>clean</goal>
+                            <goal>compile</goal>
                         </goals>
                         </goals>
+                        <phase>compile</phase>
                         <configuration>
                         <configuration>
-                            <excludeDefaultDirectories>true</excludeDefaultDirectories>
-                            <filesets>
-                                <fileset>
-                                    <directory>target/classes/jsp</directory>
-                                </fileset>
-                            </filesets>
+                            <compilerVersion>${maven.compiler.source}</compilerVersion>
+                            <keepSources>false</keepSources>
                         </configuration>
                         </configuration>
                     </execution>
                     </execution>
                 </executions>
                 </executions>
             </plugin>
             </plugin>
             <plugin>
             <plugin>
+                <!-- builds xml file of dependencies and licenses for use in about page -->
                 <groupId>com.github.jinnovations</groupId>
                 <groupId>com.github.jinnovations</groupId>
                 <artifactId>attribution-maven-plugin</artifactId>
                 <artifactId>attribution-maven-plugin</artifactId>
                 <version>0.9.5</version>
                 <version>0.9.5</version>
@@ -452,7 +445,7 @@
             <plugin> <!-- checks owsp vulnerability database during verify phase -->
             <plugin> <!-- checks owsp vulnerability database during verify phase -->
                 <groupId>org.owasp</groupId>
                 <groupId>org.owasp</groupId>
                 <artifactId>dependency-check-maven</artifactId>
                 <artifactId>dependency-check-maven</artifactId>
-                <version>3.0.1</version>
+                <version>3.1.1</version>
                 <configuration>
                 <configuration>
                     <nuspecAnalyzerEnabled>false</nuspecAnalyzerEnabled>
                     <nuspecAnalyzerEnabled>false</nuspecAnalyzerEnabled>
                     <assemblyAnalyzerEnabled>false</assemblyAnalyzerEnabled>
                     <assemblyAnalyzerEnabled>false</assemblyAnalyzerEnabled>
@@ -584,19 +577,19 @@
         <dependency>
         <dependency>
             <groupId>org.mockito</groupId>
             <groupId>org.mockito</groupId>
             <artifactId>mockito-core</artifactId>
             <artifactId>mockito-core</artifactId>
-            <version>2.2.11</version>
+            <version>2.13.0</version>
             <scope>test</scope>
             <scope>test</scope>
         </dependency>
         </dependency>
         <dependency>
         <dependency>
             <groupId>org.assertj</groupId>
             <groupId>org.assertj</groupId>
             <artifactId>assertj-core</artifactId>
             <artifactId>assertj-core</artifactId>
-            <version>3.5.2</version>
+            <version>3.9.0</version>
             <scope>test</scope>
             <scope>test</scope>
         </dependency>
         </dependency>
         <dependency>
         <dependency>
             <groupId>com.github.tomakehurst</groupId>
             <groupId>com.github.tomakehurst</groupId>
             <artifactId>wiremock</artifactId>
             <artifactId>wiremock</artifactId>
-            <version>1.58</version>
+            <version>2.14.0</version>
             <scope>test</scope>
             <scope>test</scope>
         </dependency>
         </dependency>
         <dependency>
         <dependency>
@@ -610,13 +603,13 @@
         <dependency>
         <dependency>
             <groupId>javax.servlet</groupId>
             <groupId>javax.servlet</groupId>
             <artifactId>javax.servlet-api</artifactId>
             <artifactId>javax.servlet-api</artifactId>
-            <version>3.0.1</version>
+            <version>4.0.0</version>
             <scope>provided</scope>
             <scope>provided</scope>
         </dependency>
         </dependency>
         <dependency>
         <dependency>
             <groupId>javax.servlet.jsp</groupId>
             <groupId>javax.servlet.jsp</groupId>
             <artifactId>jsp-api</artifactId>
             <artifactId>jsp-api</artifactId>
-            <version>2.2</version>
+            <version>2.2.1-b03</version>
             <scope>provided</scope>
             <scope>provided</scope>
         </dependency>
         </dependency>
         <!-- / container dependencies -->
         <!-- / container dependencies -->
@@ -687,7 +680,7 @@
         <dependency>
         <dependency>
             <groupId>org.apache.httpcomponents</groupId>
             <groupId>org.apache.httpcomponents</groupId>
             <artifactId>httpclient</artifactId>
             <artifactId>httpclient</artifactId>
-            <version>4.5.4</version>
+            <version>4.5.5</version>
         </dependency>
         </dependency>
         <dependency>
         <dependency>
             <groupId>org.graylog2</groupId>
             <groupId>org.graylog2</groupId>
@@ -707,7 +700,7 @@
         <dependency>
         <dependency>
             <groupId>org.jasig.cas.client</groupId>
             <groupId>org.jasig.cas.client</groupId>
             <artifactId>cas-client-core</artifactId>
             <artifactId>cas-client-core</artifactId>
-            <version>3.4.1</version>
+            <version>3.5.0</version>
         </dependency>
         </dependency>
         <dependency>
         <dependency>
             <groupId>net.glxn</groupId>
             <groupId>net.glxn</groupId>
@@ -755,9 +748,9 @@
             <version>2.8.2</version>
             <version>2.8.2</version>
         </dependency>
         </dependency>
         <dependency>
         <dependency>
-            <groupId>eu.bitwalker</groupId>
-            <artifactId>UserAgentUtils</artifactId>
-            <version>1.20</version>
+            <groupId>com.blueconic</groupId>
+            <artifactId>browscap-java</artifactId>
+            <version>1.2.1</version>
         </dependency>
         </dependency>
         <dependency>
         <dependency>
             <groupId>org.jetbrains.xodus</groupId>
             <groupId>org.jetbrains.xodus</groupId>
@@ -784,6 +777,11 @@
             <artifactId>zxcvbn</artifactId>
             <artifactId>zxcvbn</artifactId>
             <version>1.2.3</version>
             <version>1.2.3</version>
         </dependency>
         </dependency>
+        <dependency>
+            <groupId>com.github.ziplet</groupId>
+            <artifactId>ziplet</artifactId>
+            <version>2.3.0</version>
+        </dependency>
 
 
 
 
 
 

+ 7 - 1
server/src/build/checkstyle-import.xml

@@ -70,7 +70,6 @@
     <allow pkg="javax.annotation"/>
     <allow pkg="javax.annotation"/>
     <allow pkg="java.awt"/>
     <allow pkg="java.awt"/>
     <allow pkg="javax.security"/>
     <allow pkg="javax.security"/>
-    <allow pkg="eu.bitwalker.useragentutils"/>
     <allow pkg="javax.servlet"/>
     <allow pkg="javax.servlet"/>
     <allow pkg="javax.net"/>
     <allow pkg="javax.net"/>
     <allow pkg="javax.crypto"/>
     <allow pkg="javax.crypto"/>
@@ -133,5 +132,12 @@
         <allow pkg="org.apache.http"/>
         <allow pkg="org.apache.http"/>
     </subpackage>
     </subpackage>
 
 
+    <subpackage name="http.filter">
+        <allow pkg="com.github.ziplet.filter.compression"/>
+    </subpackage>
+
+    <subpackage name="svc.sessiontrack">
+        <allow pkg="com.blueconic.browscap"/>
+    </subpackage>
 
 
 </import-control>
 </import-control>

+ 1 - 0
server/src/main/java/password/pwm/AppProperty.java

@@ -65,6 +65,7 @@ public enum AppProperty {
     CONFIG_NEWUSER_PASSWORD_POLICY_CACHE_MS         ("config.newuser.passwordPolicyCacheMS"),
     CONFIG_NEWUSER_PASSWORD_POLICY_CACHE_MS         ("config.newuser.passwordPolicyCacheMS"),
     CONFIG_THEME                                    ("config.theme"),
     CONFIG_THEME                                    ("config.theme"),
     CONFIG_JBCRYPT_PWLIB_ENABLE                     ("config.enableJbCryptPwLibrary"),
     CONFIG_JBCRYPT_PWLIB_ENABLE                     ("config.enableJbCryptPwLibrary"),
+    CONFIG_EDITOR_BLOCK_OLD_IE                      ("configEditor.blockOldIE"),
     CONFIG_EDITOR_QUERY_FILTER_TEST_LIMIT           ("configEditor.queryFilter.testLimit"),
     CONFIG_EDITOR_QUERY_FILTER_TEST_LIMIT           ("configEditor.queryFilter.testLimit"),
     CONFIG_EDITOR_IDLE_TIMEOUT                      ("configEditor.idleTimeoutSeconds"),
     CONFIG_EDITOR_IDLE_TIMEOUT                      ("configEditor.idleTimeoutSeconds"),
     CONFIG_GUIDE_IDLE_TIMEOUT                       ("configGuide.idleTimeoutSeconds"),
     CONFIG_GUIDE_IDLE_TIMEOUT                       ("configGuide.idleTimeoutSeconds"),

+ 2 - 2
server/src/main/java/password/pwm/bean/TelemetryPublishBean.java

@@ -22,9 +22,9 @@
 
 
 package password.pwm.bean;
 package password.pwm.bean;
 
 
-import com.novell.ldapchai.provider.DirectoryVendor;
 import lombok.Builder;
 import lombok.Builder;
 import lombok.Getter;
 import lombok.Getter;
+import password.pwm.ldap.PwmLdapVendor;
 
 
 import java.io.Serializable;
 import java.io.Serializable;
 import java.time.Instant;
 import java.time.Instant;
@@ -39,7 +39,7 @@ public class TelemetryPublishBean implements Serializable {
     private final String instanceHash;
     private final String instanceHash;
     private final String siteDescription;
     private final String siteDescription;
     private final Instant installTime;
     private final Instant installTime;
-    private final List<DirectoryVendor> ldapVendor;
+    private final List<PwmLdapVendor> ldapVendor;
     private final Map<String,String> statistics;
     private final Map<String,String> statistics;
     private final List<String> configuredSettings;
     private final List<String> configuredSettings;
     private final String versionBuild;
     private final String versionBuild;

+ 1 - 1
server/src/main/java/password/pwm/http/PwmResponse.java

@@ -235,7 +235,7 @@ public class PwmResponse extends PwmHttpResponseWrapper {
         final HttpServletResponse resp = pwmRequest.getPwmResponse().getHttpServletResponse();
         final HttpServletResponse resp = pwmRequest.getPwmResponse().getHttpServletResponse();
         resp.setStatus(redirectType.getCode()); // http "other" redirect
         resp.setStatus(redirectType.getCode()); // http "other" redirect
         resp.setHeader(HttpHeader.Location.getHttpName(), url);
         resp.setHeader(HttpHeader.Location.getHttpName(), url);
-        LOGGER.trace("sending " + redirectType.getCode() + " redirect to " + url);
+        LOGGER.trace(pwmRequest, "sending " + redirectType.getCode() + " redirect to " + url);
     }
     }
 
 
     private void preCommitActions() {
     private void preCommitActions() {

+ 9 - 43
server/src/main/java/password/pwm/http/filter/ConfigAccessFilter.java

@@ -22,8 +22,6 @@
 
 
 package password.pwm.http.filter;
 package password.pwm.http.filter;
 
 
-import eu.bitwalker.useragentutils.Browser;
-import eu.bitwalker.useragentutils.UserAgent;
 import password.pwm.AppProperty;
 import password.pwm.AppProperty;
 import password.pwm.Permission;
 import password.pwm.Permission;
 import password.pwm.PwmApplication;
 import password.pwm.PwmApplication;
@@ -39,7 +37,6 @@ import password.pwm.error.PwmError;
 import password.pwm.error.PwmException;
 import password.pwm.error.PwmException;
 import password.pwm.error.PwmUnrecoverableException;
 import password.pwm.error.PwmUnrecoverableException;
 import password.pwm.http.ContextManager;
 import password.pwm.http.ContextManager;
-import password.pwm.http.HttpHeader;
 import password.pwm.http.JspUrl;
 import password.pwm.http.JspUrl;
 import password.pwm.http.ProcessStatus;
 import password.pwm.http.ProcessStatus;
 import password.pwm.http.PwmRequest;
 import password.pwm.http.PwmRequest;
@@ -48,6 +45,7 @@ import password.pwm.http.PwmSession;
 import password.pwm.http.PwmURL;
 import password.pwm.http.PwmURL;
 import password.pwm.http.bean.ConfigManagerBean;
 import password.pwm.http.bean.ConfigManagerBean;
 import password.pwm.svc.intruder.RecordType;
 import password.pwm.svc.intruder.RecordType;
+import password.pwm.svc.sessiontrack.UserAgentUtils;
 import password.pwm.util.java.JavaHelper;
 import password.pwm.util.java.JavaHelper;
 import password.pwm.util.java.JsonUtil;
 import password.pwm.util.java.JsonUtil;
 import password.pwm.util.java.TimeDuration;
 import password.pwm.util.java.TimeDuration;
@@ -76,11 +74,14 @@ public class ConfigAccessFilter extends AbstractPwmFilter {
             return;
             return;
         }
         }
 
 
-        try {
-            checkUserAgent(pwmRequest);
-        } catch (PwmException e) {
-            pwmRequest.respondWithError(e.getErrorInformation());
-            return;
+        final boolean blockOldIE = Boolean.parseBoolean( pwmRequest.getPwmApplication().getConfig().readAppProperty( AppProperty.CONFIG_EDITOR_BLOCK_OLD_IE ) );
+        if (blockOldIE) {
+            try {
+                UserAgentUtils.checkIfPreIE11( pwmRequest );
+            } catch ( PwmException e ) {
+                pwmRequest.respondWithError( e.getErrorInformation() );
+                return;
+            }
         }
         }
 
 
         final ConfigManagerBean configManagerBean = pwmRequest.getPwmApplication().getSessionStateService().getBean(pwmRequest, ConfigManagerBean.class);
         final ConfigManagerBean configManagerBean = pwmRequest.getPwmApplication().getSessionStateService().getBean(pwmRequest, ConfigManagerBean.class);
@@ -359,41 +360,6 @@ public class ConfigAccessFilter extends AbstractPwmFilter {
         return Integer.parseInt(pwmRequest.getConfig().readAppProperty(AppProperty.CONFIG_MAX_PERSISTENT_LOGIN_SECONDS));
         return Integer.parseInt(pwmRequest.getConfig().readAppProperty(AppProperty.CONFIG_MAX_PERSISTENT_LOGIN_SECONDS));
     }
     }
 
 
-    private void checkUserAgent(final PwmRequest pwmRequest) throws PwmUnrecoverableException {
-        final String userAgentString = pwmRequest.readHeaderValueAsString(HttpHeader.UserAgent);
-        if (userAgentString == null || userAgentString.isEmpty()) {
-            return;
-        }
-
-        boolean badBrowser = false;
-        try {
-            final UserAgent userAgent = new UserAgent(userAgentString);
-            final Browser browser = userAgent.getBrowser();
-            switch (browser) {
-                case IE5:
-                case IE5_5:
-                case IE6:
-                case IE7:
-                case IE8:
-                case IE9:
-                case IE10:
-                    badBrowser = true;
-                    break;
-
-                default:
-                    //other browsers okay
-                    break;
-
-            }
-        } catch (Exception e) {
-            LOGGER.error(pwmRequest, "error during browser user-agent detection: " + e.getMessage());
-        }
-
-        if (badBrowser) {
-            final String errorMsg = "Internet Explorer version is not supported for this function.  Please use Internet Explorer 11 or higher or another web browser.";
-            throw new PwmUnrecoverableException(new ErrorInformation(PwmError.ERROR_UNAUTHORIZED, errorMsg));
-        }
-    }
 
 
     private static ProcessStatus denyAndError(final PwmRequest pwmRequest, final ErrorInformation errorInformation)
     private static ProcessStatus denyAndError(final PwmRequest pwmRequest, final ErrorInformation errorInformation)
             throws ServletException, PwmUnrecoverableException, IOException
             throws ServletException, PwmUnrecoverableException, IOException

+ 21 - 148
server/src/main/java/password/pwm/http/filter/GZIPFilter.java

@@ -22,11 +22,11 @@
 
 
 package password.pwm.http.filter;
 package password.pwm.http.filter;
 
 
+import com.github.ziplet.filter.compression.CompressingFilter;
 import password.pwm.AppProperty;
 import password.pwm.AppProperty;
 import password.pwm.PwmApplication;
 import password.pwm.PwmApplication;
 import password.pwm.error.PwmUnrecoverableException;
 import password.pwm.error.PwmUnrecoverableException;
 import password.pwm.http.ContextManager;
 import password.pwm.http.ContextManager;
-import password.pwm.http.HttpHeader;
 import password.pwm.http.PwmURL;
 import password.pwm.http.PwmURL;
 import password.pwm.util.logging.PwmLogger;
 import password.pwm.util.logging.PwmLogger;
 
 
@@ -34,17 +34,10 @@ import javax.servlet.Filter;
 import javax.servlet.FilterChain;
 import javax.servlet.FilterChain;
 import javax.servlet.FilterConfig;
 import javax.servlet.FilterConfig;
 import javax.servlet.ServletException;
 import javax.servlet.ServletException;
-import javax.servlet.ServletOutputStream;
 import javax.servlet.ServletRequest;
 import javax.servlet.ServletRequest;
 import javax.servlet.ServletResponse;
 import javax.servlet.ServletResponse;
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-import javax.servlet.http.HttpServletResponseWrapper;
 import java.io.IOException;
 import java.io.IOException;
-import java.io.OutputStreamWriter;
-import java.io.PrintWriter;
-import java.util.concurrent.atomic.AtomicBoolean;
-import java.util.zip.GZIPOutputStream;
 
 
 /**
 /**
  * GZip Filter Wrapper.  This filter must be invoked _before_ a PwmRequest object is instantiated, else
  * GZip Filter Wrapper.  This filter must be invoked _before_ a PwmRequest object is instantiated, else
@@ -53,171 +46,51 @@ import java.util.zip.GZIPOutputStream;
 public class GZIPFilter implements Filter {
 public class GZIPFilter implements Filter {
     private static final PwmLogger LOGGER = PwmLogger.forClass(GZIPFilter.class);
     private static final PwmLogger LOGGER = PwmLogger.forClass(GZIPFilter.class);
 
 
+    private final CompressingFilter compressingFilter = new CompressingFilter();
+    private boolean enabled = false;
+
     public void init(final FilterConfig filterConfig)
     public void init(final FilterConfig filterConfig)
             throws ServletException
             throws ServletException
     {
     {
+        final PwmApplication pwmApplication;
+        try {
+            pwmApplication = ContextManager.getPwmApplication( filterConfig.getServletContext() );
+            enabled = Boolean.parseBoolean(pwmApplication.getConfig().readAppProperty(AppProperty.HTTP_ENABLE_GZIP));
+        } catch (PwmUnrecoverableException e) {
+            LOGGER.warn( "unable to load application configuration, defaulting to disabled" );
+        }
+
+        compressingFilter.init( filterConfig );
     }
     }
 
 
     public void destroy()
     public void destroy()
     {
     {
+        compressingFilter.destroy();
     }
     }
 
 
     @Override
     @Override
     public void doFilter(final ServletRequest servletRequest, final ServletResponse servletResponse, final FilterChain filterChain)
     public void doFilter(final ServletRequest servletRequest, final ServletResponse servletResponse, final FilterChain filterChain)
             throws IOException, ServletException
             throws IOException, ServletException
     {
     {
-        final String acceptEncoding = ((HttpServletRequest)servletRequest).getHeader(HttpHeader.Accept_Encoding.getHttpName());
-        if (acceptEncoding != null && acceptEncoding.contains("gzip") && isEnabled(servletRequest)) {
-            final GZIPHttpServletResponseWrapper gzipResponse = new GZIPHttpServletResponseWrapper((HttpServletResponse)servletResponse);
-            gzipResponse.addHeader(HttpHeader.Content_Encoding.getHttpName(), "gzip");
-            filterChain.doFilter(servletRequest, gzipResponse);
-            gzipResponse.finish();
-
+        if ( enabled && interestInRequest( servletRequest )) {
+            compressingFilter.doFilter( servletRequest, servletResponse, filterChain );
         } else {
         } else {
             filterChain.doFilter(servletRequest, servletResponse);
             filterChain.doFilter(servletRequest, servletResponse);
         }
         }
     }
     }
 
 
-    private boolean isEnabled(final ServletRequest servletRequest) {
-
+    private boolean interestInRequest( final ServletRequest servletRequest) {
         try {
         try {
             final PwmURL pwmURL = new PwmURL((HttpServletRequest) servletRequest);
             final PwmURL pwmURL = new PwmURL((HttpServletRequest) servletRequest);
-            if (pwmURL.isResourceURL() || pwmURL.isRestService()) {
+
+            // resource servlet does its own gzip compression with fancy server-side caching
+            if (pwmURL.isResourceURL()) {
                 return false;
                 return false;
             }
             }
         } catch (Exception e) {
         } catch (Exception e) {
             LOGGER.error("unable to parse request url, defaulting to non-gzip: " + e.getMessage());
             LOGGER.error("unable to parse request url, defaulting to non-gzip: " + e.getMessage());
         }
         }
 
 
-        final PwmApplication pwmApplication;
-        try {
-            pwmApplication = ContextManager.getPwmApplication((HttpServletRequest) servletRequest);
-            return Boolean.parseBoolean(pwmApplication.getConfig().readAppProperty(AppProperty.HTTP_ENABLE_GZIP));
-        } catch (PwmUnrecoverableException e) {
-            //LOGGER.trace("unable to read http-gzip app-property, defaulting to non-gzip: " + e.getMessage());
-        }
-        return false;
-    }
-
-
-    public static class GZIPHttpServletResponseWrapper extends HttpServletResponseWrapper {
-        private ServletResponseGZIPOutputStream gzipStream;
-        private ServletOutputStream outputStream;
-        private PrintWriter printWriter;
-
-        public GZIPHttpServletResponseWrapper(final HttpServletResponse response) throws IOException {
-            super(response);
-        }
-
-        public void finish() throws IOException {
-            if (printWriter != null) {
-                printWriter.close();
-            }
-            if (outputStream != null) {
-                outputStream.close();
-            }
-            if (gzipStream != null) {
-                gzipStream.close();
-            }
-        }
-
-        @Override
-        public void flushBuffer() throws IOException {
-            if (printWriter != null) {
-                printWriter.flush();
-            }
-            if (outputStream != null) {
-                outputStream.flush();
-            }
-            super.flushBuffer();
-        }
-
-        @Override
-        public ServletOutputStream getOutputStream() throws IOException {
-            if (printWriter != null) {
-                throw new IllegalStateException("getWriter() has previously been invoked, can not call getOutputStream()");
-            }
-            if (outputStream == null) {
-                initGzip();
-                outputStream = gzipStream;
-            }
-            return outputStream;
-        }
-
-        @Override
-        public PrintWriter getWriter() throws IOException {
-            if (outputStream != null) {
-                throw new IllegalStateException("getOutputStream() has previously been invoked, can not call getWriter()");
-            }
-            if (printWriter == null) {
-                initGzip();
-                printWriter = new PrintWriter(new OutputStreamWriter(gzipStream, getResponse().getCharacterEncoding()));
-            }
-            return printWriter;
-        }
-
-        @Override
-        public void setContentLength(final int len) {
-        }
-
-        private void initGzip() throws IOException {
-            gzipStream = new ServletResponseGZIPOutputStream(getResponse().getOutputStream());
-        }
-    }
-
-    public static class ServletResponseGZIPOutputStream extends ServletOutputStream {
-        private final AtomicBoolean open = new AtomicBoolean(true);
-        private GZIPOutputStream gzipStream;
-
-        public ServletResponseGZIPOutputStream(final ServletOutputStream output) throws IOException {
-            gzipStream = new GZIPOutputStream(output);
-        }
-
-        @Override
-        public void close() throws IOException {
-            if (open.compareAndSet(true, false)) {
-                gzipStream.close();
-            }
-        }
-
-        @Override
-        public void flush() throws IOException {
-            gzipStream.flush();
-        }
-
-        @Override
-        public void write(final byte[] b) throws IOException {
-            write(b, 0, b.length);
-        }
-
-        @Override
-        public void write(final byte[] b, final int off, final int len) throws IOException {
-            if (!open.get()) {
-                throw new IOException("Stream closed!");
-            }
-            gzipStream.write(b, off, len);
-        }
-
-        @Override
-        public void write(final int b) throws IOException {
-            if (!open.get()) {
-                throw new IOException("Stream closed!");
-            }
-            gzipStream.write(b);
-        }
-
-        /*
-        // servlet 3.1 method
-        public void setWriteListener(WriteListener writeListener)
-        {
-            servletOutputStream.setWriteListener(writeListener);
-        }
-
-        // servlet 3.1 method
-        public boolean isReady()
-        {
-            return servletOutputStream.isReady();
-        }
-        */
+        return true;
     }
     }
 }
 }

+ 62 - 49
server/src/main/java/password/pwm/http/filter/RequestInitializationFilter.java

@@ -155,7 +155,7 @@ public class RequestInitializationFilter implements Filter {
         } catch (Throwable e) {
         } catch (Throwable e) {
             LOGGER.error("can't load application: " + e.getMessage(),e);
             LOGGER.error("can't load application: " + e.getMessage(),e);
             if (!(new PwmURL(req).isResourceURL())) {
             if (!(new PwmURL(req).isResourceURL())) {
-                respondWithUnavalailbleError(req, resp);
+                respondWithUnavailableError(req, resp);
                 return;
                 return;
             }
             }
             return;
             return;
@@ -191,7 +191,7 @@ public class RequestInitializationFilter implements Filter {
                 LOGGER.error(logMsg,e);
                 LOGGER.error(logMsg,e);
             }
             }
             if (!(new PwmURL(req).isResourceURL())) {
             if (!(new PwmURL(req).isResourceURL())) {
-                respondWithUnavalailbleError(req, resp);
+                respondWithUnavailableError(req, resp);
                 return;
                 return;
             }
             }
             return;
             return;
@@ -200,7 +200,7 @@ public class RequestInitializationFilter implements Filter {
         filterChain.doFilter(req, resp);
         filterChain.doFilter(req, resp);
     }
     }
 
 
-    private void respondWithUnavalailbleError(final HttpServletRequest req, final HttpServletResponse resp)
+    private void respondWithUnavailableError( final HttpServletRequest req, final HttpServletResponse resp)
             throws ServletException, IOException
             throws ServletException, IOException
     {
     {
         ErrorInformation errorInformation = new ErrorInformation(PwmError.ERROR_APP_UNAVAILABLE);
         ErrorInformation errorInformation = new ErrorInformation(PwmError.ERROR_APP_UNAVAILABLE);
@@ -307,84 +307,86 @@ public class RequestInitializationFilter implements Filter {
             return;
             return;
         }
         }
 
 
+        final boolean includeXSessionID = Boolean.parseBoolean(config.readAppProperty(AppProperty.HTTP_HEADER_SEND_XSESSIONID));
+        if (includeXSessionID && pwmSession != null) {
+            resp.setHeader(HttpHeader.XSessionID, pwmSession.getSessionStateBean().getSessionID());
+        }
+
+        final boolean includeContentLanguage = Boolean.parseBoolean(config.readAppProperty(AppProperty.HTTP_HEADER_SEND_CONTENT_LANGUAGE));
+        if (includeContentLanguage) {
+            resp.setHeader(HttpHeader.Content_Language, pwmRequest.getLocale().toLanguageTag());
+        }
+
+        addStaticResponseHeaders( pwmApplication, resp.getHttpServletResponse() );
+
+
+        if (pwmSession != null) {
+            final String contentPolicy;
+            if (pwmRequest.getURL().isConfigGuideURL() || pwmRequest.getURL().isConfigManagerURL()) {
+                contentPolicy = config.readAppProperty(AppProperty.SECURITY_HTTP_CONFIG_CSP_HEADER);
+            } else {
+                contentPolicy = config.readSettingAsString(PwmSetting.SECURITY_CSP_HEADER);
+            }
+
+            if (contentPolicy != null && !contentPolicy.isEmpty()) {
+                final String nonce = pwmRequest.getCspNonce();
+                final String expandedPolicy = contentPolicy.replace("%NONCE%", nonce);
+                resp.setHeader(HttpHeader.ContentSecurityPolicy, expandedPolicy);
+            }
+        }
+    }
+
+    public static void addStaticResponseHeaders(final PwmApplication pwmApplication, final HttpServletResponse resp) throws PwmUnrecoverableException
+    {
+        final Configuration config = pwmApplication.getConfig();
+
         final String serverHeader = config.readAppProperty(AppProperty.HTTP_HEADER_SERVER);
         final String serverHeader = config.readAppProperty(AppProperty.HTTP_HEADER_SERVER);
         final boolean includeXInstance = Boolean.parseBoolean(config.readAppProperty(AppProperty.HTTP_HEADER_SEND_XINSTANCE));
         final boolean includeXInstance = Boolean.parseBoolean(config.readAppProperty(AppProperty.HTTP_HEADER_SEND_XINSTANCE));
-        final boolean includeXSessionID = Boolean.parseBoolean(config.readAppProperty(AppProperty.HTTP_HEADER_SEND_XSESSIONID));
         final boolean includeXVersion = Boolean.parseBoolean(config.readAppProperty(AppProperty.HTTP_HEADER_SEND_XVERSION));
         final boolean includeXVersion = Boolean.parseBoolean(config.readAppProperty(AppProperty.HTTP_HEADER_SEND_XVERSION));
         final boolean includeXContentTypeOptions = Boolean.parseBoolean(config.readAppProperty(AppProperty.HTTP_HEADER_SEND_XCONTENTTYPEOPTIONS));
         final boolean includeXContentTypeOptions = Boolean.parseBoolean(config.readAppProperty(AppProperty.HTTP_HEADER_SEND_XCONTENTTYPEOPTIONS));
         final boolean includeXXSSProtection = Boolean.parseBoolean(config.readAppProperty(AppProperty.HTTP_HEADER_SEND_XXSSPROTECTION));
         final boolean includeXXSSProtection = Boolean.parseBoolean(config.readAppProperty(AppProperty.HTTP_HEADER_SEND_XXSSPROTECTION));
+        final boolean includeXFrameDeny = config.readSettingAsBoolean(PwmSetting.SECURITY_PREVENT_FRAMING);
+        final boolean includeXAmb = Boolean.parseBoolean(config.readAppProperty(AppProperty.HTTP_HEADER_SEND_XAMB));
 
 
-        final boolean sendNoise = Boolean.parseBoolean(config.readAppProperty(AppProperty.HTTP_HEADER_SEND_XNOISE));
-
-        if (sendNoise) {
-            final int noiseLength = Integer.parseInt(config.readAppProperty(AppProperty.HTTP_HEADER_NOISE_LENGTH));
-            resp.setHeader(
-                    HttpHeader.XNoise,
-                    PwmRandom.getInstance().alphaNumericString(PwmRandom.getInstance().nextInt(noiseLength)+11)
-            );
+        {
+            final String noiseHeader = makeNoiseHeader( config );
+            if (noiseHeader != null) {
+                resp.setHeader( HttpHeader.XNoise.getHttpName(), noiseHeader );
+            }
         }
         }
 
 
         if (includeXVersion) {
         if (includeXVersion) {
-            resp.setHeader(HttpHeader.XVersion, PwmConstants.SERVLET_VERSION);
+            resp.setHeader(HttpHeader.XVersion.getHttpName(), PwmConstants.SERVLET_VERSION);
         }
         }
 
 
         if (includeXContentTypeOptions) {
         if (includeXContentTypeOptions) {
-            resp.setHeader(HttpHeader.XContentTypeOptions, "nosniff");
+            resp.setHeader(HttpHeader.XContentTypeOptions.getHttpName(), "nosniff");
         }
         }
 
 
         if (includeXXSSProtection) {
         if (includeXXSSProtection) {
-            resp.setHeader(HttpHeader.XXSSProtection, "1");
+            resp.setHeader(HttpHeader.XXSSProtection.getHttpName(), "1");
         }
         }
 
 
         if (includeXInstance) {
         if (includeXInstance) {
-            resp.setHeader(HttpHeader.XInstance, String.valueOf(pwmApplication.getInstanceID()));
-        }
-
-        if (includeXSessionID && pwmSession != null) {
-            resp.setHeader(HttpHeader.XSessionID, pwmSession.getSessionStateBean().getSessionID());
+            resp.setHeader(HttpHeader.XInstance.getHttpName(), String.valueOf(pwmApplication.getInstanceID()));
         }
         }
 
 
         if (serverHeader != null && !serverHeader.isEmpty()) {
         if (serverHeader != null && !serverHeader.isEmpty()) {
             final String value = MacroMachine.forNonUserSpecific(pwmApplication, null).expandMacros(serverHeader);
             final String value = MacroMachine.forNonUserSpecific(pwmApplication, null).expandMacros(serverHeader);
-            resp.setHeader(HttpHeader.Server, value);
+            resp.setHeader(HttpHeader.Server.getHttpName(), value);
         }
         }
 
 
-        // ----- non-resource urls only for the following operations -----
-
-        final boolean includeXFrameDeny = config.readSettingAsBoolean(PwmSetting.SECURITY_PREVENT_FRAMING);
-        final boolean includeXAmb = Boolean.parseBoolean(config.readAppProperty(AppProperty.HTTP_HEADER_SEND_XAMB));
-        final boolean includeContentLanguage = Boolean.parseBoolean(config.readAppProperty(AppProperty.HTTP_HEADER_SEND_CONTENT_LANGUAGE));
-
         if (includeXFrameDeny) {
         if (includeXFrameDeny) {
-            resp.setHeader(HttpHeader.XFrameOptions, "DENY");
+            resp.setHeader(HttpHeader.XFrameOptions.getHttpName(), "DENY");
         }
         }
 
 
         if (includeXAmb) {
         if (includeXAmb) {
-            resp.setHeader(HttpHeader.XAmb, PwmConstants.X_AMB_HEADER.get(
+            resp.setHeader(HttpHeader.XAmb.getHttpName(), PwmConstants.X_AMB_HEADER.get(
                     PwmRandom.getInstance().nextInt(PwmConstants.X_AMB_HEADER.size())
                     PwmRandom.getInstance().nextInt(PwmConstants.X_AMB_HEADER.size())
             ));
             ));
         }
         }
 
 
-        if (includeContentLanguage) {
-            resp.setHeader(HttpHeader.Content_Language, pwmRequest.getLocale().toLanguageTag());
-        }
-
-        resp.setHeader(HttpHeader.Cache_Control, "no-cache, no-store, must-revalidate, proxy-revalidate");
-
-        if (pwmSession != null) {
-            final String contentPolicy;
-            if (pwmRequest.getURL().isConfigGuideURL() || pwmRequest.getURL().isConfigManagerURL()) {
-                contentPolicy = config.readAppProperty(AppProperty.SECURITY_HTTP_CONFIG_CSP_HEADER);
-            } else {
-                contentPolicy = config.readSettingAsString(PwmSetting.SECURITY_CSP_HEADER);
-            }
-
-            if (contentPolicy != null && !contentPolicy.isEmpty()) {
-                final String nonce = pwmRequest.getCspNonce();
-                final String expandedPolicy = contentPolicy.replace("%NONCE%", nonce);
-                resp.setHeader(HttpHeader.ContentSecurityPolicy, expandedPolicy);
-            }
-        }
+        resp.setHeader(HttpHeader.Cache_Control.getHttpName(), "no-cache, no-store, must-revalidate, proxy-revalidate");
     }
     }
 
 
 
 
@@ -685,4 +687,15 @@ public class RequestInitializationFilter implements Filter {
         return StringUtil.mapToString(values);
         return StringUtil.mapToString(values);
     }
     }
 
 
+    private static String makeNoiseHeader(final Configuration configuration) {
+        final boolean sendNoise = Boolean.parseBoolean(configuration.readAppProperty(AppProperty.HTTP_HEADER_SEND_XNOISE));
+
+        if (sendNoise) {
+            final int noiseLength = Integer.parseInt(configuration.readAppProperty(AppProperty.HTTP_HEADER_NOISE_LENGTH));
+            return PwmRandom.getInstance().alphaNumericString(PwmRandom.getInstance().nextInt(noiseLength)+11);
+        }
+
+        return null;
+    }
+
 }
 }

+ 53 - 0
server/src/main/java/password/pwm/ldap/PwmLdapVendor.java

@@ -0,0 +1,53 @@
+package password.pwm.ldap;
+
+import com.novell.ldapchai.provider.DirectoryVendor;
+
+public enum PwmLdapVendor {
+    ACTIVE_DIRECTORY(DirectoryVendor.ACTIVE_DIRECTORY, "MICROSOFT_ACTIVE_DIRECTORY"),
+    EDIRECTORY(DirectoryVendor.EDIRECTORY, "NOVELL_EDIRECTORY"),
+    OPEN_LDAP(DirectoryVendor.OPEN_LDAP),
+    DIRECTORY_SERVER_389(DirectoryVendor.DIRECTORY_SERVER_389),
+    ORACLE_DS(DirectoryVendor.ORACLE_DS),
+    GENERIC(DirectoryVendor.GENERIC),
+
+    ;
+
+    private final DirectoryVendor chaiVendor;
+    private final String[] otherNames;
+
+    PwmLdapVendor( final DirectoryVendor directoryVendor, final String... otherNames ) {
+        this.chaiVendor = directoryVendor;
+        this.otherNames = otherNames;
+    }
+
+    public static PwmLdapVendor fromString(final String input) {
+        if (input == null) {
+            return null;
+        }
+
+        for (PwmLdapVendor vendor : PwmLdapVendor.values()) {
+            if ( vendor.name().equals( input ) ) {
+                return vendor;
+            }
+
+            if (vendor.otherNames != null) {
+                for (final String otherName : vendor.otherNames) {
+                    if (otherName.equals( input )) {
+                        return vendor;
+                    }
+                }
+            }
+        }
+
+        return null;
+    }
+
+    public static PwmLdapVendor fromChaiVendor(final DirectoryVendor directoryVendor) {
+        for (PwmLdapVendor vendor : PwmLdapVendor.values()) {
+            if (vendor.chaiVendor == directoryVendor) {
+                return vendor;
+            }
+        }
+        return null;
+    }
+}

+ 4 - 2
server/src/main/java/password/pwm/svc/sessiontrack/SessionTrackService.java

@@ -28,12 +28,12 @@ import password.pwm.PwmApplication;
 import password.pwm.bean.LocalSessionStateBean;
 import password.pwm.bean.LocalSessionStateBean;
 import password.pwm.bean.LoginInfoBean;
 import password.pwm.bean.LoginInfoBean;
 import password.pwm.bean.UserIdentity;
 import password.pwm.bean.UserIdentity;
-import password.pwm.error.PwmUnrecoverableException;
-import password.pwm.ldap.UserInfo;
 import password.pwm.bean.pub.SessionStateInfoBean;
 import password.pwm.bean.pub.SessionStateInfoBean;
 import password.pwm.error.PwmException;
 import password.pwm.error.PwmException;
+import password.pwm.error.PwmUnrecoverableException;
 import password.pwm.health.HealthRecord;
 import password.pwm.health.HealthRecord;
 import password.pwm.http.PwmSession;
 import password.pwm.http.PwmSession;
+import password.pwm.ldap.UserInfo;
 import password.pwm.svc.PwmService;
 import password.pwm.svc.PwmService;
 import password.pwm.util.logging.PwmLogger;
 import password.pwm.util.logging.PwmLogger;
 
 
@@ -214,4 +214,6 @@ public class SessionTrackService implements PwmService {
     public List<UserIdentity> getRecentLogins() {
     public List<UserIdentity> getRecentLogins() {
         return Collections.unmodifiableList(new ArrayList<>(recentLoginCache.asMap().keySet()));
         return Collections.unmodifiableList(new ArrayList<>(recentLoginCache.asMap().keySet()));
     }
     }
+
+
 }
 }

+ 65 - 0
server/src/main/java/password/pwm/svc/sessiontrack/UserAgentUtils.java

@@ -0,0 +1,65 @@
+package password.pwm.svc.sessiontrack;
+
+import com.blueconic.browscap.Capabilities;
+import com.blueconic.browscap.ParseException;
+import com.blueconic.browscap.UserAgentParser;
+import com.blueconic.browscap.UserAgentService;
+import password.pwm.error.ErrorInformation;
+import password.pwm.error.PwmError;
+import password.pwm.error.PwmUnrecoverableException;
+import password.pwm.http.HttpHeader;
+import password.pwm.http.PwmRequest;
+import password.pwm.util.java.StringUtil;
+import password.pwm.util.logging.PwmLogger;
+
+import java.io.IOException;
+
+public class UserAgentUtils  {
+    private static final PwmLogger LOGGER = PwmLogger.forClass( UserAgentUtils.class );
+
+    private static UserAgentParser cachedParser;
+
+    private static UserAgentParser getUserAgentParser() throws PwmUnrecoverableException
+    {
+        if (cachedParser == null) {
+            try {
+                cachedParser = new UserAgentService().loadParser();
+            }  catch ( IOException | ParseException e ) {
+                final String msg = "error loading user-agent parser: " + e.getMessage();
+                LOGGER.error( msg, e );
+                throw new PwmUnrecoverableException( PwmError.ERROR_UNKNOWN, msg );
+            }
+        }
+        return cachedParser;
+    }
+
+    public static void checkIfPreIE11( final PwmRequest pwmRequest) throws PwmUnrecoverableException  {
+        final String userAgentString = pwmRequest.readHeaderValueAsString( HttpHeader.UserAgent);
+        if ( StringUtil.isEmpty( userAgentString )) {
+            return ;
+        }
+
+        boolean badBrowser = false;
+
+        final UserAgentParser userAgentParser = getUserAgentParser();
+        final Capabilities capabilities = userAgentParser.parse( userAgentString );
+        final String browser = capabilities.getBrowser();
+        final String browserMajorVersion = capabilities.getBrowserMajorVersion();
+
+        if ("IE".equalsIgnoreCase( browser )) {
+            try {
+                final int majorVersionInt = Integer.parseInt( browserMajorVersion );
+                if (majorVersionInt <= 10) {
+                    badBrowser = true;
+                }
+            }  catch ( NumberFormatException e ) {
+                LOGGER.error( "error parsing user-agent major version" + e.getMessage(), e );
+            }
+        }
+
+        if (badBrowser) {
+            final String errorMsg = "Internet Explorer version is not supported for this function.  Please use Internet Explorer 11 or higher or another web browser.";
+            throw new PwmUnrecoverableException(new ErrorInformation( PwmError.ERROR_UNAUTHORIZED, errorMsg));
+        }
+    }
+}

+ 5 - 2
server/src/main/java/password/pwm/svc/telemetry/TelemetryService.java

@@ -40,6 +40,7 @@ import password.pwm.error.PwmError;
 import password.pwm.error.PwmException;
 import password.pwm.error.PwmException;
 import password.pwm.error.PwmUnrecoverableException;
 import password.pwm.error.PwmUnrecoverableException;
 import password.pwm.health.HealthRecord;
 import password.pwm.health.HealthRecord;
+import password.pwm.ldap.PwmLdapVendor;
 import password.pwm.svc.PwmService;
 import password.pwm.svc.PwmService;
 import password.pwm.svc.stats.Statistic;
 import password.pwm.svc.stats.Statistic;
 import password.pwm.svc.stats.StatisticsBundle;
 import password.pwm.svc.stats.StatisticsBundle;
@@ -258,10 +259,12 @@ public class TelemetryService implements PwmService {
             }
             }
         }
         }
 
 
-        final Set<DirectoryVendor> ldapVendors = new LinkedHashSet<>();
+        final Set<PwmLdapVendor> ldapVendors = new LinkedHashSet<>();
         for (final LdapProfile ldapProfile : config.getLdapProfiles().values()) {
         for (final LdapProfile ldapProfile : config.getLdapProfiles().values()) {
             try {
             try {
-                ldapVendors.add(ldapProfile.getProxyChaiProvider(pwmApplication).getDirectoryVendor());
+                final DirectoryVendor directoryVendor = ldapProfile.getProxyChaiProvider(pwmApplication).getDirectoryVendor();
+                final PwmLdapVendor pwmLdapVendor = PwmLdapVendor.fromChaiVendor(directoryVendor);
+                ldapVendors.add(pwmLdapVendor);
             } catch (Exception e) {
             } catch (Exception e) {
                 LOGGER.trace(SessionLabel.TELEMETRY_SESSION_LABEL, "unable to read ldap vendor type for stats publication: " + e.getMessage());
                 LOGGER.trace(SessionLabel.TELEMETRY_SESSION_LABEL, "unable to read ldap vendor type for stats publication: " + e.getMessage());
             }
             }

+ 11 - 0
server/src/main/java/password/pwm/util/java/JsonUtil.java

@@ -33,6 +33,7 @@ import com.google.gson.JsonSerializationContext;
 import com.google.gson.JsonSerializer;
 import com.google.gson.JsonSerializer;
 import com.google.gson.reflect.TypeToken;
 import com.google.gson.reflect.TypeToken;
 import password.pwm.error.PwmUnrecoverableException;
 import password.pwm.error.PwmUnrecoverableException;
+import password.pwm.ldap.PwmLdapVendor;
 import password.pwm.util.PasswordData;
 import password.pwm.util.PasswordData;
 import password.pwm.util.logging.PwmLogger;
 import password.pwm.util.logging.PwmLogger;
 
 
@@ -259,6 +260,16 @@ public class JsonUtil {
 
 
     }
     }
 
 
+    private static class PwmLdapVendorTypeAdaptor implements JsonSerializer<PwmLdapVendor>, JsonDeserializer<PwmLdapVendor> {
+        public PwmLdapVendor deserialize(final JsonElement json, final Type typeOfT, final JsonDeserializationContext context) throws JsonParseException {
+                return PwmLdapVendor.fromString( json.getAsString() );
+        }
+
+        public JsonElement serialize(final PwmLdapVendor src, final Type typeOfSrc, final JsonSerializationContext context) {
+                return new JsonPrimitive(src.name());
+        }
+    }
+
     private static GsonBuilder registerTypeAdapters(final GsonBuilder gsonBuilder) {
     private static GsonBuilder registerTypeAdapters(final GsonBuilder gsonBuilder) {
         gsonBuilder.registerTypeAdapter(Date.class, new DateTypeAdapter());
         gsonBuilder.registerTypeAdapter(Date.class, new DateTypeAdapter());
         gsonBuilder.registerTypeAdapter(Instant.class, new InstantTypeAdapter());
         gsonBuilder.registerTypeAdapter(Instant.class, new InstantTypeAdapter());

+ 2 - 1
server/src/main/java/password/pwm/ws/server/RestServlet.java

@@ -104,6 +104,8 @@ public abstract class RestServlet extends HttpServlet{
 
 
             final RestRequest restRequest = RestRequest.forRequest(pwmApplication, restAuthentication, sessionLabel, req);
             final RestRequest restRequest = RestRequest.forRequest(pwmApplication, restAuthentication, sessionLabel, req);
 
 
+            RequestInitializationFilter.addStaticResponseHeaders( pwmApplication, resp );
+
             preCheck(restRequest);
             preCheck(restRequest);
 
 
             preCheckRequest(restRequest);
             preCheckRequest(restRequest);
@@ -372,5 +374,4 @@ public abstract class RestServlet extends HttpServlet{
             throw new PwmUnrecoverableException(e.getErrorInformation());
             throw new PwmUnrecoverableException(e.getErrorInformation());
         }
         }
     }
     }
-
 }
 }

+ 1 - 0
server/src/main/resources/password/pwm/AppProperty.properties

@@ -61,6 +61,7 @@ config.fileScanFrequencyMS=5017
 config.newuser.passwordPolicyCacheMS=3600000
 config.newuser.passwordPolicyCacheMS=3600000
 config.theme=pwm
 config.theme=pwm
 config.enableJbCryptPwLibrary=true
 config.enableJbCryptPwLibrary=true
+configEditor.blockOldIE=true
 configEditor.queryFilter.testLimit=5000
 configEditor.queryFilter.testLimit=5000
 configEditor.idleTimeoutSeconds=900
 configEditor.idleTimeoutSeconds=900
 configGuide.idleTimeoutSeconds=3600
 configGuide.idleTimeoutSeconds=3600