+++ /dev/null
-/*
- * $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 $
- *
- * ====================================================================
- * 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.regexp.RE;
-import org.apache.regexp.RECompiler;
-import org.apache.regexp.RESyntaxException;
-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.
- *
- * @author Max Cooper (max@maxcooper.com)
- * @version $Revision: 1.7 $ $Date: 2002/12/10 05:02:18 $
- */
-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;
-
- /**
- * Construct a new MatchableURLPattern 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
- *
- * @see MatchableURLPatternFactory
- */
- public MatchableURLPattern(
- String pattern,
- SecurityConstraint constraint,
- WebResourceCollection resourceCollection,
- int order,
- RECompiler compiler
- ) throws RESyntaxException {
- this.pattern = pattern;
- this.constraint = constraint;
- this.resourceCollection = resourceCollection;
- this.order = order;
- init(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
- */
- 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;
- }
-
- /**
- * 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
- */
- public static final int EXTENSION = 3;
-
- /**
- * Get the pattern type. The pattern type will be determined on the first call to this method.
- *
- * @return EXACT, PATH, or EXTENSION
- */
- public int getPatternType() {
- return patternType;
- }
-
- /**
- * Get the url pattern to match.
- */
- public String getPattern() {
- return pattern;
- }
-
- /**
- * Get the SecurityConstraint object associated with this pattern.
- */
- public SecurityConstraint getSecurityConstraint() {
- return constraint;
- }
-
- /**
- * Get the order value for this pattern (the order in which it appeared in the config file).
- */
- public int getOrder() {
- return order;
- }
-
- /**
- * Get the WebResourceCollection associated with this pattern.
- */
- public WebResourceCollection getWebResourceCollection() {
- return resourceCollection;
- }
-
- /**
- * 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.<p>
- *
- * 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
- */
- 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;
- } 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);
- }
- }
- }
-
- /**
- * Get the path length of the pattern. This is only valid when getPatternType() = PATH.<p>
- * Examples:
- * <ul>
- * <li>/* = 0</li>
- * <li>/path/* = 1</li>
- * <li>/really/long/path/* = 3</li>
- * </ul>
- *
- * @return path length of this pattern
- */
- 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
- 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?
- */
- private String getConvertedPattern() {
- StringBuffer buf = new StringBuffer(pattern);
- int pos;
- // escape '.' characters
- pos = buf.toString().indexOf('.');
- while (pos != -1) {
- buf.insert(pos, "\\");
- pos = buf.toString().indexOf('.', pos + 2);
- }
- // replace '*' chars in the pattern with '.*'
- 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:
- // 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(")");
- break;
- case EXTENSION:
- buf.append('$');
- break;
- case EXACT:
- buf.insert(0, '^');
- buf.append('$');
- break;
- }
- return buf.toString();
- }
-}
-
-// ----------------------------------------------------------------------------
-// EOF
+++ /dev/null
-/*
- * $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 $
- *
- * ====================================================================
- * 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.regexp.RECompiler;
-import org.apache.regexp.RESyntaxException;
-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.
- *
- * @author Max Cooper (max@maxcooper.com)
- * @version $Revision: 1.4 $ $Date: 2002/12/09 10:17:12 $
- */
-public class MatchableURLPatternFactory {
- private RECompiler compiler;
-
- /**
- * Constructor
- */
- public MatchableURLPatternFactory() {
- compiler = new RECompiler();
- }
-
- /**
- * Create a MatchableURLPattern 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
- */
- public MatchableURLPattern createMatchableURLPattern(
- String pattern,
- SecurityConstraint constraint,
- WebResourceCollection resourceCollection,
- int order
- ) throws RESyntaxException {
- return new MatchableURLPattern(pattern, constraint, resourceCollection, order, compiler);
- }
-}
-
-// ----------------------------------------------------------------------------
-// EOF
/*
- * $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
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;
*
* @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";
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.
// 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);
// 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) {
*
* @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);
// create pattern list
patternList = new ArrayList();
- MatchableURLPatternFactory patternFactory = new MatchableURLPatternFactory();
int order = 1;
List constraints = securityConfig.getSecurityConstraints();
for (Iterator cIter = constraints.iterator(); cIter.hasNext();) {
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,
}
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);
}
}
*
* @param config filter configuration object
*/
- public void setFilterConfig(FilterConfig config) {
+ public void setFilterConfig(FilterConfig config) throws ServletException {
init(config);
}
}
/**
- * 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;
// save this request
saveRequestInformation(request);
// redirect to login page
- response.sendRedirect(request.getContextPath() + loginPage);
+ response.sendRedirect(response.encodeRedirectURL(request.getContextPath() + loginPage));
}
/**
// 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);
--- /dev/null
+/*
+ * $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
+ *
+ * (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.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;
+
+/**
+ * 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.1 $ $Date: 2002/12/17 15:10:00 $
+ */
+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 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 a PatternCompiler to use to compile this url pattern
+ *
+ * @see URLPatternFactory
+ */
+ public URLPattern(
+ String pattern,
+ SecurityConstraint constraint,
+ WebResourceCollection resourceCollection,
+ int order,
+ PatternCompiler compiler
+ ) throws Exception {
+ this.pattern = pattern;
+ this.constraint = constraint;
+ this.resourceCollection = resourceCollection;
+ this.order = order;
+ initPatternType();
+ initPathLength();
+ initConvertedPattern();
+ initCompiledPattern(compiler);
+ }
+
+ /**
+ * Get the url pattern to match.
+ */
+ public String getPattern() {
+ return pattern;
+ }
+
+ /**
+ * Get the compiled version of this pattern.
+ *
+ * @return compiled version of this pattern
+ */
+ public Pattern getCompiledPattern() {
+ return compiledPattern;
+ }
+
+ /**
+ * Get the pattern type. The pattern type will be determined on the first call to this method.
+ *
+ * @return EXACT, PATH, or EXTENSION
+ */
+ public int getPatternType() {
+ return patternType;
+ }
+
+ /**
+ * Get the path length of the pattern. This is only valid when getPatternType() = PATH.<p>
+ * Examples:
+ * <ul>
+ * <li>/* = 0</li>
+ * <li>/path/* = 1</li>
+ * <li>/really/long/path/* = 3</li>
+ * </ul>
+ *
+ * @return path length of this pattern
+ */
+ public int getPathLength() {
+ return pathLength;
+ }
+
+ /**
+ * Get the SecurityConstraint object associated with this pattern.
+ */
+ public SecurityConstraint getSecurityConstraint() {
+ return constraint;
+ }
+
+ /**
+ * Get the order value for this pattern (the order in which it appeared in the config file).
+ */
+ public int getOrder() {
+ return order;
+ }
+
+ /**
+ * Get the WebResourceCollection associated with this pattern.
+ */
+ public WebResourceCollection getWebResourceCollection() {
+ return resourceCollection;
+ }
+
+ /**
+ * Initialize the patternType protected member.
+ */
+ protected void initPatternType() {
+ if (pattern.startsWith("*.")) {
+ patternType = URLPattern.EXTENSION_TYPE;
+ } else if (pattern.startsWith("/") && pattern.endsWith("/*")) {
+ patternType = URLPattern.PATH_TYPE;
+ } else {
+ patternType = URLPattern.EXACT_TYPE;
+ }
+ }
+
+ /**
+ * Initialize the pathLength protected member.
+ */
+ protected void initPathLength() {
+ pathLength = -1;
+ int pos = pattern.indexOf('/');
+ while (pos != -1) {
+ pathLength++;
+ pos = pattern.indexOf('/', pos + 1);
+ }
+ }
+
+ /**
+ * Initialize the convertedPattern protected member.
+ */
+ protected void initConvertedPattern() {
+ StringBuffer buf = new StringBuffer(pattern);
+ int pos;
+ // escape '.' characters
+ pos = buf.toString().indexOf('.');
+ while (pos != -1) {
+ buf.insert(pos, "\\");
+ pos = buf.toString().indexOf('.', pos + 2);
+ }
+ // 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_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()-4, "(");
+ buf.append(")?$");
+ break;
+ case EXTENSION_TYPE:
+ buf.append('$');
+ break;
+ case EXACT_TYPE:
+ buf.insert(0, '^');
+ buf.append('$');
+ break;
+ }
+ 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.<p>
+ *
+ * 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);
+ }
+ }
+ }
+}
+
+// ----------------------------------------------------------------------------
+// EOF
--- /dev/null
+/*
+ * $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
+ *
+ * (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.PatternCompiler;
+import org.apache.oro.text.regex.Perl5Compiler;
+import org.securityfilter.config.SecurityConstraint;
+import org.securityfilter.config.WebResourceCollection;
+
+/**
+ * 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.1 $ $Date: 2002/12/17 15:10:01 $
+ */
+public class URLPatternFactory {
+ protected PatternCompiler compiler;
+
+ /**
+ * Constructor
+ */
+ public URLPatternFactory() {
+ compiler = new Perl5Compiler();
+ }
+
+ /**
+ * 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 Exception
+ */
+ public URLPattern createURLPattern(
+ String pattern,
+ SecurityConstraint constraint,
+ WebResourceCollection resourceCollection,
+ int order
+ ) throws Exception {
+ return new URLPattern(pattern, constraint, resourceCollection, order, compiler);
+ }
+}
+
+// ----------------------------------------------------------------------------
+// EOF
--- /dev/null
+/*
+ * $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