View | Details | Raw Unified | Return to bug 57420
Collapse All | Expand All

(-)a/java/org/apache/catalina/connector/Response.java (-2 / +2 lines)
Lines 51-56 import org.apache.catalina.util.RequestUtil; Link Here
51
import org.apache.catalina.util.SessionConfig;
51
import org.apache.catalina.util.SessionConfig;
52
import org.apache.tomcat.util.buf.CharChunk;
52
import org.apache.tomcat.util.buf.CharChunk;
53
import org.apache.tomcat.util.buf.UEncoder;
53
import org.apache.tomcat.util.buf.UEncoder;
54
import org.apache.tomcat.util.buf.UEncoder.SafeCharsSet;
54
import org.apache.tomcat.util.http.FastHttpDateFormat;
55
import org.apache.tomcat.util.http.FastHttpDateFormat;
55
import org.apache.tomcat.util.http.MimeHeaders;
56
import org.apache.tomcat.util.http.MimeHeaders;
56
import org.apache.tomcat.util.http.ServerCookie;
57
import org.apache.tomcat.util.http.ServerCookie;
Lines 91-97 public class Response Link Here
91
    }
92
    }
92
93
93
    public Response() {
94
    public Response() {
94
        urlEncoder.addSafeCharacter('/');
95
    }
95
    }
96
96
97
97
Lines 282-288 public class Response Link Here
282
    /**
282
    /**
283
     * URL encoder.
283
     * URL encoder.
284
     */
284
     */
285
    protected UEncoder urlEncoder = new UEncoder();
285
    protected UEncoder urlEncoder = new UEncoder(SafeCharsSet.WITH_SLASH);
286
286
287
287
288
    /**
288
    /**
(-)a/java/org/apache/naming/resources/DirContextURLConnection.java (-6 / +3 lines)
Lines 42-47 import javax.naming.directory.DirContext; Link Here
42
import org.apache.naming.JndiPermission;
42
import org.apache.naming.JndiPermission;
43
import org.apache.tomcat.util.buf.UDecoder;
43
import org.apache.tomcat.util.buf.UDecoder;
44
import org.apache.tomcat.util.buf.UEncoder;
44
import org.apache.tomcat.util.buf.UEncoder;
45
import org.apache.tomcat.util.buf.UEncoder.SafeCharsSet;
45
import org.apache.tomcat.util.http.FastHttpDateFormat;
46
import org.apache.tomcat.util.http.FastHttpDateFormat;
46
47
47
/**
48
/**
Lines 57-67 import org.apache.tomcat.util.http.FastHttpDateFormat; Link Here
57
public class DirContextURLConnection extends URLConnection {
58
public class DirContextURLConnection extends URLConnection {
58
59
59
    private static final UDecoder URL_DECODER = new UDecoder();
60
    private static final UDecoder URL_DECODER = new UDecoder();
60
    private static final UEncoder URL_ENCODER = new UEncoder();
61
62
    static{
63
        URL_ENCODER.addSafeCharacter('/');
64
    }
65
61
66
    // ----------------------------------------------------------- Constructors
62
    // ----------------------------------------------------------- Constructors
67
63
Lines 436-446 public class DirContextURLConnection extends URLConnection { Link Here
436
            try {
432
            try {
437
                NamingEnumeration<NameClassPair> enumeration =
433
                NamingEnumeration<NameClassPair> enumeration =
438
                    collection.list("/");
434
                    collection.list("/");
435
                UEncoder urlEncoder = new UEncoder(SafeCharsSet.WITH_SLASH);
439
                while (enumeration.hasMoreElements()) {
436
                while (enumeration.hasMoreElements()) {
440
                    NameClassPair ncp = enumeration.nextElement();
437
                    NameClassPair ncp = enumeration.nextElement();
441
                    String s = ncp.getName();
438
                    String s = ncp.getName();
442
                    result.addElement(
439
                    result.addElement(
443
                            URL_ENCODER.encodeURL(s, 0, s.length()).toString());
440
                            urlEncoder.encodeURL(s, 0, s.length()).toString());
444
                }
441
                }
445
            } catch (NamingException e) {
442
            } catch (NamingException e) {
446
                // Unexpected exception
443
                // Unexpected exception
(-)a/java/org/apache/tomcat/util/buf/UEncoder.java (-33 / +71 lines)
Lines 31-36 import java.util.BitSet; Link Here
31
 */
31
 */
