Switch all configuration options that use regular expression to require a single...
authormarkt <markt@13f79535-47bb-0310-9956-ffa450edef68>
Thu, 6 Jan 2011 16:05:41 +0000 (16:05 +0000)
committermarkt <markt@13f79535-47bb-0310-9956-ffa450edef68>
Thu, 6 Jan 2011 16:05:41 +0000 (16:05 +0000)
git-svn-id: https://svn.apache.org/repos/asf/tomcat/trunk@1055923 13f79535-47bb-0310-9956-ffa450edef68

15 files changed:
java/org/apache/catalina/filters/RemoteIpFilter.java
java/org/apache/catalina/filters/RequestFilter.java
java/org/apache/catalina/ha/tcp/LocalStrings.properties
java/org/apache/catalina/ha/tcp/LocalStrings_es.properties
java/org/apache/catalina/ha/tcp/ReplicationValve.java
java/org/apache/catalina/valves/RemoteIpValve.java
java/org/apache/catalina/valves/RequestFilterValve.java
java/org/apache/coyote/http11/AbstractHttp11Processor.java
java/org/apache/coyote/http11/Http11AprProcessor.java
java/org/apache/coyote/http11/Http11NioProcessor.java
java/org/apache/coyote/http11/Http11Processor.java
webapps/docs/changelog.xml
webapps/docs/config/cluster-valve.xml
webapps/docs/config/filter.xml
webapps/docs/config/valve.xml

index 97d6aa7..d56e624 100644 (file)
@@ -16,7 +16,6 @@ package org.apache.catalina.filters;
 import java.io.IOException;
 import java.text.DateFormat;
 import java.text.SimpleDateFormat;
-import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collections;
 import java.util.Date;
@@ -28,7 +27,6 @@ import java.util.List;
 import java.util.Locale;
 import java.util.Map;
 import java.util.regex.Pattern;
-import java.util.regex.PatternSyntaxException;
 
 import javax.servlet.Filter;
 import javax.servlet.FilterChain;
@@ -101,8 +99,8 @@ import org.apache.juli.logging.LogFactory;
  * <td>List of internal proxies ip adress. If they appear in the <code>remoteIpHeader</code> value, they will be trusted and will not appear
  * in the <code>proxiesHeader</code> value</td>
  * <td>RemoteIPInternalProxy</td>
- * <td>Comma delimited list of regular expressions (in the syntax supported by the {@link java.util.regex.Pattern} library)</td>
- * <td>10\.\d{1,3}\.\d{1,3}\.\d{1,3}, 192\.168\.\d{1,3}\.\d{1,3}, 169\.254\.\d{1,3}\.\d{1,3}, 127\.\d{1,3}\.\d{1,3}\.\d{1,3} <br/>
+ * <td>Regular expression (in the syntax supported by the {@link java.util.regex.Pattern} library)</td>
+ * <td>10\.\d{1,3}\.\d{1,3}\.\d{1,3}|192\.168\.\d{1,3}\.\d{1,3}|169\.254\.\d{1,3}\.\d{1,3}|127\.\d{1,3}\.\d{1,3}\.\d{1,3} <br/>
  * By default, 10/8, 192.168/16, 169.254/16 and 127/8 are allowed ; 172.16/12 has not been enabled by default because it is complex to
  * describe with regular expressions</td>
  * </tr>
@@ -120,7 +118,7 @@ import org.apache.juli.logging.LogFactory;
  * <td>List of trusted proxies ip adress. If they appear in the <code>remoteIpHeader</code> value, they will be trusted and will appear in
  * the <code>proxiesHeader</code> value</td>
  * <td>RemoteIPTrustedProxy</td>
- * <td>Comma delimited list of regular expressions (in the syntax supported by the {@link java.util.regex.Pattern} library)</td>
+ * <td>Regular expression (in the syntax supported by the {@link java.util.regex.Pattern} library)</td>
  * <td>&nbsp;</td>
  * </tr>
  * <tr>
