File: CookieSupport.java

package info (click to toggle)
tomcat7 7.0.56-3%2Bdeb8u11
  • links: PTS, VCS
  • area: main
  • in suites: jessie
  • size: 35,688 kB
  • ctags: 41,823
  • sloc: java: 249,464; xml: 51,553; jsp: 3,037; sh: 1,361; perl: 269; makefile: 195
file content (236 lines) | stat: -rw-r--r-- 8,136 bytes parent folder | download | duplicates (4)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.tomcat.util.http;


/**
 * Static constants for this package.
 */
public final class CookieSupport {

    // --------------------------------------------------------------- Constants
    /**
     * If set to true, we parse cookies strictly according to the servlet,
     * cookie and HTTP specs by default.
     */
    public static final boolean STRICT_SERVLET_COMPLIANCE;

    /**
     * If true, cookie values are allowed to contain an equals character without
     * being quoted.
     */
    public static final boolean ALLOW_EQUALS_IN_VALUE;

    /**
     * If true, separators that are not explicitly dis-allowed by the v0 cookie
     * spec but are disallowed by the HTTP spec will be allowed in v0 cookie
     * names and values. These characters are: \"()/:<=>?@[\\]{} Note that the
     * inclusion of / depends on the value of {@link #FWD_SLASH_IS_SEPARATOR}.
     */
    public static final boolean ALLOW_HTTP_SEPARATORS_IN_V0;

    /**
     * If set to false, we don't use the IE6/7 Max-Age/Expires work around.
     * Default is usually true. If STRICT_SERVLET_COMPLIANCE==true then default
     * is false. Explicitly setting always takes priority.
     */
    public static final boolean ALWAYS_ADD_EXPIRES;

    /**
     * If set to true, the <code>/</code> character will be treated as a
     * separator. Default is usually false. If STRICT_SERVLET_COMPLIANCE==true
     * then default is true. Explicitly setting always takes priority.
     */
    public static final boolean FWD_SLASH_IS_SEPARATOR;

    /**
     * If true, name only cookies will be permitted.
     */
    public static final boolean ALLOW_NAME_ONLY;

    /**
     * The list of separators that apply to version 0 cookies. To quote the
     * spec, these are comma, semi-colon and white-space. The HTTP spec
     * definition of linear white space is [CRLF] 1*( SP | HT )
     */
    private static final char[] V0_SEPARATORS = {',', ';', ' ', '\t'};
    private static final boolean[] V0_SEPARATOR_FLAGS = new boolean[128];

    /**
     * The list of separators that apply to version 1 cookies. This may or may
     * not include '/' depending on the setting of
     * {@link #FWD_SLASH_IS_SEPARATOR}.
     */
    private static final char[] HTTP_SEPARATORS;
    private static final boolean[] HTTP_SEPARATOR_FLAGS = new boolean[128];

