This commit is contained in:
2024-11-30 19:03:49 +08:00
commit 1e6763c160
3806 changed files with 737676 additions and 0 deletions

View File

@@ -0,0 +1,74 @@
/*
* 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.parser;
import java.io.IOException;
import java.io.StringReader;
import java.util.ArrayList;
import java.util.List;
public class AcceptEncoding {
private final String encoding;
private final double quality;
protected AcceptEncoding(String encoding, double quality) {
this.encoding = encoding;
this.quality = quality;
}
public String getEncoding() {
return encoding;
}
public double getQuality() {
return quality;
}
public static List<AcceptEncoding> parse(StringReader input) throws IOException {
List<AcceptEncoding> result = new ArrayList<>();
do {
String encoding = HttpParser.readToken(input);
if (encoding == null) {
// Invalid encoding, skip to the next one
HttpParser.skipUntil(input, 0, ',');
continue;
}
if (encoding.length() == 0) {
// No more data to read
break;
}
// See if a quality has been provided
double quality = 1;
SkipResult lookForSemiColon = HttpParser.skipConstant(input, ";");
if (lookForSemiColon == SkipResult.FOUND) {
quality = HttpParser.readWeight(input, ',');
}
if (quality > 0) {
result.add(new AcceptEncoding(encoding, quality));
}
} while (true);
return result;
}
}

View File

@@ -0,0 +1,78 @@
/*
* 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.parser;
import java.io.IOException;
import java.io.StringReader;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
public class AcceptLanguage {
private final Locale locale;
private final double quality;
protected AcceptLanguage(Locale locale, double quality) {
this.locale = locale;
this.quality = quality;
}
public Locale getLocale() {
return locale;
}
public double getQuality() {
return quality;
}
public static List<AcceptLanguage> parse(StringReader input) throws IOException {
List<AcceptLanguage> result = new ArrayList<>();
do {
// Token is broader than what is permitted in a language tag
// (alphanumeric + '-') but any invalid values that slip through
// will be caught later
String languageTag = HttpParser.readToken(input);
if (languageTag == null) {
// Invalid tag, skip to the next one
HttpParser.skipUntil(input, 0, ',');
continue;
}
if (languageTag.length() == 0) {
// No more data to read
break;
}
// See if a quality has been provided
double quality = 1;
SkipResult lookForSemiColon = HttpParser.skipConstant(input, ";");
if (lookForSemiColon == SkipResult.FOUND) {
quality = HttpParser.readWeight(input, ',');
}
if (quality > 0) {
result.add(new AcceptLanguage(Locale.forLanguageTag(languageTag), quality));
}
} while (true);
return result;
}
}

View File

@@ -0,0 +1,146 @@
/*
* 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.parser;
import java.io.IOException;
import java.io.StringReader;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
import org.apache.tomcat.util.res.StringManager;
/**
* Parser for an "Authorization" header.
*/
public class Authorization {
private static final StringManager sm = StringManager.getManager(Authorization.class);
@SuppressWarnings("unused") // Unused due to buggy client implementations
private static final Integer FIELD_TYPE_TOKEN = Integer.valueOf(0);
private static final Integer FIELD_TYPE_QUOTED_STRING = Integer.valueOf(1);
private static final Integer FIELD_TYPE_TOKEN_OR_QUOTED_STRING = Integer.valueOf(2);
private static final Integer FIELD_TYPE_LHEX = Integer.valueOf(3);
private static final Integer FIELD_TYPE_QUOTED_TOKEN = Integer.valueOf(4);
private static final Map<String,Integer> fieldTypes = new HashMap<>();
static {
// Digest field types.
// Note: These are more relaxed than RFC2617. This adheres to the
// recommendation of RFC2616 that servers are tolerant of buggy
// clients when they can be so without ambiguity.
fieldTypes.put("username", FIELD_TYPE_QUOTED_STRING);
fieldTypes.put("realm", FIELD_TYPE_QUOTED_STRING);
fieldTypes.put("nonce", FIELD_TYPE_QUOTED_STRING);
fieldTypes.put("digest-uri", FIELD_TYPE_QUOTED_STRING);
// RFC2617 says response is <">32LHEX<">. 32LHEX will also be accepted
fieldTypes.put("response", FIELD_TYPE_LHEX);
// RFC2617 says algorithm is token. <">token<"> will also be accepted
fieldTypes.put("algorithm", FIELD_TYPE_QUOTED_TOKEN);
fieldTypes.put("cnonce", FIELD_TYPE_QUOTED_STRING);
fieldTypes.put("opaque", FIELD_TYPE_QUOTED_STRING);
// RFC2617 says qop is token. <">token<"> will also be accepted
fieldTypes.put("qop", FIELD_TYPE_QUOTED_TOKEN);
// RFC2617 says nc is 8LHEX. <">8LHEX<"> will also be accepted
fieldTypes.put("nc", FIELD_TYPE_LHEX);
}
/**
* Parses an HTTP Authorization header for DIGEST authentication as per RFC
* 2617 section 3.2.2.
*
* @param input The header value to parse
*
* @return A map of directives and values as {@link String}s or
* <code>null</code> if a parsing error occurs. Although the
* values returned are {@link String}s they will have been
* validated to ensure that they conform to RFC 2617.
*
* @throws IllegalArgumentException If the header does not conform to RFC
* 2617
* @throws java.io.IOException If an error occurs while reading the input
*/
public static Map<String,String> parseAuthorizationDigest (StringReader input)
throws IllegalArgumentException, IOException {
Map<String,String> result = new HashMap<>();
if (HttpParser.skipConstant(input, "Digest") != SkipResult.FOUND) {
return null;
}
// All field names are valid tokens
String field = HttpParser.readToken(input);
if (field == null) {
return null;
}
while (!field.equals("")) {
if (HttpParser.skipConstant(input, "=") != SkipResult.FOUND) {
return null;
}
String value;
Integer type = fieldTypes.get(field.toLowerCase(Locale.ENGLISH));
if (type == null) {
// auth-param = token "=" ( token | quoted-string )
type = FIELD_TYPE_TOKEN_OR_QUOTED_STRING;
}
switch (type.intValue()) {
case 0:
// FIELD_TYPE_TOKEN
value = HttpParser.readToken(input);
break;
case 1:
// FIELD_TYPE_QUOTED_STRING
value = HttpParser.readQuotedString(input, false);
break;
case 2:
// FIELD_TYPE_TOKEN_OR_QUOTED_STRING
value = HttpParser.readTokenOrQuotedString(input, false);
break;
case 3:
// FIELD_TYPE_LHEX
value = HttpParser.readLhex(input);
break;
case 4:
// FIELD_TYPE_QUOTED_TOKEN
value = HttpParser.readQuotedToken(input);
break;
default:
// Error
throw new IllegalArgumentException(
sm.getString("authorization.unknownType", type));
}
if (value == null) {
return null;
}
result.put(field, value);
if (HttpParser.skipConstant(input, ",") == SkipResult.NOT_FOUND) {
return null;
}
field = HttpParser.readToken(input);
if (field == null) {
return null;
}
}
return result;
}
}

