1 /*
2  * Licensed to the Apache Software Foundation (ASF) under one or more
3  * contributor license agreements.  See the NOTICE file distributed with
4  * this work for additional information regarding copyright ownership.
5  * The ASF licenses this file to You under the Apache License, Version 2.0
6  * (the "License"); you may not use this file except in compliance with
7  * the License.  You may obtain a copy of the License at
8  *
9  *      http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */

17 package org.apache.tomcat.util.http.parser;
18
19 import java.io.IOException;
20 import java.io.Reader;
21 import java.io.StringReader;
22 import java.util.Collection;
23 import java.util.Enumeration;
24 import java.util.Locale;
25
26 public class TokenList {
27
28     private TokenList() {
29         // Utility class. Hide default constructor.
30     }
31
32
33     /**
34      * Parses an enumeration of header values of the form 1#token, forcing all
35      * parsed values to lower case.
36      *
37      * @param inputs     The headers to parse
38      * @param collection The Collection (usually a list of a set) to which the
39      *                       parsed tokens should be added
40      *
41      * @return {@code} true if the header values were parsed cleanly, otherwise
42      *         {@code false} (e.g. if a non-token value was encountered)
43      *
44      * @throws IOException If an I/O error occurs reading the header
45      */

46     public static boolean parseTokenList(Enumeration<String> inputs, Collection<String> collection) throws IOException {
47         boolean result = true;
48         while (inputs.hasMoreElements()) {
49             String nextHeaderValue = inputs.nextElement();
50             if (nextHeaderValue != null) {
51                 if (!TokenList.parseTokenList(new StringReader(nextHeaderValue), collection)) {
52                     result = false;
53                 }
54             }
55         }
56         return result;
57     }
58
59
60     /**
61      * Parses a header of the form 1#token, forcing all parsed values to lower
62      * case. This is typically used when header values are case-insensitive.
63      *
64      * @param input      The header to parse
65      * @param collection The Collection (usually a list of a set) to which the
66      *                       parsed tokens should be added
67      *
68      * @return {@code} true if the header was parsed cleanly, otherwise
69      *         {@code false} (e.g. if a non-token value was encountered)
70      *
71      * @throws IOException If an I/O error occurs reading the header
72      */

73     public static boolean parseTokenList(Reader input, Collection<String> collection) throws IOException {
74         boolean invalid = false;
75         boolean valid = false;
76
77         do {
78             String fieldName = HttpParser.readToken(input);
79             if (fieldName == null) {
80                 // Invalid field-name, skip to the next one
81                 invalid = true;
82                 HttpParser.skipUntil(input, 0, ',');
83                 continue;
84             }
85
86             if (fieldName.length() == 0) {
87                 // No more data to read
88                 break;
89             }
90
91             SkipResult skipResult = HttpParser.skipConstant(input, ",");
92             if (skipResult == SkipResult.EOF) {
93                 // EOF
94                 valid = true;
95                 collection.add(fieldName.toLowerCase(Locale.ENGLISH));
96                 break;
97             } else if (skipResult == SkipResult.FOUND) {
98                 valid = true;
99                 collection.add(fieldName.toLowerCase(Locale.ENGLISH));
100                 continue;
101             } else {
102                 // Not a token - ignore it
103                 invalid = true;
104                 HttpParser.skipUntil(input, 0, ',');
105                 continue;
106             }
107         } while (true);
108
109         // Only return true if at least one valid token was read and no invalid
110         // entries were found
111         return valid && !invalid;
112     }
113 }
114