@@ -610,24 +608,6 @@ public class RemoteIpFilter implements Filter {
     protected static final String TRUSTED_PROXIES_PARAMETER = "trustedProxies";
     
     /**
-     * Convert a given comma delimited list of regular expressions into an array of compiled {@link Pattern}
-     * 
-     * @return array of patterns (not <code>null</code>)
-     */
-    protected static Pattern[] commaDelimitedListToPatternArray(String commaDelimitedPatterns) {
-        String[] patterns = commaDelimitedListToStringArray(commaDelimitedPatterns);
-        List<Pattern> patternsList = new ArrayList<Pattern>();
-        for (String pattern : patterns) {
-            try {
-                patternsList.add(Pattern.compile(pattern));
-            } catch (PatternSyntaxException e) {
-                throw new IllegalArgumentException("Illegal pattern syntax '" + pattern + "'", e);
-            }
-        }
-        return patternsList.toArray(new Pattern[0]);
-    }
-    
-    /**
      * Convert a given comma delimited list of regular expressions into an array of String
      * 
      * @return array of patterns (non <code>null</code>)
@@ -658,18 +638,6 @@ public class RemoteIpFilter implements Filter {
     }
     
     /**
-     * Return <code>true</code> if the given <code>str</code> matches at least one of the given <code>patterns</code>.
-     */
-    protected static boolean matchesOne(String str, Pattern... patterns) {
-        for (Pattern pattern : patterns) {
-            if (pattern.matcher(str).matches()) {
-                return true;
-            }
-        }
-        return false;
-    }
-    
-    /**
      * @see #setHttpServerPort(int)
      */
     private int httpServerPort = 80;
@@ -682,10 +650,11 @@ public class RemoteIpFilter implements Filter {
     /**
      * @see #setInternalProxies(String)
      */
-    private Pattern[] internalProxies = new Pattern[] {
-        Pattern.compile("10\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}"), Pattern.compile("192\\.168\\.\\d{1,3}\\.\\d{1,3}"),
-        Pattern.compile("169\\.254\\.\\d{1,3}\\.\\d{1,3}"), Pattern.compile("127\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}")
-    };
+    private Pattern internalProxies = Pattern.compile(
+            "10\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}|" +
+            "192\\.168\\.\\d{1,3}\\.\\d{1,3}|" +
+            "169\\.254\\.\\d{1,3}\\.\\d{1,3}|" +
+            "127\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}");
     
     /**
      * @see #setProtocolHeader(String)
@@ -707,7 +676,7 @@ public class RemoteIpFilter implements Filter {
     /**
      * @see #setTrustedProxies(String)
      */
-    private Pattern[] trustedProxies = new Pattern[0];
+    private Pattern trustedProxies = null;
     
     @Override
     public void destroy() {
@@ -716,7 +685,8 @@ public class RemoteIpFilter implements Filter {
     
     public void doFilter(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws IOException, ServletException {
         
-        if (matchesOne(request.getRemoteAddr(), internalProxies)) {
+        if (internalProxies != null &&
+                internalProxies.matcher(request.getRemoteAddr()).matches()) {
             String remoteIp = null;
             // In java 6, proxiesHeaderValue should be declared as a java.util.Deque
             LinkedList<String> proxiesHeaderValue = new LinkedList<String>();
@@ -736,9 +706,10 @@ public class RemoteIpFilter implements Filter {
             for (idx = remoteIpHeaderValue.length - 1; idx >= 0; idx--) {
                 String currentRemoteIp = remoteIpHeaderValue[idx];
                 remoteIp = currentRemoteIp;
-                if (matchesOne(currentRemoteIp, internalProxies)) {
+                if (internalProxies.matcher(currentRemoteIp).matches()) {
                     // do nothing, internalProxies IPs are not appended to the
-                } else if (matchesOne(currentRemoteIp, trustedProxies)) {
+                } else if (trustedProxies != null &&
+                        trustedProxies.matcher(currentRemoteIp).matches()) {
                     proxiesHeaderValue.addFirst(currentRemoteIp);
                 } else {
                     idx--; // decrement idx because break statement doesn't do it
@@ -824,7 +795,7 @@ public class RemoteIpFilter implements Filter {
         return httpsServerPort;
     }
     
-    public Pattern[] getInternalProxies() {
+    public Pattern getInternalProxies() {
         return internalProxies;
     }
     
@@ -844,7 +815,7 @@ public class RemoteIpFilter implements Filter {
         return remoteIpHeader;
     }
     
-    public Pattern[] getTrustedProxies() {
+    public Pattern getTrustedProxies() {
         return trustedProxies;
     }
     
@@ -918,14 +889,18 @@ public class RemoteIpFilter implements Filter {
     
     /**
      * <p>
-     * Comma delimited list of internal proxies. Can be expressed with regular expressions.
+     * Regular expressions that defines the internal proxies.
      * </p>
      * <p>
-     * Default value : 10\.\d{1,3}\.\d{1,3}\.\d{1,3}, 192\.168\.\d{1,3}\.\d{1,3}, 127\.\d{1,3}\.\d{1,3}\.\d{1,3}
+     * Default value : 10\.\d{1,3}\.\d{1,3}\.\d{1,3}|192\.168\.\d{1,3}\.\d{1,3}|169\.254.\d{1,3}.\d{1,3}|127\.\d{1,3}\.\d{1,3}\.\d{1,3}
      * </p>
      */
     public void setInternalProxies(String internalProxies) {
-        this.internalProxies = commaDelimitedListToPatternArray(internalProxies);
+        if (internalProxies == null || internalProxies.length() == 0) {
+            this.internalProxies = null;
+        } else {
+            this.internalProxies = Pattern.compile(internalProxies);
+        }
     }
     
     /**
@@ -990,14 +965,18 @@ public class RemoteIpFilter implements Filter {
     
     /**
      * <p>
-     * Comma delimited list of proxies that are trusted when they appear in the {@link #remoteIpHeader} header. Can be expressed as a
-     * regular expression.
+     * Regular expression defining proxies that are trusted when they appear in
+     * the {@link #remoteIpHeader} header.
      * </p>
      * <p>
      * Default value : empty list, no external proxy is trusted.
      * </p>
      */
     public void setTrustedProxies(String trustedProxies) {
-        this.trustedProxies = commaDelimitedListToPatternArray(trustedProxies);
+        if (trustedProxies == null || trustedProxies.length() == 0) {
+            this.trustedProxies = null;
+        } else {
+            this.trustedProxies = Pattern.compile(trustedProxies);
+        }
     }
 }
index 7588b98..02127ad 100644 (file)
@@ -20,9 +20,7 @@ package org.apache.catalina.filters;
 
 
 import java.io.IOException;
-import java.util.ArrayList;
 import java.util.regex.Pattern;
-import java.util.regex.PatternSyntaxException;
 
 import javax.servlet.FilterChain;
 import javax.servlet.ServletException;
@@ -37,35 +35,27 @@ import org.apache.catalina.comet.CometFilterChain;
 /**
  * Implementation of a Filter that performs filtering based on comparing the
  * appropriate request property (selected based on which subclass you choose
- * to configure into your Container's pipeline) against a set of regular
- * expressions configured for this Filter.
+ * to configure into your Container's pipeline) against the regular expressions
+ * configured for this Filter.
  * <p>
  * This filter is configured by setting the <code>allow</code> and/or
- * <code>deny</code> properties to a comma-delimited list of regular
- * expressions (in the syntax supported by the jakarta-regexp library) to
- * which the appropriate request property will be compared.  Evaluation
- * proceeds as follows:
+ * <code>deny</code> properties to a regular expressions (in the syntax
+ * supported by {@link Pattern}) to which the appropriate request property will
+ * be compared.  Evaluation proceeds as follows:
  * <ul>
  * <li>The subclass extracts the request property to be filtered, and
  *     calls the common <code>process()</code> method.
- * <li>If there are any deny expressions configured, the property will
- *     be compared to each such expression.  If a match is found, this
- *     request will be rejected with a "Forbidden" HTTP response.</li>
- * <li>If there are any allow expressions configured, the property will
- *     be compared to each such expression.  If a match is found, this
- *     request will be allowed to pass through to the next filter in the
- *     current pipeline.</li>
- * <li>If one or more deny expressions was specified but no allow expressions,
- *     allow this request to pass through (because none of the deny
- *     expressions matched it).
+ * <li>If there is a deny expression configured, the property will be compared
+ *     to the expression. If a match is found, this request will be rejected
+ *     with a "Forbidden" HTTP response.</li>
+ * <li>If there is a allow expression configured, the property will be compared
+ *     to the expression. If a match is found, this request will be allowed to
+ *     pass through to the next filter in the current pipeline.</li>
+ * <li>If a deny expression was specified but no allow expression, allow this
+ *     request to pass through (because none of the deny expressions matched
+ *     it).
  * <li>The request will be rejected with a "Forbidden" HTTP response.</li>
  * </ul>
- * <p>
- * This Filter may be attached to any Container, depending on the granularity
- * of the filtering you wish to perform.
- *
- * @author Craig R. McClanahan
- * 
  */
 
 public abstract class RequestFilter
@@ -75,27 +65,14 @@ public abstract class RequestFilter
     // ----------------------------------------------------- Instance Variables
 
     /**
-     * The comma-delimited set of <code>allow</code> expressions.
-     */
-    protected String allow = null;
-
-
-    /**
-     * The set of <code>allow</code> regular expressions we will evaluate.
+     * The regular expression used to test for allowed requests.
      */
-    protected Pattern allows[] = new Pattern[0];
-
-
-    /**
-     * The set of <code>deny</code> regular expressions we will evaluate.
-     */
-    protected Pattern denies[] = new Pattern[0];
-
+    protected Pattern allow = null;
 
     /**
-     * The comma-delimited set of <code>deny</code> expressions.
+     * The regular expression used to test for denied requests.
      */
-    protected String deny = null;
+    protected Pattern deny = null;
     
     /**
      * mime type -- "text/plain"
@@ -107,53 +84,56 @@ public abstract class RequestFilter
 
 
     /**
-     * Return a comma-delimited set of the <code>allow</code> expressions
-     * configured for this Filter, if any; otherwise, return <code>null</code>.
+     * Return the regular expression used to test for allowed requests for this
+     * Filter, if any; otherwise, return <code>null</code>.
      */
     public String getAllow() {
-
-        return (this.allow);
-
+        if (allow == null) {
+            return null;
+        }
+        return allow.toString();
     }
 
 
     /**
-     * Set the comma-delimited set of the <code>allow</code> expressions
-     * configured for this Filter, if any.
+     * Set the regular expression used to test for allowed requests for this
+     * Filter, if any.
      *
-     * @param allow The new set of allow expressions
+     * @param allow The new allow expression
      */
     public void setAllow(String allow) {
-
-        this.allow = allow;
-        this.allows = precalculate(allow);
-        
+        if (allow == null || allow.length() == 0) {
+            this.allow = null;
+        } else {
+            this.allow = Pattern.compile(allow);
+        }
     }
 
 
     /**
-     * Return a comma-delimited set of the <code>deny</code> expressions
-     * configured for this Filter, if any; otherwise, return <code>null</code>.
+     * Return the regular expression used to test for denied requests for this
+     * Filter, if any; otherwise, return <code>null</code>.
      */
     public String getDeny() {
-
-        return (this.deny);
-
+        if (deny == null) {
+            return null;
+        }
+        return deny.toString();
     }
 
 
     /**
-     * Set the comma-delimited set of the <code>deny</code> expressions
-     * configured for this Filter, if any.
+     * Set the regular expression used to test for denied requests for this
+     * Filter, if any.
      *
-     * @param deny The new set of deny expressions
+     * @param allow The new deny expression
      */
     public void setDeny(String deny) {
-
-
-        this.deny = deny;
-        this.denies = precalculate(deny);
-        
+        if (deny == null || deny.length() == 0) {
+            this.deny = null;
+        } else {
+            this.deny = Pattern.compile(deny);
+        }
     }
 
 
@@ -183,42 +163,6 @@ public abstract class RequestFilter
 
 
     /**
-     * Return an array of regular expression objects initialized from the
-     * specified argument, which must be <code>null</code> or a comma-delimited
-     * list of regular expression patterns.
-     *
-     * @param list The comma-separated list of patterns
-     *
-     * @exception IllegalArgumentException if one of the patterns has
-     *  invalid syntax
-     */
-    protected Pattern[] precalculate(String list) {
-
-        if (list == null)
-            return (new Pattern[0]);
-        
-        ArrayList<Pattern> result = new ArrayList<Pattern>();
-        
-        String[] patterns = list.split(",");
-        for (String pattern : patterns) {
-            pattern = pattern.trim();
-            if (pattern.length() > 0) {
-                try {
-                    result.add(Pattern.compile(pattern));
-                } catch (PatternSyntaxException e) {
-                    IllegalArgumentException iae = new IllegalArgumentException
-                        (sm.getString("requestFilterFilter.syntax", pattern));
-                    iae.initCause(e);
-                    throw iae;
-                }
-            }
-        }
-
-        return result.toArray(new Pattern[result.size()]);
-    }
-
-
-    /**
      * Perform the filtering that has been configured for this Filter, matching
      * against the specified request property.
      *
@@ -255,8 +199,8 @@ public abstract class RequestFilter
      * @exception IOException if an input/output error occurs
      * @exception ServletException if a servlet error occurs
      */
-    protected void processCometEvent(String property, CometEvent event, CometFilterChain chain)
-            throws IOException, ServletException {
+    protected void processCometEvent(String property, CometEvent event,
+            CometFilterChain chain) throws IOException, ServletException {
         HttpServletResponse response = event.getHttpServletResponse();
         
         if (isAllowed(property)) {
@@ -275,21 +219,17 @@ public abstract class RequestFilter
      *                  <code>false</code> otherwise
      */
     private boolean isAllowed(String property) {
-        for (int i = 0; i < this.denies.length; i++) {
-            if (this.denies[i].matcher(property).matches()) {
-                return false;
-            }
+        if (deny != null && deny.matcher(property).matches()) {
+            return false;
         }
      
         // Check the allow patterns, if any
-        for (int i = 0; i < this.allows.length; i++) {
-            if (this.allows[i].matcher(property).matches()) {
-                return true;
-            }
+        if (allow != null & allow.matcher(property).matches()) {
+            return true;
         }
 
         // Allow if denies specified but not allows
-        if ((this.denies.length > 0) && (this.allows.length == 0)) {
+        if (deny != null && allow == null) {
             return true;
         }
 
@@ -303,6 +243,4 @@ public abstract class RequestFilter
         response.getWriter().write(sm.getString("http.403"));
         response.getWriter().flush();
     }
-
-
 }
index faf2198..8746fba 100644 (file)
@@ -54,9 +54,8 @@ ReplicationValve.crossContext.add=add Cross Context session replication containe
 ReplicationValve.crossContext.registerSession=register Cross context session id={0} from context {1}
 ReplicationValve.crossContext.remove=remove Cross Context session replication container from replicationValve threadlocal
 ReplicationValve.crossContext.sendDelta=send Cross Context session delta from context {0}.
-ReplicationValve.filter.loading=Loading request filters={0}
-ReplicationValve.filter.token=Request filter={0}
-ReplicationValve.filter.token.failure=Unable to compile filter={0}
+ReplicationValve.filter.loading=Loading request filter={0}
+ReplicationValve.filter.failure=Unable to compile filter={0}
 ReplicationValve.invoke.uri=Invoking replication request on {0}
 ReplicationValve.nocluster=No cluster configured for this request.
 ReplicationValve.resetDeltaRequest=Cluster is standalone: reset Session Request Delta at context {0}
index 9617586..823c366 100644 (file)
@@ -55,8 +55,7 @@ ReplicationValve.crossContext.registerSession = retistrar id de sesi\u00F3n de C
 ReplicationValve.crossContext.remove = quitar contenedor de r\u00E9plica de sesi\u00F3n de Contexto Cruzado a replicationValve threadlocal
 ReplicationValve.crossContext.sendDelta = enviar delta de sesi\u00F3n de Contexto Cruzado desde contexto {0}.
 ReplicationValve.filter.loading = Cargando filtros de requerimiento\={0}
-ReplicationValve.filter.token = Filtro de requerimiento\={0}
-ReplicationValve.filter.token.failure = No puedo compilar filtror\={0}
+ReplicationValve.filter.failure = No puedo compilar filtror\={0}
 ReplicationValve.invoke.uri = Invocando requerimiento de r\u00E9plica en {0}
 ReplicationValve.nocluster = No cluster configured for this request.
 ReplicationValve.resetDeltaRequest = Cluster is standalone\: reset Session Request Delta at context {0}
index c28621f..f352709 100644 (file)
@@ -21,8 +21,8 @@ import java.io.IOException;
 import java.util.ArrayList;
 import java.util.Iterator;
 import java.util.List;
-import java.util.StringTokenizer;
 import java.util.regex.Pattern;
+import java.util.regex.PatternSyntaxException;
 
 import javax.servlet.ServletException;
 
@@ -85,14 +85,9 @@ public class ReplicationValve
     private CatalinaCluster cluster = null ;
 
     /**
-     * holds file endings to not call for like images and others
+     * Filter expression 
      */
-    protected java.util.regex.Pattern[] reqFilters = new java.util.regex.Pattern[0];
-    
-    /**
-     * Orginal filter 
-     */
-    protected String filter ;
+    protected Pattern filter = null;
     
     /**
      * crossContext session container 
@@ -159,11 +154,14 @@ public class ReplicationValve
      * @return Returns the filter
      */
     public String getFilter() {
-       return filter ;
+       if (filter == null) {
+           return null;
+       }
+       return filter.toString();
     }
 
     /**
-     * compile filter string to regular expressions
+     * compile filter string to regular expression
      * @see Pattern#compile(java.lang.String)
      * @param filter
      *            The filter to set.
@@ -171,19 +169,15 @@ public class ReplicationValve
     public void setFilter(String filter) {
         if (log.isDebugEnabled())
             log.debug(sm.getString("ReplicationValve.filter.loading", filter));
-        this.filter = filter;
-        StringTokenizer t = new StringTokenizer(filter, ";");
-        this.reqFilters = new Pattern[t.countTokens()];
-        int i = 0;
-        while (t.hasMoreTokens()) {
-            String s = t.nextToken();
-            if (log.isTraceEnabled())
-                log.trace(sm.getString("ReplicationValve.filter.token", s));
+        
+        if (filter == null || filter.length() == 0) {
+            this.filter = null;
+        } else {
             try {
-                reqFilters[i++] = Pattern.compile(s);
-            } catch (Exception x) {
-                log.error(sm.getString("ReplicationValve.filter.token.failure",
-                        s), x);
+                this.filter = Pattern.compile(filter);
+            } catch (PatternSyntaxException pse) {
+                log.error(sm.getString("ReplicationValve.filter.failure",
+                        filter), pse);
             }
         }
     }
@@ -280,21 +274,6 @@ public class ReplicationValve
         return totalSendTime;
     }
 
-    /**
-     * @return Returns the reqFilters.
-     */
-    protected java.util.regex.Pattern[] getReqFilters() {
-        return reqFilters;
-    }
-    
-    /**
-     * @param reqFilters The reqFilters to set.
-     */
-    protected void setReqFilters(java.util.regex.Pattern[] reqFilters) {
-        this.reqFilters = reqFilters;
-    }
-    
-    
     // --------------------------------------------------------- Public Methods
     
     /**
@@ -572,14 +551,7 @@ public class ReplicationValve
      * @return True if no session change
      */
     protected boolean isRequestWithoutSessionChange(String uri) {
-
-        boolean filterfound = false;
-
-        for (int i = 0; (i < reqFilters.length) && (!filterfound); i++) {
-            java.util.regex.Matcher matcher = reqFilters[i].matcher(uri);
-            filterfound = matcher.matches();
-        }
-        return filterfound;
+        return filter.matcher(uri).matches();
     }
 
     /**
index afdcc1b..0bdfa7e 100644 (file)
 package org.apache.catalina.valves;
 
 import java.io.IOException;
-import java.util.ArrayList;
 import java.util.Enumeration;
 import java.util.Iterator;
 import java.util.LinkedList;
 import java.util.List;
 import java.util.regex.Pattern;
-import java.util.regex.PatternSyntaxException;
 
 import javax.servlet.ServletException;
 
@@ -86,8 +84,8 @@ import org.apache.juli.logging.LogFactory;
  * <td>List of internal proxies ip adress. If they appear in the <code>remoteIpHeader</code> value, they will be trusted and will not appear
  * in the <code>proxiesHeader</code> value</td>
  * <td>RemoteIPInternalProxy</td>
- * <td>Comma delimited list of regular expressions (in the syntax supported by the {@link java.util.regex.Pattern} library)</td>
- * <td>10\.\d{1,3}\.\d{1,3}\.\d{1,3}, 192\.168\.\d{1,3}\.\d{1,3}, 169\.254\.\d{1,3}\.\d{1,3}, 127\.\d{1,3}\.\d{1,3}\.\d{1,3} <br/>
+ * <td>Regular expression (in the syntax supported by the {@link java.util.regex.Pattern} library)</td>
+ * <td>10\.\d{1,3}\.\d{1,3}\.\d{1,3}|192\.168\.\d{1,3}\.\d{1,3}|169\.254\.\d{1,3}\.\d{1,3}|127\.\d{1,3}\.\d{1,3}\.\d{1,3}<br/>
  * By default, 10/8, 192.168/16, 169.254/16 and 127/8 are allowed ; 172.16/12 has not been enabled by default because it is complex to
  * describe with regular expressions</td>
  * </tr>
@@ -105,7 +103,7 @@ import org.apache.juli.logging.LogFactory;
  * <td>List of trusted proxies ip adress. If they appear in the <code>remoteIpHeader</code> value, they will be trusted and will appear
  * in the <code>proxiesHeader</code> value</td>
  * <td>RemoteIPTrustedProxy</td>
- * <td>Comma delimited list of regular expressions (in the syntax supported by the {@link java.util.regex.Pattern} library)</td>
+ * <td>Regular expression (in the syntax supported by the {@link java.util.regex.Pattern} library)</td>
  * <td>&nbsp;</td>
  * </tr>
  * <tr>
@@ -360,27 +358,9 @@ public class RemoteIpValve extends ValveBase {
     private static final Log log = LogFactory.getLog(RemoteIpValve.class);
     
     /**
-     * Convert a given comma delimited list of regular expressions into an array of compiled {@link Pattern}
+     * Convert a given comma delimited String into an array of String
      * 
-     * @return array of patterns (not <code>null</code>)
-     */
-    protected static Pattern[] commaDelimitedListToPatternArray(String commaDelimitedPatterns) {
-        String[] patterns = commaDelimitedListToStringArray(commaDelimitedPatterns);
-        List<Pattern> patternsList = new ArrayList<Pattern>();
-        for (String pattern : patterns) {
-            try {
-                patternsList.add(Pattern.compile(pattern));
-            } catch (PatternSyntaxException e) {
-                throw new IllegalArgumentException(sm.getString("remoteIpValve.syntax", pattern), e);
-            }
-        }
-        return patternsList.toArray(new Pattern[0]);
-    }
-    
-    /**
-     * Convert a given comma delimited list of regular expressions into an array of String
-     * 
-     * @return array of patterns (non <code>null</code>)
+     * @return array of String (non <code>null</code>)
      */
     protected static String[] commaDelimitedListToStringArray(String commaDelimitedStrings) {
         return (commaDelimitedStrings == null || commaDelimitedStrings.length() == 0) ? new String[0] : commaSeparatedValuesPattern
@@ -408,18 +388,6 @@ public class RemoteIpValve extends ValveBase {
     }
     
     /**
-     * Return <code>true</code> if the given <code>str</code> matches at least one of the given <code>patterns</code>.
-     */
-    protected static boolean matchesOne(String str, Pattern... patterns) {
-        for (Pattern pattern : patterns) {
-            if (pattern.matcher(str).matches()) {
-                return true;
-            }
-        }
-        return false;
-    }
-    
-    /**
      * @see #setHttpServerPort(int)
      */
     private int httpServerPort = 80;
@@ -432,10 +400,11 @@ public class RemoteIpValve extends ValveBase {
     /**
      * @see #setInternalProxies(String)
      */
-    private Pattern[] internalProxies = new Pattern[] {
-        Pattern.compile("10\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}"), Pattern.compile("192\\.168\\.\\d{1,3}\\.\\d{1,3}"),
-        Pattern.compile("169\\.254\\.\\d{1,3}\\.\\d{1,3}"), Pattern.compile("127\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}")
-    };
+    private Pattern internalProxies = Pattern.compile(
+            "10\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}|" +
+            "192\\.168\\.\\d{1,3}\\.\\d{1,3}|" +
+            "169\\.254\\.\\d{1,3}\\.\\d{1,3}|" +
+            "127\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}");
     
     /**
      * @see #setProtocolHeader(String)
@@ -460,7 +429,7 @@ public class RemoteIpValve extends ValveBase {
     /**
      * @see RemoteIpValve#setTrustedProxies(String)
      */
-    private Pattern[] trustedProxies = new Pattern[0];
+    private Pattern trustedProxies = null;
     
     public int getHttpsServerPort() {
         return httpsServerPort;
@@ -483,11 +452,10 @@ public class RemoteIpValve extends ValveBase {
      * @return comma delimited list of internal proxies
      */
     public String getInternalProxies() {
-        List<String> internalProxiesAsStringList = new ArrayList<String>();
-        for (Pattern internalProxyPattern : internalProxies) {
-            internalProxiesAsStringList.add(String.valueOf(internalProxyPattern));
+        if (internalProxies == null) {
+            return null;
         }
-        return listToCommaDelimitedString(internalProxiesAsStringList);
+        return internalProxies.toString();
     }
     
     /**
@@ -527,11 +495,10 @@ public class RemoteIpValve extends ValveBase {
      * @return comma delimited list of trusted proxies
      */
     public String getTrustedProxies() {
-        List<String> trustedProxiesAsStringList = new ArrayList<String>();
-        for (Pattern trustedProxy : trustedProxies) {
-            trustedProxiesAsStringList.add(String.valueOf(trustedProxy));
+        if (trustedProxies == null) {
+            return null;
         }
-        return listToCommaDelimitedString(trustedProxiesAsStringList);
+        return trustedProxies.toString();
     }
     
     /**
@@ -545,7 +512,8 @@ public class RemoteIpValve extends ValveBase {
         final boolean originalSecure = request.isSecure();
         final int originalServerPort = request.getServerPort();
         
-        if (matchesOne(originalRemoteAddr, internalProxies)) {
+        if (internalProxies !=null &&
+                internalProxies.matcher(originalRemoteAddr).matches()) {
             String remoteIp = null;
             // In java 6, proxiesHeaderValue should be declared as a java.util.Deque
             LinkedList<String> proxiesHeaderValue = new LinkedList<String>();
@@ -565,9 +533,10 @@ public class RemoteIpValve extends ValveBase {
             for (idx = remoteIpHeaderValue.length - 1; idx >= 0; idx--) {
                 String currentRemoteIp = remoteIpHeaderValue[idx];
                 remoteIp = currentRemoteIp;
-                if (matchesOne(currentRemoteIp, internalProxies)) {
+                if (internalProxies.matcher(currentRemoteIp).matches()) {
                     // do nothing, internalProxies IPs are not appended to the
-                } else if (matchesOne(currentRemoteIp, trustedProxies)) {
+                } else if (trustedProxies != null &&
+                        trustedProxies.matcher(currentRemoteIp).matches()) {
                     proxiesHeaderValue.addFirst(currentRemoteIp);
                 } else {
                     idx--; // decrement idx because break statement doesn't do it
@@ -674,14 +643,18 @@ public class RemoteIpValve extends ValveBase {
     
     /**
      * <p>
-     * Comma delimited list of internal proxies. Can be expressed with regular expressions.
+     * Regular expressions that defines the internal proxies.
      * </p>
      * <p>
-     * Default value : 10\.\d{1,3}\.\d{1,3}\.\d{1,3}, 192\.168\.\d{1,3}\.\d{1,3}, 127\.\d{1,3}\.\d{1,3}\.\d{1,3}
+     * Default value : 10\.\d{1,3}\.\d{1,3}\.\d{1,3}|192\.168\.\d{1,3}\.\d{1,3}|169\.254.\d{1,3}.\d{1,3}|127\.\d{1,3}\.\d{1,3}\.\d{1,3}
      * </p>
      */
-    public void setInternalProxies(String commaDelimitedInternalProxies) {
-        this.internalProxies = commaDelimitedListToPatternArray(commaDelimitedInternalProxies);
+    public void setInternalProxies(String internalProxies) {
+        if (internalProxies == null || internalProxies.length() == 0) {
+            this.internalProxies = null;
+        } else {
+            this.internalProxies = Pattern.compile(internalProxies);
+        }
     }
     
     /**
@@ -748,14 +721,18 @@ public class RemoteIpValve extends ValveBase {
     
     /**
      * <p>
-     * Comma delimited list of proxies that are trusted when they appear in the {@link #remoteIpHeader} header. Can be expressed as a
-     * regular expression.
+     * Regular expression defining proxies that are trusted when they appear in
+     * the {@link #remoteIpHeader} header.
      * </p>
      * <p>
      * Default value : empty list, no external proxy is trusted.
      * </p>
      */
-    public void setTrustedProxies(String commaDelimitedTrustedProxies) {
-        this.trustedProxies = commaDelimitedListToPatternArray(commaDelimitedTrustedProxies);
+    public void setTrustedProxies(String trustedProxies) {
+        if (trustedProxies == null || trustedProxies.length() == 0) {
+            this.trustedProxies = null;
+        } else {
+            this.trustedProxies = Pattern.compile(trustedProxies);
+        }
     }
 }
index 08d100a..27d8fe4 100644 (file)
@@ -20,9 +20,7 @@ package org.apache.catalina.valves;
 
 
 import java.io.IOException;
-import java.util.ArrayList;
 import java.util.regex.Pattern;
-import java.util.regex.PatternSyntaxException;
 
 import javax.servlet.ServletException;
 import javax.servlet.http.HttpServletResponse;
@@ -33,27 +31,25 @@ import org.apache.catalina.connector.Response;
 /**
  * Implementation of a Valve that performs filtering based on comparing the
  * appropriate request property (selected based on which subclass you choose
- * to configure into your Container's pipeline) against a set of regular
- * expressions configured for this Valve.
+ * to configure into your Container's pipeline) against the regular expressions
+ * configured for this Valve.
  * <p>
  * This valve is configured by setting the <code>allow</code> and/or
- * <code>deny</code> properties to a comma-delimited list of regular
- * expressions (in the syntax supported by the jakarta-regexp library) to
- * which the appropriate request property will be compared.  Evaluation
- * proceeds as follows:
+ * <code>deny</code> properties to a regular expressions (in the syntax
+ * supported by {@link Pattern}) to which the appropriate request property will
+ * be compared. Evaluation proceeds as follows:
  * <ul>
  * <li>The subclass extracts the request property to be filtered, and
  *     calls the common <code>process()</code> method.
- * <li>If there are any deny expressions configured, the property will
- *     be compared to each such expression.  If a match is found, this
- *     request will be rejected with a "Forbidden" HTTP response.</li>
- * <li>If there are any allow expressions configured, the property will
- *     be compared to each such expression.  If a match is found, this
- *     request will be allowed to pass through to the next Valve in the
- *     current pipeline.</li>
- * <li>If one or more deny expressions was specified but no allow expressions,
- *     allow this request to pass through (because none of the deny
- *     expressions matched it).
+ * <li>If there is a deny expression configured, the property will be compared
+ *     to the expression. If a match is found, this request will be rejected
+ *     with a "Forbidden" HTTP response.</li>
+ * <li>If there is a allow expression configured, the property will be compared
+ *     to each such expression.  If a match is found, this request will be
+ *     allowed to pass through to the next Valve in the current pipeline.</li>
+ * <li>If a deny expression was specified but no allow expression, allow this
+ *     request to pass through (because none of the deny expressions matched
+ *     it).
  * <li>The request will be rejected with a "Forbidden" HTTP response.</li>
  * </ul>
  * <p>
@@ -86,79 +82,71 @@ public abstract class RequestFilterValve
 
 
     /**
-     * The comma-delimited set of <code>allow</code> expressions.
+     * The regular expression used to test for allowed requests.
      */
-    protected String allow = null;
+    protected Pattern allow = null;
 
 
     /**
-     * The set of <code>allow</code> regular expressions we will evaluate.
+     * The regular expression used to test for denied requests.
      */
-    protected Pattern allows[] = new Pattern[0];
-
-
-    /**
-     * The set of <code>deny</code> regular expressions we will evaluate.
-     */
-    protected Pattern denies[] = new Pattern[0];
-
-
-    /**
-     * The comma-delimited set of <code>deny</code> expressions.
-     */
-    protected String deny = null;
+    protected Pattern deny = null;
 
 
     // ------------------------------------------------------------- Properties
 
 
     /**
-     * Return a comma-delimited set of the <code>allow</code> expressions
-     * configured for this Valve, if any; otherwise, return <code>null</code>.
+     * Return the regular expression used to test for allowed requests for this
+     * Valve, if any; otherwise, return <code>null</code>.
      */
     public String getAllow() {
-
-        return (this.allow);
-
+        if (allow == null) {
+            return null;
+        }
+        return allow.toString();
     }
 
 
     /**
-     * Set the comma-delimited set of the <code>allow</code> expressions
-     * configured for this Valve, if any.
+     * Set the regular expression used to test for allowed requests for this
+     * Valve, if any.
      *
-     * @param allow The new set of allow expressions
+     * @param allow The new allow expression
      */
     public void setAllow(String allow) {
-
-        this.allow = allow;
-        allows = precalculate(allow);
-
+        if (allow == null || allow.length() == 0) {
+            this.allow = null;
+        } else {
+            this.allow = Pattern.compile(allow);
+        }
     }
 
 
     /**
-     * Return a comma-delimited set of the <code>deny</code> expressions
-     * configured for this Valve, if any; otherwise, return <code>null</code>.
+     * Return the regular expression used to test for denied requests for this
+     * Valve, if any; otherwise, return <code>null</code>.
      */
     public String getDeny() {
-
-        return (this.deny);
-
+        if (deny == null) {
+            return null;
+        }
+        return deny.toString();
     }
 
 
     /**
-     * Set the comma-delimited set of the <code>deny</code> expressions
-     * configured for this Valve, if any.
+     * Set the regular expression used to test for denied requests for this
+     * Valve, if any.
      *
-     * @param deny The new set of deny expressions
+     * @param allow The new deny expression
      */
     public void setDeny(String deny) {
-
-        this.deny = deny;
-        denies = precalculate(deny);
-
+        if (deny == null || deny.length() == 0) {
+            this.deny = null;
+        } else {
+            this.deny = Pattern.compile(deny);
+        }
     }
 
 
@@ -197,48 +185,6 @@ public abstract class RequestFilterValve
 
 
     /**
-     * Return an array of regular expression objects initialized from the
-     * specified argument, which must be <code>null</code> or a comma-delimited
-     * list of regular expression patterns.
-     *
-     * @param list The comma-separated list of patterns
-     *
-     * @exception IllegalArgumentException if one of the patterns has
-     *  invalid syntax
-     */
-    protected Pattern[] precalculate(String list) {
-
-        if (list == null)
-            return (new Pattern[0]);
-        list = list.trim();
-        if (list.length() < 1)
-            return (new Pattern[0]);
-        list += ",";
-
-        ArrayList<Pattern> reList = new ArrayList<Pattern>();
-        while (list.length() > 0) {
-            int comma = list.indexOf(',');
-            if (comma < 0)
-                break;
-            String pattern = list.substring(0, comma).trim();
-            try {
-                reList.add(Pattern.compile(pattern));
-            } catch (PatternSyntaxException e) {
-                IllegalArgumentException iae = new IllegalArgumentException
-                    (sm.getString("requestFilterValve.syntax", pattern));
-                iae.initCause(e);
-                throw iae;
-            }
-            list = list.substring(comma + 1);
-        }
-
-        Pattern reArray[] = new Pattern[reList.size()];
-        return reList.toArray(reArray);
-
-    }
-
-
-    /**
      * Perform the filtering that has been configured for this Valve, matching
      * against the specified request property.
      *
@@ -254,23 +200,19 @@ public abstract class RequestFilterValve
         throws IOException, ServletException {
 
         // Check the deny patterns, if any
-        for (int i = 0; i < denies.length; i++) {
-            if (denies[i].matcher(property).matches()) {
-                response.sendError(HttpServletResponse.SC_FORBIDDEN);
-                return;
-            }
+        if (deny != null && deny.matcher(property).matches()) {
+            response.sendError(HttpServletResponse.SC_FORBIDDEN);
+            return;
         }
 
         // Check the allow patterns, if any
-        for (int i = 0; i < allows.length; i++) {
-            if (allows[i].matcher(property).matches()) {
-                getNext().invoke(request, response);
-                return;
-            }
+        if (allow != null && allow.matcher(property).matches()) {
+            getNext().invoke(request, response);
+            return;
         }
 
         // Allow if denies specified but not allows
-        if ((denies.length > 0) && (allows.length == 0)) {
+        if (deny != null && allow == null) {
             getNext().invoke(request, response);
             return;
         }
@@ -279,6 +221,4 @@ public abstract class RequestFilterValve
         response.sendError(HttpServletResponse.SC_FORBIDDEN);
 
     }
-
-
 }
index 5b7d3bf..3805640 100644 (file)
@@ -21,7 +21,6 @@ import java.util.StringTokenizer;
 import java.util.concurrent.Executor;
 import java.util.concurrent.atomic.AtomicBoolean;
 import java.util.regex.Pattern;
-import java.util.regex.PatternSyntaxException;
 
 import org.apache.coyote.ActionCode;
 import org.apache.coyote.ActionHook;
@@ -125,7 +124,7 @@ public abstract class AbstractHttp11Processor implements ActionHook, Processor {
     /**
      * List of restricted user agents.
      */
-    protected Pattern[] restrictedUserAgents = null;
+    protected Pattern restrictedUserAgents = null;
 
 
     /**
@@ -214,7 +213,7 @@ public abstract class AbstractHttp11Processor implements ActionHook, Processor {
     /**
      * List of user agents to not use gzip with
      */
-    protected Pattern noCompressionUserAgents[] = null;
+    protected Pattern noCompressionUserAgents = null;
 
     /**
      * List of MIMES which could be gzipped
@@ -272,46 +271,17 @@ public abstract class AbstractHttp11Processor implements ActionHook, Processor {
 
 
     /**
-     * Add user-agent for which gzip compression didn't works
-     * The user agent String given will be exactly matched
-     * to the user-agent header submitted by the client.
+     * Set no compression user agent pattern. Regular expression as supported
+     * by {@link Pattern}.
      *
-     * @param userAgent user-agent string
-     */
-    public void addNoCompressionUserAgent(String userAgent) {
-        try {
-            Pattern nRule = Pattern.compile(userAgent);
-            noCompressionUserAgents =
-                addREArray(noCompressionUserAgents, nRule);
-        } catch (PatternSyntaxException pse) {
-            getLog().error(sm.getString("http11processor.regexp.error", userAgent), pse);
-        }
-    }
-
-
-    /**
-     * Set no compression user agent list (this method is best when used with
-     * a large number of connectors, where it would be better to have all of
-     * them referenced a single array).
-     */
-    public void setNoCompressionUserAgents(Pattern[] noCompressionUserAgents) {
-        this.noCompressionUserAgents = noCompressionUserAgents;
-    }
-
-
-    /**
-     * Set no compression user agent list.
-     * List contains users agents separated by ',' :
-     *
-     * ie: "gorilla,desesplorer,tigrus"
+     * ie: "gorilla|desesplorer|tigrus"
      */
     public void setNoCompressionUserAgents(String noCompressionUserAgents) {
-        if (noCompressionUserAgents != null) {
-            StringTokenizer st = new StringTokenizer(noCompressionUserAgents, ",");
-
-            while (st.hasMoreTokens()) {
-                addNoCompressionUserAgent(st.nextToken().trim());
-            }
+        if (noCompressionUserAgents == null || noCompressionUserAgents.length() == 0) {
+            this.noCompressionUserAgents = null;
+        } else {
+            this.noCompressionUserAgents =
+                Pattern.compile(noCompressionUserAgents);
         }
     }
 
@@ -395,28 +365,6 @@ public abstract class AbstractHttp11Processor implements ActionHook, Processor {
 
 
     /**
-     * General use method
-     *
-     * @param rArray the REArray
-     * @param value Obj
-     */
-    private Pattern[] addREArray(Pattern rArray[], Pattern value) {
-        Pattern[] result = null;
-        if (rArray == null) {
-            result = new Pattern[1];
-            result[0] = value;
-        }
-        else {
-            result = new Pattern[rArray.length + 1];
-            for (int i = 0; i < rArray.length; i++)
-                result[i] = rArray[i];
-            result[rArray.length] = value;
-        }
-        return result;
-    }
-
-
-    /**
      * Checks if any entry in the string array starts with the specified value
      *
      * @param sArray the StringArray
@@ -435,45 +383,17 @@ public abstract class AbstractHttp11Processor implements ActionHook, Processor {
 
 
     /**
-     * Add restricted user-agent (which will downgrade the connector
-     * to HTTP/1.0 mode). The user agent String given will be matched
-     * via regexp to the user-agent header submitted by the client.
-     *
-     * @param userAgent user-agent string
-     */
-    public void addRestrictedUserAgent(String userAgent) {
-        try {
-            Pattern nRule = Pattern.compile(userAgent);
-            restrictedUserAgents = addREArray(restrictedUserAgents, nRule);
-        } catch (PatternSyntaxException pse) {
-            getLog().error(sm.getString("http11processor.regexp.error", userAgent), pse);
-        }
-    }
-
-
-    /**
-     * Set restricted user agent list (this method is best when used with
-     * a large number of connectors, where it would be better to have all of
-     * them referenced a single array).
-     */
-    public void setRestrictedUserAgents(Pattern[] restrictedUserAgents) {
-        this.restrictedUserAgents = restrictedUserAgents;
-    }
-
-
-    /**
      * Set restricted user agent list (which will downgrade the connector
-     * to HTTP/1.0 mode). List contains users agents separated by ',' :
+     * to HTTP/1.0 mode). Regular expression as supported by {@link Pattern}.
      *
-     * ie: "gorilla,desesplorer,tigrus"
+     * ie: "gorilla|desesplorer|tigrus"
      */
     public void setRestrictedUserAgents(String restrictedUserAgents) {
-        if (restrictedUserAgents != null) {
-            StringTokenizer st =
-                new StringTokenizer(restrictedUserAgents, ",");
-            while (st.hasMoreTokens()) {
-                addRestrictedUserAgent(st.nextToken().trim());
-            }
+        if (restrictedUserAgents == null ||
+                restrictedUserAgents.length() == 0) {
+            this.restrictedUserAgents = null;
+        } else {
+            this.restrictedUserAgents = Pattern.compile(restrictedUserAgents);
         }
     }
 
@@ -675,10 +595,10 @@ public abstract class AbstractHttp11Processor implements ActionHook, Processor {
             if(userAgentValueMB != null) {
                 String userAgentValue = userAgentValueMB.toString();
 
-                // If one Regexp rule match, disable compression
-                for (int i = 0; i < noCompressionUserAgents.length; i++)
-                    if (noCompressionUserAgents[i].matcher(userAgentValue).matches())
+                if (noCompressionUserAgents != null &&
+                        noCompressionUserAgents.matcher(userAgentValue).matches()) {
                         return false;
+                }
             }
         }
 
index 8096f5b..ba0a212 100644 (file)
@@ -696,12 +696,10 @@ public class Http11AprProcessor extends AbstractHttp11Processor {
             // and keepAlive flags accordingly
             if(userAgentValueMB != null) {
                 String userAgentValue = userAgentValueMB.toString();
-                for (int i = 0; i < restrictedUserAgents.length; i++) {
-                    if (restrictedUserAgents[i].matcher(userAgentValue).matches()) {
-                        http11 = false;
-                        keepAlive = false;
-                        break;
-                    }
+                if (restrictedUserAgents != null &&
+                        restrictedUserAgents.matcher(userAgentValue).matches()) {
+                    http11 = false;
+                    keepAlive = false;
                 }
             }
         }
index cbb8157..4f115c6 100644 (file)
@@ -759,12 +759,10 @@ public class Http11NioProcessor extends AbstractHttp11Processor {
             // and keepAlive flags accordingly
             if(userAgentValueMB != null) {
                 String userAgentValue = userAgentValueMB.toString();
-                for (int i = 0; i < restrictedUserAgents.length; i++) {
-                    if (restrictedUserAgents[i].matcher(userAgentValue).matches()) {
-                        http11 = false;
-                        keepAlive = false;
-                        break;
-                    }
+                if (restrictedUserAgents != null &&
+                        restrictedUserAgents.matcher(userAgentValue).matches()) {
+                    http11 = false;
+                    keepAlive = false;
                 }
             }
         }
index a4069ae..1d7361b 100644 (file)
@@ -601,12 +601,10 @@ public class Http11Processor extends AbstractHttp11Processor {
             // and keepAlive flags accordingly
             if(userAgentValueMB != null) {
                 String userAgentValue = userAgentValueMB.toString();
-                for (int i = 0; i < restrictedUserAgents.length; i++) {
-                    if (restrictedUserAgents[i].matcher(userAgentValue).matches()) {
-                        http11 = false;
-                        keepAlive = false;
-                        break;
-                    }
+                if (restrictedUserAgents != null &&
+                        restrictedUserAgents.matcher(userAgentValue).matches()) {
+                    http11 = false;
+                    keepAlive = false;
                 }
             }
         }
index e83e3d6..a842104 100644 (file)
         for LDAP seaches when using the JNDI Realm with <code>userSearch</code>.
         (markt)
       </add>
+      <update>
+        All configuration options that use regular expression now require a
+        single regular expression (using <code>java.util.regex</code>) rather
+        than a list of comma-separated or semi-colon-separated expressions.
+        (markt)
+      </update>
     </changelog>
   </subsection>
   <subsection name="Coyote">
index 95aa35b..28174c1 100644 (file)
         Set value to <code>org.apache.catalina.ha.tcp.ReplicationValve</code>
       </attribute>
       <attribute name="filter" required="false">
-        For known file extensions or urls, you can use a filter to 
-        notify the cluster that the session has not been modified during this 
-        request and the cluster doesn't have to probe the session managers for changes.
-        If there is a filter match, the cluster assumes there has been no session change.
-        An example filter would look like <code>filter=&quot;.*\.gif;.*\.js;.*\.jpg;.*\.png;.*\.htm;.*\.html;.*\.css;.*\.txt;&quot;</code>
-        The filter uses regular expressions and each filter is delimited by a semi colon.
-        <code>Pattern#compile(java.lang.String)</code>
+        For known file extensions or urls, you can use this Valve to notify the
+        cluster that the session has not been modified during this  request and
+        the cluster doesn't have to probe the session managers for changes. If
+        the request matches this filter pattern, the cluster assumes there has
+        been no session change. An example filter would look like <code>
+        filter=&quot;.*\.gif|.*\.js|.*\.jpg|.*\.png|.*\.htm|.*\.html|.*\.css|.*\.txt;&quot;
+        </code>. The filter is a regular expression using
+        <code>java.util.regex</code>.
       </attribute>
       <attribute name="primaryIndicator" required="false">
         Boolean value, so to true, and the replication valve will insert a request attribute with the name
index 5cc11d8..a0373bb 100644 (file)
@@ -549,8 +549,8 @@ FINE: Request "/docs/config/manager.html" with response status "200" content-typ
     <attributes>
 
       <attribute name="allow" required="false">
-        <p>A comma-separated list of <em>regular expression</em> patterns
-        that the remote client's IP address is compared to.  If this attribute
+        <p>A regular expression (using <code>java.util.Regex</code>) that the
+        remote client&apos;s IP address is compared to.  If this attribute
         is specified, the remote address MUST match for this request to be
         accepted.  If this attribute is not specified, all requests will be
         accepted UNLESS the remote address matches a <code>deny</code>
@@ -558,8 +558,8 @@ FINE: Request "/docs/config/manager.html" with response status "200" content-typ
       </attribute>
 
       <attribute name="deny" required="false">
-        <p>A comma-separated list of <em>regular expression</em> patterns
-        that the remote client's IP address is compared to.  If this attribute
+        <p>A regular expression (using <code>java.util.Regex</code>) that the
+        remote client's IP address is compared to.  If this attribute
         is specified, the remote address MUST NOT match for this request to be
         accepted.  If this attribute is not specified, request acceptance is
         governed solely by the <code>accept</code> attribute.</p>
@@ -604,8 +604,8 @@ FINE: Request "/docs/config/manager.html" with response status "200" content-typ
     <attributes>
 
       <attribute name="allow" required="false">
-        <p>A comma-separated list of <em>regular expression</em> patterns
-        that the remote client's hostname is compared to.  If this attribute
+        <p>A regular expression (using <code>java.util.Regex</code>) that the
+        remote client&apos;s hostname is compared to.  If this attribute
         is specified, the remote hostname MUST match for this request to be
         accepted.  If this attribute is not specified, all requests will be
         accepted UNLESS the remote hostname matches a <code>deny</code>
@@ -613,8 +613,8 @@ FINE: Request "/docs/config/manager.html" with response status "200" content-typ
       </attribute>
 
       <attribute name="deny" required="false">
-        <p>A comma-separated list of <em>regular expression</em> patterns
-        that the remote client's hostname is compared to.  If this attribute
+        <p>A regular expression (using <code>java.util.Regex</code>) that the
+        remote client's hostname is compared to.  If this attribute
         is specified, the remote hostname MUST NOT match for this request to be
         accepted.  If this attribute is not specified, request acceptance is
         governed solely by the <code>accept</code> attribute.</p>
@@ -707,7 +707,7 @@ FINE: Request "/docs/config/manager.html" with response status "200" content-typ
        &lt;filter-class&gt;org.apache.catalina.filters.RemoteIpFilter&lt;/filter-class&gt;
        &lt;init-param&gt;
          &lt;param-name&gt;allowedInternalProxies&lt;/param-name&gt;
-         &lt;param-value&gt;192\.168\.0\.10192\.168\.0\.11&lt;/param-value&gt;
+         &lt;param-value&gt;192\.168\.0\.10|192\.168\.0\.11&lt;/param-value&gt;
        &lt;/init-param&gt;
        &lt;init-param&gt;
          &lt;param-name&gt;remoteIpHeader&lt;/param-name&gt;
@@ -784,7 +784,7 @@ FINE: Request "/docs/config/manager.html" with response status "200" content-typ
        &lt;filter-class&gt;org.apache.catalina.filters.RemoteIpFilter&lt;/filter-class&gt;
        &lt;init-param&gt;
          &lt;param-name&gt;allowedInternalProxies&lt;/param-name&gt;
-         &lt;param-value&gt;192\.168\.0\.10192\.168\.0\.11&lt;/param-value&gt;
+         &lt;param-value&gt;192\.168\.0\.10|192\.168\.0\.11&lt;/param-value&gt;
        &lt;/init-param&gt;
        &lt;init-param&gt;
          &lt;param-name&gt;remoteIpHeader&lt;/param-name&gt;
@@ -839,7 +839,7 @@ FINE: Request "/docs/config/manager.html" with response status "200" content-typ
        &lt;filter-class&gt;org.apache.catalina.filters.RemoteIpFilter&lt;/filter-class&gt;
        &lt;init-param&gt;
          &lt;param-name&gt;allowedInternalProxies&lt;/param-name&gt;
-         &lt;param-value&gt;192\.168\.0\.10192\.168\.0\.11&lt;/param-value&gt;
+         &lt;param-value&gt;192\.168\.0\.10|192\.168\.0\.11&lt;/param-value&gt;
        &lt;/init-param&gt;
        &lt;init-param&gt;
          &lt;param-name&gt;remoteIpHeader&lt;/param-name&gt;
@@ -897,7 +897,7 @@ FINE: Request "/docs/config/manager.html" with response status "200" content-typ
        &lt;filter-class&gt;org.apache.catalina.filters.RemoteIpFilter&lt;/filter-class&gt;
        &lt;init-param&gt;
          &lt;param-name&gt;allowedInternalProxies&lt;/param-name&gt;
-         &lt;param-value&gt;192\.168\.0\.10192\.168\.0\.11&lt;/param-value&gt;
+         &lt;param-value&gt;192\.168\.0\.10|192\.168\.0\.11&lt;/param-value&gt;
        &lt;/init-param&gt;
        &lt;init-param&gt;
          &lt;param-name&gt;remoteIpHeader&lt;/param-name&gt;
@@ -960,13 +960,13 @@ FINE: Request "/docs/config/manager.html" with response status "200" content-typ
       </attribute>
 
       <attribute name="internalProxies" required="false">
-        <p>List of internal proxies' IP addresses as comma separated regular
-        expressions. If they appear in the <strong>remoteIpHeader</strong>
-        value, they will be trusted and will not appear in the
-        <strong>proxiesHeader</strong> value. If not specified the default value
-        of <code>10\.\d{1,3}\.\d{1,3}\.\d{1,3}, 192\.168\.\d{1,3}\.\d{1,3},
-        169\.254\.\d{1,3}\.\d{1,3}, 127\.\d{1,3}\.\d{1,3}\.\d{1,3}</code> will
-        be used.</p>
+        <p>Regular expression (using <code>java.util.regex</code>) that a
+        proxy&apos;s IP address must match to be considered an internal proxy.
+        Internal proxies that appear in the <strong>remoteIpHeader</strong> will
+        be trusted and will not appear in the <strong>proxiesHeader</strong>
+        value. If not specified the default value of <code>
+        10\.\d{1,3}\.\d{1,3}\.\d{1,3}|192\.168\.\d{1,3}\.\d{1,3}|169\.254\.\d{1,3}\.\d{1,3}|127\.\d{1,3}\.\d{1,3}\.\d{1,3}
+        </code> will be used.</p>
       </attribute>
 
       <attribute name="proxiesHeader" required="false">
@@ -977,11 +977,11 @@ FINE: Request "/docs/config/manager.html" with response status "200" content-typ
       </attribute>
 
       <attribute name="trustedProxies" required="false">
-        <p>List of trusted proxies' IP addresses as comma separated regular
-        expressions. If they appear in the <strong>remoteIpHeader</strong>
-        value, they will be trusted and will appear in the
-        <strong>proxiesHeader</strong> value. If not specified, no proxies will
-        be trusted.</p>
+        <p>Regular expression (using <code>java.util.regex</code>) that a
+        proxy&apos;s IP address must match to be considered an trusted proxy.
+        Trusted proxies that appear in the <strong>remoteIpHeader</strong> will
+        be trusted and will appear in the <strong>proxiesHeader</strong> value.
+        If not specified, no proxies will be trusted.</p>
       </attribute>
 
       <attribute name="protocolHeader" required="false">
index 88e5c29..a1e43c7 100644 (file)
       </attribute>
 
       <attribute name="allow" required="false">
-        <p>A comma-separated list of <em>regular expression</em> patterns
-        that the remote client's IP address is compared to.  If this attribute
+        <p>A regular expression (using <code>java.util.Regex</code>) that the
+        remote client&apos;s IP address is compared to.  If this attribute
         is specified, the remote address MUST match for this request to be
         accepted.  If this attribute is not specified, all requests will be
         accepted UNLESS the remote address matches a <code>deny</code>
       </attribute>
 
       <attribute name="deny" required="false">
-        <p>A comma-separated list of <em>regular expression</em> patterns
-        that the remote client's IP address is compared to.  If this attribute
+        <p>A regular expression (using <code>java.util.Regex</code>) that the
+        remote client's IP address is compared to.  If this attribute
         is specified, the remote address MUST NOT match for this request to be
         accepted.  If this attribute is not specified, request acceptance is
         governed solely by the <code>accept</code> attribute.</p>
       </attribute>
 
       <attribute name="allow" required="false">
-        <p>A comma-separated list of <em>regular expression</em> patterns
-        that the remote client's hostname is compared to.  If this attribute
+        <p>A regular expression (using <code>java.util.Regex</code>) that the
+        remote client&apos;s hostname is compared to.  If this attribute
         is specified, the remote hostname MUST match for this request to be
         accepted.  If this attribute is not specified, all requests will be
         accepted UNLESS the remote hostname matches a <code>deny</code>
       </attribute>
 
       <attribute name="deny" required="false">
-        <p>A comma-separated list of <em>regular expression</em> patterns
-        that the remote client's hostname is compared to.  If this attribute
+        <p>A regular expression (using <code>java.util.Regex</code>) that the
+        remote client's hostname is compared to.  If this attribute
         is specified, the remote hostname MUST NOT match for this request to be
         accepted.  If this attribute is not specified, request acceptance is
         governed solely by the <code>accept</code> attribute.</p>
       </attribute>
 
       <attribute name="internalProxies" required="false">
-        <p>List of internal proxies' IP addresses as comma separated regular
-        expressions. If they appear in the <strong>remoteIpHeader</strong>
-        value, they will be trusted and will not appear in the
-        <strong>proxiesHeader</strong> value. If not specified the default value
-        of <code>10\.\d{1,3}\.\d{1,3}\.\d{1,3}, 192\.168\.\d{1,3}\.\d{1,3},
-        169\.254\.\d{1,3}\.\d{1,3}, 127\.\d{1,3}\.\d{1,3}\.\d{1,3}</code> will
-        be used.</p>
+        <p>Regular expression (using <code>java.util.regex</code>) that a
+        proxy&apos;s IP address must match to be considered an internal proxy.
+        Internal proxies that appear in the <strong>remoteIpHeader</strong> will
+        be trusted and will not appear in the <strong>proxiesHeader</strong>
+        value. If not specified the default value of <code>
+        10\.\d{1,3}\.\d{1,3}\.\d{1,3}|192\.168\.\d{1,3}\.\d{1,3}|169\.254\.\d{1,3}\.\d{1,3}|127\.\d{1,3}\.\d{1,3}\.\d{1,3}
+        </code> will be used.</p>
       </attribute>
 
       <attribute name="proxiesHeader" required="false">
       </attribute>
 
       <attribute name="trustedProxies" required="false">
-        <p>List of trusted proxies' IP addresses as comma separated regular
-        expressions. If they appear in the <strong>remoteIpHeader</strong>
-        value, they will be trusted and will appear in the
-        <strong>proxiesHeader</strong> value. If not specified, no proxies will
-        be trusted.</p>
+        <p>Regular expression (using <code>java.util.regex</code>) that a
+        proxy&apos;s IP address must match to be considered an trusted proxy.
+        Trusted proxies that appear in the <strong>remoteIpHeader</strong> will
+        be trusted and will appear in the <strong>proxiesHeader</strong> value.
+        If not specified, no proxies will be trusted.</p>
       </attribute>
 
       <attribute name="protocolHeader" required="false">