View File

@@ -0,0 +1,108 @@
/*
* 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.parser;
import java.io.IOException;
import java.io.StringReader;
public class ContentRange {
private final String units;
private final long start;
private final long end;
private final long length;
public ContentRange(String units, long start, long end, long length) {
this.units = units;
this.start = start;
this.end = end;
this.length = length;
}
public String getUnits() {
return units;
}
public long getStart() {
return start;
}
public long getEnd() {
return end;
}
public long getLength() {
return length;
}
/**
* Parses a Content-Range header from an HTTP header.
*
* @param input a reader over the header text
*
* @return the range parsed from the input, or null if not valid
*
* @throws IOException if there was a problem reading the input
*/
public static ContentRange parse(StringReader input) throws IOException {
// Units (required)
String units = HttpParser.readToken(input);
if (units == null || units.length() == 0) {
return null;
}
// Must be followed by '='
if (HttpParser.skipConstant(input, "=") == SkipResult.NOT_FOUND) {
return null;
}
// Start
long start = HttpParser.readLong(input);
// Must be followed by '-'
if (HttpParser.skipConstant(input, "-") == SkipResult.NOT_FOUND) {
return null;
}
// End
long end = HttpParser.readLong(input);
// Must be followed by '/'
if (HttpParser.skipConstant(input, "/") == SkipResult.NOT_FOUND) {
return null;
}
// Length
long length = HttpParser.readLong(input);
// Doesn't matter what we look for, result should be EOF
SkipResult skipResult = HttpParser.skipConstant(input, "X");
if (skipResult != SkipResult.EOF) {
// Invalid range
return null;
}
return new ContentRange(units, start, end, length);
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,139 @@
/*
* 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.parser;
import java.io.IOException;
import java.io.Reader;
import java.io.StringReader;
import org.apache.tomcat.util.buf.ByteChunk;
import org.apache.tomcat.util.buf.MessageBytes;
public class Host {
/**
* Parse the given input as an HTTP Host header value.
*
* @param mb The host header value
*
* @return The position of ':' that separates the host from the port or -1
* if it is not present
*
* @throws IllegalArgumentException If the host header value is not
* specification compliant
*/
public static int parse(MessageBytes mb) {
return parse(new MessageBytesReader(mb));
}
/**
* Parse the given input as an HTTP Host header value.
*
* @param string The host header value
*
* @return The position of ':' that separates the host from the port or -1
* if it is not present
*
* @throws IllegalArgumentException If the host header value is not
* specification compliant
*/
public static int parse(String string) {
return parse(new StringReader(string));
}
private static int parse(Reader reader) {
try {
reader.mark(1);
int first = reader.read();
reader.reset();
if (HttpParser.isAlpha(first)) {
return HttpParser.readHostDomainName(reader);
} else if (HttpParser.isNumeric(first)) {
return HttpParser.readHostIPv4(reader, false);
} else if ('[' == first) {
return HttpParser.readHostIPv6(reader);
} else {
// Invalid
throw new IllegalArgumentException();
}
} catch (IOException ioe) {
// Should never happen
throw new IllegalArgumentException(ioe);
}
}
private static class MessageBytesReader extends Reader {
private final byte[] bytes;
private final int end;
private int pos;
private int mark;
public MessageBytesReader(MessageBytes mb) {
ByteChunk bc = mb.getByteChunk();
bytes = bc.getBytes();
pos = bc.getOffset();
end = bc.getEnd();
}
@Override
public int read(char[] cbuf, int off, int len) throws IOException {
for (int i = off; i < off + len; i++) {
// Want output in range 0 to 255, not -128 to 127
cbuf[i] = (char) (bytes[pos++] & 0xFF);
}
return len;
}
@Override
public void close() throws IOException {
// NO-OP
}
// Over-ridden methods to improve performance
@Override
public int read() throws IOException {
if (pos < end) {
// Want output in range 0 to 255, not -128 to 127
return bytes[pos++] & 0xFF;
} else {
return -1;
}
}
// Methods to support mark/reset
@Override
public boolean markSupported() {
return true;
}
@Override
public void mark(int readAheadLimit) throws IOException {
mark = pos;
}
@Override
public void reset() throws IOException {
pos = mark;
}
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,49 @@
# 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.
authorization.unknownType=Unknown Type [{0}]
cookie.fallToDebug=\n\
\ Note: further occurrences of this error will be logged at DEBUG level.
cookie.invalidCookieValue=A cookie header was received [{0}] that contained an invalid cookie. That cookie will be ignored.
cookie.invalidCookieVersion=A cookie header was received using an unrecognised cookie version of [{0}]. The header and the cookies it contains will be ignored.
cookie.valueNotPresent=<not present>
http.closingBracket=A closing bracket ']' was found in a non-IPv6 host name.
http.illegalAfterIpv6=The character [{0}] is not permitted to follow an IPv6 address in a host name
http.illegalCharacterDomain=The character [{0}] is never valid in a domain name.
http.illegalCharacterIpv4=The character [{0}] is never valid in an IPv4 address.
http.illegalCharacterIpv6=The character [{0}] is never valid in an IPv6 address.
http.invalidCharacterDomain.afterColon=The character [{0}] is not valid after a colon in a domain name.
http.invalidCharacterDomain.afterHyphen=The character [{0}] is not valid after a hyphen in a domain name.
http.invalidCharacterDomain.afterLetter=The character [{0}] is not valid after a letter in a domain name.
http.invalidCharacterDomain.afterNumber=The character [{0}] is not valid after a number in a domain name.
http.invalidCharacterDomain.afterPeriod=The character [{0}] is not valid after a period in a domain name.
http.invalidCharacterDomain.atEnd=The character [{0}] is not valid at the end of a domain name.
http.invalidCharacterDomain.atStart=The character [{0}] is not valid at the start of a domain name.
http.invalidHextet=Invalid hextet. A hextet must consist of 4 or less hex characters.
http.invalidIpv4Location=The IPv6 address contains an embedded IPv4 address at an invalid location.
http.invalidLeadingZero=A non-zero IPv4 octet may not contain a leading zero.
http.invalidOctet=Invalid octet [{0}]. The valid range for IPv4 octets is 0 to 255.
http.invalidRequestTargetCharacter=Character [{0}] is not allowed and will continue to be rejected.
http.invalidSegmentEndState=The state [{0}] is not valid for the end of a segment.
http.noClosingBracket=The IPv6 address is missing a closing bracket.
http.noOpeningBracket=The IPv6 address is missing an opening bracket.
http.singleColonEnd=An IPv6 address may not end with a single ':'.
http.singleColonStart=An IPv6 address may not start with a single ':'.
http.tooFewHextets=An IPv6 address must consist of 8 hextets but this address contains [{0}] hextets and no ''::'' sequence to represent one or more zero hextets.
http.tooManyColons=An IPv6 address may not contain more than 2 sequential colon characters.
http.tooManyDoubleColons=An IPv6 address may only contain a single '::' sequence.
http.tooManyHextets=The IPv6 address contains [{0}] hextets but a valid IPv6 address may not have more than 8.

View File

@@ -0,0 +1,22 @@
# 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.
cookie.valueNotPresent=<nicht vorhanden>
http.illegalCharacterIpv4=Das Zeichen [{0}] ist in einer IPv4-Adresse niemals erlaubt.
http.invalidHextet=Ungültiges Hextet. Ein Hextet muss aus 4 oder weniger Hexadecimalzeichen bestehen.
http.invalidIpv4Location=Die IPV6-Adresse enthält eine eingebettete IPv4-Adresse an einer ungültigen Position.
http.invalidOctet=Invalides Oktett [{0}]. Der gültige Bereich für IPv4 Oktette geht von 0 bis 255.
http.invalidSegmentEndState=Der Zustand [{0}] ist nicht gültig für das Ende eines Segments.

View File

@@ -0,0 +1,22 @@
# 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.
cookie.valueNotPresent=<no presente>
http.illegalCharacterIpv4=El caracter [{0}] nunca es válido en una dirección IPv4.\n
http.illegalCharacterIpv6=El caracter [{0}] nunca es válido en una dirección IPv6.\n
http.invalidHextet=Hextet no válido. Hextet debe consistir de 4 caracteres hexadecimales o menos.
http.singleColonEnd=Una dirección IPv6 no puede terminar con solo un ':'.\n
http.tooManyColons=Una dirección IPv6 no puede contener más de 2 caracteres ":" seguidos

View File

@@ -0,0 +1,45 @@
# 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.
cookie.fallToDebug=\ Note: toutes les occurrences suivantes de cette erreur seront enregistrées au niveau DEBUG
cookie.invalidCookieValue=Un en-tête de cookie a été reçu [{0}] qui contenait un cookie invalide, celui ci sera ignoré
cookie.invalidCookieVersion=Un en-tête de cookie a été reçu utilisant une version [{0}] non reconnue, les cookies seront ignorés
cookie.valueNotPresent=<non présent>
http.closingBracket=Un crochet ']' a été trouvé dans un nom d'hôte non IPv6
http.illegalAfterIpv6=Le caractère [{0}] n''est pas permis dans un nom d''hôte à la suite d''une adresse IPv6
http.illegalCharacterDomain=Le caractère [{0}] n''est jamais valide pour un nom de domaine
http.illegalCharacterIpv4=Le caractère [{0}] n''est pas valide pour une adresse IPV4.
http.illegalCharacterIpv6=Le caractère [{0}] n''est jamais valide dans une adresse IPv6
http.invalidCharacterDomain.afterColon=Le caractère [{0}] n''est pas valide après deux-point pour un nom de domaine
http.invalidCharacterDomain.afterHyphen=Le caractère [{0}] n''est pas valide après un trait d''union pour un nom de domaine
http.invalidCharacterDomain.afterLetter=Le caractère [{0}] n''est pas valide après une lettre pour un nom de domaine
http.invalidCharacterDomain.afterNumber=Le caractère [{0}] n''est pas valide après un nombre pour un nom de domaine
http.invalidCharacterDomain.afterPeriod=Le caractère [{0}] n''est pas valide après une virgule pour un nom de domaine
http.invalidCharacterDomain.atEnd=Le caractère [{0}] n''est pas valide à la fin d''un nom de domaine
http.invalidCharacterDomain.atStart=Le caractère [{0}] n''est pas valide au début d''un nom de domaine
http.invalidHextet="hextet" invalide. Un "hextet" doit consister au maximum de 4 caractères hexadécimaux.
http.invalidIpv4Location=L'adresse IPv6 contient une adresse IPv4 incluse à un endroit invalide
http.invalidLeadingZero=Un octet IPv4 non nul ne doit pas commencer par un zéro
http.invalidOctet=Octet [{0}] invalide. L''éventail valide pour les octets IPv4 est 0-255.
http.invalidSegmentEndState=L''état [{0}] n''est pas valide à la fin d''un segment
http.noClosingBracket=L'adresse IPv6 n'a pas de crochet de fermeture
http.noOpeningBracket=Cette adresse IPv6 n'a pas de crochet d'ouverture '['
http.singleColonEnd=Une adresse IPv6 ne doit pas se terminer par un seul ':'
http.singleColonStart=Une adresse IPv6 ne doit pas commencer par un seul ':'
http.tooFewHextets=Une adresse IPv6 doit être constitué de 8 groupes de 4 octets mais cette adresse en contient [{0}] et pas de séquence "::" pour représenter un ou plusieurs groupes de 4 octets
http.tooManyColons=Une adresse IPv6 ne peut pas contenir plus de deux caractères deux-points à la suite
http.tooManyDoubleColons=Une adresse IPv6 ne peut contenir qu'une seule séquence "::"
http.tooManyHextets=L''adresse IPv6 contient [{0}] groupes de 4 octets mais une adresse IPv6 valide ne doit pas en avoir plus de 8

View File

@@ -0,0 +1,45 @@
# 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.
cookie.fallToDebug=さらなるこのエラーの発生はDEBUGレベルで記録されます。
cookie.invalidCookieValue=無効なCookieを含むCookieヘッダーが受信されました[{0}]。 そのクッキーは無視されます。
cookie.invalidCookieVersion=[{0}]の認識できないクッキーバージョンを使用して、Cookieヘッダーが受信されました。 ヘッダーとそれに含まれるクッキーは無視されます。
cookie.valueNotPresent=<値が存在しません>
http.closingBracket=非IPv6ホスト名に閉じ括弧 ']'が見つかりました。
http.illegalAfterIpv6=文字[{0}]はホスト名のIPv6アドレスに従うことはできません。
http.illegalCharacterDomain=文字 [{0}] をドメイン名に含めることはできません。
http.illegalCharacterIpv4=文字 [{0}] は正常な IPv4 アドレスに利用できません。
http.illegalCharacterIpv6=IPv6 アドレスに文字 [{0}] を使用することはできません。
http.invalidCharacterDomain.afterColon=ドメイン名のコロンの後の文字[{0}]は無効です。
http.invalidCharacterDomain.afterHyphen=ドメイン名のハイフンの後の文字[{0}]は無効です
http.invalidCharacterDomain.afterLetter=文字 [{0}] はドメイン名に利用できません。
http.invalidCharacterDomain.afterNumber=ドメイン名の数字の後の文字[{0}]は無効です。
http.invalidCharacterDomain.afterPeriod=ドメイン名のピリオドの後の文字[{0}]は無効です。
http.invalidCharacterDomain.atEnd=文字[{0}]はドメイン名の最後には無効です。
http.invalidCharacterDomain.atStart=文字[{0}]はドメイン名の先頭には無効です。
http.invalidHextet=不正な 16 進数文字列です。16 進数文字列に使用できるのは 4 文字以下の 16 進数だけです。
http.invalidIpv4Location=IPv6 アドレスは不正な位置に埋め込み IPv4 アドレスを含んでいます。
http.invalidLeadingZero=IPv4 アドレスの 0 でないオクテットは先行する0を含まないかもしれません。
http.invalidOctet=無効なオクテット[{0}]。 IPv4オクテットの有効範囲は0〜255です。
http.invalidSegmentEndState=状態[{0}]はセグメントの最後には無効です。
http.noClosingBracket=IPv6アドレスに閉じ括弧がありません。
http.noOpeningBracket=IPv6 アドレスに開き括弧がありません。
http.singleColonEnd=IPv6 アドレス文字列は単独のコロン (:) で終端してはなりません。
http.singleColonStart=IPv6アドレスは単一の ''で始まらない場合があります
http.tooFewHextets=IPv6 アドレスは 8 個のヘクステットで構成しなければなりませんが [{0}] 個しかありません。また1つ以上のヘクステットを意味する "::" もありません。
http.tooManyColons=IPv6 アドレスでは文字 : を 2 つ以上連続することはできません。
http.tooManyDoubleColons=IPv6アドレスは単一の '::'シーケンスのみを含むことができます。
http.tooManyHextets=IPv6 アドレスは [{0}] ヘクステットで構成されていますが、正常な IPv6 アドレスなら 8 ヘクステット以上になりません。

View File

@@ -0,0 +1,46 @@
# 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.
cookie.fallToDebug=\n\
비고: 이 오류가 더 발생하는 경우 DEBUG 레벨 로그로 기록될 것입니다.
cookie.invalidCookieValue=유효하지 않은 쿠키가 포함된 쿠키 헤더 [{0}]을(를) 받았습니다. 이 쿠키는 무시될 것입니다.
cookie.invalidCookieVersion=인식되지 않는 쿠키 버전 [{0}]을(를) 사용한 쿠키 헤더를 받았습니다. 해당 헤더와 그에 포함된 쿠키들은 무시될 것입니다.
cookie.valueNotPresent=<not present>
http.closingBracket=닫는 대괄호(']')가 IPv6 이름이 아닌 호스트 이름에서 발견되었습니다.
http.illegalAfterIpv6=호스트 이름 내에서, IPv6 주소 이후에 문자 [{0}]은(는) 허용되지 않습니다.
http.illegalCharacterDomain=문자 [{0}]은(는) 도메인 이름 내에서 유효하지 않은 문자입니다.
http.illegalCharacterIpv4=문자 [{0}]은(는) IPv4 주소에서 절대 유효하지 않은 것입니다.
http.illegalCharacterIpv6=문자 [{0}]은(는) IPv6 주소 내에서 유효하지 않은 것입니다.
http.invalidCharacterDomain.afterColon=도메인 이름 내에서, 콜론 이후의 문자 [{0}]은(는) 유효하지 않습니다.
http.invalidCharacterDomain.afterHyphen=도메인 이름 내에서, 붙임표(하이픈) 이후의 문자 [{0}]은(는) 유효하지 않습니다.
http.invalidCharacterDomain.afterLetter=도메인 이름 내에서, 한 글자 이후의 문자 [{0}]은(는) 유효하지 않습니다.
http.invalidCharacterDomain.afterNumber=도메인 이름 내에서, 숫자 이후의 문자 [{0}]은(는) 유효하지 않습니다.
http.invalidCharacterDomain.afterPeriod=도메인 이름 내에서, 마침표 이후의 문자 [{0}]은(는) 유효하지 않습니다.
http.invalidCharacterDomain.atEnd=도메인 이름의 끝 위치에, 문자 [{0}]은(는) 유효하지 않습니다.
http.invalidCharacterDomain.atStart=도메인 이름의 시작 위치에, 문자 [{0}]은(는) 유효하지 않습니다.
http.invalidHextet=유효하지 않은 헥스텟(hextet)입니다. 헥스텟은 반드시 네 개 이하의 문자들이어야 합니다.
http.invalidIpv4Location=IPv6 주소가, 유효하지 않은 위치에 내장 IPv4 주소를 포함하고 있습니다.
http.invalidLeadingZero=IPv4 옥텟(octet)은, 값이 0이 아닌 이상, 0으로 시작해서는 안됩니다.
http.invalidOctet=유효하지 않은 옥텟(octet) [{0}]. IPv4 옥텟의 유효한 범위는 0에서 255까지입니다.
http.invalidSegmentEndState=상태 [{0}]은(는) segment의 끝으로 유효하지 않습니다.
http.noClosingBracket=IPv6 주소에 닫는 대괄호가 없습니다.
http.noOpeningBracket=IPv6 주소에 여는 대괄호가 없습니다.
http.singleColonEnd=IPv6 주소는 단일 ':' 문자로 끝나서는 안됩니다.
http.singleColonStart=IPv6 주소는 단일의 ':'으로 시작할 수 없습니다.
http.tooFewHextets=IPv6 주소는 반드시 8개의 헥스텟(hextet)들로 이루어져야 하지만, 이 주소는 [{0}] 개의 헥스텟들으로 이루어져 있고, 하나 이상의 0 헥스텟들을 표시하기 위한 ''::'' 시퀀스도 존재하지 않습니다.
http.tooManyColons=IPv6 주소는 연속으로 두 개를 초과한 콜론 문자('':'')들을 포함할 수 없습니다.
http.tooManyDoubleColons=IPv6 주소는 단일한 '::' 시퀀스만을 포함해야 합니다.
http.tooManyHextets=IPv6 주소가 [{0}]개의 헥스텟(hextet)들을 포함하고 있지만, 유효한 IPv6 주소는 8개를 초과할 수 없습니다.

View File

@@ -0,0 +1,38 @@
# 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.
cookie.valueNotPresent=<不存在>
http.closingBracket=在非IPv6主机名中找到了右括号']'。
http.illegalCharacterIpv4=字符[{0}]为非法的IPv4地址。
http.illegalCharacterIpv6=字符[{0}]为非法的IPv6地址。
http.invalidCharacterDomain.afterColon=字符 [{0}] 在域名中的冒号后无效。
http.invalidCharacterDomain.afterHyphen=字符 [{0}] 在域名中的连字符后无效。
http.invalidCharacterDomain.afterLetter=字符 [{0}] 在域名中的字母后无效。
http.invalidCharacterDomain.afterNumber=字符 [{0}] 在域名中的数字后无效。
http.invalidCharacterDomain.afterPeriod=字符 [{0}] 在域名中的句号后无效。
http.invalidCharacterDomain.atEnd=字符 [{0}] 在域名末尾无效。
http.invalidCharacterDomain.atStart=字符 [{0}] 在域名开头无效。
http.invalidHextet=hextet无效。 hextet必须包含4个或更少的十六进制字符。
http.invalidIpv4Location=IPv6地址在无效位置包含嵌入的IPv4地址。
http.invalidLeadingZero=非零的IPv4字符可能不包含前导零。
http.invalidOctet=无效字符[{0}].IPv4字符的有效范围为0255。
http.invalidSegmentEndState=状态[{0}]对于段的结尾无效。
http.noClosingBracket=ipv6 地址缺失一个闭合的圆括号
http.noOpeningBracket=IPv6地址缺少开括号(
http.singleColonEnd=IPv6地址不能以单个“.”结尾。
http.singleColonStart=一个IPv6地址也许不是以单个冒号":"开头的。
http.tooManyColons=IPv6地址不能包含超过2个连续冒号字符。
http.tooManyDoubleColons=一个IPv6地址只能包含一个 '::' 序列。

View File

@@ -0,0 +1,178 @@
/*
* 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.parser;
import java.io.IOException;
import java.io.StringReader;
import java.util.LinkedHashMap;
import java.util.Locale;
import java.util.Map;
public class MediaType {
private final String type;
private final String subtype;
private final LinkedHashMap<String,String> parameters;
private final String charset;
private volatile String noCharset;
private volatile String withCharset;
protected MediaType(String type, String subtype, LinkedHashMap<String,String> parameters) {
this.type = type;
this.subtype = subtype;
this.parameters = parameters;
String cs = parameters.get("charset");
if (cs != null && cs.length() > 0 && cs.charAt(0) == '"') {
cs = HttpParser.unquote(cs);
}
this.charset = cs;
}
public String getType() {
return type;
}
public String getSubtype() {
return subtype;
}
public String getCharset() {
return charset;
}
public int getParameterCount() {
return parameters.size();
}
public String getParameterValue(String parameter) {
return parameters.get(parameter.toLowerCase(Locale.ENGLISH));
}
@Override
public String toString() {
if (withCharset == null) {
synchronized (this) {
if (withCharset == null) {
StringBuilder result = new StringBuilder();
result.append(type);
result.append('/');
result.append(subtype);
for (Map.Entry<String, String> entry : parameters.entrySet()) {
String value = entry.getValue();
if (value == null || value.length() == 0) {
continue;
}
result.append(';');
// Workaround for Adobe Read 9 plug-in on IE bug
// Can be removed after 26 June 2013 (EOL of Reader 9)
// See BZ 53814
result.append(' ');
result.append(entry.getKey());
result.append('=');
result.append(value);
}
withCharset = result.toString();
}
}
}
return withCharset;
}
public String toStringNoCharset() {
if (noCharset == null) {
synchronized (this) {
if (noCharset == null) {
StringBuilder result = new StringBuilder();
result.append(type);
result.append('/');
result.append(subtype);
for (Map.Entry<String, String> entry : parameters.entrySet()) {
if (entry.getKey().equalsIgnoreCase("charset")) {
continue;
}
result.append(';');
// Workaround for Adobe Read 9 plug-in on IE bug
// Can be removed after 26 June 2013 (EOL of Reader 9)
// See BZ 53814
result.append(' ');
result.append(entry.getKey());
result.append('=');
result.append(entry.getValue());
}
noCharset = result.toString();
}
}
}
return noCharset;
}
/**
* Parses a MediaType value, either from an HTTP header or from an application.
*
* @param input a reader over the header text
* @return a MediaType parsed from the input, or null if not valid
* @throws IOException if there was a problem reading the input
*/
public static MediaType parseMediaType(StringReader input) throws IOException {
// Type (required)
String type = HttpParser.readToken(input);
if (type == null || type.length() == 0) {
return null;
}
if (HttpParser.skipConstant(input, "/") == SkipResult.NOT_FOUND) {
return null;
}
// Subtype (required)
String subtype = HttpParser.readToken(input);
if (subtype == null || subtype.length() == 0) {
return null;
}
LinkedHashMap<String,String> parameters = new LinkedHashMap<>();
SkipResult lookForSemiColon = HttpParser.skipConstant(input, ";");
if (lookForSemiColon == SkipResult.NOT_FOUND) {
return null;
}
while (lookForSemiColon == SkipResult.FOUND) {
String attribute = HttpParser.readToken(input);
String value = "";
if (HttpParser.skipConstant(input, "=") == SkipResult.FOUND) {
value = HttpParser.readTokenOrQuotedString(input, true);
}
if (attribute != null) {
parameters.put(attribute.toLowerCase(Locale.ENGLISH), value);
}
lookForSemiColon = HttpParser.skipConstant(input, ";");
if (lookForSemiColon == SkipResult.NOT_FOUND) {
return null;
}
}
return new MediaType(type, subtype, parameters);
}
}

View File

@@ -0,0 +1,65 @@
/*
* 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.parser;
import java.io.IOException;
import java.io.StringReader;
import org.apache.tomcat.util.collections.ConcurrentCache;
/**
* Caches the results of parsing content-type headers.
*/
public class MediaTypeCache {
private final ConcurrentCache<String,String[]> cache;
public MediaTypeCache(int size) {
cache = new ConcurrentCache<>(size);
}
/**
* Looks in the cache and returns the cached value if one is present. If no
* match exists in the cache, a new parser is created, the input parsed and
* the results placed in the cache and returned to the user.
*
* @param input The content-type header value to parse
* @return The results are provided as a two element String array. The
* first element is the media type less the charset and
* the second element is the charset
*/
public String[] parse(String input) {
String[] result = cache.get(input);
if (result != null) {
return result;
}
MediaType m = null;
try {
m = MediaType.parseMediaType(new StringReader(input));
} catch (IOException e) {
// Ignore - return null
}
if (m != null) {
result = new String[] {m.toStringNoCharset(), m.getCharset()};
cache.put(input, result);
}
return result;
}
}

View File

@@ -0,0 +1,124 @@
/*
* 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.parser;
import java.io.IOException;
import java.io.StringReader;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class Ranges {
private final String units;
private final List<Entry> entries;
private Ranges(String units, List<Entry> entries) {
this.units = units;
this.entries = Collections.unmodifiableList(entries);
}
public List<Entry> getEntries() {
return entries;
}
public String getUnits() {
return units;
}
public static class Entry {
private final long start;
private final long end;
public Entry(long start, long end) {
this.start = start;
this.end = end;
}
public long getStart() {
return start;
}
public long getEnd() {
return end;
}
}
/**
* Parses a Range header from an HTTP header.
*
* @param input a reader over the header text
*
* @return a set of ranges parsed from the input, or null if not valid
*
* @throws IOException if there was a problem reading the input
*/
public static Ranges parse(StringReader input) throws IOException {
// Units (required)
String units = HttpParser.readToken(input);
if (units == null || units.length() == 0) {
return null;
}
// Must be followed by '='
if (HttpParser.skipConstant(input, "=") == SkipResult.NOT_FOUND) {
return null;
}
// Range entries
List<Entry> entries = new ArrayList<>();
SkipResult skipResult;
do {
long start = HttpParser.readLong(input);
// Must be followed by '-'
if (HttpParser.skipConstant(input, "-") == SkipResult.NOT_FOUND) {
return null;
}
long end = HttpParser.readLong(input);
if (start == -1 && end == -1) {
// Invalid range
return null;
}
entries.add(new Entry(start, end));
skipResult = HttpParser.skipConstant(input, ",");
if (skipResult == SkipResult.NOT_FOUND) {
// Invalid range
return null;
}
} while (skipResult == SkipResult.FOUND);
// There must be at least one entry
if (entries.size() == 0) {
return null;
}
return new Ranges(units, entries);
}
}

View File

@@ -0,0 +1,23 @@
/*
* 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.parser;
enum SkipResult {
FOUND,
NOT_FOUND,
EOF
}

View File

@@ -0,0 +1,113 @@
/*
* 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.parser;
import java.io.IOException;
import java.io.Reader;
import java.io.StringReader;
import java.util.Collection;
import java.util.Enumeration;
import java.util.Locale;
public class TokenList {
private TokenList() {
// Utility class. Hide default constructor.
}
/**
* Parses an enumeration of header values of the form 1#token, forcing all
* parsed values to lower case.
*
* @param inputs The headers to parse
* @param collection The Collection (usually a list of a set) to which the
* parsed tokens should be added
*
* @return {@code} true if the header values were parsed cleanly, otherwise
* {@code false} (e.g. if a non-token value was encountered)
*
* @throws IOException If an I/O error occurs reading the header
*/
public static boolean parseTokenList(Enumeration<String> inputs, Collection<String> collection) throws IOException {
boolean result = true;
while (inputs.hasMoreElements()) {
String nextHeaderValue = inputs.nextElement();
if (nextHeaderValue != null) {
if (!TokenList.parseTokenList(new StringReader(nextHeaderValue), collection)) {
result = false;
}
}
}
return result;
}
/**
* Parses a header of the form 1#token, forcing all parsed values to lower
* case. This is typically used when header values are case-insensitive.
*
* @param input The header to parse
* @param collection The Collection (usually a list of a set) to which the
* parsed tokens should be added
*
* @return {@code} true if the header was parsed cleanly, otherwise
* {@code false} (e.g. if a non-token value was encountered)
*
* @throws IOException If an I/O error occurs reading the header
*/
public static boolean parseTokenList(Reader input, Collection<String> collection) throws IOException {
boolean invalid = false;
boolean valid = false;
do {
String fieldName = HttpParser.readToken(input);
if (fieldName == null) {
// Invalid field-name, skip to the next one
invalid = true;
HttpParser.skipUntil(input, 0, ',');
continue;
}
if (fieldName.length() == 0) {
// No more data to read
break;
}
SkipResult skipResult = HttpParser.skipConstant(input, ",");
if (skipResult == SkipResult.EOF) {
// EOF
valid = true;
collection.add(fieldName.toLowerCase(Locale.ENGLISH));
break;
} else if (skipResult == SkipResult.FOUND) {
valid = true;
collection.add(fieldName.toLowerCase(Locale.ENGLISH));
continue;
} else {
// Not a token - ignore it
invalid = true;
HttpParser.skipUntil(input, 0, ',');
continue;
}
} while (true);
// Only return true if at least one valid token was read and no invalid
// entries were found
return valid && !invalid;
}
}

View File

@@ -0,0 +1,37 @@
/*
* 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.parser;
import java.io.IOException;
import java.io.StringReader;
import java.util.Set;
/**
* @deprecated Use {@link TokenList}.
*/
@Deprecated
public class Vary {
private Vary() {
// Utility class. Hide default constructor.
}
public static void parseVary(StringReader input, Set<String> result) throws IOException {
TokenList.parseTokenList(input, result);
}
}