diff --git a/core/src/main/java/org/apache/shiro/util/RegExPatternMatcher.java b/core/src/main/java/org/apache/shiro/util/RegExPatternMatcher.java index b251ac50b6..b07ce3d03a 100644 --- a/core/src/main/java/org/apache/shiro/util/RegExPatternMatcher.java +++ b/core/src/main/java/org/apache/shiro/util/RegExPatternMatcher.java @@ -29,12 +29,18 @@ */ public class RegExPatternMatcher implements PatternMatcher { + private static final int DEFAULT = Pattern.DOTALL; + + private static final int CASE_INSENSITIVE = DEFAULT | Pattern.CASE_INSENSITIVE; + + private boolean caseInsensitive = false; + /** * Simple implementation that merely uses the default pattern comparison logic provided by the * JDK. *

This implementation essentially executes the following: *

-     * Pattern p = Pattern.compile(pattern);
+     * Pattern p = Pattern.compile(pattern, Pattern.DOTALL);
      * Matcher m = p.matcher(source);
      * return m.matches();
* @param pattern the pattern to match against @@ -45,8 +51,24 @@ public boolean matches(String pattern, String source) { if (pattern == null) { throw new IllegalArgumentException("pattern argument cannot be null."); } - Pattern p = Pattern.compile(pattern); + Pattern p = Pattern.compile(pattern, caseInsensitive ? CASE_INSENSITIVE : DEFAULT); Matcher m = p.matcher(source); return m.matches(); } + + /** + * Returns true if regex match should be case-insensitive. + * @return true if regex match should be case-insensitive. + */ + public boolean isCaseInsensitive() { + return caseInsensitive; + } + + /** + * Adds the Pattern.CASE_INSENSITIVE flag when compiling patterns. + * @param caseInsensitive true if patterns should match case-insensitive. + */ + public void setCaseInsensitive(boolean caseInsensitive) { + this.caseInsensitive = caseInsensitive; + } } diff --git a/core/src/test/java/org/apache/shiro/util/RegExPatternMatcherTest.java b/core/src/test/java/org/apache/shiro/util/RegExPatternMatcherTest.java index 5246ba6098..dc42368def 100644 --- a/core/src/test/java/org/apache/shiro/util/RegExPatternMatcherTest.java +++ b/core/src/test/java/org/apache/shiro/util/RegExPatternMatcherTest.java @@ -21,8 +21,6 @@ import org.junit.Test; import static org.junit.Assert.*; -import java.util.regex.Pattern; - /** * Unit tests for the {@link RegExPatternMatcher}. * @@ -32,12 +30,44 @@ public class RegExPatternMatcherTest { @Test public void testSimplePattern() { - PatternMatcher pm = new RegExPatternMatcher(); - String pattern = "a*b"; - String test = "aaaaaaab"; - //not necessary for the test, but Idea performs auto validation when it sees this: - Pattern.compile(pattern); - assertTrue(pm.matches(pattern, test)); + assertPatternMatch("a*b", "aaaaaaab"); + } + + @Test + public void testMatchesWithCarriageReturn() { + assertPatternMatch(".*", "/blah\n"); + } + + @Test + public void testMatchesWithLineFeed() { + assertPatternMatch(".*", "/blah\r"); + } + + @Test + public void testCaseInsensitive() { + RegExPatternMatcher pm = new RegExPatternMatcher(); + pm.setCaseInsensitive(true); + assertPatternMatch("/blah", "/BlaH", pm); } + @Test + public void testCaseSensitive() { + assertPatternNotMatch("/blah", "/BlaH"); + } + + private void assertPatternMatch(String pattern, String path) { + assertPatternMatch(pattern, path, new RegExPatternMatcher()); + } + + private void assertPatternMatch(String pattern, String path, PatternMatcher pm) { + assertTrue("Expected path '" + path + "' to match pattern '" + pattern + "'" , pm.matches(pattern, path)); + } + + private void assertPatternNotMatch(String pattern, String path) { + assertPatternNotMatch(pattern, path, new RegExPatternMatcher()); + } + + private void assertPatternNotMatch(String pattern, String path, PatternMatcher pm) { + assertFalse("Expected path '" + path + "' to NOT match pattern '" + pattern + "'" , pm.matches(pattern, path)); + } }