32
public final class UEncoder {
32
public final class UEncoder {
33
33
34
    public enum SafeCharsSet {
35
        WITH_SLASH("/"), DEFAULT("");
36
        private final BitSet safeChars;
37
38
        private BitSet getSafeChars() {
39
            return this.safeChars;
40
        }
41
42
        private SafeCharsSet(String additionalSafeChars) {
43
            safeChars = initialSafeChars();
44
            for (char c : additionalSafeChars.toCharArray()) {
45
                safeChars.set(c);
46
            }
47
        }
48
    }
49
34
    // Not static - the set may differ ( it's better than adding
50
    // Not static - the set may differ ( it's better than adding
35
    // an extra check for "/", "+", etc
51
    // an extra check for "/", "+", etc
36
    private BitSet safeChars=null;
52
    private BitSet safeChars=null;
Lines 38-48 public final class UEncoder { Link Here
38
    private ByteChunk bb=null;
54
    private ByteChunk bb=null;
39
    private CharChunk cb=null;
55
    private CharChunk cb=null;
40
    private CharChunk output=null;
56
    private CharChunk output=null;
57
    private final boolean readOnlySafeChars;
41
58
42
    private String encoding="UTF8";
59
    private String encoding="UTF8";
43
60
44
    public UEncoder() {
61
    public UEncoder() {
45
        initSafeChars();
62
        this.safeChars = initialSafeChars();
63
        readOnlySafeChars = false;
64
    }
65
66
    /**
67
     * Create a UEncoder with an unmodifiable safe character set.
68
     * <p>
69
     * Calls to {@link UEncoder#addSafeCharacter(char) addSafeCharacter(char)}
70
     * on instances created by this constructor will throw an
71
     * {@link IllegalStateException}.
72
     * 
73
     * @param safeCharsSet
74
     *            safe characters for this encoder
75
     */
76
    public UEncoder(SafeCharsSet safeCharsSet) {
77
        this.safeChars = safeCharsSet.getSafeChars();
78
        readOnlySafeChars = true;
46
    }
79
    }
47
80
48
    /**
81
    /**
Lines 54-59 public final class UEncoder { Link Here
54
    }
87
    }
55
88
56
    public void addSafeCharacter( char c ) {
89
    public void addSafeCharacter( char c ) {
90
        if (readOnlySafeChars) {
91
            throw new IllegalStateException("UEncoders safeChararacters are read only");
92
        }
57
        safeChars.set( c );
93
        safeChars.set( c );
58
    }
94
    }
59
95
Lines 120-155 public final class UEncoder { Link Here
120
           out.append(ch);
156
           out.append(ch);
121
       }
157
       }
122
   }
158
   }
123
   
159
124
    // -------------------- Internal implementation --------------------
160
   // -------------------- Internal implementation --------------------
125
161
126
    private void initSafeChars() {
162
   private static BitSet initialSafeChars() {
127
        safeChars=new BitSet(128);
163
       BitSet initialSafeChars = new BitSet(128);
128
        int i;
164
       int i;
129
        for (i = 'a'; i <= 'z'; i++) {
165
       for (i = 'a'; i <= 'z'; i++) {
130
            safeChars.set(i);
166
           initialSafeChars.set(i);
131
        }
167
       }
132
        for (i = 'A'; i <= 'Z'; i++) {
168
       for (i = 'A'; i <= 'Z'; i++) {
133
            safeChars.set(i);
169
           initialSafeChars.set(i);
134
        }
170
       }
135
        for (i = '0'; i <= '9'; i++) {
171
       for (i = '0'; i <= '9'; i++) {
136
            safeChars.set(i);
172
           initialSafeChars.set(i);
137
        }
173
       }
138
        //safe
174
       // safe
139
        safeChars.set('$');
175
       initialSafeChars.set('$');
140
        safeChars.set('-');
176
       initialSafeChars.set('-');
141
        safeChars.set('_');
177
       initialSafeChars.set('_');
142
        safeChars.set('.');
178
       initialSafeChars.set('.');
143
179
144
        // Dangerous: someone may treat this as " "
180
       // Dangerous: someone may treat this as " "
145
        // RFC1738 does allow it, it's not reserved
181
       // RFC1738 does allow it, it's not reserved
146
        //    safeChars.set('+');
182
       // safeChars.set('+');
147
        //extra
183
       // extra
148
        safeChars.set('!');
184
       initialSafeChars.set('!');
149
        safeChars.set('*');
185
       initialSafeChars.set('*');
150
        safeChars.set('\'');
186
       initialSafeChars.set('\'');
151
        safeChars.set('(');
187
       initialSafeChars.set('(');
152
        safeChars.set(')');
188
       initialSafeChars.set(')');
153
        safeChars.set(',');
189
       initialSafeChars.set(',');
154
    }
190
       return initialSafeChars;
191
   }
192
155
}
193
}
(-)a/test/org/apache/tomcat/util/buf/TestUEncoder.java (-1 / +26 lines)
Lines 20-25 package org.apache.tomcat.util.buf; Link Here
20
import java.io.IOException;
20
import java.io.IOException;
21
21
22
import static org.junit.Assert.assertTrue;
22
import static org.junit.Assert.assertTrue;
23
import static org.junit.Assert.fail;
24
25
import org.apache.tomcat.util.buf.UEncoder.SafeCharsSet;
23
import org.junit.Test;
26
import org.junit.Test;
24
27
25
/**
28
/**
Lines 45-48 public class TestUEncoder { Link Here
45
        assertTrue(urlEncoder.encodeURL(s, 0, s.length())
48
        assertTrue(urlEncoder.encodeURL(s, 0, s.length())
46
                .equals("%f0%90%90%81"));
49
                .equals("%f0%90%90%81"));
47
    }
50
    }
51
52
    @Test
53
    public void testEncodeURLWithSlashInit() throws IOException {
54
        UEncoder urlEncoder = new UEncoder(SafeCharsSet.WITH_SLASH);
55
56
        String s = "a+b/c/d+e.class";
57
        assertTrue(urlEncoder.encodeURL(s, 0, s.length()).equals(
58
                "a%2bb/c/d%2be.class"));
59
        assertTrue(urlEncoder.encodeURL(s, 2, s.length() - 2).equals(
60
                "b/c/d%2be.cla"));
61
62
        try {
63
            urlEncoder.addSafeCharacter('+');
64
            fail();
65
        } catch (IllegalStateException e) {
66
            // OK
67
        }
68
69
        s = new String(new char[] { 0xD801, 0xDC01 });
70
        assertTrue(urlEncoder.encodeURL(s, 0, s.length())
71
                .equals("%f0%90%90%81"));
72
    }
73
48
}
74
}
49
- 

Return to bug 57420