ttomcat-1778514358873.zip-extract/apache-tomcat-11.0.18-src/java/org/apache/tomcat/util/http/parser/StructuredField.java

Path
ttomcat-1778514358873.zip-extract/apache-tomcat-11.0.18-src/java/org/apache/tomcat/util/http/parser/StructuredField.java
Status
scanned
Type
file
Name
StructuredField.java
Extension
.java
Programming language
Java
Mime type
text/x-Algol68
File type
Algol 68 source, ASCII text, with CRLF line terminators
Tag

      
    
Rootfs path

      
    
Size
17746 (17.3 KB)
MD5
7f4f10d2c143a5a42d80d63f180c1f9b
SHA1
539696b231a01b18a43ccdeab8eebd077adb3b08
SHA256
d0dce2e86d6cac60eccf4c20e1cae8b1be2299d24d67103d59846557fd6d6a49
SHA512

      
    
SHA1_git
5599dcdaa3629ea93c29882042efe7135178f276
Is binary

      
    
Is text
True
Is archive

      
    
Is media

      
    
Is legal

      
    
Is manifest

      
    
Is readme

      
    
Is top level

      
    
Is key file

      
    
StructuredField.java | 17.3 KB |

/* * 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.util.ArrayList; import java.util.Base64; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import org.apache.tomcat.util.res.StringManager; /** * Parsing of structured fields as per RFC 8941. * <p> * The parsing implementation is complete but not all elements are currently exposed via getters. Additional getters * will be added as required as the use of structured fields expands. * <p> * The serialization of structured fields has not been implemented. */ public class StructuredField { private static final StringManager sm = StringManager.getManager(StructuredField.class); private static final int ARRAY_SIZE = 128; private static final boolean[] IS_KEY_FIRST = new boolean[ARRAY_SIZE]; private static final boolean[] IS_KEY = new boolean[ARRAY_SIZE]; private static final boolean[] IS_OWS = new boolean[ARRAY_SIZE]; private static final boolean[] IS_BASE64 = new boolean[ARRAY_SIZE]; private static final boolean[] IS_TOKEN = new boolean[ARRAY_SIZE]; static { for (int i = 0; i < ARRAY_SIZE; i++) { if (i == '*' || i >= 'a' && i <= 'z') { IS_KEY_FIRST[i] = true; IS_KEY[i] = true; } else if (i >= '0' && i <= '9' || i == '_' || i == '-' || i == '.') { IS_KEY[i] = true; } } for (int i = 0; i < ARRAY_SIZE; i++) { if (i == 9 || i == ' ') { IS_OWS[i] = true; } } for (int i = 0; i < ARRAY_SIZE; i++) { if (i == '+' || i == '/' || i >= '0' && i <= '9' || i == '=' || i >= 'A' && i <= 'Z' || i >= 'a' && i <= 'z') { IS_BASE64[i] = true; } } for (int i = 0; i < ARRAY_SIZE; i++) { if (HttpParser.isToken(i) || i == ':' || i == '/') { IS_TOKEN[i] = true; } } } static SfList parseSfList(Reader input) throws IOException { skipSP(input); SfList result = new SfList(); if (peek(input) != -1) { while (true) { SfListMember listMember = parseSfListMember(input); result.addListMember(listMember); skipOWS(input); if (peek(input) == -1) { break; } requireChar(input, ','); skipOWS(input); requireNotChar(input, -1); } } skipSP(input); requireChar(input, -1); return result; } // Item or inner list static SfListMember parseSfListMember(Reader input) throws IOException { SfListMember listMember; if (peek(input) == '(') { listMember = parseSfInnerList(input); } else { listMember = parseSfBareItem(input); } parseSfParameters(input, listMember); return listMember; } static SfInnerList parseSfInnerList(Reader input) throws IOException { requireChar(input, '('); SfInnerList innerList = new SfInnerList(); while (true) { skipSP(input); if (peek(input) == ')') { break; } SfItem<?> item = parseSfBareItem(input); parseSfParameters(input, item); innerList.addListItem(item); input.mark(1); requireChar(input, ' ', ')'); input.reset(); } requireChar(input, ')'); return innerList; } static SfDictionary parseSfDictionary(Reader input) throws IOException { skipSP(input); SfDictionary result = new SfDictionary(); if (peek(input) != -1) { while (true) { String key = parseSfKey(input); SfListMember listMember; input.mark(1); int c = input.read(); if (c == '=') { listMember = parseSfListMember(input); } else { listMember = new SfBoolean(true); input.reset(); } parseSfParameters(input, listMember); result.addDictionaryMember(key, listMember); skipOWS(input); if (peek(input) == -1) { break; } requireChar(input, ','); skipOWS(input); requireNotChar(input, -1); } } skipSP(input); requireChar(input, -1); return result; } static SfItem<?> parseSfItem(Reader input) throws IOException { skipSP(input); SfItem<?> item = parseSfBareItem(input); parseSfParameters(input, item); skipSP(input); requireChar(input, -1); return item; } static SfItem<?> parseSfBareItem(Reader input) throws IOException { int c = input.read(); SfItem<?> item; if (c == '-' || HttpParser.isNumeric(c)) { item = parseSfNumeric(input, c); } else if (c == '\"') { item = parseSfString(input); } else if (c == '*' || HttpParser.isAlpha(c)) { item = parseSfToken(input, c); } else if (c == ':') { item = parseSfByteSequence(input); } else if (c == '?') { item = parseSfBoolean(input); } else { throw new IllegalArgumentException( sm.getString("sf.bareitem.invalidCharacter", String.format("\\u%04X", Integer.valueOf(c)))); } return item; } static void parseSfParameters(Reader input, SfListMember listMember) throws IOException { while (peek(input) == ';') { requireChar(input, ';'); skipSP(input); String key = parseSfKey(input); SfItem<?> item; input.mark(1); int c = input.read(); if (c == '=') { item = parseSfBareItem(input); } else { item = new SfBoolean(true); input.reset(); } listMember.addParameter(key, item); } } static String parseSfKey(Reader input) throws IOException { StringBuilder result = new StringBuilder(); input.mark(1); int c = input.read(); if (!isKeyFirst(c)) { throw new IllegalArgumentException( sm.getString("sf.key.invalidFirstCharacter", String.format("\\u%04X", Integer.valueOf(c)))); } while (c != -1 && isKey(c)) { result.append((char) c); input.mark(1); c = input.read(); } input.reset(); return result.toString(); } static SfItem<?> parseSfNumeric(Reader input, int first) throws IOException { int sign = 1; boolean integer = true; int decimalPos = 0; StringBuilder result = new StringBuilder(); int c; if (first == '-') { sign = -1; c = input.read(); } else { c = first; } if (!HttpParser.isNumeric(c)) { throw new IllegalArgumentException( sm.getString("sf.numeric.invalidCharacter", String.format("\\u%04X", Integer.valueOf(c)))); } result.append((char) c); input.mark(1); c = input.read(); while (c != -1) { if (HttpParser.isNumeric(c)) { result.append((char) c); } else if (integer && c == '.') { if (result.length() > 12) { throw new IllegalArgumentException(sm.getString("sf.numeric.integralPartTooLong")); } integer = false; result.append((char) c); decimalPos = result.length(); } else { input.reset(); break; } if (integer && result.length() > 15) { throw new IllegalArgumentException(sm.getString("sf.numeric.integerTooLong")); } if (!integer && result.length() > 16) { throw new IllegalArgumentException(sm.getString("sf.numeric.decimalTooLong")); } input.mark(1); c = input.read(); } if (integer) { return new SfInteger(Long.parseLong(result.toString()) * sign); } if (result.charAt(result.length() - 1) == '.') { throw new IllegalArgumentException(sm.getString("sf.numeric.decimalInvalidFinal")); } if (result.length() - decimalPos > 3) { throw new IllegalArgumentException(sm.getString("sf.numeric.decimalPartTooLong")); } return new SfDecimal(Double.parseDouble(result.toString()) * sign); } static SfString parseSfString(Reader input) throws IOException { // It is known first character was '"' StringBuilder result = new StringBuilder(); while (true) { int c = input.read(); if (c == '\\') { requireNotChar(input, -1); c = input.read(); if (c != '\\' && c != '\"') { throw new IllegalArgumentException( sm.getString("sf.string.invalidEscape", String.format("\\u%04X", Integer.valueOf(c)))); } } else { if (c == '\"') { break; } // This test also covers unexpected EOF if (c < 32 || c > 126) { throw new IllegalArgumentException( sm.getString("sf.string.invalidCharacter", String.format("\\u%04X", Integer.valueOf(c)))); } } result.append((char) c); } return new SfString(result.toString()); } static SfToken parseSfToken(Reader input, int first) throws IOException { // It is known first character is valid StringBuilder result = new StringBuilder(); result.append((char) first); while (true) { input.mark(1); int c = input.read(); if (!isToken(c)) { input.reset(); break; } result.append((char) c); } return new SfToken(result.toString()); } static SfByteSequence parseSfByteSequence(Reader input) throws IOException { // It is known first character was ':' StringBuilder base64 = new StringBuilder(); while (true) { int c = input.read(); if (c == ':') { break; } else if (isBase64(c)) { base64.append((char) c); } else { throw new IllegalArgumentException( sm.getString("sf.base64.invalidCharacter", String.format("\\u%04X", Integer.valueOf(c)))); } } return new SfByteSequence(Base64.getDecoder().decode(base64.toString())); } static SfBoolean parseSfBoolean(Reader input) throws IOException { // It is known first character was '?' int c = input.read(); if (c == '1') { return new SfBoolean(true); } else if (c == '0') { return new SfBoolean(false); } else { throw new IllegalArgumentException( sm.getString("sf.boolean.invalidCharacter", String.format("\\u%04X", Integer.valueOf(c)))); } } static void skipSP(Reader input) throws IOException { input.mark(1); int c = input.read(); while (c == 32) { input.mark(1); c = input.read(); } input.reset(); } static void skipOWS(Reader input) throws IOException { input.mark(1); int c = input.read(); while (isOws(c)) { input.mark(1); c = input.read(); } input.reset(); } static void requireChar(Reader input, int... required) throws IOException { int c = input.read(); for (int r : required) { if (c == r) { return; } } throw new IllegalArgumentException( sm.getString("sf.invalidCharacter", String.format("\\u%04X", Integer.valueOf(c)))); } static void requireNotChar(Reader input, int required) throws IOException { input.mark(1); int c = input.read(); if (c == required) { throw new IllegalArgumentException( sm.getString("sf.invalidCharacter", String.format("\\u%04X", Integer.valueOf(c)))); } input.reset(); } static int peek(Reader input) throws IOException { input.mark(1); int c = input.read(); input.reset(); return c; } static boolean isKeyFirst(int c) { try { return IS_KEY_FIRST[c]; } catch (ArrayIndexOutOfBoundsException ex) { return false; } } static boolean isKey(int c) { try { return IS_KEY[c]; } catch (ArrayIndexOutOfBoundsException ex) { return false; } } static boolean isOws(int c) { try { return IS_OWS[c]; } catch (ArrayIndexOutOfBoundsException ex) { return false; } } static boolean isBase64(int c) { try { return IS_BASE64[c]; } catch (ArrayIndexOutOfBoundsException ex) { return false; } } static boolean isToken(int c) { try { return IS_TOKEN[c]; } catch (ArrayIndexOutOfBoundsException ex) { return false; } } private StructuredField() { // Utility class. Hide default constructor. } static class SfDictionary { private final Map<String,SfListMember> dictionary = new LinkedHashMap<>(); void addDictionaryMember(String key, SfListMember value) { dictionary.put(key, value); } SfListMember getDictionaryMember(String key) { return dictionary.get(key); } } static class SfList { private final List<SfListMember> listMembers = new ArrayList<>(); void addListMember(SfListMember listMember) { listMembers.add(listMember); } } static class SfListMember { private Map<String,SfItem<?>> parameters = null; void addParameter(String key, SfItem<?> value) { if (parameters == null) { parameters = new LinkedHashMap<>(); } parameters.put(key, value); } } static class SfInnerList extends SfListMember { List<SfItem<?>> listItems = new ArrayList<>(); SfInnerList() { // Default constructor is NO-OP } void addListItem(SfItem<?> item) { listItems.add(item); } List<SfItem<?>> getListItem() { return listItems; } } abstract static class SfItem<T> extends SfListMember { private final T value; SfItem(T value) { this.value = value; } T getVaue() { return value; } } static class SfInteger extends SfItem<Long> { SfInteger(long value) { super(Long.valueOf(value)); } } static class SfDecimal extends SfItem<Double> { SfDecimal(double value) { super(Double.valueOf(value)); } } static class SfString extends SfItem<String> { SfString(String value) { super(value); } } static class SfToken extends SfItem<String> { SfToken(String value) { super(value); } } static class SfByteSequence extends SfItem<byte[]> { SfByteSequence(byte[] value) { super(value); } } static class SfBoolean extends SfItem<Boolean> { SfBoolean(boolean value) { super(Boolean.valueOf(value)); } } }
Detected license expression
apache-2.0
Detected license expression (SPDX)
Apache-2.0
Percentage of license text
7.56
Copyrights

      
    
Holders

      
    
Authors

      
    
License detections License expression License expression SPDX
apache_2_0-4bde3f57-78aa-4201-96bf-531cba09e7de apache-2.0 Apache-2.0
URL Start line End line
http://www.apache.org/licenses/LICENSE-2.0 9 9