    static {
        STRICT_SERVLET_COMPLIANCE = Boolean.valueOf(System.getProperty(
                "org.apache.catalina.STRICT_SERVLET_COMPLIANCE",
                "false")).booleanValue();

        ALLOW_EQUALS_IN_VALUE = Boolean.valueOf(System.getProperty(
                "org.apache.tomcat.util.http.ServerCookie.ALLOW_EQUALS_IN_VALUE",
                "false")).booleanValue();

        ALLOW_HTTP_SEPARATORS_IN_V0 = Boolean.valueOf(System.getProperty(
                "org.apache.tomcat.util.http.ServerCookie.ALLOW_HTTP_SEPARATORS_IN_V0",
                "false")).booleanValue();

        String alwaysAddExpires = System.getProperty(
        "org.apache.tomcat.util.http.ServerCookie.ALWAYS_ADD_EXPIRES");
        if (alwaysAddExpires == null) {
            ALWAYS_ADD_EXPIRES = !STRICT_SERVLET_COMPLIANCE;
        } else {
            ALWAYS_ADD_EXPIRES =
                Boolean.valueOf(alwaysAddExpires).booleanValue();
        }

        String  fwdSlashIsSeparator = System.getProperty(
                "org.apache.tomcat.util.http.ServerCookie.FWD_SLASH_IS_SEPARATOR");
        if (fwdSlashIsSeparator == null) {
            FWD_SLASH_IS_SEPARATOR = STRICT_SERVLET_COMPLIANCE;
        } else {
            FWD_SLASH_IS_SEPARATOR =
                Boolean.valueOf(fwdSlashIsSeparator).booleanValue();
        }

        ALLOW_NAME_ONLY = Boolean.valueOf(System.getProperty(
                "org.apache.tomcat.util.http.ServerCookie.ALLOW_NAME_ONLY",
                "false")).booleanValue();


        /*
        Excluding the '/' char by default violates the RFC, but
        it looks like a lot of people put '/'
        in unquoted values: '/': ; //47
        '\t':9 ' ':32 '\"':34 '(':40 ')':41 ',':44 ':':58 ';':59 '<':60
        '=':61 '>':62 '?':63 '@':64 '[':91 '\\':92 ']':93 '{':123 '}':125
        */
        if (CookieSupport.FWD_SLASH_IS_SEPARATOR) {
            HTTP_SEPARATORS = new char[] { '\t', ' ', '\"', '(', ')', ',', '/',
                    ':', ';', '<', '=', '>', '?', '@', '[', '\\', ']', '{', '}' };
        } else {
            HTTP_SEPARATORS = new char[] { '\t', ' ', '\"', '(', ')', ',',
                    ':', ';', '<', '=', '>', '?', '@', '[', '\\', ']', '{', '}' };
        }
        for (int i = 0; i < 128; i++) {
            V0_SEPARATOR_FLAGS[i] = false;
            HTTP_SEPARATOR_FLAGS[i] = false;
        }
        for (int i = 0; i < V0_SEPARATORS.length; i++) {
            V0_SEPARATOR_FLAGS[V0_SEPARATORS[i]] = true;
        }
        for (int i = 0; i < HTTP_SEPARATORS.length; i++) {
            HTTP_SEPARATOR_FLAGS[HTTP_SEPARATORS[i]] = true;
        }

    }

    // ----------------------------------------------------------------- Methods

    /**
     * Returns true if the byte is a separator as defined by V0 of the cookie
     * spec.
     */
    public static final boolean isV0Separator(final char c) {
        if (c < 0x20 || c >= 0x7f) {
            if (c != 0x09) {
                throw new IllegalArgumentException(
                        "Control character in cookie value or attribute.");
            }
        }

        return V0_SEPARATOR_FLAGS[c];
    }

    public static boolean isV0Token(String value) {
        if( value==null) {
            return false;
        }

        int i = 0;
        int len = value.length();

        if (alreadyQuoted(value)) {
            i++;
            len--;
        }

        for (; i < len; i++) {
            char c = value.charAt(i);

            if (isV0Separator(c)) {
                return true;
            }
        }
        return false;
    }

    /**
     * Returns true if the byte is a separator as defined by V1 of the cookie
     * spec, RFC2109.
     * @throws IllegalArgumentException if a control character was supplied as
     *         input
     */
    public static final boolean isHttpSeparator(final char c) {
        if (c < 0x20 || c >= 0x7f) {
            if (c != 0x09) {
                throw new IllegalArgumentException(
                        "Control character in cookie value or attribute.");
            }
        }

        return HTTP_SEPARATOR_FLAGS[c];
    }

    public static boolean isHttpToken(String value) {
        if( value==null) {
            return false;
        }

        int i = 0;
        int len = value.length();

        if (alreadyQuoted(value)) {
            i++;
            len--;
        }

        for (; i < len; i++) {
            char c = value.charAt(i);

            if (isHttpSeparator(c)) {
                return true;
            }
        }
        return false;
    }

    public static boolean alreadyQuoted (String value) {
        if (value==null || value.length() < 2) {
            return false;
        }
        return (value.charAt(0)=='\"' && value.charAt(value.length()-1)=='\"');
    }


    // ------------------------------------------------------------- Constructor
    private CookieSupport() {
        // Utility class. Don't allow instances to be created.
    }
}