From dbc714e1878a87fb5fad355ac7d229abd72d441c Mon Sep 17 00:00:00 2001 From: maxcooper Date: Tue, 17 Dec 2002 15:09:55 +0000 Subject: [PATCH] switched to thread safe implementation using Jakarta-ORO fixed various pattern matching bugs redirects are now URL-encoded --- .../org/securityfilter/filter/SecurityFilter.java | 94 +++--- .../{MatchableURLPattern.java => URLPattern.java} | 321 +++++++++++---------- ...LPatternFactory.java => URLPatternFactory.java} | 44 +-- .../securityfilter/filter/URLPatternMatcher.java | 114 ++++++++ 4 files changed, 358 insertions(+), 215 deletions(-) rename src/share/org/securityfilter/filter/{MatchableURLPattern.java => URLPattern.java} (62%) rename src/share/org/securityfilter/filter/{MatchableURLPatternFactory.java => URLPatternFactory.java} (74%) create mode 100644 src/share/org/securityfilter/filter/URLPatternMatcher.java diff --git a/src/share/org/securityfilter/filter/SecurityFilter.java b/src/share/org/securityfilter/filter/SecurityFilter.java index 8aa21a5..fb8b2a4 100644 --- a/src/share/org/securityfilter/filter/SecurityFilter.java +++ b/src/share/org/securityfilter/filter/SecurityFilter.java @@ -1,7 +1,7 @@ /* - * $Header: /cvsroot/securityfilter/securityfilter/src/share/org/securityfilter/filter/SecurityFilter.java,v 1.9 2002/12/09 10:17:12 maxcooper Exp $ - * $Revision: 1.9 $ - * $Date: 2002/12/09 10:17:12 $ + * $Header: /cvsroot/securityfilter/securityfilter/src/share/org/securityfilter/filter/SecurityFilter.java,v 1.10 2002/12/17 15:10:00 maxcooper Exp $ + * $Revision: 1.10 $ + * $Date: 2002/12/17 15:10:00 $ * * ==================================================================== * The SecurityFilter Software License, Version 1.1 @@ -55,9 +55,6 @@ package org.securityfilter.filter; -import org.apache.regexp.RE; -import org.apache.regexp.RECompiler; -import org.apache.regexp.RESyntaxException; import org.securityfilter.config.AuthConstraint; import org.securityfilter.config.SecurityConfig; import org.securityfilter.config.SecurityConstraint; @@ -78,7 +75,7 @@ import java.util.*; * * @author Max Cooper (max@maxcooper.com) * @author Torgeir Veimo (torgeir@pobox.com) - * @version $Revision: 1.9 $ $Date: 2002/12/09 10:17:12 $ + * @version $Revision: 1.10 $ $Date: 2002/12/17 15:10:00 $ */ public class SecurityFilter implements Filter { public static final String SAVED_REQUEST_URL = SecurityFilter.class.getName() + ".SAVED_REQUEST_URL"; @@ -90,17 +87,18 @@ public class SecurityFilter implements Filter { public static final String VALIDATE_KEY = "validate"; public static final String TRUE = "true"; - private FilterConfig config; - private SecurityRealmInterface realm; - private String loginPage; - private String errorPage; - private String defaultPage; - private RE loginSubmitRE; - private List patternList; + protected FilterConfig config; + protected SecurityRealmInterface realm; + protected String loginPage; + protected String errorPage; + protected String defaultPage; + protected URLPatternFactory patternFactory; + protected URLPattern loginSubmitPattern; + protected List patternList; - private static final String FORM_USERNAME = "j_username"; - private static final String FORM_PASSWORD = "j_password"; - private static final String FORM_SUBMIT_PATTERN = ".*/j_security_check"; + protected static final String FORM_USERNAME = "j_username"; + protected static final String FORM_PASSWORD = "j_password"; + protected static final String FORM_SUBMIT_PATTERN = "*/j_security_check"; /** * Perform filtering operation, and optionally pass the request down the chain. @@ -126,6 +124,9 @@ public class SecurityFilter implements Filter { // set an attribute on this request to indicate that it has already been processed request.setAttribute(ALREADY_PROCESSED, "true"); + // get a URLPatternMatcher to use for this thread + URLPatternMatcher patternMatcher = patternFactory.createURLPatternMatcher(); + // get the part of the URL to check for matches String requestURL = getMatchableURL(hReq); @@ -135,14 +136,19 @@ public class SecurityFilter implements Filter { // wrap request wrappedRequest = new SecurityRequestWrapper(hReq, realm, savedRequest); - // check if this is a login form submittal - if (loginSubmitRE.match(requestURL)) { - processLogin(wrappedRequest, hRes); - return; - } + URLPattern match = null; + try { + // check if this is a login form submittal + if (patternMatcher.match(requestURL, loginSubmitPattern)) { + processLogin(wrappedRequest, hRes); + return; + } - // check if request matches security constraint - MatchableURLPattern match = matchPattern(requestURL, wrappedRequest.getMethod()); + // check if request matches security constraint + match = matchPattern(requestURL, wrappedRequest.getMethod(), patternMatcher); + } catch (Exception e) { + throw new ServletException("Error matching patterns", e); + } // check security constraint, if any if (match != null) { @@ -189,11 +195,17 @@ public class SecurityFilter implements Filter { * * @param config filter configuration object */ - public void init(FilterConfig config) { + public void init(FilterConfig config) throws ServletException { this.config = config; try { + patternFactory = new URLPatternFactory(); + // login submit RE - loginSubmitRE = new RE(new RECompiler().compile(FORM_SUBMIT_PATTERN)); + try { + loginSubmitPattern = patternFactory.createURLPattern(FORM_SUBMIT_PATTERN, null, null, 0); + } catch (Exception e) { + throw new ServletException("Error creating login submit pattern", e); + } // parse config file String configFile = config.getInitParameter(CONFIG_FILE_KEY); @@ -213,7 +225,6 @@ public class SecurityFilter implements Filter { // create pattern list patternList = new ArrayList(); - MatchableURLPatternFactory patternFactory = new MatchableURLPatternFactory(); int order = 1; List constraints = securityConfig.getSecurityConstraints(); for (Iterator cIter = constraints.iterator(); cIter.hasNext();) { @@ -221,7 +232,7 @@ public class SecurityFilter implements Filter { for (Iterator rIter = constraint.getWebResourceCollections().iterator(); rIter.hasNext();) { WebResourceCollection resourceCollection = (WebResourceCollection) rIter.next(); for (Iterator pIter = resourceCollection.getURLPatterns().iterator(); pIter.hasNext();) { - MatchableURLPattern pattern = patternFactory.createMatchableURLPattern( + URLPattern pattern = patternFactory.createURLPattern( (String) pIter.next(), constraint, resourceCollection, @@ -233,12 +244,12 @@ public class SecurityFilter implements Filter { } Collections.sort(patternList); - } catch (RESyntaxException rese) { - System.err.println("invalid regular expression pattern: " + rese); } catch (java.io.IOException ioe) { System.err.println("unable to parse input: " + ioe); } catch (org.xml.sax.SAXException se) { System.err.println("unable to parse input: " + se); + } catch (Exception e) { + System.err.println("invalid regular expression pattern: " + e); } } @@ -253,7 +264,7 @@ public class SecurityFilter implements Filter { * * @param config filter configuration object */ - public void setFilterConfig(FilterConfig config) { + public void setFilterConfig(FilterConfig config) throws ServletException { init(config); } @@ -265,19 +276,20 @@ public class SecurityFilter implements Filter { } /** - * Find a match for the requested URL & method, if any. + * Find a match for the requested pattern & method, if any. * - * @param URL the URL to match + * @param pattern the pattern to match * @param httpMethod the HTTP Method to match - * @return the matching MatchableURLPattern object, or null if there is no match. + * @param matcher the thread-local URLPatternMatcher object + * @return the matching URLPattern object, or null if there is no match. */ - protected MatchableURLPattern matchPattern(String URL, String httpMethod) { - // PERFORMANCE IMPROVEMENT OPPORTUNITY: cahce URL pattern matches + protected URLPattern matchPattern(String pattern, String httpMethod, URLPatternMatcher matcher) throws Exception { + // PERFORMANCE IMPROVEMENT OPPORTUNITY: cahce pattern matches Iterator i = patternList.iterator(); while (i.hasNext()) { - MatchableURLPattern pattern = (MatchableURLPattern) i.next(); - if (pattern.match(URL, httpMethod)) { - return pattern; + URLPattern urlPattern = (URLPattern) i.next(); + if (matcher.match(pattern, httpMethod, urlPattern)) { + return urlPattern; } } return null; @@ -298,7 +310,7 @@ public class SecurityFilter implements Filter { // save this request saveRequestInformation(request); // redirect to login page - response.sendRedirect(request.getContextPath() + loginPage); + response.sendRedirect(response.encodeRedirectURL(request.getContextPath() + loginPage)); } /** @@ -320,7 +332,7 @@ public class SecurityFilter implements Filter { // login successful request.setUserPrincipal(principal); String continueToURL = getContinueToURL(request); - response.sendRedirect(continueToURL); + response.sendRedirect(response.encodeRedirectURL(continueToURL)); } else { // login failed, set response status and forward to error page response.setStatus(HttpServletResponse.SC_UNAUTHORIZED); diff --git a/src/share/org/securityfilter/filter/MatchableURLPattern.java b/src/share/org/securityfilter/filter/URLPattern.java similarity index 62% rename from src/share/org/securityfilter/filter/MatchableURLPattern.java rename to src/share/org/securityfilter/filter/URLPattern.java index 492f25c..940c1da 100644 --- a/src/share/org/securityfilter/filter/MatchableURLPattern.java +++ b/src/share/org/securityfilter/filter/URLPattern.java @@ -1,7 +1,7 @@ /* - * $Header: /cvsroot/securityfilter/securityfilter/src/share/org/securityfilter/filter/Attic/MatchableURLPattern.java,v 1.7 2002/12/10 05:02:18 maxcooper Exp $ - * $Revision: 1.7 $ - * $Date: 2002/12/10 05:02:18 $ + * $Header: /cvsroot/securityfilter/securityfilter/src/share/org/securityfilter/filter/URLPattern.java,v 1.1 2002/12/17 15:10:00 maxcooper Exp $ + * $Revision: 1.1 $ + * $Date: 2002/12/17 15:10:00 $ * * ==================================================================== * The SecurityFilter Software License, Version 1.1 @@ -55,84 +55,87 @@ package org.securityfilter.filter; -import org.apache.regexp.RE; -import org.apache.regexp.RECompiler; -import org.apache.regexp.RESyntaxException; +import org.apache.oro.text.regex.Pattern; +import org.apache.oro.text.regex.PatternCompiler; +import org.apache.oro.text.regex.Perl5Compiler; import org.securityfilter.config.SecurityConstraint; import org.securityfilter.config.WebResourceCollection; -import java.util.Collection; - /** - * MatchableURLPattern - Contains matchable URL pattern and the associated SecurityConstraint and WebResourceCollection - * objects for the pattern. Also supports sorting according to the Servlet Spec v2.3. + * URLPattern - Contains matchable URL pattern and the associated + * SecurityConstraint and WebResourceCollection objects for the pattern. + * Also supports sorting according to the Servlet Spec v2.3. * * @author Max Cooper (max@maxcooper.com) - * @version $Revision: 1.7 $ $Date: 2002/12/10 05:02:18 $ + * @version $Revision: 1.1 $ $Date: 2002/12/17 15:10:00 $ */ -public class MatchableURLPattern implements Comparable { - private String pattern; - private RE patternRE; - private SecurityConstraint constraint; - private WebResourceCollection resourceCollection; - private int order; - private int patternType; - private int pathLength; +public class URLPattern implements Comparable { + /** + * Pattern type for PATH_TYPE mappings. Starts with '/' and ends with '/*'. + */ + public static final int PATH_TYPE = 1; + /** + * Pattern type for EXTENSION_TYPE mappings. Starts with *. + */ + public static final int EXTENSION_TYPE = 2; + /** + * Pattern type for patterns that do not meet the PATH_TYPE + * or EXTENSION_TYPE pattern type specifications. + */ + public static final int EXACT_TYPE = 3; + + protected String pattern; + protected String convertedPattern; + protected Pattern compiledPattern; + protected SecurityConstraint constraint; + protected WebResourceCollection resourceCollection; + protected int order; + protected int patternType; + protected int pathLength; /** - * Construct a new MatchableURLPattern object. + * Construct a new URLPattern object. * * @param pattern the url pattern to match * @param constraint the SecurityConstraint associated with this pattern * @param resourceCollection the WebResourceCollection associated with this pattern * @param order the order in which this pattern occurred in the configuration file - * @param compiler an RECompiler to use to compile this url pattern + * @param compiler a PatternCompiler to use to compile this url pattern * - * @see MatchableURLPatternFactory + * @see URLPatternFactory */ - public MatchableURLPattern( + public URLPattern( String pattern, SecurityConstraint constraint, WebResourceCollection resourceCollection, int order, - RECompiler compiler - ) throws RESyntaxException { + PatternCompiler compiler + ) throws Exception { this.pattern = pattern; this.constraint = constraint; this.resourceCollection = resourceCollection; this.order = order; - init(compiler); + initPatternType(); + initPathLength(); + initConvertedPattern(); + initCompiledPattern(compiler); } /** - * Return true if this pattern matches the passed URL. - * - * @param URL the URL to attempt to match - * @param httpMethod the http method to attempt to match - * @return true if this pattern matches the URL, false otherwise + * Get the url pattern to match. */ - public boolean match(String URL, String httpMethod) { - if (patternRE.match(URL)) { - Collection methods = resourceCollection.getHttpMethods(); - if (methods.isEmpty() || methods.contains(httpMethod.toUpperCase())) { - return true; - } - } - return false; + public String getPattern() { + return pattern; } /** - * Pattern type for patterns that do not meet the PATH or EXTENSION pattern type specifications. - */ - public static final int EXACT = 1; - /** - * Pattern type for PATH mappings. Starts with '/' and ends with '/*'. - */ - public static final int PATH = 2; - /** - * Pattern type for PATH mappings + * Get the compiled version of this pattern. + * + * @return compiled version of this pattern */ - public static final int EXTENSION = 3; + public Pattern getCompiledPattern() { + return compiledPattern; + } /** * Get the pattern type. The pattern type will be determined on the first call to this method. @@ -144,10 +147,18 @@ public class MatchableURLPattern implements Comparable { } /** - * Get the url pattern to match. + * Get the path length of the pattern. This is only valid when getPatternType() = PATH.

+ * Examples: + *

+ * + * @return path length of this pattern */ - public String getPattern() { - return pattern; + public int getPathLength() { + return pathLength; } /** @@ -172,121 +183,34 @@ public class MatchableURLPattern implements Comparable { } /** - * Test if this pattern is equivalent to another pattern. - * This is implemented so that consistency with the compareTo method results can be maintained. - * - * @param obj the value to test equivalence with - * @return true if the passed object is an equivalent MatchableURLPattern, false if it is not a MatchableURLPattern - * or if it is not equivalent. - */ - public boolean equals(Object obj) { - if (obj instanceof MatchableURLPattern) { - MatchableURLPattern otherPattern = (MatchableURLPattern) obj; - return ( - constraint.equals(otherPattern.getSecurityConstraint()) - && resourceCollection.equals(otherPattern.getWebResourceCollection()) - && pattern.equals(otherPattern.getPattern()) - ); - } - return false; - } - - /** - * Compares this MatchableURLPattern to another to support sorting.

- * - * The sort order is dictated by the servlet spec. EXACT patterns are first, followed by PATH patterns, - * followed by EXTENTION patterns. Ordering among PATH patterns is determined by path length, with the - * longer path coming first. If the path lengths are the same, or both are EXACT or EXTENSION patterns, - * ordering is determined by the order in which the pattern appeared in the config file. - * - * @param another another MatchableURLPattern to compare to - * - * @return a negative integer, zero, or a positive integer as this object is less than, equal to, or greater - * than the specified object. - * - * @exception ClassCastException thrown if o is not a MatchableURLPattern instance + * Initialize the patternType protected member. */ - public int compareTo(Object another) throws ClassCastException { - MatchableURLPattern otherPattern = (MatchableURLPattern) another; - // if the patterns are equivalent, ordering priority is equal - if (this.equals(otherPattern)) { - return 0; + protected void initPatternType() { + if (pattern.startsWith("*.")) { + patternType = URLPattern.EXTENSION_TYPE; + } else if (pattern.startsWith("/") && pattern.endsWith("/*")) { + patternType = URLPattern.PATH_TYPE; } else { - int otherPatternType = otherPattern.getPatternType(); - // if the pattern types are the same - if (patternType == otherPatternType) { - // if the type is PATH - if (patternType == MatchableURLPattern.PATH) { - int otherPathLength = otherPattern.getPathLength(); - // if path lengths are different, the pattern with longer path length should be first - if (pathLength != otherPathLength) { - return (otherPathLength - pathLength); - // path length are the same, the pattern with the smaller order should be first - } else { - return (order - otherPattern.getOrder()); - } - // for EXACT or EXTENSION, the pattern with the smaller order should be first - } else { - return (order - otherPattern.getOrder()); - } - } else { - // pattern types are not the same, order should be EXACT, PATH, EXTENSION - return (patternType - otherPatternType); - } + patternType = URLPattern.EXACT_TYPE; } } /** - * Get the path length of the pattern. This is only valid when getPatternType() = PATH.

- * Examples: - *

- * - * @return path length of this pattern + * Initialize the pathLength protected member. */ - public int getPathLength() { - return pathLength; - } - - /** - * Initialize pattern-related internal variables. - * - * @param compiler an RECompiler - * - * @exception RESyntaxException - */ - private void init(RECompiler compiler) throws RESyntaxException { - // calculate the path length + protected void initPathLength() { pathLength = -1; int pos = pattern.indexOf('/'); while (pos != -1) { pathLength++; pos = pattern.indexOf('/', pos + 1); } - // determine the pattern type - if (pattern.startsWith("*.")) { - patternType = MatchableURLPattern.EXTENSION; - } else if (pattern.startsWith("/") && pattern.endsWith("/*")) { - patternType = MatchableURLPattern.PATH; - } else { - patternType = MatchableURLPattern.EXACT; - } - // initilize the patternRE - if (compiler == null) { - compiler = new RECompiler(); - } - patternRE = new RE(compiler.compile(getConvertedPattern())); } /** - * Return the pattern string in RE syntax form. - * - * Would the jakarta-oro be more suited for matching than jakarta-regexp? + * Initialize the convertedPattern protected member. */ - private String getConvertedPattern() { + protected void initConvertedPattern() { StringBuffer buf = new StringBuffer(pattern); int pos; // escape '.' characters @@ -295,30 +219,113 @@ public class MatchableURLPattern implements Comparable { buf.insert(pos, "\\"); pos = buf.toString().indexOf('.', pos + 2); } - // replace '*' chars in the pattern with '.*' + // replace '*' chars in the compiledPattern with '.*' pos = buf.toString().indexOf('*'); while (pos != -1) { buf.replace(pos, pos + 1, ".*"); pos = buf.toString().indexOf('*', pos + 2); } + // replace '/' chars with '/+' to match one or more consecutive slashes + pos = buf.toString().indexOf('/'); + while (pos != -1) { + buf.replace(pos, pos + 1, "/+"); + pos = buf.toString().indexOf('/', pos + 2); + } // adjustments for the different expression types switch (patternType) { - case PATH: + case PATH_TYPE: // make sure it matches from the start of the string buf.insert(0, '^'); // make sure /foo/* matches /foo and /foo/morestuff, but not /foobar - buf.insert(buf.length()-3, "($|"); - buf.append(")"); + buf.insert(buf.length()-4, "("); + buf.append(")?$"); break; - case EXTENSION: + case EXTENSION_TYPE: buf.append('$'); break; - case EXACT: + case EXACT_TYPE: buf.insert(0, '^'); buf.append('$'); break; } - return buf.toString(); + convertedPattern = buf.toString(); + } + + /** + * Initialize the compiledPattern protected member. + * + * @param compiler + * @throws Exception + */ + protected void initCompiledPattern(PatternCompiler compiler) throws Exception { + compiledPattern = compiler.compile(convertedPattern, Perl5Compiler.READ_ONLY_MASK); + } + + /** + * Test if this pattern is equivalent to another pattern. + * This is implemented so that consistency with the compareTo method results can be maintained. + * + * @param obj the value to test equivalence with + * @return true if the passed object is an equivalent URLPattern, false if it is not a URLPattern + * or if it is not equivalent. + */ + public boolean equals(Object obj) { + if (obj instanceof URLPattern) { + URLPattern otherPattern = (URLPattern) obj; + return ( + constraint.equals(otherPattern.getSecurityConstraint()) + && resourceCollection.equals(otherPattern.getWebResourceCollection()) + && pattern.equals(otherPattern.getPattern()) + ); + } + return false; + } + + /** + * Compares this URLPattern to another to support sorting.

+ * + * The sort order is dictated by the servlet spec. EXACT_TYPE patterns are first, + * followed by PATH_TYPE patterns, followed by EXTENTION_TYPE patterns. Ordering + * among PATH_TYPE patterns is determined by path length, with the longer path + * coming first. If the path lengths are the same, or both are EXACT_TYPE or + * EXTENSION_TYPE patterns, ordering is determined by the order in which the + * pattern appeared in the config file. + * + * @param another another URLPattern to compare to + * + * @return a negative integer, zero, or a positive integer as this object is + * less than, equal to, or greater than the specified object. + * + * @exception ClassCastException thrown if o is not a URLPattern instance + */ + public int compareTo(Object another) throws ClassCastException { + URLPattern otherPattern = (URLPattern) another; + // if the patterns are equivalent, ordering priority is equal + if (this.equals(otherPattern)) { + return 0; + } else { + int otherPatternType = otherPattern.getPatternType(); + // if the compiledPattern types are the same + if (patternType == otherPatternType) { + // if the type is PATH_TYPE + if (patternType == URLPattern.PATH_TYPE) { + int otherPathLength = otherPattern.getPathLength(); + // if path lengths are different, the compiledPattern with longer path length should be first + if (pathLength != otherPathLength) { + return (otherPathLength - pathLength); + // path length are the same, the compiledPattern with the smaller order should be first + } else { + return (order - otherPattern.getOrder()); + } + // for EXACT_TYPE or EXTENSION_TYPE, the compiledPattern with the smaller order should be first + } else { + return (order - otherPattern.getOrder()); + } + } else { + // compiledPattern types are not the same, order should be EXACT_TYPE, PATH_TYPE, EXTENSION_TYPE + return (patternType - otherPatternType); + } + } } } diff --git a/src/share/org/securityfilter/filter/MatchableURLPatternFactory.java b/src/share/org/securityfilter/filter/URLPatternFactory.java similarity index 74% rename from src/share/org/securityfilter/filter/MatchableURLPatternFactory.java rename to src/share/org/securityfilter/filter/URLPatternFactory.java index 51e8f99..d68e5ee 100644 --- a/src/share/org/securityfilter/filter/MatchableURLPatternFactory.java +++ b/src/share/org/securityfilter/filter/URLPatternFactory.java @@ -1,7 +1,7 @@ /* - * $Header: /cvsroot/securityfilter/securityfilter/src/share/org/securityfilter/filter/Attic/MatchableURLPatternFactory.java,v 1.4 2002/12/09 10:17:12 maxcooper Exp $ - * $Revision: 1.4 $ - * $Date: 2002/12/09 10:17:12 $ + * $Header: /cvsroot/securityfilter/securityfilter/src/share/org/securityfilter/filter/URLPatternFactory.java,v 1.1 2002/12/17 15:10:01 maxcooper Exp $ + * $Revision: 1.1 $ + * $Date: 2002/12/17 15:10:01 $ * * ==================================================================== * The SecurityFilter Software License, Version 1.1 @@ -55,45 +55,55 @@ package org.securityfilter.filter; -import org.apache.regexp.RECompiler; -import org.apache.regexp.RESyntaxException; +import org.apache.oro.text.regex.PatternCompiler; +import org.apache.oro.text.regex.Perl5Compiler; import org.securityfilter.config.SecurityConstraint; import org.securityfilter.config.WebResourceCollection; /** - * MatchableURLPatternFactory creates MatchableURLPattern instances. It keeps an RECompiler to use for the creation - * of a set of instances. + * URLPatternFactory creates URLPattern instances. It keeps a Perl5PatternCompiler to use + * for the creation of a set of instances. * * @author Max Cooper (max@maxcooper.com) - * @version $Revision: 1.4 $ $Date: 2002/12/09 10:17:12 $ + * @version $Revision: 1.1 $ $Date: 2002/12/17 15:10:01 $ */ -public class MatchableURLPatternFactory { - private RECompiler compiler; +public class URLPatternFactory { + protected PatternCompiler compiler; /** * Constructor */ - public MatchableURLPatternFactory() { - compiler = new RECompiler(); + public URLPatternFactory() { + compiler = new Perl5Compiler(); } /** - * Create a MatchableURLPattern instance. + * Create a URLPatternMatcher object that is compatible with the URLPattern + * objects created by this Facotry class. + * + * @return a URLPatternMatcher object compatible with the URLPatterns created by this class + */ + public URLPatternMatcher createURLPatternMatcher() { + return new URLPatternMatcher(); + } + + /** + * Create a URLPattern instance. * * @param pattern url pattern in config file syntax * @param constraint SecurityConstraint object to associate with this pattern * @param resourceCollection WebResourceCollection to associate with this pattern * @param order order in which this pattern appeared in the config file * - * @exception RESyntaxException throws exception if pattern cannot be compiled after conversion to RE syntax + * @exception Exception */ - public MatchableURLPattern createMatchableURLPattern( + public URLPattern createURLPattern( String pattern, SecurityConstraint constraint, WebResourceCollection resourceCollection, int order - ) throws RESyntaxException { - return new MatchableURLPattern(pattern, constraint, resourceCollection, order, compiler); + ) throws Exception { + return new URLPattern(pattern, constraint, resourceCollection, order, compiler); } } diff --git a/src/share/org/securityfilter/filter/URLPatternMatcher.java b/src/share/org/securityfilter/filter/URLPatternMatcher.java new file mode 100644 index 0000000..c5307a9 --- /dev/null +++ b/src/share/org/securityfilter/filter/URLPatternMatcher.java @@ -0,0 +1,114 @@ +/* + * $Header: /cvsroot/securityfilter/securityfilter/src/share/org/securityfilter/filter/URLPatternMatcher.java,v 1.1 2002/12/17 15:10:01 maxcooper Exp $ + * $Revision: 1.1 $ + * $Date: 2002/12/17 15:10:01 $ + * + * ==================================================================== + * The SecurityFilter Software License, Version 1.1 + * + * (this license is derived and fully compatible with the Apache Software + * License - see http://www.apache.org/LICENSE.txt) + * + * Copyright (c) 2002 SecurityFilter.org. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, + * if any, must include the following acknowledgment: + * "This product includes software developed by + * SecurityFilter.org (http://www.securityfilter.org/)." + * Alternately, this acknowledgment may appear in the software itself, + * if and wherever such third-party acknowledgments normally appear. + * + * 4. The name "SecurityFilter" must not be used to endorse or promote + * products derived from this software without prior written permission. + * For written permission, please contact license@securityfilter.org . + * + * 5. Products derived from this software may not be called "SecurityFilter", + * nor may "SecurityFilter" appear in their name, without prior written + * permission of SecurityFilter.org. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + */ + +package org.securityfilter.filter; + +import org.apache.oro.text.regex.PatternMatcher; +import org.apache.oro.text.regex.Perl5Matcher; + +import java.util.Collection; + +/** + * URLPatternMatcher - A non-thread safe object to be used to match a request + * pattern with URLPattern objects. + * + * @author Max Cooper (max@maxcooper.com) + * @version $Revision: 1.1 $ $Date: 2002/12/17 15:10:01 $ + */ +public class URLPatternMatcher { + private PatternMatcher patternMatcher; + + /** + * Constructor + */ + public URLPatternMatcher() { + patternMatcher = new Perl5Matcher(); + } + + /** + * Test to see if a string pattern matches a URLPattern. + * + * @param pattern a String pattern to check for a match + * @param urlPattern a URLPattern object to match against + * @return true if the pattern matched the urlPattern, false otherwise + * @throws Exception + */ + public boolean match(String pattern, URLPattern urlPattern) throws Exception { + return patternMatcher.matches(pattern, urlPattern.getCompiledPattern()); + } + + /** + * Test to see if a string pattern and HTTP method matches a URLPattern. + * + * @param pattern a String pattern to check for a match + * @param httpMethod an HTTP pattern to check for a match + * @param urlPattern a URLPattern object to match against + * @return true if the pattern matched the urlPattern, false otherwise + * @throws Exception + */ + public boolean match(String pattern, String httpMethod, URLPattern urlPattern) throws Exception { + if (match(pattern, urlPattern)) { + Collection methods = urlPattern.getWebResourceCollection().getHttpMethods(); + if (methods.isEmpty() || methods.contains(httpMethod.toUpperCase())) { + + return true; + } + } + return false; + } +} + +// ---------------------------------------------------------------------------- +// EOF -- 2.11.0