This is an automated email from the ASF dual-hosted git repository. markt pushed a commit to branch 10.1.x in repository https://gitbox.apache.org/repos/asf/tomcat.git
commit 5f6f162f2764f3c710ba2c47b5b167fcb3e9d975 Author: Mark Thomas <ma...@apache.org> AuthorDate: Mon May 20 08:17:30 2024 +0100 Code clean-up - formatting. No functional change. --- .../valves/rewrite/QuotedStringTokenizer.java | 48 ++--- .../valves/rewrite/RandomizedTextRewriteMap.java | 9 +- .../catalina/valves/rewrite/ResolverImpl.java | 39 ++-- .../catalina/valves/rewrite/RewriteCond.java | 39 ++-- .../apache/catalina/valves/rewrite/RewriteMap.java | 25 +-- .../catalina/valves/rewrite/RewriteRule.java | 209 ++++++++++++--------- .../catalina/valves/rewrite/RewriteValve.java | 106 +++++------ .../catalina/valves/rewrite/Substitution.java | 59 +++--- 8 files changed, 281 insertions(+), 253 deletions(-) diff --git a/java/org/apache/catalina/valves/rewrite/QuotedStringTokenizer.java b/java/org/apache/catalina/valves/rewrite/QuotedStringTokenizer.java index a6204fb077..0d39915c00 100644 --- a/java/org/apache/catalina/valves/rewrite/QuotedStringTokenizer.java +++ b/java/org/apache/catalina/valves/rewrite/QuotedStringTokenizer.java @@ -32,7 +32,11 @@ public class QuotedStringTokenizer { private int returnedTokens = 0; enum WordMode { - SPACES, QUOTED, ESCAPED, SIMPLE, COMMENT + SPACES, + QUOTED, + ESCAPED, + SIMPLE, + COMMENT } public QuotedStringTokenizer(String text) { @@ -55,27 +59,27 @@ public class QuotedStringTokenizer { while (pos < length) { char currentChar = inputText.charAt(pos); switch (currentMode) { - case SPACES: - currentMode = handleSpaces(currentToken, currentChar); - break; - case QUOTED: - currentMode = handleQuoted(tokens, currentToken, currentChar); - break; - case ESCAPED: - currentToken.append(currentChar); - currentMode = WordMode.QUOTED; - break; - case SIMPLE: - currentMode = handleSimple(tokens, currentToken, currentChar); - break; - case COMMENT: - if (currentChar == '\r' || currentChar == '\n') { - currentMode = WordMode.SPACES; - } - break; - default: - throw new IllegalStateException(sm.getString("quotedStringTokenizer.tokenizeError", - inputText, Integer.valueOf(pos), currentMode)); + case SPACES: + currentMode = handleSpaces(currentToken, currentChar); + break; + case QUOTED: + currentMode = handleQuoted(tokens, currentToken, currentChar); + break; + case ESCAPED: + currentToken.append(currentChar); + currentMode = WordMode.QUOTED; + break; + case SIMPLE: + currentMode = handleSimple(tokens, currentToken, currentChar); + break; + case COMMENT: + if (currentChar == '\r' || currentChar == '\n') { + currentMode = WordMode.SPACES; + } + break; + default: + throw new IllegalStateException(sm.getString("quotedStringTokenizer.tokenizeError", inputText, + Integer.valueOf(pos), currentMode)); } pos++; } diff --git a/java/org/apache/catalina/valves/rewrite/RandomizedTextRewriteMap.java b/java/org/apache/catalina/valves/rewrite/RandomizedTextRewriteMap.java index 37a24332df..399aa98508 100644 --- a/java/org/apache/catalina/valves/rewrite/RandomizedTextRewriteMap.java +++ b/java/org/apache/catalina/valves/rewrite/RandomizedTextRewriteMap.java @@ -31,17 +31,18 @@ import org.apache.tomcat.util.res.StringManager; /** * Implement a map for the txt: and rnd: mod_rewrite capabilities. */ -public class RandomizedTextRewriteMap implements RewriteMap{ +public class RandomizedTextRewriteMap implements RewriteMap { protected static final StringManager sm = StringManager.getManager(RandomizedTextRewriteMap.class); private static final Random random = new Random(); - private final Map<String, String[]> map = new HashMap<>(); + private final Map<String,String[]> map = new HashMap<>(); /** * Create a map from a text file according to the mod_rewrite syntax. + * * @param txtFilePath the text file path - * @param useRandom if the map should produce random results + * @param useRandom if the map should produce random results */ public RandomizedTextRewriteMap(String txtFilePath, boolean useRandom) { String line; @@ -49,7 +50,7 @@ public class RandomizedTextRewriteMap implements RewriteMap{ BufferedReader reader = new BufferedReader(new InputStreamReader(txtResource.getInputStream()))) { while ((line = reader.readLine()) != null) { if (line.startsWith("#") || line.isEmpty()) { - //Ignore comment or empty lines + // Ignore comment or empty lines continue; } String[] keyValuePair = line.split(" ", 2); diff --git a/java/org/apache/catalina/valves/rewrite/ResolverImpl.java b/java/org/apache/catalina/valves/rewrite/ResolverImpl.java index c7d9295bfe..c7a3c8ab2f 100644 --- a/java/org/apache/catalina/valves/rewrite/ResolverImpl.java +++ b/java/org/apache/catalina/valves/rewrite/ResolverImpl.java @@ -50,9 +50,11 @@ public class ResolverImpl extends Resolver { /** * The following are not implemented: - * - SERVER_ADMIN - * - API_VERSION - * - IS_SUBREQ + * <ul> + * <li>SERVER_ADMIN</li> + * <li>API_VERSION</li> + * <li>IS_SUBREQ</li> + * </ul> */ @Override public String resolve(String key) { @@ -113,8 +115,7 @@ public class ResolverImpl extends Resolver { } else if (key.equals("SERVER_SOFTWARE")) { return "tomcat"; } else if (key.equals("THE_REQUEST")) { - return request.getMethod() + " " + request.getRequestURI() - + " " + request.getProtocol(); + return request.getMethod() + " " + request.getRequestURI() + " " + request.getProtocol(); } else if (key.equals("REQUEST_URI")) { return request.getRequestURI(); } else if (key.equals("REQUEST_FILENAME")) { @@ -175,8 +176,8 @@ public class ResolverImpl extends Resolver { Set<Cipher> cipherList = OpenSSLCipherConfigurationParser.parse(cipherSuite); if (cipherList.size() == 1) { Cipher cipher = cipherList.iterator().next(); - if (cipher.getLevel().equals(EncryptionLevel.EXP40) - || cipher.getLevel().equals(EncryptionLevel.EXP56)) { + if (cipher.getLevel().equals(EncryptionLevel.EXP40) || + cipher.getLevel().equals(EncryptionLevel.EXP56)) { return "true"; } else { return "false"; @@ -280,8 +281,7 @@ public class ResolverImpl extends Resolver { key = key.substring("CERT_CHAIN_".length()); try { return PEMFile.toPEM(certificates[Integer.parseInt(key)]); - } catch (NumberFormatException | ArrayIndexOutOfBoundsException - | CertificateEncodingException e) { + } catch (NumberFormatException | ArrayIndexOutOfBoundsException | CertificateEncodingException e) { // Ignore } } @@ -289,7 +289,7 @@ public class ResolverImpl extends Resolver { } private String resolveComponent(String fullDN, String component) { - HashMap<String, String> components = new HashMap<>(); + HashMap<String,String> components = new HashMap<>(); StringTokenizer tokenizer = new StringTokenizer(fullDN, ","); while (tokenizer.hasMoreElements()) { String token = tokenizer.nextToken().trim(); @@ -316,8 +316,7 @@ public class ResolverImpl extends Resolver { return elements.get(n); } } - } catch (NumberFormatException | ArrayIndexOutOfBoundsException - | CertificateParsingException e) { + } catch (NumberFormatException | ArrayIndexOutOfBoundsException | CertificateParsingException e) { // Ignore } return null; @@ -341,14 +340,14 @@ public class ResolverImpl extends Resolver { return false; } else { switch (type) { - case 0: - return resource.isDirectory(); - case 1: - return resource.isFile(); - case 2: - return resource.isFile() && resource.getContentLength() > 0; - default: - return false; + case 0: + return resource.isDirectory(); + case 1: + return resource.isFile(); + case 2: + return resource.isFile() && resource.getContentLength() > 0; + default: + return false; } } } diff --git a/java/org/apache/catalina/valves/rewrite/RewriteCond.java b/java/org/apache/catalina/valves/rewrite/RewriteCond.java index 57b2f00f6c..32e9a74e4a 100644 --- a/java/org/apache/catalina/valves/rewrite/RewriteCond.java +++ b/java/org/apache/catalina/valves/rewrite/RewriteCond.java @@ -48,9 +48,11 @@ public class RewriteCond { public static class LexicalCondition extends Condition { /** + * <pre> * -1: < - * 0: = - * 1: > + * 0: = + * 1: > + * </pre> */ public int type = 0; public String condition; @@ -59,14 +61,14 @@ public class RewriteCond { public boolean evaluate(String value, Resolver resolver) { int result = value.compareTo(condition); switch (type) { - case -1: - return (result < 0); - case 0: - return (result == 0); - case 1: - return (result > 0); - default: - return false; + case -1: + return (result < 0); + case 0: + return (result == 0); + case 1: + return (result > 0); + default: + return false; } } @@ -74,9 +76,11 @@ public class RewriteCond { public static class ResourceCondition extends Condition { /** + * <pre> * 0: -d (is directory ?) * 1: -f (is regular file ?) * 2: -s (is regular file with size ?) + * </pre> */ public int type = 0; @@ -114,7 +118,7 @@ public class RewriteCond { this.flagsString = flagsString; } - public void parse(Map<String, RewriteMap> maps) { + public void parse(Map<String,RewriteMap> maps) { test = new Substitution(); test.setSub(testString); test.parse(maps); @@ -169,8 +173,7 @@ public class RewriteCond { @Override public String toString() { - return "RewriteCond " + testString + " " + condPattern - + ((flagsString != null) ? (" " + flagsString) : ""); + return "RewriteCond " + testString + " " + condPattern + ((flagsString != null) ? (" " + flagsString) : ""); } @@ -181,9 +184,8 @@ public class RewriteCond { protected Condition condition = null; /** - * This makes the test case-insensitive, i.e., there is no difference between - * 'A-Z' and 'a-z' both in the expanded TestString and the CondPattern. This - * flag is effective only for comparisons between TestString and CondPattern. + * This makes the test case-insensitive, i.e., there is no difference between 'A-Z' and 'a-z' both in the expanded + * TestString and the CondPattern. This flag is effective only for comparisons between TestString and CondPattern. * It has no effect on filesystem and subrequest checks. */ public boolean nocase = false; @@ -196,9 +198,10 @@ public class RewriteCond { /** * Evaluate the condition based on the context * - * @param rule corresponding matched rule - * @param cond last matched condition + * @param rule corresponding matched rule + * @param cond last matched condition * @param resolver Property resolver + * * @return <code>true</code> if the condition matches */ public boolean evaluate(Matcher rule, Matcher cond, Resolver resolver) { diff --git a/java/org/apache/catalina/valves/rewrite/RewriteMap.java b/java/org/apache/catalina/valves/rewrite/RewriteMap.java index 6077c276f5..3722ba99a3 100644 --- a/java/org/apache/catalina/valves/rewrite/RewriteMap.java +++ b/java/org/apache/catalina/valves/rewrite/RewriteMap.java @@ -19,35 +19,35 @@ package org.apache.catalina.valves.rewrite; import org.apache.tomcat.util.res.StringManager; /** - * Interface for user defined lookup/replacement logic that can be defined in - * a {@code rewrite.config} file by a {@code RewriteMap} directive. Such a map - * can then be used by a {@code RewriteRule} defined in the same file. + * Interface for user defined lookup/replacement logic that can be defined in a {@code rewrite.config} file by a + * {@code RewriteMap} directive. Such a map can then be used by a {@code RewriteRule} defined in the same file. * <p> * An example {@code rewrite.config} file could look like: + * * <pre> * RewriteMap uc example.UpperCaseMap * * RewriteRule ^/(.*)$ ${uc:$1} * </pre> * - * One parameter can be optionally appended to the {@code RewriteMap} directive. - * This could be used – for example – to specify a name of a file, that - * contains a lookup table used by the implementation of the map. + * One parameter can be optionally appended to the {@code RewriteMap} directive. This could be used – for example + * – to specify a name of a file, that contains a lookup table used by the implementation of the map. */ public interface RewriteMap { /** - * Optional parameter that can be defined through the {@code RewriteMap} - * directive in the {@code rewrite.config} file. + * Optional parameter that can be defined through the {@code RewriteMap} directive in the {@code rewrite.config} + * file. * * @param params the optional parameter + * * @return value is currently ignored */ String setParameters(String params); /** - * Optional parameters that can be defined through the {@code RewriteMap} - * directive in the {@code rewrite.config} file. + * Optional parameters that can be defined through the {@code RewriteMap} directive in the {@code rewrite.config} + * file. * <p> * This method will be called, if there are more than one parameters defined. * @@ -66,10 +66,11 @@ public interface RewriteMap { /** * Maps a key to a replacement value.<br> - * The method is free to return {@code null} to indicate, that the default - * value from the {@code RewriteRule} directive should be used. + * The method is free to return {@code null} to indicate, that the default value from the {@code RewriteRule} + * directive should be used. * * @param key used by the actual implementation to generate a mapped value + * * @return mapped value or {@code null} */ String lookup(String key); diff --git a/java/org/apache/catalina/valves/rewrite/RewriteRule.java b/java/org/apache/catalina/valves/rewrite/RewriteRule.java index 269eedab7f..08034d7e24 100644 --- a/java/org/apache/catalina/valves/rewrite/RewriteRule.java +++ b/java/org/apache/catalina/valves/rewrite/RewriteRule.java @@ -34,7 +34,7 @@ public class RewriteRule { protected String flagsString = null; protected boolean positive = true; - public void parse(Map<String, RewriteMap> maps) { + public void parse(Map<String,RewriteMap> maps) { // Parse the substitution if (!"-".equals(substitutionString)) { substitution = new Substitution(); @@ -81,8 +81,10 @@ public class RewriteRule { /** * Evaluate the rule based on the context - * @param url The char sequence + * + * @param url The char sequence * @param resolver Property resolver + * * @return <code>null</code> if no rewrite took place */ public CharSequence evaluate(CharSequence url, Resolver resolver) { @@ -152,30 +154,26 @@ public class RewriteRule { */ @Override public String toString() { - return "RewriteRule " + patternString + " " + substitutionString - + ((flagsString != null) ? (" " + flagsString) : ""); + return "RewriteRule " + patternString + " " + substitutionString + + ((flagsString != null) ? (" " + flagsString) : ""); } private boolean escapeBackReferences = false; /** - * This flag chains the current rule with the next rule (which itself - * can be chained with the following rule, etc.). This has the following - * effect: if a rule matches, then processing continues as usual, i.e., - * the flag has no effect. If the rule does not match, then all following - * chained rules are skipped. For instance, use it to remove the ".www" - * part inside a per-directory rule set when you let an external redirect - * happen (where the ".www" part should not to occur!). + * This flag chains the current rule with the next rule (which itself can be chained with the following rule, etc.). + * This has the following effect: if a rule matches, then processing continues as usual, i.e., the flag has no + * effect. If the rule does not match, then all following chained rules are skipped. For instance, use it to remove + * the ".www" part inside a per-directory rule set when you let an external redirect happen (where the ".www" part + * should not to occur!). */ protected boolean chain = false; /** - * This sets a cookie on the client's browser. The cookie's name is - * specified by NAME and the value is VAL. The domain field is the domain - * of the cookie, such as '.apache.org',the optional lifetime - * is the lifetime of the cookie in minutes, and the optional path is the - * path of the cookie + * This sets a cookie on the client's browser. The cookie's name is specified by NAME and the value is VAL. The + * domain field is the domain of the cookie, such as '.apache.org',the optional lifetime is the lifetime of the + * cookie in minutes, and the optional path is the path of the cookie */ protected boolean cookie = false; protected String cookieName = null; @@ -189,9 +187,8 @@ public class RewriteRule { protected ThreadLocal<String> cookieResult = new ThreadLocal<>(); /** - * This forces a request attribute named VAR to be set to the value VAL, - * where VAL can contain regexp back references $N and %N which will be - * expanded. Multiple env flags are allowed. + * This forces a request attribute named VAR to be set to the value VAL, where VAL can contain regexp back + * references $N and %N which will be expanded. Multiple env flags are allowed. */ protected boolean env = false; protected ArrayList<String> envName = new ArrayList<>(); @@ -200,80 +197,67 @@ public class RewriteRule { protected ArrayList<ThreadLocal<String>> envResult = new ArrayList<>(); /** - * This forces the current URL to be forbidden, i.e., it immediately sends - * back an HTTP response of 403 (FORBIDDEN). Use this flag in conjunction - * with appropriate RewriteConds to conditionally block some URLs. + * This forces the current URL to be forbidden, i.e., it immediately sends back an HTTP response of 403 (FORBIDDEN). + * Use this flag in conjunction with appropriate RewriteConds to conditionally block some URLs. */ protected boolean forbidden = false; /** - * This forces the current URL to be gone, i.e., it immediately sends - * back an HTTP response of 410 (GONE). Use this flag to mark pages which - * no longer exist as gone. + * This forces the current URL to be gone, i.e., it immediately sends back an HTTP response of 410 (GONE). Use this + * flag to mark pages which no longer exist as gone. */ protected boolean gone = false; /** - * Host. This means this rule and its associated conditions will apply to - * host, allowing host rewriting (ex: redirecting internally *.foo.com to - * bar.foo.com). + * Host. This means this rule and its associated conditions will apply to host, allowing host rewriting (ex: + * redirecting internally *.foo.com to bar.foo.com). */ protected boolean host = false; /** - * Stop the rewriting process here and don't apply any more rewriting - * rules. This corresponds to the Perl last command or the break command - * from the C language. Use this flag to prevent the currently rewritten - * URL from being rewritten further by following rules. For example, use - * it to rewrite the root-path URL ('/') to a real one, e.g., '/e/www/'. + * Stop the rewriting process here and don't apply any more rewriting rules. This corresponds to the Perl last + * command or the break command from the C language. Use this flag to prevent the currently rewritten URL from being + * rewritten further by following rules. For example, use it to rewrite the root-path URL ('/') to a real one, e.g., + * '/e/www/'. */ protected boolean last = false; /** - * Re-run the rewriting process (starting again with the first rewriting - * rule). Here the URL to match is again not the original URL but the URL - * from the last rewriting rule. This corresponds to the Perl next - * command or the continue command from the C language. Use this flag to - * restart the rewriting process, i.e., to immediately go to the top of - * the loop. But be careful not to create an infinite loop! + * Re-run the rewriting process (starting again with the first rewriting rule). Here the URL to match is again not + * the original URL but the URL from the last rewriting rule. This corresponds to the Perl next command or the + * continue command from the C language. Use this flag to restart the rewriting process, i.e., to immediately go to + * the top of the loop. But be careful not to create an infinite loop! */ protected boolean next = false; /** - * This makes the Pattern case-insensitive, i.e., there is no difference - * between 'A-Z' and 'a-z' when Pattern is matched against the current - * URL. + * This makes the Pattern case-insensitive, i.e., there is no difference between 'A-Z' and 'a-z' when Pattern is + * matched against the current URL. */ protected boolean nocase = false; /** - * This flag keeps mod_rewrite from applying the usual URI escaping rules - * to the result of a rewrite. Ordinarily, special characters (such as - * '%', '$', ';', and so on) will be escaped into their hexcode - * equivalents ('%25', '%24', and '%3B', respectively); this flag - * prevents this from being done. This allows percent symbols to appear - * in the output, as in - * RewriteRule /foo/(.*) /bar?arg=P1\%3d$1 [R,NE] - * which would turn '/foo/zed' into a safe request for '/bar?arg=P1=zed'. + * This flag keeps mod_rewrite from applying the usual URI escaping rules to the result of a rewrite. Ordinarily, + * special characters (such as '%', '$', ';', and so on) will be escaped into their hexcode equivalents ('%25', + * '%24', and '%3B', respectively); this flag prevents this from being done. This allows percent symbols to appear + * in the output, as in {@code RewriteRule /foo/(.*) /bar?arg=P1\%3d$1 [R,NE]} which would turn '/foo/zed' into a + * safe request for '/bar?arg=P1=zed'. */ protected boolean noescape = false; /** - * This flag forces the rewriting engine to skip a rewriting rule if the - * current request is an internal sub-request. For instance, sub-requests - * occur internally in Apache when mod_include tries to find out - * information about possible directory default files (index.xxx). On - * sub-requests it is not always useful and even sometimes causes a - * failure to if the complete set of rules are applied. Use this flag to - * exclude some rules. Use the following rule for your decision: whenever - * you prefix some URLs with CGI-scripts to force them to be processed by - * the CGI-script, the chance is high that you will run into problems (or - * even overhead) on sub-requests. In these cases, use this flag. + * This flag forces the rewriting engine to skip a rewriting rule if the current request is an internal sub-request. + * For instance, sub-requests occur internally in Apache when mod_include tries to find out information about + * possible directory default files (index.xxx). On sub-requests it is not always useful and even sometimes causes a + * failure to if the complete set of rules are applied. Use this flag to exclude some rules. Use the following rule + * for your decision: whenever you prefix some URLs with CGI-scripts to force them to be processed by the + * CGI-script, the chance is high that you will run into problems (or even overhead) on sub-requests. In these + * cases, use this flag. */ protected boolean nosubreq = false; /* - * Note: No proxy + * Note: No proxy */ /* @@ -281,56 +265,43 @@ public class RewriteRule { */ /** - * This flag forces the rewriting engine to append a query string part in - * the substitution string to the existing one instead of replacing it. - * Use this when you want to add more data to the query string via - * a rewrite rule. + * This flag forces the rewriting engine to append a query string part in the substitution string to the existing + * one instead of replacing it. Use this when you want to add more data to the query string via a rewrite rule. */ protected boolean qsappend = false; /** - * When the requested URI contains a query string, and the target URI does - * not, the default behavior of RewriteRule is to copy that query string - * to the target URI. Using the [QSD] flag causes the query string - * to be discarded. - * Using [QSD] and [QSA] together will result in [QSD] taking precedence. + * When the requested URI contains a query string, and the target URI does not, the default behavior of RewriteRule + * is to copy that query string to the target URI. Using the [QSD] flag causes the query string to be discarded. + * Using [QSD] and [QSA] together will result in [QSD] taking precedence. */ protected boolean qsdiscard = false; /** - * Prefix Substitution with http://thishost[:thisport]/ (which makes the - * new URL a URI) to force an external redirection. If no code is given - * an HTTP response of 302 (FOUND, previously MOVED TEMPORARILY) is used. - * If you want to use other response codes in the range 300-399 just - * specify them as a number or use one of the following symbolic names: - * temp (default), permanent, seeother. Use it for rules which should - * canonicalize the URL and give it back to the client, e.g., translate - * "/~" into "/u/" or always append a slash to /u/user, etc. Note: - * When you use this flag, make sure that the substitution field is a - * valid URL! If not, you are redirecting to an invalid location! - * And remember that this flag itself only prefixes the URL with - * http://thishost[:thisport]/, rewriting continues. Usually you also - * want to stop and do the redirection immediately. To stop the - * rewriting you also have to provide the 'L' flag. + * Prefix Substitution with http://thishost[:thisport]/ (which makes the new URL a URI) to force an external + * redirection. If no code is given an HTTP response of 302 (FOUND, previously MOVED TEMPORARILY) is used. If you + * want to use other response codes in the range 300-399 just specify them as a number or use one of the following + * symbolic names: temp (default), permanent, seeother. Use it for rules which should canonicalize the URL and give + * it back to the client, e.g., translate "/~" into "/u/" or always append a slash to /u/user, etc. Note: When you + * use this flag, make sure that the substitution field is a valid URL! If not, you are redirecting to an invalid + * location! And remember that this flag itself only prefixes the URL with http://thishost[:thisport]/, rewriting + * continues. Usually you also want to stop and do the redirection immediately. To stop the rewriting you also have + * to provide the 'L' flag. */ protected boolean redirect = false; protected int redirectCode = 0; /** - * This flag forces the rewriting engine to skip the next num rules in - * sequence when the current rule matches. Use this to make pseudo - * if-then-else constructs: The last rule of the then-clause becomes - * skip=N where N is the number of rules in the else-clause. - * (This is not the same as the 'chain|C' flag!) + * This flag forces the rewriting engine to skip the next num rules in sequence when the current rule matches. Use + * this to make pseudo if-then-else constructs: The last rule of the then-clause becomes skip=N where N is the + * number of rules in the else-clause. (This is not the same as the 'chain|C' flag!) */ protected int skip = 0; /** - * Force the MIME-type of the target file to be MIME-type. For instance, - * this can be used to setup the content-type based on some conditions. - * For example, the following snippet allows .php files to be displayed - * by mod_php if they are called with the .phps extension: - * RewriteRule ^(.+\.php)s$ $1 [T=application/x-httpd-php-source] + * Force the MIME-type of the target file to be MIME-type. For instance, this can be used to setup the content-type + * based on some conditions. For example, the following snippet allows .php files to be displayed by mod_php if they + * are called with the .phps extension: RewriteRule ^(.+\.php)s$ $1 [T=application/x-httpd-php-source] */ protected boolean type = false; protected String typeValue = null; @@ -343,153 +314,203 @@ public class RewriteRule { public boolean isEscapeBackReferences() { return escapeBackReferences; } + public void setEscapeBackReferences(boolean escapeBackReferences) { this.escapeBackReferences = escapeBackReferences; } + public boolean isChain() { return chain; } + public void setChain(boolean chain) { this.chain = chain; } + public RewriteCond[] getConditions() { return conditions; } + public void setConditions(RewriteCond[] conditions) { this.conditions = conditions; } + public boolean isCookie() { return cookie; } + public void setCookie(boolean cookie) { this.cookie = cookie; } + public String getCookieName() { return cookieName; } + public void setCookieName(String cookieName) { this.cookieName = cookieName; } + public String getCookieValue() { return cookieValue; } + public void setCookieValue(String cookieValue) { this.cookieValue = cookieValue; } + public String getCookieResult() { return cookieResult.get(); } + public boolean isEnv() { return env; } + public int getEnvSize() { return envName.size(); } + public void setEnv(boolean env) { this.env = env; } + public String getEnvName(int i) { return envName.get(i); } + public void addEnvName(String envName) { this.envName.add(envName); } + public String getEnvValue(int i) { return envValue.get(i); } + public void addEnvValue(String envValue) { this.envValue.add(envValue); } + public String getEnvResult(int i) { return envResult.get(i).get(); } + public boolean isForbidden() { return forbidden; } + public void setForbidden(boolean forbidden) { this.forbidden = forbidden; } + public boolean isGone() { return gone; } + public void setGone(boolean gone) { this.gone = gone; } + public boolean isLast() { return last; } + public void setLast(boolean last) { this.last = last; } + public boolean isNext() { return next; } + public void setNext(boolean next) { this.next = next; } + public boolean isNocase() { return nocase; } + public void setNocase(boolean nocase) { this.nocase = nocase; } + public boolean isNoescape() { return noescape; } + public void setNoescape(boolean noescape) { this.noescape = noescape; } + public boolean isNosubreq() { return nosubreq; } + public void setNosubreq(boolean nosubreq) { this.nosubreq = nosubreq; } + public boolean isQsappend() { return qsappend; } + public void setQsappend(boolean qsappend) { this.qsappend = qsappend; } + public final boolean isQsdiscard() { return qsdiscard; } + public final void setQsdiscard(boolean qsdiscard) { this.qsdiscard = qsdiscard; } + public boolean isRedirect() { return redirect; } + public void setRedirect(boolean redirect) { this.redirect = redirect; } + public int getRedirectCode() { return redirectCode; } + public void setRedirectCode(int redirectCode) { this.redirectCode = redirectCode; } + public int getSkip() { return skip; } + public void setSkip(int skip) { this.skip = skip; } + public Substitution getSubstitution() { return substitution; } + public void setSubstitution(Substitution substitution) { this.substitution = substitution; } + public boolean isType() { return type; } + public void setType(boolean type) { this.type = type; } + public String getTypeValue() { return typeValue; } + public void setTypeValue(String typeValue) { this.typeValue = typeValue; } diff --git a/java/org/apache/catalina/valves/rewrite/RewriteValve.java b/java/org/apache/catalina/valves/rewrite/RewriteValve.java index d15210621d..0579987324 100644 --- a/java/org/apache/catalina/valves/rewrite/RewriteValve.java +++ b/java/org/apache/catalina/valves/rewrite/RewriteValve.java @@ -54,18 +54,13 @@ import org.apache.tomcat.util.file.ConfigurationSource; import org.apache.tomcat.util.http.RequestUtil; /** - * Note: Extra caution should be used when adding a Rewrite Rule. When - * specifying a regex to match for in a Rewrite Rule, certain regex could allow - * an attacker to DoS your server, as Java's regex parsing is vulnerable to - * "catastrophic backtracking" (also known as "Regular expression Denial of - * Service", or ReDoS). There are some open source tools to help detect - * vulnerable regex, though in general it is a hard problem. A good defence is - * to use a regex debugger on your desired regex, and read more on the subject - * of catastrophic backtracking. + * Note: Extra caution should be used when adding a Rewrite Rule. When specifying a regex to match for in a Rewrite + * Rule, certain regex could allow an attacker to DoS your server, as Java's regex parsing is vulnerable to + * "catastrophic backtracking" (also known as "Regular expression Denial of Service", or ReDoS). There are some open + * source tools to help detect vulnerable regex, though in general it is a hard problem. A good defence is to use a + * regex debugger on your desired regex, and read more on the subject of catastrophic backtracking. * - * @see <a href= - * "https://www.owasp.org/index.php/Regular_expression_Denial_of_Service_-_ReDoS">OWASP - * ReDoS</a> + * @see <a href= "https://www.owasp.org/index.php/Regular_expression_Denial_of_Service_-_ReDoS">OWASP ReDoS</a> */ public class RewriteValve extends ValveBase { @@ -82,8 +77,7 @@ public class RewriteValve extends ValveBase { /** - * Relative path to the configuration file. - * Note: If the valve's container is a context, this will be relative to + * Relative path to the configuration file. Note: If the valve's container is a context, this will be relative to * /WEB-INF/. */ protected String resourcePath = "rewrite.config"; @@ -103,7 +97,7 @@ public class RewriteValve extends ValveBase { /** * Maps to be used by the rules. */ - protected Map<String, RewriteMap> maps = new ConcurrentHashMap<>(); + protected Map<String,RewriteMap> maps = new ConcurrentHashMap<>(); /** @@ -144,8 +138,7 @@ public class RewriteValve extends ValveBase { if (getContainer() instanceof Context) { context = true; String webInfResourcePath = "/WEB-INF/" + resourcePath; - is = ((Context) getContainer()).getServletContext() - .getResourceAsStream(webInfResourcePath); + is = ((Context) getContainer()).getServletContext().getResourceAsStream(webInfResourcePath); if (containerLog.isDebugEnabled()) { if (is == null) { containerLog.debug(sm.getString("rewriteValve.noConfiguration", webInfResourcePath)); @@ -185,8 +178,7 @@ public class RewriteValve extends ValveBase { } - public void setConfiguration(String configuration) - throws Exception { + public void setConfiguration(String configuration) throws Exception { if (containerLog == null) { containerLog = LogFactory.getLog(getContainer().getLogName() + ".rewrite"); } @@ -224,8 +216,8 @@ public class RewriteValve extends ValveBase { if (result instanceof RewriteRule) { RewriteRule rule = (RewriteRule) result; if (containerLog.isTraceEnabled()) { - containerLog.trace("Add rule with pattern " + rule.getPatternString() - + " and substitution " + rule.getSubstitutionString()); + containerLog.trace("Add rule with pattern " + rule.getPatternString() + " and substitution " + + rule.getSubstitutionString()); } for (int i = (conditions.size() - 1); i > 0; i--) { if (conditions.get(i - 1).isOrnext()) { @@ -235,11 +227,10 @@ public class RewriteValve extends ValveBase { for (RewriteCond condition : conditions) { if (containerLog.isTraceEnabled()) { RewriteCond cond = condition; - containerLog.trace("Add condition " + cond.getCondPattern() - + " test " + cond.getTestString() + " to rule with pattern " - + rule.getPatternString() + " and substitution " - + rule.getSubstitutionString() + (cond.isOrnext() ? " [OR]" : "") - + (cond.isNocase() ? " [NC]" : "")); + containerLog.trace("Add condition " + cond.getCondPattern() + " test " + + cond.getTestString() + " to rule with pattern " + rule.getPatternString() + + " and substitution " + rule.getSubstitutionString() + + (cond.isOrnext() ? " [OR]" : "") + (cond.isNocase() ? " [NC]" : "")); } rule.addCondition(condition); } @@ -284,8 +275,7 @@ public class RewriteValve extends ValveBase { @Override - public void invoke(Request request, Response response) - throws IOException, ServletException { + public void invoke(Request request, Response response) throws IOException, ServletException { if (!getEnabled() || rules == null || rules.length == 0) { getNext().invoke(request, response); @@ -311,8 +301,7 @@ public class RewriteValve extends ValveBase { // converted to a string Charset uriCharset = request.getConnector().getURICharset(); String originalQueryStringEncoded = request.getQueryString(); - MessageBytes urlMB = - context ? request.getRequestPathMB() : request.getDecodedRequestURIMB(); + MessageBytes urlMB = context ? request.getRequestPathMB() : request.getDecodedRequestURIMB(); urlMB.toChars(); CharSequence urlDecoded = urlMB.getCharChunk(); CharSequence host = request.getServerName(); @@ -327,8 +316,8 @@ public class RewriteValve extends ValveBase { CharSequence newtest = rule.evaluate(test, resolver); if (newtest != null && !test.toString().equals(newtest.toString())) { if (containerLog.isTraceEnabled()) { - containerLog.trace("Rewrote " + test + " as " + newtest - + " with rule pattern " + rule.getPatternString()); + containerLog.trace( + "Rewrote " + test + " as " + newtest + " with rule pattern " + rule.getPatternString()); } if (rule.isHost()) { host = newtest; @@ -382,8 +371,7 @@ public class RewriteValve extends ValveBase { StringBuilder urlStringEncoded = new StringBuilder(URLEncoder.DEFAULT.encode(urlStringDecoded, uriCharset)); - if (!qsd && originalQueryStringEncoded != null - && originalQueryStringEncoded.length() > 0) { + if (!qsd && originalQueryStringEncoded != null && originalQueryStringEncoded.length() > 0) { if (rewrittenQueryStringDecoded == null) { urlStringEncoded.append('?'); urlStringEncoded.append(originalQueryStringEncoded); @@ -391,8 +379,8 @@ public class RewriteValve extends ValveBase { if (qsa) { // if qsa is specified append the query urlStringEncoded.append('?'); - urlStringEncoded.append(URLEncoder.QUERY.encode( - rewrittenQueryStringDecoded, uriCharset)); + urlStringEncoded + .append(URLEncoder.QUERY.encode(rewrittenQueryStringDecoded, uriCharset)); urlStringEncoded.append('&'); urlStringEncoded.append(originalQueryStringEncoded); } else if (index == urlStringEncoded.length() - 1) { @@ -401,27 +389,24 @@ public class RewriteValve extends ValveBase { urlStringEncoded.deleteCharAt(index); } else { urlStringEncoded.append('?'); - urlStringEncoded.append(URLEncoder.QUERY.encode( - rewrittenQueryStringDecoded, uriCharset)); + urlStringEncoded + .append(URLEncoder.QUERY.encode(rewrittenQueryStringDecoded, uriCharset)); } } } else if (rewrittenQueryStringDecoded != null) { urlStringEncoded.append('?'); - urlStringEncoded.append( - URLEncoder.QUERY.encode(rewrittenQueryStringDecoded, uriCharset)); + urlStringEncoded.append(URLEncoder.QUERY.encode(rewrittenQueryStringDecoded, uriCharset)); } // Insert the context if // 1. this valve is associated with a context // 2. the url starts with a leading slash // 3. the url isn't absolute - if (context && urlStringEncoded.charAt(0) == '/' && - !UriUtil.hasScheme(urlStringEncoded)) { + if (context && urlStringEncoded.charAt(0) == '/' && !UriUtil.hasScheme(urlStringEncoded)) { urlStringEncoded.insert(0, request.getContext().getEncodedPath()); } if (rule.isNoescape()) { - response.sendRedirect( - UDecoder.URLDecode(urlStringEncoded.toString(), uriCharset)); + response.sendRedirect(UDecoder.URLDecode(urlStringEncoded.toString(), uriCharset)); } else { response.sendRedirect(urlStringEncoded.toString()); } @@ -434,8 +419,7 @@ public class RewriteValve extends ValveBase { // - cookie if (rule.isCookie() && newtest != null) { - Cookie cookie = new Cookie(rule.getCookieName(), - rule.getCookieResult()); + Cookie cookie = new Cookie(rule.getCookieName(), rule.getCookieResult()); cookie.setDomain(rule.getCookieDomain()); cookie.setMaxAge(rule.getCookieLifetime()); cookie.setPath(rule.getCookiePath()); @@ -450,7 +434,7 @@ public class RewriteValve extends ValveBase { } } // - content type (note: this will not force the content type, use a filter - // to do that) + // to do that) if (rule.isType() && newtest != null) { response.setContentType(rule.getTypeValue()); } @@ -490,7 +474,7 @@ public class RewriteValve extends ValveBase { String queryStringDecoded = null; int queryIndex = urlStringDecoded.indexOf('?'); if (queryIndex != -1) { - queryStringDecoded = urlStringDecoded.substring(queryIndex+1); + queryStringDecoded = urlStringDecoded.substring(queryIndex + 1); urlStringDecoded = urlStringDecoded.substring(0, queryIndex); } // Save the current context path before re-writing starts @@ -521,8 +505,7 @@ public class RewriteValve extends ValveBase { request.getCoyoteRequest().queryString().setChars(MessageBytes.EMPTY_CHAR_ARRAY, 0, 0); chunk = request.getCoyoteRequest().queryString().getCharChunk(); chunk.append(URLEncoder.QUERY.encode(queryStringDecoded, uriCharset)); - if (qsa && originalQueryStringEncoded != null && - originalQueryStringEncoded.length() > 0) { + if (qsa && originalQueryStringEncoded != null && originalQueryStringEncoded.length() > 0) { chunk.append('&'); chunk.append(originalQueryStringEncoded); } @@ -537,8 +520,8 @@ public class RewriteValve extends ValveBase { // Reinvoke the whole request recursively Connector connector = request.getConnector(); try { - if (!connector.getProtocolHandler().getAdapter().prepare( - request.getCoyoteRequest(), response.getCoyoteResponse())) { + if (!connector.getProtocolHandler().getAdapter().prepare(request.getCoyoteRequest(), + response.getCoyoteResponse())) { return; } } catch (Exception e) { @@ -569,11 +552,11 @@ public class RewriteValve extends ValveBase { /** * This factory method will parse a line formed like: - * - * Example: - * RewriteCond %{REMOTE_HOST} ^host1.* [OR] + * <p> + * Example: {@code RewriteCond %{REMOTE_HOST} ^host1.* [OR]} * * @param line A line from the rewrite configuration + * * @return The condition, rule or map resulting from parsing the line */ public static Object parse(String line) { @@ -648,8 +631,7 @@ public class RewriteValve extends ValveBase { } if (map == null) { try { - map = (RewriteMap) (Class.forName( - rewriteMapClassName).getConstructor().newInstance()); + map = (RewriteMap) (Class.forName(rewriteMapClassName).getConstructor().newInstance()); } catch (Exception e) { throw new IllegalArgumentException(sm.getString("rewriteValve.invalidMapClassName", line)); } @@ -678,9 +660,10 @@ public class RewriteValve extends ValveBase { /** * Parser for RewriteCond flags. - * @param line The configuration line being parsed + * + * @param line The configuration line being parsed * @param condition The current condition - * @param flag The flag + * @param flag The flag */ protected static void parseCondFlag(String line, RewriteCond condition, String flag) { if (flag.equals("NC") || flag.equals("nocase")) { @@ -695,6 +678,7 @@ public class RewriteValve extends ValveBase { /** * Parser for RewriteRule flags. + * * @param line The configuration line being parsed * @param rule The current rule * @param flag The flag @@ -763,8 +747,8 @@ public class RewriteValve extends ValveBase { rule.setNoescape(true); } else if (flag.startsWith("next") || flag.startsWith("N")) { rule.setNext(true); - // Note: Proxy is not supported as Tomcat does not have proxy - // capabilities + // Note: Proxy is not supported as Tomcat does not have proxy + // capabilities } else if (flag.startsWith("qsappend") || flag.startsWith("QSA")) { rule.setQsappend(true); } else if (flag.startsWith("qsdiscard") || flag.startsWith("QSD")) { @@ -778,7 +762,7 @@ public class RewriteValve extends ValveBase { } else if (flag.startsWith("R=")) { flag = flag.substring("R=".length()); } - switch(flag) { + switch (flag) { case "temp": redirectCode = HttpServletResponse.SC_FOUND; break; diff --git a/java/org/apache/catalina/valves/rewrite/Substitution.java b/java/org/apache/catalina/valves/rewrite/Substitution.java index b7e39158e6..8070b934b6 100644 --- a/java/org/apache/catalina/valves/rewrite/Substitution.java +++ b/java/org/apache/catalina/valves/rewrite/Substitution.java @@ -44,6 +44,7 @@ public class Substitution { public class RewriteRuleBackReferenceElement extends SubstitutionElement { public int n; + @Override public String evaluate(Matcher rule, Matcher cond, Resolver resolver) { String result = rule.group(n); @@ -52,9 +53,9 @@ public class Substitution { } if (escapeBackReferences) { // Note: This should be consistent with the way httpd behaves. - // We might want to consider providing a dedicated decoder - // with an option to add additional safe characters to - // provide users with more flexibility + // We might want to consider providing a dedicated decoder + // with an option to add additional safe characters to + // provide users with more flexibility return URLEncoder.DEFAULT.encode(result, resolver.getUriCharset()); } else { return result; @@ -64,6 +65,7 @@ public class Substitution { public static class RewriteCondBackReferenceElement extends SubstitutionElement { public int n; + @Override public String evaluate(Matcher rule, Matcher cond, Resolver resolver) { return (cond.group(n) == null ? "" : cond.group(n)); @@ -72,6 +74,7 @@ public class Substitution { public static class ServerVariableElement extends SubstitutionElement { public String key; + @Override public String evaluate(Matcher rule, Matcher cond, Resolver resolver) { return resolver.resolve(key); @@ -80,6 +83,7 @@ public class Substitution { public static class ServerVariableEnvElement extends SubstitutionElement { public String key; + @Override public String evaluate(Matcher rule, Matcher cond, Resolver resolver) { return resolver.resolveEnv(key); @@ -88,6 +92,7 @@ public class Substitution { public static class ServerVariableSslElement extends SubstitutionElement { public String key; + @Override public String evaluate(Matcher rule, Matcher cond, Resolver resolver) { return resolver.resolveSsl(key); @@ -96,6 +101,7 @@ public class Substitution { public static class ServerVariableHttpElement extends SubstitutionElement { public String key; + @Override public String evaluate(Matcher rule, Matcher cond, Resolver resolver) { return resolver.resolveHttp(key); @@ -106,6 +112,7 @@ public class Substitution { public RewriteMap map = null; public SubstitutionElement[] defaultValue = null; public SubstitutionElement[] key = null; + @Override public String evaluate(Matcher rule, Matcher cond, Resolver resolver) { String result = map.lookup(evaluateSubstitution(key, rule, cond, resolver)); @@ -119,19 +126,26 @@ public class Substitution { protected SubstitutionElement[] elements = null; protected String sub = null; - public String getSub() { return sub; } - public void setSub(String sub) { this.sub = sub; } + + public String getSub() { + return sub; + } + + public void setSub(String sub) { + this.sub = sub; + } private boolean escapeBackReferences; + void setEscapeBackReferences(boolean escapeBackReferences) { this.escapeBackReferences = escapeBackReferences; } - public void parse(Map<String, RewriteMap> maps) { + public void parse(Map<String,RewriteMap> maps) { this.elements = parseSubstitution(sub, maps); } - private SubstitutionElement[] parseSubstitution(String sub, Map<String, RewriteMap> maps) { + private SubstitutionElement[] parseSubstitution(String sub, Map<String,RewriteMap> maps) { List<SubstitutionElement> elements = new ArrayList<>(); int pos = 0; @@ -186,7 +200,8 @@ public class Substitution { } newElement.map = maps.get(sub.substring(open + 1, colon)); if (newElement.map == null) { - throw new IllegalArgumentException(sm.getString("substitution.noMap", sub.substring(open + 1, colon), sub)); + throw new IllegalArgumentException( + sm.getString("substitution.noMap", sub.substring(open + 1, colon), sub)); } String key = null; String defaultValue = null; @@ -269,7 +284,7 @@ public class Substitution { for (int i = start + 1; i < sub.length(); i++) { char c = sub.charAt(i); if (c == '{') { - char previousChar = sub.charAt(i-1); + char previousChar = sub.charAt(i - 1); if (previousChar == '$' || previousChar == '%') { nesting++; } @@ -288,13 +303,13 @@ public class Substitution { for (int i = start + 1; i < sub.length(); i++) { char c = sub.charAt(i); if (c == '{') { - char previousChar = sub.charAt(i-1); + char previousChar = sub.charAt(i - 1); if (previousChar == '$' || previousChar == '%') { nesting++; } } else if (c == '}') { nesting--; - } else if (colon ? c == ':' : c =='|') { + } else if (colon ? c == ':' : c == '|') { if (nesting == 0) { return i; } @@ -305,9 +320,11 @@ public class Substitution { /** * Evaluate the substitution based on the context. - * @param rule corresponding matched rule - * @param cond last matched condition + * + * @param rule corresponding matched rule + * @param cond last matched condition * @param resolver The property resolver + * * @return The substitution result */ public String evaluate(Matcher rule, Matcher cond, Resolver resolver) { @@ -323,16 +340,14 @@ public class Substitution { } /** - * Checks whether the first int is non negative and smaller than any non negative other int - * given with {@code others}. + * Checks whether the first int is non negative and smaller than any non negative other int given with + * {@code others}. + * + * @param testPos integer to test against + * @param others list of integers that are paired against {@code testPos}. Any negative integer will be ignored. * - * @param testPos - * integer to test against - * @param others - * list of integers that are paired against {@code testPos}. Any - * negative integer will be ignored. - * @return {@code true} if {@code testPos} is not negative and is less then any given other - * integer, {@code false} otherwise + * @return {@code true} if {@code testPos} is not negative and is less then any given other integer, {@code false} + * otherwise */ private boolean isFirstPos(int testPos, int... others) { if (testPos < 0) { --------------------------------------------------------------------- To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org For additional commands, e-mail: dev-h...@tomcat.apache.org