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