Author: remy.maucherat(a)jboss.com
Date: 2008-12-05 12:07:59 -0500 (Fri, 05 Dec 2008)
New Revision: 875
Modified:
trunk/java/org/apache/catalina/connector/Response.java
trunk/java/org/jboss/web/rewrite/RewriteRule.java
trunk/java/org/jboss/web/rewrite/RewriteValve.java
trunk/java/org/jboss/web/rewrite/Substitution.java
trunk/webapps/docs/changelog.xml
trunk/webapps/docs/rewrite.xml
Log:
- Rewrite update to E and CO flags handling. Untested, will do later.
Modified: trunk/java/org/apache/catalina/connector/Response.java
===================================================================
--- trunk/java/org/apache/catalina/connector/Response.java 2008-12-05 17:07:03 UTC (rev
874)
+++ trunk/java/org/apache/catalina/connector/Response.java 2008-12-05 17:07:59 UTC (rev
875)
@@ -986,6 +986,23 @@
*
* @param cookie Cookie to be added
*/
+ public void addTomcatCookie(final TomcatCookie cookie) {
+
+ // Ignore any call from an included servlet
+ if (included)
+ return;
+
+ addCookieInternal(cookie);
+
+ }
+
+
+ /**
+ * Add the specified Cookie to those that will be included with
+ * this Response.
+ *
+ * @param cookie Cookie to be added
+ */
public void addCookieInternal(final Cookie cookie) {
if (isCommitted())
Modified: trunk/java/org/jboss/web/rewrite/RewriteRule.java
===================================================================
--- trunk/java/org/jboss/web/rewrite/RewriteRule.java 2008-12-05 17:07:03 UTC (rev 874)
+++ trunk/java/org/jboss/web/rewrite/RewriteRule.java 2008-12-05 17:07:59 UTC (rev 875)
@@ -23,6 +23,7 @@
package org.jboss.web.rewrite;
+import java.util.ArrayList;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@@ -54,6 +55,21 @@
for (int i = 0; i < conditions.length; i++) {
conditions[i].parse(maps);
}
+ // Parse flag which have substitution values
+ if (isEnv()) {
+ for (int i = 0; i < envValue.size(); i++) {
+ Substitution newEnvSubstitution = new Substitution();
+ newEnvSubstitution.setSub(envValue.get(i));
+ newEnvSubstitution.parse(maps);
+ envSubstitution.add(newEnvSubstitution);
+ envResult.add(new ThreadLocal<String>());
+ }
+ }
+ if (isCookie()) {
+ cookieSubstitution = new Substitution();
+ cookieSubstitution.setSub(cookieValue);
+ cookieSubstitution.parse(maps);
+ }
}
public void addCondition(RewriteCond condition) {
@@ -112,6 +128,14 @@
}
// Use the substitution to rewrite the url
if (rewrite) {
+ if (isEnv()) {
+ for (int i = 0; i < envSubstitution.size(); i++) {
+ envResult.get(i).set(envSubstitution.get(i).evaluate(matcher,
lastMatcher, resolver));
+ }
+ }
+ if (isCookie()) {
+ cookieResult.set(cookieSubstitution.evaluate(matcher, lastMatcher,
resolver));
+ }
if (substitution != null) {
return substitution.evaluate(matcher, lastMatcher, resolver);
} else {
@@ -153,19 +177,24 @@
protected boolean cookie = false;
protected String cookieName = null;
protected String cookieValue = null;
+ protected String cookieDomain = null;
+ protected int cookieLifetime = -1;
+ protected String cookiePath = null;
+ protected boolean cookieSecure = false;
+ protected boolean cookieHttpOnly = false;
+ protected Substitution cookieSubstitution = null;
+ protected ThreadLocal<String> cookieResult = new ThreadLocal<String>();
/**
- * This forces an environment variable named VAR to be set to the value VAL,
- * where VAL can contain regexp backreferences $N and %N which will be
- * expanded. You can use this flag more than once to set more than one variable.
- * The variables can be later dereferenced in many situations, but usually
- * from within XSSI (via <!--#echo var="VAR"-->) or CGI (e.g.
$ENV{'VAR'}).
- * Additionally you can dereference it in a following RewriteCond pattern via
- * %{ENV:VAR}. Use this to strip but remember information from URLs.
+ * 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 String envName = null;
- protected String envValue = null;
+ protected ArrayList<String> envName = new ArrayList<String>();
+ protected ArrayList<String> envValue = new ArrayList<String>();
+ protected ArrayList<Substitution> envSubstitution = new
ArrayList<Substitution>();
+ protected ArrayList<ThreadLocal<String>> envResult = new
ArrayList<ThreadLocal<String>>();
/**
* This forces the current URL to be forbidden, i.e., it immediately sends
@@ -249,11 +278,11 @@
* module. Use this flag to achieve a more powerful implementation of the
* ProxyPass directive, to map some remote stuff into the namespace of
* the local server.
- * FIXME: Likely no impl for this, so replace with a redirect
+ * FIXME: No proxy
*/
/**
- * FIMXE: No passthrough ?
+ * FIXME: No passthrough ?
*/
/**
@@ -331,24 +360,33 @@
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() {
- return envName;
+ public String getEnvName(int i) {
+ return envName.get(i);
}
- public void setEnvName(String envName) {
- this.envName = envName;
+ public void addEnvName(String envName) {
+ this.envName.add(envName);
}
- public String getEnvValue() {
- return envValue;
+ public String getEnvValue(int i) {
+ return envValue.get(i);
}
- public void setEnvValue(String envValue) {
- this.envValue = envValue;
+ public void addEnvValue(String envValue) {
+ this.envValue.add(envValue);
}
+ public String getEnvResult(int i) {
+ return envResult.get(i).get();
+ }
public boolean isForbidden() {
return forbidden;
}
@@ -457,5 +495,45 @@
public void setHost(boolean host) {
this.host = host;
}
+
+ public String getCookieDomain() {
+ return cookieDomain;
+ }
+
+ public void setCookieDomain(String cookieDomain) {
+ this.cookieDomain = cookieDomain;
+ }
+
+ public int getCookieLifetime() {
+ return cookieLifetime;
+ }
+
+ public void setCookieLifetime(int cookieLifetime) {
+ this.cookieLifetime = cookieLifetime;
+ }
+
+ public String getCookiePath() {
+ return cookiePath;
+ }
+
+ public void setCookiePath(String cookiePath) {
+ this.cookiePath = cookiePath;
+ }
+
+ public boolean isCookieSecure() {
+ return cookieSecure;
+ }
+
+ public void setCookieSecure(boolean cookieSecure) {
+ this.cookieSecure = cookieSecure;
+ }
+
+ public boolean isCookieHttpOnly() {
+ return cookieHttpOnly;
+ }
+
+ public void setCookieHttpOnly(boolean cookieHttpOnly) {
+ this.cookieHttpOnly = cookieHttpOnly;
+ }
}
Modified: trunk/java/org/jboss/web/rewrite/RewriteValve.java
===================================================================
--- trunk/java/org/jboss/web/rewrite/RewriteValve.java 2008-12-05 17:07:03 UTC (rev 874)
+++ trunk/java/org/jboss/web/rewrite/RewriteValve.java 2008-12-05 17:07:59 UTC (rev 875)
@@ -53,6 +53,7 @@
import org.apache.catalina.valves.ValveBase;
import org.apache.tomcat.util.buf.CharChunk;
import org.apache.tomcat.util.buf.MessageBytes;
+import org.apache.tomcat.util.http.TomcatCookie;
import org.apache.tomcat.util.net.URL;
public class RewriteValve extends ValveBase
@@ -356,13 +357,20 @@
// - cookie
if (rules[i].isCookie() && newtest != null) {
- response.addCookie(new Cookie(rules[i].getCookieName(),
- rules[i].getCookieValue()));
- // FIXME: Cookie impl for other parameters
+ TomcatCookie cookie = new TomcatCookie(rules[i].getCookieName(),
+ rules[i].getCookieResult());
+ cookie.setDomain(rules[i].getCookieDomain());
+ cookie.setMaxAge(rules[i].getCookieLifetime());
+ cookie.setPath(rules[i].getCookiePath());
+ cookie.setSecure(rules[i].isCookieSecure());
+ cookie.setHttpOnly(rules[i].isCookieHttpOnly());
+ response.addCookie(cookie);
}
- // - env (note: this sets a system property)
+ // - env (note: this sets a request attribute)
if (rules[i].isEnv() && newtest != null) {
- System.setProperty(rules[i].getEnvName(), rules[i].getEnvValue());
+ for (int j = 0; j < rules[i].getEnvSize(); j++) {
+ request.setAttribute(rules[i].getEnvName(j),
rules[i].getEnvResult(j));
+ }
}
// - content type (note: this will not force the content type, use a filter
// to do that)
@@ -614,12 +622,31 @@
} else if (flag.startsWith("C=")) {
flag = flag.substring("C=".length());
}
- int pos = flag.indexOf(':');
- if (pos == -1 || (pos + 1) == flag.length()) {
+ StringTokenizer tokenizer = new StringTokenizer(flag, ":");
+ if (tokenizer.countTokens() < 2) {
throw new IllegalArgumentException("Invalid flag in: " +
line);
}
- rule.setCookieName(flag.substring(0, pos));
- rule.setCookieValue(flag.substring(pos + 1));
+ rule.setCookieName(tokenizer.nextToken());
+ rule.setCookieValue(tokenizer.nextToken());
+ if (tokenizer.hasMoreTokens()) {
+ rule.setCookieDomain(tokenizer.nextToken());
+ }
+ if (tokenizer.hasMoreTokens()) {
+ try {
+ rule.setCookieLifetime(Integer.parseInt(tokenizer.nextToken()));
+ } catch (NumberFormatException e) {
+ throw new IllegalArgumentException("Invalid flag in: " +
line, e);
+ }
+ }
+ if (tokenizer.hasMoreTokens()) {
+ rule.setCookiePath(tokenizer.nextToken());
+ }
+ if (tokenizer.hasMoreTokens()) {
+ rule.setCookieSecure(Boolean.parseBoolean(tokenizer.nextToken()));
+ }
+ if (tokenizer.hasMoreTokens()) {
+ rule.setCookieHttpOnly(Boolean.parseBoolean(tokenizer.nextToken()));
+ }
} else if (flag.startsWith("env=") || flag.startsWith("E="))
{
rule.setEnv(true);
if (flag.startsWith("env=")) {
@@ -631,8 +658,8 @@
if (pos == -1 || (pos + 1) == flag.length()) {
throw new IllegalArgumentException("Invalid flag in: " +
line);
}
- rule.setEnvName(flag.substring(0, pos));
- rule.setEnvValue(flag.substring(pos + 1));
+ rule.addEnvName(flag.substring(0, pos));
+ rule.addEnvValue(flag.substring(pos + 1));
} else if (flag.startsWith("forbidden") ||
flag.startsWith("F")) {
rule.setForbidden(true);
} else if (flag.startsWith("gone") || flag.startsWith("G"))
{
@@ -648,8 +675,7 @@
} else if (flag.startsWith("noescape") ||
flag.startsWith("NE")) {
rule.setNoescape(true);
} else if (flag.startsWith("proxy") || flag.startsWith("P"))
{
- // FIXME: Proxy not supported at the moment, would require proxy
- // capabilities
+ // FIXME: Proxy not supported at the moment, would require proxy
capabilities
//rule.setProxy(true);
} else if (flag.startsWith("qsappend") ||
flag.startsWith("QSA")) {
rule.setQsappend(true);
Modified: trunk/java/org/jboss/web/rewrite/Substitution.java
===================================================================
--- trunk/java/org/jboss/web/rewrite/Substitution.java 2008-12-05 17:07:03 UTC (rev 874)
+++ trunk/java/org/jboss/web/rewrite/Substitution.java 2008-12-05 17:07:59 UTC (rev 875)
@@ -114,7 +114,6 @@
while (pos < sub.length()) {
percentPos = sub.indexOf('%', pos);
dollarPos = sub.indexOf('$', pos);
- // FIXME: System.out.println("S: " + sub + " pos: " + pos
+ " L: " + sub.length() + " %: " + percentPos + " $: " +
dollarPos);
if (percentPos == -1 && dollarPos == -1) {
// Static text
StaticElement newElement = new StaticElement();
@@ -122,7 +121,7 @@
pos = sub.length();
elements.add(newElement);
} else if (percentPos == -1 || ((dollarPos != -1) && (dollarPos <
percentPos))) {
- // $: backreference to rule or map lookup
+ // $: back reference to rule or map lookup
if (dollarPos + 1 == sub.length()) {
throw new IllegalArgumentException(sub);
}
@@ -134,7 +133,7 @@
elements.add(newElement);
}
if (Character.isDigit(sub.charAt(dollarPos + 1))) {
- // $: backreference to rule
+ // $: back reference to rule
RewriteRuleBackReferenceElement newElement = new
RewriteRuleBackReferenceElement();
newElement.n = Character.digit(sub.charAt(dollarPos + 1), 10);
pos = dollarPos + 2;
@@ -166,7 +165,7 @@
elements.add(newElement);
}
} else {
- // %: backreference to cond or server variable
+ // %: back reference to condition or server variable
if (percentPos + 1 == sub.length()) {
throw new IllegalArgumentException(sub);
}
@@ -178,7 +177,7 @@
elements.add(newElement);
}
if (Character.isDigit(sub.charAt(percentPos + 1))) {
- // %: backreference to cond
+ // %: back reference to condition
RewriteCondBackReferenceElement newElement = new
RewriteCondBackReferenceElement();
newElement.n = Character.digit(sub.charAt(percentPos + 1), 10);
pos = percentPos + 2;
@@ -224,130 +223,7 @@
}
/**
- * Create a substitution with the given string.
- */
- /*
- public Substitution(String sub, Map maps) {
- ArrayList elements = new ArrayList();
- int pos = 0;
- int percentPos = 0;
- int dollarPos = 0;
-
- while (pos < sub.length()) {
- percentPos = sub.indexOf('%', pos);
- dollarPos = sub.indexOf('$', pos);
- // FIXME: System.out.println("S: " + sub + " pos: " + pos
+ " L: " + sub.length() + " %: " + percentPos + " $: " +
dollarPos);
- if (percentPos == -1 && dollarPos == -1) {
- // Static text
- StaticElement newElement = new StaticElement();
- newElement.value = sub.substring(pos, sub.length());
- pos = sub.length();
- elements.add(newElement);
- } else if (percentPos == -1 || ((dollarPos != -1) && (dollarPos <
percentPos))) {
- // $: backreference to rule or map lookup
- if (dollarPos + 1 == sub.length()) {
- throw new IllegalArgumentException(sub);
- }
- if (pos < dollarPos) {
- // Static text
- StaticElement newElement = new StaticElement();
- newElement.value = sub.substring(pos, dollarPos);
- pos = dollarPos;
- elements.add(newElement);
- }
- if (Character.isDigit(sub.charAt(dollarPos + 1))) {
- // $: backreference to rule
- RewriteRuleBackReferenceElement newElement = new
RewriteRuleBackReferenceElement();
- newElement.n = Character.digit(sub.charAt(dollarPos + 1), 10);
- pos = dollarPos + 2;
- elements.add(newElement);
- } else {
- // $: map lookup as ${mapname:key|default}
- MapElement newElement = new MapElement();
- int open = sub.indexOf('{', dollarPos);
- int colon = sub.indexOf(':', dollarPos);
- int def = sub.indexOf('|', dollarPos);
- int close = sub.indexOf('}', dollarPos);
- if (!(-1 < open && open < colon && colon <
close)) {
- throw new IllegalArgumentException(sub);
- }
- newElement.map = (RewriteMap) maps.get(sub.substring(open + 1,
colon));
- if (newElement.map == null) {
- throw new IllegalArgumentException(sub + ": No map: " +
sub.substring(open + 1, colon));
- }
- if (def > -1) {
- if (!(colon < def && def < close)) {
- throw new IllegalArgumentException(sub);
- }
- newElement.key = sub.substring(colon + 1, def);
- newElement.defaultValue = sub.substring(def + 1, close);
- } else {
- newElement.key = sub.substring(colon + 1, close);
- }
- pos = close + 1;
- elements.add(newElement);
- }
- } else {
- // %: backreference to cond or server variable
- if (percentPos + 1 == sub.length()) {
- throw new IllegalArgumentException(sub);
- }
- if (pos < percentPos) {
- // Static text
- StaticElement newElement = new StaticElement();
- newElement.value = sub.substring(pos, percentPos);
- pos = percentPos;
- elements.add(newElement);
- }
- if (Character.isDigit(sub.charAt(percentPos + 1))) {
- // %: backreference to cond
- RewriteCondBackReferenceElement newElement = new
RewriteCondBackReferenceElement();
- newElement.n = Character.digit(sub.charAt(percentPos + 1), 10);
- pos = percentPos + 2;
- elements.add(newElement);
- } else {
- // %: server variable as %{variable}
- SubstitutionElement newElement = null;
- int open = sub.indexOf('{', percentPos);
- int colon = sub.indexOf(':', percentPos);
- int close = sub.indexOf('}', percentPos);
- if (!(-1 < open && open < close)) {
- throw new IllegalArgumentException(sub);
- }
- if (colon > -1) {
- if (!(open < colon && colon < close)) {
- throw new IllegalArgumentException(sub);
- }
- String type = sub.substring(open + 1, colon);
- if (type.equals("ENV")) {
- newElement = new ServerVariableEnvElement();
- ((ServerVariableEnvElement) newElement).key =
sub.substring(colon + 1, close);
- } else if (type.equals("SSL")) {
- newElement = new ServerVariableSslElement();
- ((ServerVariableEnvElement) newElement).key =
sub.substring(colon + 1, close);
- } else if (type.equals("HTTP")) {
- newElement = new ServerVariableHttpElement();
- ((ServerVariableEnvElement) newElement).key =
sub.substring(colon + 1, close);
- } else {
- throw new IllegalArgumentException(sub + ": Bad type:
" + type);
- }
- } else {
- newElement = new ServerVariableElement();
- ((ServerVariableElement) newElement).key = sub.substring(open +
1, close);
- }
- pos = close + 1;
- elements.add(newElement);
- }
- }
- }
-
- this.elements = (SubstitutionElement[]) elements.toArray(new
SubstitutionElement[0]);
-
- }
- */
-
- /**
- * Evaluate the substituation based on the context
+ * Evaluate the substitution based on the context
*
* @param rule corresponding matched rule
* @param cond last matched condition
Modified: trunk/webapps/docs/changelog.xml
===================================================================
--- trunk/webapps/docs/changelog.xml 2008-12-05 17:07:03 UTC (rev 874)
+++ trunk/webapps/docs/changelog.xml 2008-12-05 17:07:59 UTC (rev 875)
@@ -57,6 +57,16 @@
<add>
Add a log formatter which logs on one line. (markt)
</add>
+ <update>
+ <jira>129</jira>: Support substitution for cookies and env flags in
RewriteRule, and map the env flag
+ to request attributes. (remm)
+ </update>
+ <update>
+ Support multiple env flags in RewriteRule. (remm)
+ </update>
+ <update>
+ Support all cookie flags in RewriteRule. (remm)
+ </update>
</changelog>
</subsection>
<subsection name="Jasper">
Modified: trunk/webapps/docs/rewrite.xml
===================================================================
--- trunk/webapps/docs/rewrite.xml 2008-12-05 17:07:03 UTC (rev 874)
+++ trunk/webapps/docs/rewrite.xml 2008-12-05 17:07:59 UTC (rev 875)
@@ -561,17 +561,11 @@
<li>
'<strong><code>env|E=</code></strong><em>VAR</em>:<em>VAL</em>'
(set <strong>e</strong>nvironment variable)<br />
- This forces an environment variable named <em>VAR</em> to
+ This forces a request attribute named <em>VAR</em> to
be set to the value <em>VAL</em>, where <em>VAL</em> can
contain regexp backreferences (<code>$N</code> and
<code>%N</code>) which will be expanded. You can use this
- flag more than once, to set more than one variable. The
- variables can later be dereferenced in many situations, most commonly
- from within XSSI (via <code><!--#echo
- var="VAR"--></code>) or CGI
(<code>$ENV{'VAR'}</code>).
- You can also dereference the variable in a later RewriteCond pattern, using
- <code>%{ENV:VAR}</code>. Use this to strip
- information from URLs, while maintaining a record of that
information.</li>
+ flag more than once, to set more than one variable.</li>
<li>'<strong><code>forbidden|F</code></strong>'
(force URL
to be <strong>f</strong>orbidden)<br />