Author: fschumacher Date: Thu Jan 22 20:28:51 2015 New Revision: 1654042 URL: http://svn.apache.org/r1654042 Log: Enable UEncoder instances to share safeChars BitSet while ensuring that the shared BitSet is immutable to be threadsafe.
Change Response to use UEncoder instances with shared safeChars. Merge 1654013 from /tomcat/trunk Modified: tomcat/tc8.0.x/trunk/ (props changed) tomcat/tc8.0.x/trunk/java/org/apache/catalina/connector/Response.java tomcat/tc8.0.x/trunk/java/org/apache/tomcat/util/buf/UEncoder.java tomcat/tc8.0.x/trunk/test/org/apache/tomcat/util/buf/TestUEncoder.java tomcat/tc8.0.x/trunk/webapps/docs/changelog.xml Propchange: tomcat/tc8.0.x/trunk/ ------------------------------------------------------------------------------ --- svn:mergeinfo (original) +++ svn:mergeinfo Thu Jan 22 20:28:51 2015 @@ -1 +1 @@ -/tomcat/trunk:1636524,1637156,1637176,1637188,1637331,1637684,1637695,1638720-1638725,1639653,1640010,1640083-1640084,1640088,1640275,1640322,1640347,1640361,1640365,1640403,1640410,1640652,1640655-1640658,1640688,1640700-1640883,1640903,1640976,1640978,1641000,1641026,1641038-1641039,1641051-1641052,1641058,1641064,1641300,1641369,1641374,1641380,1641486,1641634,1641656-1641692,1641704,1641707-1641718,1641720-1641722,1641735,1641981,1642233,1642280,1642554,1642564,1642595,1642606,1642668,1642679,1642697,1642699,1642766,1643002,1643045,1643054-1643055,1643066,1643121,1643128,1643206,1643209-1643210,1643216,1643249,1643270,1643283,1643309-1643310,1643323,1643365-1643366,1643370-1643371,1643465,1643474,1643536,1643570,1643634,1643649,1643651,1643654,1643675,1643731,1643733-1643734,1643761,1643766,1643814,1643937,1643963,1644017,1644169,1644201-1644203,1644321,1644323,1644516,1644523,1644529,1644535,1644730,1644768,1644784-1644785,1644790,1644793,1644815,1644884,1644886,1644890,1644892 ,1644910,1644924,1644929-1644930,1644935,1644989,1645011,1645247,1645355,1645357-1645358,1645455,1645465,1645469,1645471,1645473,1645475,1645486-1645488,1645626,1645641,1645685,1645743,1645763,1645951-1645953,1645955,1645993,1646098-1646106,1646178,1646220,1646302,1646304,1646420,1646470-1646471,1646476,1646559,1646717-1646723,1646773,1647026,1647042,1647530,1647655,1648304,1648815,1648907,1650081,1650365,1651116,1651120,1651280,1651470,1652938,1652970,1653041,1653471,1653550,1653574,1653797,1653815-1653816,1653819,1653840,1653857 +/tomcat/trunk:1636524,1637156,1637176,1637188,1637331,1637684,1637695,1638720-1638725,1639653,1640010,1640083-1640084,1640088,1640275,1640322,1640347,1640361,1640365,1640403,1640410,1640652,1640655-1640658,1640688,1640700-1640883,1640903,1640976,1640978,1641000,1641026,1641038-1641039,1641051-1641052,1641058,1641064,1641300,1641369,1641374,1641380,1641486,1641634,1641656-1641692,1641704,1641707-1641718,1641720-1641722,1641735,1641981,1642233,1642280,1642554,1642564,1642595,1642606,1642668,1642679,1642697,1642699,1642766,1643002,1643045,1643054-1643055,1643066,1643121,1643128,1643206,1643209-1643210,1643216,1643249,1643270,1643283,1643309-1643310,1643323,1643365-1643366,1643370-1643371,1643465,1643474,1643536,1643570,1643634,1643649,1643651,1643654,1643675,1643731,1643733-1643734,1643761,1643766,1643814,1643937,1643963,1644017,1644169,1644201-1644203,1644321,1644323,1644516,1644523,1644529,1644535,1644730,1644768,1644784-1644785,1644790,1644793,1644815,1644884,1644886,1644890,1644892 ,1644910,1644924,1644929-1644930,1644935,1644989,1645011,1645247,1645355,1645357-1645358,1645455,1645465,1645469,1645471,1645473,1645475,1645486-1645488,1645626,1645641,1645685,1645743,1645763,1645951-1645953,1645955,1645993,1646098-1646106,1646178,1646220,1646302,1646304,1646420,1646470-1646471,1646476,1646559,1646717-1646723,1646773,1647026,1647042,1647530,1647655,1648304,1648815,1648907,1650081,1650365,1651116,1651120,1651280,1651470,1652938,1652970,1653041,1653471,1653550,1653574,1653797,1653815-1653816,1653819,1653840,1653857,1654013 Modified: tomcat/tc8.0.x/trunk/java/org/apache/catalina/connector/Response.java URL: http://svn.apache.org/viewvc/tomcat/tc8.0.x/trunk/java/org/apache/catalina/connector/Response.java?rev=1654042&r1=1654041&r2=1654042&view=diff ============================================================================== --- tomcat/tc8.0.x/trunk/java/org/apache/catalina/connector/Response.java (original) +++ tomcat/tc8.0.x/trunk/java/org/apache/catalina/connector/Response.java Thu Jan 22 20:28:51 2015 @@ -50,6 +50,7 @@ import org.apache.catalina.util.SessionC import org.apache.coyote.ActionCode; import org.apache.tomcat.util.buf.CharChunk; import org.apache.tomcat.util.buf.UEncoder; +import org.apache.tomcat.util.buf.UEncoder.SafeCharsSet; import org.apache.tomcat.util.http.FastHttpDateFormat; import org.apache.tomcat.util.http.MimeHeaders; import org.apache.tomcat.util.http.parser.MediaTypeCache; @@ -89,7 +90,6 @@ public class Response } public Response() { - urlEncoder.addSafeCharacter('/'); } @@ -242,7 +242,7 @@ public class Response /** * URL encoder. */ - protected final UEncoder urlEncoder = new UEncoder(); + protected final UEncoder urlEncoder = new UEncoder(SafeCharsSet.WITH_SLASH); /** Modified: tomcat/tc8.0.x/trunk/java/org/apache/tomcat/util/buf/UEncoder.java URL: http://svn.apache.org/viewvc/tomcat/tc8.0.x/trunk/java/org/apache/tomcat/util/buf/UEncoder.java?rev=1654042&r1=1654041&r2=1654042&view=diff ============================================================================== --- tomcat/tc8.0.x/trunk/java/org/apache/tomcat/util/buf/UEncoder.java (original) +++ tomcat/tc8.0.x/trunk/java/org/apache/tomcat/util/buf/UEncoder.java Thu Jan 22 20:28:51 2015 @@ -32,6 +32,22 @@ import java.util.BitSet; */ public final class UEncoder { + public enum SafeCharsSet { + WITH_SLASH("/"), DEFAULT(""); + private final BitSet safeChars; + + private BitSet getSafeChars() { + return this.safeChars; + } + + private SafeCharsSet(String additionalSafeChars) { + safeChars = initialSafeChars(); + for (char c : additionalSafeChars.toCharArray()) { + safeChars.set(c); + } + } + } + // Not static - the set may differ ( it's better than adding // an extra check for "/", "+", etc private BitSet safeChars=null; @@ -39,14 +55,34 @@ public final class UEncoder { private ByteChunk bb=null; private CharChunk cb=null; private CharChunk output=null; + private final boolean readOnlySafeChars; private final String ENCODING = "UTF8"; public UEncoder() { - initSafeChars(); + this.safeChars = initialSafeChars(); + readOnlySafeChars = false; } + /** + * Create a UEncoder with an unmodifiable safe character set. + * <p> + * Calls to {@link UEncoder#addSafeCharacter(char) addSafeCharacter(char)} + * on instances created by this constructor will throw an + * {@link IllegalStateException}. + * + * @param safeCharsSet + * safe characters for this encoder + */ + public UEncoder(SafeCharsSet safeCharsSet) { + this.safeChars = safeCharsSet.getSafeChars(); + readOnlySafeChars = true; + } + public void addSafeCharacter( char c ) { + if (readOnlySafeChars) { + throw new IllegalStateException("UEncoders safeChararacters are read only"); + } safeChars.set( c ); } @@ -116,33 +152,34 @@ public final class UEncoder { // -------------------- Internal implementation -------------------- - private void initSafeChars() { - safeChars=new BitSet(128); + private static BitSet initialSafeChars() { + BitSet initialSafeChars=new BitSet(128); int i; for (i = 'a'; i <= 'z'; i++) { - safeChars.set(i); + initialSafeChars.set(i); } for (i = 'A'; i <= 'Z'; i++) { - safeChars.set(i); + initialSafeChars.set(i); } for (i = '0'; i <= '9'; i++) { - safeChars.set(i); + initialSafeChars.set(i); } //safe - safeChars.set('$'); - safeChars.set('-'); - safeChars.set('_'); - safeChars.set('.'); + initialSafeChars.set('$'); + initialSafeChars.set('-'); + initialSafeChars.set('_'); + initialSafeChars.set('.'); // Dangerous: someone may treat this as " " // RFC1738 does allow it, it's not reserved - // safeChars.set('+'); + // initialSafeChars.set('+'); //extra - safeChars.set('!'); - safeChars.set('*'); - safeChars.set('\''); - safeChars.set('('); - safeChars.set(')'); - safeChars.set(','); + initialSafeChars.set('!'); + initialSafeChars.set('*'); + initialSafeChars.set('\''); + initialSafeChars.set('('); + initialSafeChars.set(')'); + initialSafeChars.set(','); + return initialSafeChars; } } Modified: tomcat/tc8.0.x/trunk/test/org/apache/tomcat/util/buf/TestUEncoder.java URL: http://svn.apache.org/viewvc/tomcat/tc8.0.x/trunk/test/org/apache/tomcat/util/buf/TestUEncoder.java?rev=1654042&r1=1654041&r2=1654042&view=diff ============================================================================== --- tomcat/tc8.0.x/trunk/test/org/apache/tomcat/util/buf/TestUEncoder.java (original) +++ tomcat/tc8.0.x/trunk/test/org/apache/tomcat/util/buf/TestUEncoder.java Thu Jan 22 20:28:51 2015 @@ -20,6 +20,9 @@ package org.apache.tomcat.util.buf; import java.io.IOException; import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + +import org.apache.tomcat.util.buf.UEncoder.SafeCharsSet; import org.junit.Test; /** @@ -45,4 +48,27 @@ public class TestUEncoder { assertTrue(urlEncoder.encodeURL(s, 0, s.length()) .equals("%f0%90%90%81")); } + + @Test + public void testEncodeURLWithSlashInit() throws IOException { + UEncoder urlEncoder = new UEncoder(SafeCharsSet.WITH_SLASH); + + String s = "a+b/c/d+e.class"; + assertTrue(urlEncoder.encodeURL(s, 0, s.length()).equals( + "a%2bb/c/d%2be.class")); + assertTrue(urlEncoder.encodeURL(s, 2, s.length() - 2).equals( + "b/c/d%2be.cla")); + + try { + urlEncoder.addSafeCharacter('+'); + fail(); + } catch (IllegalStateException e) { + // OK + } + + s = new String(new char[] { 0xD801, 0xDC01 }); + assertTrue(urlEncoder.encodeURL(s, 0, s.length()) + .equals("%f0%90%90%81")); + } + } Modified: tomcat/tc8.0.x/trunk/webapps/docs/changelog.xml URL: http://svn.apache.org/viewvc/tomcat/tc8.0.x/trunk/webapps/docs/changelog.xml?rev=1654042&r1=1654041&r2=1654042&view=diff ============================================================================== --- tomcat/tc8.0.x/trunk/webapps/docs/changelog.xml (original) +++ tomcat/tc8.0.x/trunk/webapps/docs/changelog.xml Thu Jan 22 20:28:51 2015 @@ -94,6 +94,10 @@ the request when using non-blocking reads with the HTTP BIO connector. (markt) </fix> + <fix> + Change Response to use UEncoder instances with shared safeChars. + (fschumacher) + </fix> </changelog> </subsection> <subsection name="Jasper"> --------------------------------------------------------------------- To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org For additional commands, e-mail: dev-h...@tomcat.apache.org